/* ----------------------------------------------------------------------------- * 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. * * naming.c * * Functions for generating various kinds of names during code generation. * * Swig_name_register is used to register a format string for generating names. * The format string makes use of the following format specifiers: * * %c - class name is substituted * %f - function name is substituted * %m - member name is substituted * %n - namespace is substituted * %v - variable name is substituted * ----------------------------------------------------------------------------- */ char cvsroot_naming_c[] = "$Id: naming.c 12655 2011-05-05 06:23:02Z wsfulton $"; #include "swig.h" #include "cparse.h" #include /* Hash table containing naming data */ static Hash *naming_hash = 0; #if 0 #define SWIG_DEBUG #endif /* ----------------------------------------------------------------------------- * Swig_name_register() * * Register a new naming format. * ----------------------------------------------------------------------------- */ void Swig_name_register(const_String_or_char_ptr method, const_String_or_char_ptr format) { if (!naming_hash) naming_hash = NewHash(); Setattr(naming_hash, method, format); } void Swig_name_unregister(const_String_or_char_ptr method) { if (naming_hash) { Delattr(naming_hash, method); } } static int name_mangle(String *r) { char *c; int special; special = 0; Replaceall(r, "::", "_"); c = Char(r); while (*c) { if (!isalnum((int) *c) && (*c != '_')) { special = 1; switch (*c) { case '+': *c = 'a'; break; case '-': *c = 's'; break; case '*': *c = 'm'; break; case '/': *c = 'd'; break; case '<': *c = 'l'; break; case '>': *c = 'g'; break; case '=': *c = 'e'; break; case ',': *c = 'c'; break; case '(': *c = 'p'; break; case ')': *c = 'P'; break; case '[': *c = 'b'; break; case ']': *c = 'B'; break; case '^': *c = 'x'; break; case '&': *c = 'A'; break; case '|': *c = 'o'; break; case '~': *c = 'n'; break; case '!': *c = 'N'; break; case '%': *c = 'M'; break; case '.': *c = 'f'; break; case '?': *c = 'q'; break; default: *c = '_'; break; } } c++; } if (special) Append(r, "___"); return special; } /* ----------------------------------------------------------------------------- * replace_nspace() * * Mangles in the namespace from nspace by replacing %n in name if nspace feature required. * ----------------------------------------------------------------------------- */ static void replace_nspace(String *name, const_String_or_char_ptr nspace) { if (nspace) { String *namspace = NewStringf("%s_", nspace); Replaceall(namspace, NSPACE_SEPARATOR, "_"); Replace(name, "%n", namspace, DOH_REPLACE_ANY); Delete(namspace); } else { Replace(name, "%n", "", DOH_REPLACE_ANY); } } /* ----------------------------------------------------------------------------- * Swig_name_mangle() * * Converts all of the non-identifier characters of a string to underscores. * ----------------------------------------------------------------------------- */ String *Swig_name_mangle(const_String_or_char_ptr s) { #if 0 String *r = NewString(s); name_mangle(r); return r; #else return Swig_string_mangle(s); #endif } /* ----------------------------------------------------------------------------- * Swig_name_wrapper() * * Returns the name of a wrapper function. * ----------------------------------------------------------------------------- */ String *Swig_name_wrapper(const_String_or_char_ptr fname) { String *r; String *f; r = NewStringEmpty(); if (!naming_hash) naming_hash = NewHash(); f = Getattr(naming_hash, "wrapper"); if (!f) { Append(r, "_wrap_%f"); } else { Append(r, f); } Replace(r, "%f", fname, DOH_REPLACE_ANY); name_mangle(r); return r; } /* ----------------------------------------------------------------------------- * Swig_name_member() * * Returns the name of a class method. * ----------------------------------------------------------------------------- */ String *Swig_name_member(const_String_or_char_ptr nspace, const_String_or_char_ptr classname, const_String_or_char_ptr membername) { String *r; String *f; String *rclassname; char *cname; rclassname = SwigType_namestr(classname); r = NewStringEmpty(); if (!naming_hash) naming_hash = NewHash(); f = Getattr(naming_hash, "member"); if (!f) { Append(r, "%n%c_%m"); } else { Append(r, f); } cname = Char(rclassname); if ((strncmp(cname, "struct ", 7) == 0) || ((strncmp(cname, "class ", 6) == 0)) || ((strncmp(cname, "union ", 6) == 0))) { cname = strchr(cname, ' ') + 1; } replace_nspace(r, nspace); Replace(r, "%c", cname, DOH_REPLACE_ANY); Replace(r, "%m", membername, DOH_REPLACE_ANY); /* name_mangle(r); */ Delete(rclassname); return r; } /* ----------------------------------------------------------------------------- * Swig_name_get() * * Returns the name of the accessor function used to get a variable. * ----------------------------------------------------------------------------- */ String *Swig_name_get(const_String_or_char_ptr nspace, const_String_or_char_ptr vname) { String *r; String *f; #ifdef SWIG_DEBUG Printf(stdout, "Swig_name_get: '%s'\n", vname); #endif r = NewStringEmpty(); if (!naming_hash) naming_hash = NewHash(); f = Getattr(naming_hash, "get"); if (!f) { Append(r, "%n%v_get"); } else { Append(r, f); } replace_nspace(r, nspace); Replace(r, "%v", vname, DOH_REPLACE_ANY); /* name_mangle(r); */ return r; } /* ----------------------------------------------------------------------------- * Swig_name_set() * * Returns the name of the accessor function used to set a variable. * ----------------------------------------------------------------------------- */ String *Swig_name_set(const_String_or_char_ptr nspace, const_String_or_char_ptr vname) { String *r; String *f; r = NewStringEmpty(); if (!naming_hash) naming_hash = NewHash(); f = Getattr(naming_hash, "set"); if (!f) { Append(r, "%n%v_set"); } else { Append(r, f); } replace_nspace(r, nspace); Replace(r, "%v", vname, DOH_REPLACE_ANY); /* name_mangle(r); */ return r; } /* ----------------------------------------------------------------------------- * Swig_name_construct() * * Returns the name of the accessor function used to create an object. * ----------------------------------------------------------------------------- */ String *Swig_name_construct(const_String_or_char_ptr nspace, const_String_or_char_ptr classname) { String *r; String *f; String *rclassname; char *cname; rclassname = SwigType_namestr(classname); r = NewStringEmpty(); if (!naming_hash) naming_hash = NewHash(); f = Getattr(naming_hash, "construct"); if (!f) { Append(r, "new_%n%c"); } else { Append(r, f); } cname = Char(rclassname); if ((strncmp(cname, "struct ", 7) == 0) || ((strncmp(cname, "class ", 6) == 0)) || ((strncmp(cname, "union ", 6) == 0))) { cname = strchr(cname, ' ') + 1; } replace_nspace(r, nspace); Replace(r, "%c", cname, DOH_REPLACE_ANY); Delete(rclassname); return r; } /* ----------------------------------------------------------------------------- * Swig_name_copyconstructor() * * Returns the name of the accessor function used to copy an object. * ----------------------------------------------------------------------------- */ String *Swig_name_copyconstructor(const_String_or_char_ptr nspace, const_String_or_char_ptr classname) { String *r; String *f; String *rclassname; char *cname; rclassname = SwigType_namestr(classname); r = NewStringEmpty(); if (!naming_hash) naming_hash = NewHash(); f = Getattr(naming_hash, "copy"); if (!f) { Append(r, "copy_%n%c"); } else { Append(r, f); } cname = Char(rclassname); if ((strncmp(cname, "struct ", 7) == 0) || ((strncmp(cname, "class ", 6) == 0)) || ((strncmp(cname, "union ", 6) == 0))) { cname = strchr(cname, ' ') + 1; } replace_nspace(r, nspace); Replace(r, "%c", cname, DOH_REPLACE_ANY); Delete(rclassname); return r; } /* ----------------------------------------------------------------------------- * Swig_name_destroy() * * Returns the name of the accessor function used to destroy an object. * ----------------------------------------------------------------------------- */ String *Swig_name_destroy(const_String_or_char_ptr nspace, const_String_or_char_ptr classname) { String *r; String *f; String *rclassname; char *cname; rclassname = SwigType_namestr(classname); r = NewStringEmpty(); if (!naming_hash) naming_hash = NewHash(); f = Getattr(naming_hash, "destroy"); if (!f) { Append(r, "delete_%n%c"); } else { Append(r, f); } cname = Char(rclassname); if ((strncmp(cname, "struct ", 7) == 0) || ((strncmp(cname, "class ", 6) == 0)) || ((strncmp(cname, "union ", 6) == 0))) { cname = strchr(cname, ' ') + 1; } replace_nspace(r, nspace); Replace(r, "%c", cname, DOH_REPLACE_ANY); Delete(rclassname); return r; } /* ----------------------------------------------------------------------------- * Swig_name_disown() * * Returns the name of the accessor function used to disown an object. * ----------------------------------------------------------------------------- */ String *Swig_name_disown(const_String_or_char_ptr nspace, const_String_or_char_ptr classname) { String *r; String *f; String *rclassname; char *cname; rclassname = SwigType_namestr(classname); r = NewStringEmpty(); if (!naming_hash) naming_hash = NewHash(); f = Getattr(naming_hash, "disown"); if (!f) { Append(r, "disown_%n%c"); } else { Append(r, f); } cname = Char(rclassname); if ((strncmp(cname, "struct ", 7) == 0) || ((strncmp(cname, "class ", 6) == 0)) || ((strncmp(cname, "union ", 6) == 0))) { cname = strchr(cname, ' ') + 1; } replace_nspace(r, nspace); Replace(r, "%c", cname, DOH_REPLACE_ANY); Delete(rclassname); return r; } /* ----------------------------------------------------------------------------- * Swig_name_object_set() * * Sets an object associated with a name and optional declarators. * ----------------------------------------------------------------------------- */ void Swig_name_object_set(Hash *namehash, String *name, SwigType *decl, DOH *object) { DOH *n; #ifdef SWIG_DEBUG Printf(stdout, "Swig_name_object_set: '%s', '%s'\n", name, decl); #endif n = Getattr(namehash, name); if (!n) { n = NewHash(); Setattr(namehash, name, n); Delete(n); } /* Add an object based on the declarator value */ if (!decl) { Setattr(n, "start", object); } else { SwigType *cd = Copy(decl); Setattr(n, cd, object); Delete(cd); } } /* ----------------------------------------------------------------------------- * Swig_name_object_get() * * Return an object associated with an optional class prefix, name, and * declarator. This function operates according to name matching rules * described for the %rename directive in the SWIG manual. * ----------------------------------------------------------------------------- */ static DOH *get_object(Hash *n, String *decl) { DOH *rn = 0; if (!n) return 0; if (decl) { rn = Getattr(n, decl); } else { rn = Getattr(n, "start"); } return rn; } static DOH *name_object_get(Hash *namehash, String *tname, SwigType *decl, SwigType *ncdecl) { DOH *rn = 0; Hash *n = Getattr(namehash, tname); if (n) { rn = get_object(n, decl); if ((!rn) && ncdecl) rn = get_object(n, ncdecl); if (!rn) rn = get_object(n, 0); } return rn; } DOH *Swig_name_object_get(Hash *namehash, String *prefix, String *name, SwigType *decl) { String *tname = NewStringEmpty(); DOH *rn = 0; char *ncdecl = 0; if (!namehash) return 0; /* DB: This removed to more tightly control feature/name matching */ /* if ((decl) && (SwigType_isqualifier(decl))) { ncdecl = strchr(Char(decl),'.'); ncdecl++; } */ #ifdef SWIG_DEBUG Printf(stdout, "Swig_name_object_get: '%s' '%s', '%s'\n", prefix, name, decl); #endif /* Perform a class-based lookup (if class prefix supplied) */ if (prefix) { if (Len(prefix)) { Printf(tname, "%s::%s", prefix, name); rn = name_object_get(namehash, tname, decl, ncdecl); if (!rn) { String *cls = Swig_scopename_last(prefix); if (!Equal(cls, prefix)) { Clear(tname); Printf(tname, "*::%s::%s", cls, name); rn = name_object_get(namehash, tname, decl, ncdecl); } Delete(cls); } /* A template-based class lookup, check name first */ if (!rn) { String *t_name = SwigType_istemplate_templateprefix(name); if (t_name) rn = Swig_name_object_get(namehash, prefix, t_name, decl); Delete(t_name); } } /* A wildcard-based class lookup */ if (!rn) { Clear(tname); Printf(tname, "*::%s", name); rn = name_object_get(namehash, tname, decl, ncdecl); } } else { /* Lookup in the global namespace only */ Clear(tname); Printf(tname, "::%s", name); rn = name_object_get(namehash, tname, decl, ncdecl); } /* Catch-all */ if (!rn) { rn = name_object_get(namehash, name, decl, ncdecl); } if (!rn && Swig_scopename_check(name)) { String *nprefix = NewStringEmpty(); String *nlast = NewStringEmpty(); Swig_scopename_split(name, &nprefix, &nlast); rn = name_object_get(namehash, nlast, decl, ncdecl); Delete(nlast); Delete(nprefix); } Delete(tname); #ifdef SWIG_DEBUG Printf(stdout, "Swig_name_object_get: found %d\n", rn ? 1 : 0); #endif return rn; } /* ----------------------------------------------------------------------------- * Swig_name_object_inherit() * * Implements name-based inheritance scheme. * ----------------------------------------------------------------------------- */ void Swig_name_object_inherit(Hash *namehash, String *base, String *derived) { Iterator ki; String *bprefix; String *dprefix; char *cbprefix; int plen; if (!namehash) return; bprefix = NewStringf("%s::", base); dprefix = NewStringf("%s::", derived); cbprefix = Char(bprefix); plen = strlen(cbprefix); for (ki = First(namehash); ki.key; ki = Next(ki)) { char *k = Char(ki.key); if (strncmp(k, cbprefix, plen) == 0) { Iterator oi; String *nkey = NewStringf("%s%s", dprefix, k + plen); Hash *n = ki.item; Hash *newh = Getattr(namehash, nkey); if (!newh) { newh = NewHash(); Setattr(namehash, nkey, newh); Delete(newh); } for (oi = First(n); oi.key; oi = Next(oi)) { if (!Getattr(newh, oi.key)) { String *ci = Copy(oi.item); Setattr(newh, oi.key, ci); Delete(ci); } } Delete(nkey); } } Delete(bprefix); Delete(dprefix); } /* ----------------------------------------------------------------------------- * merge_features() * * Given a hash, this function merges the features in the hash into the node. * ----------------------------------------------------------------------------- */ static void merge_features(Hash *features, Node *n) { Iterator ki; if (!features) return; for (ki = First(features); ki.key; ki = Next(ki)) { String *ci = Copy(ki.item); Setattr(n, ki.key, ci); Delete(ci); } } /* ----------------------------------------------------------------------------- * Swig_features_get() * * Attaches any features in the features hash to the node that matches * the declaration, decl. * ----------------------------------------------------------------------------- */ static void features_get(Hash *features, const String *tname, SwigType *decl, SwigType *ncdecl, Node *node) { Node *n = Getattr(features, tname); #ifdef SWIG_DEBUG Printf(stdout, " features_get: %s\n", tname); #endif if (n) { merge_features(get_object(n, 0), node); if (ncdecl) merge_features(get_object(n, ncdecl), node); merge_features(get_object(n, decl), node); } } void Swig_features_get(Hash *features, String *prefix, String *name, SwigType *decl, Node *node) { char *ncdecl = 0; String *rdecl = 0; String *rname = 0; if (!features) return; /* MM: This removed to more tightly control feature/name matching */ /* if ((decl) && (SwigType_isqualifier(decl))) { ncdecl = strchr(Char(decl),'.'); ncdecl++; } */ /* very specific hack for template constructors/destructors */ if (name && SwigType_istemplate(name)) { String *nodetype = nodeType(node); if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) { String *nprefix = NewStringEmpty(); String *nlast = NewStringEmpty(); String *tprefix; Swig_scopename_split(name, &nprefix, &nlast); tprefix = SwigType_templateprefix(nlast); Delete(nlast); if (Len(nprefix)) { Append(nprefix, "::"); Append(nprefix, tprefix); Delete(tprefix); rname = nprefix; } else { rname = tprefix; Delete(nprefix); } rdecl = Copy(decl); Replaceall(rdecl, name, rname); decl = rdecl; name = rname; } } #ifdef SWIG_DEBUG Printf(stdout, "Swig_features_get: '%s' '%s' '%s'\n", prefix, name, decl); #endif /* Global features */ features_get(features, "", 0, 0, node); if (name) { String *tname = NewStringEmpty(); /* add features for 'root' template */ String *dname = SwigType_istemplate_templateprefix(name); if (dname) { features_get(features, dname, decl, ncdecl, node); } /* Catch-all */ features_get(features, name, decl, ncdecl, node); /* Perform a class-based lookup (if class prefix supplied) */ if (prefix) { /* A class-generic feature */ if (Len(prefix)) { Printf(tname, "%s::", prefix); features_get(features, tname, decl, ncdecl, node); } /* A wildcard-based class lookup */ Clear(tname); Printf(tname, "*::%s", name); features_get(features, tname, decl, ncdecl, node); /* A specific class lookup */ if (Len(prefix)) { /* A template-based class lookup */ String *tprefix = SwigType_istemplate_templateprefix(prefix); if (tprefix) { Clear(tname); Printf(tname, "%s::%s", tprefix, name); features_get(features, tname, decl, ncdecl, node); } Clear(tname); Printf(tname, "%s::%s", prefix, name); features_get(features, tname, decl, ncdecl, node); Delete(tprefix); } } else { /* Lookup in the global namespace only */ Clear(tname); Printf(tname, "::%s", name); features_get(features, tname, decl, ncdecl, node); } Delete(tname); Delete(dname); } if (name && SwigType_istemplate(name)) { /* add features for complete template type */ String *dname = Swig_symbol_template_deftype(name, 0); if (!Equal(dname, name)) { Swig_features_get(features, prefix, dname, decl, node); } Delete(dname); } if (rname) Delete(rname); if (rdecl) Delete(rdecl); } /* ----------------------------------------------------------------------------- * Swig_feature_set() * * Sets a feature name and value. Also sets optional feature attributes as * passed in by featureattribs. Optional feature attributes are given a full name * concatenating the feature name plus ':' plus the attribute name. * ----------------------------------------------------------------------------- */ void Swig_feature_set(Hash *features, const_String_or_char_ptr name, SwigType *decl, const_String_or_char_ptr featurename, String *value, Hash *featureattribs) { Hash *n; Hash *fhash; #ifdef SWIG_DEBUG Printf(stdout, "Swig_feature_set: '%s' '%s' '%s' '%s'\n", name, decl, featurename, value); #endif n = Getattr(features, name); if (!n) { n = NewHash(); Setattr(features, name, n); Delete(n); } if (!decl) { fhash = Getattr(n, "start"); if (!fhash) { fhash = NewHash(); Setattr(n, "start", fhash); Delete(fhash); } } else { fhash = Getattr(n, decl); if (!fhash) { String *cdecl_ = Copy(decl); fhash = NewHash(); Setattr(n, cdecl_, fhash); Delete(cdecl_); Delete(fhash); } } if (value) { Setattr(fhash, featurename, value); } else { Delattr(fhash, featurename); } { /* Add in the optional feature attributes */ Hash *attribs = featureattribs; while (attribs) { String *attribname = Getattr(attribs, "name"); String *featureattribname = NewStringf("%s:%s", featurename, attribname); if (value) { String *attribvalue = Getattr(attribs, "value"); Setattr(fhash, featureattribname, attribvalue); } else { Delattr(fhash, featureattribname); } attribs = nextSibling(attribs); Delete(featureattribname); } } if (name && SwigType_istemplate(name)) { String *dname = Swig_symbol_template_deftype(name, 0); if (Strcmp(dname, name)) { Swig_feature_set(features, dname, decl, featurename, value, featureattribs); } Delete(dname); } } /* ----------------------------------------------------------------------------- * The rename/namewarn engine * * Code below was in parser.y for a while * ----------------------------------------------------------------------------- */ static Hash *namewarn_hash = 0; Hash *Swig_name_namewarn_hash() { if (!namewarn_hash) namewarn_hash = NewHash(); return namewarn_hash; } static Hash *rename_hash = 0; Hash *Swig_name_rename_hash() { if (!rename_hash) rename_hash = NewHash(); return rename_hash; } static List *namewarn_list = 0; List *Swig_name_namewarn_list() { if (!namewarn_list) namewarn_list = NewList(); return namewarn_list; } static List *rename_list = 0; List *Swig_name_rename_list() { if (!rename_list) rename_list = NewList(); return rename_list; } /* ----------------------------------------------------------------------------- * int Swig_need_name_warning(Node *n) * * Detects if a node needs name warnings * * ----------------------------------------------------------------------------- */ int Swig_need_name_warning(Node *n) { int need = 1; /* we don't use name warnings for: - class forwards, no symbol is generated at the target language. - template declarations, only for real instances using %template(name). - typedefs, they have no effect at the target language. */ if (checkAttribute(n, "nodeType", "classforward")) { need = 0; } else if (checkAttribute(n, "storage", "typedef")) { need = 0; } else if (Getattr(n, "hidden")) { need = 0; } else if (Getattr(n, "ignore")) { need = 0; } else if (Getattr(n, "templatetype")) { need = 0; } return need; } /* ----------------------------------------------------------------------------- * int Swig_need_redefined_warn() * * Detects when a redefined object needs a warning * * ----------------------------------------------------------------------------- */ static int nodes_are_equivalent(Node *a, Node *b, int a_inclass) { /* they must have the same type */ String *ta = nodeType(a); String *tb = nodeType(b); if (Cmp(ta, tb) != 0) return 0; /* cdecl case */ if (Cmp(ta, "cdecl") == 0) { /* typedef */ String *a_storage = Getattr(a, "storage"); String *b_storage = Getattr(b, "storage"); if ((Cmp(a_storage, "typedef") == 0) || (Cmp(b_storage, "typedef") == 0)) { if (Cmp(a_storage, b_storage) == 0) { String *a_type = (Getattr(a, "type")); String *b_type = (Getattr(b, "type")); if (Cmp(a_type, b_type) == 0) return 1; } return 0; } /* static functions */ if ((Cmp(a_storage, "static") == 0) || (Cmp(b_storage, "static") == 0)) { if (Cmp(a_storage, b_storage) != 0) return 0; } /* friend methods */ if (!a_inclass || (Cmp(a_storage, "friend") == 0)) { /* check declaration */ String *a_decl = (Getattr(a, "decl")); String *b_decl = (Getattr(b, "decl")); if (Cmp(a_decl, b_decl) == 0) { /* check return type */ String *a_type = (Getattr(a, "type")); String *b_type = (Getattr(b, "type")); if (Cmp(a_type, b_type) == 0) { /* check parameters */ Parm *ap = (Getattr(a, "parms")); Parm *bp = (Getattr(b, "parms")); while (ap && bp) { SwigType *at = Getattr(ap, "type"); SwigType *bt = Getattr(bp, "type"); if (Cmp(at, bt) != 0) return 0; ap = nextSibling(ap); bp = nextSibling(bp); } if (ap || bp) { return 0; } else { Node *a_template = Getattr(a, "template"); Node *b_template = Getattr(b, "template"); /* Not equivalent if one is a template instantiation (via %template) and the other is a non-templated function */ if ((a_template && !b_template) || (!a_template && b_template)) return 0; } return 1; } } } } else { /* %constant case */ String *a_storage = Getattr(a, "storage"); String *b_storage = Getattr(b, "storage"); if ((Cmp(a_storage, "%constant") == 0) || (Cmp(b_storage, "%constant") == 0)) { if (Cmp(a_storage, b_storage) == 0) { String *a_type = (Getattr(a, "type")); String *b_type = (Getattr(b, "type")); if ((Cmp(a_type, b_type) == 0) && (Cmp(Getattr(a, "value"), Getattr(b, "value")) == 0)) return 1; } return 0; } } return 0; } int Swig_need_redefined_warn(Node *a, Node *b, int InClass) { String *a_name = Getattr(a, "name"); String *b_name = Getattr(b, "name"); String *a_symname = Getattr(a, "sym:name"); String *b_symname = Getattr(b, "sym:name"); /* always send a warning if a 'rename' is involved */ if ((a_symname && !Equal(a_symname, a_name)) || (b_symname && !Equal(b_symname, b_name))) { if (!Equal(a_name, b_name)) { return 1; } } return !nodes_are_equivalent(a, b, InClass); } /* ----------------------------------------------------------------------------- * int Swig_need_protected(Node* n) * * Detects when we need to fully register the protected member. * This is basically any protected members when the allprotected mode is set. * Otherwise we take just the protected virtual methods and non-static methods * (potentially virtual methods) as well as constructors/destructors. * Also any "using" statements in a class may potentially be virtual. * ----------------------------------------------------------------------------- */ int Swig_need_protected(Node *n) { String *nodetype = nodeType(n); if (checkAttribute(n, "access", "protected")) { if ((Equal(nodetype, "cdecl"))) { if (Swig_director_mode() && Swig_director_protected_mode() && Swig_all_protected_mode()) { return 1; } if (SwigType_isfunction(Getattr(n, "decl"))) { String *storage = Getattr(n, "storage"); /* The function is declared virtual, or it has no storage. This eliminates typedef, static etc. */ return !storage || Equal(storage, "virtual"); } } else if (Equal(nodetype, "constructor") || Equal(nodetype, "destructor")) { return 1; } else if (Equal(nodetype, "using") && !Getattr(n, "namespace")) { return 1; } } return 0; } /* ----------------------------------------------------------------------------- * void Swig_name_nameobj_add() * * Add nameobj (rename/namewarn) * * ----------------------------------------------------------------------------- */ static List *Swig_make_attrlist(const char *ckey) { List *list = NewList(); const char *cattr = strchr(ckey, '$'); if (cattr) { String *nattr; const char *rattr = strchr(++cattr, '$'); while (rattr) { nattr = NewStringWithSize(cattr, rattr - cattr); Append(list, nattr); Delete(nattr); cattr = rattr + 1; rattr = strchr(cattr, '$'); } nattr = NewString(cattr); Append(list, nattr); Delete(nattr); } else { Append(list, "nodeType"); } return list; } static void Swig_name_object_attach_keys(const char *keys[], Hash *nameobj) { Node *kw = nextSibling(nameobj); List *matchlist = 0; while (kw) { Node *next = nextSibling(kw); String *kname = Getattr(kw, "name"); char *ckey = kname ? Char(kname) : 0; if (ckey) { const char **rkey; int isnotmatch = 0; int isregexmatch = 0; if ((strncmp(ckey, "match", 5) == 0) || (isnotmatch = (strncmp(ckey, "notmatch", 8) == 0)) || (isregexmatch = (strncmp(ckey, "regexmatch", 10) == 0)) || (isnotmatch = isregexmatch = (strncmp(ckey, "notregexmatch", 13) == 0))) { Hash *mi = NewHash(); List *attrlist = Swig_make_attrlist(ckey); if (!matchlist) matchlist = NewList(); Setattr(mi, "value", Getattr(kw, "value")); Setattr(mi, "attrlist", attrlist); if (isnotmatch) SetFlag(mi, "notmatch"); if (isregexmatch) SetFlag(mi, "regexmatch"); Delete(attrlist); Append(matchlist, mi); Delete(mi); removeNode(kw); } else { for (rkey = keys; *rkey != 0; ++rkey) { if (strcmp(ckey, *rkey) == 0) { Setattr(nameobj, *rkey, Getattr(kw, "value")); removeNode(kw); } } } } kw = next; } if (matchlist) { Setattr(nameobj, "matchlist", matchlist); Delete(matchlist); } } void Swig_name_nameobj_add(Hash *name_hash, List *name_list, String *prefix, String *name, SwigType *decl, Hash *nameobj) { String *nname = 0; if (name && Len(name)) { String *target_fmt = Getattr(nameobj, "targetfmt"); nname = prefix ? NewStringf("%s::%s", prefix, name) : NewString(name); if (target_fmt) { String *tmp = NewStringf(target_fmt, nname); Delete(nname); nname = tmp; } } if (!nname || !Len(nname) || Getattr(nameobj, "fullname") || /* any of these options trigger a 'list' nameobj */ Getattr(nameobj, "sourcefmt") || Getattr(nameobj, "matchlist") || Getattr(nameobj, "regextarget")) { if (decl) Setattr(nameobj, "decl", decl); if (nname && Len(nname)) Setattr(nameobj, "targetname", nname); /* put the new nameobj at the beginnig of the list, such that the last inserted rule take precedence */ Insert(name_list, 0, nameobj); } else { /* here we add an old 'hash' nameobj, simple and fast */ Swig_name_object_set(name_hash, nname, decl, nameobj); } Delete(nname); } /* ----------------------------------------------------------------------------- * int Swig_name_match_nameobj() * * Apply and check the nameobj's math list to the node * * ----------------------------------------------------------------------------- */ static DOH *Swig_get_lattr(Node *n, List *lattr) { DOH *res = 0; int ilen = Len(lattr); int i; for (i = 0; n && (i < ilen); ++i) { String *nattr = Getitem(lattr, i); res = Getattr(n, nattr); #ifdef SWIG_DEBUG if (!res) { Printf(stdout, "missing %s %s %s\n", nattr, Getattr(n, "name"), Getattr(n, "member")); } else { Printf(stdout, "lattr %d %s %s\n", i, nattr, DohIsString(res) ? res : Getattr(res, "name")); } #endif n = res; } return res; } #ifdef HAVE_PCRE #include int Swig_name_regexmatch_value(Node *n, String *pattern, String *s) { pcre *compiled_pat; const char *err; int errpos; int rc; compiled_pat = pcre_compile(Char(pattern), 0, &err, &errpos, NULL); if (!compiled_pat) { Swig_error("SWIG", Getline(n), "Invalid regex \"%s\": compilation failed at %d: %s\n", Char(pattern), errpos, err); exit(1); } rc = pcre_exec(compiled_pat, NULL, Char(s), Len(s), 0, 0, NULL, 0); pcre_free(compiled_pat); if (rc == PCRE_ERROR_NOMATCH) return 0; if (rc < 0 ) { Swig_error("SWIG", Getline(n), "Matching \"%s\" against regex \"%s\" failed: %d\n", Char(s), Char(pattern), rc); exit(1); } return 1; } #else /* !HAVE_PCRE */ int Swig_name_regexmatch_value(Node *n, String *pattern, String *s) { (void)pattern; (void)s; Swig_error("SWIG", Getline(n), "PCRE regex matching is not available in this SWIG build.\n"); exit(1); } #endif /* HAVE_PCRE/!HAVE_PCRE */ int Swig_name_match_value(String *mvalue, String *value) { #if defined(SWIG_USE_SIMPLE_MATCHOR) int match = 0; char *cvalue = Char(value); char *cmvalue = Char(mvalue); char *sep = strchr(cmvalue, '|'); while (sep && !match) { match = strncmp(cvalue, cmvalue, sep - cmvalue) == 0; #ifdef SWIG_DEBUG Printf(stdout, "match_value: %s %s %d\n", cvalue, cmvalue, match); #endif cmvalue = sep + 1; sep = strchr(cmvalue, '|'); } if (!match) { match = strcmp(cvalue, cmvalue) == 0; #ifdef SWIG_DEBUG Printf(stdout, "match_value: %s %s %d\n", cvalue, cmvalue, match); #endif } return match; #else return Equal(mvalue, value); #endif } int Swig_name_match_nameobj(Hash *rn, Node *n) { int match = 1; List *matchlist = Getattr(rn, "matchlist"); #ifdef SWIG_DEBUG Printf(stdout, "Swig_name_match_nameobj: %s\n", Getattr(n, "name")); #endif if (matchlist) { int ilen = Len(matchlist); int i; for (i = 0; match && (i < ilen); ++i) { Node *mi = Getitem(matchlist, i); List *lattr = Getattr(mi, "attrlist"); String *nval = Swig_get_lattr(n, lattr); int notmatch = GetFlag(mi, "notmatch"); int regexmatch = GetFlag(mi, "regexmatch"); match = 0; if (nval) { String *kwval = Getattr(mi, "value"); match = regexmatch ? Swig_name_regexmatch_value(n, kwval, nval) : Swig_name_match_value(kwval, nval); #ifdef SWIG_DEBUG Printf(stdout, "val %s %s %d %d \n", nval, kwval, match, ilen); #endif } if (notmatch) match = !match; } } #ifdef SWIG_DEBUG Printf(stdout, "Swig_name_match_nameobj: %d\n", match); #endif return match; } /* ----------------------------------------------------------------------------- * Hash *Swig_name_nameobj_lget() * * Get a nameobj (rename/namewarn) from the list of filters * * ----------------------------------------------------------------------------- */ Hash *Swig_name_nameobj_lget(List *namelist, Node *n, String *prefix, String *name, String *decl) { Hash *res = 0; if (namelist) { int len = Len(namelist); int i; int match = 0; for (i = 0; !match && (i < len); i++) { Hash *rn = Getitem(namelist, i); String *rdecl = Getattr(rn, "decl"); if (rdecl && (!decl || !Equal(rdecl, decl))) { continue; } else if (Swig_name_match_nameobj(rn, n)) { String *tname = Getattr(rn, "targetname"); if (tname) { String *sfmt = Getattr(rn, "sourcefmt"); String *sname = 0; int fullname = GetFlag(rn, "fullname"); int regextarget = GetFlag(rn, "regextarget"); if (sfmt) { if (fullname && prefix) { String *pname = NewStringf("%s::%s", prefix, name); sname = NewStringf(sfmt, pname); Delete(pname); } else { sname = NewStringf(sfmt, name); } } else { if (fullname && prefix) { sname = NewStringf("%s::%s", prefix, name); } else { sname = name; DohIncref(name); } } match = regextarget ? Swig_name_regexmatch_value(n, tname, sname) : Swig_name_match_value(tname, sname); Delete(sname); } else { /* Applying the renaming rule may fail if it contains a %(regex)s expression that doesn't match the given name. */ String *sname = NewStringf(Getattr(rn, "name"), name); if (sname) { if (Len(sname)) match = 1; Delete(sname); } } } if (match) { res = rn; break; } } } return res; } /* ----------------------------------------------------------------------------- * Swig_name_namewarn_add * * Add a namewarn objects * * ----------------------------------------------------------------------------- */ void Swig_name_namewarn_add(String *prefix, String *name, SwigType *decl, Hash *namewrn) { const char *namewrn_keys[] = { "rename", "error", "fullname", "sourcefmt", "targetfmt", 0 }; Swig_name_object_attach_keys(namewrn_keys, namewrn); Swig_name_nameobj_add(Swig_name_namewarn_hash(), Swig_name_namewarn_list(), prefix, name, decl, namewrn); } /* ----------------------------------------------------------------------------- * Hash *Swig_name_namewarn_get() * * Return the namewarn object, if there is one. * * ----------------------------------------------------------------------------- */ Hash *Swig_name_namewarn_get(Node *n, String *prefix, String *name, SwigType *decl) { if (!namewarn_hash && !namewarn_list) return 0; if (n) { /* Return in the obvious cases */ if (!name || !Swig_need_name_warning(n)) { return 0; } else { String *access = Getattr(n, "access"); int is_public = !access || Equal(access, "public"); if (!is_public && !Swig_need_protected(n)) { return 0; } } } if (name) { /* Check to see if the name is in the hash */ Hash *wrn = Swig_name_object_get(Swig_name_namewarn_hash(), prefix, name, decl); if (wrn && !Swig_name_match_nameobj(wrn, n)) wrn = 0; if (!wrn) { wrn = Swig_name_nameobj_lget(Swig_name_namewarn_list(), n, prefix, name, decl); } if (wrn && Getattr(wrn, "error")) { if (n) { Swig_error(Getfile(n), Getline(n), "%s\n", Getattr(wrn, "name")); } else { Swig_error(cparse_file, cparse_line, "%s\n", Getattr(wrn, "name")); } } return wrn; } else { return 0; } } /* ----------------------------------------------------------------------------- * String *Swig_name_warning() * * Return the name warning, if there is one. * * ----------------------------------------------------------------------------- */ String *Swig_name_warning(Node *n, String *prefix, String *name, SwigType *decl) { Hash *wrn = Swig_name_namewarn_get(n, prefix, name, decl); return (name && wrn) ? Getattr(wrn, "name") : 0; } /* ----------------------------------------------------------------------------- * Swig_name_rename_add() * * Manage the rename objects * * ----------------------------------------------------------------------------- */ static void single_rename_add(String *prefix, String *name, SwigType *decl, Hash *newname) { Swig_name_nameobj_add(Swig_name_rename_hash(), Swig_name_rename_list(), prefix, name, decl, newname); } /* Add a new rename. Works much like new_feature including default argument handling. */ void Swig_name_rename_add(String *prefix, String *name, SwigType *decl, Hash *newname, ParmList *declaratorparms) { ParmList *declparms = declaratorparms; const char *rename_keys[] = { "fullname", "sourcefmt", "targetfmt", "continue", "regextarget", 0 }; Swig_name_object_attach_keys(rename_keys, newname); /* Add the name */ single_rename_add(prefix, name, decl, newname); /* Add extra names if there are default parameters in the parameter list */ if (decl) { int constqualifier = SwigType_isconst(decl); while (declparms) { if (ParmList_has_defaultargs(declparms)) { /* Create a parameter list for the new rename by copying all but the last (defaulted) parameter */ ParmList *newparms = CopyParmListMax(declparms,ParmList_len(declparms)-1); /* Create new declaration - with the last parameter removed */ SwigType *newdecl = Copy(decl); Delete(SwigType_pop_function(newdecl)); /* remove the old parameter list from newdecl */ SwigType_add_function(newdecl, newparms); if (constqualifier) SwigType_add_qualifier(newdecl, "const"); single_rename_add(prefix, name, newdecl, newname); declparms = newparms; Delete(newdecl); } else { declparms = 0; } } } } /* Create a name applying rename/namewarn if needed */ static String *apply_rename(String *newname, int fullname, String *prefix, String *name) { String *result = 0; if (newname && Len(newname)) { if (Strcmp(newname, "$ignore") == 0) { result = Copy(newname); } else { char *cnewname = Char(newname); if (cnewname) { int destructor = name && (*(Char(name)) == '~'); String *fmt = newname; /* use name as a fmt, but avoid C++ "%" and "%=" operators */ if (Len(newname) > 1 && strchr(cnewname, '%') && !(strcmp(cnewname, "%=") == 0)) { if (fullname && prefix) { result = NewStringf(fmt, prefix, name); } else { result = NewStringf(fmt, name); } } else { result = Copy(newname); } if (destructor && result && (*(Char(result)) != '~')) { Insert(result, 0, "~"); } } } } return result; } /* ----------------------------------------------------------------------------- * String *Swig_name_make() * * Make a name after applying all the rename/namewarn objects * * ----------------------------------------------------------------------------- */ String *Swig_name_make(Node *n, String *prefix, const_String_or_char_ptr cname, SwigType *decl, String *oldname) { String *nname = 0; String *result = 0; String *name = NewString(cname); Hash *wrn = 0; String *rdecl = 0; String *rname = 0; /* very specific hack for template constructors/destructors */ #ifdef SWIG_DEBUG Printf(stdout, "Swig_name_make: looking for %s %s %s %s\n", prefix, name, decl, oldname); #endif if (name && n && SwigType_istemplate(name)) { String *nodetype = nodeType(n); if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) { String *nprefix = NewStringEmpty(); String *nlast = NewStringEmpty(); String *tprefix; Swig_scopename_split(name, &nprefix, &nlast); tprefix = SwigType_templateprefix(nlast); Delete(nlast); if (Len(nprefix)) { Append(nprefix, "::"); Append(nprefix, tprefix); Delete(tprefix); rname = nprefix; } else { rname = tprefix; Delete(nprefix); } rdecl = Copy(decl); Replaceall(rdecl, name, rname); #ifdef SWIG_DEBUG Printf(stdout, "SWIG_name_make: use new name %s %s : %s %s\n", name, decl, rname, rdecl); #endif decl = rdecl; Delete(name); name = rname; } } if (rename_hash || rename_list || namewarn_hash || namewarn_list) { Hash *rn = Swig_name_object_get(Swig_name_rename_hash(), prefix, name, decl); if (!rn || !Swig_name_match_nameobj(rn, n)) { rn = Swig_name_nameobj_lget(Swig_name_rename_list(), n, prefix, name, decl); if (rn) { String *sfmt = Getattr(rn, "sourcefmt"); int fullname = GetFlag(rn, "fullname"); if (fullname && prefix) { String *sname = NewStringf("%s::%s", prefix, name); Delete(name); name = sname; prefix = 0; } if (sfmt) { String *sname = NewStringf(sfmt, name); Delete(name); name = sname; } } } if (rn) { String *newname = Getattr(rn, "name"); int fullname = GetFlag(rn, "fullname"); result = apply_rename(newname, fullname, prefix, name); } if (result && !Equal(result, name)) { /* operators in C++ allow aliases, we look for them */ char *cresult = Char(result); if (cresult && (strncmp(cresult, "operator ", 9) == 0)) { String *nresult = Swig_name_make(n, prefix, result, decl, oldname); if (!Equal(nresult, result)) { Delete(result); result = nresult; } else { Delete(nresult); } } } nname = result ? result : name; wrn = Swig_name_namewarn_get(n, prefix, nname, decl); if (wrn) { String *rename = Getattr(wrn, "rename"); if (rename) { String *msg = Getattr(wrn, "name"); int fullname = GetFlag(wrn, "fullname"); if (result) Delete(result); result = apply_rename(rename, fullname, prefix, name); if ((msg) && (Len(msg))) { if (!Getmeta(nname, "already_warned")) { if (n) { SWIG_WARN_NODE_BEGIN(n); Swig_warning(0, Getfile(n), Getline(n), "%s\n", msg); SWIG_WARN_NODE_END(n); } else { Swig_warning(0, Getfile(name), Getline(name), "%s\n", msg); } Setmeta(nname, "already_warned", "1"); } } } } } if (!result || !Len(result)) { if (result) Delete(result); if (oldname) { result = NewString(oldname); } else { result = NewString(cname); } } Delete(name); #ifdef SWIG_DEBUG Printf(stdout, "Swig_name_make: result '%s' '%s'\n", cname, result); #endif return result; } /* ----------------------------------------------------------------------------- * void Swig_name_inherit() * * Inherit namewarn,rename, and feature objects * * ----------------------------------------------------------------------------- */ void Swig_name_inherit(String *base, String *derived) { /* Printf(stdout,"base = '%s', derived = '%s'\n", base, derived); */ Swig_name_object_inherit(Swig_name_rename_hash(), base, derived); Swig_name_object_inherit(Swig_name_namewarn_hash(), base, derived); Swig_name_object_inherit(Swig_cparse_features(), base, derived); } /* ----------------------------------------------------------------------------- * void Swig_name_str() * * Return a stringified version of a C/C++ symbol from a node. * The node passed in is expected to be a function, constructor, destructor or * variable. Some example return values: * "MyNameSpace::MyTemplate::~MyTemplate" * "MyNameSpace::ABC::ABC" * "MyNameSpace::ABC::constmethod" * "MyNameSpace::ABC::variablename" * * ----------------------------------------------------------------------------- */ String *Swig_name_str(Node *n) { String *qname; String *qualifier = Swig_symbol_qualified(n); String *name = Swig_scopename_last(Getattr(n, "name")); if (qualifier) qualifier = SwigType_namestr(qualifier); /* Very specific hack for template constructors/destructors */ if (SwigType_istemplate(name)) { String *nodetype = nodeType(n); if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) { String *nprefix = NewStringEmpty(); String *nlast = NewStringEmpty(); String *tprefix; Swig_scopename_split(name, &nprefix, &nlast); tprefix = SwigType_templateprefix(nlast); Delete(nlast); Delete(name); name = tprefix; } } qname = NewString(""); if (qualifier && Len(qualifier) > 0) Printf(qname, "%s::", qualifier); Printf(qname, "%s", SwigType_str(name, 0)); Delete(name); Delete(qualifier); return qname; } /* ----------------------------------------------------------------------------- * void Swig_name_decl() * * Return a stringified version of a C/C++ declaration without the return type. * The node passed in is expected to be a function, constructor, destructor or * variable. Some example return values: * "MyNameSpace::MyTemplate::~MyTemplate()" * "MyNameSpace::ABC::ABC(int,double)" * "MyNameSpace::ABC::constmethod(int) const" * "MyNameSpace::ABC::variablename" * * ----------------------------------------------------------------------------- */ String *Swig_name_decl(Node *n) { String *qname; String *decl; qname = Swig_name_str(n); if (checkAttribute(n, "kind", "variable")) decl = NewStringf("%s", qname); else decl = NewStringf("%s(%s)%s", qname, ParmList_errorstr(Getattr(n, "parms")), SwigType_isconst(Getattr(n, "decl")) ? " const" : ""); Delete(qname); return decl; } /* ----------------------------------------------------------------------------- * void Swig_name_fulldecl() * * Return a stringified version of a C/C++ declaration including the return type. * The node passed in is expected to be a function, constructor or destructor. * Some example return values: * "MyNameSpace::MyTemplate::~MyTemplate()" * "MyNameSpace::ABC::ABC(int,double)" * "int * MyNameSpace::ABC::constmethod(int) const" * * ----------------------------------------------------------------------------- */ String *Swig_name_fulldecl(Node *n) { String *decl = Swig_name_decl(n); String *type = Getattr(n, "type"); String *nodetype = nodeType(n); String *fulldecl; /* add on the return type */ if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) { fulldecl = decl; } else { String *t = SwigType_str(type, 0); fulldecl = NewStringf("%s %s", t, decl); Delete(decl); Delete(t); } return fulldecl; }