/Source/Swig/typeobj.c
C | 1095 lines | 670 code | 105 blank | 320 comment | 218 complexity | 0c9dca308ad36e5bc24a5207dd698094 MD5 | raw file
Possible License(s): 0BSD, GPL-2.0, LGPL-2.1
- /* -----------------------------------------------------------------------------
- * See the LICENSE file for information on copyright, usage and redistribution
- * of SWIG, and the README file for authors - http://www.swig.org/release.html.
- *
- * typeobj.c
- *
- * This file provides functions for constructing, manipulating, and testing
- * type objects. Type objects are merely the raw low-level representation
- * of C++ types. They do not incorporate high-level type system features
- * like typedef, namespaces, etc.
- * ----------------------------------------------------------------------------- */
- char cvsroot_typeobj_c[] = "$Id$";
- #include "swig.h"
- #include <ctype.h>
- /* -----------------------------------------------------------------------------
- * Synopsis
- *
- * This file provides a collection of low-level functions for constructing and
- * manipulating C++ data types. In SWIG, C++ datatypes are encoded as simple
- * text strings. This representation is compact, easy to debug, and easy to read.
- *
- * General idea:
- *
- * Types are represented by a base type (e.g., "int") and a collection of
- * type operators applied to the base (e.g., pointers, arrays, etc...).
- *
- * Encoding:
- *
- * Types are encoded as strings of type constructors such as follows:
- *
- * String Encoding C Example
- * --------------- ---------
- * p.p.int int **
- * a(300).a(400).int int [300][400]
- * p.q(const).char char const *
- *
- * All type constructors are denoted by a trailing '.':
- *
- * 'p.' = Pointer (*)
- * 'r.' = Reference (&)
- * 'a(n).' = Array of size n [n]
- * 'f(..,..).' = Function with arguments (args)
- * 'q(str).' = Qualifier (such as const or volatile) (const, volatile)
- * 'm(qual).' = Pointer to member (qual::*)
- *
- * The encoding follows the order that you might describe a type in words.
- * For example "p.a(200).int" is "A pointer to array of int's" and
- * "p.q(const).char" is "a pointer to a const char".
- *
- * This representation of types is fairly convenient because ordinary string
- * operations can be used for type manipulation. For example, a type could be
- * formed by combining two strings such as the following:
- *
- * "p.p." + "a(400).int" = "p.p.a(400).int"
- *
- * For C++, typenames may be parameterized using <(...)>. Here are some
- * examples:
- *
- * String Encoding C++ Example
- * --------------- ------------
- * p.vector<(int)> vector<int> *
- * r.foo<(int,p.double)> foo<int,double *> &
- *
- * Contents of this file:
- *
- * Most of this functions in this file pertain to the low-level manipulation
- * of type objects. There are constructor functions like this:
- *
- * SwigType_add_pointer()
- * SwigType_add_reference()
- * SwigType_add_array()
- *
- * These are used to build new types. There are also functions to undo these
- * operations. For example:
- *
- * SwigType_del_pointer()
- * SwigType_del_reference()
- * SwigType_del_array()
- *
- * In addition, there are query functions
- *
- * SwigType_ispointer()
- * SwigType_isreference()
- * SwigType_isarray()
- *
- * Finally, there are some data extraction functions that can be used to
- * extract array dimensions, template arguments, and so forth.
- *
- * It is very important for developers to realize that the functions in this
- * module do *NOT* incorporate higher-level type system features like typedef.
- * For example, you could have C code like this:
- *
- * typedef int *intptr;
- *
- * In this case, a SwigType of type 'intptr' will be treated as a simple type and
- * functions like SwigType_ispointer() will evaluate as false. It is strongly
- * advised that developers use the TypeSys_* interface to check types in a more
- * reliable manner.
- * ----------------------------------------------------------------------------- */
- /* -----------------------------------------------------------------------------
- * NewSwigType()
- *
- * Constructs a new type object. Eventually, it would be nice for this function
- * to accept an initial value in the form a C/C++ abstract type (currently unimplemented).
- * ----------------------------------------------------------------------------- */
- #ifdef NEW
- SwigType *NewSwigType(const_String_or_char_ptr initial) {
- return NewString(initial);
- }
- #endif
- /* The next few functions are utility functions used in the construction and
- management of types */
- /* -----------------------------------------------------------------------------
- * static element_size()
- *
- * This utility function finds the size of a single type element in a type string.
- * Type elements are always delimited by periods, but may be nested with
- * parentheses. A nested element is always handled as a single item.
- *
- * Returns the integer size of the element (which can be used to extract a
- * substring, to chop the element off, or for other purposes).
- * ----------------------------------------------------------------------------- */
- static int element_size(char *c) {
- int nparen;
- char *s = c;
- while (*c) {
- if (*c == '.') {
- c++;
- return (int) (c - s);
- } else if (*c == '(') {
- nparen = 1;
- c++;
- while (*c) {
- if (*c == '(')
- nparen++;
- if (*c == ')') {
- nparen--;
- if (nparen == 0)
- break;
- }
- c++;
- }
- }
- if (*c)
- c++;
- }
- return (int) (c - s);
- }
- /* -----------------------------------------------------------------------------
- * SwigType_del_element()
- *
- * Deletes one type element from the type.
- * ----------------------------------------------------------------------------- */
- SwigType *SwigType_del_element(SwigType *t) {
- int sz = element_size(Char(t));
- Delslice(t, 0, sz);
- return t;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_pop()
- *
- * Pop one type element off the type.
- * ----------------------------------------------------------------------------- */
- SwigType *SwigType_pop(SwigType *t) {
- SwigType *result;
- char *c;
- int sz;
- c = Char(t);
- if (!*c)
- return 0;
- sz = element_size(c);
- result = NewStringWithSize(c, sz);
- Delslice(t, 0, sz);
- c = Char(t);
- if (*c == '.') {
- Delitem(t, 0);
- }
- return result;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_parm()
- *
- * Returns the parameter of an operator as a string
- * ----------------------------------------------------------------------------- */
- String *SwigType_parm(SwigType *t) {
- char *start, *c;
- int nparens = 0;
- c = Char(t);
- while (*c && (*c != '(') && (*c != '.'))
- c++;
- if (!*c || (*c == '.'))
- return 0;
- c++;
- start = c;
- while (*c) {
- if (*c == ')') {
- if (nparens == 0)
- break;
- nparens--;
- } else if (*c == '(') {
- nparens++;
- }
- c++;
- }
- return NewStringWithSize(start, (int) (c - start));
- }
- /* -----------------------------------------------------------------------------
- * SwigType_split()
- *
- * Splits a type into it's component parts and returns a list of string.
- * ----------------------------------------------------------------------------- */
- List *SwigType_split(const SwigType *t) {
- String *item;
- List *list;
- char *c;
- int len;
- c = Char(t);
- list = NewList();
- while (*c) {
- len = element_size(c);
- item = NewStringWithSize(c, len);
- Append(list, item);
- Delete(item);
- c = c + len;
- if (*c == '.')
- c++;
- }
- return list;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_parmlist()
- *
- * Splits a comma separated list of parameters into its component parts
- * The input is expected to contain the parameter list within () brackets
- * Returns 0 if no argument list in the input, ie there are no round brackets ()
- * Returns an empty List if there are no parameters in the () brackets
- * For example:
- *
- * Foo(std::string,p.f().Bar<(int,double)>)
- *
- * returns 2 elements in the list:
- * std::string
- * p.f().Bar<(int,double)>
- * ----------------------------------------------------------------------------- */
-
- List *SwigType_parmlist(const String *p) {
- String *item = 0;
- List *list;
- char *c;
- char *itemstart;
- int size;
- assert(p);
- c = Char(p);
- while (*c && (*c != '(') && (*c != '.'))
- c++;
- if (!*c)
- return 0;
- assert(*c != '.'); /* p is expected to contain sub elements of a type */
- c++;
- list = NewList();
- itemstart = c;
- while (*c) {
- if (*c == ',') {
- size = (int) (c - itemstart);
- item = NewStringWithSize(itemstart, size);
- Append(list, item);
- Delete(item);
- itemstart = c + 1;
- } else if (*c == '(') {
- int nparens = 1;
- c++;
- while (*c) {
- if (*c == '(')
- nparens++;
- if (*c == ')') {
- nparens--;
- if (nparens == 0)
- break;
- }
- c++;
- }
- } else if (*c == ')') {
- break;
- }
- if (*c)
- c++;
- }
- size = (int) (c - itemstart);
- if (size > 0) {
- item = NewStringWithSize(itemstart, size);
- Append(list, item);
- }
- Delete(item);
- return list;
- }
- /* -----------------------------------------------------------------------------
- * Pointers
- *
- * SwigType_add_pointer()
- * SwigType_del_pointer()
- * SwigType_ispointer()
- *
- * Add, remove, and test if a type is a pointer. The deletion and query
- * functions take into account qualifiers (if any).
- * ----------------------------------------------------------------------------- */
- SwigType *SwigType_add_pointer(SwigType *t) {
- Insert(t, 0, "p.");
- return t;
- }
- SwigType *SwigType_del_pointer(SwigType *t) {
- char *c, *s;
- c = Char(t);
- s = c;
- /* Skip qualifiers, if any */
- if (strncmp(c, "q(", 2) == 0) {
- c = strchr(c, '.');
- assert(c);
- c++;
- }
- if (strncmp(c, "p.", 2)) {
- printf("Fatal error. SwigType_del_pointer applied to non-pointer.\n");
- abort();
- }
- Delslice(t, 0, (c - s) + 2);
- return t;
- }
- int SwigType_ispointer(SwigType *t) {
- char *c;
- if (!t)
- return 0;
- c = Char(t);
- /* Skip qualifiers, if any */
- if (strncmp(c, "q(", 2) == 0) {
- c = strchr(c, '.');
- if (!c)
- return 0;
- c++;
- }
- if (strncmp(c, "p.", 2) == 0) {
- return 1;
- }
- return 0;
- }
- /* -----------------------------------------------------------------------------
- * References
- *
- * SwigType_add_reference()
- * SwigType_del_reference()
- * SwigType_isreference()
- *
- * Add, remove, and test if a type is a reference. The deletion and query
- * functions take into account qualifiers (if any).
- * ----------------------------------------------------------------------------- */
- SwigType *SwigType_add_reference(SwigType *t) {
- Insert(t, 0, "r.");
- return t;
- }
- SwigType *SwigType_del_reference(SwigType *t) {
- char *c = Char(t);
- int check = strncmp(c, "r.", 2);
- assert(check == 0);
- Delslice(t, 0, 2);
- return t;
- }
- int SwigType_isreference(SwigType *t) {
- char *c;
- if (!t)
- return 0;
- c = Char(t);
- if (strncmp(c, "r.", 2) == 0) {
- return 1;
- }
- return 0;
- }
- /* -----------------------------------------------------------------------------
- * Qualifiers
- *
- * SwigType_add_qualifier()
- * SwigType_del_qualifier()
- * SwigType_is_qualifier()
- *
- * Adds type qualifiers like "const" and "volatile". When multiple qualifiers
- * are added to a type, they are combined together into a single qualifier.
- * Repeated qualifications have no effect. Moreover, the order of qualifications
- * is alphabetical---meaning that "const volatile" and "volatile const" are
- * stored in exactly the same way as "q(const volatile)".
- * ----------------------------------------------------------------------------- */
- SwigType *SwigType_add_qualifier(SwigType *t, const_String_or_char_ptr qual) {
- char temp[256], newq[256];
- int sz, added = 0;
- char *q, *cqual;
- char *c = Char(t);
- cqual = Char(qual);
- if (!(strncmp(c, "q(", 2) == 0)) {
- sprintf(temp, "q(%s).", cqual);
- Insert(t, 0, temp);
- return t;
- }
- /* The type already has a qualifier on it. In this case, we first check to
- see if the qualifier is already specified. In that case do nothing.
- If it is a new qualifier, we add it to the qualifier list in alphabetical
- order */
- sz = element_size(c);
- strncpy(temp, c, (sz < 256) ? sz : 256);
- if (strstr(temp, cqual)) {
- /* Qualifier already added */
- return t;
- }
- /* Add the qualifier to the existing list. */
- strcpy(newq, "q(");
- q = temp + 2;
- q = strtok(q, " ).");
- while (q) {
- if (strcmp(cqual, q) < 0) {
- /* New qualifier is less that current qualifier. We need to insert it */
- strcat(newq, cqual);
- strcat(newq, " ");
- strcat(newq, q);
- added = 1;
- } else {
- strcat(newq, q);
- }
- q = strtok(NULL, " ).");
- if (q) {
- strcat(newq, " ");
- }
- }
- if (!added) {
- strcat(newq, " ");
- strcat(newq, cqual);
- }
- strcat(newq, ").");
- Delslice(t, 0, sz);
- Insert(t, 0, newq);
- return t;
- }
- SwigType *SwigType_del_qualifier(SwigType *t) {
- char *c = Char(t);
- int check = strncmp(c, "q(", 2);
- assert(check == 0);
- Delslice(t, 0, element_size(c));
- return t;
- }
- int SwigType_isqualifier(SwigType *t) {
- char *c;
- if (!t)
- return 0;
- c = Char(t);
- if (strncmp(c, "q(", 2) == 0) {
- return 1;
- }
- return 0;
- }
- /* -----------------------------------------------------------------------------
- * Function Pointers
- * ----------------------------------------------------------------------------- */
- int SwigType_isfunctionpointer(SwigType *t) {
- char *c;
- if (!t)
- return 0;
- c = Char(t);
- if (strncmp(c, "p.f(", 4) == 0) {
- return 1;
- }
- return 0;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_functionpointer_decompose
- *
- * Decompose the function pointer into the parameter list and the return type
- * t - input and on completion contains the return type
- * returns the function's parameters
- * ----------------------------------------------------------------------------- */
- SwigType *SwigType_functionpointer_decompose(SwigType *t) {
- String *p;
- assert(SwigType_isfunctionpointer(t));
- p = SwigType_pop(t);
- Delete(p);
- p = SwigType_pop(t);
- return p;
- }
- /* -----------------------------------------------------------------------------
- * Member Pointers
- *
- * SwigType_add_memberpointer()
- * SwigType_del_memberpointer()
- * SwigType_ismemberpointer()
- *
- * Add, remove, and test for C++ pointer to members.
- * ----------------------------------------------------------------------------- */
- SwigType *SwigType_add_memberpointer(SwigType *t, const_String_or_char_ptr name) {
- String *temp = NewStringf("m(%s).", name);
- Insert(t, 0, temp);
- Delete(temp);
- return t;
- }
- SwigType *SwigType_del_memberpointer(SwigType *t) {
- char *c = Char(t);
- int check = strncmp(c, "m(", 2);
- assert(check == 0);
- Delslice(t, 0, element_size(c));
- return t;
- }
- int SwigType_ismemberpointer(SwigType *t) {
- char *c;
- if (!t)
- return 0;
- c = Char(t);
- if (strncmp(c, "m(", 2) == 0) {
- return 1;
- }
- return 0;
- }
- /* -----------------------------------------------------------------------------
- * Arrays
- *
- * SwigType_add_array()
- * SwigType_del_array()
- * SwigType_isarray()
- *
- * Utility functions:
- *
- * SwigType_array_ndim() - Calculate number of array dimensions.
- * SwigType_array_getdim() - Get array dimension
- * SwigType_array_setdim() - Set array dimension
- * SwigType_array_type() - Return array type
- * SwigType_pop_arrays() - Remove all arrays
- * ----------------------------------------------------------------------------- */
- SwigType *SwigType_add_array(SwigType *t, const_String_or_char_ptr size) {
- char temp[512];
- strcpy(temp, "a(");
- strcat(temp, Char(size));
- strcat(temp, ").");
- Insert(t, 0, temp);
- return t;
- }
- SwigType *SwigType_del_array(SwigType *t) {
- char *c = Char(t);
- int check = strncmp(c, "a(", 2);
- assert(check == 0);
- Delslice(t, 0, element_size(c));
- return t;
- }
- int SwigType_isarray(SwigType *t) {
- char *c;
- if (!t)
- return 0;
- c = Char(t);
- if (strncmp(c, "a(", 2) == 0) {
- return 1;
- }
- return 0;
- }
- /*
- * SwigType_prefix_is_simple_1D_array
- *
- * Determine if the type is a 1D array type that is treated as a pointer within SWIG
- * eg Foo[], Foo[3] return true, but Foo[3][3], Foo*[], Foo*[3], Foo**[] return false
- */
- int SwigType_prefix_is_simple_1D_array(SwigType *t) {
- char *c = Char(t);
- if (c && (strncmp(c, "a(", 2) == 0)) {
- c = strchr(c, '.');
- c++;
- return (*c == 0);
- }
- return 0;
- }
- /* Remove all arrays */
- SwigType *SwigType_pop_arrays(SwigType *t) {
- String *ta;
- assert(SwigType_isarray(t));
- ta = NewStringEmpty();
- while (SwigType_isarray(t)) {
- SwigType *td = SwigType_pop(t);
- Append(ta, td);
- Delete(td);
- }
- return ta;
- }
- /* Return number of array dimensions */
- int SwigType_array_ndim(SwigType *t) {
- int ndim = 0;
- char *c = Char(t);
- while (c && (strncmp(c, "a(", 2) == 0)) {
- c = strchr(c, '.');
- c++;
- ndim++;
- }
- return ndim;
- }
- /* Get nth array dimension */
- String *SwigType_array_getdim(SwigType *t, int n) {
- char *c = Char(t);
- while (c && (strncmp(c, "a(", 2) == 0) && (n > 0)) {
- c = strchr(c, '.');
- c++;
- n--;
- }
- if (n == 0) {
- String *dim = SwigType_parm(c);
- if (SwigType_istemplate(dim)) {
- String *ndim = SwigType_namestr(dim);
- Delete(dim);
- dim = ndim;
- }
- return dim;
- }
- return 0;
- }
- /* Replace nth array dimension */
- void SwigType_array_setdim(SwigType *t, int n, const_String_or_char_ptr rep) {
- String *result = 0;
- char temp;
- char *start;
- char *c = Char(t);
- start = c;
- if (strncmp(c, "a(", 2))
- abort();
- while (c && (strncmp(c, "a(", 2) == 0) && (n > 0)) {
- c = strchr(c, '.');
- c++;
- n--;
- }
- if (n == 0) {
- temp = *c;
- *c = 0;
- result = NewString(start);
- Printf(result, "a(%s)", rep);
- *c = temp;
- c = strchr(c, '.');
- Append(result, c);
- }
- Clear(t);
- Append(t, result);
- Delete(result);
- }
- /* Return base type of an array */
- SwigType *SwigType_array_type(SwigType *ty) {
- SwigType *t;
- t = Copy(ty);
- while (SwigType_isarray(t)) {
- Delete(SwigType_pop(t));
- }
- return t;
- }
- /* -----------------------------------------------------------------------------
- * Functions
- *
- * SwigType_add_function()
- * SwigType_del_function()
- * SwigType_isfunction()
- * SwigType_pop_function()
- *
- * Add, remove, and test for function types.
- * ----------------------------------------------------------------------------- */
- /* Returns the function type, t, constructed from the parameters, parms */
- SwigType *SwigType_add_function(SwigType *t, ParmList *parms) {
- String *pstr;
- Parm *p;
- Insert(t, 0, ").");
- pstr = NewString("f(");
- p = parms;
- for (p = parms; p; p = nextSibling(p)) {
- if (p != parms)
- Putc(',', pstr);
- Append(pstr, Getattr(p, "type"));
- }
- Insert(t, 0, pstr);
- Delete(pstr);
- return t;
- }
- SwigType *SwigType_pop_function(SwigType *t) {
- SwigType *f = 0;
- SwigType *g = 0;
- char *c = Char(t);
- if (strncmp(c, "q(", 2) == 0) {
- f = SwigType_pop(t);
- c = Char(t);
- }
- if (strncmp(c, "f(", 2)) {
- printf("Fatal error. SwigType_pop_function applied to non-function.\n");
- abort();
- }
- g = SwigType_pop(t);
- if (f)
- SwigType_push(g, f);
- Delete(f);
- return g;
- }
- int SwigType_isfunction(SwigType *t) {
- char *c;
- if (!t) {
- return 0;
- }
- c = Char(t);
- if (strncmp(c, "q(", 2) == 0) {
- /* Might be a 'const' function. Try to skip over the 'const' */
- c = strchr(c, '.');
- if (c)
- c++;
- else
- return 0;
- }
- if (strncmp(c, "f(", 2) == 0) {
- return 1;
- }
- return 0;
- }
- ParmList *SwigType_function_parms(SwigType *t) {
- List *l = SwigType_parmlist(t);
- Hash *p, *pp = 0, *firstp = 0;
- Iterator o;
- for (o = First(l); o.item; o = Next(o)) {
- p = NewParm(o.item, 0);
- if (!firstp)
- firstp = p;
- if (pp) {
- set_nextSibling(pp, p);
- Delete(p);
- }
- pp = p;
- }
- Delete(l);
- return firstp;
- }
- int SwigType_isvarargs(const SwigType *t) {
- if (Strcmp(t, "v(...)") == 0)
- return 1;
- return 0;
- }
- /* -----------------------------------------------------------------------------
- * Templates
- *
- * SwigType_add_template()
- *
- * Template handling.
- * ----------------------------------------------------------------------------- */
- /* -----------------------------------------------------------------------------
- * SwigType_add_template()
- *
- * Adds a template to a type. This template is encoded in the SWIG type
- * mechanism and produces a string like this:
- *
- * vector<int *> ----> "vector<(p.int)>"
- * ----------------------------------------------------------------------------- */
- SwigType *SwigType_add_template(SwigType *t, ParmList *parms) {
- Parm *p;
- Append(t, "<(");
- p = parms;
- for (p = parms; p; p = nextSibling(p)) {
- String *v;
- if (Getattr(p, "default"))
- continue;
- if (p != parms)
- Append(t, ",");
- v = Getattr(p, "value");
- if (v) {
- Append(t, v);
- } else {
- Append(t, Getattr(p, "type"));
- }
- }
- Append(t, ")>");
- return t;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_templateprefix()
- *
- * Returns the prefix before the first template definition.
- * For example:
- *
- * Foo<(p.int)>::bar
- *
- * returns "Foo"
- * ----------------------------------------------------------------------------- */
- String *SwigType_templateprefix(const SwigType *t) {
- const char *s = Char(t);
- const char *c = strstr(s, "<(");
- return c ? NewStringWithSize(s, c - s) : NewString(s);
- }
- /* -----------------------------------------------------------------------------
- * SwigType_templatesuffix()
- *
- * Returns text after a template substitution. Used to handle scope names
- * for example:
- *
- * Foo<(p.int)>::bar
- *
- * returns "::bar"
- * ----------------------------------------------------------------------------- */
- String *SwigType_templatesuffix(const SwigType *t) {
- const char *c;
- c = Char(t);
- while (*c) {
- if ((*c == '<') && (*(c + 1) == '(')) {
- int nest = 1;
- c++;
- while (*c && nest) {
- if (*c == '<')
- nest++;
- if (*c == '>')
- nest--;
- c++;
- }
- return NewString(c);
- }
- c++;
- }
- return NewStringEmpty();
- }
- /* -----------------------------------------------------------------------------
- * SwigType_templateargs()
- *
- * Returns the template arguments
- * For example:
- *
- * Foo<(p.int)>::bar
- *
- * returns "<(p.int)>"
- * ----------------------------------------------------------------------------- */
- String *SwigType_templateargs(const SwigType *t) {
- const char *c;
- const char *start;
- c = Char(t);
- while (*c) {
- if ((*c == '<') && (*(c + 1) == '(')) {
- int nest = 1;
- start = c;
- c++;
- while (*c && nest) {
- if (*c == '<')
- nest++;
- if (*c == '>')
- nest--;
- c++;
- }
- return NewStringWithSize(start, c - start);
- }
- c++;
- }
- return 0;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_istemplate()
- *
- * Tests a type to see if it includes template parameters
- * ----------------------------------------------------------------------------- */
- int SwigType_istemplate(const SwigType *t) {
- char *ct = Char(t);
- ct = strstr(ct, "<(");
- if (ct && (strstr(ct + 2, ")>")))
- return 1;
- return 0;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_base()
- *
- * This function returns the base of a type. For example, if you have a
- * type "p.p.int", the function would return "int".
- * ----------------------------------------------------------------------------- */
- SwigType *SwigType_base(const SwigType *t) {
- char *c;
- char *lastop = 0;
- c = Char(t);
- lastop = c;
- /* Search for the last type constructor separator '.' */
- while (*c) {
- if (*c == '.') {
- if (*(c + 1)) {
- lastop = c + 1;
- }
- c++;
- continue;
- }
- if (*c == '<') {
- /* Skip over template---it's part of the base name */
- int ntemp = 1;
- c++;
- while ((*c) && (ntemp > 0)) {
- if (*c == '>')
- ntemp--;
- else if (*c == '<')
- ntemp++;
- c++;
- }
- if (ntemp)
- break;
- continue;
- }
- if (*c == '(') {
- /* Skip over params */
- int nparen = 1;
- c++;
- while ((*c) && (nparen > 0)) {
- if (*c == '(')
- nparen++;
- else if (*c == ')')
- nparen--;
- c++;
- }
- if (nparen)
- break;
- continue;
- }
- c++;
- }
- return NewString(lastop);
- }
- /* -----------------------------------------------------------------------------
- * SwigType_prefix()
- *
- * Returns the prefix of a datatype. For example, the prefix of the
- * type "p.p.int" is "p.p.".
- * ----------------------------------------------------------------------------- */
- String *SwigType_prefix(const SwigType *t) {
- char *c, *d;
- String *r = 0;
- c = Char(t);
- d = c + strlen(c);
- /* Check for a type constructor */
- if ((d > c) && (*(d - 1) == '.'))
- d--;
- while (d > c) {
- d--;
- if (*d == '>') {
- int nest = 1;
- d--;
- while ((d > c) && (nest)) {
- if (*d == '>')
- nest++;
- if (*d == '<')
- nest--;
- d--;
- }
- }
- if (*d == ')') {
- /* Skip over params */
- int nparen = 1;
- d--;
- while ((d > c) && (nparen)) {
- if (*d == ')')
- nparen++;
- if (*d == '(')
- nparen--;
- d--;
- }
- }
- if (*d == '.') {
- char t = *(d + 1);
- *(d + 1) = 0;
- r = NewString(c);
- *(d + 1) = t;
- return r;
- }
- }
- return NewStringEmpty();
- }
- /* -----------------------------------------------------------------------------
- * SwigType_strip_qualifiers()
- *
- * Strip all qualifiers from a type and return a new type
- * ----------------------------------------------------------------------------- */
- SwigType *SwigType_strip_qualifiers(SwigType *t) {
- static Hash *memoize_stripped = 0;
- SwigType *r;
- List *l;
- Iterator ei;
- if (!memoize_stripped)
- memoize_stripped = NewHash();
- r = Getattr(memoize_stripped, t);
- if (r)
- return Copy(r);
- l = SwigType_split(t);
- r = NewStringEmpty();
- for (ei = First(l); ei.item; ei = Next(ei)) {
- if (SwigType_isqualifier(ei.item))
- continue;
- Append(r, ei.item);
- }
- Delete(l);
- {
- String *key, *value;
- key = Copy(t);
- value = Copy(r);
- Setattr(memoize_stripped, key, value);
- Delete(key);
- Delete(value);
- }
- return r;
- }