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