PageRenderTime 101ms CodeModel.GetById 15ms app.highlight 74ms RepoModel.GetById 2ms app.codeStats 1ms

/tags/rel-1-3-30rc1-b4beautify/SWIG/Source/Swig/naming.c

#
C | 1571 lines | 1183 code | 145 blank | 243 comment | 346 complexity | 4fbac8e4d7a7de7548e92ff54b7d7f7b MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
   1/* ----------------------------------------------------------------------------- 
   2 * See the LICENSE file for information on copyright, usage and redistribution
   3 * of SWIG, and the README file for authors - http://www.swig.org/release.html.
   4 *
   5 * naming.c
   6 *
   7 * Functions for generating various kinds of names during code generation.
   8 * ----------------------------------------------------------------------------- */
   9
  10char cvsroot_naming_c[] = "$Header$";
  11
  12#include "swig.h"
  13#include "cparse.h"
  14#include "swigkeys.h"
  15#include <ctype.h>
  16
  17/* Hash table containing naming data */
  18
  19static Hash *naming_hash = 0;
  20
  21#if 0
  22#define SWIG_DEBUG 
  23#endif
  24
  25/* -----------------------------------------------------------------------------
  26 * Swig_name_register()
  27 *
  28 * Register a new naming format.
  29 * ----------------------------------------------------------------------------- */
  30
  31void
  32Swig_name_register(const String_or_char *method, const String_or_char *format) {
  33  if (!naming_hash) naming_hash = NewHash();
  34  Setattr(naming_hash,method,format);
  35}
  36
  37void
  38Swig_name_unregister(const String_or_char *method) {
  39  if (naming_hash) {
  40    Delattr(naming_hash,method);
  41  }
  42}
  43
  44static int name_mangle(String *r) {
  45  char  *c;
  46  int    special;
  47  special = 0;
  48  Replaceall(r,"::","_");
  49  c = Char(r);
  50  while (*c) {
  51    if (!isalnum((int) *c) && (*c != '_')) {
  52      special = 1;
  53      switch(*c) {
  54      case '+':
  55	*c = 'a';
  56	break;
  57      case '-':
  58	*c = 's';
  59	break;
  60      case '*':
  61	*c = 'm';
  62	break;
  63      case '/':
  64	*c = 'd';
  65	break;
  66      case '<':
  67	*c = 'l';
  68	break;
  69      case '>':
  70	*c = 'g';
  71	break;
  72      case '=':
  73	*c = 'e';
  74	break;
  75      case ',':
  76	*c = 'c';
  77	break;
  78      case '(':
  79	*c = 'p';
  80	break;
  81      case ')':
  82	*c = 'P';
  83	break;
  84      case '[':
  85	*c = 'b';
  86	break;
  87      case ']':
  88	*c = 'B';
  89	break;
  90      case '^':
  91	*c = 'x';
  92	break;
  93      case '&':
  94	*c = 'A';
  95	break;
  96      case '|':
  97	*c = 'o';
  98	break;
  99      case '~':
 100	*c = 'n';
 101	break;
 102      case '!':
 103	*c = 'N';
 104	break;
 105      case '%':
 106	*c = 'M';
 107	break;
 108      case '.':
 109	*c = 'f';
 110	break;
 111      case '?':
 112	*c = 'q';
 113	break;
 114      default:
 115	*c = '_';
 116	break;
 117      }
 118    }
 119    c++;
 120  }
 121  if (special) Append(r,"___");
 122  return special;
 123}
 124
 125/* -----------------------------------------------------------------------------
 126 * Swig_name_mangle()
 127 *
 128 * Converts all of the non-identifier characters of a string to underscores.
 129 * ----------------------------------------------------------------------------- */
 130
 131String *
 132Swig_name_mangle(const String_or_char *s) {
 133#if 0
 134  String *r = NewString(s);
 135  name_mangle(r);
 136  return r;
 137#else
 138  return Swig_string_mangle(s);
 139#endif
 140}
 141
 142/* -----------------------------------------------------------------------------
 143 * Swig_name_wrapper()
 144 *
 145 * Returns the name of a wrapper function.
 146 * ----------------------------------------------------------------------------- */
 147
 148String *
 149Swig_name_wrapper(const String_or_char *fname) {
 150  String *r;
 151  String *f;
 152
 153  r = NewStringEmpty();
 154  if (!naming_hash) naming_hash = NewHash();
 155  f = HashGetAttr(naming_hash,k_wrapper);
 156  if (!f) {
 157    Append(r,"_wrap_%f");
 158  } else {
 159    Append(r,f);
 160  }
 161  Replace(r,"%f",fname, DOH_REPLACE_ANY);
 162  name_mangle(r);
 163  return r;
 164}
 165
 166
 167/* -----------------------------------------------------------------------------
 168 * Swig_name_member()
 169 *
 170 * Returns the name of a class method.
 171 * ----------------------------------------------------------------------------- */
 172
 173String *
 174Swig_name_member(const String_or_char *classname, const String_or_char *mname) {
 175  String *r;
 176  String *f;
 177  String *rclassname;
 178  char   *cname;
 179
 180  rclassname = SwigType_namestr(classname);
 181  r = NewStringEmpty();
 182  if (!naming_hash) naming_hash = NewHash();
 183  f = HashGetAttr(naming_hash,k_member);
 184  if (!f) {
 185    Append(r,"%c_%m");
 186  } else {
 187    Append(r,f);
 188  }
 189  cname = Char(rclassname);
 190  if ((strncmp(cname,"struct ", 7) == 0) ||
 191      ((strncmp(cname,"class ", 6) == 0)) ||
 192      ((strncmp(cname,"union ", 6) == 0))) {
 193    cname = strchr(cname, ' ')+1;
 194  }
 195  Replace(r,"%c",cname, DOH_REPLACE_ANY);
 196  Replace(r,"%m",mname, DOH_REPLACE_ANY);
 197  /*  name_mangle(r);*/
 198  Delete(rclassname);
 199  return r;
 200}
 201
 202/* -----------------------------------------------------------------------------
 203 * Swig_name_get()
 204 *
 205 * Returns the name of the accessor function used to get a variable.
 206 * ----------------------------------------------------------------------------- */
 207
 208String *
 209Swig_name_get(const String_or_char *vname) {
 210  String *r;
 211  String *f;
 212
 213#ifdef SWIG_DEBUG
 214  Printf(stderr,"Swig_name_get:  '%s'\n", vname); 
 215#endif
 216
 217  r = NewStringEmpty();
 218  if (!naming_hash) naming_hash = NewHash();
 219  f = Getattr(naming_hash,k_get);
 220  if (!f) {
 221    Append(r,"%v_get");
 222  } else {
 223    Append(r,f);
 224  }
 225  Replace(r,"%v",vname, DOH_REPLACE_ANY);
 226  /* name_mangle(r); */
 227  return r;
 228}
 229
 230/* ----------------------------------------------------------------------------- 
 231 * Swig_name_set()
 232 *
 233 * Returns the name of the accessor function used to set a variable.
 234 * ----------------------------------------------------------------------------- */
 235
 236String *
 237Swig_name_set(const String_or_char *vname) {
 238  String *r;
 239  String *f;
 240
 241  r = NewStringEmpty();
 242  if (!naming_hash) naming_hash = NewHash();
 243  f = HashGetAttr(naming_hash,k_set);
 244  if (!f) {
 245    Append(r,"%v_set");
 246  } else {
 247    Append(r,f);
 248  }
 249  Replace(r,"%v",vname, DOH_REPLACE_ANY);
 250  /* name_mangle(r); */
 251  return r;
 252}
 253
 254/* -----------------------------------------------------------------------------
 255 * Swig_name_construct()
 256 *
 257 * Returns the name of the accessor function used to create an object.
 258 * ----------------------------------------------------------------------------- */
 259
 260String *
 261Swig_name_construct(const String_or_char *classname) {
 262  String *r;
 263  String *f;
 264  String *rclassname;
 265  char *cname;
 266
 267  rclassname = SwigType_namestr(classname);
 268  r = NewStringEmpty();
 269  if (!naming_hash) naming_hash = NewHash();
 270  f = HashGetAttr(naming_hash,k_construct);
 271  if (!f) {
 272    Append(r,"new_%c");
 273  } else {
 274    Append(r,f);
 275  }
 276
 277  cname = Char(rclassname);
 278  if ((strncmp(cname,"struct ", 7) == 0) ||
 279      ((strncmp(cname,"class ", 6) == 0)) ||
 280      ((strncmp(cname,"union ", 6) == 0))) {
 281    cname = strchr(cname, ' ')+1;
 282  }
 283  Replace(r,"%c",cname, DOH_REPLACE_ANY);
 284  Delete(rclassname);
 285  return r;
 286}
 287
 288
 289/* -----------------------------------------------------------------------------
 290 * Swig_name_copyconstructor()
 291 *
 292 * Returns the name of the accessor function used to copy an object.
 293 * ----------------------------------------------------------------------------- */
 294
 295String *
 296Swig_name_copyconstructor(const String_or_char *classname) {
 297  String *r;
 298  String *f;
 299  String *rclassname;
 300  char *cname;
 301
 302  rclassname = SwigType_namestr(classname);
 303  r = NewStringEmpty();
 304  if (!naming_hash) naming_hash = NewHash();
 305  f = HashGetAttr(naming_hash,k_copy);
 306  if (!f) {
 307    Append(r,"copy_%c");
 308  } else {
 309    Append(r,f);
 310  }
 311
 312  cname = Char(rclassname);
 313  if ((strncmp(cname,"struct ", 7) == 0) ||
 314      ((strncmp(cname,"class ", 6) == 0)) ||
 315      ((strncmp(cname,"union ", 6) == 0))) {
 316    cname = strchr(cname, ' ')+1;
 317  }
 318
 319  Replace(r,"%c",cname, DOH_REPLACE_ANY);
 320  Delete(rclassname);
 321  return r;
 322}
 323
 324/* -----------------------------------------------------------------------------
 325 * Swig_name_destroy()
 326 *
 327 * Returns the name of the accessor function used to destroy an object.
 328 * ----------------------------------------------------------------------------- */
 329
 330String *Swig_name_destroy(const String_or_char *classname) {
 331  String *r;
 332  String *f;
 333  String *rclassname;
 334  char *cname;
 335  rclassname = SwigType_namestr(classname);
 336  r = NewStringEmpty();
 337  if (!naming_hash) naming_hash = NewHash();
 338  f = HashGetAttr(naming_hash,k_destroy);
 339  if (!f) {
 340    Append(r,"delete_%c");
 341  } else {
 342    Append(r,f);
 343  }
 344
 345  cname = Char(rclassname);
 346  if ((strncmp(cname,"struct ", 7) == 0) ||
 347      ((strncmp(cname,"class ", 6) == 0)) ||
 348      ((strncmp(cname,"union ", 6) == 0))) {
 349    cname = strchr(cname, ' ')+1;
 350  }
 351  Replace(r,"%c",cname, DOH_REPLACE_ANY);
 352  Delete(rclassname);
 353  return r;
 354}
 355
 356
 357/* -----------------------------------------------------------------------------
 358 * Swig_name_disown()
 359 *
 360 * Returns the name of the accessor function used to disown an object.
 361 * ----------------------------------------------------------------------------- */
 362
 363String *Swig_name_disown(const String_or_char *classname) {
 364  String *r;
 365  String *f;
 366  String *rclassname;
 367  char *cname;
 368  rclassname = SwigType_namestr(classname);
 369  r = NewStringEmpty();
 370  if (!naming_hash) naming_hash = NewHash();
 371  f = HashGetAttr(naming_hash,k_disown);
 372  if (!f) {
 373    Append(r,"disown_%c");
 374  } else {
 375    Append(r,f);
 376  }
 377
 378  cname = Char(rclassname);
 379  if ((strncmp(cname,"struct ", 7) == 0) ||
 380      ((strncmp(cname,"class ", 6) == 0)) ||
 381      ((strncmp(cname,"union ", 6) == 0))) {
 382    cname = strchr(cname, ' ')+1;
 383  }
 384  Replace(r,"%c",cname, DOH_REPLACE_ANY);
 385  Delete(rclassname);
 386  return r;
 387}
 388
 389
 390/* -----------------------------------------------------------------------------
 391 * Swig_name_object_set()
 392 *
 393 * Sets an object associated with a name and optional declarators. 
 394 * ----------------------------------------------------------------------------- */
 395
 396void 
 397Swig_name_object_set(Hash *namehash, String *name, SwigType *decl, DOH *object) {
 398  DOH *n;
 399
 400#ifdef SWIG_DEBUG
 401  Printf(stderr,"Swig_name_object_set:  '%s', '%s'\n", name, decl); 
 402#endif
 403  n = HashGetAttr(namehash,name);
 404  if (!n) {
 405    n = NewHash();
 406    Setattr(namehash,name,n);
 407    Delete(n);
 408  }
 409  /* Add an object based on the declarator value */
 410  if (!decl) {
 411    Setattr(n,k_start,object);
 412  } else {
 413    SwigType *cd = Copy(decl);
 414    Setattr(n,cd,object);
 415    Delete(cd);
 416  }
 417}
 418
 419
 420/* -----------------------------------------------------------------------------
 421 * Swig_name_object_get()
 422 *
 423 * Return an object associated with an optional class prefix, name, and 
 424 * declarator.   This function operates according to name matching rules
 425 * described for the %rename directive in the SWIG manual.
 426 * ----------------------------------------------------------------------------- */
 427
 428static DOH *get_object(Hash *n, String *decl) {
 429  DOH *rn = 0;
 430  if (!n) return 0;
 431  if (decl) {
 432    rn = Getattr(n,decl);
 433  } else {
 434    rn = Getattr(n,k_start);
 435  }
 436  return rn;
 437}
 438
 439static
 440DOH *
 441name_object_get(Hash *namehash, String *tname, SwigType *decl, SwigType *ncdecl) {
 442  DOH* rn = 0;
 443  Hash   *n = Getattr(namehash,tname);
 444  if (n) {
 445    rn = get_object(n,decl);
 446    if ((!rn) && ncdecl) rn = get_object(n,ncdecl);
 447    if (!rn) rn = get_object(n,0);
 448  }
 449  return rn;
 450}
 451
 452DOH *
 453Swig_name_object_get(Hash *namehash, String *prefix, String *name, SwigType *decl) {
 454  String *tname = NewStringEmpty();
 455  DOH    *rn = 0;
 456  char   *ncdecl = 0;
 457
 458  if (!namehash) return 0;
 459
 460  /* DB: This removed to more tightly control feature/name matching */
 461  /*  if ((decl) && (SwigType_isqualifier(decl))) {
 462    ncdecl = strchr(Char(decl),'.');
 463    ncdecl++;
 464  }
 465  */
 466#ifdef SWIG_DEBUG
 467  Printf(stderr,"Swig_name_object_get:  '%s', '%s'\n", name, decl); 
 468#endif
 469
 470
 471  /* Perform a class-based lookup (if class prefix supplied) */
 472  if (prefix) {
 473    if (Len(prefix)) {
 474      Printf(tname,"%s::%s", prefix, name);
 475      rn = name_object_get(namehash, tname, decl, ncdecl);
 476      if (!rn) {
 477	String *cls = Swig_scopename_last(prefix);
 478	if (!Equal(cls,prefix)) {
 479	  Clear(tname);
 480	  Printf(tname,"*::%s::%s",cls,name);
 481	  rn = name_object_get(namehash, tname, decl, ncdecl);
 482	}
 483	Delete(cls);
 484      }
 485      /* A template-based class lookup, check name first */
 486      if (!rn && SwigType_istemplate(name)) {
 487	String *t_name = SwigType_templateprefix(name);
 488	if (!Equal(t_name,name)) {
 489	  rn = Swig_name_object_get(namehash, prefix, t_name, decl);
 490	}
 491	Delete(t_name);
 492      }
 493      /* A template-based class lookup */
 494      if (0 && !rn && SwigType_istemplate(prefix)) {
 495	String *t_prefix = SwigType_templateprefix(prefix);
 496	if (Strcmp(t_prefix,prefix) != 0) {
 497	  String *t_name = SwigType_templateprefix(name);
 498	  rn = Swig_name_object_get(namehash, t_prefix, t_name, decl);
 499	  Delete(t_name);
 500	}
 501	Delete(t_prefix);
 502      }
 503    } 
 504    /* A wildcard-based class lookup */
 505    if (!rn) {
 506      Clear(tname);
 507      Printf(tname,"*::%s",name);
 508      rn = name_object_get(namehash, tname, decl, ncdecl);
 509    }
 510  } else {
 511    /* Lookup in the global namespace only */
 512    Clear(tname);
 513    Printf(tname,"::%s",name);
 514    rn = name_object_get(namehash, tname, decl, ncdecl);
 515  }
 516  /* Catch-all */
 517  if (!rn) {
 518    rn = name_object_get(namehash, name, decl, ncdecl);
 519  }
 520  if (!rn && Swig_scopename_check(name)) {
 521    String *nprefix = NewStringEmpty();
 522    String *nlast = NewStringEmpty();
 523    Swig_scopename_split(name, &nprefix, &nlast);
 524    rn = name_object_get(namehash, nlast, decl, ncdecl);
 525    Delete(nlast);
 526    Delete(nprefix);
 527  }
 528  
 529  Delete(tname);
 530
 531#ifdef SWIG_DEBUG
 532  Printf(stderr,"Swig_name_object_get:  found %d\n", rn ? 1 : 0); 
 533#endif
 534
 535  return rn;
 536}
 537
 538/* -----------------------------------------------------------------------------
 539 * Swig_name_object_inherit()
 540 *
 541 * Implements name-based inheritance scheme. 
 542 * ----------------------------------------------------------------------------- */
 543
 544void
 545Swig_name_object_inherit(Hash *namehash, String *base, String *derived) {
 546  Iterator ki;
 547  String *bprefix;
 548  String *dprefix;
 549  char *cbprefix;
 550  int   plen;
 551
 552  if (!namehash) return;
 553  
 554  bprefix = NewStringf("%s::",base);
 555  dprefix = NewStringf("%s::",derived);
 556  cbprefix = Char(bprefix);
 557  plen = strlen(cbprefix);
 558  for (ki = First(namehash); ki.key; ki = Next(ki)) {
 559    char *k = Char(ki.key);
 560    if (strncmp(k,cbprefix,plen) == 0) {
 561      Iterator oi;
 562      String *nkey = NewStringf("%s%s",dprefix,k+plen);
 563      Hash *n = ki.item;
 564      Hash *newh = HashGetAttr(namehash,nkey);
 565      if (!newh) {
 566	newh = NewHash();
 567	Setattr(namehash,nkey,newh);
 568	Delete(newh);
 569      }
 570      for (oi = First(n); oi.key; oi = Next(oi)) {
 571	if (!Getattr(newh,oi.key)) {
 572	  String *ci = Copy(oi.item);
 573	  Setattr(newh,oi.key,ci);
 574	  Delete(ci);
 575	}
 576      }
 577      Delete(nkey);
 578    }
 579  }
 580  Delete(bprefix);
 581  Delete(dprefix);
 582}
 583
 584/* -----------------------------------------------------------------------------
 585 * merge_features()
 586 *
 587 * Given a hash, this function merges the features in the hash into the node.
 588 * ----------------------------------------------------------------------------- */
 589
 590static void merge_features(Hash *features, Node *n) {
 591  Iterator ki;
 592
 593  if (!features) return;
 594  for (ki = First(features); ki.key; ki = Next(ki)) {
 595    String *ci = Copy(ki.item);    
 596    Setattr(n,ki.key,ci);
 597    Delete(ci);
 598  }
 599}
 600
 601/* -----------------------------------------------------------------------------
 602 * Swig_features_get()
 603 *
 604 * Attaches any features in the features hash to the node that matches
 605 * the declaration, decl.
 606 * ----------------------------------------------------------------------------- */
 607
 608static 
 609void features_get(Hash *features, String *tname, SwigType *decl, SwigType *ncdecl, Node *node)
 610{
 611  Node *n = Getattr(features,tname);
 612#ifdef SWIG_DEBUG
 613  Printf(stderr,"  features_get: %s\n", tname);
 614#endif
 615  if (n) {
 616    merge_features(get_object(n,0),node);
 617    if (ncdecl) merge_features(get_object(n,ncdecl),node);
 618    merge_features(get_object(n,decl),node);
 619  }
 620}
 621
 622void
 623Swig_features_get(Hash *features, String *prefix, String *name, SwigType *decl, Node *node) {
 624  char   *ncdecl = 0;
 625  String *rdecl = 0;
 626  String *rname = 0;
 627  if (!features) return;
 628
 629  /* MM: This removed to more tightly control feature/name matching */
 630  /*
 631  if ((decl) && (SwigType_isqualifier(decl))) {
 632    ncdecl = strchr(Char(decl),'.');
 633    ncdecl++;
 634  }
 635  */
 636
 637  /* very specific hack for template constructors/destructors */
 638  if (name && SwigType_istemplate(name)) {
 639    String *nodetype = Getattr(node, k_nodetype);
 640    if (nodetype && (Equal(nodetype,k_constructor) || Equal(nodetype,k_destructor))) {
 641      String *nprefix = NewStringEmpty();
 642      String *nlast = NewStringEmpty();
 643      String *tprefix;
 644      Swig_scopename_split(name, &nprefix, &nlast);    
 645      tprefix = SwigType_templateprefix(nlast);
 646      Delete(nlast);
 647      if (Len(nprefix)) {
 648	Append(nprefix,"::");
 649	Append(nprefix,tprefix);
 650	Delete(tprefix);
 651	rname = nprefix;      
 652      } else {
 653	rname = tprefix;
 654	Delete(nprefix);
 655      }
 656      rdecl = Copy(decl);
 657      Replaceall(rdecl,name,rname);
 658      decl = rdecl;
 659      name = rname;
 660    }
 661  }
 662
 663  
 664#ifdef SWIG_DEBUG
 665  Printf(stderr,"Swig_features_get: %s %s %s\n", prefix, name, decl);
 666#endif
 667
 668  /* Global features */
 669  features_get(features, empty_string, 0, 0, node);
 670  if (name) {
 671    String *tname = NewStringEmpty();
 672    /* add features for 'root' template */
 673    if (SwigType_istemplate(name)) {
 674      String *dname = SwigType_templateprefix(name);
 675      features_get(features, dname, decl, ncdecl, node);
 676      Delete(dname);
 677    }
 678    /* Catch-all */
 679    features_get(features, name, decl, ncdecl, node);
 680    /* Perform a class-based lookup (if class prefix supplied) */
 681    if (prefix) {
 682      /* A class-generic feature */
 683      if (Len(prefix)) {
 684	Printf(tname,"%s::",prefix);
 685	features_get(features, tname, decl, ncdecl, node);
 686      }
 687      /* A wildcard-based class lookup */
 688      Clear(tname);
 689      Printf(tname,"*::%s",name);
 690      features_get(features, tname, decl, ncdecl, node);
 691      /* A specific class lookup */
 692      if (Len(prefix)) {
 693	/* A template-based class lookup */
 694	if (SwigType_istemplate(prefix)) {
 695	  String *tprefix = SwigType_templateprefix(prefix);
 696	  Clear(tname);
 697	  Printf(tname,"%s::%s",tprefix,name);
 698	  features_get(features, tname, decl, ncdecl, node);
 699	  Delete(tprefix);
 700	}
 701	Clear(tname);
 702	Printf(tname,"%s::%s",prefix,name);
 703	features_get(features, tname, decl, ncdecl, node);
 704      }
 705    } else {
 706      /* Lookup in the global namespace only */
 707      Clear(tname);
 708      Printf(tname,"::%s",name);
 709      features_get(features, tname, decl, ncdecl, node);
 710    }
 711    Delete(tname);
 712  }
 713  if (name && SwigType_istemplate(name)) {
 714    /* add features for complete template type */
 715    String *dname = Swig_symbol_template_deftype(name,0);
 716    if (!Equal(dname,name)) {    
 717      Swig_features_get(features, prefix, dname, decl, node);
 718    }
 719    Delete(dname);
 720  }
 721
 722  if (rname) Delete(rname);
 723  if (rdecl) Delete(rdecl);
 724}
 725
 726
 727/* -----------------------------------------------------------------------------
 728 * Swig_feature_set()
 729 *
 730 * Sets a feature name and value. Also sets optional feature attributes as
 731 * passed in by featureattribs. Optional feature attributes are given a full name
 732 * concatenating the feature name plus ':' plus the attribute name.
 733 * ----------------------------------------------------------------------------- */
 734
 735void 
 736Swig_feature_set(Hash *features, const String_or_char *name, SwigType *decl, const String_or_char *featurename, String *value, Hash *featureattribs) {
 737  Hash *n;
 738  Hash *fhash;
 739
 740#ifdef SWIG_DEBUG
 741  Printf(stderr,"Swig_feature_set: %s %s %s %s\n", name, decl, featurename,value);  
 742#endif
 743
 744  n = Getattr(features,name);
 745  if (!n) {
 746    n = NewHash();
 747    Setattr(features,name,n);
 748    Delete(n);
 749  }
 750  if (!decl) {
 751    fhash = Getattr(n,k_start);
 752    if (!fhash) {
 753      fhash = NewHash();
 754      Setattr(n,k_start,fhash);
 755      Delete(fhash);
 756    }
 757  } else {
 758    fhash = Getattr(n,decl);
 759    if (!fhash) {
 760      String *cdecl_ = Copy(decl);
 761      fhash = NewHash();
 762      Setattr(n,cdecl_,fhash);
 763      Delete(cdecl_);
 764      Delete(fhash);
 765    }
 766  }
 767  if (value) {
 768    Setattr(fhash,featurename,value);
 769  } else {
 770    Delattr(fhash,featurename);
 771  }
 772
 773  {
 774    /* Add in the optional feature attributes */
 775    Hash *attribs = featureattribs;
 776    while(attribs) {
 777      String *attribname = Getattr(attribs,k_name);
 778      String *featureattribname = NewStringf("%s:%s", featurename, attribname);
 779      if (value) {
 780        String *attribvalue = Getattr(attribs,k_value);
 781        Setattr(fhash,featureattribname,attribvalue);
 782      } else {
 783        Delattr(fhash,featureattribname);
 784      }
 785      attribs = nextSibling(attribs);
 786      Delete(featureattribname);
 787    }
 788  }
 789
 790  if (name && SwigType_istemplate(name)) {
 791    String *dname = Swig_symbol_template_deftype(name,0);
 792    if (Strcmp(dname,name)) {    
 793      Swig_feature_set(features, dname, decl, featurename, value, featureattribs);
 794    }
 795    Delete(dname);
 796  }
 797}
 798
 799/* -----------------------------------------------------------------------------
 800 * The rename/namewarn engine
 801 *
 802 * Code below was in parser.y for a while
 803 * ----------------------------------------------------------------------------- */
 804
 805static Hash   *namewarn_hash = 0;
 806Hash *Swig_name_namewarn_hash() {
 807  if (!namewarn_hash) namewarn_hash = NewHash();
 808  return namewarn_hash;
 809}
 810
 811static Hash   *rename_hash = 0;
 812Hash *Swig_name_rename_hash() {
 813  if (!rename_hash) rename_hash = NewHash();
 814  return rename_hash;
 815}
 816
 817static List   *namewarn_list = 0;
 818List *Swig_name_namewarn_list() {
 819  if (!namewarn_list) namewarn_list = NewList();
 820  return namewarn_list;
 821}
 822
 823static List   *rename_list = 0;
 824List *Swig_name_rename_list() {
 825  if (!rename_list) rename_list = NewList();
 826  return rename_list;
 827}
 828
 829/* -----------------------------------------------------------------------------
 830 * int Swig_need_name_warning(Node *n)
 831 *
 832 * Detects if a node needs name warnings 
 833 *
 834 * ----------------------------------------------------------------------------- */
 835
 836int Swig_need_name_warning(Node *n)
 837{
 838  int need = 1;
 839  /* 
 840     we don't use name warnings for:
 841     - class forwards, no symbol is generated at the target language.
 842     - template declarations, only for real instances using %template(name).
 843     - typedefs, they have no effect at the target language.
 844  */
 845  if (checkAttribute(n,k_nodetype,k_classforward)) {
 846    need = 0;
 847  } else if (checkAttribute(n,k_storage,k_typedef))  {
 848    need = 0;
 849  } else if (Getattr(n,k_hidden)) {
 850    need = 0;
 851  } else if (Getattr(n,k_ignore)) {
 852    need = 0;
 853  } else if (Getattr(n,k_templatetype)) {
 854    need = 0;
 855  }
 856  return need;
 857}
 858
 859/* -----------------------------------------------------------------------------
 860 * int Swig_need_redefined_warn()
 861 *
 862 * Detects when a redefined object needs a warning
 863 * 
 864 * ----------------------------------------------------------------------------- */
 865
 866static int nodes_are_equivalent(Node* a, Node* b, int a_inclass)
 867{
 868  /* they must have the same type */
 869  String *ta = Getattr(a,k_nodetype);
 870  String *tb = Getattr(b,k_nodetype);  
 871  if (Cmp(ta, tb) != 0) return 0;
 872  
 873  /* cdecl case */
 874  if (Cmp(ta, k_cdecl) == 0) {
 875    /* typedef */
 876    String *a_storage = Getattr(a,k_storage);
 877    String *b_storage = Getattr(b,k_storage);
 878
 879    if ((Cmp(a_storage,k_typedef) == 0)
 880	|| (Cmp(b_storage,k_typedef) == 0)) {	
 881      if (Cmp(a_storage, b_storage) == 0) {
 882	String *a_type = (Getattr(a,k_type));
 883	String *b_type = (Getattr(b,k_type));
 884	if (Cmp(a_type, b_type) == 0) return 1;
 885      }
 886      return 0;
 887    }
 888
 889    /* static functions */
 890    if ((Cmp(a_storage, k_static) == 0) 
 891	|| (Cmp(b_storage, k_static) == 0)) {
 892      if (Cmp(a_storage, b_storage) != 0) return 0;
 893    }
 894
 895    /* friend methods */
 896    
 897    if (!a_inclass || (Cmp(a_storage,k_friend) == 0)) {
 898      /* check declaration */
 899
 900      String *a_decl = (Getattr(a,k_decl));
 901      String *b_decl = (Getattr(b,k_decl));
 902      if (Cmp(a_decl, b_decl) == 0) {
 903	/* check return type */
 904	String *a_type = (Getattr(a,k_type));
 905	String *b_type = (Getattr(b,k_type));
 906	if (Cmp(a_type, b_type) == 0) {
 907	  /* check parameters */
 908	  Parm *ap = (Getattr(a,k_parms));
 909	  Parm *bp = (Getattr(b,k_parms));
 910	  while (ap && bp) {
 911	    SwigType *at = Getattr(ap,k_type);
 912	    SwigType *bt = Getattr(bp,k_type);
 913	    if (Cmp(at, bt) != 0) return 0;
 914	    ap = nextSibling(ap);
 915	    bp = nextSibling(bp);
 916	  }
 917	  if (ap || bp) {
 918	    return 0;
 919	  } else {
 920            Node *a_template = Getattr(a,k_template);
 921            Node *b_template = Getattr(b,k_template);
 922            /* Not equivalent if one is a template instantiation (via %template) and the other is a non-templated function */
 923            if ((a_template && !b_template) || (!a_template && b_template)) return 0;
 924          }
 925	  return 1;
 926	}
 927      }
 928    }
 929  } else {
 930    /* %constant case */  
 931    String *a_storage = Getattr(a,k_storage);
 932    String *b_storage = Getattr(b,k_storage);
 933    if ((Cmp(a_storage, "%constant") == 0) 
 934	|| (Cmp(b_storage, "%constant") == 0)) {
 935      if (Cmp(a_storage, b_storage) == 0) {
 936	String *a_type = (Getattr(a,k_type));
 937	String *b_type = (Getattr(b,k_type));
 938	if ((Cmp(a_type, b_type) == 0)
 939	    && (Cmp(Getattr(a,k_value), Getattr(b,k_value)) == 0))
 940	  return 1;
 941      }
 942      return 0;
 943    }
 944  }
 945  return 0;
 946}
 947
 948int Swig_need_redefined_warn(Node* a, Node* b, int InClass)
 949{
 950  String *a_name = Getattr(a,k_name);
 951  String *b_name = Getattr(b,k_name);
 952  String *a_symname = Getattr(a,k_symname);
 953  String *b_symname = Getattr(b,k_symname);
 954  /* always send a warning if a 'rename' is involved */
 955  if ((a_symname && !Equal(a_symname,a_name))
 956      || (b_symname && !Equal(b_symname,b_name))) {
 957    if (!Equal(a_name,b_name)) {
 958      return 1;
 959    }
 960  }
 961  
 962
 963  return !nodes_are_equivalent(a, b, InClass);
 964}
 965
 966
 967/* -----------------------------------------------------------------------------
 968 * int Swig_need_protected(Node* n)
 969 *
 970 * Detects when we need to fully register the protected member.
 971 * 
 972 * ----------------------------------------------------------------------------- */
 973
 974int Swig_need_protected(Node* n)
 975{
 976  /* First, 'n' looks like a function */
 977  /* if (!Swig_director_mode()) return 0; */
 978  String *nodetype = Getattr(n,k_nodetype);
 979  if ((Equal(nodetype,k_cdecl)) && SwigType_isfunction(Getattr(n,k_decl))) {
 980    String *storage = Getattr(n,k_storage);
 981    /* and the function is declared like virtual, or it has no
 982       storage. This eliminates typedef, static and so on. */ 
 983    return !storage || Equal(storage,k_virtual);
 984  } else if (Equal(nodetype,k_constructor) || Equal(nodetype,k_destructor)) {
 985    return 1;
 986  }
 987
 988  return 0;
 989}
 990
 991/* -----------------------------------------------------------------------------
 992 * void Swig_name_nameobj_add()
 993 *
 994 * Add nameobj (rename/namewarn)
 995 * 
 996 * ----------------------------------------------------------------------------- */
 997
 998static List *Swig_make_attrlist(const char *ckey) {
 999  List *list = NewList();
1000  const char *cattr = strchr(ckey,'$');
1001  if (cattr) {
1002    String *nattr;
1003    const char *rattr = strchr(++cattr,'$');
1004    while (rattr) {
1005      nattr = NewStringWithSize(cattr, rattr-cattr);
1006      Append(list,nattr);
1007      Delete(nattr);
1008      cattr = rattr + 1;
1009      rattr = strchr(cattr,'$');
1010    }
1011    nattr = NewString(cattr);
1012    Append(list,nattr);
1013    Delete(nattr);
1014  } else {
1015    Append(list,k_nodetype);
1016  }
1017  return list;
1018}
1019
1020static void Swig_name_object_attach_keys(const char *keys[], Hash *nameobj) 
1021{
1022  Node *kw = nextSibling(nameobj);
1023  List *matchlist = 0;
1024  while (kw) {
1025    Node *next = nextSibling(kw);
1026    String *kname = Getattr(kw,k_name);
1027    char *ckey = kname ? Char(kname) :  0;
1028    if (ckey) {
1029      const char **rkey;
1030      int isnotmatch = 0;
1031      int isrxsmatch = 0;      
1032      if ((strncmp(ckey,"match",5) == 0) 
1033	  || (isnotmatch = (strncmp(ckey,"notmatch",8) == 0))
1034	  || (isrxsmatch = (strncmp(ckey,"rxsmatch",8) == 0))
1035	  || (isnotmatch = isrxsmatch = (strncmp(ckey,"notrxsmatch",11) == 0))) {
1036	Hash *mi = NewHash();
1037	List *attrlist = Swig_make_attrlist(ckey);
1038	if (!matchlist) matchlist = NewList();
1039	Setattr(mi,k_value,Getattr(kw,k_value));
1040	Setattr(mi,k_attrlist,attrlist);
1041#ifdef SWIG_DEBUG 
1042	if (isrxsmatch) Printf(stderr,"rxsmatch to use: %s %s %s\n", ckey, Getattr(kw,k_value), attrlist);
1043#endif
1044	if (isnotmatch) SetFlag(mi,k_notmatch);
1045	if (isrxsmatch) SetFlag(mi,k_rxsmatch);
1046	Delete(attrlist);
1047	Append(matchlist,mi);
1048	Delete(mi);
1049	deleteNode(kw);
1050      } else {
1051	for (rkey = keys; *rkey != 0; ++rkey) {
1052	  if (strcmp(ckey,*rkey) == 0) {
1053	    Setattr(nameobj, *rkey, Getattr(kw,k_value));
1054	    deleteNode(kw);
1055	  }
1056	}
1057      }
1058    }
1059    kw = next;
1060  }
1061  if (matchlist) {
1062    Setattr(nameobj,k_matchlist,matchlist);
1063    Delete(matchlist);
1064  }
1065}
1066
1067void Swig_name_nameobj_add(Hash *name_hash, List *name_list,
1068			   String *prefix, String *name, SwigType *decl, Hash *nameobj) {
1069  String *nname = 0;
1070  if (name && Len(name)) {
1071    String *target_fmt = Getattr(nameobj,k_targetfmt);
1072    nname = prefix ? NewStringf("%s::%s",prefix, name) : NewString(name);
1073    if (target_fmt) {
1074      String *tmp = NewStringf(target_fmt, nname);
1075      Delete(nname);
1076      nname = tmp;
1077    }
1078  }  
1079  
1080  if (!nname || !Len(nname) || 
1081      Getattr(nameobj,k_fullname)  ||  /* any of these options trigger a 'list' nameobj */
1082      Getattr(nameobj,k_sourcefmt) || 
1083      Getattr(nameobj,k_matchlist)) {
1084    if (decl) Setattr(nameobj,k_decl, decl);
1085    if (nname && Len(nname)) Setattr(nameobj,k_targetname, nname);
1086    /* put the new nameobj at the beginnig of the list, such that the
1087       last inserted rule take precedence */
1088    Insert(name_list, 0, nameobj);
1089  } else {
1090    /* here we add an old 'hash' nameobj, simple and fast */
1091    Swig_name_object_set(name_hash,nname,decl,nameobj);
1092  }
1093  Delete(nname);
1094}
1095
1096/* -----------------------------------------------------------------------------
1097 * int Swig_name_match_nameobj()
1098 *
1099 * Apply and check the nameobj's math list to the node
1100 * 
1101 * ----------------------------------------------------------------------------- */
1102
1103static DOH *Swig_get_lattr(Node *n, List *lattr)
1104{
1105  DOH *res = 0;
1106  int ilen = Len(lattr);
1107  int i;
1108  for (i = 0; n && (i < ilen); ++i) {
1109    String *nattr = Getitem(lattr,i);
1110    res = Getattr(n,nattr);
1111#ifdef SWIG_DEBUG 
1112    if (!res) {
1113      Printf(stderr,"missing %s %s %s\n",nattr, Getattr(n,k_name), Getattr(n,"member"));
1114    } else {    
1115      Printf(stderr,"lattr %d %s %s\n",i, nattr, DohIsString(res) ? res : Getattr(res,k_name));
1116    }
1117#endif
1118    n = res;
1119  }
1120  return res;
1121}
1122
1123#if defined(HAVE_RXSPENCER)
1124#include <sys/types.h>
1125#include <rxspencer/regex.h>
1126#define USE_RXSPENCER
1127#endif
1128
1129#if defined(USE_RXSPENCER)
1130int Swig_name_rxsmatch_value(String *mvalue, String *value)
1131{
1132  int match = 0;
1133  char *cvalue = Char(value);
1134  char *cmvalue = Char(mvalue);
1135  regex_t compiled;
1136  int retval = regcomp(&compiled, cmvalue, REG_EXTENDED|REG_NOSUB);
1137  if(retval != 0) return 0;
1138  retval = regexec(&compiled,cvalue,0,0,0);
1139  match = (retval == REG_NOMATCH) ? 0 : 1;
1140#ifdef SWIG_DEBUG
1141  Printf(stderr,"rxsmatch_value: %s %s %d\n",cvalue,cmvalue, match);
1142#endif
1143  regfree(&compiled);
1144  return match;
1145}
1146#else
1147int Swig_name_rxsmatch_value(String *mvalue, String *value)
1148{
1149  (void)mvalue;
1150  (void)value;  
1151  return 0;
1152}
1153#endif
1154
1155int Swig_name_match_value(String *mvalue, String *value)
1156{
1157#if defined(SWIG_USE_SIMPLE_MATCHOR)
1158  int match = 0;
1159  char *cvalue = Char(value);
1160  char *cmvalue = Char(mvalue);
1161  char *sep = strchr(cmvalue,'|');
1162  while (sep && !match) {
1163    match = strncmp(cvalue,cmvalue, sep - cmvalue) == 0;
1164#ifdef SWIG_DEBUG 
1165    Printf(stderr,"match_value: %s %s %d\n",cvalue,cmvalue, match);
1166#endif
1167    cmvalue = sep + 1;
1168    sep = strchr(cmvalue,'|');
1169  }
1170  if (!match) {
1171    match = strcmp(cvalue,cmvalue) == 0;    
1172#ifdef SWIG_DEBUG 
1173    Printf(stderr,"match_value: %s %s %d\n",cvalue,cmvalue, match);
1174#endif
1175  }
1176  return match;
1177#else
1178  return StringEqual(mvalue,value);
1179#endif
1180}
1181
1182
1183int Swig_name_match_nameobj(Hash *rn, Node *n) {
1184  int match = 1;
1185  List *matchlist = HashGetAttr(rn,k_matchlist);
1186#ifdef SWIG_DEBUG 
1187  Printf(stderr,"Swig_name_match_nameobj: %s\n",Getattr(n,"name"));
1188#endif
1189  if (matchlist) {
1190    int ilen = Len(matchlist);
1191    int i;
1192    for (i = 0; match && (i < ilen); ++i) {
1193      Node *mi = Getitem(matchlist,i);
1194      List *lattr = Getattr(mi,k_attrlist);
1195      String *nval = Swig_get_lattr(n,lattr);
1196      int notmatch = GetFlag(mi,k_notmatch);
1197      int rxsmatch = GetFlag(mi,k_rxsmatch);
1198#ifdef SWIG_DEBUG 
1199      Printf(stderr,"mi %d %s re %d not %d \n", i, nval, notmatch, rxsmatch);
1200      if (rxsmatch) {
1201	Printf(stderr,"rxsmatch %s\n",lattr);
1202      }      
1203#endif
1204      match = 0;
1205      if (nval) {
1206	String *kwval = Getattr(mi,k_value);
1207	match = rxsmatch ? Swig_name_rxsmatch_value(kwval, nval) 
1208	  : Swig_name_match_value(kwval, nval);
1209#ifdef SWIG_DEBUG 
1210	Printf(stderr,"val %s %s %d %d \n",nval, kwval,match, ilen);
1211#endif
1212      }
1213      if (notmatch) match = !match;
1214    }
1215  }
1216#ifdef SWIG_DEBUG 
1217  Printf(stderr,"Swig_name_match_nameobj: %d\n",match);
1218#endif
1219  return match;
1220}
1221
1222/* -----------------------------------------------------------------------------
1223 * Hash *Swig_name_nameobj_lget()
1224 *
1225 * Get a nameobj (rename/namewarn) from the list of filters
1226 * 
1227 * ----------------------------------------------------------------------------- */
1228
1229Hash *Swig_name_nameobj_lget(List *namelist, Node *n, String *prefix, String *name, String *decl) {
1230  Hash *res = 0;
1231  if (namelist) {
1232    int len = Len(namelist);
1233    int i;
1234    int match = 0;
1235    for (i = 0; !match && (i < len); i++) {
1236      Hash *rn = Getitem(namelist,i);
1237      String *rdecl = HashGetAttr(rn,k_decl);
1238      if (rdecl && (!decl || !Equal(rdecl,decl))) {
1239	continue;
1240      } else if (Swig_name_match_nameobj(rn, n)) {
1241	String *tname = HashGetAttr(rn,k_targetname);
1242	if (tname) {
1243	  String *sfmt = HashGetAttr(rn,k_sourcefmt);
1244	  String *sname = 0;
1245	  int fullname = GetFlag(rn,k_fullname);
1246	  int rxstarget = GetFlag(rn,k_rxstarget);
1247	  if (sfmt) {
1248	    if (fullname && prefix) {
1249	      String *pname= NewStringf("%s::%s", prefix, name);
1250	      sname = NewStringf(sfmt, pname);
1251	      Delete(pname);
1252	    } else {
1253	      sname = NewStringf(sfmt, name);
1254	    }
1255	  } else {
1256	    if (fullname && prefix) {
1257	      sname = NewStringf("%s::%s", prefix, name);
1258	    } else {
1259	      sname = name;
1260	      DohIncref(name);
1261	    }
1262	  }
1263	  match = rxstarget ? Swig_name_rxsmatch_value(tname,sname) :
1264	    Swig_name_match_value(tname,sname);
1265	  Delete(sname);
1266	} else {
1267	  match = 1;
1268	}
1269      }
1270      if (match) {
1271	res = rn;
1272	break;
1273      }
1274    }
1275  }
1276  return res;
1277}
1278
1279/* -----------------------------------------------------------------------------
1280 * Swig_name_namewarn_add
1281 *
1282 * Add a namewarn objects
1283 * 
1284 * ----------------------------------------------------------------------------- */
1285
1286void Swig_name_namewarn_add(String *prefix, String *name, SwigType *decl, Hash *namewrn) {
1287  const char *namewrn_keys[] = {"rename", "error", "fullname", "sourcefmt", "targetfmt", 0};
1288  Swig_name_object_attach_keys(namewrn_keys, namewrn);
1289  Swig_name_nameobj_add(Swig_name_namewarn_hash(), Swig_name_namewarn_list(),
1290			prefix, name, decl, namewrn);
1291}
1292
1293/* -----------------------------------------------------------------------------
1294 * Hash *Swig_name_namewarn_get()
1295 *
1296 * Return the namewarn object, if there is one.
1297 * 
1298 * ----------------------------------------------------------------------------- */
1299
1300Hash *Swig_name_namewarn_get(Node *n, String *prefix, String *name,SwigType *decl) {
1301  if (!namewarn_hash && !namewarn_list) return 0;
1302  if (n) {
1303    /* Return in the obvious cases */
1304    if (!name || !Swig_need_name_warning(n)) {
1305      return 0;
1306    } else {
1307      String *access = Getattr(n,k_access);	
1308      int is_public = !access || Equal(access,k_public);
1309      if (!is_public && !Swig_need_protected(n)) {
1310	return 0;
1311      }
1312    }
1313  }
1314  if (name) {
1315    /* Check to see if the name is in the hash */
1316    Hash *wrn = Swig_name_object_get(Swig_name_namewarn_hash(),prefix,name,decl);
1317    if (wrn && !Swig_name_match_nameobj(wrn, n)) wrn = 0;
1318    if (!wrn) {
1319      wrn = Swig_name_nameobj_lget(Swig_name_namewarn_list(), n, prefix, name, decl);
1320    }
1321    if (wrn && HashGetAttr(wrn,k_error)) {
1322      if (n) {
1323	Swig_error(Getfile(n), Getline(n), "%s\n", HashGetAttr(wrn,k_name));
1324      } else {
1325	Swig_error(cparse_file, cparse_line,"%s\n", HashGetAttr(wrn,k_name));
1326      }
1327    } 
1328    return wrn;
1329  } else {
1330    return 0;
1331  }
1332}
1333
1334/* -----------------------------------------------------------------------------
1335 * String *Swig_name_warning()
1336 *
1337 * Return the name warning, if there is one.
1338 * 
1339 * ----------------------------------------------------------------------------- */
1340
1341String *Swig_name_warning(Node *n, String *prefix, String *name,SwigType *decl) {
1342  Hash *wrn = Swig_name_namewarn_get(n, prefix, name,decl);
1343  return (name && wrn) ? HashGetAttr(wrn,k_name) : 0;
1344}
1345
1346/* -----------------------------------------------------------------------------
1347 * Swig_name_rename_add()
1348 *
1349 * Manage the rename objects
1350 * 
1351 * ----------------------------------------------------------------------------- */
1352
1353static void single_rename_add(String *prefix, String *name, SwigType *decl, Hash *newname) {
1354  Swig_name_nameobj_add(Swig_name_rename_hash(), Swig_name_rename_list(),
1355			prefix, name, decl, newname);
1356}
1357
1358/* Add a new rename. Works much like new_feature including default argument handling. */
1359void Swig_name_rename_add(String *prefix, String *name, SwigType *decl, Hash *newname, 
1360			  ParmList *declaratorparms) {
1361  
1362  ParmList *declparms = declaratorparms;
1363  
1364  const char *rename_keys[] = {"fullname", "sourcefmt", "targetfmt", "continue", "rxstarget",0};
1365  Swig_name_object_attach_keys(rename_keys, newname);
1366  
1367  /* Add the name */
1368  single_rename_add(prefix, name, decl, newname);
1369  
1370  /* Add extra names if there are default parameters in the parameter list */
1371  if (decl) {
1372    int constqualifier = SwigType_isconst(decl);
1373    while (declparms) {
1374      if (ParmList_has_defaultargs(declparms)) {
1375	
1376        /* Create a parameter list for the new rename by copying all
1377           but the last (defaulted) parameter */
1378        ParmList* newparms = ParmList_copy_all_except_last_parm(declparms);
1379	
1380        /* Create new declaration - with the last parameter removed */
1381        SwigType *newdecl = Copy(decl);
1382        Delete(SwigType_pop_function(newdecl)); /* remove the old parameter list from newdecl */
1383        SwigType_add_function(newdecl,newparms);
1384        if (constqualifier)
1385          SwigType_add_qualifier(newdecl,"const");
1386	
1387        single_rename_add(prefix, name, newdecl, newname);
1388        declparms = newparms;
1389        Delete(newdecl);
1390      } else {
1391        declparms = 0;
1392      }
1393    }
1394  }
1395}
1396
1397/* -----------------------------------------------------------------------------
1398 * String *Swig_name_make()
1399 *
1400 * Make a name after applying all the rename/namewarn objects
1401 * 
1402 * ----------------------------------------------------------------------------- */
1403
1404/* Create a name applying rename/namewarn if needed */
1405static String *apply_rename(String *newname, int fullname, String *prefix, String *name)
1406{
1407  String *result = 0;
1408  if (newname && Len(newname)) {
1409    if (Strcmp(newname,"$ignore") == 0) {
1410      result = Copy(newname);
1411    } else {
1412      char *cnewname = Char(newname);
1413      if (cnewname) {
1414	int destructor = name && (*(Char(name)) == '~');
1415	String *fmt = newname;
1416	/* use name as a fmt, but avoid C++ "%" and "%=" operators */
1417	if (Len(newname) > 1 && strchr(cnewname,'%') && !(strcmp(cnewname,"%=") == 0)) { 
1418 	  if (fullname && prefix) {
1419	    result = NewStringf(fmt,prefix,name);
1420	  } else {
1421	    result = NewStringf(fmt,name);
1422	  }
1423	} else {
1424	  result = Copy(newname);
1425	}
1426	if (destructor && result && (*(Char(result)) != '~')) {
1427	  Insert(result,0,"~");
1428	}
1429      }
1430    }
1431  }
1432  
1433  return result;
1434}
1435
1436String *
1437Swig_name_make(Node *n, String *prefix, String_or_char *cname, SwigType *decl, String *oldname) {
1438  String *nname = 0;
1439  String *result = 0;
1440  String *name = NewString(cname);
1441  Hash *wrn = 0;
1442  String *rdecl = 0;
1443  String *rname = 0;
1444
1445  /* very specific hack for template constructors/destructors */
1446#ifdef SWIG_DEBUG
1447  Printf(stderr,"SWIG_name_make: looking for %s %s %s %s\n", prefix, name, decl, oldname);
1448#endif
1449
1450  if (name && n && SwigType_istemplate(name)) {
1451    String *nodetype = Getattr(n, k_nodetype);
1452    if (nodetype && (Equal(nodetype,k_constructor) || Equal(nodetype,k_destructor))) {
1453      String *nprefix = NewStringEmpty();
1454      String *nlast = NewStringEmpty();
1455      String *tprefix;
1456      Swig_scopename_split(name, &nprefix, &nlast);    
1457      tprefix = SwigType_templateprefix(nlast);
1458      Delete(nlast);
1459      if (Len(nprefix)) {
1460	Append(nprefix,"::");
1461	Append(nprefix,tprefix);
1462	Delete(tprefix);
1463	rname = nprefix;      
1464      } else {
1465	rname = tprefix;
1466	Delete(nprefix);
1467      }
1468      rdecl = Copy(decl);
1469      Replaceall(rdecl,name,rname);
1470#ifdef SWIG_DEBUG
1471      Printf(stderr,"SWIG_name_make: use new name %s %s : %s %s\n",name, decl, rname, rdecl);
1472#endif
1473      decl = rdecl;
1474      Delete(name);
1475      name = rname;
1476    }
1477  }
1478  
1479
1480  if (rename_hash || rename_list) {
1481    Hash *rn =  Swig_name_object_get(Swig_name_rename_hash(), prefix, name, decl);
1482    if (!rn || !Swig_name_match_nameobj(rn,n)) {
1483      rn = Swig_name_nameobj_lget(Swig_name_rename_list(), n, prefix, name, decl);
1484      if (rn) {
1485	String *sfmt = HashGetAttr(rn,k_sourcefmt);
1486	int fullname = GetFlag(rn,k_fullname);
1487	if (fullname && prefix) {
1488	  String *sname = NewStringf("%s::%s", prefix, name);
1489	  Delete(name);
1490	  name = sname;
1491	  prefix = 0;
1492	}
1493	if (sfmt) {
1494	  String *sname = NewStringf(sfmt, name);
1495	  Delete(name);
1496	  name = sname;
1497	}
1498      }
1499    }
1500    if (rn) {
1501      String *newname = HashGetAttr(rn,k_name);
1502      int fullname = GetFlag(rn,k_fullname);
1503      result = apply_rename(newname, fullname, prefix, name);
1504    }
1505    if (result && !Equal(result,name)) {
1506      /* operators in C++ allow aliases, we look for them */
1507      char *cresult = Char(result);
1508      if (cresult && (strncmp(cresult,"operator ",9) == 0)) {
1509	String *nresult = Swig_name_make(n, prefix, result, decl, oldname);
1510	if (!Equal(nresult,result)) {
1511	  Delete(result);
1512	  result = nresult;
1513	} else {
1514	  Delete(nresult);
1515	}
1516      }
1517    }
1518    nname = result ? result : name;
1519    wrn = Swig_name_namewarn_get(n, prefix, nname, decl);
1520    if (wrn) {
1521      String *rename = HashGetAttr(wrn,k_rename);
1522      if (rename) {
1523	String *msg = HashGetAttr(wrn,k_name);
1524	int fullname = GetFlag(wrn,k_fullname);
1525	if (result) Delete(result);
1526	result = apply_rename(rename, fullname, prefix, name);
1527	if ((msg) && (Len(msg))) {
1528	  if (!Getmeta(nname,"already_warned")) {
1529	    if (n)  {
1530	      SWIG_WARN_NODE_BEGIN(n);
1531	      Swig_warning(0,Getfile(n), Getline(n), "%s\n", msg);
1532	      SWIG_WARN_NODE_END(n);
1533	    } else {
1534	      Swig_warning(0,Getfile(name),Getline(name), "%s\n", msg);
1535	    }
1536	    Setmeta(nname,"already_warned","1");
1537	  }
1538	}
1539      }
1540    }
1541  }
1542  if (!result || !Len(result)) {
1543    if (result) Delete(result);
1544    if (oldname) {
1545      result = NewString(oldname);
1546    } else {
1547      result = NewString(cname);
1548    }
1549  }
1550  Delete(name);
1551  
1552#ifdef SWIG_DEBUG
1553  Printf(stderr,"Swig_name_make: result  '%s' '%s'\n", cname, result); 
1554#endif
1555
1556  return result;
1557}
1558
1559/* -----------------------------------------------------------------------------
1560 * void Swig_name_inherit()
1561 *
1562 * Inherit namewarn,rename, and feature objects
1563 * 
1564 * ----------------------------------------------------------------------------- */
1565
1566void Swig_name_inherit(String *base, String *derived) {
1567  /*  Printf(stderr,"base = '%s', derived = '%s'\n", base, derived); */
1568  Swig_name_object_inherit(Swig_name_rename_hash(),base,derived);
1569  Swig_name_object_inherit(Swig_name_namewarn_hash(),base,derived);
1570  Swig_name_object_inherit(Swig_cparse_features(),base,derived);
1571}