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