import source from 1.3.40
[external/swig.git] / Source / Modules / typepass.cxx
1 /* ----------------------------------------------------------------------------- 
2  * See the LICENSE file for information on copyright, usage and redistribution
3  * of SWIG, and the README file for authors - http://www.swig.org/release.html.
4  *
5  * typepass.cxx
6  *
7  * This module builds all of the internal type information by collecting
8  * typedef declarations as well as registering classes, structures, and unions.
9  * This information is needed to correctly handle shadow classes and other
10  * advanced features.   This phase of compilation is also used to perform
11  * type-expansion.  All types are fully qualified with namespace prefixes
12  * and other information needed for compilation.
13  * ----------------------------------------------------------------------------- */
14
15 char cvsroot_typepass_cxx[] = "$Id: typepass.cxx 11279 2009-06-16 19:29:08Z wsfulton $";
16
17 #include "swigmod.h"
18 #include "cparse.h"
19
20 struct normal_node {
21   Symtab *symtab;
22   Hash *typescope;
23   List *normallist;
24   normal_node *next;
25 };
26
27 static normal_node *patch_list = 0;
28
29 /* Singleton class - all non-static methods in this class are private */
30 class TypePass:private Dispatcher {
31   Node *inclass;
32   Node *module;
33   int importmode;
34   String *nsname;
35   Hash *classhash;
36   List *normalize;
37
38   TypePass() {
39   }
40
41   /* Normalize a type. Replaces type with fully qualified version */
42   void normalize_type(SwigType *ty) {
43     SwigType *qty;
44     if (CPlusPlus) {
45       Replaceall(ty, "struct ", "");
46       Replaceall(ty, "union ", "");
47       Replaceall(ty, "class ", "");
48     }
49
50     qty = SwigType_typedef_qualified(ty);
51     /*    Printf(stdout,"%s --> %s\n", ty, qty); */
52     Clear(ty);
53     Append(ty, qty);
54     Delete(qty);
55   }
56
57   /* Normalize a parameter list */
58
59   void normalize_parms(ParmList *p) {
60     while (p) {
61       SwigType *ty = Getattr(p, "type");
62       normalize_type(ty);
63       /* This is a check for a function type */
64       {
65         SwigType *qty = SwigType_typedef_resolve_all(ty);
66         if (SwigType_isfunction(qty)) {
67           SwigType_add_pointer(ty);
68         }
69         Delete(qty);
70       }
71
72       String *value = Getattr(p, "value");
73       if (value) {
74         Node *n = Swig_symbol_clookup(value, 0);
75         if (n) {
76           String *q = Swig_symbol_qualified(n);
77           if (q && Len(q)) {
78             String *vb = Swig_scopename_last(value);
79             Clear(value);
80             Printf(value, "%s::%s", SwigType_namestr(q), vb);
81             Delete(q);
82           }
83         }
84       }
85       if (value && SwigType_istemplate(value)) {
86         String *nv = SwigType_namestr(value);
87         Setattr(p, "value", nv);
88       }
89       p = nextSibling(p);
90     }
91   }
92
93   void normalize_later(ParmList *p) {
94     while (p) {
95       SwigType *ty = Getattr(p, "type");
96       Append(normalize, ty);
97       p = nextSibling(p);
98     }
99   }
100
101   /* Walk through entries in normalize list and patch them up */
102   void normalize_list() {
103     Hash *currentsym = Swig_symbol_current();
104
105     normal_node *nn = patch_list;
106     normal_node *np;
107     while (nn) {
108       Swig_symbol_setscope(nn->symtab);
109       SwigType_set_scope(nn->typescope);
110       Iterator t;
111       for (t = First(nn->normallist); t.item; t = Next(t)) {
112         normalize_type(t.item);
113       }
114       Delete(nn->normallist);
115       np = nn->next;
116       delete(nn);
117       nn = np;
118     }
119     Swig_symbol_setscope(currentsym);
120   }
121
122   /* generate C++ inheritance type-relationships */
123   void cplus_inherit_types_impl(Node *first, Node *cls, String *clsname, const char *bases, const char *baselist, int ispublic, String *cast = 0) {
124
125     if (first == cls)
126       return;                   /* The Marcelo check */
127     if (!cls)
128       cls = first;
129     List *alist = 0;
130     List *ilist = Getattr(cls, bases);
131     if (!ilist) {
132       List *nlist = Getattr(cls, baselist);
133       if (nlist) {
134         int len = Len(nlist);
135         int i;
136         for (i = 0; i < len; i++) {
137           Node *bcls = 0;
138           int clsforward = 0;
139           String *bname = Getitem(nlist, i);
140           String *sname = bname;
141           String *tname = 0;
142
143           /* Try to locate the base class.   We look in the symbol table and we chase 
144              typedef declarations to get to the base class if necessary */
145           Symtab *st = Getattr(cls, "sym:symtab");
146
147           if (SwigType_istemplate(bname)) {
148             tname = SwigType_typedef_resolve_all(bname);
149             sname = tname;
150           }
151           while (1) {
152             String *qsname = SwigType_typedef_qualified(sname);
153             bcls = Swig_symbol_clookup(qsname, st);
154             Delete(qsname);
155             if (bcls) {
156               if (Strcmp(nodeType(bcls), "class") != 0) {
157                 /* Not a class.   The symbol could be a typedef. */
158                 if (checkAttribute(bcls, "storage", "typedef")) {
159                   SwigType *decl = Getattr(bcls, "decl");
160                   if (!decl || !(Len(decl))) {
161                     sname = Getattr(bcls, "type");
162                     st = Getattr(bcls, "sym:symtab");
163                     if (SwigType_istemplate(sname)) {
164                       if (tname)
165                         Delete(tname);
166                       tname = SwigType_typedef_resolve_all(sname);
167                       sname = tname;
168                     }
169                     continue;
170                   }
171                 }
172                 if (Strcmp(nodeType(bcls), "classforward") != 0) {
173                   Swig_error(Getfile(cls), Getline(cls), "'%s' does not have a valid base class.\n", Getattr(cls, "name"));
174                   Swig_error(Getfile(bcls), Getline(bcls), "'%s' is not a valid base class.\n", SwigType_namestr(bname));
175                 } else {
176                   Swig_warning(WARN_TYPE_INCOMPLETE, Getfile(cls), Getline(cls), "Base class '%s' is incomplete.\n", SwigType_namestr(bname));
177                   Swig_warning(WARN_TYPE_INCOMPLETE, Getfile(bcls), Getline(bcls), "Only forward declaration '%s' was found.\n", SwigType_namestr(bname));
178                   clsforward = 1;
179                 }
180                 bcls = 0;
181               } else {
182                 if (Getattr(bcls, "typepass:visit")) {
183                   if (!ilist)
184                     ilist = alist = NewList();
185                   Append(ilist, bcls);
186                 } else {
187                   Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(cls), Getline(cls), "Base class '%s' undefined.\n", SwigType_namestr(bname));
188                   Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "'%s' must be defined before it is used as a base class.\n", SwigType_namestr(bname));
189                 }
190               }
191             }
192             break;
193           }
194
195           if (tname)
196             Delete(tname);
197           if (!bcls) {
198             if (!clsforward) {
199               if (ispublic && !Getmeta(bname, "already_warned")) {
200                 Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(cls), Getline(cls), "Nothing known about base class '%s'. Ignored.\n", SwigType_namestr(bname));
201                 if (Strchr(bname, '<')) {
202                   Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(cls), Getline(cls), "Maybe you forgot to instantiate '%s' using %%template.\n",
203                                SwigType_namestr(bname));
204                 }
205                 Setmeta(bname, "already_warned", "1");
206               }
207             }
208             SwigType_inherit(clsname, bname, cast, 0);
209           }
210         }
211       }
212       if (ilist) {
213         Setattr(cls, bases, ilist);
214       }
215     }
216     if (alist)
217       Delete(alist);
218
219     if (!ilist)
220       return;
221     int len = Len(ilist);
222     int i;
223     for (i = 0; i < len; i++) {
224       Node *n = Getitem(ilist, i);
225       String *bname = Getattr(n, "name");
226       Node *bclass = n;         /* Getattr(n,"class"); */
227       Hash *scopes = Getattr(bclass, "typescope");
228       SwigType_inherit(clsname, bname, cast, 0);
229       if (!importmode) {
230         String *btype = Copy(bname);
231         SwigType_add_pointer(btype);
232         SwigType_remember(btype);
233         Delete(btype);
234       }
235       if (scopes) {
236         SwigType_inherit_scope(scopes);
237       }
238       /* Set up inheritance in the symbol table */
239       Symtab *st = Getattr(cls, "symtab");
240       Symtab *bst = Getattr(bclass, "symtab");
241       if (st == bst) {
242         Swig_warning(WARN_PARSE_REC_INHERITANCE, Getfile(cls), Getline(cls), "Recursive scope inheritance of '%s'.\n", Getattr(cls, "name"));
243         continue;
244       }
245       Symtab *s = Swig_symbol_current();
246       Swig_symbol_setscope(st);
247       Swig_symbol_inherit(bst);
248       Swig_symbol_setscope(s);
249
250       /* Recursively hit base classes */
251       String *namestr = SwigType_namestr(Getattr(bclass, "name"));
252       String *newcast = NewStringf("(%s *)%s", namestr, cast);
253       Delete(namestr);
254       cplus_inherit_types_impl(first, bclass, clsname, bases, baselist, ispublic, newcast);
255       Delete(newcast);
256     }
257   }
258
259   void append_list(List *lb, List *la) {
260     if (la && lb) {
261       for (Iterator bi = First(la); bi.item; bi = Next(bi)) {
262         Append(lb, bi.item);
263       }
264     }
265   }
266
267   void cplus_inherit_types(Node *first, Node *cls, String *clsname, String *cast = 0) {
268     cplus_inherit_types_impl(first, cls, clsname, "bases", "baselist", 1, cast);
269     cplus_inherit_types_impl(first, cls, clsname, "protectedbases", "protectedbaselist", 0, cast);
270     cplus_inherit_types_impl(first, cls, clsname, "privatebases", "privatebaselist", 0, cast);
271
272     if (!cls)
273       cls = first;
274
275     List *allbases = NewList();
276     append_list(allbases, Getattr(cls, "bases"));
277     append_list(allbases, Getattr(cls, "protectedbases"));
278     append_list(allbases, Getattr(cls, "privatebases"));
279     if (Len(allbases)) {
280       Setattr(cls, "allbases", allbases);
281     }
282     Delete(allbases);
283   }
284
285   /* ------------------------------------------------------------
286    * top()
287    * ------------------------------------------------------------ */
288
289   virtual int top(Node *n) {
290     importmode = 0;
291     module = Getattr(n, "module");
292     inclass = 0;
293     normalize = 0;
294     nsname = 0;
295     classhash = Getattr(n, "classes");
296     emit_children(n);
297     normalize_list();
298     SwigType_set_scope(0);
299     return SWIG_OK;
300   }
301
302
303   /* ------------------------------------------------------------
304    * moduleDirective()
305    * ------------------------------------------------------------ */
306
307   virtual int moduleDirective(Node *n) {
308     if (!module) {
309       module = n;
310     }
311     return SWIG_OK;
312   }
313
314   /* ------------------------------------------------------------
315    * importDirective()
316    * ------------------------------------------------------------ */
317
318   virtual int importDirective(Node *n) {
319     String *oldmodule = module;
320     int oldimport = importmode;
321     importmode = 1;
322     module = 0;
323     emit_children(n);
324     importmode = oldimport;
325     module = oldmodule;
326     return SWIG_OK;
327   }
328
329   /* ------------------------------------------------------------
330    * includeDirective()
331    * externDirective()
332    * extendDirective()
333    * ------------------------------------------------------------ */
334
335   virtual int includeDirective(Node *n) {
336     return emit_children(n);
337   }
338   virtual int externDeclaration(Node *n) {
339     return emit_children(n);
340   }
341   virtual int extendDirective(Node *n) {
342     return emit_children(n);
343   }
344
345   /* ------------------------------------------------------------
346    * classDeclaration()
347    * ------------------------------------------------------------ */
348
349   virtual int classDeclaration(Node *n) {
350     String *name = Getattr(n, "name");
351     String *tdname = Getattr(n, "tdname");
352     String *unnamed = Getattr(n, "unnamed");
353     String *storage = Getattr(n, "storage");
354     String *kind = Getattr(n, "kind");
355     Node *oldinclass = inclass;
356     List *olist = normalize;
357     Symtab *symtab;
358     String *nname = 0;
359     String *fname = 0;
360     String *scopename = 0;
361
362     normalize = NewList();
363
364     if (name) {
365       if (SwigType_istemplate(name)) {
366         // We need to fully resolve the name to make templates work correctly */
367         Node *cn;
368         fname = SwigType_typedef_resolve_all(name);
369         if (Strcmp(fname, name) != 0 && (cn = Swig_symbol_clookup_local(fname, 0))) {
370           if ((n == cn)
371               || (Strcmp(nodeType(cn), "template") == 0)
372               || (Getattr(cn, "feature:onlychildren") != 0)
373               || (Getattr(n, "feature:onlychildren") != 0)) {
374             Swig_symbol_cadd(fname, n);
375             SwigType_typedef_class(fname);
376             scopename = Copy(fname);
377           } else {
378             Swig_warning(WARN_TYPE_REDEFINED, Getfile(n), Getline(n), "Template '%s' was already wrapped,\n", SwigType_namestr(name));
379             Swig_warning(WARN_TYPE_REDEFINED, Getfile(cn), Getline(cn), "previous wrap of '%s'.\n", SwigType_namestr(Getattr(cn, "name")));
380             scopename = 0;
381           }
382         } else {
383           Swig_symbol_cadd(fname, n);
384           SwigType_typedef_class(fname);
385           scopename = Copy(fname);
386         }
387       } else {
388         if ((CPlusPlus) || (unnamed)) {
389           SwigType_typedef_class(name);
390         } else {
391           SwigType_typedef_class(NewStringf("%s %s", kind, name));
392         }
393         scopename = Copy(name);
394       }
395     } else {
396       scopename = 0;
397     }
398
399     Setattr(n, "typepass:visit", "1");
400
401     /* Need to set up a typedef if unnamed */
402     if (unnamed && tdname && (Cmp(storage, "typedef") == 0)) {
403       SwigType_typedef(unnamed, tdname);
404     }
405
406     if (nsname) {
407       nname = NewStringf("%s::%s", nsname, name);
408       String *tdname = Getattr(n, "tdname");
409       if (tdname) {
410         tdname = NewStringf("%s::%s", nsname, tdname);
411         Setattr(n, "tdname", tdname);
412       }
413     }
414     SwigType_new_scope(scopename);
415     SwigType_attach_symtab(Getattr(n, "symtab"));
416
417     /* Inherit type definitions into the class */
418     if (name) {
419       cplus_inherit_types(n, 0, nname ? nname : (fname ? fname : name));
420     }
421
422     inclass = n;
423     symtab = Swig_symbol_setscope(Getattr(n, "symtab"));
424     emit_children(n);
425     Swig_symbol_setscope(symtab);
426
427     Hash *ts = SwigType_pop_scope();
428     Setattr(n, "typescope", ts);
429     Delete(ts);
430     Setattr(n, "module", module);
431
432     /* Normalize deferred types */
433     {
434       normal_node *nn = new normal_node();
435       nn->normallist = normalize;
436       nn->symtab = Getattr(n, "symtab");
437       nn->next = patch_list;
438       nn->typescope = Getattr(n, "typescope");
439       patch_list = nn;
440     }
441
442     normalize = olist;
443
444     inclass = oldinclass;
445
446     /* If in a namespace, patch the class name */
447     if (nname) {
448       Setattr(n, "name", nname);
449       Delete(nname);
450     }
451     return SWIG_OK;
452   }
453
454   /* ------------------------------------------------------------
455    * namespaceDeclaration()
456    * ------------------------------------------------------------ */
457
458   virtual int templateDeclaration(Node *n) {
459     String *name = Getattr(n, "name");
460     String *ttype = Getattr(n, "templatetype");
461     if (Strcmp(ttype, "class") == 0) {
462       String *rname = SwigType_typedef_resolve_all(name);
463       SwigType_typedef_class(rname);
464       Delete(rname);
465     } else if (Strcmp(ttype, "classforward") == 0) {
466       String *rname = SwigType_typedef_resolve_all(name);
467       SwigType_typedef_class(rname);
468       Delete(rname);
469       /*      SwigType_typedef_class(name); */
470     }
471     return SWIG_OK;
472   }
473
474   /* ------------------------------------------------------------
475    * classforwardDeclaration()
476    * ------------------------------------------------------------ */
477
478   virtual int classforwardDeclaration(Node *n) {
479
480     /* Temporary hack. Can't do inside a class because it breaks
481        C nested structure wrapping */
482
483     if ((!inclass) || (CPlusPlus)) {
484       String *name = Getattr(n, "name");
485       String *nname;
486       SwigType_typedef_class(name);
487       if (nsname) {
488         nname = NewStringf("%s::%s", nsname, name);
489         Setattr(n, "name", nname);
490       }
491
492     }
493     return SWIG_OK;
494   }
495
496   /* ------------------------------------------------------------
497    * namespaceDeclaration()
498    * ------------------------------------------------------------ */
499
500   virtual int namespaceDeclaration(Node *n) {
501     Symtab *symtab;
502     String *name = Getattr(n, "name");
503     String *alias = Getattr(n, "alias");
504     List *olist = normalize;
505     normalize = NewList();
506     if (alias) {
507       Typetab *ts = Getattr(n, "typescope");
508       if (!ts) {
509         Node *ns;
510         /* Create a empty scope for the alias */
511         ns = Getattr(n, "namespace");
512         if (ns) {
513           SwigType_scope_alias(name, Getattr(ns, "typescope"));
514         }
515         ts = Getattr(ns, "typescope");
516         Setattr(n, "typescope", ts);
517       }
518       /* Namespace alias */
519       return SWIG_OK;
520     } else {
521       if (name) {
522         Node *nn = Swig_symbol_clookup(name, n);
523         Hash *ts = 0;
524         if (nn)
525           ts = Getattr(nn, "typescope");
526         if (!ts) {
527           SwigType_new_scope(name);
528           SwigType_attach_symtab(Getattr(n, "symtab"));
529         } else {
530           SwigType_set_scope(ts);
531         }
532       }
533       String *oldnsname = nsname;
534       nsname = Swig_symbol_qualified(Getattr(n, "symtab"));
535       symtab = Swig_symbol_setscope(Getattr(n, "symtab"));
536       emit_children(n);
537       Swig_symbol_setscope(symtab);
538
539       if (name) {
540         Hash *ts = SwigType_pop_scope();
541         Setattr(n, "typescope", ts);
542         Delete(ts);
543       }
544
545       /* Normalize deferred types */
546       {
547         normal_node *nn = new normal_node();
548         nn->normallist = normalize;
549         nn->symtab = Getattr(n, "symtab");
550         nn->next = patch_list;
551         nn->typescope = Getattr(n, "typescope");
552         patch_list = nn;
553       }
554       normalize = olist;
555
556       Delete(nsname);
557       nsname = oldnsname;
558       return SWIG_OK;
559     }
560   }
561
562   /* ------------------------------------------------------------
563    * cDeclaration()
564    * ------------------------------------------------------------ */
565
566   virtual int cDeclaration(Node *n) {
567     if (NoExcept) {
568       Delattr(n, "throws");
569     }
570
571     /* Normalize types. */
572     SwigType *ty = Getattr(n, "type");
573     normalize_type(ty);
574     SwigType *decl = Getattr(n, "decl");
575     if (decl) {
576       normalize_type(decl);
577     }
578     normalize_parms(Getattr(n, "parms"));
579     normalize_parms(Getattr(n, "throws"));
580     if (GetFlag(n, "conversion_operator")) {
581       /* The call to the operator in the generated wrapper must be fully qualified in order to compile */
582       SwigType *name = Getattr(n, "name");
583       SwigType *qualifiedname = Swig_symbol_string_qualify(name,0);
584       Clear(name);
585       Append(name, qualifiedname);
586       Delete(qualifiedname);
587     }
588
589     if (checkAttribute(n, "storage", "typedef")) {
590       String *name = Getattr(n, "name");
591       ty = Getattr(n, "type");
592       decl = Getattr(n, "decl");
593       SwigType *t = Copy(ty);
594       {
595         /* If the typename is qualified, make sure the scopename is fully qualified when making a typedef */
596         if (Swig_scopename_check(t) && strncmp(Char(t), "::", 2)) {
597           String *base, *prefix, *qprefix;
598           base = Swig_scopename_last(t);
599           prefix = Swig_scopename_prefix(t);
600           qprefix = SwigType_typedef_qualified(prefix);
601           Delete(t);
602           t = NewStringf("%s::%s", qprefix, base);
603           Delete(base);
604           Delete(prefix);
605           Delete(qprefix);
606         }
607       }
608       SwigType_push(t, decl);
609       if (CPlusPlus) {
610         Replaceall(t, "struct ", "");
611         Replaceall(t, "union ", "");
612         Replaceall(t, "class ", "");
613       }
614       SwigType_typedef(t, name);
615     }
616     /* If namespaces are active.  We need to patch the name with a namespace prefix */
617     if (nsname && !inclass) {
618       String *name = Getattr(n, "name");
619       if (name) {
620         String *nname = NewStringf("%s::%s", nsname, name);
621         Setattr(n, "name", nname);
622         Delete(nname);
623       }
624     }
625     clean_overloaded(n);
626     return SWIG_OK;
627   }
628
629
630   /* ------------------------------------------------------------
631    * constructorDeclaration()
632    * ------------------------------------------------------------ */
633
634   virtual int constructorDeclaration(Node *n) {
635     if (NoExcept) {
636       Delattr(n, "throws");
637     }
638
639     normalize_parms(Getattr(n, "parms"));
640     normalize_parms(Getattr(n, "throws"));
641
642     /* If in a namespace, patch the class name */
643     if (nsname) {
644       String *nname = NewStringf("%s::%s", nsname, Getattr(n, "name"));
645       Setattr(n, "name", nname);
646     }
647     clean_overloaded(n);
648     return SWIG_OK;
649   }
650
651   /* ------------------------------------------------------------
652    * destructorDeclaration()
653    * ------------------------------------------------------------ */
654
655   virtual int destructorDeclaration(Node *n) {
656     /* If in a namespace, patch the class name */
657     if (nsname) {
658       String *nname = NewStringf("%s::%s", nsname, Getattr(n, "name"));
659       Setattr(n, "name", nname);
660     }
661     return SWIG_OK;
662   }
663
664   /* ------------------------------------------------------------
665    * constantDirective()
666    * ------------------------------------------------------------ */
667
668   virtual int constantDirective(Node *n) {
669     SwigType *ty = Getattr(n, "type");
670     if (ty) {
671       Setattr(n, "type", SwigType_typedef_qualified(ty));
672     }
673     return SWIG_OK;
674   }
675
676
677   /* ------------------------------------------------------------
678    * enumDeclaration()
679    * ------------------------------------------------------------ */
680
681   virtual int enumDeclaration(Node *n) {
682     String *name = Getattr(n, "name");
683
684     if (name) {
685       String *scope = 0;
686
687       // Add a typedef to the type table so that we can use 'enum Name' as well as just 'Name'
688       if (nsname || inclass) {
689
690         // But first correct the name and tdname to contain the fully qualified scopename
691         if (nsname && inclass) {
692           scope = NewStringf("%s::%s", nsname, Getattr(inclass, "name"));
693         } else if (nsname) {
694           scope = NewStringf("%s", nsname);
695         } else if (inclass) {
696           scope = NewStringf("%s", Getattr(inclass, "name"));
697         }
698
699         String *nname = NewStringf("%s::%s", scope, name);
700         Setattr(n, "name", nname);
701
702         String *tdname = Getattr(n, "tdname");
703         if (tdname) {
704           tdname = NewStringf("%s::%s", scope, tdname);
705           Setattr(n, "tdname", tdname);
706         }
707
708         SwigType *t = NewStringf("enum %s", nname);
709         SwigType_typedef(t, name);
710       } else {
711         SwigType *t = NewStringf("enum %s", name);
712         SwigType_typedef(t, name);
713       }
714       Delete(scope);
715     }
716
717     String *tdname = Getattr(n, "tdname");
718     String *unnamed = Getattr(n, "unnamed");
719     String *storage = Getattr(n, "storage");
720
721     // Construct enumtype - for declaring an enum of this type with SwigType_ltype() etc
722     String *enumtype = 0;
723     if (unnamed && tdname && (Cmp(storage, "typedef") == 0)) {
724       enumtype = Copy(Getattr(n, "tdname"));
725     } else if (name) {
726       enumtype = NewStringf("%s%s", CPlusPlus ? "" : "enum ", Getattr(n, "name"));
727     } else {
728       // anonymous enums
729       enumtype = Copy(Getattr(n, "type"));
730     }
731     Setattr(n, "enumtype", enumtype);
732
733     // This block of code is for dealing with %ignore on an enum item where the target language
734     // attempts to use the C enum value in the target language itself and expects the previous enum value
735     // to be one more than the previous value... the previous enum item might not exist if it is ignored!
736     // - It sets the first non-ignored enum item with the "firstenumitem" attribute.
737     // - It adds an enumvalue attribute if the previous enum item is ignored
738     {
739       Node *c;
740       int count = 0;
741       String *previous = 0;
742       bool previous_ignored = false;
743       bool firstenumitem = false;
744       for (c = firstChild(n); c; c = nextSibling(c)) {
745         assert(strcmp(Char(nodeType(c)), "enumitem") == 0);
746
747         bool reset;
748         String *enumvalue = Getattr(c, "enumvalue");
749         if (GetFlag(c, "feature:ignore")) {
750           reset = enumvalue ? true : false;
751           previous_ignored = true;
752         } else {
753           if (!enumvalue && previous_ignored) {
754             if (previous)
755               Setattr(c, "enumvalue", NewStringf("(%s) + %d", previous, count+1));
756             else
757               Setattr(c, "enumvalue", NewStringf("%d", count));
758             SetFlag(c, "virtenumvalue"); // identify enumvalue as virtual, ie not from the parsed source
759           }
760           if (!firstenumitem) {
761             SetFlag(c, "firstenumitem");
762             firstenumitem = true;
763           }
764           reset = true;
765           previous_ignored = false;
766         }
767         if (reset) {
768           previous = enumvalue ? enumvalue : Getattr(c, "name");
769           count = 0;
770         } else {
771           count++;
772         }
773       }
774     }
775
776     emit_children(n);
777     return SWIG_OK;
778   }
779
780   /* ------------------------------------------------------------
781    * enumvalueDeclaration()
782    * ------------------------------------------------------------ */
783
784   virtual int enumvalueDeclaration(Node *n) {
785     String *name = Getattr(n, "name");
786     String *value = Getattr(n, "value");
787     if (!value)
788       value = name;
789     if (Strcmp(value, name) == 0) {
790       String *new_value;
791       if (((nsname) || (inclass)) && cparse_cplusplus) {
792         new_value = NewStringf("%s::%s", SwigType_namestr(Swig_symbol_qualified(n)), value);
793       } else {
794         new_value = NewString(value);
795       }
796       Setattr(n, "value", new_value);
797       Delete(new_value);
798     }
799     Node *next = nextSibling(n);
800
801     // Make up an enumvalue if one was not specified in the parsed code (not designed to be used on enum items and %ignore - enumvalue will be set instead)
802     if (!GetFlag(n, "feature:ignore")) {
803       if (Getattr(n, "_last") && !Getattr(n, "enumvalue")) {    // Only the first enum item has _last set (Note: first non-ignored enum item has firstenumitem set)
804         Setattr(n, "enumvalueex", "0");
805       }
806       if (next && !Getattr(next, "enumvalue")) {
807         Setattr(next, "enumvalueex", NewStringf("%s + 1", Getattr(n, "sym:name")));
808       }
809     }
810
811     return SWIG_OK;
812   }
813
814   /* ------------------------------------------------------------
815    * enumforwardDeclaration()
816    * ------------------------------------------------------------ */
817
818   virtual int enumforwardDeclaration(Node *n) {
819
820     // Use enumDeclaration() to do all the hard work.
821     // Note that no children can be emitted in a forward declaration as there aren't any.
822     return enumDeclaration(n);
823   }
824
825 #ifdef DEBUG_OVERLOADED
826   static void show_overloaded(Node *n) {
827     Node *c = Getattr(n, "sym:overloaded");
828     Node *checkoverloaded = c;
829     Printf(stdout, "-------------------- overloaded start %s sym:overloaded():%p -------------------------------\n", Getattr(n, "name"), c);
830     while (c) {
831       if (Getattr(c, "error")) {
832         c = Getattr(c, "sym:nextSibling");
833         continue;
834       }
835       if (Getattr(c, "sym:overloaded") != checkoverloaded) {
836         Printf(stdout, "sym:overloaded error c:%p checkoverloaded:%p\n", c, checkoverloaded);
837         Swig_print_node(c);
838         exit (1);
839       }
840
841       String *decl = Strcmp(nodeType(c), "using") == 0 ? NewString("------") : Getattr(c, "decl");
842       Printf(stdout, "  show_overloaded %s::%s(%s)          [%s] nodeType:%s\n", parentNode(c) ? Getattr(parentNode(c), "name") : "NOPARENT", Getattr(c, "name"), decl, Getattr(c, "sym:overname"), nodeType(c));
843       if (!Getattr(c, "sym:overloaded")) {
844         Printf(stdout, "sym:overloaded error.....%p\n", c);
845         Swig_print_node(c);
846         exit (1);
847       }
848       c = Getattr(c, "sym:nextSibling");
849     }
850     Printf(stdout, "-------------------- overloaded end   %s -------------------------------\n", Getattr(n, "name"));
851   }
852 #endif
853
854   /* ------------------------------------------------------------
855    * usingDeclaration()
856    * ------------------------------------------------------------ */
857
858   virtual int usingDeclaration(Node *n) {
859     if (Getattr(n, "namespace")) {
860       /* using namespace id */
861
862       /* For a namespace import.   We set up inheritance in the type system */
863       Node *ns = Getattr(n, "node");
864       if (ns) {
865         Typetab *ts = Getattr(ns, "typescope");
866         if (ts) {
867           SwigType_using_scope(ts);
868         }
869       }
870       return SWIG_OK;
871     } else {
872       Node *ns;
873       /* using id */
874       Symtab *stab = Getattr(n, "sym:symtab");
875       if (stab) {
876         String *uname = Getattr(n, "uname");
877         ns = Swig_symbol_clookup(uname, stab);
878         if (!ns && SwigType_istemplate(uname)) {
879           String *tmp = Swig_symbol_template_deftype(uname, 0);
880           if (!Equal(tmp, uname)) {
881             ns = Swig_symbol_clookup(tmp, stab);
882           }
883           Delete(tmp);
884         }
885       } else {
886         ns = 0;
887       }
888       if (!ns) {
889         if (is_public(n)) {
890           Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(n), Getline(n), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(n, "uname")));
891         }
892       } else {
893         /* Only a single symbol is being used.  There are only a few symbols that
894            we actually care about.  These are typedef, class declarations, and enum */
895         String *ntype = nodeType(ns);
896         if (Strcmp(ntype, "cdecl") == 0) {
897           if (checkAttribute(ns, "storage", "typedef")) {
898             /* A typedef declaration */
899             String *uname = Getattr(n, "uname");
900             SwigType_typedef_using(uname);
901           } else {
902             /* A normal C declaration. */
903             if ((inclass) && (!GetFlag(n, "feature:ignore")) && (Getattr(n, "sym:name"))) {
904               Node *c = ns;
905               Node *unodes = 0, *last_unodes = 0;
906               int ccount = 0;
907               String *symname = Getattr(n, "sym:name");
908               while (c) {
909                 if (Strcmp(nodeType(c), "cdecl") == 0) {
910                   if (!(checkAttribute(c, "storage", "static")
911                         || checkAttribute(c, "storage", "typedef")
912                         || checkAttribute(c, "storage", "friend")
913                         || (Getattr(c, "feature:extend") && !Getattr(c, "code"))
914                         || GetFlag(c, "feature:ignore"))) {
915
916                     /* Don't generate a method if the method is overridden in this class, 
917                      * for example don't generate another m(bool) should there be a Base::m(bool) :
918                      * struct Derived : Base { 
919                      *   void m(bool);
920                      *   using Base::m;
921                      * };
922                      */
923                     String *csymname = Getattr(c, "sym:name");
924                     if (!csymname || (Strcmp(csymname, symname) == 0)) {
925                       {
926                         String *decl = Getattr(c, "decl");
927                         Node *over = Getattr(n, "sym:overloaded");
928                         int match = 0;
929                         while (over) {
930                           String *odecl = Getattr(over, "decl");
931                           if (Cmp(decl, odecl) == 0) {
932                             match = 1;
933                             break;
934                           }
935                           over = Getattr(over, "sym:nextSibling");
936                         }
937                         if (match) {
938                           c = Getattr(c, "csym:nextSibling");
939                           continue;
940                         }
941                       }
942                       Node *nn = copyNode(c);
943                       Delattr(nn, "access");    // access might be different from the method in the base class
944                       if (!Getattr(nn, "sym:name"))
945                         Setattr(nn, "sym:name", symname);
946
947                       if (!GetFlag(nn, "feature:ignore")) {
948                         ParmList *parms = CopyParmList(Getattr(c, "parms"));
949                         int is_pointer = SwigType_ispointer_return(Getattr(nn, "decl"));
950                         int is_void = checkAttribute(nn, "type", "void") && !is_pointer;
951                         Setattr(nn, "parms", parms);
952                         Delete(parms);
953                         if (Getattr(n, "feature:extend")) {
954                           String *ucode = is_void ? NewStringf("{ self->%s(", Getattr(n, "uname")) : NewStringf("{ return self->%s(", Getattr(n, "uname"));
955
956                           for (ParmList *p = parms; p;) {
957                             Append(ucode, Getattr(p, "name"));
958                             p = nextSibling(p);
959                             if (p)
960                               Append(ucode, ",");
961                           }
962                           Append(ucode, "); }");
963                           Setattr(nn, "code", ucode);
964                           Delete(ucode);
965                         }
966                         ParmList *throw_parm_list = Getattr(c, "throws");
967                         if (throw_parm_list)
968                           Setattr(nn, "throws", CopyParmList(throw_parm_list));
969                         ccount++;
970                         if (!last_unodes) {
971                           last_unodes = nn;
972                           unodes = nn;
973                         } else {
974                           Setattr(nn, "previousSibling", last_unodes);
975                           Setattr(last_unodes, "nextSibling", nn);
976                           Setattr(nn, "sym:previousSibling", last_unodes);
977                           Setattr(last_unodes, "sym:nextSibling", nn);
978                           Setattr(nn, "sym:overloaded", unodes);
979                           Setattr(unodes, "sym:overloaded", unodes);
980                           last_unodes = nn;
981                         }
982                       } else {
983                         Delete(nn);
984                       }
985                     }
986                   }
987                 }
988                 c = Getattr(c, "csym:nextSibling");
989               }
990               if (unodes) {
991                 set_firstChild(n, unodes);
992                 if (ccount > 1) {
993                   if (!Getattr(n, "sym:overloaded")) {
994                     Setattr(n, "sym:overloaded", n);
995                     Setattr(n, "sym:overname", "_SWIG_0");
996                   }
997                 }
998               }
999
1000               /* Hack the parse tree symbol table for overloaded methods. Replace the "using" node with the
1001                * list of overloaded methods we have just added in as child nodes to the "using" node.
1002                * The node will still exist, it is just the symbol table linked list of overloaded methods
1003                * which is hacked. */
1004               if (Getattr(n, "sym:overloaded"))
1005               {
1006 #ifdef DEBUG_OVERLOADED
1007 show_overloaded(n);
1008 #endif
1009                 int cnt = 0;
1010                 Node *debugnode = n;
1011                 if (!firstChild(n)) {
1012                   // Remove from overloaded list ('using' node does not actually end up adding in any methods)
1013                   Node *ps = Getattr(n, "sym:previousSibling");
1014                   Node *ns = Getattr(n, "sym:nextSibling");
1015                   if (ps) {
1016                     Setattr(ps, "sym:nextSibling", ns);
1017                   }
1018                   if (ns) {
1019                     Setattr(ns, "sym:previousSibling", ps);
1020                   }
1021                 } else {
1022                   // The 'using' node results in methods being added in - slot in the these methods here 
1023                   Node *ps = Getattr(n, "sym:previousSibling");
1024                   Node *ns = Getattr(n, "sym:nextSibling");
1025                   Node *fc = firstChild(n);
1026                   Node *pp = fc;
1027
1028                   Node *firstoverloaded = Getattr(n, "sym:overloaded");
1029                   if (firstoverloaded == n) {
1030                     // This 'using' node we are cutting out was the first node in the overloaded list. 
1031                     // Change the first node in the list to its first sibling
1032                     Delattr(firstoverloaded, "sym:overloaded");
1033                     Node *nnn = Getattr(firstoverloaded, "sym:nextSibling");
1034                     firstoverloaded = fc;
1035                     while (nnn) {
1036                       Setattr(nnn, "sym:overloaded", firstoverloaded);
1037                       nnn = Getattr(nnn, "sym:nextSibling");
1038                     }
1039                   }
1040                   while (pp) {
1041                     Node *ppn = Getattr(pp, "sym:nextSibling");
1042                     Setattr(pp, "sym:overloaded", firstoverloaded);
1043                     Setattr(pp, "sym:overname", NewStringf("%s_%d", Getattr(n, "sym:overname"), cnt++));
1044                     if (ppn)
1045                       pp = ppn;
1046                     else
1047                       break;
1048                   }
1049                   if (ps) {
1050                     Setattr(ps, "sym:nextSibling", fc);
1051                     Setattr(fc, "sym:previousSibling", ps);
1052                   }
1053                   if (ns) {
1054                     Setattr(ns, "sym:previousSibling", pp);
1055                     Setattr(pp, "sym:nextSibling", ns);
1056                   }
1057                   debugnode = firstoverloaded;
1058                 }
1059                 Delattr(n, "sym:previousSibling");
1060                 Delattr(n, "sym:nextSibling");
1061                 Delattr(n, "sym:overloaded");
1062                 Delattr(n, "sym:overname");
1063 #ifdef DEBUG_OVERLOADED
1064 show_overloaded(debugnode);
1065 #endif
1066                 clean_overloaded(n); // Needed?
1067               }
1068             }
1069           }
1070         } else if ((Strcmp(ntype, "class") == 0) || ((Strcmp(ntype, "classforward") == 0))) {
1071           /* We install the using class name as kind of a typedef back to the original class */
1072           String *uname = Getattr(n, "uname");
1073           /* Import into current type scope */
1074           SwigType_typedef_using(uname);
1075         } else if (Strcmp(ntype, "enum") == 0) {
1076           SwigType_typedef_using(Getattr(n, "uname"));
1077         }
1078       }
1079     }
1080     return SWIG_OK;
1081   }
1082
1083   /* ------------------------------------------------------------
1084    * typemapDirective()
1085    * ------------------------------------------------------------ */
1086
1087   virtual int typemapDirective(Node *n) {
1088     if (inclass || nsname) {
1089       Node *items = firstChild(n);
1090       while (items) {
1091         Parm *pattern = Getattr(items, "pattern");
1092         Parm *parms = Getattr(items, "parms");
1093         normalize_later(pattern);
1094         normalize_later(parms);
1095         items = nextSibling(items);
1096       }
1097     }
1098     return SWIG_OK;
1099   }
1100
1101
1102   /* ------------------------------------------------------------
1103    * typemapcopyDirective()
1104    * ------------------------------------------------------------ */
1105
1106   virtual int typemapcopyDirective(Node *n) {
1107     if (inclass || nsname) {
1108       Node *items = firstChild(n);
1109       ParmList *pattern = Getattr(n, "pattern");
1110       normalize_later(pattern);
1111       while (items) {
1112         ParmList *npattern = Getattr(items, "pattern");
1113         normalize_later(npattern);
1114         items = nextSibling(items);
1115       }
1116     }
1117     return SWIG_OK;
1118   }
1119
1120   /* ------------------------------------------------------------
1121    * applyDirective()
1122    * ------------------------------------------------------------ */
1123
1124   virtual int applyDirective(Node *n) {
1125     if (inclass || nsname) {
1126       ParmList *pattern = Getattr(n, "pattern");
1127       normalize_later(pattern);
1128       Node *items = firstChild(n);
1129       while (items) {
1130         Parm *apattern = Getattr(items, "pattern");
1131         normalize_later(apattern);
1132         items = nextSibling(items);
1133       }
1134     }
1135     return SWIG_OK;
1136   }
1137
1138   /* ------------------------------------------------------------
1139    * clearDirective()
1140    * ------------------------------------------------------------ */
1141
1142   virtual int clearDirective(Node *n) {
1143     if (inclass || nsname) {
1144       Node *p;
1145       for (p = firstChild(n); p; p = nextSibling(p)) {
1146         ParmList *pattern = Getattr(p, "pattern");
1147         normalize_later(pattern);
1148       }
1149     }
1150     return SWIG_OK;
1151   }
1152
1153 public:
1154   static void pass(Node *n) {
1155     TypePass t;
1156     t.top(n);
1157   }
1158 };
1159
1160 void Swig_process_types(Node *n) {
1161   if (!n)
1162     return;
1163   TypePass::pass(n);
1164 }