git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@7810 626c5289-ae23-0410-ae9c-e8d60b6d4f22
734 lines
18 KiB
C
734 lines
18 KiB
C
/* -----------------------------------------------------------------------------
|
|
* naming.c
|
|
*
|
|
* Functions for generating various kinds of names during code generation
|
|
*
|
|
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
|
*
|
|
* Copyright (C) 1999-2000. The University of Chicago
|
|
* See the file LICENSE for information on usage and redistribution.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
char cvsroot_naming_c[] = "$Header$";
|
|
|
|
#include "swig.h"
|
|
#include <ctype.h>
|
|
|
|
/* Hash table containing naming data */
|
|
|
|
static Hash *naming_hash = 0;
|
|
|
|
/* #define SWIG_DEBUG */
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_name_register()
|
|
*
|
|
* Register a new naming format.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
void
|
|
Swig_name_register(const String_or_char *method, const String_or_char *format) {
|
|
if (!naming_hash) naming_hash = NewHash();
|
|
Setattr(naming_hash,method,format);
|
|
}
|
|
|
|
void
|
|
Swig_name_unregister(const String_or_char *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;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_name_mangle()
|
|
*
|
|
* Converts all of the non-identifier characters of a string to underscores.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *
|
|
Swig_name_mangle(const String_or_char *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 *fname) {
|
|
String *r;
|
|
String *f;
|
|
|
|
r = NewString("");
|
|
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 *classname, const String_or_char *mname) {
|
|
String *r;
|
|
String *f;
|
|
String *rclassname;
|
|
char *cname;
|
|
|
|
rclassname = SwigType_namestr(classname);
|
|
r = NewString("");
|
|
if (!naming_hash) naming_hash = NewHash();
|
|
f = Getattr(naming_hash,"member");
|
|
if (!f) {
|
|
Append(r,"%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(r,"%c",cname, DOH_REPLACE_ANY);
|
|
Replace(r,"%m",mname, 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 *vname) {
|
|
String *r;
|
|
String *f;
|
|
|
|
#ifdef SWIG_DEBUG
|
|
Printf(stdout,"Swig_name_get: '%s'\n", vname);
|
|
#endif
|
|
|
|
r = NewString("");
|
|
if (!naming_hash) naming_hash = NewHash();
|
|
f = Getattr(naming_hash,"get");
|
|
if (!f) {
|
|
Append(r,"%v_get");
|
|
} else {
|
|
Append(r,f);
|
|
}
|
|
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 *vname) {
|
|
String *r;
|
|
String *f;
|
|
|
|
r = NewString("");
|
|
if (!naming_hash) naming_hash = NewHash();
|
|
f = Getattr(naming_hash,"set");
|
|
if (!f) {
|
|
Append(r,"%v_set");
|
|
} else {
|
|
Append(r,f);
|
|
}
|
|
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 *classname) {
|
|
String *r;
|
|
String *f;
|
|
String *rclassname;
|
|
char *cname;
|
|
|
|
rclassname = SwigType_namestr(classname);
|
|
r = NewString("");
|
|
if (!naming_hash) naming_hash = NewHash();
|
|
f = Getattr(naming_hash,"construct");
|
|
if (!f) {
|
|
Append(r,"new_%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(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 *classname) {
|
|
String *r;
|
|
String *f;
|
|
String *rclassname;
|
|
char *cname;
|
|
|
|
rclassname = SwigType_namestr(classname);
|
|
r = NewString("");
|
|
if (!naming_hash) naming_hash = NewHash();
|
|
f = Getattr(naming_hash,"construct");
|
|
if (!f) {
|
|
Append(r,"copy_%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(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 *classname) {
|
|
String *r;
|
|
String *f;
|
|
String *rclassname;
|
|
char *cname;
|
|
rclassname = SwigType_namestr(classname);
|
|
r = NewString("");
|
|
if (!naming_hash) naming_hash = NewHash();
|
|
f = Getattr(naming_hash,"destroy");
|
|
if (!f) {
|
|
Append(r,"delete_%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(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 *classname) {
|
|
String *r;
|
|
String *f;
|
|
String *rclassname;
|
|
char *cname;
|
|
rclassname = SwigType_namestr(classname);
|
|
r = NewString("");
|
|
if (!naming_hash) naming_hash = NewHash();
|
|
f = Getattr(naming_hash,"disown");
|
|
if (!f) {
|
|
Append(r,"disown_%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(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);
|
|
}
|
|
/* Add an object based on the declarator value */
|
|
if (!decl) {
|
|
Setattr(n,"*",object);
|
|
} else {
|
|
Setattr(n,Copy(decl),object);
|
|
}
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* 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,"*");
|
|
}
|
|
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;
|
|
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++;
|
|
}
|
|
*/
|
|
|
|
|
|
/* Perform a class-based lookup (if class prefix supplied) */
|
|
if (prefix) {
|
|
if (Len(prefix)) {
|
|
tname = NewStringf("%s::%s",prefix,name);
|
|
rn = name_object_get(namehash, tname, decl, ncdecl);
|
|
Delete(tname);
|
|
if (!rn) {
|
|
String *cls = Swig_scopename_last(prefix);
|
|
if (Strcmp(cls,prefix)!= 0) {
|
|
tname = NewStringf("*::%s::%s",cls,name);
|
|
rn = name_object_get(namehash, tname, decl, ncdecl);
|
|
Delete(tname);
|
|
}
|
|
Delete(cls);
|
|
}
|
|
/* A template-based class lookup */
|
|
if (!rn && SwigType_istemplate(prefix)) {
|
|
String *tprefix = SwigType_templateprefix(prefix);
|
|
if (Strcmp(tprefix,prefix) != 0) {
|
|
rn = Swig_name_object_get(namehash, tprefix, name, decl);
|
|
}
|
|
Delete(tprefix);
|
|
}
|
|
}
|
|
/* A wildcard-based class lookup */
|
|
if (!rn) {
|
|
tname = NewStringf("*::%s",name);
|
|
rn = name_object_get(namehash, tname, decl, ncdecl);
|
|
Delete(tname);
|
|
}
|
|
} else {
|
|
/* Lookup in the global namespace only */
|
|
tname = NewStringf("::%s",name);
|
|
rn = name_object_get(namehash, tname, decl, ncdecl);
|
|
Delete(tname);
|
|
}
|
|
/* Catch-all */
|
|
if (!rn) {
|
|
rn = name_object_get(namehash, name, decl, ncdecl);
|
|
}
|
|
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) {
|
|
Hash *n, *newh;
|
|
String *nkey;
|
|
Iterator oi;
|
|
|
|
nkey = NewStringf("%s%s",dprefix,k+plen);
|
|
n = ki.item;
|
|
newh = Getattr(namehash,nkey);
|
|
if (!newh) {
|
|
newh = NewHash();
|
|
Setattr(namehash,nkey,newh);
|
|
}
|
|
for (oi = First(n); oi.key; oi = Next(oi)) {
|
|
if (!Getattr(newh,oi.key)) {
|
|
Setattr(newh,oi.key,Copy(oi.item));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* 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)) {
|
|
Setattr(n,ki.key,Copy(ki.item));
|
|
}
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_features_get()
|
|
*
|
|
* Attaches any features in the features hash to the node that matches
|
|
* the declaration, decl.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static
|
|
void features_get(Hash *features, 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) {
|
|
String *tname;
|
|
char *ncdecl = 0;
|
|
String *rdecl = 0;
|
|
SwigType *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) &&
|
|
((Strcmp(nodeType(node),"constructor") == 0)
|
|
|| (Strcmp(nodeType(node),"destructor") == 0))) {
|
|
rname = SwigType_templateprefix(name);
|
|
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) {
|
|
/* 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)) {
|
|
tname = NewStringf("%s::",prefix);
|
|
features_get(features, tname, decl, ncdecl, node);
|
|
Delete(tname);
|
|
}
|
|
/* A wildcard-based class lookup */
|
|
tname = NewStringf("*::%s",name);
|
|
features_get(features, tname, decl, ncdecl, node);
|
|
Delete(tname);
|
|
/* A specific class lookup */
|
|
if (Len(prefix)) {
|
|
/* A template-based class lookup */
|
|
if (SwigType_istemplate(prefix)) {
|
|
String *tprefix = SwigType_templateprefix(prefix);
|
|
tname = NewStringf("%s::%s",tprefix,name);
|
|
features_get(features, tname, decl, ncdecl, node);
|
|
Delete(tname);
|
|
Delete(tprefix);
|
|
}
|
|
tname = NewStringf("%s::%s",prefix,name);
|
|
features_get(features, tname, decl, ncdecl, node);
|
|
Delete(tname);
|
|
}
|
|
} else {
|
|
/* Lookup in the global namespace only */
|
|
tname = NewStringf("::%s",name);
|
|
features_get(features, tname, decl, ncdecl, node);
|
|
Delete(tname);
|
|
}
|
|
}
|
|
if (name && SwigType_istemplate(name)) {
|
|
String *dname = Swig_symbol_template_deftype(name,0);
|
|
if (Strcmp(dname,name)) {
|
|
Swig_features_get(features, prefix, dname, decl, node);
|
|
}
|
|
Delete(dname);
|
|
}
|
|
|
|
Delete(rname);
|
|
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 *name, SwigType *decl, const String_or_char *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);
|
|
}
|
|
if (!decl) {
|
|
fhash = Getattr(n,"*");
|
|
if (!fhash) {
|
|
fhash = NewHash();
|
|
Setattr(n,"*",fhash);
|
|
}
|
|
} else {
|
|
fhash = Getattr(n,decl);
|
|
if (!fhash) {
|
|
fhash = NewHash();
|
|
Setattr(n,Copy(decl),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);
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|