aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/swig/Source/Swig/symbol.c
diff options
context:
space:
mode:
authorvitalyisaev <vitalyisaev@ydb.tech>2023-11-30 13:26:22 +0300
committervitalyisaev <vitalyisaev@ydb.tech>2023-11-30 15:44:45 +0300
commit0a98fece5a9b54f16afeb3a94b3eb3105e9c3962 (patch)
tree291d72dbd7e9865399f668c84d11ed86fb190bbf /contrib/tools/swig/Source/Swig/symbol.c
parentcb2c8d75065e5b3c47094067cb4aa407d4813298 (diff)
downloadydb-0a98fece5a9b54f16afeb3a94b3eb3105e9c3962.tar.gz
YQ Connector:Use docker-compose in integrational tests
Diffstat (limited to 'contrib/tools/swig/Source/Swig/symbol.c')
-rw-r--r--contrib/tools/swig/Source/Swig/symbol.c2128
1 files changed, 2128 insertions, 0 deletions
diff --git a/contrib/tools/swig/Source/Swig/symbol.c b/contrib/tools/swig/Source/Swig/symbol.c
new file mode 100644
index 0000000000..107b1caef9
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/symbol.c
@@ -0,0 +1,2128 @@
+/* -----------------------------------------------------------------------------
+ * 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 https://www.swig.org/legal.html.
+ *
+ * symbol.c
+ *
+ * This file implements the SWIG symbol table. See details below.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "cparse.h"
+#include <ctype.h>
+
+/* #define SWIG_DEBUG*/
+/* -----------------------------------------------------------------------------
+ * Synopsis
+ *
+ * This module provides symbol table management for all of SWIG. In previous
+ * releases, the management of symbols was rather haphazard. This module tries
+ * to correct that.
+ *
+ * All symbols are associated with simple identifiers. For example, here are some
+ * declarations that generate symbol table entries:
+ *
+ * decl symbol
+ * -------------- ------------
+ * void foo(int); foo
+ * int x; x
+ * typedef int *blah; blah
+ *
+ * Associated with each symbol is a Hash table that can contain any set of
+ * attributes that make sense for that object. For example:
+ *
+ * typedef int *blah; ----> "name" : 'blah'
+ * "type" : 'int'
+ * "decl" : 'p.'
+ * "storage" : 'typedef'
+ *
+ * In some cases, the symbol table needs to manage overloaded entries. For instance,
+ * overloaded functions. In this case, a linked list is built. The "sym:nextSibling"
+ * attribute is reserved to hold a link to the next entry. For example:
+ *
+ * int foo(int); --> "name" : "foo" "name" : "foo"
+ * int foo(int,double); "type" : "int" "type" : "int"
+ * "decl" : "f(int)." "decl" : "f(int,double)."
+ * ... ...
+ * "sym:nextSibling" : --------> "sym:nextSibling": --------> ...
+ *
+ * When more than one symbol has the same name, the symbol declarator is
+ * used to detect duplicates. For example, in the above case, foo(int) and
+ * foo(int,double) are different because their "decl" attribute is different.
+ * However, if a third declaration "foo(int)" was made, it would generate a
+ * conflict (due to having a declarator that matches a previous entry).
+ *
+ * Structures and classes:
+ *
+ * C/C++ symbol tables are normally managed in a few different spaces. The
+ * most visible namespace is reserved for functions, variables, typedef, enum values
+ * and such. In C, a separate tag-space is reserved for 'struct name', 'class name',
+ * and 'union name' declarations. In SWIG, a single namespace is used for everything
+ * this means that certain incompatibilities will arise with some C programs. For instance:
+ *
+ * struct Foo {
+ * ...
+ * }
+ *
+ * int Foo(); // Error. Name clash. Works in C though
+ *
+ * Due to the unified namespace for structures, special handling is performed for
+ * the following:
+ *
+ * typedef struct Foo {
+ *
+ * } Foo;
+ *
+ * In this case, the symbol table contains an entry for the structure itself. The
+ * typedef is left out of the symbol table.
+ *
+ * Target language vs C:
+ *
+ * The symbol tables are normally managed *in the namespace of the target language*.
+ * This means that name-collisions can be resolved using %rename and related
+ * directives. A quirk of this is that sometimes the symbol tables need to
+ * be used for C type resolution as well. To handle this, each symbol table
+ * also has a C-symbol table lurking behind the scenes. This is used to locate
+ * symbols in the C namespace. However, this symbol table is not used for error
+ * reporting nor is it used for anything else during code generation.
+ *
+ * Symbol table structure:
+ *
+ * Symbol tables themselves are a special kind of node that is organized just like
+ * a normal parse tree node. Symbol tables are organized in a tree that can be
+ * traversed using the SWIG-DOM API. The following attributes names are reserved.
+ *
+ * name -- Name of the scope defined by the symbol table (if any)
+ * This name is the C-scope name and is not affected by
+ * %renaming operations
+ * symtab -- Hash table mapping identifiers to nodes.
+ * csymtab -- Hash table mapping C identifiers to nodes.
+ *
+ * Reserved attributes on symbol objects:
+ *
+ * When a symbol is placed in the symbol table, the following attributes
+ * are set:
+ *
+ * sym:name -- Symbol name
+ * sym:nextSibling -- Next symbol (if overloaded)
+ * sym:previousSibling -- Previous symbol (if overloaded)
+ * sym:symtab -- Symbol table object holding the symbol
+ * sym:overloaded -- Set to the first symbol if overloaded
+ *
+ * These names are modeled after XML namespaces. In particular, every attribute
+ * pertaining to symbol table management is prefaced by the "sym:" prefix.
+ *
+ * An example dump of the parse tree showing symbol table entries for the
+ * following code should clarify this:
+ *
+ * namespace OuterNamespace {
+ * namespace InnerNamespace {
+ * class Class {
+ * };
+ * struct Struct {
+ * int Var;
+ * };
+ * }
+ * }
+ *
+ * +++ namespace ----------------------------------------
+ * | sym:name - "OuterNamespace"
+ * | symtab - 0xa064bf0
+ * | sym:symtab - 0xa041690
+ * | sym:overname - "__SWIG_0"
+ *
+ * +++ namespace ----------------------------------------
+ * | sym:name - "InnerNamespace"
+ * | symtab - 0xa064cc0
+ * | sym:symtab - 0xa064bf0
+ * | sym:overname - "__SWIG_0"
+ *
+ * +++ class ----------------------------------------
+ * | sym:name - "Class"
+ * | symtab - 0xa064d80
+ * | sym:symtab - 0xa064cc0
+ * | sym:overname - "__SWIG_0"
+ * |
+ * +++ class ----------------------------------------
+ * | sym:name - "Struct"
+ * | symtab - 0xa064f00
+ * | sym:symtab - 0xa064cc0
+ * | sym:overname - "__SWIG_0"
+ *
+ * +++ cdecl ----------------------------------------
+ * | sym:name - "Var"
+ * | sym:symtab - 0xa064f00
+ * | sym:overname - "__SWIG_0"
+ * |
+ *
+ *
+ * Each class and namespace has its own scope and thus a new symbol table (sym)
+ * is created. The sym attribute is only set for the first entry in the symbol
+ * table. The sym:symtab entry points to the symbol table in which the symbol
+ * exists, so for example, Struct is in the scope OuterNamespace::InnerNamespace
+ * so sym:symtab points to this symbol table (0xa064cc0).
+ *
+ * ----------------------------------------------------------------------------- */
+
+static Hash *current = 0; /* The current symbol table hash */
+static Hash *ccurrent = 0; /* The current c symbol table hash */
+static Hash *current_symtab = 0; /* Current symbol table node */
+static Hash *symtabs = 0; /* Hash of all symbol tables by fully-qualified name */
+static Hash *global_scope = 0; /* Global scope */
+
+static int use_inherit = 1;
+
+/* common attribute keys, to avoid calling find_key all the times */
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_print_tables()
+ *
+ * Debug display of symbol tables
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_print_tables(Symtab *symtab) {
+ if (!symtab)
+ symtab = current_symtab;
+
+ Printf(stdout, "SYMBOL TABLES start =======================================\n");
+ Swig_print_tree(symtab);
+ Printf(stdout, "SYMBOL TABLES finish =======================================\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_print_tables_summary()
+ *
+ * Debug summary display of all symbol tables by fully-qualified name
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_print_tables_summary(void) {
+ Printf(stdout, "SYMBOL TABLES SUMMARY start =======================================\n");
+ Swig_print_node(symtabs);
+ Printf(stdout, "SYMBOL TABLES SUMMARY finish =======================================\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * symbol_print_symbols()
+ * ----------------------------------------------------------------------------- */
+
+static void symbol_print_symbols(const char *symboltabletype, const char *nextSibling) {
+ Node *table = symtabs;
+ Iterator ki = First(table);
+ int show_pointers = 0;
+ while (ki.key) {
+ String *k = ki.key;
+ Printf(stdout, "===================================================\n");
+ Printf(stdout, "%s -\n", k);
+ {
+ Symtab *symtab = Getattr(Getattr(table, k), symboltabletype);
+ Iterator it = First(symtab);
+ while (it.key) {
+ String *symname = it.key;
+ Printf(stdout, " %s (%s)", symname, nodeType(it.item));
+ if (show_pointers)
+ Printf(stdout, " %p", it.item);
+ Printf(stdout, "\n");
+ {
+ Node *sibling = Getattr(it.item, nextSibling);
+ while (sibling) {
+ Printf(stdout, " %s (%s)", symname, nodeType(sibling));
+ if (show_pointers)
+ Printf(stdout, " %p", sibling);
+ Printf(stdout, "\n");
+ sibling = Getattr(sibling, nextSibling);
+ }
+ }
+ it = Next(it);
+ }
+ }
+ ki = Next(ki);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_print_symbols()
+ *
+ * Debug display of all the target language symbols
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_print_symbols(void) {
+ Printf(stdout, "SYMBOLS start =======================================\n");
+ symbol_print_symbols("symtab", "sym:nextSibling");
+ Printf(stdout, "SYMBOLS finish =======================================\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_print_csymbols()
+ *
+ * Debug display of all the C symbols
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_print_csymbols(void) {
+ Printf(stdout, "CSYMBOLS start =======================================\n");
+ symbol_print_symbols("csymtab", "csym:nextSibling");
+ Printf(stdout, "CSYMBOLS finish =======================================\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_init()
+ *
+ * Create a new symbol table object
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_init(void) {
+
+ current = NewHash();
+ current_symtab = NewHash();
+ ccurrent = NewHash();
+ set_nodeType(current_symtab, "symboltable");
+ Setattr(current_symtab, "symtab", current);
+ Delete(current);
+ Setattr(current_symtab, "csymtab", ccurrent);
+ Delete(ccurrent);
+
+ /* Set the global scope */
+ symtabs = NewHash();
+ Setattr(symtabs, "", current_symtab);
+ Delete(current_symtab);
+ global_scope = current_symtab;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_setscopename()
+ *
+ * Set the C scopename of the current symbol table.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_setscopename(const_String_or_char_ptr name) {
+ String *qname;
+ /* assert(!Getattr(current_symtab,"name")); */
+ Setattr(current_symtab, "name", name);
+
+ /* Set nested scope in parent */
+
+ qname = Swig_symbol_qualifiedscopename(current_symtab);
+
+ /* Save a reference to this scope */
+ Setattr(symtabs, qname, current_symtab);
+ Delete(qname);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_getscopename()
+ *
+ * Get the C scopename of the current symbol table
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_symbol_getscopename(void) {
+ return Getattr(current_symtab, "name");
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_getscope()
+ *
+ * Given a fully qualified C scopename, this function returns a symbol table
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_getscope(const_String_or_char_ptr name) {
+ if (!symtabs)
+ return 0;
+ if (Equal("::", (const_String_or_char_ptr ) name))
+ name = "";
+ return Getattr(symtabs, name);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_qualifiedscopename()
+ *
+ * Get the fully qualified C scopename of a symbol table. Note, this only pertains
+ * to the C/C++ scope name. It is not affected by renaming.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_symbol_qualifiedscopename(Symtab *symtab) {
+ String *result = 0;
+ Hash *parent;
+ String *name;
+ if (!symtab)
+ symtab = current_symtab;
+ parent = Getattr(symtab, "parentNode");
+ if (parent) {
+ result = Swig_symbol_qualifiedscopename(parent);
+ }
+ name = Getattr(symtab, "name");
+ if (name) {
+ if (!result) {
+ result = NewStringEmpty();
+ }
+ if (Len(result)) {
+ Printv(result, "::", name, NIL);
+ } else {
+ Append(result, name);
+ }
+ }
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_qualified_language_scopename()
+ *
+ * Get the fully qualified C scopename of a symbol table but using a language
+ * specific separator for the scopenames. Basically the same as
+ * Swig_symbol_qualifiedscopename() but using the different separator.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_symbol_qualified_language_scopename(Symtab *n) {
+ /* TODO: fix for %rename to work */
+ String *result = Swig_symbol_qualifiedscopename(n);
+ Replaceall(result, "::", NSPACE_SEPARATOR);
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_newscope()
+ *
+ * Create a new scope. Returns the newly created scope.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_newscope(void) {
+ Hash *n;
+ Hash *hsyms, *h;
+
+ hsyms = NewHash();
+ h = NewHash();
+
+ set_nodeType(h, "symboltable");
+ Setattr(h, "symtab", hsyms);
+ Delete(hsyms);
+ set_parentNode(h, current_symtab);
+
+ n = lastChild(current_symtab);
+ if (!n) {
+ set_firstChild(current_symtab, h);
+ } else {
+ set_nextSibling(n, h);
+ Delete(h);
+ }
+ set_lastChild(current_symtab, h);
+ current = hsyms;
+ ccurrent = NewHash();
+ Setattr(h, "csymtab", ccurrent);
+ Delete(ccurrent);
+ current_symtab = h;
+ return h;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_setscope()
+ *
+ * Set the current scope. Returns the previous current scope.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_setscope(Symtab *sym) {
+ Symtab *ret = current_symtab;
+ current_symtab = sym;
+ current = Getattr(sym, "symtab");
+ assert(current);
+ ccurrent = Getattr(sym, "csymtab");
+ assert(ccurrent);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_popscope()
+ *
+ * Pop out of the current scope. Returns the popped scope and sets the
+ * scope to the parent scope.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_popscope(void) {
+ Hash *h = current_symtab;
+ current_symtab = Getattr(current_symtab, "parentNode");
+ assert(current_symtab);
+ current = Getattr(current_symtab, "symtab");
+ assert(current);
+ ccurrent = Getattr(current_symtab, "csymtab");
+ assert(ccurrent);
+ return h;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_global_scope()
+ *
+ * Return the symbol table for the global scope.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_global_scope(void) {
+ return global_scope;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_current()
+ *
+ * Return the current symbol table.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_current(void) {
+ return current_symtab;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_alias()
+ *
+ * Makes an alias for a symbol in the global symbol table.
+ * Primarily for namespace aliases such as 'namespace X = Y;'.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_alias(const_String_or_char_ptr aliasname, Symtab *s) {
+ String *qname = Swig_symbol_qualifiedscopename(current_symtab);
+ if (qname) {
+ Printf(qname, "::%s", aliasname);
+ } else {
+ qname = NewString(aliasname);
+ }
+ if (!Getattr(symtabs, qname)) {
+ Setattr(symtabs, qname, s);
+ }
+ Delete(qname);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_inherit()
+ *
+ * Inherit symbols from another scope. Primarily for C++ inheritance and
+ * for using directives, such as 'using namespace X;'
+ * but not for using declarations, such as 'using A;'.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_inherit(Symtab *s) {
+ int i, ilen;
+ List *inherit = Getattr(current_symtab, "inherit");
+ if (!inherit) {
+ inherit = NewList();
+ Setattr(current_symtab, "inherit", inherit);
+ Delete(inherit);
+ }
+
+ if (s == current_symtab) {
+ Swig_warning(WARN_PARSE_REC_INHERITANCE, Getfile(s), Getline(s), "Recursive scope inheritance of '%s'.\n", Getattr(s, "name"));
+ return;
+ }
+ assert(s != current_symtab);
+ ilen = Len(inherit);
+ for (i = 0; i < ilen; i++) {
+ Node *n = Getitem(inherit, i);
+ if (n == s)
+ return; /* Already inherited */
+ }
+ Append(inherit, s);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_cadd()
+ *
+ * Adds a node to the C symbol table only.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_cadd(const_String_or_char_ptr name, Node *n) {
+ Node *append = 0;
+ Node *cn;
+ /* There are a few options for weak symbols. A "weak" symbol
+ is any symbol that can be replaced by another symbol in the C symbol
+ table. An example would be a forward class declaration. A forward
+ class sits in the symbol table until a real class declaration comes along.
+
+ Certain symbols are marked as "sym:typename". These are important
+ symbols related to the C++ type-system and take precedence in the C
+ symbol table. An example might be code like this:
+
+ template<class T> T foo(T x);
+ int foo(int);
+
+ In this case, the template is marked with "sym:typename" so that it
+ stays in the C symbol table (so that it can be expanded using %template).
+ */
+
+ if (!name)
+ return;
+
+ if (SwigType_istemplate(name)) {
+ String *cname = NewString(name);
+ String *dname = Swig_symbol_template_deftype(cname, 0);
+ if (!Equal(dname, name)) {
+ Swig_symbol_cadd(dname, n);
+ }
+ Delete(dname);
+ Delete(cname);
+ }
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_cadd %s %p\n", name, n);
+#endif
+ cn = Getattr(ccurrent, name);
+
+ if (cn && (Getattr(cn, "sym:typename"))) {
+ /* The node in the C symbol table is a typename. Do nothing */
+ /* We might append the symbol at the end */
+ append = n;
+ } else if (cn && (Getattr(cn, "sym:weak"))) {
+ /* The node in the symbol table is weak. Replace it */
+ if (checkAttribute(cn, "nodeType", "template")
+ && checkAttribute(cn, "templatetype", "classforward")) {
+ /* The node is a template classforward declaration, and the
+ default template parameters here take precedence. */
+ ParmList *pc = Getattr(cn, "templateparms");
+ ParmList *pn = Getattr(n, "templateparms");
+#ifdef SWIG_DEBUG
+ Printf(stderr, "found template classforward %s\n", Getattr(cn, "name"));
+#endif
+ while (pc && pn) {
+ String *value = Getattr(pc, "value");
+ if (value) {
+#ifdef SWIG_DEBUG
+ Printf(stderr, "add default template value %s %s\n", Getattr(pc, "name"), value);
+#endif
+ Setattr(pn, "value", value);
+ }
+ pc = nextSibling(pc);
+ pn = nextSibling(pn);
+ }
+ Setattr(n, "templateparms", Getattr(cn, "templateparms"));
+ }
+ Setattr(ccurrent, name, n);
+
+ } else if (cn && (Getattr(n, "sym:weak"))) {
+ /* The node being added is weak. Don't worry about it */
+ } else if (cn && (Getattr(n, "sym:typename"))) {
+ /* The node being added is a typename. We definitely add it */
+ Setattr(ccurrent, name, n);
+ append = cn;
+ } else if (cn && (Checkattr(cn, "nodeType", "templateparm"))) {
+ Swig_error(Getfile(n), Getline(n), "Declaration of '%s' shadows template parameter,\n", name);
+ Swig_error(Getfile(cn), Getline(cn), "previous template parameter declaration '%s'.\n", name);
+ return;
+ } else if (cn) {
+ append = n;
+ } else if (!cn) {
+ /* No conflict. Add the symbol */
+ Setattr(ccurrent, name, n);
+ }
+
+ /* Multiple entries in the C symbol table. We append to the symbol table */
+ if (append) {
+ Node *fn, *pn = 0;
+ cn = Getattr(ccurrent, name);
+ fn = cn;
+ while (fn) {
+ pn = fn;
+ if (fn == append) {
+ /* already added. Bail */
+ return;
+ }
+ fn = Getattr(fn, "csym:nextSibling");
+ }
+ if (pn) {
+ Setattr(pn, "csym:nextSibling", append);
+ }
+ }
+
+ /* Special typedef handling. When a typedef node is added to the symbol table, we
+ might have to add a type alias. This would occur if the typedef mapped to another
+ scope in the system. For example:
+
+ class Foo {
+ };
+
+ typedef Foo OtherFoo;
+
+ In this case, OtherFoo becomes an alias for Foo. */
+
+ {
+ Node *td = n;
+ while (td && ((Equal(nodeType(td), "cdecl") && Checkattr(td, "storage", "typedef")) || (Equal(nodeType(td), "using") && !Getattr(n, "namespace")))) {
+ SwigType *type;
+ Node *td1;
+ int using_not_typedef = Equal(nodeType(td), "using");
+ type = Copy(Getattr(td, using_not_typedef ? "uname" : "type"));
+ SwigType_push(type, Getattr(td, "decl"));
+ td1 = Swig_symbol_clookup(type, 0);
+
+ /* Fix pathetic case #1214313:
+
+ class Foo
+ {
+ };
+
+ typedef Foo FooBar;
+
+ class CBaz
+ {
+ public:
+ typedef FooBar Foo;
+ };
+
+ ie, when Foo -> FooBar -> Foo, jump one scope up when possible.
+
+ */
+ if (td1) {
+ String *st = 0;
+ String *sn = Getattr(td, "name");
+ if (Equal(nodeType(td1), "cdecl") && Checkattr(td1, "storage", "typedef"))
+ st = Getattr(td1, "type");
+ else if (Equal(nodeType(td1), "using") && !Getattr(td1, "namespace"))
+ st = Getattr(td1, "uname");
+ if (st && sn && Equal(st, sn)) {
+ Symtab *sc = Getattr(current_symtab, "parentNode");
+ if (sc)
+ td1 = Swig_symbol_clookup(type, sc);
+ }
+ }
+
+ Delete(type);
+ if (td1 == td)
+ break;
+ td = td1;
+ if (td) {
+ Symtab *st = Getattr(td, "symtab");
+ if (st) {
+ Swig_symbol_alias(Getattr(n, "name"), st);
+ break;
+ }
+ }
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_add()
+ *
+ * Adds a node to the symbol table. Returns the node itself if successfully
+ * added. Otherwise, it returns the symbol table entry of the conflicting node.
+ *
+ * Also places the symbol in a behind-the-scenes C symbol table. This is needed
+ * for namespace support, type resolution, and other issues.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_add(const_String_or_char_ptr symname, Node *n) {
+ Hash *c, *cl = 0;
+ SwigType *decl, *ndecl;
+ String *cstorage, *nstorage;
+ int nt = 0, ct = 0;
+ int pn = 0;
+ int u1 = 0, u2 = 0;
+ String *name, *overname;
+
+ /* See if the node has a name. If so, we place in the C symbol table for this
+ scope. We don't worry about overloading here---the primary purpose of this
+ is to record information for type/name resolution for later. Conflicts
+ in C namespaces are errors, but these will be caught by the C++ compiler
+ when compiling the wrapper code */
+
+
+ /* There are a few options for weak symbols. A "weak" symbol
+ is any symbol that can be replaced by another symbol in the C symbol
+ table. An example would be a forward class declaration. A forward
+ class sits in the symbol table until a real class declaration comes along.
+
+ Certain symbols are marked as "sym:typename". These are important
+ symbols related to the C++ type-system and take precedence in the C
+ symbol table. An example might be code like this:
+
+ template<class T> T foo(T x);
+ int foo(int);
+
+ In this case, the template is marked with "sym:typename" so that it
+ stays in the C symbol table (so that it can be expanded using %template).
+ */
+
+ name = Getattr(n, "name");
+ if (name && Len(name)) {
+ Swig_symbol_cadd(name, n);
+ }
+
+ /* No symbol name defined. We return. */
+ if (!symname) {
+ Setattr(n, "sym:symtab", current_symtab);
+ return n;
+ }
+
+ /* If node is ignored. We don't proceed any further */
+ if (GetFlag(n, "feature:ignore"))
+ return n;
+
+ /* See if the symbol already exists in the table */
+ c = Getattr(current, symname);
+
+ /* Check for a weak symbol. A weak symbol is allowed to be in the
+ symbol table, but is silently overwritten by other symbols. An example
+ would be a forward class declaration. For instance:
+
+ class Foo;
+
+ In this case, "Foo" sits in the symbol table. However, the
+ definition of Foo would replace the entry if it appeared later. */
+
+ if (c && Getattr(c, "sym:weak")) {
+ c = 0;
+ }
+ if (c) {
+ /* There is a symbol table conflict. There are a few cases to consider here:
+ (1) A conflict between a class/enum and a typedef declaration is okay.
+ In this case, the symbol table entry is set to the class/enum declaration
+ itself, not the typedef.
+ (2) A conflict between namespaces is okay--namespaces are open
+ (3) Otherwise, overloading is only allowed for functions
+ (4) This special case is okay: a class template instantiated with same name as the template's name
+ */
+
+ /* Check for namespaces */
+ String *ntype = Getattr(n, "nodeType");
+ if ((Equal(ntype, Getattr(c, "nodeType"))) && ((Equal(ntype, "namespace")))) {
+ Node *cl, *pcl = 0;
+ cl = c;
+ while (cl) {
+ pcl = cl;
+ cl = Getattr(cl, "sym:nextSibling");
+ }
+ Setattr(pcl, "sym:nextSibling", n);
+ Setattr(n, "sym:symtab", current_symtab);
+ Setattr(n, "sym:name", symname);
+ Setattr(n, "sym:previousSibling", pcl);
+ return n;
+ }
+
+ /* Special case: class template instantiated with same name as the template's name eg: %template(X) X<int>; */
+ if (Equal(nodeType(c), "template")) {
+ String *nt1 = Getattr(c, "templatetype");
+ String *nt2 = nodeType(n);
+ if (Equal(nt1, "class") && Equal(nt1, nt2)) {
+ if (Getattr(n, "template")) {
+ /* Finally check that another %template with same name doesn't already exist */
+ if (!Getattr(c, "sym:nextSibling")) {
+ Setattr(c, "sym:nextSibling", n);
+ Setattr(n, "sym:symtab", current_symtab);
+ Setattr(n, "sym:name", symname);
+ Setattr(n, "sym:previousSibling", c);
+ return n;
+ }
+ }
+ }
+ }
+
+ if (Getattr(n, "allows_typedef"))
+ nt = 1;
+ if (Getattr(c, "allows_typedef"))
+ ct = 1;
+ if (nt || ct) {
+ Node *td, *other;
+ String *s;
+ /* At least one of the nodes allows typedef overloading. Make sure that
+ both don't--this would be a conflict */
+
+ if (nt && ct)
+ return c;
+
+ /* Figure out which node allows the typedef */
+ if (nt) {
+ td = n;
+ other = c;
+ } else {
+ td = c;
+ other = n;
+ }
+ /* Make sure the other node is a typedef */
+ s = Getattr(other, "storage");
+ if (!s || (!Equal(s, "typedef")))
+ return c; /* No. This is a conflict */
+
+ /* Hmmm. This appears to be okay. Make sure the symbol table refers to the allow_type node */
+
+ if (td != c) {
+ Setattr(current, symname, td);
+ Setattr(td, "sym:symtab", current_symtab);
+ Setattr(td, "sym:name", symname);
+ }
+ return n;
+ }
+
+ decl = Getattr(c, "decl");
+ ndecl = Getattr(n, "decl");
+
+ {
+ String *nt1, *nt2;
+ nt1 = Getattr(n, "nodeType");
+ if (Equal(nt1, "template"))
+ nt1 = Getattr(n, "templatetype");
+ nt2 = Getattr(c, "nodeType");
+ if (Equal(nt2, "template"))
+ nt2 = Getattr(c, "templatetype");
+ if (Equal(nt1, "using"))
+ u1 = 1;
+ if (Equal(nt2, "using"))
+ u2 = 1;
+
+ if ((!Equal(nt1, nt2)) && !(u1 || u2))
+ return c;
+ }
+ if (!(u1 || u2)) {
+ if ((!SwigType_isfunction(decl)) || (!SwigType_isfunction(ndecl))) {
+ /* Symbol table conflict */
+ return c;
+ }
+ }
+
+ /* Hmmm. Declarator seems to indicate that this is a function */
+ /* Look at storage class to see if compatible */
+ cstorage = Getattr(c, "storage");
+ nstorage = Getattr(n, "storage");
+
+ /* If either one is declared as typedef, forget it. We're hosed */
+ if (Cmp(cstorage, "typedef") == 0) {
+ return c;
+ }
+ if (Cmp(nstorage, "typedef") == 0) {
+ return c;
+ }
+
+ /* Okay. Walk down the list of symbols and see if we get a declarator match */
+ {
+ String *nt = Getattr(n, "nodeType");
+ int n_template = Equal(nt, "template") && Checkattr(n, "templatetype", "cdecl");
+ int n_plain_cdecl = Equal(nt, "cdecl");
+ Node *cn = c;
+ pn = 0;
+ while (cn) {
+ decl = Getattr(cn, "decl");
+ if (!(u1 || u2)) {
+ if (Cmp(ndecl, decl) == 0) {
+ /* Declarator conflict */
+ /* Now check we don't have a non-templated function overloaded by a templated function with same params,
+ * eg void foo(); template<typename> void foo(); */
+ String *cnt = Getattr(cn, "nodeType");
+ int cn_template = Equal(cnt, "template") && Checkattr(cn, "templatetype", "cdecl");
+ int cn_plain_cdecl = Equal(cnt, "cdecl");
+ if (!((n_template && cn_plain_cdecl) || (cn_template && n_plain_cdecl))) {
+ /* found a conflict */
+ return cn;
+ }
+ }
+ }
+ cl = cn;
+ cn = Getattr(cn, "sym:nextSibling");
+ pn++;
+ }
+ }
+ /* Well, we made it this far. Guess we can drop the symbol in place */
+ Setattr(n, "sym:symtab", current_symtab);
+ Setattr(n, "sym:name", symname);
+ /* Printf(stdout,"%s %p\n", Getattr(n,"sym:overname"), current_symtab); */
+ assert(!Getattr(n, "sym:overname"));
+ overname = NewStringf("__SWIG_%d", pn);
+ Setattr(n, "sym:overname", overname);
+ /*Printf(stdout,"%s %s %s\n", symname, Getattr(n,"decl"), Getattr(n,"sym:overname")); */
+ Setattr(cl, "sym:nextSibling", n);
+ Setattr(n, "sym:previousSibling", cl);
+ Setattr(cl, "sym:overloaded", c);
+ Setattr(n, "sym:overloaded", c);
+ Delete(overname);
+ return n;
+ }
+
+ /* No conflict. Just add it */
+ Setattr(n, "sym:symtab", current_symtab);
+ Setattr(n, "sym:name", symname);
+ /* Printf(stdout,"%s\n", Getattr(n,"sym:overname")); */
+ overname = NewStringf("__SWIG_%d", pn);
+ Setattr(n, "sym:overname", overname);
+ Delete(overname);
+ /* Printf(stdout,"%s %s %s\n", symname, Getattr(n,"decl"), Getattr(n,"sym:overname")); */
+ Setattr(current, symname, n);
+ return n;
+}
+
+/* -----------------------------------------------------------------------------
+ * symbol_lookup()
+ *
+ * Internal function to handle fully qualified symbol table lookups. This
+ * works from the symbol table supplied in symtab and unwinds its way out
+ * towards the global scope.
+ *
+ * This function operates in the C namespace, not the target namespace.
+ *
+ * The check function is an optional callback that can be used to verify a particular
+ * symbol match. This is only used in some of the more exotic parts of SWIG. For instance,
+ * verifying that a class hierarchy implements all pure virtual methods.
+ * ----------------------------------------------------------------------------- */
+
+static Node *_symbol_lookup(const String *name, Symtab *symtab, int (*check) (Node *n)) {
+ Node *n;
+ List *inherit;
+ Hash *sym = Getattr(symtab, "csymtab");
+ if (Getmark(symtab))
+ return 0;
+ Setmark(symtab, 1);
+
+ n = Getattr(sym, name);
+
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_look %s %p %p %s\n", name, n, symtab, Getattr(symtab, "name"));
+#endif
+
+ if (n) {
+ /* if a check-function is defined. Call it to determine a match */
+ if (check) {
+ int c = check(n);
+ if (c == 1) {
+ Setmark(symtab, 0);
+ return n;
+ }
+ if (c < 0) {
+ /* Terminate the search right away */
+ Setmark(symtab, 0);
+ return 0;
+ }
+ } else {
+ Setmark(symtab, 0);
+ return n;
+ }
+ }
+
+ if (!n && SwigType_istemplate(name)) {
+ String *dname = 0;
+ Setmark(symtab, 0);
+ dname = Swig_symbol_template_deftype(name, symtab);
+ if (!Equal(dname, name)) {
+ n = _symbol_lookup(dname, symtab, check);
+ }
+ Delete(dname);
+ if (n)
+ return n;
+ Setmark(symtab, 1);
+ }
+
+ inherit = Getattr(symtab, "inherit");
+ if (inherit && use_inherit) {
+ int i, len;
+ len = Len(inherit);
+ for (i = 0; i < len; i++) {
+ n = _symbol_lookup(name, Getitem(inherit, i), check);
+ if (n) {
+ Setmark(symtab, 0);
+ return n;
+ }
+ }
+ }
+
+ Setmark(symtab, 0);
+ return 0;
+}
+
+static Node *symbol_lookup(const_String_or_char_ptr name, Symtab *symtab, int (*check) (Node *n)) {
+ Node *n = 0;
+ if (DohCheck(name)) {
+ n = _symbol_lookup(name, symtab, check);
+ } else {
+ String *sname = NewString(name);
+ n = _symbol_lookup(sname, symtab, check);
+ Delete(sname);
+ }
+ return n;
+}
+
+
+
+/* -----------------------------------------------------------------------------
+ * symbol_lookup_qualified()
+ * ----------------------------------------------------------------------------- */
+
+static Node *symbol_lookup_qualified(const_String_or_char_ptr name, Symtab *symtab, const String *prefix, int local, int (*checkfunc) (Node *n)) {
+ /* This is a little funky, we search by fully qualified names */
+
+ if (!symtab)
+ return 0;
+ if (!prefix) {
+ Node *n;
+ String *bname = 0;
+ String *prefix = 0;
+ Swig_scopename_split(name, &prefix, &bname);
+ n = symbol_lookup_qualified(bname, symtab, prefix, local, checkfunc);
+ Delete(bname);
+ Delete(prefix);
+ return n;
+ } else {
+ Symtab *st;
+ Node *n = 0;
+ /* Make qualified name of current scope */
+ String *qalloc = 0;
+ String *qname = Swig_symbol_qualifiedscopename(symtab);
+ const String *cqname;
+ if (qname) {
+ if (Len(qname)) {
+ if (prefix && Len(prefix)) {
+ Printv(qname, "::", prefix, NIL);
+ }
+ } else {
+ Append(qname, prefix);
+ }
+ qalloc = qname;
+ cqname = qname;
+ } else {
+ cqname = prefix;
+ }
+ st = Getattr(symtabs, cqname);
+ /* Found a scope match */
+ if (st) {
+ if (!name) {
+ if (qalloc)
+ Delete(qalloc);
+ return st;
+ }
+ n = symbol_lookup(name, st, checkfunc);
+ }
+ if (qalloc)
+ Delete(qalloc);
+
+ if (!n) {
+ if (!local) {
+ Node *pn = Getattr(symtab, "parentNode");
+ if (pn)
+ n = symbol_lookup_qualified(name, pn, prefix, local, checkfunc);
+
+ /* Check inherited scopes */
+ if (!n) {
+ List *inherit = Getattr(symtab, "inherit");
+ if (inherit && use_inherit) {
+ int i, len;
+ len = Len(inherit);
+ for (i = 0; i < len; i++) {
+ Node *prefix_node = symbol_lookup(prefix, Getitem(inherit, i), checkfunc);
+ if (prefix_node) {
+ Node *prefix_symtab = Getattr(prefix_node, "symtab");
+ if (prefix_symtab) {
+ n = symbol_lookup(name, prefix_symtab, checkfunc);
+ break;
+ }
+ }
+ }
+ }
+ }
+ } else {
+ n = 0;
+ }
+ }
+ return n;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_clookup()
+ *
+ * Look up a symbol in the symbol table. This uses the C name, not scripting
+ * names. Note: If we come across a using declaration, we follow it to
+ * to get the real node. Any using directives are also followed (but this is
+ * implemented in symbol_lookup()).
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_clookup(const_String_or_char_ptr name, Symtab *n) {
+ Hash *hsym = 0;
+ Node *s = 0;
+
+ if (!n) {
+ hsym = current_symtab;
+ } else {
+ if (!Checkattr(n, "nodeType", "symboltable")) {
+ n = Getattr(n, "sym:symtab");
+ }
+ assert(n);
+ if (n) {
+ hsym = n;
+ }
+ }
+
+ if (Swig_scopename_check(name)) {
+ char *cname = Char(name);
+ if (strncmp(cname, "::", 2) == 0) {
+ String *nname = NewString(cname + 2);
+ if (Swig_scopename_check(nname)) {
+ s = symbol_lookup_qualified(nname, global_scope, 0, 0, 0);
+ } else {
+ s = symbol_lookup(nname, global_scope, 0);
+ }
+ Delete(nname);
+ } else {
+ String *prefix = Swig_scopename_prefix(name);
+ if (prefix) {
+ s = symbol_lookup_qualified(name, hsym, 0, 0, 0);
+ Delete(prefix);
+ if (!s) {
+ return 0;
+ }
+ }
+ }
+ }
+ if (!s) {
+ while (hsym) {
+ s = symbol_lookup(name, hsym, 0);
+ if (s)
+ break;
+ hsym = Getattr(hsym, "parentNode");
+ if (!hsym)
+ break;
+ }
+ }
+
+ if (!s) {
+ return 0;
+ }
+ /* Check if s is a 'using' node */
+ while (s && Checkattr(s, "nodeType", "using")) {
+ String *uname = Getattr(s, "uname");
+ Symtab *un = Getattr(s, "sym:symtab");
+ Node *ss = (!Equal(name, uname) || (un != n)) ? Swig_symbol_clookup(uname, un) : 0; /* avoid infinity loop */
+ if (!ss) {
+ SWIG_WARN_NODE_BEGIN(s);
+ Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(s, "uname")));
+ SWIG_WARN_NODE_END(s);
+ }
+ s = ss;
+ }
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_clookup_check()
+ *
+ * This function is identical to Swig_symbol_clookup() except that it
+ * accepts a callback function that is invoked to determine a symbol match.
+ * The purpose of this function is to support complicated algorithms that need
+ * to examine multiple definitions of the same symbol that might appear in an
+ * inheritance hierarchy.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_clookup_check(const_String_or_char_ptr name, Symtab *n, int (*checkfunc) (Node *n)) {
+ Hash *hsym = 0;
+ Node *s = 0;
+
+ if (!n) {
+ hsym = current_symtab;
+ } else {
+ if (!Checkattr(n, "nodeType", "symboltable")) {
+ n = Getattr(n, "sym:symtab");
+ }
+ assert(n);
+ if (n) {
+ hsym = n;
+ }
+ }
+
+ if (Swig_scopename_check(name)) {
+ char *cname = Char(name);
+ if (strncmp(cname, "::", 2) == 0) {
+ String *nname = NewString(cname + 2);
+ if (Swig_scopename_check(nname)) {
+ s = symbol_lookup_qualified(nname, global_scope, 0, 0, checkfunc);
+ } else {
+ s = symbol_lookup(nname, global_scope, checkfunc);
+ }
+ Delete(nname);
+ } else {
+ String *prefix = Swig_scopename_prefix(name);
+ if (prefix) {
+ s = symbol_lookup_qualified(name, hsym, 0, 0, checkfunc);
+ Delete(prefix);
+ if (!s) {
+ return 0;
+ }
+ }
+ }
+ }
+ if (!s) {
+ while (hsym) {
+ s = symbol_lookup(name, hsym, checkfunc);
+ if (s)
+ break;
+ hsym = Getattr(hsym, "parentNode");
+ if (!hsym)
+ break;
+ }
+ }
+ if (!s) {
+ return 0;
+ }
+ /* Check if s is a 'using' node */
+ while (s && Checkattr(s, "nodeType", "using")) {
+ Node *ss;
+ ss = Swig_symbol_clookup(Getattr(s, "uname"), Getattr(s, "sym:symtab"));
+ if (!ss && !checkfunc) {
+ SWIG_WARN_NODE_BEGIN(s);
+ Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(s, "uname")));
+ SWIG_WARN_NODE_END(s);
+ }
+ s = ss;
+ }
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_clookup_local()
+ *
+ * Same as Swig_symbol_clookup but parent nodes are not searched, that is, just
+ * this symbol table is searched.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_clookup_local(const_String_or_char_ptr name, Symtab *n) {
+ Hash *hsym;
+ Node *s = 0;
+
+ if (!n) {
+ hsym = current_symtab;
+ } else {
+ if (!Checkattr(n, "nodeType", "symboltable")) {
+ n = Getattr(n, "sym:symtab");
+ }
+ assert(n);
+ hsym = n;
+ }
+
+ if (Swig_scopename_check(name)) {
+ char *cname = Char(name);
+ if (strncmp(cname, "::", 2) == 0) {
+ String *nname = NewString(cname + 2);
+ if (Swig_scopename_check(nname)) {
+ s = symbol_lookup_qualified(nname, global_scope, 0, 0, 0);
+ } else {
+ s = symbol_lookup(nname, global_scope, 0);
+ }
+ Delete(nname);
+ } else {
+ s = symbol_lookup_qualified(name, hsym, 0, 0, 0);
+ }
+ }
+ if (!s) {
+ s = symbol_lookup(name, hsym, 0);
+ }
+ if (!s)
+ return 0;
+ /* Check if s is a 'using' node */
+ while (s && Checkattr(s, "nodeType", "using")) {
+ Node *ss = Swig_symbol_clookup_local(Getattr(s, "uname"), Getattr(s, "sym:symtab"));
+ if (!ss) {
+ SWIG_WARN_NODE_BEGIN(s);
+ Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(s, "uname")));
+ SWIG_WARN_NODE_END(s);
+ }
+ s = ss;
+ }
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_clookup_local_check()
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_clookup_local_check(const_String_or_char_ptr name, Symtab *n, int (*checkfunc) (Node *)) {
+ Hash *hsym;
+ Node *s = 0;
+
+ if (!n) {
+ hsym = current_symtab;
+ } else {
+ if (!Checkattr(n, "nodeType", "symboltable")) {
+ n = Getattr(n, "sym:symtab");
+ }
+ assert(n);
+ hsym = n;
+ }
+
+ if (Swig_scopename_check(name)) {
+ char *cname = Char(name);
+ if (strncmp(cname, "::", 2) == 0) {
+ String *nname = NewString(cname + 2);
+ if (Swig_scopename_check(nname)) {
+ s = symbol_lookup_qualified(nname, global_scope, 0, 0, checkfunc);
+ } else {
+ s = symbol_lookup(nname, global_scope, checkfunc);
+ }
+ Delete(nname);
+ } else {
+ s = symbol_lookup_qualified(name, hsym, 0, 0, checkfunc);
+ }
+ }
+ if (!s) {
+ s = symbol_lookup(name, hsym, checkfunc);
+ }
+ if (!s)
+ return 0;
+ /* Check if s is a 'using' node */
+ while (s && Checkattr(s, "nodeType", "using")) {
+ Node *ss = Swig_symbol_clookup_local_check(Getattr(s, "uname"), Getattr(s, "sym:symtab"), checkfunc);
+ if (!ss && !checkfunc) {
+ SWIG_WARN_NODE_BEGIN(s);
+ Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(s, "uname")));
+ SWIG_WARN_NODE_END(s);
+ }
+ s = ss;
+ }
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_clookup_no_inherit()
+ *
+ * Symbol lookup like Swig_symbol_clookup but does not follow using declarations.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_clookup_no_inherit(const_String_or_char_ptr name, Symtab *n) {
+ Node *s = 0;
+ assert(use_inherit==1);
+ use_inherit = 0;
+ s = Swig_symbol_clookup(name, n);
+ use_inherit = 1;
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_cscope()
+ *
+ * Look up a scope name.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_cscope(const_String_or_char_ptr name, Symtab *symtab) {
+ char *cname = Char(name);
+ if (strncmp(cname, "::", 2) == 0)
+ return symbol_lookup_qualified(0, global_scope, name, 0, 0);
+ return symbol_lookup_qualified(0, symtab, name, 0, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_remove()
+ *
+ * Remove a symbol. If the symbol is an overloaded function and the symbol removed
+ * is not the last in the list of overloaded functions, then the overloaded
+ * names (sym:overname attribute) are changed to start from zero, eg __SWIG_0.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_remove(Node *n) {
+ Symtab *symtab;
+ String *symname;
+ String *overname;
+ Node *symprev;
+ Node *symnext;
+ Node *fixovername = 0;
+ symtab = Getattr(n, "sym:symtab"); /* Get symbol table object */
+ symtab = Getattr(symtab, "symtab"); /* Get actual hash table of symbols */
+ symname = Getattr(n, "sym:name");
+ symprev = Getattr(n, "sym:previousSibling");
+ symnext = Getattr(n, "sym:nextSibling");
+
+ /* If previous symbol, just fix the links */
+ if (symprev) {
+ if (symnext) {
+ Setattr(symprev, "sym:nextSibling", symnext);
+ fixovername = symprev; /* fix as symbol to remove is somewhere in the middle of the linked list */
+ } else {
+ Delattr(symprev, "sym:nextSibling");
+ }
+ } else {
+ /* If no previous symbol, see if there is a next symbol */
+ if (symnext) {
+ Setattr(symtab, symname, symnext);
+ fixovername = symnext; /* fix as symbol to remove is at head of linked list */
+ } else {
+ if (symname)
+ Delattr(symtab, symname);
+ }
+ }
+ if (symnext) {
+ if (symprev) {
+ Setattr(symnext, "sym:previousSibling", symprev);
+ } else {
+ Delattr(symnext, "sym:previousSibling");
+ }
+ }
+ Delattr(n, "sym:symtab");
+ Delattr(n, "sym:previousSibling");
+ Delattr(n, "sym:nextSibling");
+ Delattr(n, "csym:nextSibling");
+ Delattr(n, "sym:overname");
+ Delattr(n, "csym:previousSibling");
+ Delattr(n, "sym:overloaded");
+ n = 0;
+
+ if (fixovername) {
+ Node *nn = fixovername;
+ Node *head = fixovername;
+ int pn = 0;
+
+ /* find head of linked list */
+ while (nn) {
+ head = nn;
+ nn = Getattr(nn, "sym:previousSibling");
+ }
+
+ /* adjust all the sym:overname strings to start from 0 and increment by one */
+ nn = head;
+ while (nn) {
+ assert(Getattr(nn, "sym:overname"));
+ Delattr(nn, "sym:overname");
+ overname = NewStringf("__SWIG_%d", pn);
+ Setattr(nn, "sym:overname", overname);
+ Delete(overname);
+ pn++;
+ nn = Getattr(nn, "sym:nextSibling");
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_qualified()
+ *
+ * Return the qualified name of a symbol
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_symbol_qualified(Node *n) {
+ Hash *symtab;
+ if (Checkattr(n, "nodeType", "symboltable")) {
+ symtab = n;
+ } else {
+ symtab = Getattr(n, "sym:symtab");
+ }
+ if (!symtab)
+ return NewStringEmpty();
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_qscope %s %p %s\n", Getattr(n, "name"), symtab, Getattr(symtab, "name"));
+#endif
+ return Swig_symbol_qualifiedscopename(symtab);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_isoverloaded()
+ *
+ * Check if a symbol is overloaded. Returns the first symbol if so.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_isoverloaded(Node *n) {
+ return Getattr(n, "sym:overloaded");
+}
+
+/* -----------------------------------------------------------------------------
+ * symbol_template_qualify()
+ *
+ * Internal function to create a fully qualified type name for templates
+ * ----------------------------------------------------------------------------- */
+
+/* This cache produces problems with OSS, don't active it */
+/* #define SWIG_TEMPLATE_QUALIFY_CACHE */
+static SwigType *symbol_template_qualify(const SwigType *e, Symtab *st) {
+ String *tprefix, *tsuffix;
+ SwigType *qprefix;
+ String *targs;
+ List *targslist;
+ Node *tempn;
+ Symtab *tscope;
+ Iterator ti;
+#ifdef SWIG_TEMPLATE_QUALIFY_CACHE
+ static Hash *qualify_cache = 0;
+ String *scopetype = st ? NewStringf("%s::%s", Getattr(st, "name"), e)
+ : NewStringf("%s::%s", Swig_symbol_getscopename(), e);
+ if (!qualify_cache) {
+ qualify_cache = NewHash();
+ }
+ if (scopetype) {
+ String *cres = Getattr(qualify_cache, scopetype);
+ if (cres) {
+ Delete(scopetype);
+ return Copy(cres);
+ }
+ }
+#endif
+
+ tprefix = SwigType_templateprefix(e);
+ tsuffix = SwigType_templatesuffix(e);
+ qprefix = Swig_symbol_type_qualify(tprefix, st);
+ targs = SwigType_templateargs(e);
+ targslist = SwigType_parmlist(targs);
+ tempn = Swig_symbol_clookup_local(tprefix, st);
+ tscope = tempn ? Getattr(tempn, "sym:symtab") : 0;
+ Append(qprefix, "<(");
+ for (ti = First(targslist); ti.item;) {
+ String *vparm;
+ /* TODO: the logic here should be synchronised with that in SwigType_typedef_qualified() */
+ /* TODO: ti.item might be a non-type parameter possibly within (), eg: (std::is_integral_v<(A)>||std::is_same_v<(A,node_t)>) */
+ String *qparm = Swig_symbol_type_qualify(ti.item, st);
+ if (tscope && (tscope != st)) {
+ String *ty = Swig_symbol_type_qualify(qparm, tscope);
+ Delete(qparm);
+ qparm = ty;
+ }
+
+ vparm = Swig_symbol_template_param_eval(qparm, st);
+ Append(qprefix, vparm);
+ ti = Next(ti);
+ if (ti.item) {
+ Putc(',', qprefix);
+ }
+ Delete(qparm);
+ Delete(vparm);
+ }
+ Append(qprefix, ")>");
+ Append(qprefix, tsuffix);
+ Delete(tprefix);
+ Delete(tsuffix);
+ Delete(targs);
+ Delete(targslist);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_temp_qual %s %s\n", e, qprefix);
+#endif
+#ifdef SWIG_TEMPLATE_QUALIFY_CACHE
+ Setattr(qualify_cache, scopetype, qprefix);
+ Delete(scopetype);
+#endif
+
+ return qprefix;
+}
+
+
+static int symbol_no_constructor(Node *n) {
+ return !Checkattr(n, "nodeType", "constructor");
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_type_qualify()
+ *
+ * Create a fully qualified type name
+ * Note: Does not resolve a constructor if passed in as the 'type'.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *Swig_symbol_type_qualify(const SwigType *t, Symtab *st) {
+ List *elements;
+ String *result = NewStringEmpty();
+ int i, len;
+ char *c = Char(t);
+ if (strncmp(c, "::", 2) == 0) {
+ Append(result, t);
+ return result;
+ }
+
+ elements = SwigType_split(t);
+
+ len = Len(elements);
+ for (i = 0; i < len; i++) {
+ String *e = Getitem(elements, i);
+ if (SwigType_issimple(e)) {
+ /* Note: the unary scope operator (::) is being removed from the template parameters here. */
+ Node *n = Swig_symbol_clookup_check(e, st, symbol_no_constructor);
+ if (n) {
+ String *name = Getattr(n, "name");
+ Clear(e);
+ Append(e, name);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_qual_ei %d %s %s %p\n", i, name, e, st);
+#endif
+ if (!Swig_scopename_check(name)) {
+ String *qname = Swig_symbol_qualified(n);
+ if (qname && Len(qname)) {
+ Insert(e, 0, "::");
+ Insert(e, 0, qname);
+ }
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_qual_sc %d %s %s %p\n", i, qname, e, st);
+#endif
+ Delete(qname);
+ }
+ } else if (SwigType_istemplate(e)) {
+ SwigType *ty = symbol_template_qualify(e, st);
+ Clear(e);
+ Append(e, ty);
+ Delete(ty);
+ }
+ if (strncmp(Char(e), "::", 2) == 0) {
+ Delitem(e, 0);
+ Delitem(e, 0);
+ }
+ Append(result, e);
+ } else if (SwigType_isfunction(e)) {
+ List *parms = SwigType_parmlist(e);
+ String *s = NewString("f(");
+ Iterator pi = First(parms);
+ while (pi.item) {
+ String *pf = Swig_symbol_type_qualify(pi.item, st);
+ Append(s, pf);
+ pi = Next(pi);
+ if (pi.item) {
+ Append(s, ",");
+ }
+ Delete(pf);
+ }
+ Append(s, ").");
+ Append(result, s);
+ Delete(parms);
+ Delete(s);
+ } else {
+ Append(result, e);
+ }
+ }
+ Delete(elements);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_qualify %s %s %p %s\n", t, result, st, st ? Getattr(st, "name") : 0);
+#endif
+
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_template_reduce()
+ * Resolves template parameter types
+ * For example:
+ * typedef int Int;
+ * typedef Int Integer;
+ * with input:
+ * Foo<(Int,Integer)>
+ * returns:
+ * Foo<(int,int)>
+ * ----------------------------------------------------------------------------- */
+
+static
+SwigType *Swig_symbol_template_reduce(SwigType *qt, Symtab *ntab) {
+ Parm *p;
+ String *templateargs = SwigType_templateargs(qt);
+ List *parms = SwigType_parmlist(templateargs);
+ Iterator pi = First(parms);
+ String *tprefix = SwigType_templateprefix(qt);
+ String *tsuffix = SwigType_templatesuffix(qt);
+ String *qprefix = SwigType_typedef_qualified(tprefix);
+ Append(qprefix, "<(");
+ while ((p = pi.item)) {
+ String *np;
+ String *tp = Swig_symbol_typedef_reduce(p, ntab);
+ String *qp = Swig_symbol_type_qualify(tp, ntab);
+ Node *n = Swig_symbol_clookup(qp, ntab);
+ if (n) {
+ String *qual = Swig_symbol_qualified(n);
+ np = Copy(Getattr(n, "name"));
+ Delete(tp);
+ tp = np;
+ if (qual && Len(qual)) {
+ Insert(np, 0, "::");
+ Insert(np, 0, qual);
+ }
+ Delete(qual);
+ } else {
+ np = qp;
+ }
+ Append(qprefix, np);
+ pi = Next(pi);
+ if (pi.item) {
+ Append(qprefix, ",");
+ }
+ Delete(qp);
+ Delete(tp);
+ }
+ Append(qprefix, ")>");
+ Append(qprefix, tsuffix);
+ Delete(parms);
+ Delete(tprefix);
+ Delete(tsuffix);
+ Delete(templateargs);
+ return qprefix;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_typedef_reduce()
+ *
+ * Chase a typedef through symbol tables looking for a match.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *Swig_symbol_typedef_reduce(const SwigType *ty, Symtab *tab) {
+ SwigType *prefix, *base;
+ Node *n;
+ String *nt;
+
+ base = SwigType_base(ty);
+ prefix = SwigType_prefix(ty);
+
+ n = Swig_symbol_clookup(base, tab);
+ if (!n) {
+ if (SwigType_istemplate(ty)) {
+ SwigType *qt = Swig_symbol_template_reduce(base, tab);
+ Append(prefix, qt);
+ Delete(qt);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_reduce (a) %s %s\n", ty, prefix);
+#endif
+ Delete(base);
+ return prefix;
+ } else {
+ Delete(prefix);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_reduce (b) %s %s\n", ty, ty);
+#endif
+ return Copy(ty);
+ }
+ }
+ nt = Getattr(n, "nodeType");
+ if (Equal(nt, "using")) {
+ String *uname = Getattr(n, "uname");
+ if (uname) {
+ n = Swig_symbol_clookup(base, Getattr(n, "sym:symtab"));
+ if (!n) {
+ Delete(base);
+ Delete(prefix);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_reduce (c) %s %s\n", ty, ty);
+#endif
+ return Copy(ty);
+ }
+ }
+ }
+ if (Equal(nt, "cdecl")) {
+ String *storage = Getattr(n, "storage");
+ if (storage && (Equal(storage, "typedef"))) {
+ SwigType *decl;
+ SwigType *rt;
+ SwigType *qt;
+ Symtab *ntab;
+ SwigType *nt = Copy(Getattr(n, "type"));
+
+ /* Fix for case 'typedef struct Hello hello;' */
+ {
+ const char *dclass[3] = { "struct ", "union ", "class " };
+ int i;
+ char *c = Char(nt);
+ for (i = 0; i < 3; i++) {
+ if (strstr(c, dclass[i]) == c) {
+ Replace(nt, dclass[i], "", DOH_REPLACE_FIRST);
+ }
+ }
+ }
+ decl = Getattr(n, "decl");
+ if (decl) {
+ SwigType_push(nt, decl);
+ }
+ SwigType_push(nt, prefix);
+ Delete(base);
+ Delete(prefix);
+ ntab = Getattr(n, "sym:symtab");
+ rt = Swig_symbol_typedef_reduce(nt, ntab);
+ qt = Swig_symbol_type_qualify(rt, ntab);
+ if (SwigType_istemplate(qt)) {
+ SwigType *qtr = Swig_symbol_template_reduce(qt, ntab);
+ Delete(qt);
+ qt = qtr;
+ }
+ Delete(nt);
+ Delete(rt);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_reduce (d) %s %s\n", qt, ty);
+#endif
+ return qt;
+ }
+ }
+ Delete(base);
+ Delete(prefix);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_reduce (e) %s %s\n", ty, ty);
+#endif
+ return Copy(ty);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_string_qualify()
+ *
+ * This function takes a string and looks for identifiers. Identifiers are
+ * then qualified according to scope rules. This function is used in a number
+ * of settings including expression evaluation, scoping of conversion operators,
+ * and so forth.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_symbol_string_qualify(String *s, Symtab *st) {
+ int have_id = 0;
+ String *id = NewStringEmpty();
+ String *r = NewStringEmpty();
+ char *c = Char(s);
+ int first_char = 1;
+ while (*c) {
+ if (isalpha((int) *c) || (*c == '_') || (*c == ':') || (*c == '~' && first_char) || (isdigit((int) *c) && !first_char)) {
+ Putc(*c, id);
+ have_id = 1;
+ } else {
+ if (have_id) {
+ String *qid = Swig_symbol_type_qualify(id, st);
+ Append(r, qid);
+ Clear(id);
+ Delete(qid);
+ have_id = 0;
+ }
+ Putc(*c, r);
+ }
+ first_char = (*c == ':');
+ c++;
+ }
+ if (have_id) {
+ String *qid = Swig_symbol_type_qualify(id, st);
+ Append(r, qid);
+ Delete(qid);
+ }
+ Delete(id);
+ return r;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_template_defargs()
+ *
+ * Apply default arg from generic template default args
+ * Returns a parameter list which contains missing default arguments (if any)
+ * Note side effects: parms will also contain the extra parameters in its list
+ * (but only if non-zero).
+ * ----------------------------------------------------------------------------- */
+
+
+ParmList *Swig_symbol_template_defargs(Parm *parms, Parm *targs, Symtab *tscope, Symtab *tsdecl) {
+ ParmList *expandedparms = parms;
+ if (Len(parms) < Len(targs)) {
+ Parm *lp = parms;
+ Parm *p = lp;
+ Parm *tp = targs;
+ while (p && tp) {
+ p = nextSibling(p);
+ tp = nextSibling(tp);
+ if (p)
+ lp = p;
+ }
+ while (tp) {
+ String *value = Getattr(tp, "value");
+ if (value) {
+ Parm *cp;
+ Parm *ta = targs;
+ Parm *p = parms;
+ SwigType *nt = Swig_symbol_string_qualify(value, tsdecl);
+ SwigType *ntq = 0;
+#ifdef SWIG_DEBUG
+ Printf(stderr, "value %s %s %s\n", value, nt, tsdecl ? Getattr(tsdecl, "name") : tsdecl);
+#endif
+ while (p && ta) {
+ String *name = Getattr(ta, "name");
+ String *pvalue = Getattr(p, "value");
+ String *value = pvalue ? pvalue : Getattr(p, "type");
+ String *ttq = Swig_symbol_type_qualify(value, tscope);
+ /* value = SwigType_typedef_resolve_all(value); */
+ Replaceid(nt, name, ttq);
+ p = nextSibling(p);
+ ta = nextSibling(ta);
+ Delete(ttq);
+ }
+ ntq = Swig_symbol_type_qualify(nt, tsdecl);
+ if (SwigType_istemplate(ntq)) {
+ String *ty = Swig_symbol_template_deftype(ntq, tscope);
+ Delete(ntq);
+ ntq = ty;
+ }
+ cp = NewParmWithoutFileLineInfo(ntq, 0);
+ if (lp) {
+ set_nextSibling(lp, cp);
+ Delete(cp);
+ } else {
+ expandedparms = cp;
+ }
+ lp = cp;
+ tp = nextSibling(tp);
+ Delete(nt);
+ Delete(ntq);
+ } else {
+ tp = 0;
+ }
+ }
+ }
+ return expandedparms;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_template_deftype()
+ *
+ * Apply default args to generic template type
+ * ----------------------------------------------------------------------------- */
+
+#define SWIG_TEMPLATE_DEFTYPE_CACHE
+SwigType *Swig_symbol_template_deftype(const SwigType *type, Symtab *tscope) {
+ String *result = NewStringEmpty();
+ List *elements = SwigType_split(type);
+ int len = Len(elements);
+ int i;
+#ifdef SWIG_TEMPLATE_DEFTYPE_CACHE
+ static Hash *s_cache = 0;
+ Hash *scope_cache;
+ /* The lookup depends on the current scope and potential namespace qualification.
+ Looking up x in namespace y is not the same as looking up x::y in outer scope.
+ -> we use a 2-level hash: first scope and then symbol. */
+ String *scope_name = tscope
+ ? Swig_symbol_qualifiedscopename(tscope)
+ : Swig_symbol_qualifiedscopename(current_symtab);
+ String *type_name = tscope
+ ? NewStringf("%s::%s", Getattr(tscope, "name"), type)
+ : NewStringf("%s::%s", Swig_symbol_getscopename(), type);
+ if (!scope_name) scope_name = NewString("::");
+ if (!s_cache) {
+ s_cache = NewHash();
+ }
+ scope_cache = Getattr(s_cache, scope_name);
+ if (scope_cache) {
+ String *cres = Getattr(scope_cache, type_name);
+ if (cres) {
+ Append(result, cres);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "cached deftype %s(%s) -> %s\n", type, scope_name, result);
+#endif
+ Delete(type_name);
+ Delete(scope_name);
+ return result;
+ }
+ } else {
+ scope_cache = NewHash();
+ Setattr(s_cache, scope_name, scope_cache);
+ Delete(scope_name);
+ }
+#endif
+
+#ifdef SWIG_DEBUG
+ Printf(stderr, "finding deftype %s\n", type);
+#endif
+
+ for (i = 0; i < len; i++) {
+ String *e = Getitem(elements, i);
+ if (SwigType_isfunction(e)) {
+ String *s = NewString("f(");
+ List *parms = SwigType_parmlist(e);
+ Iterator pi = First(parms);
+ while (pi.item) {
+ String *pf = SwigType_istemplate(e) ? Swig_symbol_template_deftype(pi.item, tscope)
+ : Swig_symbol_type_qualify(pi.item, tscope);
+ Append(s, pf);
+ pi = Next(pi);
+ if (pi.item) {
+ Append(s, ",");
+ }
+ Delete(pf);
+ }
+ Append(s, ").");
+ Append(result, s);
+ Delete(s);
+ Delete(parms);
+ } else if (SwigType_istemplate(e)) {
+ String *prefix = SwigType_prefix(e);
+ String *base = SwigType_base(e);
+ String *tprefix = SwigType_templateprefix(base);
+ String *targs = SwigType_templateargs(base);
+ String *tsuffix = SwigType_templatesuffix(base);
+ ParmList *tparms = SwigType_function_parms(targs, 0);
+ Node *tempn = Swig_symbol_clookup_local(tprefix, tscope);
+ if (!tempn && tsuffix && Len(tsuffix)) {
+ tempn = Swig_symbol_clookup(tprefix, 0);
+ }
+#ifdef SWIG_DEBUG
+ Printf(stderr, "deftype type %s %s %d\n", e, tprefix, (long) tempn);
+#endif
+ if (tempn) {
+ ParmList *tnargs = Getattr(tempn, "templateparms");
+ ParmList *expandedparms;
+ Parm *p;
+ Symtab *tsdecl = Getattr(tempn, "sym:symtab");
+
+#ifdef SWIG_DEBUG
+ Printf(stderr, "deftype type %s %s %s\n", tprefix, targs, tsuffix);
+#endif
+ Append(tprefix, "<(");
+ expandedparms = Swig_symbol_template_defargs(tparms, tnargs, tscope, tsdecl);
+ p = expandedparms;
+ tscope = tsdecl;
+ while (p) {
+ SwigType *ptype = Getattr(p, "type");
+ SwigType *ttr = ptype ? ptype : Getattr(p, "value");
+ SwigType *ttf = Swig_symbol_type_qualify(ttr, tscope);
+ SwigType *ttq = Swig_symbol_template_param_eval(ttf, tscope);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "arg type %s\n", ttq);
+#endif
+ if (SwigType_istemplate(ttq)) {
+ SwigType *ttd = Swig_symbol_template_deftype(ttq, tscope);
+ Delete(ttq);
+ ttq = ttd;
+#ifdef SWIG_DEBUG
+ Printf(stderr, "arg deftype %s\n", ttq);
+#endif
+ }
+ Append(tprefix, ttq);
+ p = nextSibling(p);
+ if (p)
+ Putc(',', tprefix);
+ Delete(ttf);
+ Delete(ttq);
+ }
+ Append(tprefix, ")>");
+ Append(tprefix, tsuffix);
+ Append(prefix, tprefix);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "deftype %s %s \n", type, tprefix);
+#endif
+ Append(result, prefix);
+ } else {
+ Append(result, e);
+ }
+ Delete(prefix);
+ Delete(base);
+ Delete(tprefix);
+ Delete(tsuffix);
+ Delete(targs);
+ Delete(tparms);
+ } else {
+ Append(result, e);
+ }
+ }
+ Delete(elements);
+#ifdef SWIG_TEMPLATE_DEFTYPE_CACHE
+ Setattr(scope_cache, type_name, result);
+ Delete(type_name);
+#endif
+
+ return result;
+}
+
+SwigType *Swig_symbol_template_param_eval(const SwigType *p, Symtab *symtab) {
+ String *value = Copy(p);
+ Node *lastnode = 0;
+ while (1) {
+ Node *n = Swig_symbol_clookup(value, symtab);
+ if (n == lastnode)
+ break;
+ lastnode = n;
+ if (n) {
+ String *nt = Getattr(n, "nodeType");
+ if (Equal(nt, "enumitem")) {
+ /* An enum item. Generate a fully qualified name */
+ String *qn = Swig_symbol_qualified(n);
+ if (qn && Len(qn)) {
+ Append(qn, "::");
+ Append(qn, Getattr(n, "name"));
+ Delete(value);
+ value = qn;
+ continue;
+ } else {
+ Delete(qn);
+ break;
+ }
+ } else if ((Equal(nt, "cdecl"))) {
+ String *nv = Getattr(n, "value");
+ if (nv) {
+ Delete(value);
+ value = Copy(nv);
+ continue;
+ }
+ }
+ }
+ break;
+ }
+ return value;
+}