diff options
author | thegeorg <thegeorg@yandex-team.com> | 2023-10-03 11:19:48 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2023-10-03 11:43:28 +0300 |
commit | cda0c13f23f6b169fb0a49dc504b40a0aaecea09 (patch) | |
tree | 26476e92e5af2c856e017afb1df8f8dff42495bf /contrib/tools/swig/Source/Swig/symbol.c | |
parent | 4854116da9c5e3c95bb8440f2ea997c54b6e1a61 (diff) | |
download | ydb-cda0c13f23f6b169fb0a49dc504b40a0aaecea09.tar.gz |
Move contrib/tools/jdk to build/platform/java/jdk/testing
Diffstat (limited to 'contrib/tools/swig/Source/Swig/symbol.c')
-rw-r--r-- | contrib/tools/swig/Source/Swig/symbol.c | 2128 |
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; +} |