diff options
Diffstat (limited to 'Source/Modules/typepass.cxx')
| -rw-r--r-- | Source/Modules/typepass.cxx | 1164 |
1 files changed, 1164 insertions, 0 deletions
diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx new file mode 100644 index 0000000..6cb7f0a --- /dev/null +++ b/Source/Modules/typepass.cxx @@ -0,0 +1,1164 @@ +/* ----------------------------------------------------------------------------- + * See the LICENSE file for information on copyright, usage and redistribution + * of SWIG, and the README file for authors - http://www.swig.org/release.html. + * + * typepass.cxx + * + * This module builds all of the internal type information by collecting + * typedef declarations as well as registering classes, structures, and unions. + * This information is needed to correctly handle shadow classes and other + * advanced features. This phase of compilation is also used to perform + * type-expansion. All types are fully qualified with namespace prefixes + * and other information needed for compilation. + * ----------------------------------------------------------------------------- */ + +char cvsroot_typepass_cxx[] = "$Id: typepass.cxx 11279 2009-06-16 19:29:08Z wsfulton $"; + +#include "swigmod.h" +#include "cparse.h" + +struct normal_node { + Symtab *symtab; + Hash *typescope; + List *normallist; + normal_node *next; +}; + +static normal_node *patch_list = 0; + +/* Singleton class - all non-static methods in this class are private */ +class TypePass:private Dispatcher { + Node *inclass; + Node *module; + int importmode; + String *nsname; + Hash *classhash; + List *normalize; + + TypePass() { + } + + /* Normalize a type. Replaces type with fully qualified version */ + void normalize_type(SwigType *ty) { + SwigType *qty; + if (CPlusPlus) { + Replaceall(ty, "struct ", ""); + Replaceall(ty, "union ", ""); + Replaceall(ty, "class ", ""); + } + + qty = SwigType_typedef_qualified(ty); + /* Printf(stdout,"%s --> %s\n", ty, qty); */ + Clear(ty); + Append(ty, qty); + Delete(qty); + } + + /* Normalize a parameter list */ + + void normalize_parms(ParmList *p) { + while (p) { + SwigType *ty = Getattr(p, "type"); + normalize_type(ty); + /* This is a check for a function type */ + { + SwigType *qty = SwigType_typedef_resolve_all(ty); + if (SwigType_isfunction(qty)) { + SwigType_add_pointer(ty); + } + Delete(qty); + } + + String *value = Getattr(p, "value"); + if (value) { + Node *n = Swig_symbol_clookup(value, 0); + if (n) { + String *q = Swig_symbol_qualified(n); + if (q && Len(q)) { + String *vb = Swig_scopename_last(value); + Clear(value); + Printf(value, "%s::%s", SwigType_namestr(q), vb); + Delete(q); + } + } + } + if (value && SwigType_istemplate(value)) { + String *nv = SwigType_namestr(value); + Setattr(p, "value", nv); + } + p = nextSibling(p); + } + } + + void normalize_later(ParmList *p) { + while (p) { + SwigType *ty = Getattr(p, "type"); + Append(normalize, ty); + p = nextSibling(p); + } + } + + /* Walk through entries in normalize list and patch them up */ + void normalize_list() { + Hash *currentsym = Swig_symbol_current(); + + normal_node *nn = patch_list; + normal_node *np; + while (nn) { + Swig_symbol_setscope(nn->symtab); + SwigType_set_scope(nn->typescope); + Iterator t; + for (t = First(nn->normallist); t.item; t = Next(t)) { + normalize_type(t.item); + } + Delete(nn->normallist); + np = nn->next; + delete(nn); + nn = np; + } + Swig_symbol_setscope(currentsym); + } + + /* generate C++ inheritance type-relationships */ + void cplus_inherit_types_impl(Node *first, Node *cls, String *clsname, const char *bases, const char *baselist, int ispublic, String *cast = 0) { + + if (first == cls) + return; /* The Marcelo check */ + if (!cls) + cls = first; + List *alist = 0; + List *ilist = Getattr(cls, bases); + if (!ilist) { + List *nlist = Getattr(cls, baselist); + if (nlist) { + int len = Len(nlist); + int i; + for (i = 0; i < len; i++) { + Node *bcls = 0; + int clsforward = 0; + String *bname = Getitem(nlist, i); + String *sname = bname; + String *tname = 0; + + /* Try to locate the base class. We look in the symbol table and we chase + typedef declarations to get to the base class if necessary */ + Symtab *st = Getattr(cls, "sym:symtab"); + + if (SwigType_istemplate(bname)) { + tname = SwigType_typedef_resolve_all(bname); + sname = tname; + } + while (1) { + String *qsname = SwigType_typedef_qualified(sname); + bcls = Swig_symbol_clookup(qsname, st); + Delete(qsname); + if (bcls) { + if (Strcmp(nodeType(bcls), "class") != 0) { + /* Not a class. The symbol could be a typedef. */ + if (checkAttribute(bcls, "storage", "typedef")) { + SwigType *decl = Getattr(bcls, "decl"); + if (!decl || !(Len(decl))) { + sname = Getattr(bcls, "type"); + st = Getattr(bcls, "sym:symtab"); + if (SwigType_istemplate(sname)) { + if (tname) + Delete(tname); + tname = SwigType_typedef_resolve_all(sname); + sname = tname; + } + continue; + } + } + if (Strcmp(nodeType(bcls), "classforward") != 0) { + Swig_error(Getfile(cls), Getline(cls), "'%s' does not have a valid base class.\n", Getattr(cls, "name")); + Swig_error(Getfile(bcls), Getline(bcls), "'%s' is not a valid base class.\n", SwigType_namestr(bname)); + } else { + Swig_warning(WARN_TYPE_INCOMPLETE, Getfile(cls), Getline(cls), "Base class '%s' is incomplete.\n", SwigType_namestr(bname)); + Swig_warning(WARN_TYPE_INCOMPLETE, Getfile(bcls), Getline(bcls), "Only forward declaration '%s' was found.\n", SwigType_namestr(bname)); + clsforward = 1; + } + bcls = 0; + } else { + if (Getattr(bcls, "typepass:visit")) { + if (!ilist) + ilist = alist = NewList(); + Append(ilist, bcls); + } else { + Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(cls), Getline(cls), "Base class '%s' undefined.\n", SwigType_namestr(bname)); + Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "'%s' must be defined before it is used as a base class.\n", SwigType_namestr(bname)); + } + } + } + break; + } + + if (tname) + Delete(tname); + if (!bcls) { + if (!clsforward) { + if (ispublic && !Getmeta(bname, "already_warned")) { + Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(cls), Getline(cls), "Nothing known about base class '%s'. Ignored.\n", SwigType_namestr(bname)); + if (Strchr(bname, '<')) { + Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(cls), Getline(cls), "Maybe you forgot to instantiate '%s' using %%template.\n", + SwigType_namestr(bname)); + } + Setmeta(bname, "already_warned", "1"); + } + } + SwigType_inherit(clsname, bname, cast, 0); + } + } + } + if (ilist) { + Setattr(cls, bases, ilist); + } + } + if (alist) + Delete(alist); + + if (!ilist) + return; + int len = Len(ilist); + int i; + for (i = 0; i < len; i++) { + Node *n = Getitem(ilist, i); + String *bname = Getattr(n, "name"); + Node *bclass = n; /* Getattr(n,"class"); */ + Hash *scopes = Getattr(bclass, "typescope"); + SwigType_inherit(clsname, bname, cast, 0); + if (!importmode) { + String *btype = Copy(bname); + SwigType_add_pointer(btype); + SwigType_remember(btype); + Delete(btype); + } + if (scopes) { + SwigType_inherit_scope(scopes); + } + /* Set up inheritance in the symbol table */ + Symtab *st = Getattr(cls, "symtab"); + Symtab *bst = Getattr(bclass, "symtab"); + if (st == bst) { + Swig_warning(WARN_PARSE_REC_INHERITANCE, Getfile(cls), Getline(cls), "Recursive scope inheritance of '%s'.\n", Getattr(cls, "name")); + continue; + } + Symtab *s = Swig_symbol_current(); + Swig_symbol_setscope(st); + Swig_symbol_inherit(bst); + Swig_symbol_setscope(s); + + /* Recursively hit base classes */ + String *namestr = SwigType_namestr(Getattr(bclass, "name")); + String *newcast = NewStringf("(%s *)%s", namestr, cast); + Delete(namestr); + cplus_inherit_types_impl(first, bclass, clsname, bases, baselist, ispublic, newcast); + Delete(newcast); + } + } + + void append_list(List *lb, List *la) { + if (la && lb) { + for (Iterator bi = First(la); bi.item; bi = Next(bi)) { + Append(lb, bi.item); + } + } + } + + void cplus_inherit_types(Node *first, Node *cls, String *clsname, String *cast = 0) { + cplus_inherit_types_impl(first, cls, clsname, "bases", "baselist", 1, cast); + cplus_inherit_types_impl(first, cls, clsname, "protectedbases", "protectedbaselist", 0, cast); + cplus_inherit_types_impl(first, cls, clsname, "privatebases", "privatebaselist", 0, cast); + + if (!cls) + cls = first; + + List *allbases = NewList(); + append_list(allbases, Getattr(cls, "bases")); + append_list(allbases, Getattr(cls, "protectedbases")); + append_list(allbases, Getattr(cls, "privatebases")); + if (Len(allbases)) { + Setattr(cls, "allbases", allbases); + } + Delete(allbases); + } + + /* ------------------------------------------------------------ + * top() + * ------------------------------------------------------------ */ + + virtual int top(Node *n) { + importmode = 0; + module = Getattr(n, "module"); + inclass = 0; + normalize = 0; + nsname = 0; + classhash = Getattr(n, "classes"); + emit_children(n); + normalize_list(); + SwigType_set_scope(0); + return SWIG_OK; + } + + + /* ------------------------------------------------------------ + * moduleDirective() + * ------------------------------------------------------------ */ + + virtual int moduleDirective(Node *n) { + if (!module) { + module = n; + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * importDirective() + * ------------------------------------------------------------ */ + + virtual int importDirective(Node *n) { + String *oldmodule = module; + int oldimport = importmode; + importmode = 1; + module = 0; + emit_children(n); + importmode = oldimport; + module = oldmodule; + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * includeDirective() + * externDirective() + * extendDirective() + * ------------------------------------------------------------ */ + + virtual int includeDirective(Node *n) { + return emit_children(n); + } + virtual int externDeclaration(Node *n) { + return emit_children(n); + } + virtual int extendDirective(Node *n) { + return emit_children(n); + } + + /* ------------------------------------------------------------ + * classDeclaration() + * ------------------------------------------------------------ */ + + virtual int classDeclaration(Node *n) { + String *name = Getattr(n, "name"); + String *tdname = Getattr(n, "tdname"); + String *unnamed = Getattr(n, "unnamed"); + String *storage = Getattr(n, "storage"); + String *kind = Getattr(n, "kind"); + Node *oldinclass = inclass; + List *olist = normalize; + Symtab *symtab; + String *nname = 0; + String *fname = 0; + String *scopename = 0; + + normalize = NewList(); + + if (name) { + if (SwigType_istemplate(name)) { + // We need to fully resolve the name to make templates work correctly */ + Node *cn; + fname = SwigType_typedef_resolve_all(name); + if (Strcmp(fname, name) != 0 && (cn = Swig_symbol_clookup_local(fname, 0))) { + if ((n == cn) + || (Strcmp(nodeType(cn), "template") == 0) + || (Getattr(cn, "feature:onlychildren") != 0) + || (Getattr(n, "feature:onlychildren") != 0)) { + Swig_symbol_cadd(fname, n); + SwigType_typedef_class(fname); + scopename = Copy(fname); + } else { + Swig_warning(WARN_TYPE_REDEFINED, Getfile(n), Getline(n), "Template '%s' was already wrapped,\n", SwigType_namestr(name)); + Swig_warning(WARN_TYPE_REDEFINED, Getfile(cn), Getline(cn), "previous wrap of '%s'.\n", SwigType_namestr(Getattr(cn, "name"))); + scopename = 0; + } + } else { + Swig_symbol_cadd(fname, n); + SwigType_typedef_class(fname); + scopename = Copy(fname); + } + } else { + if ((CPlusPlus) || (unnamed)) { + SwigType_typedef_class(name); + } else { + SwigType_typedef_class(NewStringf("%s %s", kind, name)); + } + scopename = Copy(name); + } + } else { + scopename = 0; + } + + Setattr(n, "typepass:visit", "1"); + + /* Need to set up a typedef if unnamed */ + if (unnamed && tdname && (Cmp(storage, "typedef") == 0)) { + SwigType_typedef(unnamed, tdname); + } + + if (nsname) { + nname = NewStringf("%s::%s", nsname, name); + String *tdname = Getattr(n, "tdname"); + if (tdname) { + tdname = NewStringf("%s::%s", nsname, tdname); + Setattr(n, "tdname", tdname); + } + } + SwigType_new_scope(scopename); + SwigType_attach_symtab(Getattr(n, "symtab")); + + /* Inherit type definitions into the class */ + if (name) { + cplus_inherit_types(n, 0, nname ? nname : (fname ? fname : name)); + } + + inclass = n; + symtab = Swig_symbol_setscope(Getattr(n, "symtab")); + emit_children(n); + Swig_symbol_setscope(symtab); + + Hash *ts = SwigType_pop_scope(); + Setattr(n, "typescope", ts); + Delete(ts); + Setattr(n, "module", module); + + /* Normalize deferred types */ + { + normal_node *nn = new normal_node(); + nn->normallist = normalize; + nn->symtab = Getattr(n, "symtab"); + nn->next = patch_list; + nn->typescope = Getattr(n, "typescope"); + patch_list = nn; + } + + normalize = olist; + + inclass = oldinclass; + + /* If in a namespace, patch the class name */ + if (nname) { + Setattr(n, "name", nname); + Delete(nname); + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * namespaceDeclaration() + * ------------------------------------------------------------ */ + + virtual int templateDeclaration(Node *n) { + String *name = Getattr(n, "name"); + String *ttype = Getattr(n, "templatetype"); + if (Strcmp(ttype, "class") == 0) { + String *rname = SwigType_typedef_resolve_all(name); + SwigType_typedef_class(rname); + Delete(rname); + } else if (Strcmp(ttype, "classforward") == 0) { + String *rname = SwigType_typedef_resolve_all(name); + SwigType_typedef_class(rname); + Delete(rname); + /* SwigType_typedef_class(name); */ + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * classforwardDeclaration() + * ------------------------------------------------------------ */ + + virtual int classforwardDeclaration(Node *n) { + + /* Temporary hack. Can't do inside a class because it breaks + C nested structure wrapping */ + + if ((!inclass) || (CPlusPlus)) { + String *name = Getattr(n, "name"); + String *nname; + SwigType_typedef_class(name); + if (nsname) { + nname = NewStringf("%s::%s", nsname, name); + Setattr(n, "name", nname); + } + + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * namespaceDeclaration() + * ------------------------------------------------------------ */ + + virtual int namespaceDeclaration(Node *n) { + Symtab *symtab; + String *name = Getattr(n, "name"); + String *alias = Getattr(n, "alias"); + List *olist = normalize; + normalize = NewList(); + if (alias) { + Typetab *ts = Getattr(n, "typescope"); + if (!ts) { + Node *ns; + /* Create a empty scope for the alias */ + ns = Getattr(n, "namespace"); + if (ns) { + SwigType_scope_alias(name, Getattr(ns, "typescope")); + } + ts = Getattr(ns, "typescope"); + Setattr(n, "typescope", ts); + } + /* Namespace alias */ + return SWIG_OK; + } else { + if (name) { + Node *nn = Swig_symbol_clookup(name, n); + Hash *ts = 0; + if (nn) + ts = Getattr(nn, "typescope"); + if (!ts) { + SwigType_new_scope(name); + SwigType_attach_symtab(Getattr(n, "symtab")); + } else { + SwigType_set_scope(ts); + } + } + String *oldnsname = nsname; + nsname = Swig_symbol_qualified(Getattr(n, "symtab")); + symtab = Swig_symbol_setscope(Getattr(n, "symtab")); + emit_children(n); + Swig_symbol_setscope(symtab); + + if (name) { + Hash *ts = SwigType_pop_scope(); + Setattr(n, "typescope", ts); + Delete(ts); + } + + /* Normalize deferred types */ + { + normal_node *nn = new normal_node(); + nn->normallist = normalize; + nn->symtab = Getattr(n, "symtab"); + nn->next = patch_list; + nn->typescope = Getattr(n, "typescope"); + patch_list = nn; + } + normalize = olist; + + Delete(nsname); + nsname = oldnsname; + return SWIG_OK; + } + } + + /* ------------------------------------------------------------ + * cDeclaration() + * ------------------------------------------------------------ */ + + virtual int cDeclaration(Node *n) { + if (NoExcept) { + Delattr(n, "throws"); + } + + /* Normalize types. */ + SwigType *ty = Getattr(n, "type"); + normalize_type(ty); + SwigType *decl = Getattr(n, "decl"); + if (decl) { + normalize_type(decl); + } + normalize_parms(Getattr(n, "parms")); + normalize_parms(Getattr(n, "throws")); + if (GetFlag(n, "conversion_operator")) { + /* The call to the operator in the generated wrapper must be fully qualified in order to compile */ + SwigType *name = Getattr(n, "name"); + SwigType *qualifiedname = Swig_symbol_string_qualify(name,0); + Clear(name); + Append(name, qualifiedname); + Delete(qualifiedname); + } + + if (checkAttribute(n, "storage", "typedef")) { + String *name = Getattr(n, "name"); + ty = Getattr(n, "type"); + decl = Getattr(n, "decl"); + SwigType *t = Copy(ty); + { + /* If the typename is qualified, make sure the scopename is fully qualified when making a typedef */ + if (Swig_scopename_check(t) && strncmp(Char(t), "::", 2)) { + String *base, *prefix, *qprefix; + base = Swig_scopename_last(t); + prefix = Swig_scopename_prefix(t); + qprefix = SwigType_typedef_qualified(prefix); + Delete(t); + t = NewStringf("%s::%s", qprefix, base); + Delete(base); + Delete(prefix); + Delete(qprefix); + } + } + SwigType_push(t, decl); + if (CPlusPlus) { + Replaceall(t, "struct ", ""); + Replaceall(t, "union ", ""); + Replaceall(t, "class ", ""); + } + SwigType_typedef(t, name); + } + /* If namespaces are active. We need to patch the name with a namespace prefix */ + if (nsname && !inclass) { + String *name = Getattr(n, "name"); + if (name) { + String *nname = NewStringf("%s::%s", nsname, name); + Setattr(n, "name", nname); + Delete(nname); + } + } + clean_overloaded(n); + return SWIG_OK; + } + + + /* ------------------------------------------------------------ + * constructorDeclaration() + * ------------------------------------------------------------ */ + + virtual int constructorDeclaration(Node *n) { + if (NoExcept) { + Delattr(n, "throws"); + } + + normalize_parms(Getattr(n, "parms")); + normalize_parms(Getattr(n, "throws")); + + /* If in a namespace, patch the class name */ + if (nsname) { + String *nname = NewStringf("%s::%s", nsname, Getattr(n, "name")); + Setattr(n, "name", nname); + } + clean_overloaded(n); + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * destructorDeclaration() + * ------------------------------------------------------------ */ + + virtual int destructorDeclaration(Node *n) { + /* If in a namespace, patch the class name */ + if (nsname) { + String *nname = NewStringf("%s::%s", nsname, Getattr(n, "name")); + Setattr(n, "name", nname); + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * constantDirective() + * ------------------------------------------------------------ */ + + virtual int constantDirective(Node *n) { + SwigType *ty = Getattr(n, "type"); + if (ty) { + Setattr(n, "type", SwigType_typedef_qualified(ty)); + } + return SWIG_OK; + } + + + /* ------------------------------------------------------------ + * enumDeclaration() + * ------------------------------------------------------------ */ + + virtual int enumDeclaration(Node *n) { + String *name = Getattr(n, "name"); + + if (name) { + String *scope = 0; + + // Add a typedef to the type table so that we can use 'enum Name' as well as just 'Name' + if (nsname || inclass) { + + // But first correct the name and tdname to contain the fully qualified scopename + if (nsname && inclass) { + scope = NewStringf("%s::%s", nsname, Getattr(inclass, "name")); + } else if (nsname) { + scope = NewStringf("%s", nsname); + } else if (inclass) { + scope = NewStringf("%s", Getattr(inclass, "name")); + } + + String *nname = NewStringf("%s::%s", scope, name); + Setattr(n, "name", nname); + + String *tdname = Getattr(n, "tdname"); + if (tdname) { + tdname = NewStringf("%s::%s", scope, tdname); + Setattr(n, "tdname", tdname); + } + + SwigType *t = NewStringf("enum %s", nname); + SwigType_typedef(t, name); + } else { + SwigType *t = NewStringf("enum %s", name); + SwigType_typedef(t, name); + } + Delete(scope); + } + + String *tdname = Getattr(n, "tdname"); + String *unnamed = Getattr(n, "unnamed"); + String *storage = Getattr(n, "storage"); + + // Construct enumtype - for declaring an enum of this type with SwigType_ltype() etc + String *enumtype = 0; + if (unnamed && tdname && (Cmp(storage, "typedef") == 0)) { + enumtype = Copy(Getattr(n, "tdname")); + } else if (name) { + enumtype = NewStringf("%s%s", CPlusPlus ? "" : "enum ", Getattr(n, "name")); + } else { + // anonymous enums + enumtype = Copy(Getattr(n, "type")); + } + Setattr(n, "enumtype", enumtype); + + // This block of code is for dealing with %ignore on an enum item where the target language + // attempts to use the C enum value in the target language itself and expects the previous enum value + // to be one more than the previous value... the previous enum item might not exist if it is ignored! + // - It sets the first non-ignored enum item with the "firstenumitem" attribute. + // - It adds an enumvalue attribute if the previous enum item is ignored + { + Node *c; + int count = 0; + String *previous = 0; + bool previous_ignored = false; + bool firstenumitem = false; + for (c = firstChild(n); c; c = nextSibling(c)) { + assert(strcmp(Char(nodeType(c)), "enumitem") == 0); + + bool reset; + String *enumvalue = Getattr(c, "enumvalue"); + if (GetFlag(c, "feature:ignore")) { + reset = enumvalue ? true : false; + previous_ignored = true; + } else { + if (!enumvalue && previous_ignored) { + if (previous) + Setattr(c, "enumvalue", NewStringf("(%s) + %d", previous, count+1)); + else + Setattr(c, "enumvalue", NewStringf("%d", count)); + SetFlag(c, "virtenumvalue"); // identify enumvalue as virtual, ie not from the parsed source + } + if (!firstenumitem) { + SetFlag(c, "firstenumitem"); + firstenumitem = true; + } + reset = true; + previous_ignored = false; + } + if (reset) { + previous = enumvalue ? enumvalue : Getattr(c, "name"); + count = 0; + } else { + count++; + } + } + } + + emit_children(n); + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * enumvalueDeclaration() + * ------------------------------------------------------------ */ + + virtual int enumvalueDeclaration(Node *n) { + String *name = Getattr(n, "name"); + String *value = Getattr(n, "value"); + if (!value) + value = name; + if (Strcmp(value, name) == 0) { + String *new_value; + if (((nsname) || (inclass)) && cparse_cplusplus) { + new_value = NewStringf("%s::%s", SwigType_namestr(Swig_symbol_qualified(n)), value); + } else { + new_value = NewString(value); + } + Setattr(n, "value", new_value); + Delete(new_value); + } + Node *next = nextSibling(n); + + // Make up an enumvalue if one was not specified in the parsed code (not designed to be used on enum items and %ignore - enumvalue will be set instead) + if (!GetFlag(n, "feature:ignore")) { + if (Getattr(n, "_last") && !Getattr(n, "enumvalue")) { // Only the first enum item has _last set (Note: first non-ignored enum item has firstenumitem set) + Setattr(n, "enumvalueex", "0"); + } + if (next && !Getattr(next, "enumvalue")) { + Setattr(next, "enumvalueex", NewStringf("%s + 1", Getattr(n, "sym:name"))); + } + } + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * enumforwardDeclaration() + * ------------------------------------------------------------ */ + + virtual int enumforwardDeclaration(Node *n) { + + // Use enumDeclaration() to do all the hard work. + // Note that no children can be emitted in a forward declaration as there aren't any. + return enumDeclaration(n); + } + +#ifdef DEBUG_OVERLOADED + static void show_overloaded(Node *n) { + Node *c = Getattr(n, "sym:overloaded"); + Node *checkoverloaded = c; + Printf(stdout, "-------------------- overloaded start %s sym:overloaded():%p -------------------------------\n", Getattr(n, "name"), c); + while (c) { + if (Getattr(c, "error")) { + c = Getattr(c, "sym:nextSibling"); + continue; + } + if (Getattr(c, "sym:overloaded") != checkoverloaded) { + Printf(stdout, "sym:overloaded error c:%p checkoverloaded:%p\n", c, checkoverloaded); + Swig_print_node(c); + exit (1); + } + + String *decl = Strcmp(nodeType(c), "using") == 0 ? NewString("------") : Getattr(c, "decl"); + Printf(stdout, " show_overloaded %s::%s(%s) [%s] nodeType:%s\n", parentNode(c) ? Getattr(parentNode(c), "name") : "NOPARENT", Getattr(c, "name"), decl, Getattr(c, "sym:overname"), nodeType(c)); + if (!Getattr(c, "sym:overloaded")) { + Printf(stdout, "sym:overloaded error.....%p\n", c); + Swig_print_node(c); + exit (1); + } + c = Getattr(c, "sym:nextSibling"); + } + Printf(stdout, "-------------------- overloaded end %s -------------------------------\n", Getattr(n, "name")); + } +#endif + + /* ------------------------------------------------------------ + * usingDeclaration() + * ------------------------------------------------------------ */ + + virtual int usingDeclaration(Node *n) { + if (Getattr(n, "namespace")) { + /* using namespace id */ + + /* For a namespace import. We set up inheritance in the type system */ + Node *ns = Getattr(n, "node"); + if (ns) { + Typetab *ts = Getattr(ns, "typescope"); + if (ts) { + SwigType_using_scope(ts); + } + } + return SWIG_OK; + } else { + Node *ns; + /* using id */ + Symtab *stab = Getattr(n, "sym:symtab"); + if (stab) { + String *uname = Getattr(n, "uname"); + ns = Swig_symbol_clookup(uname, stab); + if (!ns && SwigType_istemplate(uname)) { + String *tmp = Swig_symbol_template_deftype(uname, 0); + if (!Equal(tmp, uname)) { + ns = Swig_symbol_clookup(tmp, stab); + } + Delete(tmp); + } + } else { + ns = 0; + } + if (!ns) { + if (is_public(n)) { + Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(n), Getline(n), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(n, "uname"))); + } + } else { + /* Only a single symbol is being used. There are only a few symbols that + we actually care about. These are typedef, class declarations, and enum */ + String *ntype = nodeType(ns); + if (Strcmp(ntype, "cdecl") == 0) { + if (checkAttribute(ns, "storage", "typedef")) { + /* A typedef declaration */ + String *uname = Getattr(n, "uname"); + SwigType_typedef_using(uname); + } else { + /* A normal C declaration. */ + if ((inclass) && (!GetFlag(n, "feature:ignore")) && (Getattr(n, "sym:name"))) { + Node *c = ns; + Node *unodes = 0, *last_unodes = 0; + int ccount = 0; + String *symname = Getattr(n, "sym:name"); + while (c) { + if (Strcmp(nodeType(c), "cdecl") == 0) { + if (!(checkAttribute(c, "storage", "static") + || checkAttribute(c, "storage", "typedef") + || checkAttribute(c, "storage", "friend") + || (Getattr(c, "feature:extend") && !Getattr(c, "code")) + || GetFlag(c, "feature:ignore"))) { + + /* Don't generate a method if the method is overridden in this class, + * for example don't generate another m(bool) should there be a Base::m(bool) : + * struct Derived : Base { + * void m(bool); + * using Base::m; + * }; + */ + String *csymname = Getattr(c, "sym:name"); + if (!csymname || (Strcmp(csymname, symname) == 0)) { + { + String *decl = Getattr(c, "decl"); + Node *over = Getattr(n, "sym:overloaded"); + int match = 0; + while (over) { + String *odecl = Getattr(over, "decl"); + if (Cmp(decl, odecl) == 0) { + match = 1; + break; + } + over = Getattr(over, "sym:nextSibling"); + } + if (match) { + c = Getattr(c, "csym:nextSibling"); + continue; + } + } + Node *nn = copyNode(c); + Delattr(nn, "access"); // access might be different from the method in the base class + if (!Getattr(nn, "sym:name")) + Setattr(nn, "sym:name", symname); + + if (!GetFlag(nn, "feature:ignore")) { + ParmList *parms = CopyParmList(Getattr(c, "parms")); + int is_pointer = SwigType_ispointer_return(Getattr(nn, "decl")); + int is_void = checkAttribute(nn, "type", "void") && !is_pointer; + Setattr(nn, "parms", parms); + Delete(parms); + if (Getattr(n, "feature:extend")) { + String *ucode = is_void ? NewStringf("{ self->%s(", Getattr(n, "uname")) : NewStringf("{ return self->%s(", Getattr(n, "uname")); + + for (ParmList *p = parms; p;) { + Append(ucode, Getattr(p, "name")); + p = nextSibling(p); + if (p) + Append(ucode, ","); + } + Append(ucode, "); }"); + Setattr(nn, "code", ucode); + Delete(ucode); + } + ParmList *throw_parm_list = Getattr(c, "throws"); + if (throw_parm_list) + Setattr(nn, "throws", CopyParmList(throw_parm_list)); + ccount++; + if (!last_unodes) { + last_unodes = nn; + unodes = nn; + } else { + Setattr(nn, "previousSibling", last_unodes); + Setattr(last_unodes, "nextSibling", nn); + Setattr(nn, "sym:previousSibling", last_unodes); + Setattr(last_unodes, "sym:nextSibling", nn); + Setattr(nn, "sym:overloaded", unodes); + Setattr(unodes, "sym:overloaded", unodes); + last_unodes = nn; + } + } else { + Delete(nn); + } + } + } + } + c = Getattr(c, "csym:nextSibling"); + } + if (unodes) { + set_firstChild(n, unodes); + if (ccount > 1) { + if (!Getattr(n, "sym:overloaded")) { + Setattr(n, "sym:overloaded", n); + Setattr(n, "sym:overname", "_SWIG_0"); + } + } + } + + /* Hack the parse tree symbol table for overloaded methods. Replace the "using" node with the + * list of overloaded methods we have just added in as child nodes to the "using" node. + * The node will still exist, it is just the symbol table linked list of overloaded methods + * which is hacked. */ + if (Getattr(n, "sym:overloaded")) + { +#ifdef DEBUG_OVERLOADED +show_overloaded(n); +#endif + int cnt = 0; + Node *debugnode = n; + if (!firstChild(n)) { + // Remove from overloaded list ('using' node does not actually end up adding in any methods) + Node *ps = Getattr(n, "sym:previousSibling"); + Node *ns = Getattr(n, "sym:nextSibling"); + if (ps) { + Setattr(ps, "sym:nextSibling", ns); + } + if (ns) { + Setattr(ns, "sym:previousSibling", ps); + } + } else { + // The 'using' node results in methods being added in - slot in the these methods here + Node *ps = Getattr(n, "sym:previousSibling"); + Node *ns = Getattr(n, "sym:nextSibling"); + Node *fc = firstChild(n); + Node *pp = fc; + + Node *firstoverloaded = Getattr(n, "sym:overloaded"); + if (firstoverloaded == n) { + // This 'using' node we are cutting out was the first node in the overloaded list. + // Change the first node in the list to its first sibling + Delattr(firstoverloaded, "sym:overloaded"); + Node *nnn = Getattr(firstoverloaded, "sym:nextSibling"); + firstoverloaded = fc; + while (nnn) { + Setattr(nnn, "sym:overloaded", firstoverloaded); + nnn = Getattr(nnn, "sym:nextSibling"); + } + } + while (pp) { + Node *ppn = Getattr(pp, "sym:nextSibling"); + Setattr(pp, "sym:overloaded", firstoverloaded); + Setattr(pp, "sym:overname", NewStringf("%s_%d", Getattr(n, "sym:overname"), cnt++)); + if (ppn) + pp = ppn; + else + break; + } + if (ps) { + Setattr(ps, "sym:nextSibling", fc); + Setattr(fc, "sym:previousSibling", ps); + } + if (ns) { + Setattr(ns, "sym:previousSibling", pp); + Setattr(pp, "sym:nextSibling", ns); + } + debugnode = firstoverloaded; + } + Delattr(n, "sym:previousSibling"); + Delattr(n, "sym:nextSibling"); + Delattr(n, "sym:overloaded"); + Delattr(n, "sym:overname"); +#ifdef DEBUG_OVERLOADED +show_overloaded(debugnode); +#endif + clean_overloaded(n); // Needed? + } + } + } + } else if ((Strcmp(ntype, "class") == 0) || ((Strcmp(ntype, "classforward") == 0))) { + /* We install the using class name as kind of a typedef back to the original class */ + String *uname = Getattr(n, "uname"); + /* Import into current type scope */ + SwigType_typedef_using(uname); + } else if (Strcmp(ntype, "enum") == 0) { + SwigType_typedef_using(Getattr(n, "uname")); + } + } + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * typemapDirective() + * ------------------------------------------------------------ */ + + virtual int typemapDirective(Node *n) { + if (inclass || nsname) { + Node *items = firstChild(n); + while (items) { + Parm *pattern = Getattr(items, "pattern"); + Parm *parms = Getattr(items, "parms"); + normalize_later(pattern); + normalize_later(parms); + items = nextSibling(items); + } + } + return SWIG_OK; + } + + + /* ------------------------------------------------------------ + * typemapcopyDirective() + * ------------------------------------------------------------ */ + + virtual int typemapcopyDirective(Node *n) { + if (inclass || nsname) { + Node *items = firstChild(n); + ParmList *pattern = Getattr(n, "pattern"); + normalize_later(pattern); + while (items) { + ParmList *npattern = Getattr(items, "pattern"); + normalize_later(npattern); + items = nextSibling(items); + } + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * applyDirective() + * ------------------------------------------------------------ */ + + virtual int applyDirective(Node *n) { + if (inclass || nsname) { + ParmList *pattern = Getattr(n, "pattern"); + normalize_later(pattern); + Node *items = firstChild(n); + while (items) { + Parm *apattern = Getattr(items, "pattern"); + normalize_later(apattern); + items = nextSibling(items); + } + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * clearDirective() + * ------------------------------------------------------------ */ + + virtual int clearDirective(Node *n) { + if (inclass || nsname) { + Node *p; + for (p = firstChild(n); p; p = nextSibling(p)) { + ParmList *pattern = Getattr(p, "pattern"); + normalize_later(pattern); + } + } + return SWIG_OK; + } + +public: + static void pass(Node *n) { + TypePass t; + t.top(n); + } +}; + +void Swig_process_types(Node *n) { + if (!n) + return; + TypePass::pass(n); +} |
