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