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
15char cvsroot_typepass_cxx[] = "$Id: typepass.cxx 11279 2009-06-16 19:29:08Z wsfulton $";
16
17#include "swigmod.h"
18#include "cparse.h"
19
20struct normal_node {
21  Symtab *symtab;
22  Hash *typescope;
23  List *normallist;
24  normal_node *next;
25};
26
27static normal_node *patch_list = 0;
28
29/* Singleton class - all non-static methods in this class are private */
30class 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
1007show_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
1064show_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
1153public:
1154  static void pass(Node *n) {
1155    TypePass t;
1156    t.top(n);
1157  }
1158};
1159
1160void Swig_process_types(Node *n) {
1161  if (!n)
1162    return;
1163  TypePass::pass(n);
1164}
1165