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 * typesys.c
10 *
11 * SWIG type system management. These functions are used to manage
12 * the C++ type system including typenames, typedef, type scopes,
13 * inheritance, and namespaces. Generation of support code for the
14 * run-time type checker is also handled here.
15 * ----------------------------------------------------------------------------- */
16
17 #include "swig.h"
18 #include "cparse.h"
19
20 /* -----------------------------------------------------------------------------
21 * Synopsis
22 *
23 * The purpose of this module is to manage type names and scoping issues related
24 * to the C++ type system. The primary use is tracking typenames through typedef
25 * and inheritance.
26 *
27 * New typenames are introduced by typedef, class, and enum declarations.
28 * Each type is declared in a scope. This is either the global scope, a
29 * class, or a namespace. For example:
30 *
31 * typedef int A; // Typename A, in global scope
32 * namespace Foo {
33 * typedef int A; // Typename A, in scope Foo::
34 * }
35 * class Bar { // Typename Bar, in global scope
36 * typedef int A; // Typename A, in scope Bar::
37 * }
38 *
39 * To manage scopes, the type system is constructed as a tree of hash tables. Each
40 * hash table contains the following attributes:
41 *
42 * "name" - Scope name
43 * "qname" - Fully qualified typename
44 * "typetab" - Type table containing typenames and typedef information
45 * For a given key in the typetab table, the value is a fully
46 * qualified name if not pointing to itself.
47 * "symtab" - Hash table of symbols defined in a scope
48 * "inherit" - List of inherited scopes
49 * "parent" - Parent scope
50 *
51 * The contents of these tables can be viewed for debugging using the -debug-typedef
52 * option which calls SwigType_print_scope().
53 *
54 * Typedef information is stored in the "typetab" hash table. For example,
55 * if you have these declarations:
56 *
57 * typedef int A;
58 * typedef A B;
59 * typedef B *C;
60 *
61 * typetab in scope '' contains:
62 * "A" : "int"
63 * "B" : "A"
64 * "C" : "p.B"
65 *
66 * To resolve a type back to its root type, one repeatedly expands on the type base.
67 * For example:
68 *
69 * C *[40] ---> a(40).p.C (string type representation, see stype.c)
70 * ---> a(40).p.p.B (C --> p.B)
71 * ---> a(40).p.p.A (B --> A)
72 * ---> a(40).p.p.int (A --> int)
73 *
74 *
75 * Using declarations are stored in the "typetab" hash table. For example,
76 *
77 * namespace NN {
78 * struct SS {};
79 * }
80 * namespace N {
81 * struct S {};
82 * using NN::SS;
83 * }
84 * using N::S;
85 *
86 * typetab in scope '' contains:
87 * "S" : "N::S"
88 *
89 * and typetab in scope 'N' contains:
90 * "SS" : "NN::SS"
91 * "S" : "S"
92 *
93 *
94 * For inheritance, SWIG tries to resolve types back to the base class. For instance, if
95 * you have this:
96 *
97 * class Foo {
98 * public:
99 * typedef int Integer;
100 * };
101 * struct Bar : public Foo {
102 * void blah(Integer x);
103 * };
104 *
105 * In this case typetab in scope '' contains:
106 * "Foo" : "Foo"
107 * "Bar" : "Bar"
108 * and scope 'Foo' contains:
109 * "Integer" : "int"
110 * and scope 'Bar' inherits from 'Foo' but is empty (observe that blah is not a scope or typedef)
111 *
112 * The argument type of Bar::blah will be set to Foo::Integer.
113 *
114 *
115 * The scope-inheritance mechanism is used to manage C++ using directives.
116 *
117 * namespace XX {
118 * class CC {};
119 * }
120 * namespace X {
121 * class C {};
122 * using namespace XX;
123 * }
124 * using namespace X;
125 *
126 * typetab in scope '' inherits from 'X'
127 * typetab in scope 'X' inherits from 'XX' and contains:
128 * "C" : "C"
129 * typetab in scope 'XX' contains:
130 * "CC" : "CC"
131 *
132 *
133 * The scope-inheritance mechanism is used to manage C++ namespace aliases.
134 * For example, if you have this:
135 *
136 * namespace Foo {
137 * typedef int Integer;
138 * }
139 *
140 * namespace F = Foo;
141 *
142 * In this case, F is defined as a scope that "inherits" from Foo. Internally,
143 * F will merely be an empty scope that points to Foo. SWIG will never
144 * place new type information into a namespace alias---attempts to do so
145 * will generate a warning message (in the parser) and will place information into
146 * Foo instead.
147 *
148 *----------------------------------------------------------------------------- */
149
150 static Typetab *current_scope = 0; /* Current type scope */
151 static Hash *current_typetab = 0; /* Current type table */
152 static Hash *current_symtab = 0; /* Current symbol table */
153 static Typetab *global_scope = 0; /* The global scope */
154 static Hash *scopes = 0; /* Hash table containing fully qualified scopes */
155
156 /* Performance optimization */
157 #define SWIG_TYPEDEF_RESOLVE_CACHE
158 static Hash *typedef_resolve_cache = 0;
159 static Hash *typedef_all_cache = 0;
160 static Hash *typedef_qualified_cache = 0;
161
162 static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix);
163
164 /* common attribute keys, to avoid calling find_key all the times */
165
166 /*
167 Enable this one if your language fully support SwigValueWrapper<T>.
168
169 Leaving at '0' keeps the old swig behavior, which is not
170 always safe, but is well known.
171
172 Setting at '1' activates the new scheme, which is always safe but
173 it requires all the typemaps to be ready for that.
174
175 */
176 static int value_wrapper_mode = 0;
Swig_value_wrapper_mode(int mode)177 int Swig_value_wrapper_mode(int mode) {
178 value_wrapper_mode = mode;
179 return mode;
180 }
181
182
flush_cache()183 static void flush_cache() {
184 typedef_resolve_cache = 0;
185 typedef_all_cache = 0;
186 typedef_qualified_cache = 0;
187 }
188
189 /* Initialize the scoping system */
190
SwigType_typesystem_init()191 void SwigType_typesystem_init() {
192 if (global_scope)
193 Delete(global_scope);
194 if (scopes)
195 Delete(scopes);
196
197 current_scope = NewHash();
198 global_scope = current_scope;
199
200 Setattr(current_scope, "name", ""); /* No name for global scope */
201 current_typetab = NewHash();
202 Setattr(current_scope, "typetab", current_typetab);
203
204 current_symtab = 0;
205 scopes = NewHash();
206 Setattr(scopes, "", current_scope);
207 }
208
209
210 /* -----------------------------------------------------------------------------
211 * SwigType_typedef()
212 *
213 * Defines a new typedef in the current scope. Returns -1 if the type name is
214 * already defined.
215 * ----------------------------------------------------------------------------- */
216
SwigType_typedef(const SwigType * type,const_String_or_char_ptr name)217 int SwigType_typedef(const SwigType *type, const_String_or_char_ptr name) {
218 /* Printf(stdout, "typedef %s %s\n", type, name); */
219 if (Getattr(current_typetab, name))
220 return -1; /* Already defined */
221 if (Strcmp(type, name) == 0) { /* Can't typedef a name to itself */
222 return 0;
223 }
224
225 /* Check if 'type' is already a scope. If so, we create an alias in the type
226 system for it. This is needed to make strange nested scoping problems work
227 correctly. */
228 {
229 Typetab *t = SwigType_find_scope(current_scope, type);
230 if (t) {
231 SwigType_new_scope(name);
232 SwigType_inherit_scope(t);
233 SwigType_pop_scope();
234 }
235 }
236 Setattr(current_typetab, name, type);
237 flush_cache();
238 return 0;
239 }
240
241
242 /* -----------------------------------------------------------------------------
243 * SwigType_typedef_class()
244 *
245 * Defines a class in the current scope.
246 * ----------------------------------------------------------------------------- */
247
SwigType_typedef_class(const_String_or_char_ptr name)248 int SwigType_typedef_class(const_String_or_char_ptr name) {
249 String *cname;
250 /* Printf(stdout,"class : '%s'\n", name); */
251 if (Getattr(current_typetab, name))
252 return -1; /* Already defined */
253 cname = NewString(name);
254 Setmeta(cname, "class", "1");
255 Setattr(current_typetab, cname, cname);
256 Delete(cname);
257 flush_cache();
258 return 0;
259 }
260
261 /* -----------------------------------------------------------------------------
262 * SwigType_scope_name()
263 *
264 * Returns the qualified scope name of a type table
265 * ----------------------------------------------------------------------------- */
266
SwigType_scope_name(Typetab * ttab)267 String *SwigType_scope_name(Typetab *ttab) {
268 String *qname = NewString(Getattr(ttab, "name"));
269 ttab = Getattr(ttab, "parent");
270 while (ttab) {
271 String *pname = Getattr(ttab, "name");
272 if (Len(pname)) {
273 Insert(qname, 0, "::");
274 Insert(qname, 0, pname);
275 }
276 ttab = Getattr(ttab, "parent");
277 }
278 return qname;
279 }
280
281 /* -----------------------------------------------------------------------------
282 * SwigType_new_scope()
283 *
284 * Creates a new scope
285 * ----------------------------------------------------------------------------- */
286
SwigType_new_scope(const_String_or_char_ptr name)287 void SwigType_new_scope(const_String_or_char_ptr name) {
288 Typetab *s;
289 Hash *ttab;
290 String *qname;
291
292 if (!name) {
293 name = "<unnamed>";
294 }
295 s = NewHash();
296 Setattr(s, "name", name);
297 Setattr(s, "parent", current_scope);
298 ttab = NewHash();
299 Setattr(s, "typetab", ttab);
300
301 /* Build fully qualified name */
302 qname = SwigType_scope_name(s);
303 #if 1
304 {
305 /* TODO: only do with templates? What happens with non-templates with code below? */
306 String *stripped_qname;
307 stripped_qname = SwigType_remove_global_scope_prefix(qname);
308 /* Use fully qualified name for hash key without unary scope prefix, qname may contain unary scope */
309 Setattr(scopes, stripped_qname, s);
310 Setattr(s, "qname", qname);
311 /*
312 Printf(stdout, "SwigType_new_scope stripped %s %s\n", qname, stripped_qname);
313 */
314 Delete(stripped_qname);
315 }
316 #else
317 Printf(stdout, "SwigType_new_scope %s\n", qname);
318 Setattr(scopes, qname, s);
319 Setattr(s, "qname", qname);
320 #endif
321 Delete(qname);
322
323 current_scope = s;
324 current_typetab = ttab;
325 current_symtab = 0;
326 flush_cache();
327 }
328
329 /* -----------------------------------------------------------------------------
330 * SwigType_inherit_scope()
331 *
332 * Makes the current scope inherit from another scope. This is used for both
333 * C++ class inheritance, namespaces, and namespace aliases.
334 * ----------------------------------------------------------------------------- */
335
SwigType_inherit_scope(Typetab * scope)336 void SwigType_inherit_scope(Typetab *scope) {
337 List *inherits;
338 int i, len;
339 inherits = Getattr(current_scope, "inherit");
340 if (!inherits) {
341 inherits = NewList();
342 Setattr(current_scope, "inherit", inherits);
343 Delete(inherits);
344 }
345 assert(scope != current_scope);
346
347 len = Len(inherits);
348 for (i = 0; i < len; i++) {
349 Node *n = Getitem(inherits, i);
350 if (n == scope)
351 return;
352 }
353 Append(inherits, scope);
354 }
355
356 /* -----------------------------------------------------------------------------
357 * SwigType_scope_alias()
358 *
359 * Creates a scope-alias.
360 * ----------------------------------------------------------------------------- */
361
SwigType_scope_alias(String * aliasname,Typetab * ttab)362 void SwigType_scope_alias(String *aliasname, Typetab *ttab) {
363 String *q;
364 /* Printf(stdout,"alias: '%s' '%p'\n", aliasname, ttab); */
365 q = SwigType_scope_name(current_scope);
366 if (Len(q)) {
367 Append(q, "::");
368 }
369 Append(q, aliasname);
370 Setattr(scopes, q, ttab);
371 flush_cache();
372 }
373
374 /* -----------------------------------------------------------------------------
375 * SwigType_using_scope()
376 *
377 * Import another scope into this scope.
378 * ----------------------------------------------------------------------------- */
379
SwigType_using_scope(Typetab * scope)380 void SwigType_using_scope(Typetab *scope) {
381 SwigType_inherit_scope(scope);
382 {
383 List *ulist;
384 int i, len;
385 ulist = Getattr(current_scope, "using");
386 if (!ulist) {
387 ulist = NewList();
388 Setattr(current_scope, "using", ulist);
389 Delete(ulist);
390 }
391 assert(scope != current_scope);
392 len = Len(ulist);
393 for (i = 0; i < len; i++) {
394 Typetab *n = Getitem(ulist, i);
395 if (n == scope)
396 return;
397 }
398 Append(ulist, scope);
399 }
400 flush_cache();
401 }
402
403 /* -----------------------------------------------------------------------------
404 * SwigType_pop_scope()
405 *
406 * Pop off the last scope and perform a merge operation. Returns the hash
407 * table for the scope that was popped off.
408 * ----------------------------------------------------------------------------- */
409
SwigType_pop_scope()410 Typetab *SwigType_pop_scope() {
411 Typetab *t, *old = current_scope;
412 t = Getattr(current_scope, "parent");
413 if (!t)
414 t = global_scope;
415 current_scope = t;
416 current_typetab = Getattr(t, "typetab");
417 current_symtab = Getattr(t, "symtab");
418 flush_cache();
419 return old;
420 }
421
422 /* -----------------------------------------------------------------------------
423 * SwigType_set_scope()
424 *
425 * Set the scope. Returns the old scope.
426 * ----------------------------------------------------------------------------- */
427
SwigType_set_scope(Typetab * t)428 Typetab *SwigType_set_scope(Typetab *t) {
429 Typetab *old = current_scope;
430 if (!t)
431 t = global_scope;
432 current_scope = t;
433 current_typetab = Getattr(t, "typetab");
434 current_symtab = Getattr(t, "symtab");
435 flush_cache();
436 return old;
437 }
438
439 /* -----------------------------------------------------------------------------
440 * SwigType_attach_symtab()
441 *
442 * Attaches a symbol table to a type scope
443 * ----------------------------------------------------------------------------- */
444
SwigType_attach_symtab(Symtab * sym)445 void SwigType_attach_symtab(Symtab *sym) {
446 Setattr(current_scope, "symtab", sym);
447 current_symtab = sym;
448 }
449
450 /* -----------------------------------------------------------------------------
451 * SwigType_print_scope()
452 *
453 * Debugging function for printing out current scope
454 * ----------------------------------------------------------------------------- */
455
SwigType_print_scope(void)456 void SwigType_print_scope(void) {
457 Hash *ttab;
458 Iterator i, j;
459
460 Printf(stdout, "SCOPES start =======================================\n");
461 for (i = First(scopes); i.key; i = Next(i)) {
462 Printf(stdout, "-------------------------------------------------------------\n");
463 ttab = Getattr(i.item, "typetab");
464
465 Printf(stdout, "Type scope '%s' (%p)\n", i.key, i.item);
466 {
467 List *inherit = Getattr(i.item, "inherit");
468 if (inherit) {
469 Iterator j;
470 for (j = First(inherit); j.item; j = Next(j)) {
471 Printf(stdout, " Inherits from '%s' (%p)\n", Getattr(j.item, "qname"), j.item);
472 }
473 }
474 }
475 for (j = First(ttab); j.key; j = Next(j)) {
476 Printf(stdout, "%40s -> %s\n", j.key, j.item);
477 }
478 }
479 Printf(stdout, "SCOPES finish =======================================\n");
480 }
481
SwigType_find_scope(Typetab * s,const SwigType * nameprefix)482 static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix) {
483 Typetab *ss;
484 Typetab *s_orig = s;
485 String *nnameprefix = 0;
486 static int check_parent = 1;
487 int is_template = 0;
488
489 if (Getmark(s))
490 return 0;
491 Setmark(s, 1);
492
493 is_template = SwigType_istemplate(nameprefix);
494 if (is_template) {
495 nnameprefix = SwigType_typedef_resolve_all(nameprefix);
496 nameprefix = nnameprefix;
497 }
498
499 ss = s;
500 while (ss) {
501 String *full;
502 String *qname = Getattr(ss, "qname");
503 if (qname) {
504 full = NewStringf("%s::%s", qname, nameprefix);
505 } else {
506 full = NewString(nameprefix);
507 }
508 s = Getattr(scopes, full);
509 if (!s && is_template) {
510 /* try look up scope with all the unary scope operators within the template parameter list removed */
511 SwigType *full_stripped = SwigType_remove_global_scope_prefix(full);
512 s = Getattr(scopes, full_stripped);
513 Delete(full_stripped);
514 }
515 Delete(full);
516 if (s) {
517 if (nnameprefix)
518 Delete(nnameprefix);
519 Setmark(s_orig, 0);
520 return s;
521 }
522 if (!s) {
523 /* Check inheritance */
524 List *inherit;
525 inherit = Getattr(ss, "using");
526 if (inherit) {
527 Typetab *ttab;
528 int i, len;
529 len = Len(inherit);
530 for (i = 0; i < len; i++) {
531 int oldcp = check_parent;
532 ttab = Getitem(inherit, i);
533 check_parent = 0;
534 s = SwigType_find_scope(ttab, nameprefix);
535 check_parent = oldcp;
536 if (s) {
537 if (nnameprefix)
538 Delete(nnameprefix);
539 Setmark(s_orig, 0);
540 return s;
541 }
542 }
543 }
544 }
545 if (!check_parent)
546 break;
547 ss = Getattr(ss, "parent");
548 }
549 if (nnameprefix)
550 Delete(nnameprefix);
551 Setmark(s_orig, 0);
552 return 0;
553 }
554
555 /* -----------------------------------------------------------------------------
556 * typedef_resolve()
557 *
558 * Resolves a typedef and returns a new type string. Returns 0 if there is no
559 * typedef mapping. base is a name without qualification.
560 * Internal function.
561 * ----------------------------------------------------------------------------- */
562
563 static Typetab *resolved_scope = 0;
564
565 /* Internal function */
566
_typedef_resolve(Typetab * s,String * base,int look_parent)567 static SwigType *_typedef_resolve(Typetab *s, String *base, int look_parent) {
568 Hash *ttab;
569 SwigType *type = 0;
570 List *inherit;
571 Typetab *parent;
572
573 /* if (!s) return 0; *//* now is checked below */
574 /* Printf(stdout,"Typetab %s : %s\n", Getattr(s,"name"), base); */
575
576 if (!Getmark(s)) {
577 Setmark(s, 1);
578
579 ttab = Getattr(s, "typetab");
580 type = Getattr(ttab, base);
581 if (type) {
582 resolved_scope = s;
583 Setmark(s, 0);
584 } else {
585 /* Hmmm. Not found in my scope. It could be in an inherited scope */
586 inherit = Getattr(s, "inherit");
587 if (inherit) {
588 int i, len;
589 len = Len(inherit);
590 for (i = 0; i < len; i++) {
591 type = _typedef_resolve(Getitem(inherit, i), base, 0);
592 if (type) {
593 Setmark(s, 0);
594 break;
595 }
596 }
597 }
598 if (!type) {
599 /* Hmmm. Not found in my scope. check parent */
600 if (look_parent) {
601 parent = Getattr(s, "parent");
602 type = parent ? _typedef_resolve(parent, base, 1) : 0;
603 }
604 }
605 Setmark(s, 0);
606 }
607 }
608 return type;
609 }
610
611 /* -----------------------------------------------------------------------------
612 * template_parameters_resolve()
613 *
614 * For use with templates only. Attempts to resolve one template parameter.
615 *
616 * If one of the template parameters can be resolved, the type is returned with
617 * just the one parameter resolved and the remaining parameters left as is.
618 * If none of the template parameters can be resolved, zero is returned.
619 * ----------------------------------------------------------------------------- */
620
template_parameters_resolve(const String * base)621 static String *template_parameters_resolve(const String *base) {
622 List *tparms;
623 String *suffix;
624 String *type;
625 int i, sz;
626 int rep = 0;
627 type = SwigType_templateprefix(base);
628 suffix = SwigType_templatesuffix(base);
629 Append(type, "<(");
630 tparms = SwigType_parmlist(base);
631 sz = Len(tparms);
632 for (i = 0; i < sz; i++) {
633 SwigType *tpr;
634 SwigType *tp = Getitem(tparms, i);
635 if (!rep) {
636 tpr = SwigType_typedef_resolve(tp);
637 } else {
638 tpr = 0;
639 }
640 if (tpr) {
641 Append(type, tpr);
642 Delete(tpr);
643 rep = 1;
644 } else {
645 Append(type, tp);
646 }
647 if ((i + 1) < sz)
648 Append(type, ",");
649 }
650 if (rep) {
651 Append(type, ")>");
652 Append(type, suffix);
653 } else {
654 Delete(type);
655 type = 0;
656 }
657 Delete(suffix);
658 Delete(tparms);
659 return type;
660 }
661
typedef_resolve(Typetab * s,String * base)662 static SwigType *typedef_resolve(Typetab *s, String *base) {
663 return _typedef_resolve(s, base, 1);
664 }
665
666
667 /* -----------------------------------------------------------------------------
668 * SwigType_typedef_resolve()
669 *
670 * Given a type declaration, this function looks to reduce/resolve the type via a
671 * typedef (including via C++ using declarations).
672 *
673 * If it is able to find a typedef, the resolved type is returned. If no typedef
674 * is found NULL is returned. The type name is resolved in the current scope.
675 * The type returned is not always fully qualified for the global scope, it is
676 * valid for use in the current scope. If the current scope is global scope, a
677 * fully qualified type should be returned.
678 *
679 * Some additional notes are in Doc/Manual/Extending.html.
680 * ----------------------------------------------------------------------------- */
681
682 /* #define SWIG_DEBUG */
SwigType_typedef_resolve(const SwigType * t)683 SwigType *SwigType_typedef_resolve(const SwigType *t) {
684 String *base;
685 String *type = 0;
686 String *r = 0;
687 Typetab *s;
688 Hash *ttab;
689 String *namebase = 0;
690 String *nameprefix = 0, *rnameprefix = 0;
691 int newtype = 0;
692
693 resolved_scope = 0;
694
695 #ifdef SWIG_TYPEDEF_RESOLVE_CACHE
696 if (!typedef_resolve_cache) {
697 typedef_resolve_cache = NewHash();
698 }
699 r = Getattr(typedef_resolve_cache, t);
700 if (r) {
701 resolved_scope = Getmeta(r, "scope");
702 return Copy(r);
703 }
704 #endif
705
706 base = SwigType_base(t);
707
708 #ifdef SWIG_DEBUG
709 Printf(stdout, "base = '%s' t='%s'\n", base, t);
710 #endif
711
712 if (SwigType_issimple(base)) {
713 s = current_scope;
714 ttab = current_typetab;
715 if (strncmp(Char(base), "::", 2) == 0) {
716 s = global_scope;
717 ttab = Getattr(s, "typetab");
718 Delitem(base, 0);
719 Delitem(base, 0);
720 }
721 /* Do a quick check in the local scope */
722 type = Getattr(ttab, base);
723 if (type) {
724 resolved_scope = s;
725 }
726 if (!type) {
727 /* Didn't find in this scope. We need to do a little more searching */
728 if (Swig_scopename_check(base)) {
729 /* A qualified name. */
730 Swig_scopename_split(base, &nameprefix, &namebase);
731 #ifdef SWIG_DEBUG
732 Printf(stdout, "nameprefix = '%s'\n", nameprefix);
733 #endif
734 if (nameprefix) {
735 rnameprefix = SwigType_typedef_resolve(nameprefix);
736 if(rnameprefix != NULL) {
737 #ifdef SWIG_DEBUG
738 Printf(stdout, "nameprefix '%s' is a typedef to '%s'\n", nameprefix, rnameprefix);
739 #endif
740 type = Copy(namebase);
741 Insert(type, 0, "::");
742 Insert(type, 0, rnameprefix);
743 if (strncmp(Char(type), "::", 2) == 0) {
744 Delitem(type, 0);
745 Delitem(type, 0);
746 }
747 newtype = 1;
748 } else {
749 /* Name had a prefix on it. See if we can locate the proper scope for it */
750 String *rnameprefix = template_parameters_resolve(nameprefix);
751 nameprefix = rnameprefix ? Copy(rnameprefix) : nameprefix;
752 Delete(rnameprefix);
753 s = SwigType_find_scope(s, nameprefix);
754
755 /* Couldn't locate a scope for the type. */
756 if (!s) {
757 Delete(base);
758 Delete(namebase);
759 Delete(nameprefix);
760 r = 0;
761 goto return_result;
762 }
763 /* Try to locate the name starting in the scope */
764 #ifdef SWIG_DEBUG
765 Printf(stdout, "namebase = '%s'\n", namebase);
766 #endif
767 type = typedef_resolve(s, namebase);
768 if (type && resolved_scope) {
769 /* we need to look for the resolved type, this will also
770 fix the resolved_scope if 'type' and 'namebase' are
771 declared in different scopes */
772 String *rtype = 0;
773 rtype = typedef_resolve(resolved_scope, type);
774 if (rtype)
775 type = rtype;
776 }
777 #ifdef SWIG_DEBUG
778 Printf(stdout, "%s type = '%s'\n", Getattr(s, "name"), type);
779 #endif
780 if ((type) && (!Swig_scopename_check(type)) && resolved_scope) {
781 Typetab *rtab = resolved_scope;
782 String *qname = Getattr(resolved_scope, "qname");
783 /* If qualified *and* the typename is defined from the resolved scope, we qualify */
784 if ((qname) && typedef_resolve(resolved_scope, type)) {
785 type = Copy(type);
786 Insert(type, 0, "::");
787 Insert(type, 0, qname);
788 #ifdef SWIG_DEBUG
789 Printf(stdout, "qual %s \n", type);
790 #endif
791 newtype = 1;
792 }
793 resolved_scope = rtab;
794 }
795 }
796 } else {
797 /* Name is unqualified. */
798 type = typedef_resolve(s, base);
799 }
800 } else {
801 /* Name is unqualified. */
802 type = typedef_resolve(s, base);
803 }
804 }
805
806 if (!type && SwigType_istemplate(base)) {
807 String *tprefix = SwigType_templateprefix(base);
808 String *rtprefix = SwigType_typedef_resolve(tprefix);
809 /* We're looking for a using declaration on the template prefix to resolve the template prefix
810 * in another scope. Using declaration do not have template parameters. */
811 if (rtprefix && !SwigType_istemplate(rtprefix)) {
812 String *tsuffix = SwigType_templatesuffix(base);
813 String *targs = SwigType_templateargs(base);
814 type = NewString(rtprefix);
815 newtype = 1;
816 Append(type, targs);
817 Append(type, tsuffix);
818 Delete(targs);
819 Delete(tsuffix);
820 Delete(rtprefix);
821 }
822 Delete(tprefix);
823 }
824
825 if (type && (Equal(base, type))) {
826 if (newtype)
827 Delete(type);
828 Delete(base);
829 Delete(namebase);
830 Delete(nameprefix);
831 r = 0;
832 goto return_result;
833 }
834
835 /* If the type is a template, and no typedef was found, we need to check the
836 template arguments one by one to see if they can be resolved. */
837
838 if (!type && SwigType_istemplate(base)) {
839 newtype = 1;
840 type = template_parameters_resolve(base);
841 }
842 Delete(namebase);
843 Delete(nameprefix);
844 } else {
845 if (SwigType_isfunction(base)) {
846 List *parms;
847 int i, sz;
848 int rep = 0;
849 type = NewString("f(");
850 newtype = 1;
851 parms = SwigType_parmlist(base);
852 sz = Len(parms);
853 for (i = 0; i < sz; i++) {
854 SwigType *tpr;
855 SwigType *tp = Getitem(parms, i);
856 if (!rep) {
857 tpr = SwigType_typedef_resolve(tp);
858 } else {
859 tpr = 0;
860 }
861 if (tpr) {
862 Append(type, tpr);
863 Delete(tpr);
864 rep = 1;
865 } else {
866 Append(type, tp);
867 }
868 if ((i + 1) < sz)
869 Append(type, ",");
870 }
871 Append(type, ").");
872 Delete(parms);
873 if (!rep) {
874 Delete(type);
875 type = 0;
876 }
877 } else if (SwigType_ismemberpointer(base)) {
878 String *rt;
879 String *mtype = SwigType_parm(base);
880 rt = SwigType_typedef_resolve(mtype);
881 if (rt) {
882 type = NewStringf("m(%s).", rt);
883 newtype = 1;
884 Delete(rt);
885 }
886 Delete(mtype);
887 } else {
888 type = 0;
889 }
890 }
891 r = SwigType_prefix(t);
892 if (!type) {
893 if (r && Len(r)) {
894 char *cr = Char(r);
895 if ((strstr(cr, "f(") || (strstr(cr, "m(")))) {
896 SwigType *rt = SwigType_typedef_resolve(r);
897 if (rt) {
898 Delete(r);
899 Append(rt, base);
900 Delete(base);
901 r = rt;
902 goto return_result;
903 }
904 }
905 }
906 Delete(r);
907 Delete(base);
908 r = 0;
909 goto return_result;
910 }
911 Delete(base);
912
913 /* If 'type' is an array, then the right-most qualifier in 'r' should
914 be added to 'type' after the array qualifier, so that given
915 a(7).q(volatile).double myarray // typedef volatile double[7] myarray;
916 the type
917 q(const).myarray // const myarray
918 becomes
919 a(7).q(const volatile).double // const volatile double[7]
920 and NOT
921 q(const).a(7).q(volatile).double // non-sensical type
922 */
923 if (r && Len(r) && SwigType_isarray(type)) {
924 List *r_elem;
925 String *r_qual;
926 int r_sz;
927 r_elem = SwigType_split(r);
928 r_sz = Len(r_elem);
929 r_qual = Getitem(r_elem, r_sz-1);
930 if (SwigType_isqualifier(r_qual)) {
931 String *new_r;
932 String *new_type;
933 List *type_elem;
934 String *type_qual;
935 String *r_qual_arg;
936 int i, type_sz;
937
938 type_elem = SwigType_split(type);
939 type_sz = Len(type_elem);
940
941 for (i = 0; i < type_sz; ++i) {
942 String *e = Getitem(type_elem, i);
943 if (!SwigType_isarray(e))
944 break;
945 }
946 type_qual = Copy(Getitem(type_elem, i));
947 r_qual_arg = SwigType_parm(r_qual);
948 SwigType_add_qualifier(type_qual, r_qual_arg);
949 Delete(r_qual_arg);
950 Setitem(type_elem, i, type_qual);
951
952 new_r = NewStringEmpty();
953 for (i = 0; i < r_sz-1; ++i) {
954 Append(new_r, Getitem(r_elem, i));
955 }
956 new_type = NewStringEmpty();
957 for (i = 0; i < type_sz; ++i) {
958 Append(new_type, Getitem(type_elem, i));
959 }
960 #ifdef SWIG_DEBUG
961 Printf(stdout, "r+type='%s%s' new_r+new_type='%s%s'\n", r, type, new_r, new_type);
962 #endif
963
964 Delete(r);
965 r = new_r;
966 newtype = 1;
967 type = new_type;
968 Delete(type_elem);
969 }
970 Delete(r_elem);
971 }
972
973 Append(r, type);
974 if (newtype) {
975 Delete(type);
976 }
977
978 return_result:
979 #ifdef SWIG_TYPEDEF_RESOLVE_CACHE
980 {
981 String *key = NewString(t);
982 if (r) {
983 SwigType *r1;
984 Setattr(typedef_resolve_cache, key, r);
985 Setmeta(r, "scope", resolved_scope);
986 r1 = Copy(r);
987 Delete(r);
988 r = r1;
989 }
990 Delete(key);
991 }
992 #endif
993 return r;
994 }
995
996 /* -----------------------------------------------------------------------------
997 * SwigType_typedef_resolve_all()
998 *
999 * Fully resolve a type down to its most basic datatype
1000 * ----------------------------------------------------------------------------- */
1001
SwigType_typedef_resolve_all(const SwigType * t)1002 SwigType *SwigType_typedef_resolve_all(const SwigType *t) {
1003 SwigType *n;
1004 SwigType *r;
1005 int count = 0;
1006
1007 /* Check to see if the typedef resolve has been done before by checking the cache */
1008 if (!typedef_all_cache) {
1009 typedef_all_cache = NewHash();
1010 }
1011 r = Getattr(typedef_all_cache, t);
1012 if (r) {
1013 return Copy(r);
1014 }
1015
1016 #ifdef SWIG_DEBUG
1017 Printf(stdout, "SwigType_typedef_resolve_all start ... %s\n", t);
1018 #endif
1019 /* Recursively resolve the typedef */
1020 r = NewString(t);
1021 while ((n = SwigType_typedef_resolve(r))) {
1022 Delete(r);
1023 r = n;
1024 if (++count >= 512) {
1025 Swig_error(Getfile(t), Getline(t), "Recursive typedef detected resolving '%s' to '%s' to '%s' and so on...\n", SwigType_str(t, 0), SwigType_str(SwigType_typedef_resolve(t), 0), SwigType_str(SwigType_typedef_resolve(SwigType_typedef_resolve(t)), 0));
1026 break;
1027 }
1028 }
1029
1030 /* Add the typedef to the cache for next time it is looked up */
1031 {
1032 String *key;
1033 SwigType *rr = Copy(r);
1034 key = NewString(t);
1035 Setattr(typedef_all_cache, key, rr);
1036 Delete(key);
1037 Delete(rr);
1038 }
1039 #ifdef SWIG_DEBUG
1040 Printf(stdout, "SwigType_typedef_resolve_all end === %s => %s\n", t, r);
1041 #endif
1042 return r;
1043 }
1044
1045
1046 /* -----------------------------------------------------------------------------
1047 * SwigType_typedef_qualified()
1048 *
1049 * Given a type declaration, this function tries to fully qualify it so that the
1050 * resulting type can be used in the global scope. The type name is resolved in
1051 * the current scope.
1052 *
1053 * It provides a fully qualified name, not necessarily a fully expanded name.
1054 * When a using declaration or using directive is found the type may not be fully
1055 * expanded, but it will be resolved and fully qualified for use in the global scope.
1056 *
1057 * This function is for looking up scopes to qualify a type. It does not resolve
1058 * C typedefs, it just qualifies them. See SwigType_typedef_resolve for resolving.
1059 *
1060 * If the unary scope operator (::) is used as a prefix to the type to denote global
1061 * scope, it is left in place.
1062 * ----------------------------------------------------------------------------- */
1063
SwigType_typedef_qualified(const SwigType * t)1064 SwigType *SwigType_typedef_qualified(const SwigType *t) {
1065 List *elements;
1066 String *result;
1067 int i, len;
1068
1069 if (!typedef_qualified_cache)
1070 typedef_qualified_cache = NewHash();
1071 result = Getattr(typedef_qualified_cache, t);
1072 if (result) {
1073 String *rc = Copy(result);
1074 return rc;
1075 }
1076
1077 result = NewStringEmpty();
1078 elements = SwigType_split(t);
1079 len = Len(elements);
1080 for (i = 0; i < len; i++) {
1081 String *ty = 0;
1082 String *e = Getitem(elements, i);
1083 if (SwigType_issimple(e)) {
1084 if (!SwigType_istemplate(e)) {
1085 String *isenum = 0;
1086 if (SwigType_isenum(e)) {
1087 isenum = NewString("enum ");
1088 ty = NewString(Char(e) + 5);
1089 e = ty;
1090 }
1091 resolved_scope = 0;
1092 if (typedef_resolve(current_scope, e) && resolved_scope) {
1093 /* resolved_scope contains the scope that actually resolved the symbol */
1094 String *qname = Getattr(resolved_scope, "qname");
1095 if (qname) {
1096 Insert(e, 0, "::");
1097 Insert(e, 0, qname);
1098 }
1099 } else {
1100 if (Swig_scopename_check(e)) {
1101 String *qlast;
1102 String *qname;
1103 Swig_scopename_split(e, &qname, &qlast);
1104 if (qname) {
1105 String *tqname = SwigType_typedef_qualified(qname);
1106 Clear(e);
1107 Printf(e, "%s::%s", tqname, qlast);
1108 Delete(qname);
1109 Delete(tqname);
1110 }
1111 Delete(qlast);
1112
1113 /* Automatic template instantiation might go here??? */
1114 } else {
1115 /* It's a bare name. It's entirely possible, that the
1116 name is part of a namespace. We'll check this by unrolling
1117 out of the current scope */
1118
1119 Typetab *cs = current_scope;
1120 if (cs) {
1121 Typetab *found_scope = SwigType_find_scope(cs, e);
1122 if (found_scope) {
1123 String *qs = SwigType_scope_name(found_scope);
1124 Clear(e);
1125 Append(e, qs);
1126 Delete(qs);
1127 }
1128 }
1129 }
1130 }
1131 if (isenum) {
1132 Insert(e, 0, isenum);
1133 Delete(isenum);
1134 }
1135 } else {
1136 /* Template. We need to qualify template parameters as well as the template itself */
1137 String *tprefix, *qprefix;
1138 String *tsuffix;
1139 Iterator pi;
1140 Parm *p;
1141 List *parms;
1142 ty = Swig_symbol_template_deftype(e, current_symtab);
1143 e = ty;
1144 parms = SwigType_parmlist(e);
1145 tprefix = SwigType_templateprefix(e);
1146 tsuffix = SwigType_templatesuffix(e);
1147 qprefix = SwigType_typedef_qualified(tprefix);
1148 Append(qprefix, "<(");
1149 pi = First(parms);
1150 while ((p = pi.item)) {
1151 String *qt = SwigType_typedef_qualified(p);
1152 if (Equal(qt, p)) { /* && (!Swig_scopename_check(qt))) */
1153 /* No change in value. It is entirely possible that the parameter is an integer value.
1154 If there is a symbol table associated with this scope, we're going to check for this */
1155
1156 if (current_symtab) {
1157 Node *lastnode = 0;
1158 String *value = Copy(p);
1159 while (1) {
1160 Node *n = Swig_symbol_clookup(value, current_symtab);
1161 if (n == lastnode)
1162 break;
1163 lastnode = n;
1164 if (n) {
1165 char *ntype = Char(nodeType(n));
1166 if (strcmp(ntype, "enumitem") == 0) {
1167 /* An enum item. Generate a fully qualified name */
1168 String *qn = Swig_symbol_qualified(n);
1169 if (Len(qn)) {
1170 Append(qn, "::");
1171 Append(qn, Getattr(n, "name"));
1172 Delete(value);
1173 value = qn;
1174 continue;
1175 } else {
1176 Delete(qn);
1177 break;
1178 }
1179 } else if ((strcmp(ntype, "cdecl") == 0) && (Getattr(n, "value"))) {
1180 Delete(value);
1181 value = Copy(Getattr(n, "value"));
1182 continue;
1183 }
1184 }
1185 break;
1186 }
1187 Append(qprefix, value);
1188 Delete(value);
1189 } else {
1190 Append(qprefix, p);
1191 }
1192 } else {
1193 Append(qprefix, qt);
1194 }
1195 Delete(qt);
1196 pi = Next(pi);
1197 if (pi.item) {
1198 Append(qprefix, ",");
1199 }
1200 }
1201 Append(qprefix, ")>");
1202 Append(qprefix, tsuffix);
1203 Delete(tsuffix);
1204 Clear(e);
1205 Append(e, qprefix);
1206 Delete(tprefix);
1207 Delete(qprefix);
1208 Delete(parms);
1209 }
1210 Append(result, e);
1211 Delete(ty);
1212 } else if (SwigType_isfunction(e)) {
1213 List *parms = SwigType_parmlist(e);
1214 String *s = NewString("f(");
1215 Iterator pi;
1216 pi = First(parms);
1217 while (pi.item) {
1218 String *pq = SwigType_typedef_qualified(pi.item);
1219 Append(s, pq);
1220 Delete(pq);
1221 pi = Next(pi);
1222 if (pi.item) {
1223 Append(s, ",");
1224 }
1225 }
1226 Append(s, ").");
1227 Append(result, s);
1228 Delete(s);
1229 Delete(parms);
1230 } else if (SwigType_isarray(e)) {
1231 String *ndim;
1232 String *dim = SwigType_parm(e);
1233 ndim = Swig_symbol_string_qualify(dim, 0);
1234 Printf(result, "a(%s).", ndim);
1235 Delete(dim);
1236 Delete(ndim);
1237 } else {
1238 Append(result, e);
1239 }
1240 }
1241 Delete(elements);
1242 {
1243 String *key, *cresult;
1244 key = NewString(t);
1245 cresult = NewString(result);
1246 Setattr(typedef_qualified_cache, key, cresult);
1247 Delete(key);
1248 Delete(cresult);
1249 }
1250 return result;
1251 }
1252
1253 /* -----------------------------------------------------------------------------
1254 * SwigType_istypedef()
1255 *
1256 * Checks a typename to see if it is a typedef.
1257 * ----------------------------------------------------------------------------- */
1258
SwigType_istypedef(const SwigType * t)1259 int SwigType_istypedef(const SwigType *t) {
1260 String *type;
1261
1262 type = SwigType_typedef_resolve(t);
1263 if (type) {
1264 Delete(type);
1265 return 1;
1266 } else {
1267 return 0;
1268 }
1269 }
1270
1271
1272 /* -----------------------------------------------------------------------------
1273 * SwigType_typedef_using()
1274 *
1275 * Processes a 'using' declaration to import types from one scope into another.
1276 * Name is a qualified name like A::B.
1277 * ----------------------------------------------------------------------------- */
1278
SwigType_typedef_using(const_String_or_char_ptr name)1279 int SwigType_typedef_using(const_String_or_char_ptr name) {
1280 String *base;
1281 String *td;
1282 String *prefix;
1283 Typetab *s;
1284 Typetab *tt = 0;
1285
1286 String *defined_name = 0;
1287
1288 /* Printf(stdout, "using %s\n", name); */
1289
1290 if (!Swig_scopename_check(name))
1291 return -1; /* Not properly qualified */
1292 base = Swig_scopename_last(name);
1293
1294 /* See if the base is already defined in this scope */
1295 if (Getattr(current_typetab, base)) {
1296 Delete(base);
1297 return -1;
1298 }
1299
1300 /* See if the using name is a scope */
1301 /* tt = SwigType_find_scope(current_scope,name);
1302 Printf(stdout,"tt = %p, name = '%s'\n", tt, name); */
1303
1304 /* We set up a typedef B --> A::B */
1305 Setattr(current_typetab, base, name);
1306
1307 /* Find the scope name where the symbol is defined */
1308 td = SwigType_typedef_resolve(name);
1309 /* Printf(stdout,"td = '%s' %p\n", td, resolved_scope); */
1310 if (resolved_scope) {
1311 defined_name = Getattr(resolved_scope, "qname");
1312 if (defined_name) {
1313 defined_name = Copy(defined_name);
1314 Append(defined_name, "::");
1315 Append(defined_name, base);
1316 /* Printf(stdout,"defined_name = '%s'\n", defined_name); */
1317 tt = SwigType_find_scope(current_scope, defined_name);
1318 }
1319 }
1320 if (td)
1321 Delete(td);
1322
1323
1324 /* Figure out the scope the using directive refers to */
1325 {
1326 prefix = Swig_scopename_prefix(name);
1327 if (prefix) {
1328 s = SwigType_find_scope(current_scope, prefix);
1329 if (s) {
1330 Hash *ttab = Getattr(s, "typetab");
1331 if (!Getattr(ttab, base) && defined_name) {
1332 Setattr(ttab, base, defined_name);
1333 }
1334 }
1335 }
1336 }
1337
1338 if (tt) {
1339 /* Using directive had its own scope. We need to create a new scope for it */
1340 SwigType_new_scope(base);
1341 SwigType_inherit_scope(tt);
1342 SwigType_pop_scope();
1343 }
1344
1345 if (defined_name)
1346 Delete(defined_name);
1347 Delete(prefix);
1348 Delete(base);
1349 return 0;
1350 }
1351
1352 /* -----------------------------------------------------------------------------
1353 * SwigType_isclass()
1354 *
1355 * Determines if a type defines a class or not. A class is defined by
1356 * its type-table entry maps to itself. Note: a pointer to a class is not
1357 * a class.
1358 * ----------------------------------------------------------------------------- */
1359
SwigType_isclass(const SwigType * t)1360 int SwigType_isclass(const SwigType *t) {
1361 SwigType *qty, *qtys;
1362 int isclass = 0;
1363
1364 qty = SwigType_typedef_resolve_all(t);
1365 qtys = SwigType_strip_qualifiers(qty);
1366 if (SwigType_issimple(qtys)) {
1367 String *td = SwigType_typedef_resolve(qtys);
1368 if (td) {
1369 Delete(td);
1370 }
1371 if (resolved_scope) {
1372 isclass = 1;
1373 }
1374 /* Hmmm. Not a class. If a template, it might be uninstantiated */
1375 if (!isclass) {
1376 String *tp = SwigType_istemplate_templateprefix(qtys);
1377 if (tp && Strcmp(tp, t) != 0) {
1378 isclass = SwigType_isclass(tp);
1379 }
1380 Delete(tp);
1381 }
1382 }
1383 Delete(qty);
1384 Delete(qtys);
1385 return isclass;
1386 }
1387
1388 /* -----------------------------------------------------------------------------
1389 * SwigType_type()
1390 *
1391 * Returns an integer code describing the datatype. This is only used for
1392 * compatibility with SWIG1.1 language modules and is likely to go away once
1393 * everything is based on typemaps.
1394 * ----------------------------------------------------------------------------- */
1395
SwigType_type(const SwigType * t)1396 int SwigType_type(const SwigType *t) {
1397 char *c;
1398 /* Check for the obvious stuff */
1399 c = Char(t);
1400
1401 if (strncmp(c, "p.", 2) == 0) {
1402 if (SwigType_type(c + 2) == T_CHAR)
1403 return T_STRING;
1404 else if (SwigType_type(c + 2) == T_WCHAR)
1405 return T_WSTRING;
1406 else
1407 return T_POINTER;
1408 }
1409 if (strncmp(c, "a(", 2) == 0)
1410 return T_ARRAY;
1411 if (strncmp(c, "r.", 2) == 0)
1412 return T_REFERENCE;
1413 if (strncmp(c, "z.", 2) == 0)
1414 return T_RVALUE_REFERENCE;
1415 if (strncmp(c, "m(", 2) == 0)
1416 return T_MPOINTER;
1417 if (strncmp(c, "q(", 2) == 0) {
1418 while (*c && (*c != '.'))
1419 c++;
1420 if (*c)
1421 return SwigType_type(c + 1);
1422 return T_ERROR;
1423 }
1424 if (strncmp(c, "f(", 2) == 0)
1425 return T_FUNCTION;
1426
1427 /* Look for basic types */
1428 if (strcmp(c, "int") == 0)
1429 return T_INT;
1430 if (strcmp(c, "long") == 0)
1431 return T_LONG;
1432 if (strcmp(c, "short") == 0)
1433 return T_SHORT;
1434 if (strcmp(c, "unsigned") == 0)
1435 return T_UINT;
1436 if (strcmp(c, "unsigned short") == 0)
1437 return T_USHORT;
1438 if (strcmp(c, "unsigned long") == 0)
1439 return T_ULONG;
1440 if (strcmp(c, "unsigned int") == 0)
1441 return T_UINT;
1442 if (strcmp(c, "char") == 0)
1443 return T_CHAR;
1444 if (strcmp(c, "signed char") == 0)
1445 return T_SCHAR;
1446 if (strcmp(c, "unsigned char") == 0)
1447 return T_UCHAR;
1448 if (strcmp(c, "wchar_t") == 0)
1449 return T_WCHAR;
1450 if (strcmp(c, "float") == 0)
1451 return T_FLOAT;
1452 if (strcmp(c, "double") == 0)
1453 return T_DOUBLE;
1454 if (strcmp(c, "long double") == 0)
1455 return T_LONGDOUBLE;
1456 if (!cparse_cplusplus && (strcmp(c, "float complex") == 0))
1457 return T_FLTCPLX;
1458 if (!cparse_cplusplus && (strcmp(c, "double complex") == 0))
1459 return T_DBLCPLX;
1460 if (!cparse_cplusplus && (strcmp(c, "complex") == 0))
1461 return T_COMPLEX;
1462 if (strcmp(c, "void") == 0)
1463 return T_VOID;
1464 if (strcmp(c, "bool") == 0)
1465 return T_BOOL;
1466 if (strcmp(c, "long long") == 0)
1467 return T_LONGLONG;
1468 if (strcmp(c, "unsigned long long") == 0)
1469 return T_ULONGLONG;
1470 if (strncmp(c, "enum ", 5) == 0)
1471 return T_INT;
1472 if (strcmp(c, "auto") == 0)
1473 return T_AUTO;
1474
1475 if (strcmp(c, "v(...)") == 0)
1476 return T_VARARGS;
1477 /* Hmmm. Unknown type */
1478 if (SwigType_istypedef(t)) {
1479 int r;
1480 SwigType *nt = SwigType_typedef_resolve(t);
1481 r = SwigType_type(nt);
1482 Delete(nt);
1483 return r;
1484 }
1485 return T_USER;
1486 }
1487
1488 /* -----------------------------------------------------------------------------
1489 * SwigType_alttype()
1490 *
1491 * Returns the alternative value type needed in C++ for class value
1492 * types. When swig is not sure about using a plain $ltype value,
1493 * since the class doesn't have a default constructor, or it can't be
1494 * assigned, you will get back 'SwigValueWrapper<type >'.
1495 *
1496 * This is the default behavior unless:
1497 *
1498 * 1.- swig detects a default_constructor and 'setallocate:default_constructor'
1499 * attribute.
1500 *
1501 * 2.- swig doesn't mark 'type' as non-assignable.
1502 *
1503 * 3.- the user specifies that the value wrapper is not needed by using
1504 * %feature("novaluewrapper") like so:
1505 *
1506 * %feature("novaluewrapper") MyOpaqueClass;
1507 * class MyOpaqueClass;
1508 *
1509 * The user can also force the use of the value wrapper with
1510 * %feature("valuewrapper").
1511 * ----------------------------------------------------------------------------- */
1512
SwigType_alttype(const SwigType * t,int local_tmap)1513 SwigType *SwigType_alttype(const SwigType *t, int local_tmap) {
1514 Node *n;
1515 SwigType *w = 0;
1516 int use_wrapper = 0;
1517 SwigType *td = 0;
1518
1519 if (!cparse_cplusplus)
1520 return 0;
1521
1522 if (value_wrapper_mode == 0) {
1523 /* old partial use of SwigValueTypes, it can fail for opaque types */
1524 if (local_tmap)
1525 return 0;
1526 if (SwigType_isclass(t)) {
1527 SwigType *ftd = SwigType_typedef_resolve_all(t);
1528 td = SwigType_strip_qualifiers(ftd);
1529 Delete(ftd);
1530 n = Swig_symbol_clookup(td, 0);
1531 if (n) {
1532 if (GetFlag(n, "feature:valuewrapper")) {
1533 use_wrapper = 1;
1534 } else {
1535 if (Checkattr(n, "nodeType", "class")
1536 && (!Getattr(n, "allocate:default_constructor")
1537 || (Getattr(n, "allocate:noassign")))) {
1538 use_wrapper = !GetFlag(n, "feature:novaluewrapper") || GetFlag(n, "feature:nodefault");
1539 }
1540 }
1541 } else {
1542 if (SwigType_issimple(td) && SwigType_istemplate(td)) {
1543 use_wrapper = 1;
1544 }
1545 }
1546 }
1547 } else {
1548 /* safe use of SwigValueTypes, it can fail with some typemaps */
1549 SwigType *ftd = SwigType_typedef_resolve_all(t);
1550 td = SwigType_strip_qualifiers(ftd);
1551 Delete(ftd);
1552 if (SwigType_type(td) == T_USER) {
1553 use_wrapper = 1;
1554 n = Swig_symbol_clookup(td, 0);
1555 if (n) {
1556 if ((Checkattr(n, "nodeType", "class")
1557 && !Getattr(n, "allocate:noassign")
1558 && (Getattr(n, "allocate:default_constructor")))
1559 || (GetFlag(n, "feature:novaluewrapper"))) {
1560 use_wrapper = GetFlag(n, "feature:valuewrapper");
1561 }
1562 }
1563 }
1564 }
1565
1566 if (use_wrapper) {
1567 /* Need a space before the type in case it starts "::" (since the <:
1568 * token is a digraph for [ in C++. Also need a space after the
1569 * type in case it ends with ">" since then we form the token ">>".
1570 */
1571 w = NewStringf("SwigValueWrapper< %s >", td);
1572 }
1573 Delete(td);
1574 return w;
1575 }
1576
1577 /* ----------------------------------------------------------------------------
1578 * * * * WARNING * * * ***
1579 * ***
1580 * Don't even think about modifying anything below this line unless you ***
1581 * are completely on top of *EVERY* subtle aspect of the C++ type system ***
1582 * and you are prepared to suffer endless hours of agony trying to ***
1583 * debug the SWIG run-time type checker after you break it. ***
1584 * ------------------------------------------------------------------------- */
1585
1586 /* -----------------------------------------------------------------------------
1587 * SwigType_remember()
1588 *
1589 * This function "remembers" a datatype that was used during wrapper code generation
1590 * so that a type-checking table can be generated later on. It is up to the language
1591 * modules to actually call this function--it is not done automatically.
1592 *
1593 * Type tracking is managed through two separate hash tables. The hash 'r_mangled'
1594 * is mapping between mangled type names (used in the target language) and
1595 * fully-resolved C datatypes used in the source input. The second hash 'r_resolved'
1596 * is the inverse mapping that maps fully-resolved C datatypes to all of the mangled
1597 * names in the scripting languages. For example, consider the following set of
1598 * typedef declarations:
1599 *
1600 * typedef double Real;
1601 * typedef double Float;
1602 * typedef double Point[3];
1603 *
1604 * Now, suppose that the types 'double *', 'Real *', 'Float *', 'double[3]', and
1605 * 'Point' were used in an interface file and "remembered" using this function.
1606 * The hash tables would look like this:
1607 *
1608 * r_mangled {
1609 * _p_double : [ p.double, a(3).double ]
1610 * _p_Real : [ p.double ]
1611 * _p_Float : [ p.double ]
1612 * _Point : [ a(3).double ]
1613 *
1614 * r_resolved {
1615 * p.double : [ _p_double, _p_Real, _p_Float ]
1616 * a(3).double : [ _p_double, _Point ]
1617 * }
1618 *
1619 * Together these two hash tables can be used to determine type-equivalency between
1620 * mangled typenames. To do this, we view the two hash tables as a large graph and
1621 * compute the transitive closure.
1622 * ----------------------------------------------------------------------------- */
1623
1624 static Hash *r_mangled = 0; /* Hash mapping mangled types to fully resolved types */
1625 static Hash *r_resolved = 0; /* Hash mapping resolved types to mangled types */
1626 static Hash *r_ltype = 0; /* Hash mapping mangled names to their local c type */
1627 static Hash *r_clientdata = 0; /* Hash mapping resolved types to client data */
1628 static Hash *r_mangleddata = 0; /* Hash mapping mangled types to client data */
1629 static Hash *r_remembered = 0; /* Hash of types we remembered already */
1630
1631 static void (*r_tracefunc) (const SwigType *t, String *mangled, String *clientdata) = 0;
1632
SwigType_remember_mangleddata(String * mangled,const_String_or_char_ptr clientdata)1633 void SwigType_remember_mangleddata(String *mangled, const_String_or_char_ptr clientdata) {
1634 if (!r_mangleddata) {
1635 r_mangleddata = NewHash();
1636 }
1637 Setattr(r_mangleddata, mangled, clientdata);
1638 }
1639
1640
SwigType_remember_clientdata(const SwigType * t,const_String_or_char_ptr clientdata)1641 void SwigType_remember_clientdata(const SwigType *t, const_String_or_char_ptr clientdata) {
1642 String *mt;
1643 SwigType *lt;
1644 Hash *h;
1645 SwigType *fr;
1646 SwigType *qr;
1647 String *tkey;
1648 String *cd;
1649 Hash *lthash;
1650
1651 if (!r_mangled) {
1652 r_mangled = NewHash();
1653 r_resolved = NewHash();
1654 r_ltype = NewHash();
1655 r_clientdata = NewHash();
1656 r_remembered = NewHash();
1657 }
1658
1659 {
1660 String *last;
1661 last = Getattr(r_remembered, t);
1662 if (last && (Cmp(last, clientdata) == 0))
1663 return;
1664 }
1665
1666 tkey = Copy(t);
1667 cd = clientdata ? NewString(clientdata) : NewStringEmpty();
1668 Setattr(r_remembered, tkey, cd);
1669 Delete(tkey);
1670 Delete(cd);
1671
1672 mt = SwigType_manglestr(t); /* Create mangled string */
1673
1674 if (r_tracefunc) {
1675 (*r_tracefunc) (t, mt, (String *) clientdata);
1676 }
1677
1678 if (SwigType_istypedef(t)) {
1679 lt = Copy(t);
1680 } else {
1681 lt = SwigType_ltype(t);
1682 }
1683
1684 lthash = Getattr(r_ltype, mt);
1685 if (!lthash) {
1686 lthash = NewHash();
1687 Setattr(r_ltype, mt, lthash);
1688 }
1689 Setattr(lthash, lt, "1");
1690 Delete(lt);
1691
1692 fr = SwigType_typedef_resolve_all(t); /* Create fully resolved type */
1693 qr = SwigType_typedef_qualified(fr);
1694 Delete(fr);
1695
1696 /* Added to deal with possible table bug */
1697 fr = SwigType_strip_qualifiers(qr);
1698 Delete(qr);
1699
1700 /*Printf(stdout,"t = '%s'\n", t);
1701 Printf(stdout,"fr= '%s'\n\n", fr); */
1702
1703 if (t) {
1704 char *ct = Char(t);
1705 if (strchr(ct, '<') && !(strstr(ct, "<("))) {
1706 Printf(stdout, "Bad template type passed to SwigType_remember: %s\n", t);
1707 assert(0);
1708 }
1709 }
1710
1711 h = Getattr(r_mangled, mt);
1712 if (!h) {
1713 h = NewHash();
1714 Setattr(r_mangled, mt, h);
1715 Delete(h);
1716 }
1717 Setattr(h, fr, mt);
1718
1719 h = Getattr(r_resolved, fr);
1720 if (!h) {
1721 h = NewHash();
1722 Setattr(r_resolved, fr, h);
1723 Delete(h);
1724 }
1725 Setattr(h, mt, fr);
1726
1727 if (clientdata) {
1728 String *cd = Getattr(r_clientdata, fr);
1729 if (cd) {
1730 if (Strcmp(clientdata, cd) != 0) {
1731 Printf(stderr, "*** Internal error. Inconsistent clientdata for type '%s'\n", SwigType_str(fr, 0));
1732 Printf(stderr, "*** '%s' != '%s'\n", clientdata, cd);
1733 assert(0);
1734 }
1735 } else {
1736 String *cstr = NewString(clientdata);
1737 Setattr(r_clientdata, fr, cstr);
1738 Delete(cstr);
1739 }
1740 }
1741
1742 /* If the remembered type is a reference, we also remember the pointer version.
1743 This is to prevent odd problems with mixing pointers and references--especially
1744 when different functions are using different typenames (via typedef). */
1745
1746 if (SwigType_isreference(t)) {
1747 SwigType *tt = Copy(t);
1748 SwigType_del_reference(tt);
1749 SwigType_add_pointer(tt);
1750 SwigType_remember_clientdata(tt, clientdata);
1751 } else if (SwigType_isrvalue_reference(t)) {
1752 SwigType *tt = Copy(t);
1753 SwigType_del_rvalue_reference(tt);
1754 SwigType_add_pointer(tt);
1755 SwigType_remember_clientdata(tt, clientdata);
1756 }
1757 }
1758
SwigType_remember(const SwigType * ty)1759 void SwigType_remember(const SwigType *ty) {
1760 SwigType_remember_clientdata(ty, 0);
1761 }
1762
SwigType_remember_trace(void (* tf)(const SwigType *,String *,String *))1763 void (*SwigType_remember_trace(void (*tf) (const SwigType *, String *, String *))) (const SwigType *, String *, String *) {
1764 void (*o) (const SwigType *, String *, String *) = r_tracefunc;
1765 r_tracefunc = tf;
1766 return o;
1767 }
1768
1769 /* -----------------------------------------------------------------------------
1770 * SwigType_equivalent_mangle()
1771 *
1772 * Return a list of all of the mangled typenames that are equivalent to another
1773 * mangled name. This works as follows: For each fully qualified C datatype
1774 * in the r_mangled hash entry, we collect all of the mangled names from the
1775 * r_resolved hash and combine them together in a list (removing duplicate entries).
1776 * ----------------------------------------------------------------------------- */
1777
SwigType_equivalent_mangle(String * ms,Hash * checked,Hash * found)1778 List *SwigType_equivalent_mangle(String *ms, Hash *checked, Hash *found) {
1779 List *l;
1780 Hash *h;
1781 Hash *ch;
1782 Hash *mh;
1783
1784 if (found) {
1785 h = found;
1786 } else {
1787 h = NewHash();
1788 }
1789 if (checked) {
1790 ch = checked;
1791 } else {
1792 ch = NewHash();
1793 }
1794 if (Getattr(ch, ms))
1795 goto check_exit; /* Already checked this type */
1796 Setattr(h, ms, "1");
1797 Setattr(ch, ms, "1");
1798 mh = Getattr(r_mangled, ms);
1799 if (mh) {
1800 Iterator ki;
1801 ki = First(mh);
1802 while (ki.key) {
1803 Hash *rh;
1804 if (Getattr(ch, ki.key)) {
1805 ki = Next(ki);
1806 continue;
1807 }
1808 Setattr(ch, ki.key, "1");
1809 rh = Getattr(r_resolved, ki.key);
1810 if (rh) {
1811 Iterator rk;
1812 rk = First(rh);
1813 while (rk.key) {
1814 Setattr(h, rk.key, "1");
1815 SwigType_equivalent_mangle(rk.key, ch, h);
1816 rk = Next(rk);
1817 }
1818 }
1819 ki = Next(ki);
1820 }
1821 }
1822 check_exit:
1823 if (!found) {
1824 l = Keys(h);
1825 Delete(h);
1826 Delete(ch);
1827 return l;
1828 } else {
1829 return 0;
1830 }
1831 }
1832
1833 /* -----------------------------------------------------------------------------
1834 * SwigType_clientdata_collect()
1835 *
1836 * Returns the clientdata field for a mangled type-string.
1837 * ----------------------------------------------------------------------------- */
1838
1839 static
SwigType_clientdata_collect(String * ms)1840 String *SwigType_clientdata_collect(String *ms) {
1841 Hash *mh;
1842 String *clientdata = 0;
1843
1844 if (r_mangleddata) {
1845 clientdata = Getattr(r_mangleddata, ms);
1846 if (clientdata)
1847 return clientdata;
1848 }
1849
1850 mh = Getattr(r_mangled, ms);
1851 if (mh) {
1852 Iterator ki;
1853 ki = First(mh);
1854 while (ki.key) {
1855 clientdata = Getattr(r_clientdata, ki.key);
1856 if (clientdata)
1857 break;
1858 ki = Next(ki);
1859 }
1860 }
1861 return clientdata;
1862 }
1863
1864
1865
1866
1867 /* -----------------------------------------------------------------------------
1868 * SwigType_inherit()
1869 *
1870 * Record information about inheritance. We keep a hash table that keeps
1871 * a mapping between base classes and all of the classes that are derived
1872 * from them.
1873 *
1874 * subclass is a hash that maps base-classes to all of the classes derived from them.
1875 *
1876 * derived - name of derived class
1877 * base - name of base class
1878 * cast - additional casting code when casting from derived to base
1879 * conversioncode - if set, overrides the default code in the function when casting
1880 * from derived to base
1881 * ----------------------------------------------------------------------------- */
1882
1883 static Hash *subclass = 0;
1884 static Hash *conversions = 0;
1885
SwigType_inherit(String * derived,String * base,String * cast,String * conversioncode)1886 void SwigType_inherit(String *derived, String *base, String *cast, String *conversioncode) {
1887 Hash *h;
1888 String *dd = 0;
1889 String *bb = 0;
1890 if (!subclass)
1891 subclass = NewHash();
1892
1893 /* Printf(stdout,"'%s' --> '%s' '%s'\n", derived, base, cast); */
1894
1895 if (SwigType_istemplate(derived)) {
1896 String *ty = SwigType_typedef_resolve_all(derived);
1897 dd = SwigType_typedef_qualified(ty);
1898 derived = dd;
1899 Delete(ty);
1900 }
1901 if (SwigType_istemplate(base)) {
1902 String *ty = SwigType_typedef_resolve_all(base);
1903 bb = SwigType_typedef_qualified(ty);
1904 base = bb;
1905 Delete(ty);
1906 }
1907
1908 /* Printf(stdout,"'%s' --> '%s' '%s'\n", derived, base, cast); */
1909
1910 h = Getattr(subclass, base);
1911 if (!h) {
1912 h = NewHash();
1913 Setattr(subclass, base, h);
1914 Delete(h);
1915 }
1916 if (!Getattr(h, derived)) {
1917 Hash *c = NewHash();
1918 if (cast)
1919 Setattr(c, "cast", cast);
1920 if (conversioncode)
1921 Setattr(c, "convcode", conversioncode);
1922 Setattr(h, derived, c);
1923 Delete(c);
1924 }
1925
1926 Delete(dd);
1927 Delete(bb);
1928 }
1929
1930 /* -----------------------------------------------------------------------------
1931 * SwigType_issubtype()
1932 *
1933 * Determines if a t1 is a subtype of t2, ie, is t1 derived from t2
1934 * ----------------------------------------------------------------------------- */
1935
SwigType_issubtype(const SwigType * t1,const SwigType * t2)1936 int SwigType_issubtype(const SwigType *t1, const SwigType *t2) {
1937 SwigType *ft1, *ft2;
1938 String *b1, *b2;
1939 Hash *h;
1940 int r = 0;
1941
1942 if (!subclass)
1943 return 0;
1944
1945 ft1 = SwigType_typedef_resolve_all(t1);
1946 ft2 = SwigType_typedef_resolve_all(t2);
1947 b1 = SwigType_base(ft1);
1948 b2 = SwigType_base(ft2);
1949
1950 h = Getattr(subclass, b2);
1951 if (h) {
1952 if (Getattr(h, b1)) {
1953 r = 1;
1954 }
1955 }
1956 Delete(ft1);
1957 Delete(ft2);
1958 Delete(b1);
1959 Delete(b2);
1960 /* Printf(stdout, "issubtype(%s,%s) --> %d\n", t1, t2, r); */
1961 return r;
1962 }
1963
1964 /* -----------------------------------------------------------------------------
1965 * SwigType_inherit_equiv()
1966 *
1967 * Modify the type table to handle C++ inheritance
1968 * ----------------------------------------------------------------------------- */
1969
SwigType_inherit_equiv(File * out)1970 void SwigType_inherit_equiv(File *out) {
1971 String *ckey;
1972 String *prefix, *base;
1973 String *mprefix, *mkey;
1974 Hash *sub;
1975 Hash *rh;
1976 List *rlist;
1977 Iterator rk, bk, ck;
1978
1979 if (!conversions)
1980 conversions = NewHash();
1981 if (!subclass)
1982 subclass = NewHash();
1983
1984 rk = First(r_resolved);
1985 while (rk.key) {
1986 /* rkey is a fully qualified type. We strip all of the type constructors off of it just to get the base */
1987 base = SwigType_base(rk.key);
1988 /* Check to see whether the base is recorded in the subclass table */
1989 sub = Getattr(subclass, base);
1990 Delete(base);
1991 if (!sub) {
1992 rk = Next(rk);
1993 continue;
1994 }
1995
1996 /* This type has subclasses. We now need to walk through these subtypes and generate pointer conversion functions */
1997
1998 rh = Getattr(r_resolved, rk.key);
1999 rlist = NewList();
2000 for (ck = First(rh); ck.key; ck = Next(ck)) {
2001 Append(rlist, ck.key);
2002 }
2003 /* Printf(stdout,"rk.key = '%s'\n", rk.key);
2004 Printf(stdout,"rh = %p '%s'\n", rh,rh); */
2005
2006 bk = First(sub);
2007 while (bk.key) {
2008 prefix = SwigType_prefix(rk.key);
2009 Append(prefix, bk.key);
2010 /* Printf(stdout,"set %p = '%s' : '%s'\n", rh, SwigType_manglestr(prefix),prefix); */
2011 mprefix = SwigType_manglestr(prefix);
2012 Setattr(rh, mprefix, prefix);
2013 mkey = SwigType_manglestr(rk.key);
2014 ckey = NewStringf("%s+%s", mprefix, mkey);
2015 if (!Getattr(conversions, ckey)) {
2016 String *convname = NewStringf("%sTo%s", mprefix, mkey);
2017 String *lkey = SwigType_lstr(rk.key, 0);
2018 String *lprefix = SwigType_lstr(prefix, 0);
2019 Hash *subhash = Getattr(sub, bk.key);
2020 String *convcode = Getattr(subhash, "convcode");
2021 if (convcode) {
2022 char *newmemoryused = Strstr(convcode, "newmemory"); /* see if newmemory parameter is used in order to avoid unused parameter warnings */
2023 String *fn = Copy(convcode);
2024 Replaceall(fn, "$from", "x");
2025 Printf(out, "static void *%s(void *x, int *%s) {", convname, newmemoryused ? "newmemory" : "SWIGUNUSEDPARM(newmemory)");
2026 Printf(out, "%s", fn);
2027 } else {
2028 String *cast = Getattr(subhash, "cast");
2029 Printf(out, "static void *%s(void *x, int *SWIGUNUSEDPARM(newmemory)) {", convname);
2030 Printf(out, "\n return (void *)((%s) ", lkey);
2031 if (cast)
2032 Printf(out, "%s", cast);
2033 Printf(out, " ((%s) x));\n", lprefix);
2034 }
2035 Printf(out, "}\n");
2036 Setattr(conversions, ckey, convname);
2037 Delete(ckey);
2038 Delete(lkey);
2039 Delete(lprefix);
2040
2041 /* This inserts conversions for typedefs */
2042 {
2043 Hash *r = Getattr(r_resolved, prefix);
2044 if (r) {
2045 Iterator rrk;
2046 rrk = First(r);
2047 while (rrk.key) {
2048 Iterator rlk;
2049 String *rkeymangle;
2050
2051 /* Make sure this name equivalence is not due to inheritance */
2052 if (Cmp(prefix, Getattr(r, rrk.key)) == 0) {
2053 rkeymangle = Copy(mkey);
2054 ckey = NewStringf("%s+%s", rrk.key, rkeymangle);
2055 if (!Getattr(conversions, ckey)) {
2056 Setattr(conversions, ckey, convname);
2057 }
2058 Delete(ckey);
2059 for (rlk = First(rlist); rlk.item; rlk = Next(rlk)) {
2060 ckey = NewStringf("%s+%s", rrk.key, rlk.item);
2061 Setattr(conversions, ckey, convname);
2062 Delete(ckey);
2063 }
2064 Delete(rkeymangle);
2065 /* This is needed to pick up other alternative names for the same type.
2066 Needed to make templates work */
2067 Setattr(rh, rrk.key, rrk.item);
2068 }
2069 rrk = Next(rrk);
2070 }
2071 }
2072 }
2073 Delete(convname);
2074 }
2075 Delete(prefix);
2076 Delete(mprefix);
2077 Delete(mkey);
2078 bk = Next(bk);
2079 }
2080 rk = Next(rk);
2081 Delete(rlist);
2082 }
2083 }
2084
2085 /* Helper function to sort the mangled list */
SwigType_compare_mangled(const DOH * a,const DOH * b)2086 static int SwigType_compare_mangled(const DOH *a, const DOH *b) {
2087 return strcmp((char *) Data(a), (char *) Data(b));
2088 }
2089
2090 /* -----------------------------------------------------------------------------
2091 * SwigType_get_sorted_mangled_list()
2092 *
2093 * Returns the sorted list of mangled type names that should be exported into the
2094 * wrapper file.
2095 * ----------------------------------------------------------------------------- */
SwigType_get_sorted_mangled_list()2096 List *SwigType_get_sorted_mangled_list() {
2097 List *l = Keys(r_mangled);
2098 SortList(l, SwigType_compare_mangled);
2099 return l;
2100 }
2101
2102
2103 /* -----------------------------------------------------------------------------
2104 * SwigType_type_table()
2105 *
2106 * Generate the type-table for the type-checker.
2107 * ----------------------------------------------------------------------------- */
2108
SwigType_emit_type_table(File * f_forward,File * f_table)2109 void SwigType_emit_type_table(File *f_forward, File *f_table) {
2110 Iterator ki;
2111 String *types, *table, *cast, *cast_init, *cast_temp;
2112 Hash *imported_types;
2113 List *mangled_list;
2114 List *table_list = NewList();
2115 int i = 0;
2116
2117 if (!r_mangled) {
2118 r_mangled = NewHash();
2119 r_resolved = NewHash();
2120 }
2121
2122 Printf(f_table, "\n/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */\n\n");
2123
2124 SwigType_inherit_equiv(f_table);
2125
2126 /*#define DEBUG 1*/
2127 #ifdef DEBUG
2128 Printf(stdout, "---r_mangled---\n");
2129 Printf(stdout, "%s\n", r_mangled);
2130
2131 Printf(stdout, "---r_resolved---\n");
2132 Printf(stdout, "%s\n", r_resolved);
2133
2134 Printf(stdout, "---r_ltype---\n");
2135 Printf(stdout, "%s\n", r_ltype);
2136
2137 Printf(stdout, "---subclass---\n");
2138 Printf(stdout, "%s\n", subclass);
2139
2140 Printf(stdout, "---conversions---\n");
2141 Printf(stdout, "%s\n", conversions);
2142
2143 Printf(stdout, "---r_clientdata---\n");
2144 Printf(stdout, "%s\n", r_clientdata);
2145
2146 #endif
2147 table = NewStringEmpty();
2148 types = NewStringEmpty();
2149 cast = NewStringEmpty();
2150 cast_init = NewStringEmpty();
2151 imported_types = NewHash();
2152
2153 Printf(table, "static swig_type_info *swig_type_initial[] = {\n");
2154 Printf(cast_init, "static swig_cast_info *swig_cast_initial[] = {\n");
2155
2156 Printf(f_forward, "\n/* -------- TYPES TABLE (BEGIN) -------- */\n\n");
2157
2158 mangled_list = SwigType_get_sorted_mangled_list();
2159 for (ki = First(mangled_list); ki.item; ki = Next(ki)) {
2160 List *el;
2161 Iterator ei;
2162 SwigType *lt;
2163 SwigType *rt = 0;
2164 String *nt;
2165 String *ln;
2166 String *rn;
2167 const String *cd;
2168 Hash *lthash;
2169 Iterator ltiter;
2170 Hash *nthash;
2171
2172 cast_temp = NewStringEmpty();
2173
2174 Printv(types, "static swig_type_info _swigt_", ki.item, " = {", NIL);
2175 Append(table_list, ki.item);
2176 Printf(cast_temp, "static swig_cast_info _swigc_%s[] = {", ki.item);
2177 i++;
2178
2179 cd = SwigType_clientdata_collect(ki.item);
2180 if (!cd)
2181 cd = "0";
2182
2183 lthash = Getattr(r_ltype, ki.item);
2184 nt = 0;
2185 nthash = NewHash();
2186 ltiter = First(lthash);
2187 while (ltiter.key) {
2188 lt = ltiter.key;
2189 rt = SwigType_typedef_resolve_all(lt);
2190 /* we save the original type and the fully resolved version */
2191 ln = SwigType_lstr(lt, 0);
2192 rn = SwigType_lstr(rt, 0);
2193 if (Equal(ln, rn)) {
2194 Setattr(nthash, ln, "1");
2195 } else {
2196 Setattr(nthash, rn, "1");
2197 Setattr(nthash, ln, "1");
2198 }
2199 if (SwigType_istemplate(rt)) {
2200 String *dt = Swig_symbol_template_deftype(rt, 0);
2201 String *dn = SwigType_lstr(dt, 0);
2202 if (!Equal(dn, rn) && !Equal(dn, ln)) {
2203 Setattr(nthash, dn, "1");
2204 }
2205 Delete(dt);
2206 Delete(dn);
2207 }
2208
2209 ltiter = Next(ltiter);
2210 }
2211
2212 /* now build nt */
2213 ltiter = First(nthash);
2214 nt = 0;
2215 while (ltiter.key) {
2216 if (nt) {
2217 Printf(nt, "|%s", ltiter.key);
2218 } else {
2219 nt = NewString(ltiter.key);
2220 }
2221 ltiter = Next(ltiter);
2222 }
2223 Delete(nthash);
2224
2225 Printf(types, "\"%s\", \"%s\", 0, 0, (void*)%s, 0};\n", ki.item, nt, cd);
2226
2227 el = SwigType_equivalent_mangle(ki.item, 0, 0);
2228 for (ei = First(el); ei.item; ei = Next(ei)) {
2229 String *ckey;
2230 String *conv;
2231 ckey = NewStringf("%s+%s", ei.item, ki.item);
2232 conv = Getattr(conversions, ckey);
2233 if (conv) {
2234 Printf(cast_temp, " {&_swigt_%s, %s, 0, 0},", ei.item, conv);
2235 } else {
2236 Printf(cast_temp, " {&_swigt_%s, 0, 0, 0},", ei.item);
2237 }
2238 Delete(ckey);
2239
2240 if (!Getattr(r_mangled, ei.item) && !Getattr(imported_types, ei.item)) {
2241 Printf(types, "static swig_type_info _swigt_%s = {\"%s\", 0, 0, 0, 0, 0};\n", ei.item, ei.item);
2242 Append(table_list, ei.item);
2243
2244 Printf(cast, "static swig_cast_info _swigc_%s[] = {{&_swigt_%s, 0, 0, 0},{0, 0, 0, 0}};\n", ei.item, ei.item);
2245 i++;
2246
2247 Setattr(imported_types, ei.item, "1");
2248 }
2249 }
2250 Delete(el);
2251 Printf(cast, "%s{0, 0, 0, 0}};\n", cast_temp);
2252 Delete(cast_temp);
2253 Delete(nt);
2254 Delete(rt);
2255 }
2256 /* print the tables in the proper order */
2257 SortList(table_list, SwigType_compare_mangled);
2258 i = 0;
2259 for (ki = First(table_list); ki.item; ki = Next(ki)) {
2260 Printf(f_forward, "#define SWIGTYPE%s swig_types[%d]\n", ki.item, i++);
2261 Printf(table, " &_swigt_%s,\n", ki.item);
2262 Printf(cast_init, " _swigc_%s,\n", ki.item);
2263 }
2264 if (i == 0) {
2265 /* empty arrays are not allowed by ISO C */
2266 Printf(table, " NULL\n");
2267 Printf(cast_init, " NULL\n");
2268 }
2269
2270 Delete(table_list);
2271
2272 Delete(mangled_list);
2273
2274 Printf(table, "};\n");
2275 Printf(cast_init, "};\n");
2276 Printf(f_table, "%s\n", types);
2277 Printf(f_table, "%s\n", table);
2278 Printf(f_table, "%s\n", cast);
2279 Printf(f_table, "%s\n", cast_init);
2280 Printf(f_table, "\n/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */\n\n");
2281
2282 Printf(f_forward, "static swig_type_info *swig_types[%d];\n", i + 1);
2283 Printf(f_forward, "static swig_module_info swig_module = {swig_types, %d, 0, 0, 0, 0};\n", i);
2284 Printf(f_forward, "#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)\n");
2285 Printf(f_forward, "#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)\n");
2286 Printf(f_forward, "\n/* -------- TYPES TABLE (END) -------- */\n\n");
2287
2288 Delete(types);
2289 Delete(table);
2290 Delete(cast);
2291 Delete(cast_init);
2292 Delete(imported_types);
2293 }
2294