/tags/rel-2.0.0/trunk/Source/Swig/typesys.c
# · C · 2073 lines · 1444 code · 206 blank · 423 comment · 343 complexity · fef339c00239f2d36ab0acbf39922f36 MD5 · raw file
Large files are truncated click here to view the full file
- /* -----------------------------------------------------------------------------
- * This file is part of SWIG, which is licensed as a whole under version 3
- * (or any later version) of the GNU General Public License. Some additional
- * terms also apply to certain portions of SWIG. The full details of the SWIG
- * license and copyrights can be found in the LICENSE and COPYRIGHT files
- * included with the SWIG source code as distributed by the SWIG developers
- * and at http://www.swig.org/legal.html.
- *
- * typesys.c
- *
- * SWIG type system management. These functions are used to manage
- * the C++ type system including typenames, typedef, type scopes,
- * inheritance, and namespaces. Generation of support code for the
- * run-time type checker is also handled here.
- * ----------------------------------------------------------------------------- */
- char cvsroot_typesys_c[] = "$Id: typesys.c 12025 2010-05-14 04:10:19Z olly $";
- #include "swig.h"
- #include "cparse.h"
- /* -----------------------------------------------------------------------------
- * Synopsis
- *
- * The purpose of this module is to manage type names and scoping issues related
- * to the C++ type system. The primary use is tracking typenames through typedef
- * and inheritance.
- *
- * New typenames are introduced by typedef, class, and enum declarations.
- * Each type is declared in a scope. This is either the global scope, a
- * class, or a namespace. For example:
- *
- * typedef int A; // Typename A, in global scope
- * namespace Foo {
- * typedef int A; // Typename A, in scope Foo::
- * }
- * class Bar { // Typename Bar, in global scope
- * typedef int A; // Typename A, in scope Bar::
- * }
- *
- * To manage scopes, the type system is constructed as a tree of hash tables. Each
- * hash table contains the following attributes:
- *
- * "name" - Scope name
- * "qname" - Fully qualified typename
- * "typetab" - Type table containing typenames and typedef information
- * "symtab" - Hash table of symbols defined in a scope
- * "inherit" - List of inherited scopes
- * "parent" - Parent scope
- *
- * Typedef information is stored in the "typetab" hash table. For example,
- * if you have these declarations:
- *
- * typedef int A;
- * typedef A B;
- * typedef B *C;
- *
- * typetab is built as follows:
- *
- * "A" : "int"
- * "B" : "A"
- * "C" : "p.B"
- *
- * To resolve a type back to its root type, one repeatedly expands on the type base.
- * For example:
- *
- * C *[40] ---> a(40).p.C (string type representation, see stype.c)
- * ---> a(40).p.p.B (C --> p.B)
- * ---> a(40).p.p.A (B --> A)
- * ---> a(40).p.p.int (A --> int)
- *
- * For inheritance, SWIG tries to resolve types back to the base class. For instance, if
- * you have this:
- *
- * class Foo {
- * public:
- * typedef int Integer;
- * };
- *
- * class Bar : public Foo {
- * void blah(Integer x);
- * };
- *
- * The argument type of Bar::blah will be set to Foo::Integer.
- *
- * The scope-inheritance mechanism is used to manage C++ namespace aliases.
- * For example, if you have this:
- *
- * namespace Foo {
- * typedef int Integer;
- * }
- *
- * namespace F = Foo;
- *
- * In this case, "F::" is defined as a scope that "inherits" from Foo. Internally,
- * "F::" will merely be an empty scope that refers to Foo. SWIG will never
- * place new type information into a namespace alias---attempts to do so
- * will generate a warning message (in the parser) and will place information into
- * Foo instead.
- *
- *----------------------------------------------------------------------------- */
- static Typetab *current_scope = 0; /* Current type scope */
- static Hash *current_typetab = 0; /* Current type table */
- static Hash *current_symtab = 0; /* Current symbol table */
- static Typetab *global_scope = 0; /* The global scope */
- static Hash *scopes = 0; /* Hash table containing fully qualified scopes */
- /* Performance optimization */
- #define SWIG_TYPEDEF_RESOLVE_CACHE
- static Hash *typedef_resolve_cache = 0;
- static Hash *typedef_all_cache = 0;
- static Hash *typedef_qualified_cache = 0;
- static Typetab *SwigType_find_scope(Typetab *s, String *nameprefix);
- /* common attribute keys, to avoid calling find_key all the times */
- /*
- Enable this one if your language fully support SwigValueWrapper<T>.
-
- Leaving at '0' keeps the old swig behavior, which is not
- always safe, but is well known.
- Setting at '1' activates the new scheme, which is always safe but
- it requires all the typemaps to be ready for that.
-
- */
- static int value_wrapper_mode = 0;
- int Swig_value_wrapper_mode(int mode) {
- value_wrapper_mode = mode;
- return mode;
- }
- static void flush_cache() {
- typedef_resolve_cache = 0;
- typedef_all_cache = 0;
- typedef_qualified_cache = 0;
- }
- /* Initialize the scoping system */
- void SwigType_typesystem_init() {
- if (global_scope)
- Delete(global_scope);
- if (scopes)
- Delete(scopes);
- current_scope = NewHash();
- global_scope = current_scope;
- Setattr(current_scope, "name", ""); /* No name for global scope */
- current_typetab = NewHash();
- Setattr(current_scope, "typetab", current_typetab);
- current_symtab = 0;
- scopes = NewHash();
- Setattr(scopes, "", current_scope);
- }
- /* -----------------------------------------------------------------------------
- * SwigType_typedef()
- *
- * Defines a new typedef in the current scope. Returns -1 if the type name is
- * already defined.
- * ----------------------------------------------------------------------------- */
- int SwigType_typedef(SwigType *type, const_String_or_char_ptr name) {
- if (Getattr(current_typetab, name))
- return -1; /* Already defined */
- if (Strcmp(type, name) == 0) { /* Can't typedef a name to itself */
- return 0;
- }
- /* Check if 'type' is already a scope. If so, we create an alias in the type
- system for it. This is needed to make strange nested scoping problems work
- correctly. */
- {
- Typetab *t = SwigType_find_scope(current_scope, type);
- if (t) {
- SwigType_new_scope(name);
- SwigType_inherit_scope(t);
- SwigType_pop_scope();
- }
- }
- Setattr(current_typetab, name, type);
- flush_cache();
- return 0;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_typedef_class()
- *
- * Defines a class in the current scope.
- * ----------------------------------------------------------------------------- */
- int SwigType_typedef_class(const_String_or_char_ptr name) {
- String *cname;
- /* Printf(stdout,"class : '%s'\n", name); */
- if (Getattr(current_typetab, name))
- return -1; /* Already defined */
- cname = NewString(name);
- Setmeta(cname, "class", "1");
- Setattr(current_typetab, cname, cname);
- Delete(cname);
- flush_cache();
- return 0;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_scope_name()
- *
- * Returns the qualified scope name of a type table
- * ----------------------------------------------------------------------------- */
- String *SwigType_scope_name(Typetab *ttab) {
- String *qname = NewString(Getattr(ttab, "name"));
- ttab = Getattr(ttab, "parent");
- while (ttab) {
- String *pname = Getattr(ttab, "name");
- if (Len(pname)) {
- Insert(qname, 0, "::");
- Insert(qname, 0, pname);
- }
- ttab = Getattr(ttab, "parent");
- }
- return qname;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_new_scope()
- *
- * Creates a new scope
- * ----------------------------------------------------------------------------- */
- void SwigType_new_scope(const_String_or_char_ptr name) {
- Typetab *s;
- Hash *ttab;
- String *qname;
- if (!name) {
- name = "<unnamed>";
- }
- s = NewHash();
- Setattr(s, "name", name);
- Setattr(s, "parent", current_scope);
- ttab = NewHash();
- Setattr(s, "typetab", ttab);
- /* Build fully qualified name and */
- qname = SwigType_scope_name(s);
- Setattr(scopes, qname, s);
- Setattr(s, "qname", qname);
- Delete(qname);
- current_scope = s;
- current_typetab = ttab;
- current_symtab = 0;
- flush_cache();
- }
- /* -----------------------------------------------------------------------------
- * SwigType_inherit_scope()
- *
- * Makes the current scope inherit from another scope. This is used for both
- * C++ class inheritance, namespaces, and namespace aliases.
- * ----------------------------------------------------------------------------- */
- void SwigType_inherit_scope(Typetab *scope) {
- List *inherits;
- int i, len;
- inherits = Getattr(current_scope, "inherit");
- if (!inherits) {
- inherits = NewList();
- Setattr(current_scope, "inherit", inherits);
- Delete(inherits);
- }
- assert(scope != current_scope);
- len = Len(inherits);
- for (i = 0; i < len; i++) {
- Node *n = Getitem(inherits, i);
- if (n == scope)
- return;
- }
- Append(inherits, scope);
- }
- /* -----------------------------------------------------------------------------
- * SwigType_scope_alias()
- *
- * Creates a scope-alias.
- * ----------------------------------------------------------------------------- */
- void SwigType_scope_alias(String *aliasname, Typetab *ttab) {
- String *q;
- /* Printf(stdout,"alias: '%s' '%x'\n", aliasname, ttab); */
- q = SwigType_scope_name(current_scope);
- if (Len(q)) {
- Append(q, "::");
- }
- Append(q, aliasname);
- Setattr(scopes, q, ttab);
- flush_cache();
- }
- /* -----------------------------------------------------------------------------
- * SwigType_using_scope()
- *
- * Import another scope into this scope.
- * ----------------------------------------------------------------------------- */
- void SwigType_using_scope(Typetab *scope) {
- SwigType_inherit_scope(scope);
- {
- List *ulist;
- int i, len;
- ulist = Getattr(current_scope, "using");
- if (!ulist) {
- ulist = NewList();
- Setattr(current_scope, "using", ulist);
- Delete(ulist);
- }
- assert(scope != current_scope);
- len = Len(ulist);
- for (i = 0; i < len; i++) {
- Typetab *n = Getitem(ulist, i);
- if (n == scope)
- return;
- }
- Append(ulist, scope);
- }
- flush_cache();
- }
- /* -----------------------------------------------------------------------------
- * SwigType_pop_scope()
- *
- * Pop off the last scope and perform a merge operation. Returns the hash
- * table for the scope that was popped off.
- * ----------------------------------------------------------------------------- */
- Typetab *SwigType_pop_scope() {
- Typetab *t, *old = current_scope;
- t = Getattr(current_scope, "parent");
- if (!t)
- t = global_scope;
- current_scope = t;
- current_typetab = Getattr(t, "typetab");
- current_symtab = Getattr(t, "symtab");
- flush_cache();
- return old;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_set_scope()
- *
- * Set the scope. Returns the old scope.
- * ----------------------------------------------------------------------------- */
- Typetab *SwigType_set_scope(Typetab *t) {
- Typetab *old = current_scope;
- if (!t)
- t = global_scope;
- current_scope = t;
- current_typetab = Getattr(t, "typetab");
- current_symtab = Getattr(t, "symtab");
- flush_cache();
- return old;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_attach_symtab()
- *
- * Attaches a symbol table to a type scope
- * ----------------------------------------------------------------------------- */
- void SwigType_attach_symtab(Symtab *sym) {
- Setattr(current_scope, "symtab", sym);
- current_symtab = sym;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_print_scope()
- *
- * Debugging function for printing out current scope
- * ----------------------------------------------------------------------------- */
- void SwigType_print_scope(Typetab *t) {
- Hash *ttab;
- Iterator i, j;
- for (i = First(scopes); i.key; i = Next(i)) {
- t = i.item;
- ttab = Getattr(i.item, "typetab");
- Printf(stdout, "Type scope '%s' (%x)\n", i.key, i.item);
- {
- List *inherit = Getattr(i.item, "inherit");
- if (inherit) {
- Iterator j;
- for (j = First(inherit); j.item; j = Next(j)) {
- Printf(stdout, " Inherits from '%s' (%x)\n", Getattr(j.item, "qname"), j.item);
- }
- }
- }
- Printf(stdout, "-------------------------------------------------------------\n");
- for (j = First(ttab); j.key; j = Next(j)) {
- Printf(stdout, "%40s -> %s\n", j.key, j.item);
- }
- }
- }
- static Typetab *SwigType_find_scope(Typetab *s, String *nameprefix) {
- Typetab *ss;
- String *nnameprefix = 0;
- static int check_parent = 1;
- /* Printf(stdout,"find_scope: %x(%s) '%s'\n", s, Getattr(s,"name"), nameprefix); */
- if (SwigType_istemplate(nameprefix)) {
- nnameprefix = SwigType_typedef_resolve_all(nameprefix);
- nameprefix = nnameprefix;
- }
- ss = s;
- while (ss) {
- String *full;
- String *qname = Getattr(ss, "qname");
- if (qname) {
- full = NewStringf("%s::%s", qname, nameprefix);
- } else {
- full = NewString(nameprefix);
- }
- if (Getattr(scopes, full)) {
- s = Getattr(scopes, full);
- } else {
- s = 0;
- }
- Delete(full);
- if (s) {
- if (nnameprefix)
- Delete(nnameprefix);
- return s;
- }
- if (!s) {
- /* Check inheritance */
- List *inherit;
- inherit = Getattr(ss, "using");
- if (inherit) {
- Typetab *ttab;
- int i, len;
- len = Len(inherit);
- for (i = 0; i < len; i++) {
- int oldcp = check_parent;
- ttab = Getitem(inherit, i);
- check_parent = 0;
- s = SwigType_find_scope(ttab, nameprefix);
- check_parent = oldcp;
- if (s) {
- if (nnameprefix)
- Delete(nnameprefix);
- return s;
- }
- }
- }
- }
- if (!check_parent)
- break;
- ss = Getattr(ss, "parent");
- }
- if (nnameprefix)
- Delete(nnameprefix);
- return 0;
- }
- /* -----------------------------------------------------------------------------
- * typedef_resolve()
- *
- * Resolves a typedef and returns a new type string. Returns 0 if there is no
- * typedef mapping. base is a name without qualification.
- * Internal function.
- * ----------------------------------------------------------------------------- */
- static Typetab *resolved_scope = 0;
- /* Internal function */
- static SwigType *_typedef_resolve(Typetab *s, String *base, int look_parent) {
- Hash *ttab;
- SwigType *type = 0;
- List *inherit;
- Typetab *parent;
- /* if (!s) return 0; *//* now is checked bellow */
- /* Printf(stdout,"Typetab %s : %s\n", Getattr(s,"name"), base); */
- if (!Getmark(s)) {
- Setmark(s, 1);
- ttab = Getattr(s, "typetab");
- type = Getattr(ttab, base);
- if (type) {
- resolved_scope = s;
- Setmark(s, 0);
- } else {
- /* Hmmm. Not found in my scope. It could be in an inherited scope */
- inherit = Getattr(s, "inherit");
- if (inherit) {
- int i, len;
- len = Len(inherit);
- for (i = 0; i < len; i++) {
- type = _typedef_resolve(Getitem(inherit, i), base, 0);
- if (type) {
- Setmark(s, 0);
- break;
- }
- }
- }
- if (!type) {
- /* Hmmm. Not found in my scope. check parent */
- if (look_parent) {
- parent = Getattr(s, "parent");
- type = parent ? _typedef_resolve(parent, base, 1) : 0;
- }
- }
- Setmark(s, 0);
- }
- }
- return type;
- }
- static SwigType *typedef_resolve(Typetab *s, String *base) {
- return _typedef_resolve(s, base, 1);
- }
- /* -----------------------------------------------------------------------------
- * SwigType_typedef_resolve()
- * ----------------------------------------------------------------------------- */
- /* #define SWIG_DEBUG */
- SwigType *SwigType_typedef_resolve(const SwigType *t) {
- String *base;
- String *type = 0;
- String *r = 0;
- Typetab *s;
- Hash *ttab;
- String *namebase = 0;
- String *nameprefix = 0;
- int newtype = 0;
- /*
- if (!noscope) {
- noscope = NewStringEmpty();
- }
- */
- resolved_scope = 0;
- #ifdef SWIG_TYPEDEF_RESOLVE_CACHE
- if (!typedef_resolve_cache) {
- typedef_resolve_cache = NewHash();
- }
- r = Getattr(typedef_resolve_cache, t);
- if (r) {
- resolved_scope = Getmeta(r, "scope");
- return Copy(r);
- }
- #endif
- base = SwigType_base(t);
- #ifdef SWIG_DEBUG
- Printf(stdout, "base = '%s' t='%s'\n", base, t);
- #endif
- if (SwigType_issimple(base)) {
- s = current_scope;
- ttab = current_typetab;
- if (strncmp(Char(base), "::", 2) == 0) {
- s = global_scope;
- ttab = Getattr(s, "typetab");
- Delitem(base, 0);
- Delitem(base, 0);
- }
- /* Do a quick check in the local scope */
- type = Getattr(ttab, base);
- if (type) {
- resolved_scope = s;
- }
- if (!type) {
- /* Didn't find in this scope. We need to do a little more searching */
- if (Swig_scopename_check(base)) {
- /* A qualified name. */
- Swig_scopename_split(base, &nameprefix, &namebase);
- #ifdef SWIG_DEBUG
- Printf(stdout, "nameprefix = '%s'\n", nameprefix);
- #endif
- if (nameprefix) {
- /* Name had a prefix on it. See if we can locate the proper scope for it */
- s = SwigType_find_scope(s, nameprefix);
- /* Couldn't locate a scope for the type. */
- if (!s) {
- Delete(base);
- Delete(namebase);
- Delete(nameprefix);
- r = 0;
- goto return_result;
- }
- /* Try to locate the name starting in the scope */
- #ifdef SWIG_DEBUG
- Printf(stdout, "namebase = '%s'\n", namebase);
- #endif
- type = typedef_resolve(s, namebase);
- if (type) {
- /* we need to look for the resolved type, this will also
- fix the resolved_scope if 'type' and 'namebase' are
- declared in different scopes */
- String *rtype = 0;
- rtype = typedef_resolve(resolved_scope, type);
- if (rtype)
- type = rtype;
- }
- #ifdef SWIG_DEBUG
- Printf(stdout, "%s type = '%s'\n", Getattr(s, "name"), type);
- #endif
- if ((type) && (!Swig_scopename_check(type)) && resolved_scope) {
- Typetab *rtab = resolved_scope;
- String *qname = Getattr(resolved_scope, "qname");
- /* If qualified *and* the typename is defined from the resolved scope, we qualify */
- if ((qname) && typedef_resolve(resolved_scope, type)) {
- type = Copy(type);
- Insert(type, 0, "::");
- Insert(type, 0, qname);
- #ifdef SWIG_DEBUG
- Printf(stdout, "qual %s \n", type);
- #endif
- newtype = 1;
- }
- resolved_scope = rtab;
- }
- } else {
- /* Name is unqualified. */
- type = typedef_resolve(s, base);
- }
- } else {
- /* Name is unqualified. */
- type = typedef_resolve(s, base);
- }
- }
- if (type && (Equal(base, type))) {
- if (newtype)
- Delete(type);
- Delete(base);
- Delete(namebase);
- Delete(nameprefix);
- r = 0;
- goto return_result;
- }
- /* If the type is a template, and no typedef was found, we need to check the
- template arguments one by one to see if they can be resolved. */
- if (!type && SwigType_istemplate(base)) {
- List *tparms;
- String *suffix;
- int i, sz;
- int rep = 0;
- type = SwigType_templateprefix(base);
- newtype = 1;
- suffix = SwigType_templatesuffix(base);
- Append(type, "<(");
- tparms = SwigType_parmlist(base);
- sz = Len(tparms);
- for (i = 0; i < sz; i++) {
- SwigType *tpr;
- SwigType *tp = Getitem(tparms, i);
- if (!rep) {
- tpr = SwigType_typedef_resolve(tp);
- } else {
- tpr = 0;
- }
- if (tpr) {
- Append(type, tpr);
- Delete(tpr);
- rep = 1;
- } else {
- Append(type, tp);
- }
- if ((i + 1) < sz)
- Append(type, ",");
- }
- Append(type, ")>");
- Append(type, suffix);
- Delete(suffix);
- Delete(tparms);
- if (!rep) {
- Delete(type);
- type = 0;
- }
- }
- if (namebase)
- Delete(namebase);
- if (nameprefix)
- Delete(nameprefix);
- } else {
- if (SwigType_isfunction(base)) {
- List *parms;
- int i, sz;
- int rep = 0;
- type = NewString("f(");
- newtype = 1;
- parms = SwigType_parmlist(base);
- sz = Len(parms);
- for (i = 0; i < sz; i++) {
- SwigType *tpr;
- SwigType *tp = Getitem(parms, i);
- if (!rep) {
- tpr = SwigType_typedef_resolve(tp);
- } else {
- tpr = 0;
- }
- if (tpr) {
- Append(type, tpr);
- Delete(tpr);
- rep = 1;
- } else {
- Append(type, tp);
- }
- if ((i + 1) < sz)
- Append(type, ",");
- }
- Append(type, ").");
- Delete(parms);
- if (!rep) {
- Delete(type);
- type = 0;
- }
- } else if (SwigType_ismemberpointer(base)) {
- String *rt;
- String *mtype = SwigType_parm(base);
- rt = SwigType_typedef_resolve(mtype);
- if (rt) {
- type = NewStringf("m(%s).", rt);
- newtype = 1;
- Delete(rt);
- }
- Delete(mtype);
- } else {
- type = 0;
- }
- }
- r = SwigType_prefix(t);
- if (!type) {
- if (r && Len(r)) {
- char *cr = Char(r);
- if ((strstr(cr, "f(") || (strstr(cr, "m(")))) {
- SwigType *rt = SwigType_typedef_resolve(r);
- if (rt) {
- Delete(r);
- Append(rt, base);
- Delete(base);
- r = rt;
- goto return_result;
- }
- }
- }
- Delete(r);
- Delete(base);
- r = 0;
- goto return_result;
- }
- Delete(base);
- Append(r, type);
- if (newtype) {
- Delete(type);
- }
- return_result:
- #ifdef SWIG_TYPEDEF_RESOLVE_CACHE
- {
- String *key = NewString(t);
- if (r) {
- SwigType *r1;
- Setattr(typedef_resolve_cache, key, r);
- Setmeta(r, "scope", resolved_scope);
- r1 = Copy(r);
- Delete(r);
- r = r1;
- }
- Delete(key);
- }
- #endif
- return r;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_typedef_resolve_all()
- *
- * Fully resolve a type down to its most basic datatype
- * ----------------------------------------------------------------------------- */
- SwigType *SwigType_typedef_resolve_all(SwigType *t) {
- SwigType *n;
- SwigType *r;
- /* Check to see if the typedef resolve has been done before by checking the cache */
- if (!typedef_all_cache) {
- typedef_all_cache = NewHash();
- }
- r = Getattr(typedef_all_cache, t);
- if (r) {
- return Copy(r);
- }
- /* Recursively resolve the typedef */
- r = NewString(t);
- while ((n = SwigType_typedef_resolve(r))) {
- Delete(r);
- r = n;
- }
- /* Add the typedef to the cache for next time it is looked up */
- {
- String *key;
- SwigType *rr = Copy(r);
- key = NewString(t);
- Setattr(typedef_all_cache, key, rr);
- Delete(key);
- Delete(rr);
- }
- return r;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_typedef_qualified()
- *
- * Given a type declaration, this function tries to fully qualify it according to
- * typedef scope rules.
- * If the unary scope operator (::) is used as a prefix to the type to denote global
- * scope, it is left in place.
- * ----------------------------------------------------------------------------- */
- SwigType *SwigType_typedef_qualified(SwigType *t) {
- List *elements;
- String *result;
- int i, len;
- if (!typedef_qualified_cache)
- typedef_qualified_cache = NewHash();
- result = Getattr(typedef_qualified_cache, t);
- if (result) {
- String *rc = Copy(result);
- return rc;
- }
- result = NewStringEmpty();
- elements = SwigType_split(t);
- len = Len(elements);
- for (i = 0; i < len; i++) {
- String *ty = 0;
- String *e = Getitem(elements, i);
- if (SwigType_issimple(e)) {
- if (!SwigType_istemplate(e)) {
- String *isenum = 0;
- if (SwigType_isenum(e)) {
- isenum = NewString("enum ");
- ty = NewString(Char(e) + 5);
- e = ty;
- }
- resolved_scope = 0;
- if (typedef_resolve(current_scope, e)) {
- /* resolved_scope contains the scope that actually resolved the symbol */
- String *qname = Getattr(resolved_scope, "qname");
- if (qname) {
- Insert(e, 0, "::");
- Insert(e, 0, qname);
- }
- } else {
- if (Swig_scopename_check(e)) {
- String *qlast;
- String *qname;
- Swig_scopename_split(e, &qname, &qlast);
- if (qname) {
- String *tqname = SwigType_typedef_qualified(qname);
- Clear(e);
- Printf(e, "%s::%s", tqname, qlast);
- Delete(qname);
- Delete(tqname);
- }
- Delete(qlast);
- /* Automatic template instantiation might go here??? */
- } else {
- /* It's a bare name. It's entirely possible, that the
- name is part of a namespace. We'll check this by unrolling
- out of the current scope */
- Typetab *cs = current_scope;
- while (cs) {
- String *qs = SwigType_scope_name(cs);
- if (Len(qs)) {
- Append(qs, "::");
- }
- Append(qs, e);
- if (Getattr(scopes, qs)) {
- Clear(e);
- Append(e, qs);
- Delete(qs);
- break;
- }
- Delete(qs);
- cs = Getattr(cs, "parent");
- }
- }
- }
- if (isenum) {
- Insert(e, 0, isenum);
- Delete(isenum);
- }
- } else {
- /* Template. We need to qualify template parameters as well as the template itself */
- String *tprefix, *qprefix;
- String *tsuffix;
- Iterator pi;
- Parm *p;
- List *parms;
- ty = Swig_symbol_template_deftype(e, current_symtab);
- e = ty;
- parms = SwigType_parmlist(e);
- tprefix = SwigType_templateprefix(e);
- tsuffix = SwigType_templatesuffix(e);
- qprefix = SwigType_typedef_qualified(tprefix);
- Append(qprefix, "<(");
- pi = First(parms);
- while ((p = pi.item)) {
- String *qt = SwigType_typedef_qualified(p);
- if (Equal(qt, p)) { /* && (!Swig_scopename_check(qt))) */
- /* No change in value. It is entirely possible that the parameter is an integer value.
- If there is a symbol table associated with this scope, we're going to check for this */
- if (current_symtab) {
- Node *lastnode = 0;
- String *value = Copy(p);
- while (1) {
- Node *n = Swig_symbol_clookup(value, current_symtab);
- if (n == lastnode)
- break;
- lastnode = n;
- if (n) {
- char *ntype = Char(nodeType(n));
- if (strcmp(ntype, "enumitem") == 0) {
- /* An enum item. Generate a fully qualified name */
- String *qn = Swig_symbol_qualified(n);
- if (Len(qn)) {
- Append(qn, "::");
- Append(qn, Getattr(n, "name"));
- Delete(value);
- value = qn;
- continue;
- } else {
- Delete(qn);
- break;
- }
- } else if ((strcmp(ntype, "cdecl") == 0) && (Getattr(n, "value"))) {
- Delete(value);
- value = Copy(Getattr(n, "value"));
- continue;
- }
- }
- break;
- }
- Append(qprefix, value);
- Delete(value);
- } else {
- Append(qprefix, p);
- }
- } else {
- Append(qprefix, qt);
- }
- Delete(qt);
- pi = Next(pi);
- if (pi.item) {
- Append(qprefix, ",");
- }
- }
- Append(qprefix, ")>");
- Append(qprefix, tsuffix);
- Delete(tsuffix);
- Clear(e);
- Append(e, qprefix);
- Delete(tprefix);
- Delete(qprefix);
- Delete(parms);
- }
- Append(result, e);
- Delete(ty);
- } else if (SwigType_isfunction(e)) {
- List *parms = SwigType_parmlist(e);
- String *s = NewString("f(");
- Iterator pi;
- pi = First(parms);
- while (pi.item) {
- String *pq = SwigType_typedef_qualified(pi.item);
- Append(s, pq);
- Delete(pq);
- pi = Next(pi);
- if (pi.item) {
- Append(s, ",");
- }
- }
- Append(s, ").");
- Append(result, s);
- Delete(s);
- Delete(parms);
- } else if (SwigType_isarray(e)) {
- String *ndim;
- String *dim = SwigType_parm(e);
- ndim = Swig_symbol_string_qualify(dim, 0);
- Printf(result, "a(%s).", ndim);
- Delete(dim);
- Delete(ndim);
- } else {
- Append(result, e);
- }
- }
- Delete(elements);
- {
- String *key, *cresult;
- key = NewString(t);
- cresult = NewString(result);
- Setattr(typedef_qualified_cache, key, cresult);
- Delete(key);
- Delete(cresult);
- }
- return result;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_istypedef()
- *
- * Checks a typename to see if it is a typedef.
- * ----------------------------------------------------------------------------- */
- int SwigType_istypedef(SwigType *t) {
- String *type;
- type = SwigType_typedef_resolve(t);
- if (type) {
- Delete(type);
- return 1;
- } else {
- return 0;
- }
- }
- /* -----------------------------------------------------------------------------
- * SwigType_typedef_using()
- *
- * Processes a 'using' declaration to import types from one scope into another.
- * Name is a qualified name like A::B.
- * ----------------------------------------------------------------------------- */
- int SwigType_typedef_using(const_String_or_char_ptr name) {
- String *base;
- String *td;
- String *prefix;
- Typetab *s;
- Typetab *tt = 0;
- String *defined_name = 0;
- /* Printf(stdout,"using %s\n", name); */
- if (!Swig_scopename_check(name))
- return -1; /* Not properly qualified */
- base = Swig_scopename_last(name);
- /* See if the base is already defined in this scope */
- if (Getattr(current_typetab, base)) {
- Delete(base);
- return -1;
- }
- /* See if the using name is a scope */
- /* tt = SwigType_find_scope(current_scope,name);
- Printf(stdout,"tt = %x, name = '%s'\n", tt, name); */
- /* We set up a typedef B --> A::B */
- Setattr(current_typetab, base, name);
- /* Find the scope name where the symbol is defined */
- td = SwigType_typedef_resolve(name);
- /* Printf(stdout,"td = '%s' %x\n", td, resolved_scope); */
- if (resolved_scope) {
- defined_name = Getattr(resolved_scope, "qname");
- if (defined_name) {
- defined_name = Copy(defined_name);
- Append(defined_name, "::");
- Append(defined_name, base);
- /* Printf(stdout,"defined_name = '%s'\n", defined_name); */
- tt = SwigType_find_scope(current_scope, defined_name);
- }
- }
- if (td)
- Delete(td);
- /* Figure out the scope the using directive refers to */
- {
- prefix = Swig_scopename_prefix(name);
- if (prefix) {
- s = SwigType_find_scope(current_scope, prefix);
- if (s) {
- Hash *ttab = Getattr(s, "typetab");
- if (!Getattr(ttab, base) && defined_name) {
- Setattr(ttab, base, defined_name);
- }
- }
- }
- }
- if (tt) {
- /* Using directive had its own scope. We need to create a new scope for it */
- SwigType_new_scope(base);
- SwigType_inherit_scope(tt);
- SwigType_pop_scope();
- }
- if (defined_name)
- Delete(defined_name);
- Delete(prefix);
- Delete(base);
- return 0;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_isclass()
- *
- * Determines if a type defines a class or not. A class is defined by
- * its type-table entry maps to itself. Note: a pointer to a class is not
- * a class.
- * ----------------------------------------------------------------------------- */
- int SwigType_isclass(SwigType *t) {
- SwigType *qty, *qtys;
- int isclass = 0;
- qty = SwigType_typedef_resolve_all(t);
- qtys = SwigType_strip_qualifiers(qty);
- if (SwigType_issimple(qtys)) {
- String *td = SwigType_typedef_resolve(qtys);
- if (td) {
- Delete(td);
- }
- if (resolved_scope) {
- isclass = 1;
- }
- /* Hmmm. Not a class. If a template, it might be uninstantiated */
- if (!isclass) {
- String *tp = SwigType_istemplate_templateprefix(qtys);
- if (tp && Strcmp(tp, t) != 0) {
- isclass = SwigType_isclass(tp);
- }
- Delete(tp);
- }
- }
- Delete(qty);
- Delete(qtys);
- return isclass;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_type()
- *
- * Returns an integer code describing the datatype. This is only used for
- * compatibility with SWIG1.1 language modules and is likely to go away once
- * everything is based on typemaps.
- * ----------------------------------------------------------------------------- */
- int SwigType_type(SwigType *t) {
- char *c;
- /* Check for the obvious stuff */
- c = Char(t);
- if (strncmp(c, "p.", 2) == 0) {
- if (SwigType_type(c + 2) == T_CHAR)
- return T_STRING;
- else
- return T_POINTER;
- }
- if (strncmp(c, "a(", 2) == 0)
- return T_ARRAY;
- if (strncmp(c, "r.", 2) == 0)
- return T_REFERENCE;
- if (strncmp(c, "m(", 2) == 0)
- return T_MPOINTER;
- if (strncmp(c, "q(", 2) == 0) {
- while (*c && (*c != '.'))
- c++;
- if (*c)
- return SwigType_type(c + 1);
- return T_ERROR;
- }
- if (strncmp(c, "f(", 2) == 0)
- return T_FUNCTION;
- /* Look for basic types */
- if (strcmp(c, "int") == 0)
- return T_INT;
- if (strcmp(c, "long") == 0)
- return T_LONG;
- if (strcmp(c, "short") == 0)
- return T_SHORT;
- if (strcmp(c, "unsigned") == 0)
- return T_UINT;
- if (strcmp(c, "unsigned short") == 0)
- return T_USHORT;
- if (strcmp(c, "unsigned long") == 0)
- return T_ULONG;
- if (strcmp(c, "unsigned int") == 0)
- return T_UINT;
- if (strcmp(c, "char") == 0)
- return T_CHAR;
- if (strcmp(c, "signed char") == 0)
- return T_SCHAR;
- if (strcmp(c, "unsigned char") == 0)
- return T_UCHAR;
- if (strcmp(c, "float") == 0)
- return T_FLOAT;
- if (strcmp(c, "double") == 0)
- return T_DOUBLE;
- if (strcmp(c, "long double") == 0)
- return T_LONGDOUBLE;
- if (!cparse_cplusplus && (strcmp(c, "float complex") == 0))
- return T_FLTCPLX;
- if (!cparse_cplusplus && (strcmp(c, "double complex") == 0))
- return T_DBLCPLX;
- if (!cparse_cplusplus && (strcmp(c, "complex") == 0))
- return T_COMPLEX;
- if (strcmp(c, "void") == 0)
- return T_VOID;
- if (strcmp(c, "bool") == 0)
- return T_BOOL;
- if (strcmp(c, "long long") == 0)
- return T_LONGLONG;
- if (strcmp(c, "unsigned long long") == 0)
- return T_ULONGLONG;
- if (strncmp(c, "enum ", 5) == 0)
- return T_INT;
- if (strcmp(c, "v(...)") == 0)
- return T_VARARGS;
- /* Hmmm. Unknown type */
- if (SwigType_istypedef(t)) {
- int r;
- SwigType *nt = SwigType_typedef_resolve(t);
- r = SwigType_type(nt);
- Delete(nt);
- return r;
- }
- return T_USER;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_alttype()
- *
- * Returns the alternative value type needed in C++ for class value
- * types. When swig is not sure about using a plain $ltype value,
- * since the class doesn't have a default constructor, or it can't be
- * assigned, you will get back 'SwigValueWrapper<type >'.
- *
- * This is the default behavior unless:
- *
- * 1.- swig detects a default_constructor and 'setallocate:default_constructor'
- * attribute.
- *
- * 2.- swig doesn't mark 'type' as non-assignable.
- *
- * 3.- the user specify that the value wrapper is not needed by using
- * the %feature("novaluewrapper"), in that case the user need to type
- *
- * %feature("novaluewrapper") MyOpaqueClass;
- * class MyOpaqueClass;
- *
- * Users can also force the use of the value wrapper by using the
- * %feature("valuewrapper").
- * ----------------------------------------------------------------------------- */
- SwigType *SwigType_alttype(SwigType *t, int local_tmap) {
- Node *n;
- SwigType *w = 0;
- int use_wrapper = 0;
- SwigType *td = 0;
- if (!cparse_cplusplus)
- return 0;
- if (value_wrapper_mode == 0) {
- /* old partial use of SwigValueTypes, it can fail for opaque types */
- if (local_tmap)
- return 0;
- if (SwigType_isclass(t)) {
- SwigType *ftd = SwigType_typedef_resolve_all(t);
- td = SwigType_strip_qualifiers(ftd);
- Delete(ftd);
- n = Swig_symbol_clookup(td, 0);
- if (n) {
- if (GetFlag(n, "feature:valuewrapper")) {
- use_wrapper = 1;
- } else {
- if (Checkattr(n, "nodeType", "class")
- && (!Getattr(n, "allocate:default_constructor")
- || (Getattr(n, "allocate:noassign")))) {
- use_wrapper = !GetFlag(n, "feature:novaluewrapper") || GetFlag(n, "feature:nodefault");
- }
- }
- } else {
- if (SwigType_issimple(td) && SwigType_istemplate(td)) {
- use_wrapper = !n || !GetFlag(n, "feature:novaluewrapper");
- }
- }
- }
- } else {
- /* safe use of SwigValueTypes, it can fail with some typemaps */
- SwigType *ftd = SwigType_typedef_resolve_all(t);
- td = SwigType_strip_qualifiers(ftd);
- Delete(ftd);
- if (SwigType_type(td) == T_USER) {
- use_wrapper = 1;
- n = Swig_symbol_clookup(td, 0);
- if (n) {
- if ((Checkattr(n, "nodeType", "class")
- && !Getattr(n, "allocate:noassign")
- && (Getattr(n, "allocate:default_constructor")))
- || (GetFlag(n, "feature:novaluewrapper"))) {
- use_wrapper = GetFlag(n, "feature:valuewrapper");
- }
- }
- }
- }
- if (use_wrapper) {
- /* Need a space before the type in case it starts "::" (since the <:
- * token is a digraph for [ in C++. Also need a space after the
- * type in case it ends with ">" since then we form the token ">>".
- */
- w = NewStringf("SwigValueWrapper< %s >", td);
- }
- Delete(td);
- return w;
- }
- /* ----------------------------------------------------------------------------
- * * * * WARNING * * * ***
- * ***
- * Don't even think about modifying anything below this line unless you ***
- * are completely on top of *EVERY* subtle aspect of the C++ type system ***
- * and you are prepared to suffer endless hours of agony trying to ***
- * debug the SWIG run-time type checker after you break it. ***
- * ------------------------------------------------------------------------- */
- /* -----------------------------------------------------------------------------
- * SwigType_remember()
- *
- * This function "remembers" a datatype that was used during wrapper code generation
- * so that a type-checking table can be generated later on. It is up to the language
- * modules to actually call this function--it is not done automatically.
- *
- * Type tracking is managed through two separate hash tables. The hash 'r_mangled'
- * is mapping between mangled type names (used in the target language) and
- * fully-resolved C datatypes used in the source input. The second hash 'r_resolved'
- * is the inverse mapping that maps fully-resolved C datatypes to all of the mangled
- * names in the scripting languages. For example, consider the following set of
- * typedef declarations:
- *
- * typedef double Real;
- * typedef double Float;
- * typedef double Point[3];
- *
- * Now, suppose that the types 'double *', 'Real *', 'Float *', 'double[3]', and
- * 'Point' were used in an interface file and "remembered" using this function.
- * The hash tables would look like this:
- *
- * r_mangled {
- * _p_double : [ p.double, a(3).double ]
- * _p_Real : [ p.double ]
- * _p_Float : [ p.double ]
- * _Point : [ a(3).double ]
- *
- * r_resolved {
- * p.double : [ _p_double, _p_Real, _p_Float ]
- * a(3).double : [ _p_double, _Point ]
- * }
- *
- * Together these two hash tables can be used to determine type-equivalency between
- * mangled typenames. To do this, we view the two hash tables as a large graph and
- * compute the transitive closure.
- * ----------------------------------------------------------------------------- */
- static Hash *r_mangled = 0; /* Hash mapping mangled types to fully resolved types */
- static Hash *r_resolved = 0; /* Hash mapping resolved types to mangled types */
- static Hash *r_ltype = 0; /* Hash mapping mangled names to their local c type */
- static Hash *r_clientdata = 0; /* Hash mapping resolved types to client data */
- static Hash *r_mangleddata = 0; /* Hash mapping mangled types to client data */
- static Hash *r_remembered = 0; /* Hash of types we remembered already */
- static void (*r_tracefunc) (SwigType *t, String *mangled, String *clientdata) = 0;
- void SwigType_remember_mangleddata(String *mangled, const_String_or_char_ptr clientdata) {
- if (!r_mangleddata) {
- r_mangleddata = NewHash();
- }
- Setattr(r_mangleddata, mangled, clientdata);
- }
- void SwigType_remember_clientdata(SwigType *t, const_String_or_char_ptr clientdata) {
- String *mt;
- SwigType *lt;
- Hash *h;
- SwigType *fr;
- SwigType *qr;
- String *tkey;
- String *cd;
- Hash *lthash;
- if (!r_mangled) {
- r_mangled = NewHash();
- r_resolved = NewHash();
- r_ltype = NewHash();
- r_clientdata = NewHash();
- r_remembered = NewHash();
- }
- {
- String *last;
- last = Getattr(r_remembered, t);
- if (last && (Cmp(last, clientdata) == 0))
- return;
- }
- tkey = Copy(t);
- cd = clientdata ? NewString(clientdata) : NewStringEmpty();
- Setattr(r_remembered, tkey, cd);
- Delete(tkey);
- Delete(cd);
- mt = SwigType_manglestr(t); /* Create mangled string */
- if (r_tracefunc) {
- (*r_tracefunc) (t, mt, (String *) clientdata);
- }
- if (SwigType_istypedef(t)) {
- lt = Copy(t);
- } else {
- lt = SwigType_ltype(t);
- }
- lthash = Getattr(r_ltype, mt);
- if (!lthash) {
- lthash = NewHash();
- Setattr(r_ltype, mt, lthash);
- }
- Setattr(lthash, lt, "1");
- Delete(lt);
- fr = SwigType_typedef_resolve_all(t); /* Create fully resolved type */
- qr = SwigType_typedef_qualified(fr);
- Delete(fr);
- /* Added to deal with possible table bug */
- fr = SwigType_strip_qualifiers(qr);
- Delete(qr);
- /*Printf(stdout,"t = '%s'\n", t);
- Printf(stdout,"fr= '%s'\n\n", fr); */
- if (t) {
- char *ct = Char(t);
- if (strchr(ct, '<') && !(strstr(ct, "<("))) {
- Printf(stdout, "Bad template type passed to SwigType_remember: %s\n", t);
- assert(0);
- }
- }
- h = Getattr(r_mangled, mt);
- if (!h) {
- h = NewHash();
- Setattr(r_mangled, mt, h);
- Delete(h);
- }
- Setattr(h, fr, mt);
- h = Getattr(r_resolved, fr);
- if (!h) {
- h = NewHash();
- Setattr(r_resolved, fr, h);
- Delete(h);
- }
- Setattr(h, mt, fr);
- if (clientdata) {
- String *cd = Getattr(r_clientdata, fr);
- if (cd) {
- if (Strcmp(clientdata, cd) != 0) {
- Printf(stderr, "*** Internal error. Inconsistent clientdata for type '%s'\n", SwigType_str(fr, 0));
- Printf(stderr, "*** '%s' != '%s'\n", clientdata, cd);
- assert(0);
- }
- } else {
- String *cstr = NewString(clientdata);
- Setattr(r_clientdata, fr, cstr);
- Delete(cstr);
- }
- }
- /* If the remembered type is a reference, we also remember the pointer version.
- This is to prevent odd problems with mixing pointers and references--especially
- when different functions are using different typenames (via typedef). */
- if (SwigType_isreference(t)) {
- SwigType *tt = Copy(t);
- SwigType_del_reference(tt);
- SwigType_add_pointer(tt);
- SwigType_remember_clientdata(tt, clientdata);
- }
- }
- void SwigType_remember(SwigType *ty) {
- SwigType_remember_clientdata(ty, 0);
- }
- void (*SwigType_remember_trace(void (*tf) (SwigType *, String *, String *))) (SwigType *, String *, String *) {
- void (*o) (SwigType *, String *, String *) = r_tracefunc;
- r_tracefunc = tf;
- return o;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_equivalent_mangle()
- *
- * Return a list of all of the mangled typenames that are equivalent to another
- * mangled name. This works as follows: For each fully qualified C datatype
- * in the r_mangled hash entry, we collect all of the mangled names from the
- * r_resolved hash and combine them together in a list (removing duplicate entries).
- * ----------------------------------------------------------------------------- */
- List *SwigType_equivalent_mangle(String *ms, Hash *checked, Hash *found) {
- List *l;
- Hash *h;
- Hash *ch;
- Hash *mh;
- if (found) {
- h = found;
- } else {
- h = NewHash();
- }
- if (checked) {
- ch = checked;
- } else {
- ch = NewHash();
- }
- if (Getattr(ch, ms))
- goto check_exit; /* Already checked this type */
- Setattr(h, ms, "1");
- Setattr(ch, ms, "1");
- mh = Getattr(r_mangled, ms);
- if (mh) {
- Iterator ki;
- ki = First(mh);
- while (ki.key) {
- Hash *rh;
- if (Getattr(ch, ki.key)) {
- ki = Next(ki);
- continue;
- }
- Setattr(ch, ki.key, "1");
- rh = Getattr(r_resolved, ki.key);
- if (rh) {
- Iterator rk;
- rk = First(rh);
- while (rk.key) {
- Setattr(h, rk.key, "1");
- SwigType_equivalent_mangle(rk.key, ch, h);
- rk = Next(rk);
- }
- }
- ki = Next(ki);
- }
- }
- check_exit:
- if (!found) {
- l = Keys(h);
- Delete(h);
- Delete(ch);
- return l;
- } else {
- return 0;
- }
- }
- /* -----------------------------------------------------------------------------
- * SwigType_clientdata_collect()
- *
- * Returns the clientdata field for a mangled type-string.
- * ----------------------------------------------------------------------------- */
- static
- String *SwigType_clientdata_collect(String *ms) {
- Hash *mh;
- String *clientdata = 0;
- if (r_mangleddata) {
- clientdata = Getattr(r_mangleddata, ms);
- if (clientdata)
- return clientdata;
- }
- mh = Getattr(r_mangled, ms);
- if (mh) {
- Iterator ki;
- ki = First(mh);
- while (ki.key) {
- clientdata = Getattr(r_clientdata, ki.key);
- if (clientdata)
- break;
- ki = Next(ki);
- }
- }
- return clientdata;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_inherit()
- *
- * Record information about inheritance. We keep a hash table that keeps
- * a mapping between base classes and all of the classes that are derived
- * from them.
- *
- * subclass is a hash that maps base-classes to all of the classes derived from them.
- *
- * derived - name of derived class
- * base - name of base class
- * cast - additional casting code when casting from derived to base
- * conversioncode - if set, overrides the default code in the function when casting
- * from derived to base
- * ----------------------------------------------------------------------------- */
- static Hash *subclass = 0;
- static Hash *conversions = 0;
- void SwigType_inherit(String *derived, String *base, String *cast, String *conversioncode) {
- Hash *h;
- String *dd = 0;
- String *bb = 0;
- if (!subclass)
- subclass = NewHash();
- /* Printf(stdout,"'%s' --> '%s' '%s'\n", derived, base, cast); */
- if (SwigType_istemplate(derived)) {
- String *ty = SwigType_typedef_resolve_all(derived);
- dd = SwigType_typedef_qualified(ty);
- derived = dd;
- Delete(ty);
- }
- if (SwigType_istemplate(base)) {
- String *ty = SwigType_typedef_resolve_all(base);
- bb = SwigType_typedef_qualified(ty);
- base = bb;
- Delete(ty);
- }
- /* Printf(stdout,"'%s' --> '%s' '%s'\n", derived, base, cast); */
- h = Getattr(subclass, base);
- if (!h) {
- h = NewHash();
- Setattr(subclass, base, h);
- Delete(h);
- }
- if (!Getattr(h, derived)) {
- Hash *c = NewHash();
- if (cast)
- Setattr(c, "cast", cast);
- if (conversioncode)
- Setattr(c, "convcode", conversioncode);
- Setattr(h, derived, c);
- Delete(c);
- }
- Delete(dd);
- Delete(bb);
- }
- /* -----------------------------------------------------------------------------
- * SwigType_issubtype()
- *
- * Determines if a t1 is a subtype of t2, ie, is t1 derived from t2
- * ----------------------------------------------------------------------------- */
- int SwigType_issubtype(SwigType *t1, SwigType *t2) {
- SwigType *ft1, *ft2;
- String *b1, *b2;
- Hash *h;
- int r = 0;
- if (!subclass)
- return 0;
- ft1 = SwigType_typedef_resolve_all(t1);
- ft2 = SwigType_typedef_resolve_all(t2);
- b1 = SwigType_base(ft1);
- b2 = SwigType_base(ft2);
- h = Getattr(subclass, b2);
- if (h) {
- if (Getattr(h, b1)) {
- r = 1;
- }
- }
- Delete(ft1);
- Delete(ft2);
- Delete(b1);
- Delete(b2);
- /* Printf(stdout, "issubtype(%s,%s) --> %d\n", t1, t2, r); */
- return r;
- }
- /* -----------------------------------------------------------------------------
- * SwigType_inherit_equiv()
- *
- * Modify the type table to handle C++ inheritance
- * ----------------------------------------------------------------------------- */
- void SwigType_inherit_equiv(File *out) {
- String *ckey;
- String *prefix, *base;
- String *mprefix, *mkey;
- Hash *sub;
- Hash *rh;
- List *rlist;
- Iterator rk, bk, ck;
- if (!conversions)
- conversions = NewHash();
- if (!subclass)
- subclass = NewHash();
- rk = First(r_resolved);
- while (rk.key) {
- /* rkey is a fully qualified type. We strip all of the type constructors off of it just to get the base */
- base = SwigType_base(rk.key);
- /* Check to see whether the base is recorded in the subclass table */
- sub = Getattr(subclass, base);
- Delete(base);
- if (!sub) {
- rk = Next(rk);
- continue;
- }
- /* This type has subclasses. We now need to walk through these subtypes and generate pointer conversion functions */
- rh = Getattr(r_resolved, rk.key);
- rlist = NewList();
- for (ck = First(rh); ck.key; ck = Next(ck)) {
- Append(rlist, ck.key);
- }
- /* Printf(stdout,"rk.key = '%s'\n", rk.key);
- Printf(stdout,"rh = %x '%s'\n", rh,rh); */
- bk = First(sub);
- while (bk.key) {
- prefix = SwigType_prefix(rk.key);
- Append(prefix, bk.key);
- /* Printf(stdout,"set %x = '%s' : '%s'\n", rh, SwigType_manglestr(prefix),prefix); */
- mprefix = SwigType_manglestr(prefix);
- Setattr(rh, mprefix, prefix);
- mkey = SwigType_manglestr(rk.key);
- ckey = NewStringf("%s+%s", mprefix, mkey);
- if (!Getattr(conversions, ckey)) {
- String *convname = NewStringf("%sTo%s", mprefix, mkey);
- String *lkey = SwigType_lstr(rk.key, 0);
- String *lprefix = SwigType_lstr(prefix, 0);
- Hash *subhash = Getattr(sub, bk.key);
- String *convcode = Getattr(subhash, "convcode");
- if (convcode) {
- char *newmemoryused = Strstr(convcode, "newmemory"); /* see if newmemory parameter is used in order to avoid unused parameter warnings */
- String *fn = Copy(convcode);
- Replaceall(fn, "$from", "x");
- Printf(out, "static void *%s(void *x, int *%s) {", convname, newmemoryused ? "newmemory" : "SWIGUNUSEDPARM(newmemory)");
- Printf(out, "%s", fn);
- } else {
- String *cast = Getattr(subhash, "cast");
- Printf(out, "static void *%s(void *x, int *SWIGUNUSEDPARM(newmemory)) {", convnam…