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