/* ----------------------------------------------------------------------------- * 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. * * Author(s) : David Beazley (beazley@cs.uchicago.edu) * * Copyright (C) 1999-2003. The University of Chicago * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ char cvsroot_stype_c[] = "$Header$"; #include "swig.h" #include /* ----------------------------------------------------------------------------- * 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 * * r.foo<(int,p.double)> foo & * * 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: * * TypeObj_add_pointer() * TypeObj_add_reference() * TypeObj_add_array() * * These are used to build new types. There are also functions to undo these * operations. For example: * * TypeObj_del_pointer() * TypeObj_del_reference() * TypeObj_del_array() * * In addition, there are query functions * * TypeObj_is_pointer() * TypeObj_is_reference() * TypeObj_is_array() * * 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 TypeObj of type 'intptr' will be treated as a simple type and * functions like TypeObj_is_pointer() will evaluate as false. It is strongly * advised that developers use the TypeSys_* interface to check types in a more * reliable manner. * ----------------------------------------------------------------------------- */ typedef String TypeObj; /* ----------------------------------------------------------------------------- * NewTypeObj() * * 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). * ----------------------------------------------------------------------------- */ TypeObj * NewTypeObj(const String_or_char *initial) { return NewString(initial); } /* 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 delimeted 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) { 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; } /* ----------------------------------------------------------------------------- * TypeObj_del_element() * * Deletes one type element from the type. * ----------------------------------------------------------------------------- */ void TypeObj_del_element(TypeObj *t) { int sz = element_size(Char(t)); Delslice(t,0,sz); } /* ----------------------------------------------------------------------------- * Pointers * * TypeObj_add_pointer() * TypeObj_del_pointer() * TypeObj_is_pointer() * * Add, remove, and test if a type is a pointer. The deletion and query * functions take into account qualifiers (if any). * ----------------------------------------------------------------------------- */ void TypeObj_add_pointer(TypeObj *t) { Insert(t,0,"p."); } void TypeObj_del_pointer(TypeObj *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); } int TypeObj_is_pointer(TypeObj *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 * * TypeObj_add_reference() * TypeObj_del_reference() * TypeObj_is_reference() * * Add, remove, and test if a type is a pointer. The deletion and query * functions take into account qualifiers (if any). * ----------------------------------------------------------------------------- */ void TypeObj_add_reference(TypeObj *t) { Insert(t,0,"r."); } void TypeObj_del_reference(TypeObj *t) { char *c = Char(t); assert(strncmp(c,"r.",2) == 0); Delslice(t,0,2); } int TypeObj_is_reference(TypeObj *t) { char *c; if (!t) return 0; c = Char(t); if (strncmp(c,"r.",2) == 0) { return 1; } return 0; } /* ----------------------------------------------------------------------------- * Qualifiers * * TypeObj_add_qualifier() * TypeObj_del_qualifier() * TypeObj_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)". * ----------------------------------------------------------------------------- */ void TypeObj_add_qualifier(TypeObj *t, String *qual) { char temp[256]; char *cqual = Char(qual); if (!SwigType_is_qualifier(t)) { sprintf(temp,"q(%s).",cqual); Insert(t,0,temp); } else { /* Already has a qualifier on it. We are going to generate a canonical qualifier string */ String *qt; char *c, *qc, *cqt; String *newq; qt = NewStringWithSize(t,element_size(t)); /* Get the old qualifier */ cqt = Char(qt); /* See if the added qualifier is already there */ if (strstr(cqt,cqual)) { /* Already added this qualifier */ Delete(qt); return; } /* We need to add the qualifier to the qualifier list */ /* To do this, we keep the qualifiers in alphabetical order */ newq = NewString("q("); qc = cqual; c = cqt+2; c = strtok(c," )."); while (c) { if (!strlen(c)) { c = strtok(NULL," )."); continue; } if (qc) { if (strcmp(c,qc) < 0) { Printf(newq,"%s",c); } else { Printf(newq,"%s %s", qc,c); qc = 0; } } else { Printf(newq,"%s",c); } c = strtok(NULL," )."); if (c) Putc(' ',newq); } if (qc) { Printf(newq," %s",qc); } Putc(')',newq); Putc('.',newq); SwigType_push(t,newq); Delete(newq); Delete(qt); } } /* ----------------------------------------------------------------------------- * SwigType_add_memberpointer() * * Add a pointer to a member to a type * ----------------------------------------------------------------------------- */ void SwigType_add_memberpointer(SwigType *t, String_or_char *name) { String *temp = NewStringf("m(%s).", name); Insert(t,0,temp); Delete(temp); } /* ----------------------------------------------------------------------------- * SwigType_add_array() * * Adds an array constructor to a type * ----------------------------------------------------------------------------- */ void SwigType_add_array(SwigType *t, String *size) { char temp[256]; sprintf(temp,"a(%s).", Char(size)); Insert(t,0,temp); } /* ----------------------------------------------------------------------------- * SwigType_pop_arrays() * * Pop all arrays off as a single item * ----------------------------------------------------------------------------- */ SwigType * SwigType_pop_arrays(SwigType *t) { String *ta; if (!SwigType_isarray(t)) return 0; ta = NewString(""); while (SwigType_isarray(t)) { SwigType *td = SwigType_pop(t); Append(ta,td); Delete(td); } return ta; } /* ----------------------------------------------------------------------------- * SwigType_add_qualifier() * * Adds a qualifier to a type * ----------------------------------------------------------------------------- */ /* ----------------------------------------------------------------------------- * SwigType_add_function() * * Adds a function to a type. Accepts a list of abstract types as parameters. * These abstract types should be passed as a list of type-strings. * ----------------------------------------------------------------------------- */ void 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); Printf(pstr,"%s", Getattr(p,"type")); } Insert(t,0,pstr); Delete(pstr); } 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; } ParmList * SwigType_function_parms(SwigType *t) { List *l = SwigType_parmlist(t); Hash *p, *pp = 0, *firstp = 0; DOH *obj; for (obj = Firstitem(l); obj; obj = Nextitem(l)) { p = NewParm(obj,0); if (!firstp) firstp = p; if (pp) { set_nextSibling(pp,p); } pp = p; } Delete(l); return firstp; } /* ----------------------------------------------------------------------------- * 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 ----> "vector<(p.int)>" * ----------------------------------------------------------------------------- */ void 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,")>"); } /* ----------------------------------------------------------------------------- * static isolate_element() * * Isolate a single element of a type string (delimeted by periods) * ----------------------------------------------------------------------------- */ static String * isolate_element(char *c) { String *result = NewString(""); while (*c) { if (*c == '.') { Putc(*c,result); return result; } else if (*c == '(') { int nparen = 1; Putc(*c,result); c++; while(*c) { Putc(*c,result); if (*c == '(') nparen++; if (*c == ')') { nparen--; if (nparen == 0) break; } c++; } } else { Putc(*c,result); } if (*c) c++; } return result; } /* ----------------------------------------------------------------------------- * SwigType_split() * * Splits a type into it's component parts and returns a list of string. * ----------------------------------------------------------------------------- */ List *SwigType_split(SwigType *t) { DOH *item; List *list; char *c; int len; c = Char(t); list = NewList(); while (*c) { item = isolate_element(c); len = Len(item); if (len) { Append(list,item); Delete(item); } else { Delete(item); break; } c = c + len; if (*c == '.') c++; } return list; } /* ----------------------------------------------------------------------------- * SwigType_pop() * * Pop off the first type-constructor object and updates the type * ----------------------------------------------------------------------------- */ String *SwigType_pop(SwigType *t) { String *result; char *c; if (Len(t) == 0) return 0; c = Char(t); result = isolate_element(c); Replace(t,result,"",DOH_REPLACE_ANY | DOH_REPLACE_FIRST); c = Char(t); if (*c == '.') { Delitem(t,0); } return result; } /* ----------------------------------------------------------------------------- * SwigType_push() * * Push a type constructor onto the type * ----------------------------------------------------------------------------- */ void SwigType_push(SwigType *t, String *cons) { if (!cons) return; if (!Len(cons)) return; if (Len(t)) { char *c = Char(cons); if (c[strlen(c)-1] != '.') Insert(t,0,"."); } Insert(t,0,cons); } /* ----------------------------------------------------------------------------- * SwigType_parmlist() * * Splits a comma separated list of components into strings. * ----------------------------------------------------------------------------- */ List *SwigType_parmlist(const String *p) { DOH *item; List *list; char *c; c = Char(p); while (*c && (*c != '(') && (*c != '.')) c++; if (!*c || (*c == '.')) return 0; c++; list = NewList(); item = NewString(""); while (*c) { if (*c == ',') { Append(list,item); Delete(item); item = NewString(""); } else if (*c == '(') { int nparens = 1; Putc(*c,item); c++; while (*c) { Putc(*c,item); if (*c == '(') nparens++; if (*c == ')') { nparens--; if (nparens == 0) break; } c++; } } else if (*c == ')') { break; } else { Putc(*c,item); } if (*c) c++; } Append(list,item); Delete(item); return list; } /* ----------------------------------------------------------------------------- * SwigType_parm() * * Returns the parameter of an operator as a string * ----------------------------------------------------------------------------- */ String *SwigType_parm(SwigType *t) { String *result; char *c; int nparens = 0; c = Char(t); while (*c && (*c != '(') && (*c != '.')) c++; if (!*c || (*c == '.')) return 0; c++; result = NewString(""); while (*c) { if (*c == ')') { if (nparens == 0) return result; nparens--; } else if (*c == '(') { nparens++; } Putc(*c,result); c++; } return result; } /* ----------------------------------------------------------------------------- * SwigType_ispointer() * SwigType_ispointer_return() * SwigType_isarray() * SwigType_isreference() * SwigType_isfunction() * SwigType_isqualifier() * * Testing functions for querying a raw datatype * ----------------------------------------------------------------------------- */ int SwigType_ispointer_return(SwigType *t) { char* c; int idx; if (!t) return 0; c = Char(t); idx = strlen(c)-4; if (idx >= 0) { return (strcmp(c+idx, ").p.") == 0); } return 0; } int SwigType_isreference_return(SwigType *t) { char* c; int idx; if (!t) return 0; c = Char(t); idx = strlen(c)-4; if (idx >= 0) { return (strcmp(c+idx, ").r.") == 0); } return 0; } int SwigType_ismemberpointer(SwigType *t) { char *c; if (!t) return 0; c = Char(t); if (strncmp(c,"m(",2) == 0) { return 1; } return 0; } int SwigType_isarray(SwigType *t) { char *c; if (!t) return 0; c = Char(t); if (strncmp(c,"a(",2) == 0) { return 1; } return 0; } 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; } int SwigType_isqualifier(SwigType *t) { char *c; if (!t) return 0; c = Char(t); if (strncmp(c,"q(",2) == 0) { return 1; } return 0; } int SwigType_isconst(SwigType *t) { char *c; if (!t) return 0; c = Char(t); if (strncmp(c,"q(",2) == 0) { String *q = SwigType_parm(t); if (strstr(Char(q),"const")) { Delete(q); return 1; } Delete(q); } /* Hmmm. Might be const through a typedef */ if (SwigType_issimple(t)) { int ret; SwigType *td = SwigType_typedef_resolve(t); if (td) { ret = SwigType_isconst(td); Delete(td); return ret; } } return 0; } int SwigType_ismutable(SwigType *t) { int r; SwigType *qt = SwigType_typedef_resolve_all(t); if (SwigType_isreference(qt)) { Delete(SwigType_pop(qt)); } r = SwigType_isconst(qt); Delete(qt); return r ? 0 : 1; } int SwigType_isenum(SwigType *t) { char *c = Char(t); if (!t) return 0; if (strncmp(c,"enum ",5) == 0) { return 1; } return 0; } int SwigType_issimple(SwigType *t) { char *c = Char(t); if (!t) return 0; while (*c) { if (*c == '<') { int nest = 1; c++; while (*c && nest) { if (*c == '<') nest++; if (*c == '>') nest--; c++; } c--; } if (*c == '.') return 0; c++; } return 1; } int SwigType_isvarargs(const SwigType *t) { if (Strcmp(t,"v(...)") == 0) return 1; return 0; } int SwigType_istemplate(const SwigType *t) { if (Strstr(t,"<(")) return 1; return 0; } /* ----------------------------------------------------------------------------- * SwigType_base() * * Returns the base name of a datatype. * ----------------------------------------------------------------------------- */ SwigType *SwigType_base(SwigType *t) { char *c, *d; c = Char(t); d = c + strlen(c); /* Check for a type constructor */ if ((d > c) && (*(d-1) == '.')) d--; while (d > c) { d--; if (*d == '>') { /* Skip over template--that's part of the base name */ int ntemp = 1; d--; while ((d > c) && (ntemp > 0)) { if (*d == '>') ntemp++; if (*d == '<') ntemp--; d--; } } if (*d == ')') { /* Skip over params */ int nparen = 1; d--; while ((d > c) && (nparen > 0)) { if (*d == ')') nparen++; if (*d == '(') nparen--; d--; } } if (*d == '.') return NewString(d+1); } return NewString(c); } /* ----------------------------------------------------------------------------- * SwigType_prefix() * * Returns the prefix of a datatype * ----------------------------------------------------------------------------- */ String *SwigType_prefix(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 NewString(""); } /* ----------------------------------------------------------------------------- * SwigType_templateprefix() * * Returns the prefix before the first template definition. * For example: * * Foo<(p.int)>::bar * * Results in "Foo" * ----------------------------------------------------------------------------- */ String * SwigType_templateprefix(SwigType *t) { char *c; String *r; String *s = NewString(t); c = Char(s); while (*c) { if (*c == '<') { *c = 0; r = NewString(Char(s)); Delete(s); return r; } c++; } return 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) { 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 NewString(""); } /* ----------------------------------------------------------------------------- * SwigType_templateargs() * * Returns the template part * ----------------------------------------------------------------------------- */ String * SwigType_templateargs(SwigType *t) { String *result = NewString(""); char *c; c = Char(t); while (*c) { if ((*c == '<') && (*(c+1) == '(')) { int nest = 1; Putc(*c,result); c++; while (*c && nest) { Putc(*c,result); if (*c == '<') nest++; if (*c == '>') nest--; c++; } return result; } c++; } Delete(result); return 0; } /* ----------------------------------------------------------------------------- * SwigType_strip_qualifiers() * * Strip all qualifiers from a type and return a new type * ----------------------------------------------------------------------------- */ static Hash *memoize_stripped = 0; SwigType * SwigType_strip_qualifiers(SwigType *t) { SwigType *r; List *l; SwigType *e; if (!memoize_stripped) memoize_stripped = NewHash(); r = Getattr(memoize_stripped,t); if (r) return Copy(r); l = SwigType_split(t); r = NewString(""); for (e = Firstitem(l); e; e = Nextitem(l)) { if (SwigType_isqualifier(e)) continue; Append(r,e); } Setattr(memoize_stripped,Copy(t),Copy(r)); return r; } /* ----------------------------------------------------------------------------- * SwigType_array_ndim() * * Returns the number of dimensions of an array. * ----------------------------------------------------------------------------- */ 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; } /* ----------------------------------------------------------------------------- * SwigType_array_getdim() * * Get the value of the nth 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) return SwigType_parm(c); return 0; } /* ----------------------------------------------------------------------------- * SwigType_array_setdim() * * Replace the nth dimension of an array to a new value. * ----------------------------------------------------------------------------- */ void SwigType_array_setdim(SwigType *t, int n, String_or_char *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); } /* ----------------------------------------------------------------------------- * SwigType_array_type() * * Return the 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; } /* ----------------------------------------------------------------------------- * SwigType_default() * * Create the default string for this datatype. This takes a type and strips it * down to its most primitive form--resolving all typedefs and removing operators. * * Rules: * Pointers: p.SWIGTYPE * References: r.SWIGTYPE * Arrays: a().SWIGTYPE * Types: SWIGTYPE * MemberPointer: m(CLASS).SWIGTYPE * Enums: enum SWIGENUM * ----------------------------------------------------------------------------- */ static Hash *default_cache = 0; SwigType *SwigType_default(SwigType *t) { String *r1, *def; String *r = 0; if (!default_cache) default_cache = NewHash(); r = Getattr(default_cache,t); if (r) return Copy(r); r = t; while ((r1 = SwigType_typedef_resolve(r))) { if (r != t) Delete(r); r = r1; } if (SwigType_isqualifier(r)) { if (r == t) r = Copy(t); do { Delete(SwigType_pop(r)); } while (SwigType_isqualifier(r)); } if (SwigType_ispointer(r)) { def = NewString("p.SWIGTYPE"); } else if (SwigType_isreference(r)) { def = NewString("r.SWIGTYPE"); } else if (SwigType_isarray(r)) { def = NewString("a().SWIGTYPE"); } else if (SwigType_ismemberpointer(r)) { def = NewString("m(CLASS).SWIGTYPE"); } else if (SwigType_isenum(r)) { def = NewString("enum SWIGTYPE"); } else if (SwigType_isvarargs(r)) { def = NewString("v(...)"); } else { def = NewString("SWIGTYPE"); } if (r != t) Delete(r); Setattr(default_cache,t,Copy(def)); return def; } /* ----------------------------------------------------------------------------- * SwigType_namestr() * * Returns a string of the base type. Takes care of template expansions * ----------------------------------------------------------------------------- */ String * SwigType_namestr(const SwigType *t) { String *r; String *suffix; List *p; char tmp[256]; char *c, *d, *e; int i, sz; if (!SwigType_istemplate(t)) return NewString(t); c = Strstr(t,"<("); d = Char(t); e = tmp; while (d != c) { *(e++) = *(d++); } *e = 0; r = NewString(tmp); Putc('<',r); p = SwigType_parmlist(t); sz = Len(p); for (i = 0; i < sz; i++) { Append(r,SwigType_str(Getitem(p,i),0)); if ((i+1) < sz) Putc(',',r); } Putc(' ',r); Putc('>',r); suffix = SwigType_templatesuffix(t); Append(r,suffix); Delete(suffix); #if 0 if (SwigType_istemplate(r)) { SwigType *rr = SwigType_namestr(r); Delete(r); return rr; } #endif return r; } /* ----------------------------------------------------------------------------- * SwigType_str() * * Create a C string representation of a datatype. * ----------------------------------------------------------------------------- */ String * SwigType_str(SwigType *s, const String_or_char *id) { String *result; String *element = 0, *nextelement; List *elements; int nelements, i; if (id) { result = NewString(Char(id)); } else { result = NewString(""); } elements = SwigType_split(s); nelements = Len(elements); if (nelements > 0) { element = Getitem(elements,0); } /* Now, walk the type list and start emitting */ for (i = 0; i < nelements; i++) { if (i < (nelements - 1)) { nextelement = Getitem(elements,i+1); } else { nextelement = 0; } if (SwigType_isqualifier(element)) { DOH *q = 0; q = SwigType_parm(element); Insert(result,0," "); Insert(result,0,q); Delete(q); } else if (SwigType_ispointer(element)) { Insert(result,0,"*"); if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { Insert(result,0,"("); Append(result,")"); } } else if (SwigType_ismemberpointer(element)) { String *q; q = SwigType_parm(element); Insert(result,0,"::*"); Insert(result,0,q); if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { Insert(result,0,"("); Append(result,")"); } Delete(q); } else if (SwigType_isreference(element)) { Insert(result,0,"&"); if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { Insert(result,0,"("); Append(result,")"); } } else if (SwigType_isarray(element)) { DOH *size; Append(result,"["); size = SwigType_parm(element); Append(result,size); Append(result,"]"); Delete(size); } else if (SwigType_isfunction(element)) { DOH *parms, *p; int j, plen; Append(result,"("); parms = SwigType_parmlist(element); plen = Len(parms); for (j = 0; j < plen; j++) { p = SwigType_str(Getitem(parms,j),0); Append(result,p); if (j < (plen-1)) Append(result,","); } Append(result,")"); Delete(parms); } else { if (Strcmp(element,"v(...)") == 0) { Insert(result,0,"..."); } else { String *bs = SwigType_namestr(element); Insert(result,0," "); Insert(result,0,bs); Delete(bs); } } element = nextelement; } Delete(elements); Chop(result); return result; } /* ----------------------------------------------------------------------------- * SwigType_ltype(SwigType *ty) * * Create a locally assignable type * ----------------------------------------------------------------------------- */ SwigType * SwigType_ltype(SwigType *s) { String *result; String *element; SwigType *td, *tc = 0; List *elements; int nelements, i; int firstarray = 1; result = NewString(""); tc = Copy(s); /* Nuke all leading qualifiers */ while (SwigType_isqualifier(tc)) { Delete(SwigType_pop(tc)); } if (SwigType_issimple(tc)) { /* Resolve any typedef definitions */ td = SwigType_typedef_resolve(tc); if (td && (SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isenum(td) || SwigType_isreference(td))) { /* We need to use the typedef type */ Delete(tc); tc = td; } else if (td) { Delete(td); } } elements = SwigType_split(tc); nelements = Len(elements); /* Now, walk the type list and start emitting */ for (i = 0; i < nelements; i++) { element = Getitem(elements,i); if (SwigType_isqualifier(element)) { /* Do nothing. Ignore */ } else if (SwigType_ispointer(element)) { Append(result,element); firstarray = 0; } else if (SwigType_ismemberpointer(element)) { Append(result,element); firstarray = 0; } else if (SwigType_isreference(element)) { Append(result,"p."); firstarray = 0; } else if (SwigType_isarray(element) && firstarray) { Append(result,"p."); firstarray = 0; } else if (SwigType_isenum(element)) { Append(result,"int"); } else { Append(result,element); } } Delete(elements); Delete(tc); return result; } /* ----------------------------------------------------------------------------- * SwigType_lstr(DOH *s, DOH *id) * * Produces a type-string that is suitable as a lvalue in an expression. * That is, a type that can be freely assigned a value without violating * any C assignment rules. * * - Qualifiers such as 'const' and 'volatile' are stripped. * - Arrays are converted into a *single* pointer (i.e., * double [][] becomes double *). * - References are converted into a pointer. * - Typedef names that refer to read-only types will be replaced * with an equivalent assignable version. * -------------------------------------------------------------------- */ String * SwigType_lstr(SwigType *s, const String_or_char *id) { String *result; SwigType *tc; tc = SwigType_ltype(s); result = SwigType_str(tc,id); Delete(tc); return result; } /* ----------------------------------------------------------------------------- * SwigType_rcaststr() * * Produces a casting string that maps the type returned by lstr() to the real * datatype printed by str(). * ----------------------------------------------------------------------------- */ String *SwigType_rcaststr(SwigType *s, const String_or_char *name) { String *result, *cast; String *element = 0, *nextelement; SwigType *td, *rs, *tc = 0; List *elements; int nelements, i; int clear = 1; int firstarray = 1; int isreference = 0; result = NewString(""); if (SwigType_isconst(s)) { tc = Copy(s); Delete(SwigType_pop(tc)); rs = tc; } else { rs = s; } if (SwigType_issimple(rs)) { td = SwigType_typedef_resolve(rs); if ((td) && (SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td))) { elements = SwigType_split(td); } else if (td && SwigType_isenum(td)) { elements = SwigType_split(rs); clear = 0; } else { elements = SwigType_split(rs); } if (td) Delete(td); } else { elements = SwigType_split(rs); } nelements = Len(elements); if (nelements > 0) { element = Getitem(elements,0); } /* Now, walk the type list and start emitting */ for (i = 0; i < nelements; i++) { if (i < (nelements - 1)) { nextelement = Getitem(elements,i+1); } else { nextelement = 0; } if (SwigType_isqualifier(element)) { DOH *q = 0; q = SwigType_parm(element); Insert(result,0," "); Insert(result,0,q); Delete(q); clear = 0; } else if (SwigType_ispointer(element)) { Insert(result,0,"*"); if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { Insert(result,0,"("); Append(result,")"); } firstarray = 0; } else if (SwigType_ismemberpointer(element)) { String *q; Insert(result,0,"::*"); q = SwigType_parm(element); Insert(result,0,q); Delete(q); if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { Insert(result,0,"("); Append(result,")"); } firstarray = 0; } else if (SwigType_isreference(element)) { Insert(result,0,"&"); if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { Insert(result,0,"("); Append(result,")"); } isreference = 1; } else if (SwigType_isarray(element)) { DOH *size; if (firstarray && !isreference) { Append(result,"(*)"); firstarray = 0; } else { Append(result,"["); size = SwigType_parm(element); Append(result,size); Append(result,"]"); Delete(size); clear = 0; } } else if (SwigType_isfunction(element)) { DOH *parms, *p; int j, plen; Append(result,"("); parms = SwigType_parmlist(element); plen = Len(parms); for (j = 0; j < plen; j++) { p = SwigType_str(Getitem(parms,j),0); Append(result,p); if (j < (plen-1)) Append(result,","); } Append(result,")"); Delete(parms); } else if (SwigType_isenum(element)) { String *bs = SwigType_namestr(element); Insert(result,0,bs); Delete(bs); clear = 0; } else { String *bs = SwigType_namestr(element); Insert(result,0," "); Insert(result,0,bs); Delete(bs); } element = nextelement; } Delete(elements); if (clear) { cast = NewString(""); } else { cast = NewStringf("(%s)",result); } if (name) { if (isreference) { Append(cast,"*"); } Append(cast,name); } Delete(result); Delete(tc); return cast; } /* ----------------------------------------------------------------------------- * SwigType_lcaststr() * * Casts a variable from the real type to the local datatype. * ----------------------------------------------------------------------------- */ String *SwigType_lcaststr(SwigType *s, const String_or_char *name) { String *result; result = NewString(""); if (SwigType_isarray(s)) { Printf(result,"(%s)%s", SwigType_lstr(s,0),name); } else if (SwigType_isreference(s)) { Printf(result,"(%s)", SwigType_str(s,0)); if (name) Printf(result,"%s", name); } else if (SwigType_isqualifier(s)) { Printf(result,"(%s)%s", SwigType_lstr(s,0),name); } else { if (name) Append(result,name); } return result; } String *SwigType_manglestr_default(SwigType *s) { char *c; String *result,*base; SwigType *lt; SwigType *ss = 0; if (SwigType_istemplate(s)) { ss = SwigType_typedef_resolve_all(s); s = ss; } lt = SwigType_ltype(s); result = SwigType_prefix(lt); base = SwigType_base(lt); c = Char(result); while (*c) { if (!isalnum((int)*c)) *c = '_'; c++; } if (SwigType_istemplate(base)) { String *b = SwigType_namestr(base); Delete(base); base = b; } Replace(base,"struct ","", DOH_REPLACE_ANY); /* This might be problematic */ Replace(base,"class ","", DOH_REPLACE_ANY); Replace(base,"union ","", DOH_REPLACE_ANY); c = Char(base); while (*c) { if (*c == '<') *c = 'T'; else if (*c == '>') *c = 't'; else if (*c == '*') *c = 'p'; else if (*c == '[') *c = 'a'; else if (*c == ']') *c = 'A'; else if (*c == '&') *c = 'R'; else if (*c == '(') *c = 'f'; else if (*c == ')') *c = 'F'; else if (!isalnum((int)*c)) *c = '_'; c++; } Append(result,base); Insert(result,0,"_"); Delete(lt); Delete(base); if (ss) Delete(ss); return result; } String *SwigType_manglestr(SwigType *s) { return SwigType_manglestr_default(s); } /* ----------------------------------------------------------------------------- * SwigType_typename_replace() * * Replaces a typename in a type with something else. Needed for templates. * ----------------------------------------------------------------------------- */ void SwigType_typename_replace(SwigType *t, String *pat, String *rep) { String *nt; int i; List *elem; if (!Strstr(t,pat)) return; if (Strcmp(t,pat) == 0) { Replace(t,pat,rep,DOH_REPLACE_ANY); return; } nt = NewString(""); elem = SwigType_split(t); for (i = 0; i < Len(elem); i++) { String *e = Getitem(elem,i); if (SwigType_issimple(e)) { if (Strcmp(e,pat) == 0) { /* Replaces a type of the form 'pat' with 'rep' */ Replace(e,pat,rep,DOH_REPLACE_ANY); } else if (SwigType_istemplate(e)) { /* Replaces a type of the form 'pat' with 'rep' */ if (Strncmp(e,pat,Len(pat)) == 0) { String *repbase = SwigType_templateprefix(rep); Replace(e,pat,repbase,DOH_REPLACE_ID | DOH_REPLACE_FIRST); Delete(repbase); } { List *tparms = SwigType_parmlist(e); int j; String *nt = SwigType_templateprefix(e); Printf(nt,"<("); for (j = 0; j < Len(tparms); j++) { SwigType_typename_replace(Getitem(tparms,j), pat, rep); Printf(nt,"%s",Getitem(tparms,j)); if (j < (Len(tparms)-1)) Printf(nt,","); } Printf(nt,")>%s", SwigType_templatesuffix(e)); Clear(e); Append(e,nt); Delete(nt); } } else if (Swig_scopename_check(e)) { String *first, *rest; first = Swig_scopename_first(e); rest = Swig_scopename_suffix(e); SwigType_typename_replace(rest,pat,rep); SwigType_typename_replace(first,pat,rep); Clear(e); Printf(e,"%s::%s", first,rest); Delete(first); Delete(rest); } } else if (SwigType_isfunction(e)) { int j; List *fparms = SwigType_parmlist(e); Clear(e); Printf(e,"f("); for (j = 0; j < Len(fparms); j++) { SwigType_typename_replace(Getitem(fparms,j), pat, rep); Printf(e,"%s",Getitem(fparms,j)); if (j < (Len(fparms)-1)) Printf(e,","); } Printf(e,")."); } Append(nt,e); } Clear(t); Append(t,nt); } /* ----------------------------------------------------------------------------- * SwigType_check_decl() * * Checks type declarators for a match * ----------------------------------------------------------------------------- */ int SwigType_check_decl(SwigType *ty, const SwigType *decl) { SwigType *t,*t1,*t2; int r; t = SwigType_typedef_resolve_all(ty); t1 = SwigType_strip_qualifiers(t); t2 = SwigType_prefix(t1); r = Cmp(t2,decl); Delete(t); Delete(t1); Delete(t2); if (r == 0) return 1; return 0; }