* templates-scope-enforcement: Test a few %template errors Add using declarations to templates into typedef table. Fix type lookup in the presence of using directives and using declarations More docs on %template Testcase fix for nameclash in php %template scope enforcement and class definition fixes Template documentation tweaks More consistent formatting of examples in documentation More consistent formatting of examples in documentation Documentation corrections to use targetlang formatting More consistent formatting of examples in documentation More consistent formatting of examples in documentation More consistent formatting of examples in documentation Namespace documentation minor corrections Improve description of template_parameters_resolve Minor code optimisation in template_parameters_resolve Fix scope lookup for template parameters containing unary scope operators Typemap change for templates
1295 lines
41 KiB
C++
1295 lines
41 KiB
C++
/* -----------------------------------------------------------------------------
|
|
* This file is part of SWIG, which is licensed as a whole under version 3
|
|
* (or any later version) of the GNU General Public License. Some additional
|
|
* terms also apply to certain portions of SWIG. The full details of the SWIG
|
|
* license and copyrights can be found in the LICENSE and COPYRIGHT files
|
|
* included with the SWIG source code as distributed by the SWIG developers
|
|
* and at http://www.swig.org/legal.html.
|
|
*
|
|
* 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.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
#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;
|
|
String *nssymname;
|
|
Hash *classhash;
|
|
List *normalize;
|
|
|
|
TypePass() :
|
|
inclass(0),
|
|
module(0),
|
|
importmode(0),
|
|
nsname(0),
|
|
nssymname(0),
|
|
classhash(0),
|
|
normalize(0) {
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
// A case when both outer and nested classes inherit from the same parent. Constructor may be found instead of the class itself.
|
|
} else if (GetFlag(cls, "nested") && checkAttribute(bcls, "nodeType", "constructor")) {
|
|
bcls = Getattr(bcls, "parentNode");
|
|
if (Getattr(bcls, "typepass:visit")) {
|
|
if (!Getattr(bcls, "feature:onlychildren")) {
|
|
if (!ilist)
|
|
ilist = alist = NewList();
|
|
Append(ilist, bcls);
|
|
} else {
|
|
if (!GetFlag(bcls, "feature:ignore")) {
|
|
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname));
|
|
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname));
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
if (Strcmp(nodeType(bcls), "classforward") != 0) {
|
|
Swig_error(Getfile(bname), Getline(bname), "'%s' is not a valid base class.\n", SwigType_namestr(bname));
|
|
Swig_error(Getfile(bcls), Getline(bcls), "See definition of '%s'.\n", SwigType_namestr(bname));
|
|
} else {
|
|
Swig_warning(WARN_TYPE_INCOMPLETE, Getfile(bname), Getline(bname), "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 (!Getattr(bcls, "feature:onlychildren")) {
|
|
if (!ilist)
|
|
ilist = alist = NewList();
|
|
Append(ilist, bcls);
|
|
} else {
|
|
if (!GetFlag(bcls, "feature:ignore")) {
|
|
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname));
|
|
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname));
|
|
}
|
|
}
|
|
} else {
|
|
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "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 && !GetFlag(cls, "feature:ignore")) {
|
|
if (ispublic && !Getmeta(bname, "already_warned")) {
|
|
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Nothing known about base class '%s'. Ignored.\n", SwigType_namestr(bname));
|
|
if (Strchr(bname, '<')) {
|
|
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "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 (ispublic && !GetFlag(bclass, "feature:ignore")) {
|
|
String *smartptr = Getattr(first, "feature:smartptr");
|
|
if (smartptr) {
|
|
SwigType *smart = Swig_cparse_smartptr(first);
|
|
if (smart) {
|
|
/* Record a (fake) inheritance relationship between smart pointer
|
|
and smart pointer to base class, so that smart pointer upcasts
|
|
are automatically generated. */
|
|
SwigType *bsmart = Copy(smart);
|
|
SwigType *rclsname = SwigType_typedef_resolve_all(clsname);
|
|
SwigType *rbname = SwigType_typedef_resolve_all(bname);
|
|
int replace_count = Replaceall(bsmart, rclsname, rbname);
|
|
if (replace_count == 0) {
|
|
// If no replacement made, it will be because rclsname is fully resolved, but the
|
|
// type in the smartptr feature used a typedef or not fully resolved name.
|
|
String *firstname = Getattr(first, "name");
|
|
Replaceall(bsmart, firstname, rbname);
|
|
}
|
|
Delete(rclsname);
|
|
Delete(rbname);
|
|
String *smartnamestr = SwigType_namestr(smart);
|
|
String *bsmartnamestr = SwigType_namestr(bsmart);
|
|
/* construct casting code */
|
|
String *convcode = NewStringf("\n *newmemory = SWIG_CAST_NEW_MEMORY;\n return (void *) new %s(*(%s *)$from);\n", bsmartnamestr, smartnamestr);
|
|
Delete(bsmartnamestr);
|
|
Delete(smartnamestr);
|
|
/* setup inheritance relationship between smart pointer templates */
|
|
SwigType_inherit(smart, bsmart, 0, convcode);
|
|
if (!GetFlag(bclass, "feature:smartptr"))
|
|
Swig_warning(WARN_LANG_SMARTPTR_MISSING, Getfile(first), Getline(first), "Base class '%s' of '%s' is not similarly marked as a smart pointer.\n", SwigType_namestr(Getattr(bclass, "name")), SwigType_namestr(Getattr(first, "name")));
|
|
Delete(convcode);
|
|
Delete(bsmart);
|
|
}
|
|
Delete(smart);
|
|
} else {
|
|
if (GetFlag(bclass, "feature:smartptr"))
|
|
Swig_warning(WARN_LANG_SMARTPTR_MISSING, Getfile(first), Getline(first), "Derived class '%s' of '%s' is not similarly marked as a smart pointer.\n", SwigType_namestr(Getattr(first, "name")), SwigType_namestr(Getattr(bclass, "name")));
|
|
}
|
|
}
|
|
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", SwigType_namestr(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;
|
|
nssymname = 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");
|
|
save_value<Node*> oldinclass(inclass);
|
|
List *olist = normalize;
|
|
Symtab *symtab;
|
|
String *nname = 0;
|
|
String *fname = 0;
|
|
String *scopename = 0;
|
|
String *template_default_expanded = 0;
|
|
|
|
normalize = NewList();
|
|
|
|
if (name) {
|
|
if (SwigType_istemplate(name)) {
|
|
// We need to fully resolve the name and expand default template parameters to make templates work correctly */
|
|
Node *cn;
|
|
SwigType *resolved_name = SwigType_typedef_resolve_all(name);
|
|
SwigType *deftype_name = Swig_symbol_template_deftype(resolved_name, 0);
|
|
fname = Copy(resolved_name);
|
|
if (!Equal(resolved_name, deftype_name))
|
|
template_default_expanded = Copy(deftype_name);
|
|
if (!Equal(fname, name) && (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);
|
|
if (template_default_expanded)
|
|
Swig_symbol_cadd(template_default_expanded, 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);
|
|
}
|
|
Delete(deftype_name);
|
|
Delete(resolved_name);
|
|
} 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);
|
|
}
|
|
// name of the outer class should already be patched to contain its outer classes names, but not to contain namespaces
|
|
// namespace name (if present) is added after processing child nodes
|
|
if (Getattr(n, "nested:outer") && name) {
|
|
String *outerName = Getattr(Getattr(n, "nested:outer"), "name");
|
|
name = NewStringf("%s::%s", outerName, name);
|
|
Setattr(n, "name", name);
|
|
if (tdname) {
|
|
tdname = NewStringf("%s::%s", outerName, tdname);
|
|
Setattr(n, "tdname", tdname);
|
|
}
|
|
}
|
|
|
|
if (nsname && name) {
|
|
nname = NewStringf("%s::%s", nsname, name);
|
|
String *tdname = Getattr(n, "tdname");
|
|
if (tdname) {
|
|
tdname = NewStringf("%s::%s", nsname, tdname);
|
|
Setattr(n, "tdname", tdname);
|
|
}
|
|
}
|
|
if (nssymname) {
|
|
if (GetFlag(n, "feature:nspace"))
|
|
Setattr(n, "sym:nspace", nssymname);
|
|
}
|
|
SwigType_new_scope(scopename);
|
|
SwigType_attach_symtab(Getattr(n, "symtab"));
|
|
|
|
/* Inherit type definitions into the class */
|
|
if (name && !(GetFlag(n, "nested") && !checkAttribute(n, "access", "public") &&
|
|
(GetFlag(n, "feature:flatnested") || Language::instance()->nestedClassesSupport() == Language::NCS_None))) {
|
|
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);
|
|
|
|
// When a fully qualified templated type with default parameters is used in the parsed code,
|
|
// the following additional symbols and scopes are needed for successful lookups
|
|
if (template_default_expanded) {
|
|
Swig_symbol_alias(template_default_expanded, Getattr(n, "symtab"));
|
|
SwigType_scope_alias(template_default_expanded, Getattr(n, "typescope"));
|
|
}
|
|
|
|
/* 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;
|
|
|
|
/* If in a namespace, patch the class name */
|
|
if (nname) {
|
|
Setattr(n, "name", nname);
|
|
Delete(nname);
|
|
}
|
|
Delete(fname);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* ------------------------------------------------------------
|
|
* templateDeclaration()
|
|
* ------------------------------------------------------------ */
|
|
|
|
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); */
|
|
} else if (Strcmp(ttype, "cdecl") == 0) {
|
|
String *rname = SwigType_typedef_resolve_all(name);
|
|
SwigType_typedef_class(rname);
|
|
Delete(rname);
|
|
}
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* ------------------------------------------------------------
|
|
* lambdaDeclaration()
|
|
* ------------------------------------------------------------ */
|
|
|
|
virtual int lambdaDeclaration(Node *) {
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* ------------------------------------------------------------
|
|
* classforwardDeclaration()
|
|
* ------------------------------------------------------------ */
|
|
|
|
virtual int classforwardDeclaration(Node *n) {
|
|
|
|
/* Can't do inside a C struct because it breaks C nested structure wrapping */
|
|
if ((!inclass) || (CPlusPlus)) {
|
|
String *name = Getattr(n, "name");
|
|
SwigType_typedef_class(name);
|
|
}
|
|
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) {
|
|
/* Create an empty scope for the alias */
|
|
Node *ns = Getattr(n, "namespace");
|
|
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;
|
|
String *oldnssymname = nssymname;
|
|
nsname = Swig_symbol_qualified(Getattr(n, "symtab"));
|
|
nssymname = Swig_symbol_qualified_language_scopename(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(nssymname);
|
|
nssymname = oldnssymname;
|
|
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");
|
|
if (!ty) {
|
|
return SWIG_OK;
|
|
}
|
|
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"));
|
|
|
|
clean_overloaded(n);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* ------------------------------------------------------------
|
|
* destructorDeclaration()
|
|
* ------------------------------------------------------------ */
|
|
|
|
virtual int destructorDeclaration(Node *) {
|
|
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);
|
|
|
|
if (nssymname) {
|
|
if (GetFlag(n, "feature:nspace"))
|
|
Setattr(n, "sym:nspace", nssymname);
|
|
}
|
|
|
|
// 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") || !Getattr(c, "sym:name")) {
|
|
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");
|
|
String *scopedenum = Getattr(parentNode(n), "scopedenum");
|
|
if (!value)
|
|
value = name;
|
|
if (Strcmp(value, name) == 0) {
|
|
String *new_value;
|
|
if ((nsname || inclass || scopedenum) && cparse_cplusplus) {
|
|
new_value = NewStringf("%s::%s", SwigType_namestr(Swig_symbol_qualified(n)), value);
|
|
} else {
|
|
new_value = NewString(value);
|
|
}
|
|
if ((nsname || inclass || scopedenum) && !cparse_cplusplus) {
|
|
String *cppvalue = NewStringf("%s::%s", SwigType_namestr(Swig_symbol_qualified(n)), value);
|
|
Setattr(n, "cppvalue", cppvalue); /* for target languages that always generate C++ code even when wrapping C code */
|
|
}
|
|
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.
|
|
int result = enumDeclaration(n);
|
|
if (result == SWIG_OK) {
|
|
// Detect when the real enum matching the forward enum declaration has not been parsed/declared
|
|
SwigType *ty = SwigType_typedef_resolve_all(Getattr(n, "type"));
|
|
Replaceall(ty, "enum ", "");
|
|
Node *nn = Swig_symbol_clookup(ty, 0);
|
|
|
|
String *nodetype = nn ? nodeType(nn) : 0;
|
|
if (nodetype) {
|
|
if (Equal(nodetype, "enumforward")) {
|
|
SetFlag(nn, "enumMissing");
|
|
} // if a real enum was declared this would be an "enum" node type
|
|
}
|
|
Delete(ty);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
#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 (!(Swig_storage_isstatic(c)
|
|
|| 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
|
|
Setattr(nn, "access", Getattr(n, "access"));
|
|
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")) {
|
|
int cnt = 0;
|
|
#ifdef DEBUG_OVERLOADED
|
|
Node *debugnode = n;
|
|
show_overloaded(n);
|
|
#endif
|
|
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);
|
|
}
|
|
#ifdef DEBUG_OVERLOADED
|
|
debugnode = firstoverloaded;
|
|
#endif
|
|
}
|
|
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"));
|
|
} else if (Strcmp(ntype, "template") == 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);
|
|
}
|
|
|