/* ----------------------------------------------------------------------------- * 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. * * extend.c * * Extensions support (%extend) * ----------------------------------------------------------------------------- */ #include "swig.h" #include "cparse.h" static Hash *extendhash = 0; /* Hash table of added methods */ /* ----------------------------------------------------------------------------- * Swig_extend_hash() * * Access the extend hash * ----------------------------------------------------------------------------- */ Hash *Swig_extend_hash(void) { if (!extendhash) extendhash = NewHash(); return extendhash; } /* ----------------------------------------------------------------------------- * Swig_extend_merge() * * Extension merge. This function is used to handle the %extend directive * when it appears before a class definition. To handle this, the %extend * actually needs to take precedence. Therefore, we will selectively nuke symbols * from the current symbol table, replacing them with the added methods. * ----------------------------------------------------------------------------- */ void Swig_extend_merge(Node *cls, Node *am) { Node *n; Node *csym; n = firstChild(am); while (n) { String *symname; if (Strcmp(nodeType(n),"constructor") == 0) { symname = Getattr(n,"sym:name"); if (symname) { if (Strcmp(symname,Getattr(n,"name")) == 0) { /* If the name and the sym:name of a constructor are the same, then it hasn't been renamed. However---the name of the class itself might have been renamed so we need to do a consistency check here */ if (Getattr(cls,"sym:name")) { Setattr(n,"sym:name", Getattr(cls,"sym:name")); } } } } symname = Getattr(n,"sym:name"); DohIncref(symname); if ((symname) && (!Getattr(n,"error"))) { /* Remove node from its symbol table */ Swig_symbol_remove(n); csym = Swig_symbol_add(symname,n); if (csym != n) { /* Conflict with previous definition. Nuke previous definition */ String *e = NewStringEmpty(); String *en = NewStringEmpty(); String *ec = NewStringEmpty(); Printf(ec,"Identifier '%s' redefined by %%extend (ignored),",symname); Printf(en,"%%extend definition of '%s'.",symname); SWIG_WARN_NODE_BEGIN(n); Swig_warning(WARN_PARSE_REDEFINED,Getfile(csym),Getline(csym),"%s\n",ec); Swig_warning(WARN_PARSE_REDEFINED,Getfile(n),Getline(n),"%s\n",en); SWIG_WARN_NODE_END(n); Printf(e,"%s:%d:%s\n%s:%d:%s\n",Getfile(csym),Getline(csym),ec, Getfile(n),Getline(n),en); Setattr(csym,"error",e); Delete(e); Delete(en); Delete(ec); Swig_symbol_remove(csym); /* Remove class definition */ Swig_symbol_add(symname,n); /* Insert extend definition */ } } n = nextSibling(n); } } /* ----------------------------------------------------------------------------- * Swig_extend_append_previous() * ----------------------------------------------------------------------------- */ void Swig_extend_append_previous(Node *cls, Node *am) { Node *n, *ne; Node *pe = 0; Node *ae = 0; if (!am) return; n = firstChild(am); while (n) { ne = nextSibling(n); set_nextSibling(n,0); /* typemaps and fragments need to be prepended */ if (((Cmp(nodeType(n),"typemap") == 0) || (Cmp(nodeType(n),"fragment") == 0))) { if (!pe) pe = Swig_cparse_new_node("extend"); appendChild(pe, n); } else { if (!ae) ae = Swig_cparse_new_node("extend"); appendChild(ae, n); } n = ne; } if (pe) prependChild(cls,pe); if (ae) appendChild(cls,ae); } /* ----------------------------------------------------------------------------- * Swig_extend_unused_check() * * Check for unused %extend. Special case, don't report unused * extensions for templates * ----------------------------------------------------------------------------- */ void Swig_extend_unused_check(void) { Iterator ki; if (!extendhash) return; for (ki = First(extendhash); ki.key; ki = Next(ki)) { if (!Strchr(ki.key,'<')) { SWIG_WARN_NODE_BEGIN(ki.item); Swig_warning(WARN_PARSE_EXTEND_UNDEF,Getfile(ki.item), Getline(ki.item), "%%extend defined for an undeclared class %s.\n", SwigType_namestr(ki.key)); SWIG_WARN_NODE_END(ki.item); } } }