import source from 1.3.40
[external/swig.git] / Source / CParse / parser.y
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  * parser.y
6  *
7  * YACC parser for SWIG.   The grammar is a somewhat broken subset of C/C++.
8  * This file is a bit of a mess and probably needs to be rewritten at
9  * some point.  Beware.
10  * ----------------------------------------------------------------------------- */
11
12 %{
13
14 #define yylex yylex
15
16 char cvsroot_parser_y[] = "$Id: parser.y 11582 2009-08-15 10:40:19Z wsfulton $";
17
18 #include "swig.h"
19 #include "cparse.h"
20 #include "preprocessor.h"
21 #include <ctype.h>
22
23 /* We do this for portability */
24 #undef alloca
25 #define alloca malloc
26
27 /* -----------------------------------------------------------------------------
28  *                               Externals
29  * ----------------------------------------------------------------------------- */
30
31 int  yyparse();
32
33 /* NEW Variables */
34
35 static Node    *top = 0;      /* Top of the generated parse tree */
36 static int      unnamed = 0;  /* Unnamed datatype counter */
37 static Hash    *extendhash = 0;     /* Hash table of added methods */
38 static Hash    *classes = 0;        /* Hash table of classes */
39 static Symtab  *prev_symtab = 0;
40 static Node    *current_class = 0;
41 String  *ModuleName = 0;
42 static Node    *module_node = 0;
43 static String  *Classprefix = 0;  
44 static String  *Namespaceprefix = 0;
45 static int      inclass = 0;
46 static char    *last_cpptype = 0;
47 static int      inherit_list = 0;
48 static Parm    *template_parameters = 0;
49 static int      extendmode   = 0;
50 static int      compact_default_args = 0;
51 static int      template_reduce = 0;
52 static int      cparse_externc = 0;
53
54 static int      max_class_levels = 0;
55 static int      class_level = 0;
56 static Node   **class_decl = NULL;
57
58 /* -----------------------------------------------------------------------------
59  *                            Assist Functions
60  * ----------------------------------------------------------------------------- */
61
62
63  
64 /* Called by the parser (yyparse) when an error is found.*/
65 static void yyerror (const char *e) {
66   (void)e;
67 }
68
69 static Node *new_node(const_String_or_char_ptr tag) {
70   Node *n = NewHash();
71   set_nodeType(n,tag);
72   Setfile(n,cparse_file);
73   Setline(n,cparse_line);
74   return n;
75 }
76
77 /* Copies a node.  Does not copy tree links or symbol table data (except for
78    sym:name) */
79
80 static Node *copy_node(Node *n) {
81   Node *nn;
82   Iterator k;
83   nn = NewHash();
84   Setfile(nn,Getfile(n));
85   Setline(nn,Getline(n));
86   for (k = First(n); k.key; k = Next(k)) {
87     String *ci;
88     String *key = k.key;
89     char *ckey = Char(key);
90     if ((strcmp(ckey,"nextSibling") == 0) ||
91         (strcmp(ckey,"previousSibling") == 0) ||
92         (strcmp(ckey,"parentNode") == 0) ||
93         (strcmp(ckey,"lastChild") == 0)) {
94       continue;
95     }
96     if (Strncmp(key,"csym:",5) == 0) continue;
97     /* We do copy sym:name.  For templates */
98     if ((strcmp(ckey,"sym:name") == 0) || 
99         (strcmp(ckey,"sym:weak") == 0) ||
100         (strcmp(ckey,"sym:typename") == 0)) {
101       String *ci = Copy(k.item);
102       Setattr(nn,key, ci);
103       Delete(ci);
104       continue;
105     }
106     if (strcmp(ckey,"sym:symtab") == 0) {
107       Setattr(nn,"sym:needs_symtab", "1");
108     }
109     /* We don't copy any other symbol table attributes */
110     if (strncmp(ckey,"sym:",4) == 0) {
111       continue;
112     }
113     /* If children.  We copy them recursively using this function */
114     if (strcmp(ckey,"firstChild") == 0) {
115       /* Copy children */
116       Node *cn = k.item;
117       while (cn) {
118         Node *copy = copy_node(cn);
119         appendChild(nn,copy);
120         Delete(copy);
121         cn = nextSibling(cn);
122       }
123       continue;
124     }
125     /* We don't copy the symbol table.  But we drop an attribute 
126        requires_symtab so that functions know it needs to be built */
127
128     if (strcmp(ckey,"symtab") == 0) {
129       /* Node defined a symbol table. */
130       Setattr(nn,"requires_symtab","1");
131       continue;
132     }
133     /* Can't copy nodes */
134     if (strcmp(ckey,"node") == 0) {
135       continue;
136     }
137     if ((strcmp(ckey,"parms") == 0) || (strcmp(ckey,"pattern") == 0) || (strcmp(ckey,"throws") == 0)
138         || (strcmp(ckey,"kwargs") == 0)) {
139       ParmList *pl = CopyParmList(k.item);
140       Setattr(nn,key,pl);
141       Delete(pl);
142       continue;
143     }
144     /* Looks okay.  Just copy the data using Copy */
145     ci = Copy(k.item);
146     Setattr(nn, key, ci);
147     Delete(ci);
148   }
149   return nn;
150 }
151
152 /* -----------------------------------------------------------------------------
153  *                              Variables
154  * ----------------------------------------------------------------------------- */
155
156 static char  *typemap_lang = 0;    /* Current language setting */
157
158 static int cplus_mode  = 0;
159 static String  *class_rename = 0;
160
161 /* C++ modes */
162
163 #define  CPLUS_PUBLIC    1
164 #define  CPLUS_PRIVATE   2
165 #define  CPLUS_PROTECTED 3
166
167 /* include types */
168 static int   import_mode = 0;
169
170 void SWIG_typemap_lang(const char *tm_lang) {
171   typemap_lang = Swig_copy_string(tm_lang);
172 }
173
174 void SWIG_cparse_set_compact_default_args(int defargs) {
175   compact_default_args = defargs;
176 }
177
178 int SWIG_cparse_template_reduce(int treduce) {
179   template_reduce = treduce;
180   return treduce;  
181 }
182
183 /* -----------------------------------------------------------------------------
184  *                           Assist functions
185  * ----------------------------------------------------------------------------- */
186
187 static int promote_type(int t) {
188   if (t <= T_UCHAR || t == T_CHAR) return T_INT;
189   return t;
190 }
191
192 /* Perform type-promotion for binary operators */
193 static int promote(int t1, int t2) {
194   t1 = promote_type(t1);
195   t2 = promote_type(t2);
196   return t1 > t2 ? t1 : t2;
197 }
198
199 static String *yyrename = 0;
200
201 /* Forward renaming operator */
202
203 static String *resolve_node_scope(String *cname);
204
205
206 Hash *Swig_cparse_features(void) {
207   static Hash   *features_hash = 0;
208   if (!features_hash) features_hash = NewHash();
209   return features_hash;
210 }
211
212 static String *feature_identifier_fix(String *s) {
213   if (SwigType_istemplate(s)) {
214     String *tp, *ts, *ta, *tq;
215     tp = SwigType_templateprefix(s);
216     ts = SwigType_templatesuffix(s);
217     ta = SwigType_templateargs(s);
218     tq = Swig_symbol_type_qualify(ta,0);
219     Append(tp,tq);
220     Append(tp,ts);
221     Delete(ts);
222     Delete(ta);
223     Delete(tq);
224     return tp;
225   } else {
226     return NewString(s);
227   }
228 }
229
230 /* Generate the symbol table name for an object */
231 /* This is a bit of a mess. Need to clean up */
232 static String *add_oldname = 0;
233
234
235
236 static String *make_name(Node *n, String *name,SwigType *decl) {
237   int destructor = name && (*(Char(name)) == '~');
238
239   if (yyrename) {
240     String *s = NewString(yyrename);
241     Delete(yyrename);
242     yyrename = 0;
243     if (destructor  && (*(Char(s)) != '~')) {
244       Insert(s,0,"~");
245     }
246     return s;
247   }
248
249   if (!name) return 0;
250   return Swig_name_make(n,Namespaceprefix,name,decl,add_oldname);
251 }
252
253 /* Generate an unnamed identifier */
254 static String *make_unnamed() {
255   unnamed++;
256   return NewStringf("$unnamed%d$",unnamed);
257 }
258
259 /* Return if the node is a friend declaration */
260 static int is_friend(Node *n) {
261   return Cmp(Getattr(n,"storage"),"friend") == 0;
262 }
263
264 static int is_operator(String *name) {
265   return Strncmp(name,"operator ", 9) == 0;
266 }
267
268
269 /* Add declaration list to symbol table */
270 static int  add_only_one = 0;
271
272 static void add_symbols(Node *n) {
273   String *decl;
274   String *wrn = 0;
275   if (inclass && n) {
276     cparse_normalize_void(n);
277   }
278   while (n) {
279     String *symname = 0;
280     /* for friends, we need to pop the scope once */
281     String *old_prefix = 0;
282     Symtab *old_scope = 0;
283     int isfriend = inclass && is_friend(n);
284     int iscdecl = Cmp(nodeType(n),"cdecl") == 0;
285     int only_csymbol = 0;
286     if (extendmode) {
287       Setattr(n,"isextension","1");
288     }
289     
290     if (inclass) {
291       String *name = Getattr(n, "name");
292       if (isfriend) {
293         /* for friends, we need to add the scopename if needed */
294         String *prefix = name ? Swig_scopename_prefix(name) : 0;
295         old_prefix = Namespaceprefix;
296         old_scope = Swig_symbol_popscope();
297         Namespaceprefix = Swig_symbol_qualifiedscopename(0);
298         if (!prefix) {
299           if (name && !is_operator(name) && Namespaceprefix) {
300             String *nname = NewStringf("%s::%s", Namespaceprefix, name);
301             Setattr(n,"name",nname);
302             Delete(nname);
303           }
304         } else {
305           Symtab *st = Swig_symbol_getscope(prefix);
306           String *ns = st ? Getattr(st,"name") : prefix;
307           String *base  = Swig_scopename_last(name);
308           String *nname = NewStringf("%s::%s", ns, base);
309           Setattr(n,"name",nname);
310           Delete(nname);
311           Delete(base);
312           Delete(prefix);
313         }
314         Namespaceprefix = 0;
315       } else {
316         /* for member functions, we need to remove the redundant
317            class scope if provided, as in
318            
319            struct Foo {
320            int Foo::method(int a);
321            };
322            
323         */
324         String *prefix = name ? Swig_scopename_prefix(name) : 0;
325         if (prefix) {
326           if (Classprefix && (Equal(prefix,Classprefix))) {
327             String *base = Swig_scopename_last(name);
328             Setattr(n,"name",base);
329             Delete(base);
330           }
331           Delete(prefix);
332         }
333
334         /*
335         if (!Getattr(n,"parentNode") && class_level) set_parentNode(n,class_decl[class_level - 1]);
336         */
337         Setattr(n,"ismember","1");
338       }
339     }
340     if (!isfriend && inclass) {
341       if ((cplus_mode != CPLUS_PUBLIC)) {
342         only_csymbol = 1;
343         if (cplus_mode == CPLUS_PROTECTED) {
344           Setattr(n,"access", "protected");
345           only_csymbol = !Swig_need_protected(n);
346         } else {
347           Setattr(n,"access", "private");
348           /* private are needed only when they are pure virtuals - why? */
349           if ((Cmp(Getattr(n,"storage"),"virtual") == 0) && (Cmp(Getattr(n,"value"),"0") == 0)) {
350             only_csymbol = 0;
351           }
352         }
353       } else {
354           Setattr(n,"access", "public");
355       }
356     }
357     if (Getattr(n,"sym:name")) {
358       n = nextSibling(n);
359       continue;
360     }
361     decl = Getattr(n,"decl");
362     if (!SwigType_isfunction(decl)) {
363       String *name = Getattr(n,"name");
364       String *makename = Getattr(n,"parser:makename");
365       if (iscdecl) {    
366         String *storage = Getattr(n, "storage");
367         if (Cmp(storage,"typedef") == 0) {
368           Setattr(n,"kind","typedef");
369         } else {
370           SwigType *type = Getattr(n,"type");
371           String *value = Getattr(n,"value");
372           Setattr(n,"kind","variable");
373           if (value && Len(value)) {
374             Setattr(n,"hasvalue","1");
375           }
376           if (type) {
377             SwigType *ty;
378             SwigType *tmp = 0;
379             if (decl) {
380               ty = tmp = Copy(type);
381               SwigType_push(ty,decl);
382             } else {
383               ty = type;
384             }
385             if (!SwigType_ismutable(ty)) {
386               SetFlag(n,"hasconsttype");
387               SetFlag(n,"feature:immutable");
388             }
389             if (tmp) Delete(tmp);
390           }
391           if (!type) {
392             Printf(stderr,"notype name %s\n", name);
393           }
394         }
395       }
396       Swig_features_get(Swig_cparse_features(), Namespaceprefix, name, 0, n);
397       if (makename) {
398         symname = make_name(n, makename,0);
399         Delattr(n,"parser:makename"); /* temporary information, don't leave it hanging around */
400       } else {
401         makename = name;
402         symname = make_name(n, makename,0);
403       }
404       
405       if (!symname) {
406         symname = Copy(Getattr(n,"unnamed"));
407       }
408       if (symname) {
409         wrn = Swig_name_warning(n, Namespaceprefix, symname,0);
410       }
411     } else {
412       String *name = Getattr(n,"name");
413       SwigType *fdecl = Copy(decl);
414       SwigType *fun = SwigType_pop_function(fdecl);
415       if (iscdecl) {    
416         Setattr(n,"kind","function");
417       }
418       
419       Swig_features_get(Swig_cparse_features(),Namespaceprefix,name,fun,n);
420
421       symname = make_name(n, name,fun);
422       wrn = Swig_name_warning(n, Namespaceprefix,symname,fun);
423       
424       Delete(fdecl);
425       Delete(fun);
426       
427     }
428     if (!symname) {
429       n = nextSibling(n);
430       continue;
431     }
432     if (only_csymbol || GetFlag(n,"feature:ignore")) {
433       /* Only add to C symbol table and continue */
434       Swig_symbol_add(0, n);
435     } else if (strncmp(Char(symname),"$ignore",7) == 0) {
436       char *c = Char(symname)+7;
437       SetFlag(n,"feature:ignore");
438       if (strlen(c)) {
439         SWIG_WARN_NODE_BEGIN(n);
440         Swig_warning(0,Getfile(n), Getline(n), "%s\n",c+1);
441         SWIG_WARN_NODE_END(n);
442       }
443       Swig_symbol_add(0, n);
444     } else {
445       Node *c;
446       if ((wrn) && (Len(wrn))) {
447         String *metaname = symname;
448         if (!Getmeta(metaname,"already_warned")) {
449           SWIG_WARN_NODE_BEGIN(n);
450           Swig_warning(0,Getfile(n),Getline(n), "%s\n", wrn);
451           SWIG_WARN_NODE_END(n);
452           Setmeta(metaname,"already_warned","1");
453         }
454       }
455       c = Swig_symbol_add(symname,n);
456
457       if (c != n) {
458         /* symbol conflict attempting to add in the new symbol */
459         if (Getattr(n,"sym:weak")) {
460           Setattr(n,"sym:name",symname);
461         } else {
462           String *e = NewStringEmpty();
463           String *en = NewStringEmpty();
464           String *ec = NewStringEmpty();
465           int redefined = Swig_need_redefined_warn(n,c,inclass);
466           if (redefined) {
467             Printf(en,"Identifier '%s' redefined (ignored)",symname);
468             Printf(ec,"previous definition of '%s'",symname);
469           } else {
470             Printf(en,"Redundant redeclaration of '%s'",symname);
471             Printf(ec,"previous declaration of '%s'",symname);
472           }
473           if (Cmp(symname,Getattr(n,"name"))) {
474             Printf(en," (Renamed from '%s')", SwigType_namestr(Getattr(n,"name")));
475           }
476           Printf(en,",");
477           if (Cmp(symname,Getattr(c,"name"))) {
478             Printf(ec," (Renamed from '%s')", SwigType_namestr(Getattr(c,"name")));
479           }
480           Printf(ec,".");
481           SWIG_WARN_NODE_BEGIN(n);
482           if (redefined) {
483             Swig_warning(WARN_PARSE_REDEFINED,Getfile(n),Getline(n),"%s\n",en);
484             Swig_warning(WARN_PARSE_REDEFINED,Getfile(c),Getline(c),"%s\n",ec);
485           } else if (!is_friend(n) && !is_friend(c)) {
486             Swig_warning(WARN_PARSE_REDUNDANT,Getfile(n),Getline(n),"%s\n",en);
487             Swig_warning(WARN_PARSE_REDUNDANT,Getfile(c),Getline(c),"%s\n",ec);
488           }
489           SWIG_WARN_NODE_END(n);
490           Printf(e,"%s:%d:%s\n%s:%d:%s\n",Getfile(n),Getline(n),en,
491                  Getfile(c),Getline(c),ec);
492           Setattr(n,"error",e);
493           Delete(e);
494           Delete(en);
495           Delete(ec);
496         }
497       }
498     }
499     /* restore the class scope if needed */
500     if (isfriend) {
501       Swig_symbol_setscope(old_scope);
502       if (old_prefix) {
503         Delete(Namespaceprefix);
504         Namespaceprefix = old_prefix;
505       }
506     }
507     Delete(symname);
508
509     if (add_only_one) return;
510     n = nextSibling(n);
511   }
512 }
513
514
515 /* add symbols a parse tree node copy */
516
517 static void add_symbols_copy(Node *n) {
518   String *name;
519   int    emode = 0;
520   while (n) {
521     char *cnodeType = Char(nodeType(n));
522
523     if (strcmp(cnodeType,"access") == 0) {
524       String *kind = Getattr(n,"kind");
525       if (Strcmp(kind,"public") == 0) {
526         cplus_mode = CPLUS_PUBLIC;
527       } else if (Strcmp(kind,"private") == 0) {
528         cplus_mode = CPLUS_PRIVATE;
529       } else if (Strcmp(kind,"protected") == 0) {
530         cplus_mode = CPLUS_PROTECTED;
531       }
532       n = nextSibling(n);
533       continue;
534     }
535
536     add_oldname = Getattr(n,"sym:name");
537     if ((add_oldname) || (Getattr(n,"sym:needs_symtab"))) {
538       if (add_oldname) {
539         DohIncref(add_oldname);
540         /*  Disable this, it prevents %rename to work with templates */
541         /* If already renamed, we used that name  */
542         /*
543         if (Strcmp(add_oldname, Getattr(n,"name")) != 0) {
544           Delete(yyrename);
545           yyrename = Copy(add_oldname);
546         }
547         */
548       }
549       Delattr(n,"sym:needs_symtab");
550       Delattr(n,"sym:name");
551
552       add_only_one = 1;
553       add_symbols(n);
554
555       if (Getattr(n,"partialargs")) {
556         Swig_symbol_cadd(Getattr(n,"partialargs"),n);
557       }
558       add_only_one = 0;
559       name = Getattr(n,"name");
560       if (Getattr(n,"requires_symtab")) {
561         Swig_symbol_newscope();
562         Swig_symbol_setscopename(name);
563         Delete(Namespaceprefix);
564         Namespaceprefix = Swig_symbol_qualifiedscopename(0);
565       }
566       if (strcmp(cnodeType,"class") == 0) {
567         inclass = 1;
568         current_class = n;
569         if (Strcmp(Getattr(n,"kind"),"class") == 0) {
570           cplus_mode = CPLUS_PRIVATE;
571         } else {
572           cplus_mode = CPLUS_PUBLIC;
573         }
574       }
575       if (strcmp(cnodeType,"extend") == 0) {
576         emode = cplus_mode;
577         cplus_mode = CPLUS_PUBLIC;
578       }
579       add_symbols_copy(firstChild(n));
580       if (strcmp(cnodeType,"extend") == 0) {
581         cplus_mode = emode;
582       }
583       if (Getattr(n,"requires_symtab")) {
584         Setattr(n,"symtab", Swig_symbol_popscope());
585         Delattr(n,"requires_symtab");
586         Delete(Namespaceprefix);
587         Namespaceprefix = Swig_symbol_qualifiedscopename(0);
588       }
589       if (add_oldname) {
590         Delete(add_oldname);
591         add_oldname = 0;
592       }
593       if (strcmp(cnodeType,"class") == 0) {
594         inclass = 0;
595         current_class = 0;
596       }
597     } else {
598       if (strcmp(cnodeType,"extend") == 0) {
599         emode = cplus_mode;
600         cplus_mode = CPLUS_PUBLIC;
601       }
602       add_symbols_copy(firstChild(n));
603       if (strcmp(cnodeType,"extend") == 0) {
604         cplus_mode = emode;
605       }
606     }
607     n = nextSibling(n);
608   }
609 }
610
611 /* Extension merge.  This function is used to handle the %extend directive
612    when it appears before a class definition.   To handle this, the %extend
613    actually needs to take precedence.  Therefore, we will selectively nuke symbols
614    from the current symbol table, replacing them with the added methods */
615
616 static void merge_extensions(Node *cls, Node *am) {
617   Node *n;
618   Node *csym;
619
620   n = firstChild(am);
621   while (n) {
622     String *symname;
623     if (Strcmp(nodeType(n),"constructor") == 0) {
624       symname = Getattr(n,"sym:name");
625       if (symname) {
626         if (Strcmp(symname,Getattr(n,"name")) == 0) {
627           /* If the name and the sym:name of a constructor are the same,
628              then it hasn't been renamed.  However---the name of the class
629              itself might have been renamed so we need to do a consistency
630              check here */
631           if (Getattr(cls,"sym:name")) {
632             Setattr(n,"sym:name", Getattr(cls,"sym:name"));
633           }
634         }
635       } 
636     }
637
638     symname = Getattr(n,"sym:name");
639     DohIncref(symname);
640     if ((symname) && (!Getattr(n,"error"))) {
641       /* Remove node from its symbol table */
642       Swig_symbol_remove(n);
643       csym = Swig_symbol_add(symname,n);
644       if (csym != n) {
645         /* Conflict with previous definition.  Nuke previous definition */
646         String *e = NewStringEmpty();
647         String *en = NewStringEmpty();
648         String *ec = NewStringEmpty();
649         Printf(ec,"Identifier '%s' redefined by %%extend (ignored),",symname);
650         Printf(en,"%%extend definition of '%s'.",symname);
651         SWIG_WARN_NODE_BEGIN(n);
652         Swig_warning(WARN_PARSE_REDEFINED,Getfile(csym),Getline(csym),"%s\n",ec);
653         Swig_warning(WARN_PARSE_REDEFINED,Getfile(n),Getline(n),"%s\n",en);
654         SWIG_WARN_NODE_END(n);
655         Printf(e,"%s:%d:%s\n%s:%d:%s\n",Getfile(csym),Getline(csym),ec, 
656                Getfile(n),Getline(n),en);
657         Setattr(csym,"error",e);
658         Delete(e);
659         Delete(en);
660         Delete(ec);
661         Swig_symbol_remove(csym);              /* Remove class definition */
662         Swig_symbol_add(symname,n);            /* Insert extend definition */
663       }
664     }
665     n = nextSibling(n);
666   }
667 }
668
669 static void append_previous_extension(Node *cls, Node *am) {
670   Node *n, *ne;
671   Node *pe = 0;
672   Node *ae = 0;
673
674   if (!am) return;
675   
676   n = firstChild(am);
677   while (n) {
678     ne = nextSibling(n);
679     set_nextSibling(n,0);
680     /* typemaps and fragments need to be prepended */
681     if (((Cmp(nodeType(n),"typemap") == 0) || (Cmp(nodeType(n),"fragment") == 0)))  {
682       if (!pe) pe = new_node("extend");
683       appendChild(pe, n);
684     } else {
685       if (!ae) ae = new_node("extend");
686       appendChild(ae, n);
687     }    
688     n = ne;
689   }
690   if (pe) prependChild(cls,pe);
691   if (ae) appendChild(cls,ae);
692 }
693  
694
695 /* Check for unused %extend.  Special case, don't report unused
696    extensions for templates */
697  
698 static void check_extensions() {
699   Iterator ki;
700
701   if (!extendhash) return;
702   for (ki = First(extendhash); ki.key; ki = Next(ki)) {
703     if (!Strchr(ki.key,'<')) {
704       SWIG_WARN_NODE_BEGIN(ki.item);
705       Swig_warning(WARN_PARSE_EXTEND_UNDEF,Getfile(ki.item), Getline(ki.item), "%%extend defined for an undeclared class %s.\n", ki.key);
706       SWIG_WARN_NODE_END(ki.item);
707     }
708   }
709 }
710
711 /* Check a set of declarations to see if any are pure-abstract */
712
713 static List *pure_abstract(Node *n) {
714   List *abs = 0;
715   while (n) {
716     if (Cmp(nodeType(n),"cdecl") == 0) {
717       String *decl = Getattr(n,"decl");
718       if (SwigType_isfunction(decl)) {
719         String *init = Getattr(n,"value");
720         if (Cmp(init,"0") == 0) {
721           if (!abs) {
722             abs = NewList();
723           }
724           Append(abs,n);
725           Setattr(n,"abstract","1");
726         }
727       }
728     } else if (Cmp(nodeType(n),"destructor") == 0) {
729       if (Cmp(Getattr(n,"value"),"0") == 0) {
730         if (!abs) {
731           abs = NewList();
732         }
733         Append(abs,n);
734         Setattr(n,"abstract","1");
735       }
736     }
737     n = nextSibling(n);
738   }
739   return abs;
740 }
741
742 /* Make a classname */
743
744 static String *make_class_name(String *name) {
745   String *nname = 0;
746   if (Namespaceprefix) {
747     nname= NewStringf("%s::%s", Namespaceprefix, name);
748   } else {
749     nname = NewString(name);
750   }
751   if (SwigType_istemplate(nname)) {
752     String *prefix, *args, *qargs;
753     prefix = SwigType_templateprefix(nname);
754     args   = SwigType_templateargs(nname);
755     qargs  = Swig_symbol_type_qualify(args,0);
756     Append(prefix,qargs);
757     Delete(nname);
758     Delete(args);
759     Delete(qargs);
760     nname = prefix;
761   }
762   return nname;
763 }
764
765 static List *make_inherit_list(String *clsname, List *names) {
766   int i, ilen;
767   String *derived;
768   List *bases = NewList();
769
770   if (Namespaceprefix) derived = NewStringf("%s::%s", Namespaceprefix,clsname);
771   else derived = NewString(clsname);
772
773   ilen = Len(names);
774   for (i = 0; i < ilen; i++) {
775     Node *s;
776     String *base;
777     String *n = Getitem(names,i);
778     /* Try to figure out where this symbol is */
779     s = Swig_symbol_clookup(n,0);
780     if (s) {
781       while (s && (Strcmp(nodeType(s),"class") != 0)) {
782         /* Not a class.  Could be a typedef though. */
783         String *storage = Getattr(s,"storage");
784         if (storage && (Strcmp(storage,"typedef") == 0)) {
785           String *nn = Getattr(s,"type");
786           s = Swig_symbol_clookup(nn,Getattr(s,"sym:symtab"));
787         } else {
788           break;
789         }
790       }
791       if (s && ((Strcmp(nodeType(s),"class") == 0) || (Strcmp(nodeType(s),"template") == 0))) {
792         String *q = Swig_symbol_qualified(s);
793         Append(bases,s);
794         if (q) {
795           base = NewStringf("%s::%s", q, Getattr(s,"name"));
796           Delete(q);
797         } else {
798           base = NewString(Getattr(s,"name"));
799         }
800       } else {
801         base = NewString(n);
802       }
803     } else {
804       base = NewString(n);
805     }
806     if (base) {
807       Swig_name_inherit(base,derived);
808       Delete(base);
809     }
810   }
811   return bases;
812 }
813
814 /* If the class name is qualified.  We need to create or lookup namespace entries */
815
816 static Symtab *get_global_scope() {
817   Symtab *symtab = Swig_symbol_current();
818   Node   *pn = parentNode(symtab);
819   while (pn) {
820     symtab = pn;
821     pn = parentNode(symtab);
822     if (!pn) break;
823   }
824   Swig_symbol_setscope(symtab);
825   return symtab;
826 }
827  
828 /* Remove the block braces, { and }, if the 'noblock' attribute is set.
829  * Node *kw can be either a Hash or Parmlist. */
830 static String *remove_block(Node *kw, const String *inputcode) {
831   String *modified_code = 0;
832   while (kw) {
833    String *name = Getattr(kw,"name");
834    if (name && (Cmp(name,"noblock") == 0)) {
835      char *cstr = Char(inputcode);
836      size_t len = Len(inputcode);
837      if (len && cstr[0] == '{') {
838        --len; ++cstr; 
839        if (len && cstr[len - 1] == '}') { --len; }
840        /* we now remove the extra spaces */
841        while (len && isspace((int)cstr[0])) { --len; ++cstr; }
842        while (len && isspace((int)cstr[len - 1])) { --len; }
843        modified_code = NewStringWithSize(cstr, len);
844        break;
845      }
846    }
847    kw = nextSibling(kw);
848   }
849   return modified_code;
850 }
851
852
853 static Node *nscope = 0;
854 static Node *nscope_inner = 0;
855 static String *resolve_node_scope(String *cname) {
856   Symtab *gscope = 0;
857   nscope = 0;
858   nscope_inner = 0;  
859   if (Swig_scopename_check(cname)) {
860     Node   *ns;
861     String *prefix = Swig_scopename_prefix(cname);
862     String *base = Swig_scopename_last(cname);
863     if (prefix && (Strncmp(prefix,"::",2) == 0)) {
864       /* Use the global scope */
865       String *nprefix = NewString(Char(prefix)+2);
866       Delete(prefix);
867       prefix= nprefix;
868       gscope = get_global_scope();
869     }    
870     if (!prefix || (Len(prefix) == 0)) {
871       /* Use the global scope, but we need to add a 'global' namespace.  */
872       if (!gscope) gscope = get_global_scope();
873       /* note that this namespace is not the "unnamed" one,
874          and we don't use Setattr(nscope,"name", ""),
875          because the unnamed namespace is private */
876       nscope = new_node("namespace");
877       Setattr(nscope,"symtab", gscope);;
878       nscope_inner = nscope;
879       return base;
880     }
881     /* Try to locate the scope */
882     ns = Swig_symbol_clookup(prefix,0);
883     if (!ns) {
884       Swig_error(cparse_file,cparse_line,"Undefined scope '%s'\n", prefix);
885     } else {
886       Symtab *nstab = Getattr(ns,"symtab");
887       if (!nstab) {
888         Swig_error(cparse_file,cparse_line,
889                    "'%s' is not defined as a valid scope.\n", prefix);
890         ns = 0;
891       } else {
892         /* Check if the node scope is the current scope */
893         String *tname = Swig_symbol_qualifiedscopename(0);
894         String *nname = Swig_symbol_qualifiedscopename(nstab);
895         if (tname && (Strcmp(tname,nname) == 0)) {
896           ns = 0;
897           cname = base;
898         }
899         Delete(tname);
900         Delete(nname);
901       }
902       if (ns) {
903         /* we will try to create a new node using the namespaces we
904            can find in the scope name */
905         List *scopes;
906         String *sname;
907         Iterator si;
908         String *name = NewString(prefix);
909         scopes = NewList();
910         while (name) {
911           String *base = Swig_scopename_last(name);
912           String *tprefix = Swig_scopename_prefix(name);
913           Insert(scopes,0,base);
914           Delete(base);
915           Delete(name);
916           name = tprefix;
917         }
918         for (si = First(scopes); si.item; si = Next(si)) {
919           Node *ns1,*ns2;
920           sname = si.item;
921           ns1 = Swig_symbol_clookup(sname,0);
922           assert(ns1);
923           if (Strcmp(nodeType(ns1),"namespace") == 0) {
924             if (Getattr(ns1,"alias")) {
925               ns1 = Getattr(ns1,"namespace");
926             }
927           } else {
928             /* now this last part is a class */
929             si = Next(si);
930             ns1 = Swig_symbol_clookup(sname,0);
931             /*  or a nested class tree, which is unrolled here */
932             for (; si.item; si = Next(si)) {
933               if (si.item) {
934                 Printf(sname,"::%s",si.item);
935               }
936             }
937             /* we get the 'inner' class */
938             nscope_inner = Swig_symbol_clookup(sname,0);
939             /* set the scope to the inner class */
940             Swig_symbol_setscope(Getattr(nscope_inner,"symtab"));
941             /* save the last namespace prefix */
942             Delete(Namespaceprefix);
943             Namespaceprefix = Swig_symbol_qualifiedscopename(0);
944             /* and return the node name, including the inner class prefix */
945             break;
946           }
947           /* here we just populate the namespace tree as usual */
948           ns2 = new_node("namespace");
949           Setattr(ns2,"name",sname);
950           Setattr(ns2,"symtab", Getattr(ns1,"symtab"));
951           add_symbols(ns2);
952           Swig_symbol_setscope(Getattr(ns1,"symtab"));
953           Delete(Namespaceprefix);
954           Namespaceprefix = Swig_symbol_qualifiedscopename(0);
955           if (nscope_inner) {
956             if (Getattr(nscope_inner,"symtab") != Getattr(ns2,"symtab")) {
957               appendChild(nscope_inner,ns2);
958               Delete(ns2);
959             }
960           }
961           nscope_inner = ns2;
962           if (!nscope) nscope = ns2;
963         }
964         cname = base;
965         Delete(scopes);
966       }
967     }
968     Delete(prefix);
969   }
970   return cname;
971 }
972  
973
974
975
976
977 /* Structures for handling code fragments built for nested classes */
978
979 typedef struct Nested {
980   String   *code;        /* Associated code fragment */
981   int      line;         /* line number where it starts */
982   char     *name;        /* Name associated with this nested class */
983   char     *kind;        /* Kind of class */
984   int      unnamed;      /* unnamed class */
985   SwigType *type;        /* Datatype associated with the name */
986   struct Nested   *next;        /* Next code fragment in list */
987 } Nested;
988
989 /* Some internal variables for saving nested class information */
990
991 static Nested      *nested_list = 0;
992
993 /* Add a function to the nested list */
994
995 static void add_nested(Nested *n) {
996   Nested *n1;
997   if (!nested_list) nested_list = n;
998   else {
999     n1 = nested_list;
1000     while (n1->next) n1 = n1->next;
1001     n1->next = n;
1002   }
1003 }
1004
1005 /* Strips C-style and C++-style comments from string in-place. */
1006 static void strip_comments(char *string) {
1007   int state = 0; /* 
1008                   * 0 - not in comment
1009                   * 1 - in c-style comment
1010                   * 2 - in c++-style comment
1011                   * 3 - in string
1012                   * 4 - after reading / not in comments
1013                   * 5 - after reading * in c-style comments
1014                   * 6 - after reading \ in strings
1015                   */
1016   char * c = string;
1017   while (*c) {
1018     switch (state) {
1019     case 0:
1020       if (*c == '\"')
1021         state = 3;
1022       else if (*c == '/')
1023         state = 4;
1024       break;
1025     case 1:
1026       if (*c == '*')
1027         state = 5;
1028       *c = ' ';
1029       break;
1030     case 2:
1031       if (*c == '\n')
1032         state = 0;
1033       else
1034         *c = ' ';
1035       break;
1036     case 3:
1037       if (*c == '\"')
1038         state = 0;
1039       else if (*c == '\\')
1040         state = 6;
1041       break;
1042     case 4:
1043       if (*c == '/') {
1044         *(c-1) = ' ';
1045         *c = ' ';
1046         state = 2;
1047       } else if (*c == '*') {
1048         *(c-1) = ' ';
1049         *c = ' ';
1050         state = 1;
1051       } else
1052         state = 0;
1053       break;
1054     case 5:
1055       if (*c == '/')
1056         state = 0;
1057       else 
1058         state = 1;
1059       *c = ' ';
1060       break;
1061     case 6:
1062       state = 3;
1063       break;
1064     }
1065     ++c;
1066   }
1067 }
1068
1069 /* Dump all of the nested class declarations to the inline processor
1070  * However.  We need to do a few name replacements and other munging
1071  * first.  This function must be called before closing a class! */
1072
1073 static Node *dump_nested(const char *parent) {
1074   Nested *n,*n1;
1075   Node *ret = 0;
1076   n = nested_list;
1077   if (!parent) {
1078     nested_list = 0;
1079     return 0;
1080   }
1081   while (n) {
1082     Node *retx;
1083     SwigType *nt;
1084     /* Token replace the name of the parent class */
1085     Replace(n->code, "$classname", parent, DOH_REPLACE_ANY);
1086
1087     /* Fix up the name of the datatype (for building typedefs and other stuff) */
1088     Append(n->type,parent);
1089     Append(n->type,"_");
1090     Append(n->type,n->name);
1091
1092     /* Add the appropriate declaration to the C++ processor */
1093     retx = new_node("cdecl");
1094     Setattr(retx,"name",n->name);
1095     nt = Copy(n->type);
1096     Setattr(retx,"type",nt);
1097     Delete(nt);
1098     Setattr(retx,"nested",parent);
1099     if (n->unnamed) {
1100       Setattr(retx,"unnamed","1");
1101     }
1102     
1103     add_symbols(retx);
1104     if (ret) {
1105       set_nextSibling(retx,ret);
1106       Delete(ret);
1107     }
1108     ret = retx;
1109
1110     /* Insert a forward class declaration */
1111     /* Disabled: [ 597599 ] union in class: incorrect scope 
1112        retx = new_node("classforward");
1113        Setattr(retx,"kind",n->kind);
1114        Setattr(retx,"name",Copy(n->type));
1115        Setattr(retx,"sym:name", make_name(n->type,0));
1116        set_nextSibling(retx,ret);
1117        ret = retx; 
1118     */
1119
1120     /* Strip comments - further code may break in presence of comments. */
1121     strip_comments(Char(n->code));
1122
1123     /* Make all SWIG created typedef structs/unions/classes unnamed else 
1124        redefinition errors occur - nasty hack alert.*/
1125
1126     {
1127       const char* types_array[3] = {"struct", "union", "class"};
1128       int i;
1129       for (i=0; i<3; i++) {
1130         char* code_ptr = Char(n->code);
1131         while (code_ptr) {
1132           /* Replace struct name (as in 'struct name {...}' ) with whitespace
1133              name will be between struct and opening brace */
1134         
1135           code_ptr = strstr(code_ptr, types_array[i]);
1136           if (code_ptr) {
1137             char *open_bracket_pos;
1138             code_ptr += strlen(types_array[i]);
1139             open_bracket_pos = strchr(code_ptr, '{');
1140             if (open_bracket_pos) { 
1141               /* Make sure we don't have something like struct A a; */
1142               char* semi_colon_pos = strchr(code_ptr, ';');
1143               if (!(semi_colon_pos && (semi_colon_pos < open_bracket_pos)))
1144                 while (code_ptr < open_bracket_pos)
1145                   *code_ptr++ = ' ';
1146             }
1147           }
1148         }
1149       }
1150     }
1151     
1152     {
1153       /* Remove SWIG directive %constant which may be left in the SWIG created typedefs */
1154       char* code_ptr = Char(n->code);
1155       while (code_ptr) {
1156         code_ptr = strstr(code_ptr, "%constant");
1157         if (code_ptr) {
1158           char* directive_end_pos = strchr(code_ptr, ';');
1159           if (directive_end_pos) { 
1160             while (code_ptr <= directive_end_pos)
1161               *code_ptr++ = ' ';
1162           }
1163         }
1164       }
1165     }
1166     {
1167       Node *head = new_node("insert");
1168       String *code = NewStringf("\n%s\n",n->code);
1169       Setattr(head,"code", code);
1170       Delete(code);
1171       set_nextSibling(head,ret);
1172       Delete(ret);      
1173       ret = head;
1174     }
1175       
1176     /* Dump the code to the scanner */
1177     start_inline(Char(n->code),n->line);
1178
1179     n1 = n->next;
1180     Delete(n->code);
1181     free(n);
1182     n = n1;
1183   }
1184   nested_list = 0;
1185   return ret;
1186 }
1187
1188 Node *Swig_cparse(File *f) {
1189   scanner_file(f);
1190   top = 0;
1191   yyparse();
1192   return top;
1193 }
1194
1195 static void single_new_feature(const char *featurename, String *val, Hash *featureattribs, char *declaratorid, SwigType *type, ParmList *declaratorparms, String *qualifier) {
1196   String *fname;
1197   String *name;
1198   String *fixname;
1199   SwigType *t = Copy(type);
1200
1201   /* Printf(stdout, "single_new_feature: [%s] [%s] [%s] [%s] [%s] [%s]\n", featurename, val, declaratorid, t, ParmList_str_defaultargs(declaratorparms), qualifier); */
1202
1203   fname = NewStringf("feature:%s",featurename);
1204   if (declaratorid) {
1205     fixname = feature_identifier_fix(declaratorid);
1206   } else {
1207     fixname = NewStringEmpty();
1208   }
1209   if (Namespaceprefix) {
1210     name = NewStringf("%s::%s",Namespaceprefix, fixname);
1211   } else {
1212     name = fixname;
1213   }
1214
1215   if (declaratorparms) Setmeta(val,"parms",declaratorparms);
1216   if (!Len(t)) t = 0;
1217   if (t) {
1218     if (qualifier) SwigType_push(t,qualifier);
1219     if (SwigType_isfunction(t)) {
1220       SwigType *decl = SwigType_pop_function(t);
1221       if (SwigType_ispointer(t)) {
1222         String *nname = NewStringf("*%s",name);
1223         Swig_feature_set(Swig_cparse_features(), nname, decl, fname, val, featureattribs);
1224         Delete(nname);
1225       } else {
1226         Swig_feature_set(Swig_cparse_features(), name, decl, fname, val, featureattribs);
1227       }
1228       Delete(decl);
1229     } else if (SwigType_ispointer(t)) {
1230       String *nname = NewStringf("*%s",name);
1231       Swig_feature_set(Swig_cparse_features(),nname,0,fname,val, featureattribs);
1232       Delete(nname);
1233     }
1234   } else {
1235     /* Global feature, that is, feature not associated with any particular symbol */
1236     Swig_feature_set(Swig_cparse_features(),name,0,fname,val, featureattribs);
1237   }
1238   Delete(fname);
1239   Delete(name);
1240 }
1241
1242 /* Add a new feature to the Hash. Additional features are added if the feature has a parameter list (declaratorparms)
1243  * and one or more of the parameters have a default argument. An extra feature is added for each defaulted parameter,
1244  * simulating the equivalent overloaded method. */
1245 static void new_feature(const char *featurename, String *val, Hash *featureattribs, char *declaratorid, SwigType *type, ParmList *declaratorparms, String *qualifier) {
1246
1247   ParmList *declparms = declaratorparms;
1248
1249   /* remove the { and } braces if the noblock attribute is set */
1250   String *newval = remove_block(featureattribs, val);
1251   val = newval ? newval : val;
1252
1253   /* Add the feature */
1254   single_new_feature(featurename, val, featureattribs, declaratorid, type, declaratorparms, qualifier);
1255
1256   /* Add extra features if there are default parameters in the parameter list */
1257   if (type) {
1258     while (declparms) {
1259       if (ParmList_has_defaultargs(declparms)) {
1260
1261         /* Create a parameter list for the new feature by copying all
1262            but the last (defaulted) parameter */
1263         ParmList* newparms = CopyParmListMax(declparms, ParmList_len(declparms)-1);
1264
1265         /* Create new declaration - with the last parameter removed */
1266         SwigType *newtype = Copy(type);
1267         Delete(SwigType_pop_function(newtype)); /* remove the old parameter list from newtype */
1268         SwigType_add_function(newtype,newparms);
1269
1270         single_new_feature(featurename, Copy(val), featureattribs, declaratorid, newtype, newparms, qualifier);
1271         declparms = newparms;
1272       } else {
1273         declparms = 0;
1274       }
1275     }
1276   }
1277 }
1278
1279 /* check if a function declaration is a plain C object */
1280 static int is_cfunction(Node *n) {
1281   if (!cparse_cplusplus || cparse_externc) return 1;
1282   if (Cmp(Getattr(n,"storage"),"externc") == 0) {
1283     return 1;
1284   }
1285   return 0;
1286 }
1287
1288 /* If the Node is a function with parameters, check to see if any of the parameters
1289  * have default arguments. If so create a new function for each defaulted argument. 
1290  * The additional functions form a linked list of nodes with the head being the original Node n. */
1291 static void default_arguments(Node *n) {
1292   Node *function = n;
1293
1294   if (function) {
1295     ParmList *varargs = Getattr(function,"feature:varargs");
1296     if (varargs) {
1297       /* Handles the %varargs directive by looking for "feature:varargs" and 
1298        * substituting ... with an alternative set of arguments.  */
1299       Parm     *p = Getattr(function,"parms");
1300       Parm     *pp = 0;
1301       while (p) {
1302         SwigType *t = Getattr(p,"type");
1303         if (Strcmp(t,"v(...)") == 0) {
1304           if (pp) {
1305             ParmList *cv = Copy(varargs);
1306             set_nextSibling(pp,cv);
1307             Delete(cv);
1308           } else {
1309             ParmList *cv =  Copy(varargs);
1310             Setattr(function,"parms", cv);
1311             Delete(cv);
1312           }
1313           break;
1314         }
1315         pp = p;
1316         p = nextSibling(p);
1317       }
1318     }
1319
1320     /* Do not add in functions if kwargs is being used or if user wants old default argument wrapping
1321        (one wrapped method per function irrespective of number of default arguments) */
1322     if (compact_default_args 
1323         || is_cfunction(function) 
1324         || GetFlag(function,"feature:compactdefaultargs") 
1325         || GetFlag(function,"feature:kwargs")) {
1326       ParmList *p = Getattr(function,"parms");
1327       if (p) 
1328         Setattr(p,"compactdefargs", "1"); /* mark parameters for special handling */
1329       function = 0; /* don't add in extra methods */
1330     }
1331   }
1332
1333   while (function) {
1334     ParmList *parms = Getattr(function,"parms");
1335     if (ParmList_has_defaultargs(parms)) {
1336
1337       /* Create a parameter list for the new function by copying all
1338          but the last (defaulted) parameter */
1339       ParmList* newparms = CopyParmListMax(parms,ParmList_len(parms)-1);
1340
1341       /* Create new function and add to symbol table */
1342       {
1343         SwigType *ntype = Copy(nodeType(function));
1344         char *cntype = Char(ntype);
1345         Node *new_function = new_node(ntype);
1346         SwigType *decl = Copy(Getattr(function,"decl"));
1347         int constqualifier = SwigType_isconst(decl);
1348         String *ccode = Copy(Getattr(function,"code"));
1349         String *cstorage = Copy(Getattr(function,"storage"));
1350         String *cvalue = Copy(Getattr(function,"value"));
1351         SwigType *ctype = Copy(Getattr(function,"type"));
1352         String *cthrow = Copy(Getattr(function,"throw"));
1353
1354         Delete(SwigType_pop_function(decl)); /* remove the old parameter list from decl */
1355         SwigType_add_function(decl,newparms);
1356         if (constqualifier)
1357           SwigType_add_qualifier(decl,"const");
1358
1359         Setattr(new_function,"name", Getattr(function,"name"));
1360         Setattr(new_function,"code", ccode);
1361         Setattr(new_function,"decl", decl);
1362         Setattr(new_function,"parms", newparms);
1363         Setattr(new_function,"storage", cstorage);
1364         Setattr(new_function,"value", cvalue);
1365         Setattr(new_function,"type", ctype);
1366         Setattr(new_function,"throw", cthrow);
1367
1368         Delete(ccode);
1369         Delete(cstorage);
1370         Delete(cvalue);
1371         Delete(ctype);
1372         Delete(cthrow);
1373         Delete(decl);
1374
1375         {
1376           Node *throws = Getattr(function,"throws");
1377           ParmList *pl = CopyParmList(throws);
1378           if (throws) Setattr(new_function,"throws",pl);
1379           Delete(pl);
1380         }
1381
1382         /* copy specific attributes for global (or in a namespace) template functions - these are not templated class methods */
1383         if (strcmp(cntype,"template") == 0) {
1384           Node *templatetype = Getattr(function,"templatetype");
1385           Node *symtypename = Getattr(function,"sym:typename");
1386           Parm *templateparms = Getattr(function,"templateparms");
1387           if (templatetype) {
1388             Node *tmp = Copy(templatetype);
1389             Setattr(new_function,"templatetype",tmp);
1390             Delete(tmp);
1391           }
1392           if (symtypename) {
1393             Node *tmp = Copy(symtypename);
1394             Setattr(new_function,"sym:typename",tmp);
1395             Delete(tmp);
1396           }
1397           if (templateparms) {
1398             Parm *tmp = CopyParmList(templateparms);
1399             Setattr(new_function,"templateparms",tmp);
1400             Delete(tmp);
1401           }
1402         } else if (strcmp(cntype,"constructor") == 0) {
1403           /* only copied for constructors as this is not a user defined feature - it is hard coded in the parser */
1404           if (GetFlag(function,"feature:new")) SetFlag(new_function,"feature:new");
1405         }
1406
1407         add_symbols(new_function);
1408         /* mark added functions as ones with overloaded parameters and point to the parsed method */
1409         Setattr(new_function,"defaultargs", n);
1410
1411         /* Point to the new function, extending the linked list */
1412         set_nextSibling(function, new_function);
1413         Delete(new_function);
1414         function = new_function;
1415         
1416         Delete(ntype);
1417       }
1418     } else {
1419       function = 0;
1420     }
1421   }
1422 }
1423
1424 /* -----------------------------------------------------------------------------
1425  * tag_nodes()
1426  *
1427  * Used by the parser to mark subtypes with extra information.
1428  * ----------------------------------------------------------------------------- */
1429
1430 static void tag_nodes(Node *n, const_String_or_char_ptr attrname, DOH *value) {
1431   while (n) {
1432     Setattr(n, attrname, value);
1433     tag_nodes(firstChild(n), attrname, value);
1434     n = nextSibling(n);
1435   }
1436 }
1437
1438 %}
1439
1440 %union {
1441   char  *id;
1442   List  *bases;
1443   struct Define {
1444     String *val;
1445     String *rawval;
1446     int     type;
1447     String *qualifier;
1448     String *bitfield;
1449     Parm   *throws;
1450     String *throwf;
1451   } dtype;
1452   struct {
1453     char *type;
1454     String *filename;
1455     int   line;
1456   } loc;
1457   struct {
1458     char      *id;
1459     SwigType  *type;
1460     String    *defarg;
1461     ParmList  *parms;
1462     short      have_parms;
1463     ParmList  *throws;
1464     String    *throwf;
1465   } decl;
1466   Parm         *tparms;
1467   struct {
1468     String     *method;
1469     Hash       *kwargs;
1470   } tmap;
1471   struct {
1472     String     *type;
1473     String     *us;
1474   } ptype;
1475   SwigType     *type;
1476   String       *str;
1477   Parm         *p;
1478   ParmList     *pl;
1479   int           ivalue;
1480   Node         *node;
1481 };
1482
1483 %token <id> ID
1484 %token <str> HBLOCK
1485 %token <id> POUND 
1486 %token <id> STRING
1487 %token <loc> INCLUDE IMPORT INSERT
1488 %token <str> CHARCONST 
1489 %token <dtype> NUM_INT NUM_FLOAT NUM_UNSIGNED NUM_LONG NUM_ULONG NUM_LONGLONG NUM_ULONGLONG
1490 %token <ivalue> TYPEDEF
1491 %token <type> TYPE_INT TYPE_UNSIGNED TYPE_SHORT TYPE_LONG TYPE_FLOAT TYPE_DOUBLE TYPE_CHAR TYPE_WCHAR TYPE_VOID TYPE_SIGNED TYPE_BOOL TYPE_COMPLEX TYPE_TYPEDEF TYPE_RAW TYPE_NON_ISO_INT8 TYPE_NON_ISO_INT16 TYPE_NON_ISO_INT32 TYPE_NON_ISO_INT64
1492 %token LPAREN RPAREN COMMA SEMI EXTERN INIT LBRACE RBRACE PERIOD
1493 %token CONST_QUAL VOLATILE REGISTER STRUCT UNION EQUAL SIZEOF MODULE LBRACKET RBRACKET
1494 %token ILLEGAL CONSTANT
1495 %token NAME RENAME NAMEWARN EXTEND PRAGMA FEATURE VARARGS
1496 %token ENUM
1497 %token CLASS TYPENAME PRIVATE PUBLIC PROTECTED COLON STATIC VIRTUAL FRIEND THROW CATCH EXPLICIT
1498 %token USING
1499 %token <node> NAMESPACE
1500 %token NATIVE INLINE
1501 %token TYPEMAP EXCEPT ECHO APPLY CLEAR SWIGTEMPLATE FRAGMENT
1502 %token WARN 
1503 %token LESSTHAN GREATERTHAN MODULO DELETE_KW
1504 %token LESSTHANOREQUALTO GREATERTHANOREQUALTO EQUALTO NOTEQUALTO
1505 %token QUESTIONMARK
1506 %token TYPES PARMS
1507 %token NONID DSTAR DCNOT
1508 %token <ivalue> TEMPLATE
1509 %token <str> OPERATOR
1510 %token <str> COPERATOR
1511 %token PARSETYPE PARSEPARM PARSEPARMS
1512
1513 %left  CAST
1514 %left  QUESTIONMARK
1515 %left  LOR
1516 %left  LAND
1517 %left  OR
1518 %left  XOR
1519 %left  AND
1520 %left  EQUALTO NOTEQUALTO
1521 %left  GREATERTHAN LESSTHAN GREATERTHANOREQUALTO LESSTHANOREQUALTO
1522 %left  LSHIFT RSHIFT
1523 %left  PLUS MINUS
1524 %left  STAR SLASH MODULUS
1525 %left  UMINUS NOT LNOT
1526 %left  DCOLON
1527
1528 %type <node>     program interface declaration swig_directive ;
1529
1530 /* SWIG directives */
1531 %type <node>     extend_directive apply_directive clear_directive constant_directive ;
1532 %type <node>     echo_directive except_directive fragment_directive include_directive inline_directive ;
1533 %type <node>     insert_directive module_directive name_directive native_directive ;
1534 %type <node>     pragma_directive rename_directive feature_directive varargs_directive typemap_directive ;
1535 %type <node>     types_directive template_directive warn_directive ;
1536
1537 /* C declarations */
1538 %type <node>     c_declaration c_decl c_decl_tail c_enum_decl c_enum_forward_decl c_constructor_decl ;
1539 %type <node>     enumlist edecl;
1540
1541 /* C++ declarations */
1542 %type <node>     cpp_declaration cpp_class_decl cpp_forward_class_decl cpp_template_decl;
1543 %type <node>     cpp_members cpp_member;
1544 %type <node>     cpp_constructor_decl cpp_destructor_decl cpp_protection_decl cpp_conversion_operator;
1545 %type <node>     cpp_swig_directive cpp_temp_possible cpp_nested cpp_opt_declarators ;
1546 %type <node>     cpp_using_decl cpp_namespace_decl cpp_catch_decl ;
1547 %type <node>     kwargs options;
1548
1549 /* Misc */
1550 %type <dtype>    initializer cpp_const ;
1551 %type <id>       storage_class;
1552 %type <pl>       parms  ptail rawparms varargs_parms;
1553 %type <pl>       templateparameters templateparameterstail;
1554 %type <p>        parm valparm rawvalparms valparms valptail ;
1555 %type <p>        typemap_parm tm_list tm_tail ;
1556 %type <p>        templateparameter ;
1557 %type <id>       templcpptype cpptype access_specifier;
1558 %type <node>     base_specifier
1559 %type <type>     type rawtype type_right ;
1560 %type <bases>    base_list inherit raw_inherit;
1561 %type <dtype>    definetype def_args etype;
1562 %type <dtype>    expr exprnum exprcompound valexpr;
1563 %type <id>       ename ;
1564 %type <id>       template_decl;
1565 %type <str>      type_qualifier ;
1566 %type <id>       type_qualifier_raw;
1567 %type <id>       idstring idstringopt;
1568 %type <id>       pragma_lang;
1569 %type <str>      pragma_arg;
1570 %type <loc>      includetype;
1571 %type <type>     pointer primitive_type;
1572 %type <decl>     declarator direct_declarator notso_direct_declarator parameter_declarator typemap_parameter_declarator nested_decl;
1573 %type <decl>     abstract_declarator direct_abstract_declarator ctor_end;
1574 %type <tmap>     typemap_type;
1575 %type <str>      idcolon idcolontail idcolonnt idcolontailnt idtemplate stringbrace stringbracesemi;
1576 %type <id>       string stringnum ;
1577 %type <tparms>   template_parms;
1578 %type <dtype>    cpp_end cpp_vend;
1579 %type <ivalue>   rename_namewarn;
1580 %type <ptype>    type_specifier primitive_type_list ;
1581 %type <node>     fname stringtype;
1582 %type <node>     featattr;
1583
1584 %%
1585
1586 /* ======================================================================
1587  *                          High-level Interface file
1588  *
1589  * An interface is just a sequence of declarations which may be SWIG directives
1590  * or normal C declarations.
1591  * ====================================================================== */
1592
1593 program        :  interface {
1594                    if (!classes) classes = NewHash();
1595                    Setattr($1,"classes",classes); 
1596                    Setattr($1,"name",ModuleName);
1597                    
1598                    if ((!module_node) && ModuleName) {
1599                      module_node = new_node("module");
1600                      Setattr(module_node,"name",ModuleName);
1601                    }
1602                    Setattr($1,"module",module_node);
1603                    check_extensions();
1604                    top = $1;
1605                }
1606                | PARSETYPE parm SEMI {
1607                  top = Copy(Getattr($2,"type"));
1608                  Delete($2);
1609                }
1610                | PARSETYPE error {
1611                  top = 0;
1612                }
1613                | PARSEPARM parm SEMI {
1614                  top = $2;
1615                }
1616                | PARSEPARM error {
1617                  top = 0;
1618                }
1619                | PARSEPARMS LPAREN parms RPAREN SEMI {
1620                  top = $3;
1621                }
1622                | PARSEPARMS error SEMI {
1623                  top = 0;
1624                }
1625                ;
1626
1627 interface      : interface declaration {  
1628                    /* add declaration to end of linked list (the declaration isn't always a single declaration, sometimes it is a linked list itself) */
1629                    appendChild($1,$2);
1630                    $$ = $1;
1631                }
1632                | empty {
1633                    $$ = new_node("top");
1634                }
1635                ;
1636
1637 declaration    : swig_directive { $$ = $1; }
1638                | c_declaration { $$ = $1; } 
1639                | cpp_declaration { $$ = $1; }
1640                | SEMI { $$ = 0; }
1641                | error {
1642                   $$ = 0;
1643                   Swig_error(cparse_file, cparse_line,"Syntax error in input(1).\n");
1644                   exit(1);
1645                }
1646 /* Out of class constructor/destructor declarations */
1647                | c_constructor_decl { 
1648                   if ($$) {
1649                       add_symbols($$);
1650                   }
1651                   $$ = $1; 
1652                }              
1653
1654 /* Out of class conversion operator.  For example:
1655      inline A::operator char *() const { ... }.
1656
1657    This is nearly impossible to parse normally.  We just let the
1658    first part generate a syntax error and then resynchronize on the
1659    COPERATOR token---discarding the rest of the definition. Ugh.
1660
1661  */
1662
1663                | error COPERATOR {
1664                   $$ = 0;
1665                   skip_decl();
1666                }
1667                ;
1668
1669 /* ======================================================================
1670  *                           SWIG DIRECTIVES 
1671  * ====================================================================== */
1672   
1673 swig_directive : extend_directive { $$ = $1; }
1674                | apply_directive { $$ = $1; }
1675                | clear_directive { $$ = $1; }
1676                | constant_directive { $$ = $1; }
1677                | echo_directive { $$ = $1; }
1678                | except_directive { $$ = $1; }
1679                | fragment_directive { $$ = $1; }
1680                | include_directive { $$ = $1; }
1681                | inline_directive { $$ = $1; }
1682                | insert_directive { $$ = $1; }
1683                | module_directive { $$ = $1; }
1684                | name_directive { $$ = $1; }
1685                | native_directive { $$ = $1; }
1686                | pragma_directive { $$ = $1; }
1687                | rename_directive { $$ = $1; }
1688                | feature_directive { $$ = $1; }
1689                | varargs_directive { $$ = $1; }
1690                | typemap_directive { $$ = $1; }
1691                | types_directive  { $$ = $1; }
1692                | template_directive { $$ = $1; }
1693                | warn_directive { $$ = $1; }
1694                ;
1695
1696 /* ------------------------------------------------------------
1697    %extend classname { ... } 
1698    ------------------------------------------------------------ */
1699
1700 extend_directive : EXTEND options idcolon LBRACE {
1701                Node *cls;
1702                String *clsname;
1703                cplus_mode = CPLUS_PUBLIC;
1704                if (!classes) classes = NewHash();
1705                if (!extendhash) extendhash = NewHash();
1706                clsname = make_class_name($3);
1707                cls = Getattr(classes,clsname);
1708                if (!cls) {
1709                  /* No previous definition. Create a new scope */
1710                  Node *am = Getattr(extendhash,clsname);
1711                  if (!am) {
1712                    Swig_symbol_newscope();
1713                    Swig_symbol_setscopename($3);
1714                    prev_symtab = 0;
1715                  } else {
1716                    prev_symtab = Swig_symbol_setscope(Getattr(am,"symtab"));
1717                  }
1718                  current_class = 0;
1719                } else {
1720                  /* Previous class definition.  Use its symbol table */
1721                  prev_symtab = Swig_symbol_setscope(Getattr(cls,"symtab"));
1722                  current_class = cls;
1723                  extendmode = 1;
1724                }
1725                Classprefix = NewString($3);
1726                Namespaceprefix= Swig_symbol_qualifiedscopename(0);
1727                Delete(clsname);
1728              } cpp_members RBRACE {
1729                String *clsname;
1730                extendmode = 0;
1731                $$ = new_node("extend");
1732                Setattr($$,"symtab",Swig_symbol_popscope());
1733                if (prev_symtab) {
1734                  Swig_symbol_setscope(prev_symtab);
1735                }
1736                Namespaceprefix = Swig_symbol_qualifiedscopename(0);
1737                clsname = make_class_name($3);
1738                Setattr($$,"name",clsname);
1739
1740                /* Mark members as extend */
1741
1742                tag_nodes($6,"feature:extend",(char*) "1");
1743                if (current_class) {
1744                  /* We add the extension to the previously defined class */
1745                  appendChild($$,$6);
1746                  appendChild(current_class,$$);
1747                } else {
1748                  /* We store the extensions in the extensions hash */
1749                  Node *am = Getattr(extendhash,clsname);
1750                  if (am) {
1751                    /* Append the members to the previous extend methods */
1752                    appendChild(am,$6);
1753                  } else {
1754                    appendChild($$,$6);
1755                    Setattr(extendhash,clsname,$$);
1756                  }
1757                }
1758                current_class = 0;
1759                Delete(Classprefix);
1760                Delete(clsname);
1761                Classprefix = 0;
1762                prev_symtab = 0;
1763                $$ = 0;
1764
1765              }
1766              ;
1767
1768 /* ------------------------------------------------------------
1769    %apply
1770    ------------------------------------------------------------ */
1771
1772 apply_directive : APPLY typemap_parm LBRACE tm_list RBRACE {
1773                     $$ = new_node("apply");
1774                     Setattr($$,"pattern",Getattr($2,"pattern"));
1775                     appendChild($$,$4);
1776                };
1777
1778 /* ------------------------------------------------------------
1779    %clear
1780    ------------------------------------------------------------ */
1781
1782 clear_directive : CLEAR tm_list SEMI {
1783                  $$ = new_node("clear");
1784                  appendChild($$,$2);
1785                }
1786                ;
1787
1788 /* ------------------------------------------------------------
1789    %constant name = value;
1790    %constant type name = value;
1791    ------------------------------------------------------------ */
1792
1793 constant_directive :  CONSTANT ID EQUAL definetype SEMI {
1794                    if (($4.type != T_ERROR) && ($4.type != T_SYMBOL)) {
1795                      SwigType *type = NewSwigType($4.type);
1796                      $$ = new_node("constant");
1797                      Setattr($$,"name",$2);
1798                      Setattr($$,"type",type);
1799                      Setattr($$,"value",$4.val);
1800                      if ($4.rawval) Setattr($$,"rawval", $4.rawval);
1801                      Setattr($$,"storage","%constant");
1802                      SetFlag($$,"feature:immutable");
1803                      add_symbols($$);
1804                      Delete(type);
1805                    } else {
1806                      if ($4.type == T_ERROR) {
1807                        Swig_warning(WARN_PARSE_UNSUPPORTED_VALUE,cparse_file,cparse_line,"Unsupported constant value (ignored)\n");
1808                      }
1809                      $$ = 0;
1810                    }
1811
1812                }
1813
1814                | CONSTANT type declarator def_args SEMI {
1815                  if (($4.type != T_ERROR) && ($4.type != T_SYMBOL)) {
1816                    SwigType_push($2,$3.type);
1817                    /* Sneaky callback function trick */
1818                    if (SwigType_isfunction($2)) {
1819                      SwigType_add_pointer($2);
1820                    }
1821                    $$ = new_node("constant");
1822                    Setattr($$,"name",$3.id);
1823                    Setattr($$,"type",$2);
1824                    Setattr($$,"value",$4.val);
1825                    if ($4.rawval) Setattr($$,"rawval", $4.rawval);
1826                    Setattr($$,"storage","%constant");
1827                    SetFlag($$,"feature:immutable");
1828                    add_symbols($$);
1829                  } else {
1830                      if ($4.type == T_ERROR) {
1831                        Swig_warning(WARN_PARSE_UNSUPPORTED_VALUE,cparse_file,cparse_line,"Unsupported constant value\n");
1832                      }
1833                    $$ = 0;
1834                  }
1835                }
1836                | CONSTANT error SEMI {
1837                  Swig_warning(WARN_PARSE_BAD_VALUE,cparse_file,cparse_line,"Bad constant value (ignored).\n");
1838                  $$ = 0;
1839                }
1840                ;
1841
1842 /* ------------------------------------------------------------
1843    %echo "text"
1844    %echo %{ ... %}
1845    ------------------------------------------------------------ */
1846
1847 echo_directive : ECHO HBLOCK {
1848                  char temp[64];
1849                  Replace($2,"$file",cparse_file, DOH_REPLACE_ANY);
1850                  sprintf(temp,"%d", cparse_line);
1851                  Replace($2,"$line",temp,DOH_REPLACE_ANY);
1852                  Printf(stderr,"%s\n", $2);
1853                  Delete($2);
1854                  $$ = 0;
1855                }
1856                | ECHO string {
1857                  char temp[64];
1858                  String *s = NewString($2);
1859                  Replace(s,"$file",cparse_file, DOH_REPLACE_ANY);
1860                  sprintf(temp,"%d", cparse_line);
1861                  Replace(s,"$line",temp,DOH_REPLACE_ANY);
1862                  Printf(stderr,"%s\n", s);
1863                  Delete(s);
1864                  $$ = 0;
1865                }
1866                ;
1867
1868 /* ------------------------------------------------------------
1869    %except(lang) { ... }
1870    %except { ... }
1871    %except(lang);   
1872    %except;
1873    ------------------------------------------------------------ */
1874
1875 except_directive : EXCEPT LPAREN ID RPAREN LBRACE {
1876                     skip_balanced('{','}');
1877                     $$ = 0;
1878                     Swig_warning(WARN_DEPRECATED_EXCEPT,cparse_file, cparse_line, "%%except is deprecated.  Use %%exception instead.\n");
1879                }
1880
1881                | EXCEPT LBRACE {
1882                     skip_balanced('{','}');
1883                     $$ = 0;
1884                     Swig_warning(WARN_DEPRECATED_EXCEPT,cparse_file, cparse_line, "%%except is deprecated.  Use %%exception instead.\n");
1885                }
1886
1887                | EXCEPT LPAREN ID RPAREN SEMI {
1888                  $$ = 0;
1889                  Swig_warning(WARN_DEPRECATED_EXCEPT,cparse_file, cparse_line, "%%except is deprecated.  Use %%exception instead.\n");
1890                }
1891
1892                | EXCEPT SEMI {
1893                  $$ = 0;
1894                  Swig_warning(WARN_DEPRECATED_EXCEPT,cparse_file, cparse_line, "%%except is deprecated.  Use %%exception instead.\n");
1895                }
1896                ;
1897
1898 /* fragment keyword arguments */
1899 stringtype    : string LBRACE parm RBRACE {              
1900                  $$ = NewHash();
1901                  Setattr($$,"value",$1);
1902                  Setattr($$,"type",Getattr($3,"type"));
1903                }
1904                ;
1905
1906 fname         : string {
1907                  $$ = NewHash();
1908                  Setattr($$,"value",$1);
1909               }
1910               | stringtype {
1911                 $$ = $1;
1912               }
1913               ;
1914
1915 /* ------------------------------------------------------------
1916    %fragment(name, section) %{ ... %}
1917    %fragment("name" {type}, "section") %{ ... %}
1918    %fragment("name", "section", fragment="fragment1", fragment="fragment2") %{ ... %}
1919    Also as above but using { ... }
1920    %fragment("name");
1921    ------------------------------------------------------------ */
1922
1923 fragment_directive: FRAGMENT LPAREN fname COMMA kwargs RPAREN HBLOCK {
1924                    Hash *p = $5;
1925                    $$ = new_node("fragment");
1926                    Setattr($$,"value",Getattr($3,"value"));
1927                    Setattr($$,"type",Getattr($3,"type"));
1928                    Setattr($$,"section",Getattr(p,"name"));
1929                    Setattr($$,"kwargs",nextSibling(p));
1930                    Setattr($$,"code",$7);
1931                  }
1932                  | FRAGMENT LPAREN fname COMMA kwargs RPAREN LBRACE {
1933                    Hash *p = $5;
1934                    String *code;
1935                    skip_balanced('{','}');
1936                    $$ = new_node("fragment");
1937                    Setattr($$,"value",Getattr($3,"value"));
1938                    Setattr($$,"type",Getattr($3,"type"));
1939                    Setattr($$,"section",Getattr(p,"name"));
1940                    Setattr($$,"kwargs",nextSibling(p));
1941                    Delitem(scanner_ccode,0);
1942                    Delitem(scanner_ccode,DOH_END);
1943                    code = Copy(scanner_ccode);
1944                    Setattr($$,"code",code);
1945                    Delete(code);
1946                  }
1947                  | FRAGMENT LPAREN fname RPAREN SEMI {
1948                    $$ = new_node("fragment");
1949                    Setattr($$,"value",Getattr($3,"value"));
1950                    Setattr($$,"type",Getattr($3,"type"));
1951                    Setattr($$,"emitonly","1");
1952                  }
1953                  ;
1954
1955 /* ------------------------------------------------------------
1956    %includefile "filename" [option1="xyz", ...] [ declarations ] 
1957    %importfile  "filename" [option1="xyz", ...] [ declarations ]
1958    ------------------------------------------------------------ */
1959
1960 include_directive: includetype options string LBRACKET {
1961                      $1.filename = Copy(cparse_file);
1962                      $1.line = cparse_line;
1963                      scanner_set_location(NewString($3),1);
1964                      if ($2) { 
1965                        String *maininput = Getattr($2, "maininput");
1966                        if (maininput)
1967                          scanner_set_main_input_file(NewString(maininput));
1968                      }
1969                } interface RBRACKET {
1970                      String *mname = 0;
1971                      $$ = $6;
1972                      scanner_set_location($1.filename,$1.line);
1973                      if (strcmp($1.type,"include") == 0) set_nodeType($$,"include");
1974                      if (strcmp($1.type,"import") == 0) {
1975                        mname = $2 ? Getattr($2,"module") : 0;
1976                        set_nodeType($$,"import");
1977                        if (import_mode) --import_mode;
1978                      }
1979                      
1980                      Setattr($$,"name",$3);
1981                      /* Search for the module (if any) */
1982                      {
1983                          Node *n = firstChild($$);
1984                          while (n) {
1985                              if (Strcmp(nodeType(n),"module") == 0) {
1986                                  if (mname) {
1987                                    Setattr(n,"name", mname);
1988                                    mname = 0;
1989                                  }
1990                                  Setattr($$,"module",Getattr(n,"name"));
1991                                  break;
1992                              }
1993                              n = nextSibling(n);
1994                          }
1995                          if (mname) {
1996                            /* There is no module node in the import
1997                               node, ie, you imported a .h file
1998                               directly.  We are forced then to create
1999                               a new import node with a module node.
2000                            */                         
2001                            Node *nint = new_node("import");
2002                            Node *mnode = new_node("module");
2003                            Setattr(mnode,"name", mname);
2004                            appendChild(nint,mnode);
2005                            Delete(mnode);
2006                            appendChild(nint,firstChild($$));
2007                            $$ = nint;
2008                            Setattr($$,"module",mname);
2009                          }
2010                      }
2011                      Setattr($$,"options",$2);
2012                }
2013                ;
2014
2015 includetype    : INCLUDE { $$.type = (char *) "include"; }
2016                | IMPORT  { $$.type = (char *) "import"; ++import_mode;}
2017                ;
2018
2019 /* ------------------------------------------------------------
2020    %inline %{ ... %}
2021    ------------------------------------------------------------ */
2022
2023 inline_directive : INLINE HBLOCK {
2024                  String *cpps;
2025                  if (Namespaceprefix) {
2026                    Swig_error(cparse_file, cparse_start_line, "%%inline directive inside a namespace is disallowed.\n");
2027
2028                    $$ = 0;
2029                  } else {
2030                    $$ = new_node("insert");
2031                    Setattr($$,"code",$2);
2032                    /* Need to run through the preprocessor */
2033                    Setline($2,cparse_start_line);
2034                    Setfile($2,cparse_file);
2035                    Seek($2,0,SEEK_SET);
2036                    cpps = Preprocessor_parse($2);
2037                    start_inline(Char(cpps), cparse_start_line);
2038                    Delete($2);
2039                    Delete(cpps);
2040                  }
2041                  
2042                }
2043                | INLINE LBRACE {
2044                  String *cpps;
2045                  int start_line = cparse_line;
2046                  skip_balanced('{','}');
2047                  if (Namespaceprefix) {
2048                    Swig_error(cparse_file, cparse_start_line, "%%inline directive inside a namespace is disallowed.\n");
2049                    
2050                    $$ = 0;
2051                  } else {
2052                    String *code;
2053                    $$ = new_node("insert");
2054                    Delitem(scanner_ccode,0);
2055                    Delitem(scanner_ccode,DOH_END);
2056                    code = Copy(scanner_ccode);
2057                    Setattr($$,"code", code);
2058                    Delete(code);                   
2059                    cpps=Copy(scanner_ccode);
2060                    start_inline(Char(cpps), start_line);
2061                    Delete(cpps);
2062                  }
2063                }
2064                 ;
2065
2066 /* ------------------------------------------------------------
2067    %{ ... %}
2068    %insert(section) "filename"
2069    %insert("section") "filename"
2070    %insert(section) %{ ... %}
2071    %insert("section") %{ ... %}
2072    ------------------------------------------------------------ */
2073
2074 insert_directive : HBLOCK {
2075                  $$ = new_node("insert");
2076                  Setattr($$,"code",$1);
2077                }
2078                | INSERT LPAREN idstring RPAREN string {
2079                  String *code = NewStringEmpty();
2080                  $$ = new_node("insert");
2081                  Setattr($$,"section",$3);
2082                  Setattr($$,"code",code);
2083                  if (Swig_insert_file($5,code) < 0) {
2084                    Swig_error(cparse_file, cparse_line, "Couldn't find '%s'.\n", $5);
2085                    $$ = 0;
2086                  } 
2087                }
2088                | INSERT LPAREN idstring RPAREN HBLOCK {
2089                  $$ = new_node("insert");
2090                  Setattr($$,"section",$3);
2091                  Setattr($$,"code",$5);
2092                }
2093                | INSERT LPAREN idstring RPAREN LBRACE {
2094                  String *code;
2095                  skip_balanced('{','}');
2096                  $$ = new_node("insert");
2097                  Setattr($$,"section",$3);
2098                  Delitem(scanner_ccode,0);
2099                  Delitem(scanner_ccode,DOH_END);
2100                  code = Copy(scanner_ccode);
2101                  Setattr($$,"code", code);
2102                  Delete(code);
2103                }
2104                ;
2105       
2106 /* ------------------------------------------------------------
2107     %module modname
2108     %module "modname"
2109    ------------------------------------------------------------ */
2110
2111 module_directive: MODULE options idstring {
2112                  $$ = new_node("module");
2113                  if ($2) {
2114                    Setattr($$,"options",$2);
2115                    if (Getattr($2,"directors")) {
2116                      Wrapper_director_mode_set(1);
2117                    } 
2118                    if (Getattr($2,"dirprot")) {
2119                      Wrapper_director_protected_mode_set(1);
2120                    } 
2121                    if (Getattr($2,"allprotected")) {
2122                      Wrapper_all_protected_mode_set(1);
2123                    } 
2124                    if (Getattr($2,"templatereduce")) {
2125                      template_reduce = 1;
2126                    }
2127                    if (Getattr($2,"notemplatereduce")) {
2128                      template_reduce = 0;
2129                    }
2130                  }
2131                  if (!ModuleName) ModuleName = NewString($3);
2132                  if (!import_mode) {
2133                    /* first module included, we apply global
2134                       ModuleName, which can be modify by -module */
2135                    String *mname = Copy(ModuleName);
2136                    Setattr($$,"name",mname);
2137                    Delete(mname);
2138                  } else { 
2139                    /* import mode, we just pass the idstring */
2140                    Setattr($$,"name",$3);   
2141                  }               
2142                  if (!module_node) module_node = $$;
2143                }
2144                ;
2145
2146 /* ------------------------------------------------------------
2147    %name(newname)    declaration
2148    %name("newname")  declaration
2149    ------------------------------------------------------------ */
2150
2151 name_directive : NAME LPAREN idstring RPAREN {
2152                  Swig_warning(WARN_DEPRECATED_NAME,cparse_file,cparse_line, "%%name is deprecated.  Use %%rename instead.\n");
2153                  Delete(yyrename);
2154                  yyrename = NewString($3);
2155                  $$ = 0;
2156                }
2157                | NAME LPAREN RPAREN {
2158                  Swig_warning(WARN_DEPRECATED_NAME,cparse_file,cparse_line, "%%name is deprecated.  Use %%rename instead.\n");
2159                  $$ = 0;
2160                  Swig_error(cparse_file,cparse_line,"Missing argument to %%name directive.\n");
2161                }
2162                ;
2163
2164
2165 /* ------------------------------------------------------------
2166    %native(scriptname) name;
2167    %native(scriptname) type name (parms);
2168    ------------------------------------------------------------ */
2169
2170 native_directive : NATIVE LPAREN ID RPAREN storage_class ID SEMI {
2171                  $$ = new_node("native");
2172                  Setattr($$,"name",$3);
2173                  Setattr($$,"wrap:name",$6);
2174                  add_symbols($$);
2175                }
2176                | NATIVE LPAREN ID RPAREN storage_class type declarator SEMI {
2177                  if (!SwigType_isfunction($7.type)) {
2178                    Swig_error(cparse_file,cparse_line,"%%native declaration '%s' is not a function.\n", $7.id);
2179                    $$ = 0;
2180                  } else {
2181                      Delete(SwigType_pop_function($7.type));
2182                      /* Need check for function here */
2183                      SwigType_push($6,$7.type);
2184                      $$ = new_node("native");
2185                      Setattr($$,"name",$3);
2186                      Setattr($$,"wrap:name",$7.id);
2187                      Setattr($$,"type",$6);
2188                      Setattr($$,"parms",$7.parms);
2189                      Setattr($$,"decl",$7.type);
2190                  }
2191                  add_symbols($$);
2192                }
2193                ;
2194
2195 /* ------------------------------------------------------------
2196    %pragma(lang) name=value
2197    %pragma(lang) name
2198    %pragma name = value
2199    %pragma name
2200    ------------------------------------------------------------ */
2201
2202 pragma_directive : PRAGMA pragma_lang ID EQUAL pragma_arg {
2203                  $$ = new_node("pragma");
2204                  Setattr($$,"lang",$2);
2205                  Setattr($$,"name",$3);
2206                  Setattr($$,"value",$5);
2207                }
2208               | PRAGMA pragma_lang ID {
2209                 $$ = new_node("pragma");
2210                 Setattr($$,"lang",$2);
2211                 Setattr($$,"name",$3);
2212               }
2213               ;
2214
2215 pragma_arg    : string { $$ = NewString($1); }
2216               | HBLOCK { $$ = $1; }
2217               ;
2218
2219 pragma_lang   : LPAREN ID RPAREN { $$ = $2; }
2220               | empty { $$ = (char *) "swig"; }
2221               ;
2222
2223 /* ------------------------------------------------------------
2224    %rename identifier newname;
2225    %rename identifier "newname";
2226    ------------------------------------------------------------ */
2227
2228 rename_directive : rename_namewarn declarator idstring SEMI {
2229                 SwigType *t = $2.type;
2230                 Hash *kws = NewHash();
2231                 String *fixname;
2232                 fixname = feature_identifier_fix($2.id);
2233                 Setattr(kws,"name",$3);
2234                 if (!Len(t)) t = 0;
2235                 /* Special declarator check */
2236                 if (t) {
2237                   if (SwigType_isfunction(t)) {
2238                     SwigType *decl = SwigType_pop_function(t);
2239                     if (SwigType_ispointer(t)) {
2240                       String *nname = NewStringf("*%s",fixname);
2241                       if ($1) {
2242                         Swig_name_rename_add(Namespaceprefix, nname,decl,kws,$2.parms);
2243                       } else {
2244                         Swig_name_namewarn_add(Namespaceprefix,nname,decl,kws);
2245                       }
2246                       Delete(nname);
2247                     } else {
2248                       if ($1) {
2249                         Swig_name_rename_add(Namespaceprefix,(fixname),decl,kws,$2.parms);
2250                       } else {
2251                         Swig_name_namewarn_add(Namespaceprefix,(fixname),decl,kws);
2252                       }
2253                     }
2254                     Delete(decl);
2255                   } else if (SwigType_ispointer(t)) {
2256                     String *nname = NewStringf("*%s",fixname);
2257                     if ($1) {
2258                       Swig_name_rename_add(Namespaceprefix,(nname),0,kws,$2.parms);
2259                     } else {
2260                       Swig_name_namewarn_add(Namespaceprefix,(nname),0,kws);
2261                     }
2262                     Delete(nname);
2263                   }
2264                 } else {
2265                   if ($1) {
2266                     Swig_name_rename_add(Namespaceprefix,(fixname),0,kws,$2.parms);
2267                   } else {
2268                     Swig_name_namewarn_add(Namespaceprefix,(fixname),0,kws);
2269                   }
2270                 }
2271                 $$ = 0;
2272                 scanner_clear_rename();
2273               }
2274               | rename_namewarn LPAREN kwargs RPAREN declarator cpp_const SEMI {
2275                 String *fixname;
2276                 Hash *kws = $3;
2277                 SwigType *t = $5.type;
2278                 fixname = feature_identifier_fix($5.id);
2279                 if (!Len(t)) t = 0;
2280                 /* Special declarator check */
2281                 if (t) {
2282                   if ($6.qualifier) SwigType_push(t,$6.qualifier);
2283                   if (SwigType_isfunction(t)) {
2284                     SwigType *decl = SwigType_pop_function(t);
2285                     if (SwigType_ispointer(t)) {
2286                       String *nname = NewStringf("*%s",fixname);
2287                       if ($1) {
2288                         Swig_name_rename_add(Namespaceprefix, nname,decl,kws,$5.parms);
2289                       } else {
2290                         Swig_name_namewarn_add(Namespaceprefix,nname,decl,kws);
2291                       }
2292                       Delete(nname);
2293                     } else {
2294                       if ($1) {
2295                         Swig_name_rename_add(Namespaceprefix,(fixname),decl,kws,$5.parms);
2296                       } else {
2297                         Swig_name_namewarn_add(Namespaceprefix,(fixname),decl,kws);
2298                       }
2299                     }
2300                     Delete(decl);
2301                   } else if (SwigType_ispointer(t)) {
2302                     String *nname = NewStringf("*%s",fixname);
2303                     if ($1) {
2304                       Swig_name_rename_add(Namespaceprefix,(nname),0,kws,$5.parms);
2305                     } else {
2306                       Swig_name_namewarn_add(Namespaceprefix,(nname),0,kws);
2307                     }
2308                     Delete(nname);
2309                   }
2310                 } else {
2311                   if ($1) {
2312                     Swig_name_rename_add(Namespaceprefix,(fixname),0,kws,$5.parms);
2313                   } else {
2314                     Swig_name_namewarn_add(Namespaceprefix,(fixname),0,kws);
2315                   }
2316                 }
2317                 $$ = 0;
2318                 scanner_clear_rename();
2319               }
2320               | rename_namewarn LPAREN kwargs RPAREN string SEMI {
2321                 if ($1) {
2322                   Swig_name_rename_add(Namespaceprefix,$5,0,$3,0);
2323                 } else {
2324                   Swig_name_namewarn_add(Namespaceprefix,$5,0,$3);
2325                 }
2326                 $$ = 0;
2327                 scanner_clear_rename();
2328               }
2329               ;
2330
2331 rename_namewarn : RENAME {
2332                     $$ = 1;
2333                 } 
2334                 | NAMEWARN {
2335                     $$ = 0;
2336                 };
2337
2338
2339 /* ------------------------------------------------------------
2340    Feature targeting a symbol name (non-global feature):
2341
2342      %feature(featurename) name "val";
2343      %feature(featurename, val) name;
2344
2345    where "val" could instead be the other bracket types, that is,
2346    { val } or %{ val %} or indeed omitted whereupon it defaults to "1".
2347    Or, the global feature which does not target a symbol name:
2348
2349      %feature(featurename) "val";
2350      %feature(featurename, val);
2351
2352    An empty val (empty string) clears the feature.
2353    Any number of feature attributes can optionally be added, for example
2354    a non-global feature with 2 attributes:
2355
2356      %feature(featurename, attrib1="attribval1", attrib2="attribval2") name "val";
2357      %feature(featurename, val, attrib1="attribval1", attrib2="attribval2") name;
2358    ------------------------------------------------------------ */
2359
2360                   /* Non-global feature */
2361 feature_directive : FEATURE LPAREN idstring RPAREN declarator cpp_const stringbracesemi {
2362                     String *val = $7 ? NewString($7) : NewString("1");
2363                     new_feature($3, val, 0, $5.id, $5.type, $5.parms, $6.qualifier);
2364                     $$ = 0;
2365                     scanner_clear_rename();
2366                   }
2367                   | FEATURE LPAREN idstring COMMA stringnum RPAREN declarator cpp_const SEMI {
2368                     String *val = Len($5) ? NewString($5) : 0;
2369                     new_feature($3, val, 0, $7.id, $7.type, $7.parms, $8.qualifier);
2370                     $$ = 0;
2371                     scanner_clear_rename();
2372                   }
2373                   | FEATURE LPAREN idstring featattr RPAREN declarator cpp_const stringbracesemi {
2374                     String *val = $8 ? NewString($8) : NewString("1");
2375                     new_feature($3, val, $4, $6.id, $6.type, $6.parms, $7.qualifier);
2376                     $$ = 0;
2377                     scanner_clear_rename();
2378                   }
2379                   | FEATURE LPAREN idstring COMMA stringnum featattr RPAREN declarator cpp_const SEMI {
2380                     String *val = Len($5) ? NewString($5) : 0;
2381                     new_feature($3, val, $6, $8.id, $8.type, $8.parms, $9.qualifier);
2382                     $$ = 0;
2383                     scanner_clear_rename();
2384                   }
2385
2386                   /* Global feature */
2387                   | FEATURE LPAREN idstring RPAREN stringbracesemi {
2388                     String *val = $5 ? NewString($5) : NewString("1");
2389                     new_feature($3, val, 0, 0, 0, 0, 0);
2390                     $$ = 0;
2391                     scanner_clear_rename();
2392                   }
2393                   | FEATURE LPAREN idstring COMMA stringnum RPAREN SEMI {
2394                     String *val = Len($5) ? NewString($5) : 0;
2395                     new_feature($3, val, 0, 0, 0, 0, 0);
2396                     $$ = 0;
2397                     scanner_clear_rename();
2398                   }
2399                   | FEATURE LPAREN idstring featattr RPAREN stringbracesemi {
2400                     String *val = $6 ? NewString($6) : NewString("1");
2401                     new_feature($3, val, $4, 0, 0, 0, 0);
2402                     $$ = 0;
2403                     scanner_clear_rename();
2404                   }
2405                   | FEATURE LPAREN idstring COMMA stringnum featattr RPAREN SEMI {
2406                     String *val = Len($5) ? NewString($5) : 0;
2407                     new_feature($3, val, $6, 0, 0, 0, 0);
2408                     $$ = 0;
2409                     scanner_clear_rename();
2410                   }
2411                   ;
2412
2413 stringbracesemi : stringbrace { $$ = $1; }
2414                 | SEMI { $$ = 0; }
2415                 | PARMS LPAREN parms RPAREN SEMI { $$ = $3; } 
2416                 ;
2417
2418 featattr        : COMMA idstring EQUAL stringnum {
2419                   $$ = NewHash();
2420                   Setattr($$,"name",$2);
2421                   Setattr($$,"value",$4);
2422                 }
2423                 | COMMA idstring EQUAL stringnum featattr {
2424                   $$ = NewHash();
2425                   Setattr($$,"name",$2);
2426                   Setattr($$,"value",$4);
2427                   set_nextSibling($$,$5);
2428                 }
2429                 ;
2430
2431 /* %varargs() directive. */
2432
2433 varargs_directive : VARARGS LPAREN varargs_parms RPAREN declarator cpp_const SEMI {
2434                  Parm *val;
2435                  String *name;
2436                  SwigType *t;
2437                  if (Namespaceprefix) name = NewStringf("%s::%s", Namespaceprefix, $5.id);
2438                  else name = NewString($5.id);
2439                  val = $3;
2440                  if ($5.parms) {
2441                    Setmeta(val,"parms",$5.parms);
2442                  }
2443                  t = $5.type;
2444                  if (!Len(t)) t = 0;
2445                  if (t) {
2446                    if ($6.qualifier) SwigType_push(t,$6.qualifier);
2447                    if (SwigType_isfunction(t)) {
2448                      SwigType *decl = SwigType_pop_function(t);
2449                      if (SwigType_ispointer(t)) {
2450                        String *nname = NewStringf("*%s",name);
2451                        Swig_feature_set(Swig_cparse_features(), nname, decl, "feature:varargs", val, 0);
2452                        Delete(nname);
2453                      } else {
2454                        Swig_feature_set(Swig_cparse_features(), name, decl, "feature:varargs", val, 0);
2455                      }
2456                      Delete(decl);
2457                    } else if (SwigType_ispointer(t)) {
2458                      String *nname = NewStringf("*%s",name);
2459                      Swig_feature_set(Swig_cparse_features(),nname,0,"feature:varargs",val, 0);
2460                      Delete(nname);
2461                    }
2462                  } else {
2463                    Swig_feature_set(Swig_cparse_features(),name,0,"feature:varargs",val, 0);
2464                  }
2465                  Delete(name);
2466                  $$ = 0;
2467               };
2468
2469 varargs_parms   : parms { $$ = $1; }
2470                 | NUM_INT COMMA parm { 
2471                   int i;
2472                   int n;
2473                   Parm *p;
2474                   n = atoi(Char($1.val));
2475                   if (n <= 0) {
2476                     Swig_error(cparse_file, cparse_line,"Argument count in %%varargs must be positive.\n");
2477                     $$ = 0;
2478                   } else {
2479                     $$ = Copy($3);
2480                     Setattr($$,"name","VARARGS_SENTINEL");
2481                     for (i = 0; i < n; i++) {
2482                       p = Copy($3);
2483                       set_nextSibling(p,$$);
2484                       Delete($$);
2485                       $$ = p;
2486                     }
2487                   }
2488                 }
2489                ;
2490
2491
2492 /* ------------------------------------------------------------
2493    %typemap(method) type { ... }
2494    %typemap(method) type "..."
2495    %typemap(method) type;    - typemap deletion
2496    %typemap(method) type1,type2,... = type;    - typemap copy
2497    %typemap type1,type2,... = type;            - typemap copy
2498    ------------------------------------------------------------ */
2499
2500 typemap_directive :  TYPEMAP LPAREN typemap_type RPAREN tm_list stringbrace {
2501                    $$ = 0;
2502                    if ($3.method) {
2503                      String *code = 0;
2504                      $$ = new_node("typemap");
2505                      Setattr($$,"method",$3.method);
2506                      if ($3.kwargs) {
2507                        ParmList *kw = $3.kwargs;
2508                        code = remove_block(kw, $6);
2509                        Setattr($$,"kwargs", $3.kwargs);
2510                      }
2511                      code = code ? code : NewString($6);
2512                      Setattr($$,"code", code);
2513                      Delete(code);
2514                      appendChild($$,$5);
2515                    }
2516                }
2517                | TYPEMAP LPAREN typemap_type RPAREN tm_list SEMI {
2518                  $$ = 0;
2519                  if ($3.method) {
2520                    $$ = new_node("typemap");
2521                    Setattr($$,"method",$3.method);
2522                    appendChild($$,$5);
2523                  }
2524                }
2525                | TYPEMAP LPAREN typemap_type RPAREN tm_list EQUAL typemap_parm SEMI {
2526                    $$ = 0;
2527                    if ($3.method) {
2528                      $$ = new_node("typemapcopy");
2529                      Setattr($$,"method",$3.method);
2530                      Setattr($$,"pattern", Getattr($7,"pattern"));
2531                      appendChild($$,$5);
2532                    }
2533                }
2534                ;
2535
2536 /* typemap method type (lang,method) or (method) */
2537
2538 typemap_type   : kwargs {
2539                  Hash *p;
2540                  String *name;
2541                  p = nextSibling($1);
2542                  if (p && (!Getattr(p,"value"))) {
2543                    /* this is the deprecated two argument typemap form */
2544                    Swig_warning(WARN_DEPRECATED_TYPEMAP_LANG,cparse_file, cparse_line,
2545                                 "Specifying the language name in %%typemap is deprecated - use #ifdef SWIG<LANG> instead.\n");
2546                    /* two argument typemap form */
2547                    name = Getattr($1,"name");
2548                    if (!name || (Strcmp(name,typemap_lang))) {
2549                      $$.method = 0;
2550                      $$.kwargs = 0;
2551                    } else {
2552                      $$.method = Getattr(p,"name");
2553                      $$.kwargs = nextSibling(p);
2554                    }
2555                  } else {
2556                    /* one-argument typemap-form */
2557                    $$.method = Getattr($1,"name");
2558                    $$.kwargs = p;
2559                  }
2560                 }
2561                ;
2562
2563 tm_list        : typemap_parm tm_tail {
2564                  $$ = $1;
2565                  set_nextSibling($$,$2);
2566                 }
2567                ;
2568
2569 tm_tail        : COMMA typemap_parm tm_tail {
2570                  $$ = $2;
2571                  set_nextSibling($$,$3);
2572                 }
2573                | empty { $$ = 0;}
2574                ;
2575
2576 typemap_parm   : type typemap_parameter_declarator {
2577                   Parm *parm;
2578                   SwigType_push($1,$2.type);
2579                   $$ = new_node("typemapitem");
2580                   parm = NewParm($1,$2.id);
2581                   Setattr($$,"pattern",parm);
2582                   Setattr($$,"parms", $2.parms);
2583                   Delete(parm);
2584                   /*              $$ = NewParm($1,$2.id);
2585                                   Setattr($$,"parms",$2.parms); */
2586                 }
2587                | LPAREN parms RPAREN {
2588                   $$ = new_node("typemapitem");
2589                   Setattr($$,"pattern",$2);
2590                   /*              Setattr($$,"multitype",$2); */
2591                }
2592                | LPAREN parms RPAREN LPAREN parms RPAREN {
2593                  $$ = new_node("typemapitem");
2594                  Setattr($$,"pattern", $2);
2595                  /*                 Setattr($$,"multitype",$2); */
2596                  Setattr($$,"parms",$5);
2597                }
2598                ;
2599
2600 /* ------------------------------------------------------------
2601    %types(parmlist); 
2602    %types(parmlist) %{ ... %}
2603    ------------------------------------------------------------ */
2604
2605 types_directive : TYPES LPAREN parms RPAREN stringbracesemi {
2606                    $$ = new_node("types");
2607                    Setattr($$,"parms",$3);
2608                    if ($5)
2609                      Setattr($$,"convcode",NewString($5));
2610                }
2611                ;
2612
2613 /* ------------------------------------------------------------
2614    %template(name) tname<args>;
2615    ------------------------------------------------------------ */
2616
2617 template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN valparms GREATERTHAN SEMI {
2618                   Parm *p, *tp;
2619                   Node *n;
2620                   Node *tnode = 0;
2621                   Symtab *tscope = 0;
2622                   int     specialized = 0;
2623
2624                   $$ = 0;
2625
2626                   tscope = Swig_symbol_current();          /* Get the current scope */
2627
2628                   /* If the class name is qualified, we need to create or lookup namespace entries */
2629                   if (!inclass) {
2630                     $5 = resolve_node_scope($5);
2631                   }
2632
2633                   /*
2634                     We use the new namespace entry 'nscope' only to
2635                     emit the template node. The template parameters are
2636                     resolved in the current 'tscope'.
2637
2638                     This is closer to the C++ (typedef) behavior.
2639                   */
2640                   n = Swig_cparse_template_locate($5,$7,tscope);
2641
2642                   /* Patch the argument types to respect namespaces */
2643                   p = $7;
2644                   while (p) {
2645                     SwigType *value = Getattr(p,"value");
2646                     if (!value) {
2647                       SwigType *ty = Getattr(p,"type");
2648                       if (ty) {
2649                         SwigType *rty = 0;
2650                         int reduce = template_reduce;
2651                         if (reduce || !SwigType_ispointer(ty)) {
2652                           rty = Swig_symbol_typedef_reduce(ty,tscope);
2653                           if (!reduce) reduce = SwigType_ispointer(rty);
2654                         }
2655                         ty = reduce ? Swig_symbol_type_qualify(rty,tscope) : Swig_symbol_type_qualify(ty,tscope);
2656                         Setattr(p,"type",ty);
2657                         Delete(ty);
2658                         Delete(rty);
2659                       }
2660                     } else {
2661                       value = Swig_symbol_type_qualify(value,tscope);
2662                       Setattr(p,"value",value);
2663                       Delete(value);
2664                     }
2665
2666                     p = nextSibling(p);
2667                   }
2668
2669                   /* Look for the template */
2670                   {
2671                     Node *nn = n;
2672                     Node *linklistend = 0;
2673                     while (nn) {
2674                       Node *templnode = 0;
2675                       if (Strcmp(nodeType(nn),"template") == 0) {
2676                         int nnisclass = (Strcmp(Getattr(nn,"templatetype"),"class") == 0); /* if not a templated class it is a templated function */
2677                         Parm *tparms = Getattr(nn,"templateparms");
2678                         if (!tparms) {
2679                           specialized = 1;
2680                         }
2681                         if (nnisclass && !specialized && ((ParmList_len($7) > ParmList_len(tparms)))) {
2682                           Swig_error(cparse_file, cparse_line, "Too many template parameters. Maximum of %d.\n", ParmList_len(tparms));
2683                         } else if (nnisclass && !specialized && ((ParmList_len($7) < ParmList_numrequired(tparms)))) {
2684                           Swig_error(cparse_file, cparse_line, "Not enough template parameters specified. %d required.\n", ParmList_numrequired(tparms));
2685                         } else if (!nnisclass && ((ParmList_len($7) != ParmList_len(tparms)))) {
2686                           /* must be an overloaded templated method - ignore it as it is overloaded with a different number of template parameters */
2687                           nn = Getattr(nn,"sym:nextSibling"); /* repeat for overloaded templated functions */
2688                           continue;
2689                         } else {
2690                           String *tname = Copy($5);
2691                           int def_supplied = 0;
2692                           /* Expand the template */
2693                           Node *templ = Swig_symbol_clookup($5,0);
2694                           Parm *targs = templ ? Getattr(templ,"templateparms") : 0;
2695
2696                           ParmList *temparms;
2697                           if (specialized) temparms = CopyParmList($7);
2698                           else temparms = CopyParmList(tparms);
2699
2700                           /* Create typedef's and arguments */
2701                           p = $7;
2702                           tp = temparms;
2703                           if (!p && ParmList_len(p) != ParmList_len(temparms)) {
2704                             /* we have no template parameters supplied in %template for a template that has default args*/
2705                             p = tp;
2706                             def_supplied = 1;
2707                           }
2708
2709                           while (p) {
2710                             String *value = Getattr(p,"value");
2711                             if (def_supplied) {
2712                               Setattr(p,"default","1");
2713                             }
2714                             if (value) {
2715                               Setattr(tp,"value",value);
2716                             } else {
2717                               SwigType *ty = Getattr(p,"type");
2718                               if (ty) {
2719                                 Setattr(tp,"type",ty);
2720                               }
2721                               Delattr(tp,"value");
2722                             }
2723                             /* fix default arg values */
2724                             if (targs) {
2725                               Parm *pi = temparms;
2726                               Parm *ti = targs;
2727                               String *tv = Getattr(tp,"value");
2728                               if (!tv) tv = Getattr(tp,"type");
2729                               while(pi != tp && ti && pi) {
2730                                 String *name = Getattr(ti,"name");
2731                                 String *value = Getattr(pi,"value");
2732                                 if (!value) value = Getattr(pi,"type");
2733                                 Replaceid(tv, name, value);
2734                                 pi = nextSibling(pi);
2735                                 ti = nextSibling(ti);
2736                               }
2737                             }
2738                             p = nextSibling(p);
2739                             tp = nextSibling(tp);
2740                             if (!p && tp) {
2741                               p = tp;
2742                               def_supplied = 1;
2743                             }
2744                           }
2745
2746                           templnode = copy_node(nn);
2747                           /* We need to set the node name based on name used to instantiate */
2748                           Setattr(templnode,"name",tname);
2749                           Delete(tname);
2750                           if (!specialized) {
2751                             Delattr(templnode,"sym:typename");
2752                           } else {
2753                             Setattr(templnode,"sym:typename","1");
2754                           }
2755                           if ($3) {
2756                             /*
2757                                Comment this out for 1.3.28. We need to
2758                                re-enable it later but first we need to
2759                                move %ignore from using %rename to use
2760                                %feature(ignore).
2761
2762                                String *symname = Swig_name_make(templnode,0,$3,0,0);
2763                             */
2764                             String *symname = $3;
2765                             Swig_cparse_template_expand(templnode,symname,temparms,tscope);
2766                             Setattr(templnode,"sym:name",symname);
2767                           } else {
2768                             static int cnt = 0;
2769                             String *nname = NewStringf("__dummy_%d__", cnt++);
2770                             Swig_cparse_template_expand(templnode,nname,temparms,tscope);
2771                             Setattr(templnode,"sym:name",nname);
2772                             Delete(nname);
2773                             Setattr(templnode,"feature:onlychildren",
2774                                     "typemap,typemapitem,typemapcopy,typedef,types,fragment");
2775                           }
2776                           Delattr(templnode,"templatetype");
2777                           Setattr(templnode,"template",nn);
2778                           tnode = templnode;
2779                           Setfile(templnode,cparse_file);
2780                           Setline(templnode,cparse_line);
2781                           Delete(temparms);
2782
2783                           add_symbols_copy(templnode);
2784
2785                           if (Strcmp(nodeType(templnode),"class") == 0) {
2786
2787                             /* Identify pure abstract methods */
2788                             Setattr(templnode,"abstract", pure_abstract(firstChild(templnode)));
2789
2790                             /* Set up inheritance in symbol table */
2791                             {
2792                               Symtab  *csyms;
2793                               List *baselist = Getattr(templnode,"baselist");
2794                               csyms = Swig_symbol_current();
2795                               Swig_symbol_setscope(Getattr(templnode,"symtab"));
2796                               if (baselist) {
2797                                 List *bases = make_inherit_list(Getattr(templnode,"name"),baselist);
2798                                 if (bases) {
2799                                   Iterator s;
2800                                   for (s = First(bases); s.item; s = Next(s)) {
2801                                     Symtab *st = Getattr(s.item,"symtab");
2802                                     if (st) {
2803                                       Setfile(st,Getfile(s.item));
2804                                       Setline(st,Getline(s.item));
2805                                       Swig_symbol_inherit(st);
2806                                     }
2807                                   }
2808                                   Delete(bases);
2809                                 }
2810                               }
2811                               Swig_symbol_setscope(csyms);
2812                             }
2813
2814                             /* Merge in addmethods for this class */
2815
2816                             /* !!! This may be broken.  We may have to add the
2817                                addmethods at the beginning of the class */
2818
2819                             if (extendhash) {
2820                               String *stmp = 0;
2821                               String *clsname;
2822                               Node *am;
2823                               if (Namespaceprefix) {
2824                                 clsname = stmp = NewStringf("%s::%s", Namespaceprefix, Getattr(templnode,"name"));
2825                               } else {
2826                                 clsname = Getattr(templnode,"name");
2827                               }
2828                               am = Getattr(extendhash,clsname);
2829                               if (am) {
2830                                 Symtab *st = Swig_symbol_current();
2831                                 Swig_symbol_setscope(Getattr(templnode,"symtab"));
2832                                 /*                          Printf(stdout,"%s: %s %x %x\n", Getattr(templnode,"name"), clsname, Swig_symbol_current(), Getattr(templnode,"symtab")); */
2833                                 merge_extensions(templnode,am);
2834                                 Swig_symbol_setscope(st);
2835                                 append_previous_extension(templnode,am);
2836                                 Delattr(extendhash,clsname);
2837                               }
2838                               if (stmp) Delete(stmp);
2839                             }
2840                             /* Add to classes hash */
2841                             if (!classes) classes = NewHash();
2842
2843                             {
2844                               if (Namespaceprefix) {
2845                                 String *temp = NewStringf("%s::%s", Namespaceprefix, Getattr(templnode,"name"));
2846                                 Setattr(classes,temp,templnode);
2847                                 Delete(temp);
2848                               } else {
2849                                 String *qs = Swig_symbol_qualifiedscopename(templnode);
2850                                 Setattr(classes, qs,templnode);
2851                                 Delete(qs);
2852                               }
2853                             }
2854                           }
2855                         }
2856
2857                         /* all the overloaded templated functions are added into a linked list */
2858                         if (nscope_inner) {
2859                           /* non-global namespace */
2860                           if (templnode) {
2861                             appendChild(nscope_inner,templnode);
2862                             Delete(templnode);
2863                             if (nscope) $$ = nscope;
2864                           }
2865                         } else {
2866                           /* global namespace */
2867                           if (!linklistend) {
2868                             $$ = templnode;
2869                           } else {
2870                             set_nextSibling(linklistend,templnode);
2871                             Delete(templnode);
2872                           }
2873                           linklistend = templnode;
2874                         }
2875                       }
2876                       nn = Getattr(nn,"sym:nextSibling"); /* repeat for overloaded templated functions. If a templated class there will never be a sibling. */
2877                     }
2878                   }
2879                   Swig_symbol_setscope(tscope);
2880                   Delete(Namespaceprefix);
2881                   Namespaceprefix = Swig_symbol_qualifiedscopename(0);
2882                 }
2883                ;
2884
2885 /* ------------------------------------------------------------
2886    %warn "text"
2887    %warn(no)
2888    ------------------------------------------------------------ */
2889
2890 warn_directive : WARN string {
2891                   Swig_warning(0,cparse_file, cparse_line,"%s\n", $2);
2892                   $$ = 0;
2893                }
2894                ;
2895
2896 /* ======================================================================
2897  *                              C Parsing
2898  * ====================================================================== */
2899
2900 c_declaration   : c_decl {
2901                     $$ = $1; 
2902                     if ($$) {
2903                       add_symbols($$);
2904                       default_arguments($$);
2905                     }
2906                 }
2907                 | c_enum_decl { $$ = $1; }
2908                 | c_enum_forward_decl { $$ = $1; }
2909
2910 /* An extern C type declaration, disable cparse_cplusplus if needed. */
2911
2912                 | EXTERN string LBRACE {
2913                   if (Strcmp($2,"C") == 0) {
2914                     cparse_externc = 1;
2915                   }
2916                 } interface RBRACE {
2917                   cparse_externc = 0;
2918                   if (Strcmp($2,"C") == 0) {
2919                     Node *n = firstChild($5);
2920                     $$ = new_node("extern");
2921                     Setattr($$,"name",$2);
2922                     appendChild($$,n);
2923                     while (n) {
2924                       SwigType *decl = Getattr(n,"decl");
2925                       if (SwigType_isfunction(decl)) {
2926                         Setattr(n,"storage","externc");
2927                       }
2928                       n = nextSibling(n);
2929                     }
2930                   } else {
2931                      Swig_warning(WARN_PARSE_UNDEFINED_EXTERN,cparse_file, cparse_line,"Unrecognized extern type \"%s\".\n", $2);
2932                     $$ = new_node("extern");
2933                     Setattr($$,"name",$2);
2934                     appendChild($$,firstChild($5));
2935                   }
2936                 }
2937                 ;
2938
2939 /* ------------------------------------------------------------
2940    A C global declaration of some kind (may be variable, function, typedef, etc.)
2941    ------------------------------------------------------------ */
2942
2943 c_decl  : storage_class type declarator initializer c_decl_tail {
2944               $$ = new_node("cdecl");
2945               if ($4.qualifier) SwigType_push($3.type,$4.qualifier);
2946               Setattr($$,"type",$2);
2947               Setattr($$,"storage",$1);
2948               Setattr($$,"name",$3.id);
2949               Setattr($$,"decl",$3.type);
2950               Setattr($$,"parms",$3.parms);
2951               Setattr($$,"value",$4.val);
2952               Setattr($$,"throws",$4.throws);
2953               Setattr($$,"throw",$4.throwf);
2954               if (!$5) {
2955                 if (Len(scanner_ccode)) {
2956                   String *code = Copy(scanner_ccode);
2957                   Setattr($$,"code",code);
2958                   Delete(code);
2959                 }
2960               } else {
2961                 Node *n = $5;
2962                 /* Inherit attributes */
2963                 while (n) {
2964                   String *type = Copy($2);
2965                   Setattr(n,"type",type);
2966                   Setattr(n,"storage",$1);
2967                   n = nextSibling(n);
2968                   Delete(type);
2969                 }
2970               }
2971               if ($4.bitfield) {
2972                 Setattr($$,"bitfield", $4.bitfield);
2973               }
2974
2975               /* Look for "::" declarations (ignored) */
2976               if (Strstr($3.id,"::")) {
2977                 /* This is a special case. If the scope name of the declaration exactly
2978                    matches that of the declaration, then we will allow it. Otherwise, delete. */
2979                 String *p = Swig_scopename_prefix($3.id);
2980                 if (p) {
2981                   if ((Namespaceprefix && Strcmp(p,Namespaceprefix) == 0) ||
2982                       (inclass && Strcmp(p,Classprefix) == 0)) {
2983                     String *lstr = Swig_scopename_last($3.id);
2984                     Setattr($$,"name",lstr);
2985                     Delete(lstr);
2986                     set_nextSibling($$,$5);
2987                   } else {
2988                     Delete($$);
2989                     $$ = $5;
2990                   }
2991                   Delete(p);
2992                 } else {
2993                   Delete($$);
2994                   $$ = $5;
2995                 }
2996               } else {
2997                 set_nextSibling($$,$5);
2998               }
2999            }
3000            ;
3001
3002 /* Allow lists of variables and functions to be built up */
3003
3004 c_decl_tail    : SEMI { 
3005                    $$ = 0;
3006                    Clear(scanner_ccode); 
3007                }
3008                | COMMA declarator initializer c_decl_tail {
3009                  $$ = new_node("cdecl");
3010                  if ($3.qualifier) SwigType_push($2.type,$3.qualifier);
3011                  Setattr($$,"name",$2.id);
3012                  Setattr($$,"decl",$2.type);
3013                  Setattr($$,"parms",$2.parms);
3014                  Setattr($$,"value",$3.val);
3015                  Setattr($$,"throws",$3.throws);
3016                  Setattr($$,"throw",$3.throwf);
3017                  if ($3.bitfield) {
3018                    Setattr($$,"bitfield", $3.bitfield);
3019                  }
3020                  if (!$4) {
3021                    if (Len(scanner_ccode)) {
3022                      String *code = Copy(scanner_ccode);
3023                      Setattr($$,"code",code);
3024                      Delete(code);
3025                    }
3026                  } else {
3027                    set_nextSibling($$,$4);
3028                  }
3029                }
3030                | LBRACE { 
3031                    skip_balanced('{','}');
3032                    $$ = 0;
3033                }
3034               ;
3035
3036 initializer   : def_args { 
3037                    $$ = $1; 
3038                    $$.qualifier = 0;
3039                    $$.throws = 0;
3040                    $$.throwf = 0;
3041               }
3042               | type_qualifier def_args { 
3043                    $$ = $2; 
3044                    $$.qualifier = $1;
3045                    $$.throws = 0;
3046                    $$.throwf = 0;
3047               }
3048               | THROW LPAREN parms RPAREN def_args { 
3049                    $$ = $5; 
3050                    $$.qualifier = 0;
3051                    $$.throws = $3;
3052                    $$.throwf = NewString("1");
3053               }
3054               | type_qualifier THROW LPAREN parms RPAREN def_args { 
3055                    $$ = $6; 
3056                    $$.qualifier = $1;
3057                    $$.throws = $4;
3058                    $$.throwf = NewString("1");
3059               }
3060               ;
3061
3062
3063 /* ------------------------------------------------------------
3064    enum Name;
3065    ------------------------------------------------------------ */
3066
3067 c_enum_forward_decl : storage_class ENUM ID SEMI {
3068                    SwigType *ty = 0;
3069                    $$ = new_node("enumforward");
3070                    ty = NewStringf("enum %s", $3);
3071                    Setattr($$,"name",$3);
3072                    Setattr($$,"type",ty);
3073                    Setattr($$,"sym:weak", "1");
3074                    add_symbols($$);
3075               }
3076               ;
3077
3078 /* ------------------------------------------------------------
3079    enum { ... }
3080  * ------------------------------------------------------------ */
3081
3082 c_enum_decl : storage_class ENUM ename LBRACE enumlist RBRACE SEMI {
3083                   SwigType *ty = 0;
3084                   $$ = new_node("enum");
3085                   ty = NewStringf("enum %s", $3);
3086                   Setattr($$,"name",$3);
3087                   Setattr($$,"type",ty);
3088                   appendChild($$,$5);
3089                   add_symbols($$);       /* Add to tag space */
3090                   add_symbols($5);       /* Add enum values to id space */
3091                }
3092                | storage_class ENUM ename LBRACE enumlist RBRACE declarator c_decl_tail {
3093                  Node *n;
3094                  SwigType *ty = 0;
3095                  String   *unnamed = 0;
3096                  int       unnamedinstance = 0;
3097
3098                  $$ = new_node("enum");
3099                  if ($3) {
3100                    Setattr($$,"name",$3);
3101                    ty = NewStringf("enum %s", $3);
3102                  } else if ($7.id) {
3103                    unnamed = make_unnamed();
3104                    ty = NewStringf("enum %s", unnamed);
3105                    Setattr($$,"unnamed",unnamed);
3106                    /* name is not set for unnamed enum instances, e.g. enum { foo } Instance; */
3107                    if ($1 && Cmp($1,"typedef") == 0) {
3108                      Setattr($$,"name",$7.id);
3109                    } else {
3110                      unnamedinstance = 1;
3111                    }
3112                    Setattr($$,"storage",$1);
3113                  }
3114                  if ($7.id && Cmp($1,"typedef") == 0) {
3115                    Setattr($$,"tdname",$7.id);
3116                    Setattr($$,"allows_typedef","1");
3117                  }
3118                  appendChild($$,$5);
3119                  n = new_node("cdecl");
3120                  Setattr(n,"type",ty);
3121                  Setattr(n,"name",$7.id);
3122                  Setattr(n,"storage",$1);
3123                  Setattr(n,"decl",$7.type);
3124                  Setattr(n,"parms",$7.parms);
3125                  Setattr(n,"unnamed",unnamed);
3126
3127                  if (unnamedinstance) {
3128                    SwigType *cty = NewString("enum ");
3129                    Setattr($$,"type",cty);
3130                    Setattr($$,"unnamedinstance","1");
3131                    Setattr(n,"unnamedinstance","1");
3132                    Delete(cty);
3133                  }
3134                  if ($8) {
3135                    Node *p = $8;
3136                    set_nextSibling(n,p);
3137                    while (p) {
3138                      SwigType *cty = Copy(ty);
3139                      Setattr(p,"type",cty);
3140                      Setattr(p,"unnamed",unnamed);
3141                      Setattr(p,"storage",$1);
3142                      Delete(cty);
3143                      p = nextSibling(p);
3144                    }
3145                  } else {
3146                    if (Len(scanner_ccode)) {
3147                      String *code = Copy(scanner_ccode);
3148                      Setattr(n,"code",code);
3149                      Delete(code);
3150                    }
3151                  }
3152
3153                  /* Ensure that typedef enum ABC {foo} XYZ; uses XYZ for sym:name, like structs.
3154                   * Note that class_rename/yyrename are bit of a mess so used this simple approach to change the name. */
3155                  if ($7.id && $3 && Cmp($1,"typedef") == 0) {
3156                    String *name = NewString($7.id);
3157                    Setattr($$, "parser:makename", name);
3158                    Delete(name);
3159                  }
3160
3161                  add_symbols($$);       /* Add enum to tag space */
3162                  set_nextSibling($$,n);
3163                  Delete(n);
3164                  add_symbols($5);       /* Add enum values to id space */
3165                  add_symbols(n);
3166                  Delete(unnamed);
3167                }
3168                ;
3169
3170 c_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end {
3171                    /* This is a sick hack.  If the ctor_end has parameters,
3172                       and the parms parameter only has 1 parameter, this
3173                       could be a declaration of the form:
3174
3175                          type (id)(parms)
3176
3177                          Otherwise it's an error. */
3178                     int err = 0;
3179                     $$ = 0;
3180
3181                     if ((ParmList_len($4) == 1) && (!Swig_scopename_check($2))) {
3182                       SwigType *ty = Getattr($4,"type");
3183                       String *name = Getattr($4,"name");
3184                       err = 1;
3185                       if (!name) {
3186                         $$ = new_node("cdecl");
3187                         Setattr($$,"type",$2);
3188                         Setattr($$,"storage",$1);
3189                         Setattr($$,"name",ty);
3190
3191                         if ($6.have_parms) {
3192                           SwigType *decl = NewStringEmpty();
3193                           SwigType_add_function(decl,$6.parms);
3194                           Setattr($$,"decl",decl);
3195                           Setattr($$,"parms",$6.parms);
3196                           if (Len(scanner_ccode)) {
3197                             String *code = Copy(scanner_ccode);
3198                             Setattr($$,"code",code);
3199                             Delete(code);
3200                           }
3201                         }
3202                         if ($6.defarg) {
3203                           Setattr($$,"value",$6.defarg);
3204                         }
3205                         Setattr($$,"throws",$6.throws);
3206                         Setattr($$,"throw",$6.throwf);
3207                         err = 0;
3208                       }
3209                     }
3210                     if (err) {
3211                       Swig_error(cparse_file,cparse_line,"Syntax error in input(2).\n");
3212                       exit(1);
3213                     }
3214                 }
3215                 ;
3216
3217 /* ======================================================================
3218  *                       C++ Support
3219  * ====================================================================== */
3220
3221 cpp_declaration : cpp_class_decl {  $$ = $1; }
3222                 | cpp_forward_class_decl { $$ = $1; }
3223                 | cpp_template_decl { $$ = $1; }
3224                 | cpp_using_decl { $$ = $1; }
3225                 | cpp_namespace_decl { $$ = $1; }
3226                 | cpp_catch_decl { $$ = 0; }
3227                 ;
3228
3229 cpp_class_decl  :
3230
3231 /* A simple class/struct/union definition */
3232                 storage_class cpptype idcolon inherit LBRACE {
3233                    List *bases = 0;
3234                    Node *scope = 0;
3235                    $<node>$ = new_node("class");
3236                    Setline($<node>$,cparse_start_line);
3237                    Setattr($<node>$,"kind",$2);
3238                    if ($4) {
3239                      Setattr($<node>$,"baselist", Getattr($4,"public"));
3240                      Setattr($<node>$,"protectedbaselist", Getattr($4,"protected"));
3241                      Setattr($<node>$,"privatebaselist", Getattr($4,"private"));
3242                    }
3243                    Setattr($<node>$,"allows_typedef","1");
3244
3245                    /* preserve the current scope */
3246                    prev_symtab = Swig_symbol_current();
3247                   
3248                    /* If the class name is qualified.  We need to create or lookup namespace/scope entries */
3249                    scope = resolve_node_scope($3);
3250                    Setfile(scope,cparse_file);
3251                    Setline(scope,cparse_line);
3252                    $3 = scope;
3253                    
3254                    /* support for old nested classes "pseudo" support, such as:
3255
3256                          %rename(Ala__Ola) Ala::Ola;
3257                         class Ala::Ola {
3258                         public:
3259                             Ola() {}
3260                          };
3261
3262                       this should disappear when a proper implementation is added.
3263                    */
3264                    if (nscope_inner && Strcmp(nodeType(nscope_inner),"namespace") != 0) {
3265                      if (Namespaceprefix) {
3266                        String *name = NewStringf("%s::%s", Namespaceprefix, $3);                       
3267                        $3 = name;
3268                        Namespaceprefix = 0;
3269                        nscope_inner = 0;
3270                      }
3271                    }
3272                    Setattr($<node>$,"name",$3);
3273
3274                    Delete(class_rename);
3275                    class_rename = make_name($<node>$,$3,0);
3276                    Classprefix = NewString($3);
3277                    /* Deal with inheritance  */
3278                    if ($4) {
3279                      bases = make_inherit_list($3,Getattr($4,"public"));
3280                    }
3281                    if (SwigType_istemplate($3)) {
3282                      String *fbase, *tbase, *prefix;
3283                      prefix = SwigType_templateprefix($3);
3284                      if (Namespaceprefix) {
3285                        fbase = NewStringf("%s::%s", Namespaceprefix,$3);
3286                        tbase = NewStringf("%s::%s", Namespaceprefix, prefix);
3287                      } else {
3288                        fbase = Copy($3);
3289                        tbase = Copy(prefix);
3290                      }
3291                      Swig_name_inherit(tbase,fbase);
3292                      Delete(fbase);
3293                      Delete(tbase);
3294                      Delete(prefix);
3295                    }
3296                    if (strcmp($2,"class") == 0) {
3297                      cplus_mode = CPLUS_PRIVATE;
3298                    } else {
3299                      cplus_mode = CPLUS_PUBLIC;
3300                    }
3301                    Swig_symbol_newscope();
3302                    Swig_symbol_setscopename($3);
3303                    if (bases) {
3304                      Iterator s;
3305                      for (s = First(bases); s.item; s = Next(s)) {
3306                        Symtab *st = Getattr(s.item,"symtab");
3307                        if (st) {
3308                          Setfile(st,Getfile(s.item));
3309                          Setline(st,Getline(s.item));
3310                          Swig_symbol_inherit(st); 
3311                        }
3312                      }
3313                      Delete(bases);
3314                    }
3315                    Delete(Namespaceprefix);
3316                    Namespaceprefix = Swig_symbol_qualifiedscopename(0);
3317                    cparse_start_line = cparse_line;
3318
3319                    /* If there are active template parameters, we need to make sure they are
3320                       placed in the class symbol table so we can catch shadows */
3321
3322                    if (template_parameters) {
3323                      Parm *tp = template_parameters;
3324                      while(tp) {
3325                        String *tpname = Copy(Getattr(tp,"name"));
3326                        Node *tn = new_node("templateparm");
3327                        Setattr(tn,"name",tpname);
3328                        Swig_symbol_cadd(tpname,tn);
3329                        tp = nextSibling(tp);
3330                        Delete(tpname);
3331                      }
3332                    }
3333                    if (class_level >= max_class_levels) {
3334                        if (!max_class_levels) {
3335                            max_class_levels = 16;
3336                        } else {
3337                            max_class_levels *= 2;
3338                        }
3339                        class_decl = (Node**) realloc(class_decl, sizeof(Node*) * max_class_levels);
3340                        if (!class_decl) {
3341                            Swig_error(cparse_file, cparse_line, "realloc() failed\n");
3342                        }
3343                    }
3344                    class_decl[class_level++] = $<node>$;
3345                    inclass = 1;
3346                } cpp_members RBRACE cpp_opt_declarators {
3347                  Node *p;
3348                  SwigType *ty;
3349                  Symtab *cscope = prev_symtab;
3350                  Node *am = 0;
3351                  String *scpname = 0;
3352                  $$ = class_decl[--class_level];
3353                  inclass = 0;
3354                  
3355                  /* Check for pure-abstract class */
3356                  Setattr($$,"abstract", pure_abstract($7));
3357                  
3358                  /* This bit of code merges in a previously defined %extend directive (if any) */
3359                  
3360                  if (extendhash) {
3361                    String *clsname = Swig_symbol_qualifiedscopename(0);
3362                    am = Getattr(extendhash,clsname);
3363                    if (am) {
3364                      merge_extensions($$,am);
3365                      Delattr(extendhash,clsname);
3366                    }
3367                    Delete(clsname);
3368                  }
3369                  if (!classes) classes = NewHash();
3370                  scpname = Swig_symbol_qualifiedscopename(0);
3371                  Setattr(classes,scpname,$$);
3372                  Delete(scpname);
3373
3374                  appendChild($$,$7);
3375                  
3376                  if (am) append_previous_extension($$,am);
3377
3378                  p = $9;
3379                  if (p) {
3380                    set_nextSibling($$,p);
3381                  }
3382                  
3383                  if (cparse_cplusplus && !cparse_externc) {
3384                    ty = NewString($3);
3385                  } else {
3386                    ty = NewStringf("%s %s", $2,$3);
3387                  }
3388                  while (p) {
3389                    Setattr(p,"storage",$1);
3390                    Setattr(p,"type",ty);
3391                    p = nextSibling(p);
3392                  }
3393                  /* Dump nested classes */
3394                  {
3395                    String *name = $3;
3396                    if ($9) {
3397                      SwigType *decltype = Getattr($9,"decl");
3398                      if (Cmp($1,"typedef") == 0) {
3399                        if (!decltype || !Len(decltype)) {
3400                          String *cname;
3401                          name = Getattr($9,"name");
3402                          cname = Copy(name);
3403                          Setattr($$,"tdname",cname);
3404                          Delete(cname);
3405
3406                          /* Use typedef name as class name */
3407                          if (class_rename && (Strcmp(class_rename,$3) == 0)) {
3408                            Delete(class_rename);
3409                            class_rename = NewString(name);
3410                          }
3411                          if (!Getattr(classes,name)) {
3412                            Setattr(classes,name,$$);
3413                          }
3414                          Setattr($$,"decl",decltype);
3415                        }
3416                      }
3417                    }
3418                    appendChild($$,dump_nested(Char(name)));
3419                  }
3420
3421                  if (cplus_mode != CPLUS_PUBLIC) {
3422                  /* we 'open' the class at the end, to allow %template
3423                     to add new members */
3424                    Node *pa = new_node("access");
3425                    Setattr(pa,"kind","public");
3426                    cplus_mode = CPLUS_PUBLIC;
3427                    appendChild($$,pa);
3428                    Delete(pa);
3429                  }
3430
3431                  Setattr($$,"symtab",Swig_symbol_popscope());
3432
3433                  Classprefix = 0;
3434                  if (nscope_inner) {
3435                    /* this is tricky */
3436                    /* we add the declaration in the original namespace */
3437                    appendChild(nscope_inner,$$);
3438                    Swig_symbol_setscope(Getattr(nscope_inner,"symtab"));
3439                    Delete(Namespaceprefix);
3440                    Namespaceprefix = Swig_symbol_qualifiedscopename(0);
3441                    add_symbols($$);
3442                    if (nscope) $$ = nscope;
3443                    /* but the variable definition in the current scope */
3444                    Swig_symbol_setscope(cscope);
3445                    Delete(Namespaceprefix);
3446                    Namespaceprefix = Swig_symbol_qualifiedscopename(0);
3447                    add_symbols($9);
3448                  } else {
3449                    Delete(yyrename);
3450                    yyrename = Copy(class_rename);
3451                    Delete(Namespaceprefix);
3452                    Namespaceprefix = Swig_symbol_qualifiedscopename(0);
3453
3454                    add_symbols($$);
3455                    add_symbols($9);
3456                  }
3457                  Swig_symbol_setscope(cscope);
3458                  Delete(Namespaceprefix);
3459                  Namespaceprefix = Swig_symbol_qualifiedscopename(0);
3460                }
3461
3462 /* An unnamed struct, possibly with a typedef */
3463
3464              | storage_class cpptype LBRACE {
3465                String *unnamed;
3466                unnamed = make_unnamed();
3467                $<node>$ = new_node("class");
3468                Setline($<node>$,cparse_start_line);
3469                Setattr($<node>$,"kind",$2);
3470                Setattr($<node>$,"storage",$1);
3471                Setattr($<node>$,"unnamed",unnamed);
3472                Setattr($<node>$,"allows_typedef","1");
3473                Delete(class_rename);
3474                class_rename = make_name($<node>$,0,0);
3475                if (strcmp($2,"class") == 0) {
3476                  cplus_mode = CPLUS_PRIVATE;
3477                } else {
3478                  cplus_mode = CPLUS_PUBLIC;
3479                }
3480                Swig_symbol_newscope();
3481                cparse_start_line = cparse_line;
3482                if (class_level >= max_class_levels) {
3483                    if (!max_class_levels) {
3484                        max_class_levels = 16;
3485                    } else {
3486                        max_class_levels *= 2;
3487                    }
3488                    class_decl = (Node**) realloc(class_decl, sizeof(Node*) * max_class_levels);
3489                    if (!class_decl) {
3490                        Swig_error(cparse_file, cparse_line, "realloc() failed\n");
3491                    }
3492                }
3493                class_decl[class_level++] = $<node>$;
3494                inclass = 1;
3495                Classprefix = NewStringEmpty();
3496                Delete(Namespaceprefix);
3497                Namespaceprefix = Swig_symbol_qualifiedscopename(0);
3498              } cpp_members RBRACE declarator c_decl_tail {
3499                String *unnamed;
3500                Node *n;
3501                Classprefix = 0;
3502                $$ = class_decl[--class_level];
3503                inclass = 0;
3504                unnamed = Getattr($$,"unnamed");
3505
3506                /* Check for pure-abstract class */
3507                Setattr($$,"abstract", pure_abstract($5));
3508
3509                n = new_node("cdecl");
3510                Setattr(n,"name",$7.id);
3511                Setattr(n,"unnamed",unnamed);
3512                Setattr(n,"type",unnamed);
3513                Setattr(n,"decl",$7.type);
3514                Setattr(n,"parms",$7.parms);
3515                Setattr(n,"storage",$1);
3516                if ($8) {
3517                  Node *p = $8;
3518                  set_nextSibling(n,p);
3519                  while (p) {
3520                    String *type = Copy(unnamed);
3521                    Setattr(p,"name",$7.id);
3522                    Setattr(p,"unnamed",unnamed);
3523                    Setattr(p,"type",type);
3524                    Delete(type);
3525                    Setattr(p,"storage",$1);
3526                    p = nextSibling(p);
3527                  }
3528                }
3529                set_nextSibling($$,n);
3530                Delete(n);
3531                {
3532                  /* If a proper typedef name was given, we'll use it to set the scope name */
3533                  String *name = 0;
3534                  if ($1 && (strcmp($1,"typedef") == 0)) {
3535                    if (!Len($7.type)) { 
3536                      String *scpname = 0;
3537                      name = $7.id;
3538                      Setattr($$,"tdname",name);
3539                      Setattr($$,"name",name);
3540                      Swig_symbol_setscopename(name);
3541
3542                      /* If a proper name was given, we use that as the typedef, not unnamed */
3543                      Clear(unnamed);
3544                      Append(unnamed, name);
3545                      
3546                      n = nextSibling(n);
3547                      set_nextSibling($$,n);
3548
3549                      /* Check for previous extensions */
3550                      if (extendhash) {
3551                        String *clsname = Swig_symbol_qualifiedscopename(0);
3552                        Node *am = Getattr(extendhash,clsname);
3553                        if (am) {
3554                          /* Merge the extension into the symbol table */
3555                          merge_extensions($$,am);
3556                          append_previous_extension($$,am);
3557                          Delattr(extendhash,clsname);
3558                        }
3559                        Delete(clsname);
3560                      }
3561                      if (!classes) classes = NewHash();
3562                      scpname = Swig_symbol_qualifiedscopename(0);
3563                      Setattr(classes,scpname,$$);
3564                      Delete(scpname);
3565                    } else {
3566                      Swig_symbol_setscopename((char*)"<unnamed>");
3567                    }
3568                  }
3569                  appendChild($$,$5);
3570                  appendChild($$,dump_nested(Char(name)));
3571                }
3572                /* Pop the scope */
3573                Setattr($$,"symtab",Swig_symbol_popscope());
3574                if (class_rename) {
3575                  Delete(yyrename);
3576                  yyrename = NewString(class_rename);
3577                }
3578                Delete(Namespaceprefix);
3579                Namespaceprefix = Swig_symbol_qualifiedscopename(0);
3580                add_symbols($$);
3581                add_symbols(n);
3582                Delete(unnamed);
3583               }
3584              ;
3585
3586 cpp_opt_declarators :  SEMI { $$ = 0; }
3587                     |  declarator c_decl_tail {
3588                         $$ = new_node("cdecl");
3589                         Setattr($$,"name",$1.id);
3590                         Setattr($$,"decl",$1.type);
3591                         Setattr($$,"parms",$1.parms);
3592                         set_nextSibling($$,$2);
3593                     }
3594                     ;
3595 /* ------------------------------------------------------------
3596    class Name;
3597    ------------------------------------------------------------ */
3598
3599 cpp_forward_class_decl : storage_class cpptype idcolon SEMI {
3600               if ($1 && (Strcmp($1,"friend") == 0)) {
3601                 /* Ignore */
3602                 $$ = 0; 
3603               } else {
3604                 $$ = new_node("classforward");
3605                 Setfile($$,cparse_file);
3606                 Setline($$,cparse_line);
3607                 Setattr($$,"kind",$2);
3608                 Setattr($$,"name",$3);
3609                 Setattr($$,"sym:weak", "1");
3610                 add_symbols($$);
3611               }
3612              }
3613              ;
3614
3615 /* ------------------------------------------------------------
3616    template<...> decl
3617    ------------------------------------------------------------ */
3618
3619 cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { template_parameters = $3; } cpp_temp_possible {
3620                       String *tname = 0;
3621                       int     error = 0;
3622
3623                       /* check if we get a namespace node with a class declaration, and retrieve the class */
3624                       Symtab *cscope = Swig_symbol_current();
3625                       Symtab *sti = 0;
3626                       Node *ntop = $6;
3627                       Node *ni = ntop;
3628                       SwigType *ntype = ni ? nodeType(ni) : 0;
3629                       while (ni && Strcmp(ntype,"namespace") == 0) {
3630                         sti = Getattr(ni,"symtab");
3631                         ni = firstChild(ni);
3632                         ntype = nodeType(ni);
3633                       }
3634                       if (sti) {
3635                         Swig_symbol_setscope(sti);
3636                         Delete(Namespaceprefix);
3637                         Namespaceprefix = Swig_symbol_qualifiedscopename(0);
3638                         $6 = ni;
3639                       }
3640
3641                       template_parameters = 0;
3642                       $$ = $6;
3643                       if ($$) tname = Getattr($$,"name");
3644                       
3645                       /* Check if the class is a template specialization */
3646                       if (($$) && (Strchr(tname,'<')) && (!is_operator(tname))) {
3647                         /* If a specialization.  Check if defined. */
3648                         Node *tempn = 0;
3649                         {
3650                           String *tbase = SwigType_templateprefix(tname);
3651                           tempn = Swig_symbol_clookup_local(tbase,0);
3652                           if (!tempn || (Strcmp(nodeType(tempn),"template") != 0)) {
3653                             SWIG_WARN_NODE_BEGIN(tempn);
3654                             Swig_warning(WARN_PARSE_TEMPLATE_SP_UNDEF, Getfile($$),Getline($$),"Specialization of non-template '%s'.\n", tbase);
3655                             SWIG_WARN_NODE_END(tempn);
3656                             tempn = 0;
3657                             error = 1;
3658                           }
3659                           Delete(tbase);
3660                         }
3661                         Setattr($$,"specialization","1");
3662                         Setattr($$,"templatetype",nodeType($$));
3663                         set_nodeType($$,"template");
3664                         /* Template partial specialization */
3665                         if (tempn && ($3) && ($6)) {
3666                           List   *tlist;
3667                           String *targs = SwigType_templateargs(tname);
3668                           tlist = SwigType_parmlist(targs);
3669                           /*                      Printf(stdout,"targs = '%s' %s\n", targs, tlist); */
3670                           if (!Getattr($$,"sym:weak")) {
3671                             Setattr($$,"sym:typename","1");
3672                           }
3673                           
3674                           if (Len(tlist) != ParmList_len(Getattr(tempn,"templateparms"))) {
3675                             Swig_error(Getfile($$),Getline($$),"Inconsistent argument count in template partial specialization. %d %d\n", Len(tlist), ParmList_len(Getattr(tempn,"templateparms")));
3676                             
3677                           } else {
3678
3679                           /* This code builds the argument list for the partial template
3680                              specialization.  This is a little hairy, but the idea is as
3681                              follows:
3682
3683                              $3 contains a list of arguments supplied for the template.
3684                              For example template<class T>.
3685
3686                              tlist is a list of the specialization arguments--which may be
3687                              different.  For example class<int,T>.
3688
3689                              tp is a copy of the arguments in the original template definition.
3690      
3691                              The patching algorithm walks through the list of supplied
3692                              arguments ($3), finds the position in the specialization arguments
3693                              (tlist), and then patches the name in the argument list of the
3694                              original template.
3695                           */
3696
3697                           {
3698                             String *pn;
3699                             Parm *p, *p1;
3700                             int i, nargs;
3701                             Parm *tp = CopyParmList(Getattr(tempn,"templateparms"));
3702                             nargs = Len(tlist);
3703                             p = $3;
3704                             while (p) {
3705                               for (i = 0; i < nargs; i++){
3706                                 pn = Getattr(p,"name");
3707                                 if (Strcmp(pn,SwigType_base(Getitem(tlist,i))) == 0) {
3708                                   int j;
3709                                   Parm *p1 = tp;
3710                                   for (j = 0; j < i; j++) {
3711                                     p1 = nextSibling(p1);
3712                                   }
3713                                   Setattr(p1,"name",pn);
3714                                   Setattr(p1,"partialarg","1");
3715                                 }
3716                               }
3717                               p = nextSibling(p);
3718                             }
3719                             p1 = tp;
3720                             i = 0;
3721                             while (p1) {
3722                               if (!Getattr(p1,"partialarg")) {
3723                                 Delattr(p1,"name");
3724                                 Setattr(p1,"type", Getitem(tlist,i));
3725                               } 
3726                               i++;
3727                               p1 = nextSibling(p1);
3728                             }
3729                             Setattr($$,"templateparms",tp);
3730                             Delete(tp);
3731                           }
3732 #if 0
3733                           /* Patch the parameter list */
3734                           if (tempn) {
3735                             Parm *p,*p1;
3736                             ParmList *tp = CopyParmList(Getattr(tempn,"templateparms"));
3737                             p = $3;
3738                             p1 = tp;
3739                             while (p && p1) {
3740                               String *pn = Getattr(p,"name");
3741                               Printf(stdout,"pn = '%s'\n", pn);
3742                               if (pn) Setattr(p1,"name",pn);
3743                               else Delattr(p1,"name");
3744                               pn = Getattr(p,"type");
3745                               if (pn) Setattr(p1,"type",pn);
3746                               p = nextSibling(p);
3747                               p1 = nextSibling(p1);
3748                             }
3749                             Setattr($$,"templateparms",tp);
3750                             Delete(tp);
3751                           } else {
3752                             Setattr($$,"templateparms",$3);
3753                           }
3754 #endif
3755                           Delattr($$,"specialization");
3756                           Setattr($$,"partialspecialization","1");
3757                           /* Create a specialized name for matching */
3758                           {
3759                             Parm *p = $3;
3760                             String *fname = NewString(Getattr($$,"name"));
3761                             String *ffname = 0;
3762
3763                             char   tmp[32];
3764                             int    i, ilen;
3765                             while (p) {
3766                               String *n = Getattr(p,"name");
3767                               if (!n) {
3768                                 p = nextSibling(p);
3769                                 continue;
3770                               }
3771                               ilen = Len(tlist);
3772                               for (i = 0; i < ilen; i++) {
3773                                 if (Strstr(Getitem(tlist,i),n)) {
3774                                   sprintf(tmp,"$%d",i+1);
3775                                   Replaceid(fname,n,tmp);
3776                                 }
3777                               }
3778                               p = nextSibling(p);
3779                             }
3780                             /* Patch argument names with typedef */
3781                             {
3782                               Iterator tt;
3783                               List *tparms = SwigType_parmlist(fname);
3784                               ffname = SwigType_templateprefix(fname);
3785                               Append(ffname,"<(");
3786                               for (tt = First(tparms); tt.item; ) {
3787                                 SwigType *rtt = Swig_symbol_typedef_reduce(tt.item,0);
3788                                 SwigType *ttr = Swig_symbol_type_qualify(rtt,0);
3789                                 Append(ffname,ttr);
3790                                 tt = Next(tt);
3791                                 if (tt.item) Putc(',',ffname);
3792                                 Delete(rtt);
3793                                 Delete(ttr);
3794                               }
3795                               Delete(tparms);
3796                               Append(ffname,")>");
3797                             }
3798                             {
3799                               String *partials = Getattr(tempn,"partials");
3800                               if (!partials) {
3801                                 partials = NewList();
3802                                 Setattr(tempn,"partials",partials);
3803                                 Delete(partials);
3804                               }
3805                               /*                              Printf(stdout,"partial: fname = '%s', '%s'\n", fname, Swig_symbol_typedef_reduce(fname,0)); */
3806                               Append(partials,ffname);
3807                             }
3808                             Setattr($$,"partialargs",ffname);
3809                             Swig_symbol_cadd(ffname,$$);
3810                           }
3811                           }
3812                           Delete(tlist);
3813                           Delete(targs);
3814                         } else {
3815                           /* Need to resolve exact specialization name */
3816                           /* add default args from generic template */
3817                           String *ty = Swig_symbol_template_deftype(tname,0);
3818                           String *fname = Swig_symbol_type_qualify(ty,0);
3819                           Swig_symbol_cadd(fname,$$);
3820                           Delete(ty);
3821                           Delete(fname);
3822                         }
3823                       }  else if ($$) {
3824                         Setattr($$,"templatetype",nodeType($6));
3825                         set_nodeType($$,"template");
3826                         Setattr($$,"templateparms", $3);
3827                         if (!Getattr($$,"sym:weak")) {
3828                           Setattr($$,"sym:typename","1");
3829                         }
3830                         add_symbols($$);
3831                         default_arguments($$);
3832                         /* We also place a fully parameterized version in the symbol table */
3833                         {
3834                           Parm *p;
3835                           String *fname = NewStringf("%s<(", Getattr($$,"name"));
3836                           p = $3;
3837                           while (p) {
3838                             String *n = Getattr(p,"name");
3839                             if (!n) n = Getattr(p,"type");
3840                             Append(fname,n);
3841                             p = nextSibling(p);
3842                             if (p) Putc(',',fname);
3843                           }
3844                           Append(fname,")>");
3845                           Swig_symbol_cadd(fname,$$);
3846                         }
3847                       }
3848                       $$ = ntop;
3849                       Swig_symbol_setscope(cscope);
3850                       Delete(Namespaceprefix);
3851                       Namespaceprefix = Swig_symbol_qualifiedscopename(0);
3852                       if (error) $$ = 0;
3853                   }
3854                 | TEMPLATE cpptype idcolon {
3855                   Swig_warning(WARN_PARSE_EXPLICIT_TEMPLATE, cparse_file, cparse_line, "Explicit template instantiation ignored.\n");
3856                    $$ = 0; 
3857                 }
3858                 ;
3859
3860 cpp_temp_possible:  c_decl {
3861                   $$ = $1;
3862                 }
3863                 | cpp_class_decl {
3864                    $$ = $1;
3865                 }
3866                 | cpp_constructor_decl {
3867                    $$ = $1;
3868                 }
3869                 | cpp_template_decl {
3870                   $$ = 0;
3871                 }
3872                 | cpp_forward_class_decl {
3873                   $$ = $1;
3874                 }
3875                 | cpp_conversion_operator {
3876                   $$ = $1;
3877                 }
3878                 ;
3879
3880 template_parms  : templateparameters {
3881                    /* Rip out the parameter names */
3882                   Parm *p = $1;
3883                   $$ = $1;
3884
3885                   while (p) {
3886                     String *name = Getattr(p,"name");
3887                     if (!name) {
3888                       /* Hmmm. Maybe it's a 'class T' parameter */
3889                       char *type = Char(Getattr(p,"type"));
3890                       /* Template template parameter */
3891                       if (strncmp(type,"template<class> ",16) == 0) {
3892                         type += 16;
3893                       }
3894                       if ((strncmp(type,"class ",6) == 0) || (strncmp(type,"typename ", 9) == 0)) {
3895                         char *t = strchr(type,' ');
3896                         Setattr(p,"name", t+1);
3897                       } else {
3898                         /*
3899                          Swig_error(cparse_file, cparse_line, "Missing template parameter name\n");
3900                          $$.rparms = 0;
3901                          $$.parms = 0;
3902                          break; */
3903                       }
3904                     }
3905                     p = nextSibling(p);
3906                   }
3907                  }
3908                  ;
3909
3910 templateparameters : templateparameter templateparameterstail {
3911                       set_nextSibling($1,$2);
3912                       $$ = $1;
3913                    }
3914                    | empty { $$ = 0; }
3915                    ;
3916
3917 templateparameter : templcpptype {
3918                     $$ = NewParm(NewString($1), 0);
3919                   }
3920                   | parm {
3921                     $$ = $1;
3922                   }
3923                   ;
3924
3925 templateparameterstail : COMMA templateparameter templateparameterstail {
3926                          set_nextSibling($2,$3);
3927                          $$ = $2;
3928                        }
3929                        | empty { $$ = 0; }
3930                        ;
3931
3932 /* Namespace support */
3933
3934 cpp_using_decl : USING idcolon SEMI {
3935                   String *uname = Swig_symbol_type_qualify($2,0);
3936                   String *name = Swig_scopename_last($2);
3937                   $$ = new_node("using");
3938                   Setattr($$,"uname",uname);
3939                   Setattr($$,"name", name);
3940                   Delete(uname);
3941                   Delete(name);
3942                   add_symbols($$);
3943              }
3944              | USING NAMESPACE idcolon SEMI {
3945                Node *n = Swig_symbol_clookup($3,0);
3946                if (!n) {
3947                  Swig_error(cparse_file, cparse_line, "Nothing known about namespace '%s'\n", $3);
3948                  $$ = 0;
3949                } else {
3950
3951                  while (Strcmp(nodeType(n),"using") == 0) {
3952                    n = Getattr(n,"node");
3953                  }
3954                  if (n) {
3955                    if (Strcmp(nodeType(n),"namespace") == 0) {
3956                      Symtab *current = Swig_symbol_current();
3957                      Symtab *symtab = Getattr(n,"symtab");
3958                      $$ = new_node("using");
3959                      Setattr($$,"node",n);
3960                      Setattr($$,"namespace", $3);
3961                      if (current != symtab) {
3962                        Swig_symbol_inherit(symtab);
3963                      }
3964                    } else {
3965                      Swig_error(cparse_file, cparse_line, "'%s' is not a namespace.\n", $3);
3966                      $$ = 0;
3967                    }
3968                  } else {
3969                    $$ = 0;
3970                  }
3971                }
3972              }
3973              ;
3974
3975 cpp_namespace_decl : NAMESPACE idcolon LBRACE { 
3976                 Hash *h;
3977                 $1 = Swig_symbol_current();
3978                 h = Swig_symbol_clookup($2,0);
3979                 if (h && ($1 == Getattr(h,"sym:symtab")) && (Strcmp(nodeType(h),"namespace") == 0)) {
3980                   if (Getattr(h,"alias")) {
3981                     h = Getattr(h,"namespace");
3982                     Swig_warning(WARN_PARSE_NAMESPACE_ALIAS, cparse_file, cparse_line, "Namespace alias '%s' not allowed here. Assuming '%s'\n",
3983                                  $2, Getattr(h,"name"));
3984                     $2 = Getattr(h,"name");
3985                   }
3986                   Swig_symbol_setscope(Getattr(h,"symtab"));
3987                 } else {
3988                   Swig_symbol_newscope();
3989                   Swig_symbol_setscopename($2);
3990                 }
3991                 Delete(Namespaceprefix);
3992                 Namespaceprefix = Swig_symbol_qualifiedscopename(0);
3993              } interface RBRACE {
3994                 Node *n = $5;
3995                 set_nodeType(n,"namespace");
3996                 Setattr(n,"name",$2);
3997                 Setattr(n,"symtab", Swig_symbol_popscope());
3998                 Swig_symbol_setscope($1);
3999                 $$ = n;
4000                 Delete(Namespaceprefix);
4001                 Namespaceprefix = Swig_symbol_qualifiedscopename(0);
4002                 add_symbols($$);
4003              } 
4004              | NAMESPACE LBRACE {
4005                Hash *h;
4006                $1 = Swig_symbol_current();
4007                h = Swig_symbol_clookup((char *)"    ",0);
4008                if (h && (Strcmp(nodeType(h),"namespace") == 0)) {
4009                  Swig_symbol_setscope(Getattr(h,"symtab"));
4010                } else {
4011                  Swig_symbol_newscope();
4012                  /* we don't use "__unnamed__", but a long 'empty' name */
4013                  Swig_symbol_setscopename("    ");
4014                }
4015                Namespaceprefix = 0;
4016              } interface RBRACE {
4017                $$ = $4;
4018                set_nodeType($$,"namespace");
4019                Setattr($$,"unnamed","1");
4020                Setattr($$,"symtab", Swig_symbol_popscope());
4021                Swig_symbol_setscope($1);
4022                Delete(Namespaceprefix);
4023                Namespaceprefix = Swig_symbol_qualifiedscopename(0);
4024                add_symbols($$);
4025              }
4026              | NAMESPACE ID EQUAL idcolon SEMI {
4027                /* Namespace alias */
4028                Node *n;
4029                $$ = new_node("namespace");
4030                Setattr($$,"name",$2);
4031                Setattr($$,"alias",$4);
4032                n = Swig_symbol_clookup($4,0);
4033                if (!n) {
4034                  Swig_error(cparse_file, cparse_line, "Unknown namespace '%s'\n", $4);
4035                  $$ = 0;
4036                } else {
4037                  if (Strcmp(nodeType(n),"namespace") != 0) {
4038                    Swig_error(cparse_file, cparse_line, "'%s' is not a namespace\n",$4);
4039                    $$ = 0;
4040                  } else {
4041                    while (Getattr(n,"alias")) {
4042                      n = Getattr(n,"namespace");
4043                    }
4044                    Setattr($$,"namespace",n);
4045                    add_symbols($$);
4046                    /* Set up a scope alias */
4047                    Swig_symbol_alias($2,Getattr(n,"symtab"));
4048                  }
4049                }
4050              }
4051              ;
4052
4053 cpp_members  : cpp_member cpp_members {
4054                    $$ = $1;
4055                    /* Insert cpp_member (including any siblings) to the front of the cpp_members linked list */
4056                    if ($$) {
4057                      Node *p = $$;
4058                      Node *pp =0;
4059                      while (p) {
4060                        pp = p;
4061                        p = nextSibling(p);
4062                      }
4063                      set_nextSibling(pp,$2);
4064                    } else {
4065                      $$ = $2;
4066                    }
4067              }
4068              | EXTEND LBRACE { 
4069                   if (cplus_mode != CPLUS_PUBLIC) {
4070                      Swig_error(cparse_file,cparse_line,"%%extend can only be used in a public section\n");
4071                   }
4072              } cpp_members RBRACE cpp_members {
4073                $$ = new_node("extend");
4074                tag_nodes($4,"feature:extend",(char*) "1");
4075                appendChild($$,$4);
4076                set_nextSibling($$,$6);
4077              }
4078              | include_directive { $$ = $1; }
4079              | empty { $$ = 0;}
4080              | error {
4081                int start_line = cparse_line;
4082                skip_decl();
4083                Swig_error(cparse_file,start_line,"Syntax error in input(3).\n");
4084                exit(1);
4085                } cpp_members { 
4086                  $$ = $3;
4087              }
4088              ;
4089
4090 /* ======================================================================
4091  *                         C++ Class members
4092  * ====================================================================== */
4093
4094 /* A class member.  May be data or a function. Static or virtual as well */
4095
4096 cpp_member   : c_declaration { $$ = $1; }
4097              | cpp_constructor_decl { 
4098                  $$ = $1; 
4099                  if (extendmode) {
4100                    String *symname;
4101                    symname= make_name($$,Getattr($$,"name"), Getattr($$,"decl"));
4102                    if (Strcmp(symname,Getattr($$,"name")) == 0) {
4103                      /* No renaming operation.  Set name to class name */
4104                      Delete(yyrename);
4105                      yyrename = NewString(Getattr(current_class,"sym:name"));
4106                    } else {
4107                      Delete(yyrename);
4108                      yyrename = symname;
4109                    }
4110                  }
4111                  add_symbols($$);
4112                  default_arguments($$);
4113              }
4114              | cpp_destructor_decl { $$ = $1; }
4115              | cpp_protection_decl { $$ = $1; }
4116              | cpp_swig_directive { $$ = $1; }
4117              | cpp_conversion_operator { $$ = $1; }
4118              | cpp_forward_class_decl { $$ = $1; }
4119              | cpp_nested { $$ = $1; }
4120              | storage_class idcolon SEMI { $$ = 0; }
4121              | cpp_using_decl { $$ = $1; }
4122              | cpp_template_decl { $$ = $1; }
4123              | cpp_catch_decl { $$ = 0; }
4124              | template_directive { $$ = $1; }
4125              | warn_directive { $$ = $1; }
4126              | anonymous_bitfield { $$ = 0; }
4127              | fragment_directive {$$ = $1; }
4128              | types_directive {$$ = $1; }
4129              | SEMI { $$ = 0; }
4130              ;
4131
4132 /* Possibly a constructor */
4133 /* Note: the use of 'type' is here to resolve a shift-reduce conflict.  For example:
4134             typedef Foo ();
4135             typedef Foo (*ptr)();
4136 */
4137   
4138 cpp_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end {
4139               if (Classprefix) {
4140                  SwigType *decl = NewStringEmpty();
4141                  $$ = new_node("constructor");
4142                  Setattr($$,"storage",$1);
4143                  Setattr($$,"name",$2);
4144                  Setattr($$,"parms",$4);
4145                  SwigType_add_function(decl,$4);
4146                  Setattr($$,"decl",decl);
4147                  Setattr($$,"throws",$6.throws);
4148                  Setattr($$,"throw",$6.throwf);
4149                  if (Len(scanner_ccode)) {
4150                    String *code = Copy(scanner_ccode);
4151                    Setattr($$,"code",code);
4152                    Delete(code);
4153                  }
4154                  SetFlag($$,"feature:new");
4155               } else {
4156                 $$ = 0;
4157               }
4158               }
4159               ;
4160
4161 /* A destructor (hopefully) */
4162
4163 cpp_destructor_decl : NOT idtemplate LPAREN parms RPAREN cpp_end {
4164                String *name = NewStringf("%s",$2);
4165                if (*(Char(name)) != '~') Insert(name,0,"~");
4166                $$ = new_node("destructor");
4167                Setattr($$,"name",name);
4168                Delete(name);
4169                if (Len(scanner_ccode)) {
4170                  String *code = Copy(scanner_ccode);
4171                  Setattr($$,"code",code);
4172                  Delete(code);
4173                }
4174                {
4175                  String *decl = NewStringEmpty();
4176                  SwigType_add_function(decl,$4);
4177                  Setattr($$,"decl",decl);
4178                  Delete(decl);
4179                }
4180                Setattr($$,"throws",$6.throws);
4181                Setattr($$,"throw",$6.throwf);
4182                add_symbols($$);
4183               }
4184
4185 /* A virtual destructor */
4186
4187               | VIRTUAL NOT idtemplate LPAREN parms RPAREN cpp_vend {
4188                 String *name;
4189                 char *c = 0;
4190                 $$ = new_node("destructor");
4191                /* Check for template names.  If the class is a template
4192                   and the constructor is missing the template part, we
4193                   add it */
4194                 if (Classprefix) {
4195                   c = strchr(Char(Classprefix),'<');
4196                   if (c && !Strchr($3,'<')) {
4197                     $3 = NewStringf("%s%s",$3,c);
4198                   }
4199                 }
4200                 Setattr($$,"storage","virtual");
4201                 name = NewStringf("%s",$3);
4202                 if (*(Char(name)) != '~') Insert(name,0,"~");
4203                 Setattr($$,"name",name);
4204                 Delete(name);
4205                 Setattr($$,"throws",$7.throws);
4206                 Setattr($$,"throw",$7.throwf);
4207                 if ($7.val) {
4208                   Setattr($$,"value","0");
4209                 }
4210                 if (Len(scanner_ccode)) {
4211                   String *code = Copy(scanner_ccode);
4212                   Setattr($$,"code",code);
4213                   Delete(code);
4214                 }
4215                 {
4216                   String *decl = NewStringEmpty();
4217                   SwigType_add_function(decl,$5);
4218                   Setattr($$,"decl",decl);
4219                   Delete(decl);
4220                 }
4221
4222                 add_symbols($$);
4223               }
4224               ;
4225
4226
4227 /* C++ type conversion operator */
4228 cpp_conversion_operator : storage_class COPERATOR type pointer LPAREN parms RPAREN cpp_vend {
4229                  $$ = new_node("cdecl");
4230                  Setattr($$,"type",$3);
4231                  Setattr($$,"name",$2);
4232                  Setattr($$,"storage",$1);
4233
4234                  SwigType_add_function($4,$6);
4235                  if ($8.qualifier) {
4236                    SwigType_push($4,$8.qualifier);
4237                  }
4238                  Setattr($$,"decl",$4);
4239                  Setattr($$,"parms",$6);
4240                  Setattr($$,"conversion_operator","1");
4241                  add_symbols($$);
4242               }
4243                | storage_class COPERATOR type AND LPAREN parms RPAREN cpp_vend {
4244                  SwigType *decl;
4245                  $$ = new_node("cdecl");
4246                  Setattr($$,"type",$3);
4247                  Setattr($$,"name",$2);
4248                  Setattr($$,"storage",$1);
4249                  decl = NewStringEmpty();
4250                  SwigType_add_reference(decl);
4251                  SwigType_add_function(decl,$6);
4252                  if ($8.qualifier) {
4253                    SwigType_push(decl,$8.qualifier);
4254                  }
4255                  Setattr($$,"decl",decl);
4256                  Setattr($$,"parms",$6);
4257                  Setattr($$,"conversion_operator","1");
4258                  add_symbols($$);
4259                }
4260
4261               | storage_class COPERATOR type LPAREN parms RPAREN cpp_vend {
4262                 String *t = NewStringEmpty();
4263                 $$ = new_node("cdecl");
4264                 Setattr($$,"type",$3);
4265                 Setattr($$,"name",$2);
4266                  Setattr($$,"storage",$1);
4267                 SwigType_add_function(t,$5);
4268                 if ($7.qualifier) {
4269                   SwigType_push(t,$7.qualifier);
4270                 }
4271                 Setattr($$,"decl",t);
4272                 Setattr($$,"parms",$5);
4273                 Setattr($$,"conversion_operator","1");
4274                 add_symbols($$);
4275               }
4276               ;
4277
4278 /* isolated catch clause. */
4279
4280 cpp_catch_decl : CATCH LPAREN parms RPAREN LBRACE {
4281                  skip_balanced('{','}');
4282                  $$ = 0;
4283                }
4284                ;
4285
4286 /* public: */
4287 cpp_protection_decl : PUBLIC COLON { 
4288                 $$ = new_node("access");
4289                 Setattr($$,"kind","public");
4290                 cplus_mode = CPLUS_PUBLIC;
4291               }
4292
4293 /* private: */
4294               | PRIVATE COLON { 
4295                 $$ = new_node("access");
4296                 Setattr($$,"kind","private");
4297                 cplus_mode = CPLUS_PRIVATE;
4298               }
4299
4300 /* protected: */
4301
4302               | PROTECTED COLON { 
4303                 $$ = new_node("access");
4304                 Setattr($$,"kind","protected");
4305                 cplus_mode = CPLUS_PROTECTED;
4306               }
4307               ;
4308
4309
4310 /* ----------------------------------------------------------------------
4311    Nested structure.    This is a sick "hack".   If we encounter
4312    a nested structure, we're going to grab the text of its definition and
4313    feed it back into the scanner.  In the meantime, we need to grab
4314    variable declaration information and generate the associated wrapper
4315    code later.  Yikes!
4316
4317    This really only works in a limited sense.   Since we use the
4318    code attached to the nested class to generate both C/C++ code,
4319    it can't have any SWIG directives in it.  It also needs to be parsable
4320    by SWIG or this whole thing is going to puke.
4321    ---------------------------------------------------------------------- */
4322
4323 /* A struct sname { } id;  declaration */
4324
4325 cpp_nested :   storage_class cpptype ID LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}');
4326               } nested_decl SEMI {
4327                 $$ = 0;
4328                 if (cplus_mode == CPLUS_PUBLIC) {
4329                   if ($6.id && strcmp($2, "class") != 0) {
4330                     Nested *n = (Nested *) malloc(sizeof(Nested));
4331                     n->code = NewStringEmpty();
4332                     Printv(n->code, "typedef ", $2, " ",
4333                            Char(scanner_ccode), " $classname_", $6.id, ";\n", NIL);
4334
4335                     n->name = Swig_copy_string($6.id);
4336                     n->line = cparse_start_line;
4337                     n->type = NewStringEmpty();
4338                     n->kind = $2;
4339                     n->unnamed = 0;
4340                     SwigType_push(n->type, $6.type);
4341                     n->next = 0;
4342                     add_nested(n);
4343                   } else {
4344                     Swig_warning(WARN_PARSE_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", $2);
4345                     if (strcmp($2, "class") == 0) {
4346                       /* For now, just treat the nested class as a forward
4347                        * declaration (SF bug #909387). */
4348                       $$ = new_node("classforward");
4349                       Setfile($$,cparse_file);
4350                       Setline($$,cparse_line);
4351                       Setattr($$,"kind",$2);
4352                       Setattr($$,"name",$3);
4353                       Setattr($$,"sym:weak", "1");
4354                       add_symbols($$);
4355                     }
4356                   }
4357                 }
4358               }
4359 /* A struct { } id;  declaration */
4360               | storage_class cpptype LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}');
4361               } nested_decl SEMI {
4362                 $$ = 0;
4363                 if (cplus_mode == CPLUS_PUBLIC) {
4364                   if (strcmp($2,"class") == 0) {
4365                     Swig_warning(WARN_PARSE_NESTED_CLASS,cparse_file, cparse_line,"Nested class not currently supported (ignored)\n");
4366                     /* Generate some code for a new class */
4367                   } else if ($5.id) {
4368                     /* Generate some code for a new class */
4369                     Nested *n = (Nested *) malloc(sizeof(Nested));
4370                     n->code = NewStringEmpty();
4371                     Printv(n->code, "typedef ", $2, " " ,
4372                             Char(scanner_ccode), " $classname_", $5.id, ";\n",NIL);
4373                     n->name = Swig_copy_string($5.id);
4374                     n->line = cparse_start_line;
4375                     n->type = NewStringEmpty();
4376                     n->kind = $2;
4377                     n->unnamed = 1;
4378                     SwigType_push(n->type,$5.type);
4379                     n->next = 0;
4380                     add_nested(n);
4381                   } else {
4382                     Swig_warning(WARN_PARSE_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", $2);
4383                   }
4384                 }
4385               }
4386 /* A  'class name : base_list { };'  declaration, always ignored */
4387 /*****
4388      This fixes derived_nested.i, but it adds one shift/reduce. Anyway,
4389      we are waiting for the nested class support.
4390  *****/
4391               | storage_class cpptype idcolon COLON base_list LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}');
4392               } SEMI {
4393                 $$ = 0;
4394                 if (cplus_mode == CPLUS_PUBLIC) {
4395                   Swig_warning(WARN_PARSE_NESTED_CLASS,cparse_file, cparse_line,"Nested class not currently supported (ignored)\n");
4396                 }
4397               }
4398 /*
4399               | TEMPLATE LESSTHAN template_parms GREATERTHAN cpptype idcolon LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}');
4400               } SEMI {
4401                 $$ = 0;
4402                 if (cplus_mode == CPLUS_PUBLIC) {
4403                   Swig_warning(WARN_PARSE_NESTED_CLASS,cparse_file, cparse_line,"Nested class not currently supported (ignored)\n");
4404                 }
4405               }
4406 */
4407               ;
4408
4409 nested_decl   : declarator { $$ = $1;}
4410               | empty { $$.id = 0; }
4411               ;
4412
4413
4414 /* These directives can be included inside a class definition */
4415
4416 cpp_swig_directive: pragma_directive { $$ = $1; }
4417
4418 /* A constant (includes #defines) inside a class */
4419              | constant_directive { $$ = $1; }
4420
4421 /* This is the new style rename */
4422
4423              | name_directive { $$ = $1; }
4424
4425 /* rename directive */
4426              | rename_directive { $$ = $1; }
4427              | feature_directive { $$ = $1; }
4428              | varargs_directive { $$ = $1; }
4429              | insert_directive { $$ = $1; }
4430              | typemap_directive { $$ = $1; }
4431              | apply_directive { $$ = $1; }
4432              | clear_directive { $$ = $1; }
4433              | echo_directive { $$ = $1; }
4434              ;
4435
4436 cpp_end        : cpp_const SEMI {
4437                     Clear(scanner_ccode);
4438                     $$.throws = $1.throws;
4439                     $$.throwf = $1.throwf;
4440                }
4441                | cpp_const LBRACE { 
4442                     skip_balanced('{','}'); 
4443                     $$.throws = $1.throws;
4444                     $$.throwf = $1.throwf;
4445                }
4446                ;
4447
4448 cpp_vend       : cpp_const SEMI { 
4449                      Clear(scanner_ccode);
4450                      $$.val = 0;
4451                      $$.qualifier = $1.qualifier;
4452                      $$.bitfield = 0;
4453                      $$.throws = $1.throws;
4454                      $$.throwf = $1.throwf;
4455                 }
4456                | cpp_const EQUAL definetype SEMI { 
4457                      Clear(scanner_ccode);
4458                      $$.val = $3.val;
4459                      $$.qualifier = $1.qualifier;
4460                      $$.bitfield = 0;
4461                      $$.throws = $1.throws; 
4462                      $$.throwf = $1.throwf; 
4463                }
4464                | cpp_const LBRACE { 
4465                      skip_balanced('{','}');
4466                      $$.val = 0;
4467                      $$.qualifier = $1.qualifier;
4468                      $$.bitfield = 0;
4469                      $$.throws = $1.throws; 
4470                      $$.throwf = $1.throwf; 
4471                }
4472                ;
4473
4474
4475 anonymous_bitfield :  storage_class type COLON expr SEMI { };
4476
4477 /* ====================================================================== 
4478  *                       PRIMITIVES
4479  * ====================================================================== */
4480
4481 storage_class  : EXTERN { $$ = "extern"; }
4482                | EXTERN string { 
4483                    if (strcmp($2,"C") == 0) {
4484                      $$ = "externc";
4485                    } else {
4486                      Swig_warning(WARN_PARSE_UNDEFINED_EXTERN,cparse_file, cparse_line,"Unrecognized extern type \"%s\".\n", $2);
4487                      $$ = 0;
4488                    }
4489                }
4490                | STATIC { $$ = "static"; }
4491                | TYPEDEF { $$ = "typedef"; }
4492                | VIRTUAL { $$ = "virtual"; }
4493                | FRIEND { $$ = "friend"; }
4494                | EXPLICIT { $$ = "explicit"; }
4495                | empty { $$ = 0; }
4496                ;
4497
4498 /* ------------------------------------------------------------------------------
4499    Function parameter lists
4500    ------------------------------------------------------------------------------ */
4501
4502 parms          : rawparms {
4503                  Parm *p;
4504                  $$ = $1;
4505                  p = $1;
4506                  while (p) {
4507                    Replace(Getattr(p,"type"),"typename ", "", DOH_REPLACE_ANY);
4508                    p = nextSibling(p);
4509                  }
4510                }
4511                ;
4512
4513 rawparms          : parm ptail {
4514                   set_nextSibling($1,$2);
4515                   $$ = $1;
4516                 }
4517                | empty { $$ = 0; }
4518                ;
4519
4520 ptail          : COMMA parm ptail {
4521                  set_nextSibling($2,$3);
4522                  $$ = $2;
4523                 }
4524                | empty { $$ = 0; }
4525                ;
4526
4527
4528 parm           : rawtype parameter_declarator {
4529                    SwigType_push($1,$2.type);
4530                    $$ = NewParm($1,$2.id);
4531                    Setfile($$,cparse_file);
4532                    Setline($$,cparse_line);
4533                    if ($2.defarg) {
4534                      Setattr($$,"value",$2.defarg);
4535                    }
4536                 }
4537
4538                 | TEMPLATE LESSTHAN cpptype GREATERTHAN cpptype idcolon def_args {
4539                   $$ = NewParm(NewStringf("template<class> %s %s", $5,$6), 0);
4540                   Setfile($$,cparse_file);
4541                   Setline($$,cparse_line);
4542                   if ($7.val) {
4543                     Setattr($$,"value",$7.val);
4544                   }
4545                 }
4546                 | PERIOD PERIOD PERIOD {
4547                   SwigType *t = NewString("v(...)");
4548                   $$ = NewParm(t, 0);
4549                   Setfile($$,cparse_file);
4550                   Setline($$,cparse_line);
4551                 }
4552                 ;
4553
4554 valparms        : rawvalparms {
4555                  Parm *p;
4556                  $$ = $1;
4557                  p = $1;
4558                  while (p) {
4559                    if (Getattr(p,"type")) {
4560                      Replace(Getattr(p,"type"),"typename ", "", DOH_REPLACE_ANY);
4561                    }
4562                    p = nextSibling(p);
4563                  }
4564                }
4565                ;
4566
4567 rawvalparms     : valparm valptail {
4568                   set_nextSibling($1,$2);
4569                   $$ = $1;
4570                 }
4571                | empty { $$ = 0; }
4572                ;
4573
4574 valptail       : COMMA valparm valptail {
4575                  set_nextSibling($2,$3);
4576                  $$ = $2;
4577                 }
4578                | empty { $$ = 0; }
4579                ;
4580
4581
4582 valparm        : parm {
4583                   $$ = $1;
4584                   {
4585                     /* We need to make a possible adjustment for integer parameters. */
4586                     SwigType *type;
4587                     Node     *n = 0;
4588
4589                     while (!n) {
4590                       type = Getattr($1,"type");
4591                       n = Swig_symbol_clookup(type,0);     /* See if we can find a node that matches the typename */
4592                       if ((n) && (Strcmp(nodeType(n),"cdecl") == 0)) {
4593                         SwigType *decl = Getattr(n,"decl");
4594                         if (!SwigType_isfunction(decl)) {
4595                           String *value = Getattr(n,"value");
4596                           if (value) {
4597                             String *v = Copy(value);
4598                             Setattr($1,"type",v);
4599                             Delete(v);
4600                             n = 0;
4601                           }
4602                         }
4603                       } else {
4604                         break;
4605                       }
4606                     }
4607                   }
4608
4609                }
4610                | valexpr {
4611                   $$ = NewParm(0,0);
4612                   Setfile($$,cparse_file);
4613                   Setline($$,cparse_line);
4614                   Setattr($$,"value",$1.val);
4615                }
4616                ;
4617
4618 def_args       : EQUAL definetype { 
4619                   $$ = $2; 
4620                   if ($2.type == T_ERROR) {
4621                     Swig_warning(WARN_PARSE_BAD_DEFAULT,cparse_file, cparse_line, "Can't set default argument (ignored)\n");
4622                     $$.val = 0;
4623                     $$.rawval = 0;
4624                     $$.bitfield = 0;
4625                     $$.throws = 0;
4626                     $$.throwf = 0;
4627                   }
4628                }
4629                | EQUAL definetype LBRACKET expr RBRACKET { 
4630                   $$ = $2;
4631                   if ($2.type == T_ERROR) {
4632                     Swig_warning(WARN_PARSE_BAD_DEFAULT,cparse_file, cparse_line, "Can't set default argument (ignored)\n");
4633                     $$ = $2;
4634                     $$.val = 0;
4635                     $$.rawval = 0;
4636                     $$.bitfield = 0;
4637                     $$.throws = 0;
4638                     $$.throwf = 0;
4639                   } else {
4640                     $$.val = NewStringf("%s[%s]",$2.val,$4.val); 
4641                   }               
4642                }
4643                | EQUAL LBRACE {
4644                  skip_balanced('{','}');
4645                  $$.val = 0;
4646                  $$.rawval = 0;
4647                  $$.type = T_INT;
4648                  $$.bitfield = 0;
4649                  $$.throws = 0;
4650                  $$.throwf = 0;
4651                }
4652                | COLON expr { 
4653                  $$.val = 0;
4654                  $$.rawval = 0;
4655                  $$.type = 0;
4656                  $$.bitfield = $2.val;
4657                  $$.throws = 0;
4658                  $$.throwf = 0;
4659                }
4660                | empty {
4661                  $$.val = 0;
4662                  $$.rawval = 0;
4663                  $$.type = T_INT;
4664                  $$.bitfield = 0;
4665                  $$.throws = 0;
4666                  $$.throwf = 0;
4667                }
4668                ;
4669
4670 parameter_declarator : declarator def_args {
4671                  $$ = $1;
4672                  $$.defarg = $2.rawval ? $2.rawval : $2.val;
4673             }
4674             | abstract_declarator def_args {
4675               $$ = $1;
4676               $$.defarg = $2.rawval ? $2.rawval : $2.val;
4677             }
4678             | def_args {
4679               $$.type = 0;
4680               $$.id = 0;
4681               $$.defarg = $1.rawval ? $1.rawval : $1.val;
4682             }
4683             ;
4684
4685 typemap_parameter_declarator : declarator {
4686                  $$ = $1;
4687                  if (SwigType_isfunction($1.type)) {
4688                    Delete(SwigType_pop_function($1.type));
4689                  } else if (SwigType_isarray($1.type)) {
4690                    SwigType *ta = SwigType_pop_arrays($1.type);
4691                    if (SwigType_isfunction($1.type)) {
4692                      Delete(SwigType_pop_function($1.type));
4693                    } else {
4694                      $$.parms = 0;
4695                    }
4696                    SwigType_push($1.type,ta);
4697                    Delete(ta);
4698                  } else {
4699                    $$.parms = 0;
4700                  }
4701             }
4702             | abstract_declarator {
4703               $$ = $1;
4704               if (SwigType_isfunction($1.type)) {
4705                 Delete(SwigType_pop_function($1.type));
4706               } else if (SwigType_isarray($1.type)) {
4707                 SwigType *ta = SwigType_pop_arrays($1.type);
4708                 if (SwigType_isfunction($1.type)) {
4709                   Delete(SwigType_pop_function($1.type));
4710                 } else {
4711                   $$.parms = 0;
4712                 }
4713                 SwigType_push($1.type,ta);
4714                 Delete(ta);
4715               } else {
4716                 $$.parms = 0;
4717               }
4718             }
4719             | empty {
4720               $$.type = 0;
4721               $$.id = 0;
4722               $$.parms = 0;
4723               }
4724             ;
4725
4726
4727 declarator :  pointer notso_direct_declarator {
4728               $$ = $2;
4729               if ($$.type) {
4730                 SwigType_push($1,$$.type);
4731                 Delete($$.type);
4732               }
4733               $$.type = $1;
4734            }
4735            | pointer AND notso_direct_declarator {
4736               $$ = $3;
4737               SwigType_add_reference($1);
4738               if ($$.type) {
4739                 SwigType_push($1,$$.type);
4740                 Delete($$.type);
4741               }
4742               $$.type = $1;
4743            }
4744            | direct_declarator {
4745               $$ = $1;
4746               if (!$$.type) $$.type = NewStringEmpty();
4747            }
4748            | AND notso_direct_declarator { 
4749              $$ = $2;
4750              $$.type = NewStringEmpty();
4751              SwigType_add_reference($$.type);
4752              if ($2.type) {
4753                SwigType_push($$.type,$2.type);
4754                Delete($2.type);
4755              }
4756            }
4757            | idcolon DSTAR notso_direct_declarator { 
4758              SwigType *t = NewStringEmpty();
4759
4760              $$ = $3;
4761              SwigType_add_memberpointer(t,$1);
4762              if ($$.type) {
4763                SwigType_push(t,$$.type);
4764                Delete($$.type);
4765              }
4766              $$.type = t;
4767              } 
4768            | pointer idcolon DSTAR notso_direct_declarator { 
4769              SwigType *t = NewStringEmpty();
4770              $$ = $4;
4771              SwigType_add_memberpointer(t,$2);
4772              SwigType_push($1,t);
4773              if ($$.type) {
4774                SwigType_push($1,$$.type);
4775                Delete($$.type);
4776              }
4777              $$.type = $1;
4778              Delete(t);
4779            }
4780            | pointer idcolon DSTAR AND notso_direct_declarator { 
4781              $$ = $5;
4782              SwigType_add_memberpointer($1,$2);
4783              SwigType_add_reference($1);
4784              if ($$.type) {
4785                SwigType_push($1,$$.type);
4786                Delete($$.type);
4787              }
4788              $$.type = $1;
4789            }
4790            | idcolon DSTAR AND notso_direct_declarator { 
4791              SwigType *t = NewStringEmpty();
4792              $$ = $4;
4793              SwigType_add_memberpointer(t,$1);
4794              SwigType_add_reference(t);
4795              if ($$.type) {
4796                SwigType_push(t,$$.type);
4797                Delete($$.type);
4798              } 
4799              $$.type = t;
4800            }
4801            ;
4802
4803 notso_direct_declarator : idcolon {
4804                 /* Note: This is non-standard C.  Template declarator is allowed to follow an identifier */
4805                  $$.id = Char($1);
4806                  $$.type = 0;
4807                  $$.parms = 0;
4808                  $$.have_parms = 0;
4809                   }
4810                   | NOT idcolon {
4811                   $$.id = Char(NewStringf("~%s",$2));
4812                   $$.type = 0;
4813                   $$.parms = 0;
4814                   $$.have_parms = 0;
4815                   }
4816
4817 /* This generate a shift-reduce conflict with constructors */
4818                  | LPAREN idcolon RPAREN {
4819                   $$.id = Char($2);
4820                   $$.type = 0;
4821                   $$.parms = 0;
4822                   $$.have_parms = 0;
4823                   }
4824
4825 /*
4826                   | LPAREN AND idcolon RPAREN {
4827                      $$.id = Char($3);
4828                      $$.type = 0;
4829                      $$.parms = 0;
4830                      $$.have_parms = 0;
4831                   }
4832 */
4833 /* Technically, this should be LPAREN declarator RPAREN, but we get reduce/reduce conflicts */
4834                   | LPAREN pointer notso_direct_declarator RPAREN {
4835                     $$ = $3;
4836                     if ($$.type) {
4837                       SwigType_push($2,$$.type);
4838                       Delete($$.type);
4839                     }
4840                     $$.type = $2;
4841                   }
4842                   | LPAREN idcolon DSTAR notso_direct_declarator RPAREN {
4843                     SwigType *t;
4844                     $$ = $4;
4845                     t = NewStringEmpty();
4846                     SwigType_add_memberpointer(t,$2);
4847                     if ($$.type) {
4848                       SwigType_push(t,$$.type);
4849                       Delete($$.type);
4850                     }
4851                     $$.type = t;
4852                     }
4853                   | notso_direct_declarator LBRACKET RBRACKET { 
4854                     SwigType *t;
4855                     $$ = $1;
4856                     t = NewStringEmpty();
4857                     SwigType_add_array(t,(char*)"");
4858                     if ($$.type) {
4859                       SwigType_push(t,$$.type);
4860                       Delete($$.type);
4861                     }
4862                     $$.type = t;
4863                   }
4864                   | notso_direct_declarator LBRACKET expr RBRACKET { 
4865                     SwigType *t;
4866                     $$ = $1;
4867                     t = NewStringEmpty();
4868                     SwigType_add_array(t,$3.val);
4869                     if ($$.type) {
4870                       SwigType_push(t,$$.type);
4871                       Delete($$.type);
4872                     }
4873                     $$.type = t;
4874                   }
4875                   | notso_direct_declarator LPAREN parms RPAREN {
4876                     SwigType *t;
4877                     $$ = $1;
4878                     t = NewStringEmpty();
4879                     SwigType_add_function(t,$3);
4880                     if (!$$.have_parms) {
4881                       $$.parms = $3;
4882                       $$.have_parms = 1;
4883                     }
4884                     if (!$$.type) {
4885                       $$.type = t;
4886                     } else {
4887                       SwigType_push(t, $$.type);
4888                       Delete($$.type);
4889                       $$.type = t;
4890                     }
4891                   }
4892                   ;
4893
4894 direct_declarator : idcolon {
4895                 /* Note: This is non-standard C.  Template declarator is allowed to follow an identifier */
4896                  $$.id = Char($1);
4897                  $$.type = 0;
4898                  $$.parms = 0;
4899                  $$.have_parms = 0;
4900                   }
4901
4902                   | NOT idcolon {
4903                   $$.id = Char(NewStringf("~%s",$2));
4904                   $$.type = 0;
4905                   $$.parms = 0;
4906                   $$.have_parms = 0;
4907                   }
4908
4909 /* This generate a shift-reduce conflict with constructors */
4910 /*
4911                   | LPAREN idcolon RPAREN {
4912                   $$.id = Char($2);
4913                   $$.type = 0;
4914                   $$.parms = 0;
4915                   $$.have_parms = 0;
4916                   }
4917 */
4918 /* Technically, this should be LPAREN declarator RPAREN, but we get reduce/reduce conflicts */
4919                   | LPAREN pointer direct_declarator RPAREN {
4920                     $$ = $3;
4921                     if ($$.type) {
4922                       SwigType_push($2,$$.type);
4923                       Delete($$.type);
4924                     }
4925                     $$.type = $2;
4926                   }
4927                   | LPAREN AND direct_declarator RPAREN {
4928                     $$ = $3;
4929                     if (!$$.type) {
4930                       $$.type = NewStringEmpty();
4931                     }
4932                     SwigType_add_reference($$.type);
4933                   }
4934                   | LPAREN idcolon DSTAR direct_declarator RPAREN {
4935                     SwigType *t;
4936                     $$ = $4;
4937                     t = NewStringEmpty();
4938                     SwigType_add_memberpointer(t,$2);
4939                     if ($$.type) {
4940                       SwigType_push(t,$$.type);
4941                       Delete($$.type);
4942                     }
4943                     $$.type = t;
4944                     }
4945                   | direct_declarator LBRACKET RBRACKET { 
4946                     SwigType *t;
4947                     $$ = $1;
4948                     t = NewStringEmpty();
4949                     SwigType_add_array(t,(char*)"");
4950                     if ($$.type) {
4951                       SwigType_push(t,$$.type);
4952                       Delete($$.type);
4953                     }
4954                     $$.type = t;
4955                   }
4956                   | direct_declarator LBRACKET expr RBRACKET { 
4957                     SwigType *t;
4958                     $$ = $1;
4959                     t = NewStringEmpty();
4960                     SwigType_add_array(t,$3.val);
4961                     if ($$.type) {
4962                       SwigType_push(t,$$.type);
4963                       Delete($$.type);
4964                     }
4965                     $$.type = t;
4966                   }
4967                   | direct_declarator LPAREN parms RPAREN {
4968                     SwigType *t;
4969                     $$ = $1;
4970                     t = NewStringEmpty();
4971                     SwigType_add_function(t,$3);
4972                     if (!$$.have_parms) {
4973                       $$.parms = $3;
4974                       $$.have_parms = 1;
4975                     }
4976                     if (!$$.type) {
4977                       $$.type = t;
4978                     } else {
4979                       SwigType_push(t, $$.type);
4980                       Delete($$.type);
4981                       $$.type = t;
4982                     }
4983                   }
4984                   ;
4985
4986 abstract_declarator : pointer {
4987                     $$.type = $1;
4988                     $$.id = 0;
4989                     $$.parms = 0;
4990                     $$.have_parms = 0;
4991                   }
4992                   | pointer direct_abstract_declarator { 
4993                      $$ = $2;
4994                      SwigType_push($1,$2.type);
4995                      $$.type = $1;
4996                      Delete($2.type);
4997                   }
4998                   | pointer AND {
4999                     $$.type = $1;
5000                     SwigType_add_reference($$.type);
5001                     $$.id = 0;
5002                     $$.parms = 0;
5003                     $$.have_parms = 0;
5004                   }
5005                   | pointer AND direct_abstract_declarator {
5006                     $$ = $3;
5007                     SwigType_add_reference($1);
5008                     if ($$.type) {
5009                       SwigType_push($1,$$.type);
5010                       Delete($$.type);
5011                     }
5012                     $$.type = $1;
5013                   }
5014                   | direct_abstract_declarator {
5015                     $$ = $1;
5016                   }
5017                   | AND direct_abstract_declarator {
5018                     $$ = $2;
5019                     $$.type = NewStringEmpty();
5020                     SwigType_add_reference($$.type);
5021                     if ($2.type) {
5022                       SwigType_push($$.type,$2.type);
5023                       Delete($2.type);
5024                     }
5025                   }
5026                   | AND { 
5027                     $$.id = 0;
5028                     $$.parms = 0;
5029                     $$.have_parms = 0;
5030                     $$.type = NewStringEmpty();
5031                     SwigType_add_reference($$.type);
5032                   }
5033                   | idcolon DSTAR { 
5034                     $$.type = NewStringEmpty();
5035                     SwigType_add_memberpointer($$.type,$1);
5036                     $$.id = 0;
5037                     $$.parms = 0;
5038                     $$.have_parms = 0;
5039                   }
5040                   | pointer idcolon DSTAR { 
5041                     SwigType *t = NewStringEmpty();
5042                     $$.type = $1;
5043                     $$.id = 0;
5044                     $$.parms = 0;
5045                     $$.have_parms = 0;
5046                     SwigType_add_memberpointer(t,$2);
5047                     SwigType_push($$.type,t);
5048                     Delete(t);
5049                   }
5050                   | pointer idcolon DSTAR direct_abstract_declarator { 
5051                     $$ = $4;
5052                     SwigType_add_memberpointer($1,$2);
5053                     if ($$.type) {
5054                       SwigType_push($1,$$.type);
5055                       Delete($$.type);
5056                     }
5057                     $$.type = $1;
5058                   }
5059                   ;
5060
5061 direct_abstract_declarator : direct_abstract_declarator LBRACKET RBRACKET { 
5062                     SwigType *t;
5063                     $$ = $1;
5064                     t = NewStringEmpty();
5065                     SwigType_add_array(t,(char*)"");
5066                     if ($$.type) {
5067                       SwigType_push(t,$$.type);
5068                       Delete($$.type);
5069                     }
5070                     $$.type = t;
5071                   }
5072                   | direct_abstract_declarator LBRACKET expr RBRACKET { 
5073                     SwigType *t;
5074                     $$ = $1;
5075                     t = NewStringEmpty();
5076                     SwigType_add_array(t,$3.val);
5077                     if ($$.type) {
5078                       SwigType_push(t,$$.type);
5079                       Delete($$.type);
5080                     }
5081                     $$.type = t;
5082                   }
5083                   | LBRACKET RBRACKET { 
5084                     $$.type = NewStringEmpty();
5085                     $$.id = 0;
5086                     $$.parms = 0;
5087                     $$.have_parms = 0;
5088                     SwigType_add_array($$.type,(char*)"");
5089                   }
5090                   | LBRACKET expr RBRACKET { 
5091                     $$.type = NewStringEmpty();
5092                     $$.id = 0;
5093                     $$.parms = 0;
5094                     $$.have_parms = 0;
5095                     SwigType_add_array($$.type,$2.val);
5096                   }
5097                   | LPAREN abstract_declarator RPAREN {
5098                     $$ = $2;
5099                   }
5100                   | direct_abstract_declarator LPAREN parms RPAREN {
5101                     SwigType *t;
5102                     $$ = $1;
5103                     t = NewStringEmpty();
5104                     SwigType_add_function(t,$3);
5105                     if (!$$.type) {
5106                       $$.type = t;
5107                     } else {
5108                       SwigType_push(t,$$.type);
5109                       Delete($$.type);
5110                       $$.type = t;
5111                     }
5112                     if (!$$.have_parms) {
5113                       $$.parms = $3;
5114                       $$.have_parms = 1;
5115                     }
5116                   }
5117                   | LPAREN parms RPAREN {
5118                     $$.type = NewStringEmpty();
5119                     SwigType_add_function($$.type,$2);
5120                     $$.parms = $2;
5121                     $$.have_parms = 1;
5122                     $$.id = 0;
5123                   }
5124                   ;
5125
5126
5127 pointer    : STAR type_qualifier pointer { 
5128                $$ = NewStringEmpty();
5129                SwigType_add_pointer($$);
5130                SwigType_push($$,$2);
5131                SwigType_push($$,$3);
5132                Delete($3);
5133            }
5134            | STAR pointer {
5135              $$ = NewStringEmpty();
5136              SwigType_add_pointer($$);
5137              SwigType_push($$,$2);
5138              Delete($2);
5139              } 
5140            | STAR type_qualifier { 
5141                 $$ = NewStringEmpty();  
5142                 SwigType_add_pointer($$);
5143                 SwigType_push($$,$2);
5144            }
5145            | STAR {
5146               $$ = NewStringEmpty();
5147               SwigType_add_pointer($$);
5148            }
5149            ;
5150
5151 type_qualifier : type_qualifier_raw {
5152                   $$ = NewStringEmpty();
5153                   if ($1) SwigType_add_qualifier($$,$1);
5154                }
5155                | type_qualifier_raw type_qualifier {
5156                   $$ = $2;
5157                   if ($1) SwigType_add_qualifier($$,$1);
5158                }
5159                ;
5160
5161 type_qualifier_raw :  CONST_QUAL { $$ = "const"; }
5162                    |  VOLATILE { $$ = "volatile"; }
5163                    |  REGISTER { $$ = 0; }
5164                    ;
5165
5166 /* Data type must be a built in type or an identifier for user-defined types
5167    This type can be preceded by a modifier. */
5168
5169 type            : rawtype {
5170                    $$ = $1;
5171                    Replace($$,"typename ","", DOH_REPLACE_ANY);
5172                 }
5173                 ;
5174
5175 rawtype       : type_qualifier type_right {
5176                    $$ = $2;
5177                    SwigType_push($$,$1);
5178                }
5179                | type_right { $$ = $1; }
5180                | type_right type_qualifier {
5181                   $$ = $1;
5182                   SwigType_push($$,$2);
5183                }
5184                | type_qualifier type_right type_qualifier {
5185                   $$ = $2;
5186                   SwigType_push($$,$3);
5187                   SwigType_push($$,$1);
5188                }
5189                ;
5190
5191 type_right     : primitive_type { $$ = $1;
5192                   /* Printf(stdout,"primitive = '%s'\n", $$);*/
5193                 }
5194                | TYPE_BOOL { $$ = $1; }
5195                | TYPE_VOID { $$ = $1; }
5196                | TYPE_TYPEDEF template_decl { $$ = NewStringf("%s%s",$1,$2); }
5197                | ENUM idcolon { $$ = NewStringf("enum %s", $2); }
5198                | TYPE_RAW { $$ = $1; }
5199
5200                | idcolon {
5201                   $$ = $1;
5202                }
5203                | cpptype idcolon { 
5204                  $$ = NewStringf("%s %s", $1, $2);
5205                }
5206                ;
5207
5208 primitive_type : primitive_type_list {
5209                  if (!$1.type) $1.type = NewString("int");
5210                  if ($1.us) {
5211                    $$ = NewStringf("%s %s", $1.us, $1.type);
5212                    Delete($1.us);
5213                    Delete($1.type);
5214                  } else {
5215                    $$ = $1.type;
5216                  }
5217                  if (Cmp($$,"signed int") == 0) {
5218                    Delete($$);
5219                    $$ = NewString("int");
5220                  } else if (Cmp($$,"signed long") == 0) {
5221                    Delete($$);
5222                    $$ = NewString("long");
5223                  } else if (Cmp($$,"signed short") == 0) {
5224                    Delete($$);
5225                    $$ = NewString("short");
5226                  } else if (Cmp($$,"signed long long") == 0) {
5227                    Delete($$);
5228                    $$ = NewString("long long");
5229                  }
5230                }
5231                ;
5232
5233 primitive_type_list : type_specifier { 
5234                  $$ = $1;
5235                }
5236                | type_specifier primitive_type_list {
5237                     if ($1.us && $2.us) {
5238                       Swig_error(cparse_file, cparse_line, "Extra %s specifier.\n", $2.us);
5239                     }
5240                     $$ = $2;
5241                     if ($1.us) $$.us = $1.us;
5242                     if ($1.type) {
5243                       if (!$2.type) $$.type = $1.type;
5244                       else {
5245                         int err = 0;
5246                         if ((Cmp($1.type,"long") == 0)) {
5247                           if ((Cmp($2.type,"long") == 0) || (Strncmp($2.type,"double",6) == 0)) {
5248                             $$.type = NewStringf("long %s", $2.type);
5249                           } else if (Cmp($2.type,"int") == 0) {
5250                             $$.type = $1.type;
5251                           } else {
5252                             err = 1;
5253                           }
5254                         } else if ((Cmp($1.type,"short")) == 0) {
5255                           if (Cmp($2.type,"int") == 0) {
5256                             $$.type = $1.type;
5257                           } else {
5258                             err = 1;
5259                           }
5260                         } else if (Cmp($1.type,"int") == 0) {
5261                           $$.type = $2.type;
5262                         } else if (Cmp($1.type,"double") == 0) {
5263                           if (Cmp($2.type,"long") == 0) {
5264                             $$.type = NewString("long double");
5265                           } else if (Cmp($2.type,"complex") == 0) {
5266                             $$.type = NewString("double complex");
5267                           } else {
5268                             err = 1;
5269                           }
5270                         } else if (Cmp($1.type,"float") == 0) {
5271                           if (Cmp($2.type,"complex") == 0) {
5272                             $$.type = NewString("float complex");
5273                           } else {
5274                             err = 1;
5275                           }
5276                         } else if (Cmp($1.type,"complex") == 0) {
5277                           $$.type = NewStringf("%s complex", $2.type);
5278                         } else {
5279                           err = 1;
5280                         }
5281                         if (err) {
5282                           Swig_error(cparse_file, cparse_line, "Extra %s specifier.\n", $1.type);
5283                         }
5284                       }
5285                     }
5286                }
5287                ; 
5288
5289
5290 type_specifier : TYPE_INT { 
5291                     $$.type = NewString("int");
5292                     $$.us = 0;
5293                }
5294                | TYPE_SHORT { 
5295                     $$.type = NewString("short");
5296                     $$.us = 0;
5297                 }
5298                | TYPE_LONG { 
5299                     $$.type = NewString("long");
5300                     $$.us = 0;
5301                 }
5302                | TYPE_CHAR { 
5303                     $$.type = NewString("char");
5304                     $$.us = 0;
5305                 }
5306                | TYPE_WCHAR { 
5307                     $$.type = NewString("wchar_t");
5308                     $$.us = 0;
5309                 }
5310                | TYPE_FLOAT { 
5311                     $$.type = NewString("float");
5312                     $$.us = 0;
5313                 }
5314                | TYPE_DOUBLE { 
5315                     $$.type = NewString("double");
5316                     $$.us = 0;
5317                 }
5318                | TYPE_SIGNED { 
5319                     $$.us = NewString("signed");
5320                     $$.type = 0;
5321                 }
5322                | TYPE_UNSIGNED { 
5323                     $$.us = NewString("unsigned");
5324                     $$.type = 0;
5325                 }
5326                | TYPE_COMPLEX { 
5327                     $$.type = NewString("complex");
5328                     $$.us = 0;
5329                 }
5330                | TYPE_NON_ISO_INT8 { 
5331                     $$.type = NewString("__int8");
5332                     $$.us = 0;
5333                 }
5334                | TYPE_NON_ISO_INT16 { 
5335                     $$.type = NewString("__int16");
5336                     $$.us = 0;
5337                 }
5338                | TYPE_NON_ISO_INT32 { 
5339                     $$.type = NewString("__int32");
5340                     $$.us = 0;
5341                 }
5342                | TYPE_NON_ISO_INT64 { 
5343                     $$.type = NewString("__int64");
5344                     $$.us = 0;
5345                 }
5346                ;
5347
5348 definetype     : { /* scanner_check_typedef(); */ } expr {
5349                    $$ = $2;
5350                    if ($$.type == T_STRING) {
5351                      $$.rawval = NewStringf("\"%(escape)s\"",$$.val);
5352                    } else if ($$.type != T_CHAR) {
5353                      $$.rawval = 0;
5354                    }
5355                    $$.bitfield = 0;
5356                    $$.throws = 0;
5357                    $$.throwf = 0;
5358                    scanner_ignore_typedef();
5359                 }
5360 /*
5361                 | string {
5362                    $$.val = NewString($1);
5363                    $$.rawval = NewStringf("\"%(escape)s\"",$$.val);
5364                    $$.type = T_STRING;
5365                    $$.bitfield = 0;
5366                    $$.throws = 0;
5367                    $$.throwf = 0;
5368                 }
5369 */
5370                 ;
5371
5372 /* Some stuff for handling enums */
5373
5374 ename          :  ID { $$ = $1; }
5375                |  empty { $$ = (char *) 0;}
5376                ;
5377
5378 enumlist       :  enumlist COMMA edecl { 
5379
5380                   /* Ignore if there is a trailing comma in the enum list */
5381                   if ($3) {
5382                     Node *leftSibling = Getattr($1,"_last");
5383                     if (!leftSibling) {
5384                       leftSibling=$1;
5385                     }
5386                     set_nextSibling(leftSibling,$3);
5387                     Setattr($1,"_last",$3);
5388                   }
5389                   $$ = $1;
5390                }
5391                |  edecl { 
5392                    $$ = $1; 
5393                    if ($1) {
5394                      Setattr($1,"_last",$1);
5395                    }
5396                }
5397                ;
5398
5399 edecl          :  ID {
5400                    SwigType *type = NewSwigType(T_INT);
5401                    $$ = new_node("enumitem");
5402                    Setattr($$,"name",$1);
5403                    Setattr($$,"type",type);
5404                    SetFlag($$,"feature:immutable");
5405                    Delete(type);
5406                  }
5407                  | ID EQUAL etype {
5408                    $$ = new_node("enumitem");
5409                    Setattr($$,"name",$1);
5410                    Setattr($$,"enumvalue", $3.val);
5411                    if ($3.type == T_CHAR) {
5412                      SwigType *type = NewSwigType(T_CHAR);
5413                      Setattr($$,"value",NewStringf("\'%(escape)s\'", $3.val));
5414                      Setattr($$,"type",type);
5415                      Delete(type);
5416                    } else {
5417                      SwigType *type = NewSwigType(T_INT);
5418                      Setattr($$,"value",$1);
5419                      Setattr($$,"type",type);
5420                      Delete(type);
5421                    }
5422                    SetFlag($$,"feature:immutable");
5423                  }
5424                  | empty { $$ = 0; }
5425                  ;
5426
5427 etype            : expr {
5428                    $$ = $1;
5429                    if (($$.type != T_INT) && ($$.type != T_UINT) &&
5430                        ($$.type != T_LONG) && ($$.type != T_ULONG) &&
5431                        ($$.type != T_SHORT) && ($$.type != T_USHORT) &&
5432                        ($$.type != T_SCHAR) && ($$.type != T_UCHAR) &&
5433                        ($$.type != T_CHAR)) {
5434                      Swig_error(cparse_file,cparse_line,"Type error. Expecting an int\n");
5435                    }
5436                    if ($$.type == T_CHAR) $$.type = T_INT;
5437                 }
5438                ;
5439
5440 /* Arithmetic expressions.  Used for constants, C++ templates, and other cool stuff. */
5441
5442 expr           : valexpr { $$ = $1; }
5443                | type {
5444                  Node *n;
5445                  $$.val = $1;
5446                  $$.type = T_INT;
5447                  /* Check if value is in scope */
5448                  n = Swig_symbol_clookup($1,0);
5449                  if (n) {
5450                    /* A band-aid for enum values used in expressions. */
5451                    if (Strcmp(nodeType(n),"enumitem") == 0) {
5452                      String *q = Swig_symbol_qualified(n);
5453                      if (q) {
5454                        $$.val = NewStringf("%s::%s", q, Getattr(n,"name"));
5455                        Delete(q);
5456                      }
5457                    }
5458                  }
5459                }
5460                ;
5461
5462 valexpr        : exprnum { $$ = $1; }
5463                | string {
5464                     $$.val = NewString($1);
5465                     $$.type = T_STRING;
5466                }
5467                | SIZEOF LPAREN type parameter_declarator RPAREN {
5468                   SwigType_push($3,$4.type);
5469                   $$.val = NewStringf("sizeof(%s)",SwigType_str($3,0));
5470                   $$.type = T_ULONG;
5471                }
5472                | exprcompound { $$ = $1; }
5473                | CHARCONST {
5474                   $$.val = NewString($1);
5475                   if (Len($$.val)) {
5476                     $$.rawval = NewStringf("'%(escape)s'", $$.val);
5477                   } else {
5478                     $$.rawval = NewString("'\\0'");
5479                   }
5480                   $$.type = T_CHAR;
5481                   $$.bitfield = 0;
5482                   $$.throws = 0;
5483                   $$.throwf = 0;
5484                }
5485
5486 /* grouping */
5487                |  LPAREN expr RPAREN %prec CAST {
5488                     $$.val = NewStringf("(%s)",$2.val);
5489                     $$.type = $2.type;
5490                }
5491
5492 /* A few common casting operations */
5493
5494                | LPAREN expr RPAREN expr %prec CAST {
5495                  $$ = $4;
5496                  if ($4.type != T_STRING) {
5497                    switch ($2.type) {
5498                      case T_FLOAT:
5499                      case T_DOUBLE:
5500                      case T_LONGDOUBLE:
5501                      case T_FLTCPLX:
5502                      case T_DBLCPLX:
5503                        $$.val = NewStringf("(%s)%s", $2.val, $4.val); /* SwigType_str and decimal points don't mix! */
5504                        break;
5505                      default:
5506                        $$.val = NewStringf("(%s) %s", SwigType_str($2.val,0), $4.val);
5507                        break;
5508                    }
5509                  }
5510                }
5511                | LPAREN expr pointer RPAREN expr %prec CAST {
5512                  $$ = $5;
5513                  if ($5.type != T_STRING) {
5514                    SwigType_push($2.val,$3);
5515                    $$.val = NewStringf("(%s) %s", SwigType_str($2.val,0), $5.val);
5516                  }
5517                }
5518                | LPAREN expr AND RPAREN expr %prec CAST {
5519                  $$ = $5;
5520                  if ($5.type != T_STRING) {
5521                    SwigType_add_reference($2.val);
5522                    $$.val = NewStringf("(%s) %s", SwigType_str($2.val,0), $5.val);
5523                  }
5524                }
5525                | LPAREN expr pointer AND RPAREN expr %prec CAST {
5526                  $$ = $6;
5527                  if ($6.type != T_STRING) {
5528                    SwigType_push($2.val,$3);
5529                    SwigType_add_reference($2.val);
5530                    $$.val = NewStringf("(%s) %s", SwigType_str($2.val,0), $6.val);
5531                  }
5532                }
5533                | AND expr {
5534                  $$ = $2;
5535                  $$.val = NewStringf("&%s",$2.val);
5536                }
5537                | STAR expr {
5538                  $$ = $2;
5539                  $$.val = NewStringf("*%s",$2.val);
5540                }
5541                ;
5542
5543 exprnum        :  NUM_INT { $$ = $1; }
5544                |  NUM_FLOAT { $$ = $1; }
5545                |  NUM_UNSIGNED { $$ = $1; }
5546                |  NUM_LONG { $$ = $1; }
5547                |  NUM_ULONG { $$ = $1; }
5548                |  NUM_LONGLONG { $$ = $1; }
5549                |  NUM_ULONGLONG { $$ = $1; }
5550                ;
5551
5552 exprcompound   : expr PLUS expr {
5553                  $$.val = NewStringf("%s+%s",$1.val,$3.val);
5554                  $$.type = promote($1.type,$3.type);
5555                }
5556                | expr MINUS expr {
5557                  $$.val = NewStringf("%s-%s",$1.val,$3.val);
5558                  $$.type = promote($1.type,$3.type);
5559                }
5560                | expr STAR expr {
5561                  $$.val = NewStringf("%s*%s",$1.val,$3.val);
5562                  $$.type = promote($1.type,$3.type);
5563                }
5564                | expr SLASH expr {
5565                  $$.val = NewStringf("%s/%s",$1.val,$3.val);
5566                  $$.type = promote($1.type,$3.type);
5567                }
5568                | expr MODULUS expr {
5569                  $$.val = NewStringf("%s%%%s",$1.val,$3.val);
5570                  $$.type = promote($1.type,$3.type);
5571                }
5572                | expr AND expr {
5573                  $$.val = NewStringf("%s&%s",$1.val,$3.val);
5574                  $$.type = promote($1.type,$3.type);
5575                }
5576                | expr OR expr {
5577                  $$.val = NewStringf("%s|%s",$1.val,$3.val);
5578                  $$.type = promote($1.type,$3.type);
5579                }
5580                | expr XOR expr {
5581                  $$.val = NewStringf("%s^%s",$1.val,$3.val);
5582                  $$.type = promote($1.type,$3.type);
5583                }
5584                | expr LSHIFT expr {
5585                  $$.val = NewStringf("%s << %s",$1.val,$3.val);
5586                  $$.type = promote_type($1.type);
5587                }
5588                | expr RSHIFT expr {
5589                  $$.val = NewStringf("%s >> %s",$1.val,$3.val);
5590                  $$.type = promote_type($1.type);
5591                }
5592                | expr LAND expr {
5593                  $$.val = NewStringf("%s&&%s",$1.val,$3.val);
5594                  $$.type = T_INT;
5595                }
5596                | expr LOR expr {
5597                  $$.val = NewStringf("%s||%s",$1.val,$3.val);
5598                  $$.type = T_INT;
5599                }
5600                | expr EQUALTO expr {
5601                  $$.val = NewStringf("%s==%s",$1.val,$3.val);
5602                  $$.type = T_INT;
5603                }
5604                | expr NOTEQUALTO expr {
5605                  $$.val = NewStringf("%s!=%s",$1.val,$3.val);
5606                  $$.type = T_INT;
5607                }
5608 /* Sadly this causes 2 reduce-reduce conflicts with templates.  FIXME resolve these.
5609                | expr GREATERTHAN expr {
5610                  $$.val = NewStringf("%s SWIG_LT %s", $1.val, $3.val);
5611                  $$.type = T_INT;
5612                }
5613                | expr LESSTHAN expr {
5614                  $$.val = NewStringf("%s SWIG_GT %s", $1.val, $3.val);
5615                  $$.type = T_INT;
5616                }
5617 */
5618                | expr GREATERTHANOREQUALTO expr {
5619                  /* Putting >= in the expression literally causes an infinite
5620                   * loop somewhere in the type system.  Just workaround for now
5621                   * - SWIG_GE is defined in swiglabels.swg. */
5622                  $$.val = NewStringf("%s SWIG_GE %s", $1.val, $3.val);
5623                  $$.type = T_INT;
5624                }
5625                | expr LESSTHANOREQUALTO expr {
5626                  $$.val = NewStringf("%s SWIG_LE %s", $1.val, $3.val);
5627                  $$.type = T_INT;
5628                }
5629                | expr QUESTIONMARK expr COLON expr %prec QUESTIONMARK {
5630                  $$.val = NewStringf("%s?%s:%s", $1.val, $3.val, $5.val);
5631                  /* This may not be exactly right, but is probably good enough
5632                   * for the purposes of parsing constant expressions. */
5633                  $$.type = promote($3.type, $5.type);
5634                }
5635                | MINUS expr %prec UMINUS {
5636                  $$.val = NewStringf("-%s",$2.val);
5637                  $$.type = $2.type;
5638                }
5639                | PLUS expr %prec UMINUS {
5640                  $$.val = NewStringf("+%s",$2.val);
5641                  $$.type = $2.type;
5642                }
5643                | NOT expr {
5644                  $$.val = NewStringf("~%s",$2.val);
5645                  $$.type = $2.type;
5646                }
5647                | LNOT expr {
5648                  $$.val = NewStringf("!%s",$2.val);
5649                  $$.type = T_INT;
5650                }
5651                | type LPAREN {
5652                  String *qty;
5653                  skip_balanced('(',')');
5654                  qty = Swig_symbol_type_qualify($1,0);
5655                  if (SwigType_istemplate(qty)) {
5656                    String *nstr = SwigType_namestr(qty);
5657                    Delete(qty);
5658                    qty = nstr;
5659                  }
5660                  $$.val = NewStringf("%s%s",qty,scanner_ccode);
5661                  Clear(scanner_ccode);
5662                  $$.type = T_INT;
5663                  Delete(qty);
5664                }
5665                ;
5666
5667 inherit        : raw_inherit {
5668                  $$ = $1;
5669                }
5670                ;
5671
5672 raw_inherit     : COLON { inherit_list = 1; } base_list { $$ = $3; inherit_list = 0; }
5673                 | empty { $$ = 0; }
5674                 ;
5675
5676 base_list      : base_specifier {
5677                    Hash *list = NewHash();
5678                    Node *base = $1;
5679                    Node *name = Getattr(base,"name");
5680                    List *lpublic = NewList();
5681                    List *lprotected = NewList();
5682                    List *lprivate = NewList();
5683                    Setattr(list,"public",lpublic);
5684                    Setattr(list,"protected",lprotected);
5685                    Setattr(list,"private",lprivate);
5686                    Delete(lpublic);
5687                    Delete(lprotected);
5688                    Delete(lprivate);
5689                    Append(Getattr(list,Getattr(base,"access")),name);
5690                    $$ = list;
5691                }
5692
5693                | base_list COMMA base_specifier {
5694                    Hash *list = $1;
5695                    Node *base = $3;
5696                    Node *name = Getattr(base,"name");
5697                    Append(Getattr(list,Getattr(base,"access")),name);
5698                    $$ = list;
5699                }
5700                ;
5701
5702 base_specifier : opt_virtual idcolon {
5703                  $$ = NewHash();
5704                  Setfile($$,cparse_file);
5705                  Setline($$,cparse_line);
5706                  Setattr($$,"name",$2);
5707                  if (last_cpptype && (Strcmp(last_cpptype,"struct") != 0)) {
5708                    Setattr($$,"access","private");
5709                    Swig_warning(WARN_PARSE_NO_ACCESS,cparse_file,cparse_line,
5710                                 "No access specifier given for base class %s (ignored).\n",$2);
5711                  } else {
5712                    Setattr($$,"access","public");
5713                  }
5714                }
5715                | opt_virtual access_specifier opt_virtual idcolon {
5716                  $$ = NewHash();
5717                  Setfile($$,cparse_file);
5718                  Setline($$,cparse_line);
5719                  Setattr($$,"name",$4);
5720                  Setattr($$,"access",$2);
5721                  if (Strcmp($2,"public") != 0) {
5722                    Swig_warning(WARN_PARSE_PRIVATE_INHERIT, cparse_file, 
5723                                 cparse_line,"%s inheritance ignored.\n", $2);
5724                  }
5725                }
5726                ;
5727
5728 access_specifier :  PUBLIC { $$ = (char*)"public"; }
5729                | PRIVATE { $$ = (char*)"private"; }
5730                | PROTECTED { $$ = (char*)"protected"; }
5731                ;
5732
5733
5734 templcpptype   : CLASS { 
5735                    $$ = (char*)"class"; 
5736                    if (!inherit_list) last_cpptype = $$;
5737                }
5738                | TYPENAME { 
5739                    $$ = (char *)"typename"; 
5740                    if (!inherit_list) last_cpptype = $$;
5741                }
5742                ;
5743
5744 cpptype        : templcpptype {
5745                  $$ = $1;
5746                }
5747                | STRUCT { 
5748                    $$ = (char*)"struct"; 
5749                    if (!inherit_list) last_cpptype = $$;
5750                }
5751                | UNION {
5752                    $$ = (char*)"union"; 
5753                    if (!inherit_list) last_cpptype = $$;
5754                }
5755                ;
5756
5757 opt_virtual    : VIRTUAL
5758                | empty
5759                ;
5760
5761 cpp_const      : type_qualifier {
5762                     $$.qualifier = $1;
5763                     $$.throws = 0;
5764                     $$.throwf = 0;
5765                }
5766                | THROW LPAREN parms RPAREN {
5767                     $$.qualifier = 0;
5768                     $$.throws = $3;
5769                     $$.throwf = NewString("1");
5770                }
5771                | type_qualifier THROW LPAREN parms RPAREN {
5772                     $$.qualifier = $1;
5773                     $$.throws = $4;
5774                     $$.throwf = NewString("1");
5775                }
5776                | empty { 
5777                     $$.qualifier = 0; 
5778                     $$.throws = 0;
5779                     $$.throwf = 0;
5780                }
5781                ;
5782
5783 ctor_end       : cpp_const ctor_initializer SEMI { 
5784                     Clear(scanner_ccode); 
5785                     $$.have_parms = 0; 
5786                     $$.defarg = 0; 
5787                     $$.throws = $1.throws;
5788                     $$.throwf = $1.throwf;
5789                }
5790                | cpp_const ctor_initializer LBRACE { 
5791                     skip_balanced('{','}'); 
5792                     $$.have_parms = 0; 
5793                     $$.defarg = 0; 
5794                     $$.throws = $1.throws;
5795                     $$.throwf = $1.throwf;
5796                }
5797                | LPAREN parms RPAREN SEMI { 
5798                     Clear(scanner_ccode); 
5799                     $$.parms = $2; 
5800                     $$.have_parms = 1; 
5801                     $$.defarg = 0; 
5802                     $$.throws = 0;
5803                     $$.throwf = 0;
5804                }
5805                | LPAREN parms RPAREN LBRACE {
5806                     skip_balanced('{','}'); 
5807                     $$.parms = $2; 
5808                     $$.have_parms = 1; 
5809                     $$.defarg = 0; 
5810                     $$.throws = 0;
5811                     $$.throwf = 0;
5812                }
5813                | EQUAL definetype SEMI { 
5814                     $$.have_parms = 0; 
5815                     $$.defarg = $2.val; 
5816                     $$.throws = 0;
5817                     $$.throwf = 0;
5818                }
5819                ;
5820
5821 ctor_initializer : COLON mem_initializer_list
5822                | empty
5823                ;
5824
5825 mem_initializer_list : mem_initializer
5826                | mem_initializer_list COMMA mem_initializer
5827                ;
5828
5829 mem_initializer : idcolon LPAREN {
5830                     skip_balanced('(',')');
5831                     Clear(scanner_ccode);
5832                 }
5833                 ;
5834
5835 template_decl : LESSTHAN valparms GREATERTHAN { 
5836                      String *s = NewStringEmpty();
5837                      SwigType_add_template(s,$2);
5838                      $$ = Char(s);
5839                      scanner_last_id(1);
5840                  }
5841                | empty { $$ = (char*)"";  }
5842                ;
5843
5844 idstring       : ID { $$ = $1; }
5845                | string { $$ = $1; }
5846                ;
5847
5848 idstringopt    : idstring { $$ = $1; }
5849                | empty { $$ = 0; }
5850                ;
5851  
5852 idcolon        : idtemplate idcolontail { 
5853                   $$ = 0;
5854                   if (!$$) $$ = NewStringf("%s%s", $1,$2);
5855                   Delete($2);
5856                }
5857                | NONID DCOLON idtemplate idcolontail { 
5858                  $$ = NewStringf("::%s%s",$3,$4);
5859                  Delete($4);
5860                }
5861                | idtemplate {
5862                  $$ = NewString($1);
5863                }     
5864                | NONID DCOLON idtemplate {
5865                  $$ = NewStringf("::%s",$3);
5866                }
5867                | OPERATOR {
5868                  $$ = NewString($1);
5869                }
5870                | NONID DCOLON OPERATOR {
5871                  $$ = NewStringf("::%s",$3);
5872                }
5873                ;
5874
5875 idcolontail    : DCOLON idtemplate idcolontail {
5876                    $$ = NewStringf("::%s%s",$2,$3);
5877                    Delete($3);
5878                }
5879                | DCOLON idtemplate {
5880                    $$ = NewStringf("::%s",$2);
5881                }
5882                | DCOLON OPERATOR {
5883                    $$ = NewStringf("::%s",$2);
5884                }
5885 /*               | DCOLON COPERATOR {
5886                  $$ = NewString($2);                 
5887                  } */
5888
5889                | DCNOT idtemplate {
5890                  $$ = NewStringf("::~%s",$2);
5891                }
5892                ;
5893
5894
5895 idtemplate    : ID template_decl {
5896                   $$ = NewStringf("%s%s",$1,$2);
5897                   /*              if (Len($2)) {
5898                     scanner_last_id(1);
5899                     } */
5900               }
5901               ;
5902
5903 /* Identifier, but no templates */
5904 idcolonnt     : ID idcolontailnt { 
5905                   $$ = 0;
5906                   if (!$$) $$ = NewStringf("%s%s", $1,$2);
5907                   Delete($2);
5908                }
5909                | NONID DCOLON ID idcolontailnt { 
5910                  $$ = NewStringf("::%s%s",$3,$4);
5911                  Delete($4);
5912                }
5913                | ID {
5914                  $$ = NewString($1);
5915                }     
5916                | NONID DCOLON ID {
5917                  $$ = NewStringf("::%s",$3);
5918                }
5919                | OPERATOR {
5920                  $$ = NewString($1);
5921                }
5922                | NONID DCOLON OPERATOR {
5923                  $$ = NewStringf("::%s",$3);
5924                }
5925                ;
5926
5927 idcolontailnt   : DCOLON ID idcolontailnt {
5928                    $$ = NewStringf("::%s%s",$2,$3);
5929                    Delete($3);
5930                }
5931                | DCOLON ID {
5932                    $$ = NewStringf("::%s",$2);
5933                }
5934                | DCOLON OPERATOR {
5935                    $$ = NewStringf("::%s",$2);
5936                }
5937                | DCNOT ID {
5938                  $$ = NewStringf("::~%s",$2);
5939                }
5940                ;
5941
5942 /* Concatenated strings */
5943 string         : string STRING { 
5944                    $$ = (char *) malloc(strlen($1)+strlen($2)+1);
5945                    strcpy($$,$1);
5946                    strcat($$,$2);
5947                }
5948                | STRING { $$ = $1;}
5949                ; 
5950
5951 stringbrace    : string {
5952                  $$ = NewString($1);
5953                }
5954                | LBRACE {
5955                   skip_balanced('{','}');
5956                   $$ = NewString(scanner_ccode);
5957                }
5958               | HBLOCK {
5959                  $$ = $1;
5960               }
5961                ;
5962
5963 options        : LPAREN kwargs RPAREN {
5964                   Hash *n;
5965                   $$ = NewHash();
5966                   n = $2;
5967                   while(n) {
5968                      String *name, *value;
5969                      name = Getattr(n,"name");
5970                      value = Getattr(n,"value");
5971                      if (!value) value = (String *) "1";
5972                      Setattr($$,name, value);
5973                      n = nextSibling(n);
5974                   }
5975                }   
5976                | empty { $$ = 0; };
5977
5978  
5979 /* Keyword arguments */
5980 kwargs         : idstring EQUAL stringnum {
5981                  $$ = NewHash();
5982                  Setattr($$,"name",$1);
5983                  Setattr($$,"value",$3);
5984                }
5985                | idstring EQUAL stringnum COMMA kwargs {
5986                  $$ = NewHash();
5987                  Setattr($$,"name",$1);
5988                  Setattr($$,"value",$3);
5989                  set_nextSibling($$,$5);
5990                }
5991                | idstring {
5992                  $$ = NewHash();
5993                  Setattr($$,"name",$1);
5994                }
5995                | idstring COMMA kwargs {
5996                  $$ = NewHash();
5997                  Setattr($$,"name",$1);
5998                  set_nextSibling($$,$3);
5999                }
6000                | idstring EQUAL stringtype  {
6001                  $$ = $3;
6002                  Setattr($$,"name",$1);
6003                }
6004                | idstring EQUAL stringtype COMMA kwargs {
6005                  $$ = $3;
6006                  Setattr($$,"name",$1);
6007                  set_nextSibling($$,$5);
6008                }
6009                ;
6010
6011 stringnum      : string {
6012                  $$ = $1;
6013                }
6014                | exprnum {
6015                  $$ = Char($1.val);
6016                }
6017                ;
6018
6019 empty          :   ;
6020
6021 %%
6022
6023 SwigType *Swig_cparse_type(String *s) {
6024    String *ns;
6025    ns = NewStringf("%s;",s);
6026    Seek(ns,0,SEEK_SET);
6027    scanner_file(ns);
6028    top = 0;
6029    scanner_next_token(PARSETYPE);
6030    yyparse();
6031    /*   Printf(stdout,"typeparse: '%s' ---> '%s'\n", s, top); */
6032    return top;
6033 }
6034
6035
6036 Parm *Swig_cparse_parm(String *s) {
6037    String *ns;
6038    ns = NewStringf("%s;",s);
6039    Seek(ns,0,SEEK_SET);
6040    scanner_file(ns);
6041    top = 0;
6042    scanner_next_token(PARSEPARM);
6043    yyparse();
6044    /*   Printf(stdout,"typeparse: '%s' ---> '%s'\n", s, top); */
6045    Delete(ns);
6046    return top;
6047 }
6048
6049
6050 ParmList *Swig_cparse_parms(String *s) {
6051    String *ns;
6052    char *cs = Char(s);
6053    if (cs && cs[0] != '(') {
6054      ns = NewStringf("(%s);",s);
6055    } else {
6056      ns = NewStringf("%s;",s);
6057    }   
6058    Seek(ns,0,SEEK_SET);
6059    scanner_file(ns);
6060    top = 0;
6061    scanner_next_token(PARSEPARMS);
6062    yyparse();
6063    /*   Printf(stdout,"typeparse: '%s' ---> '%s'\n", s, top); */
6064    return top;
6065 }
6066