diff options
Diffstat (limited to 'Source/Swig/typeobj.c')
-rw-r--r-- | Source/Swig/typeobj.c | 1095 |
1 files changed, 1095 insertions, 0 deletions
diff --git a/Source/Swig/typeobj.c b/Source/Swig/typeobj.c new file mode 100644 index 0000000..085fda3 --- /dev/null +++ b/Source/Swig/typeobj.c @@ -0,0 +1,1095 @@ +/* ----------------------------------------------------------------------------- + * 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: typeobj.c 11080 2009-01-24 13:15:51Z bhy $"; + +#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; +} |