PageRenderTime 36ms CodeModel.GetById 14ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 1ms

/trunk/Source/CParse/parser.y

#
Happy | 2145 lines | 1937 code | 208 blank | 0 comment | 0 complexity | 5b14796929a0cd0b9de545ab12b6b340 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/* -----------------------------------------------------------------------------
   2 * This file is part of SWIG, which is licensed as a whole under version 3 
   3 * (or any later version) of the GNU General Public License. Some additional
   4 * terms also apply to certain portions of SWIG. The full details of the SWIG
   5 * license and copyrights can be found in the LICENSE and COPYRIGHT files
   6 * included with the SWIG source code as distributed by the SWIG developers
   7 * and at http://www.swig.org/legal.html.
   8 *
   9 * parser.y
  10 *
  11 * YACC parser for SWIG.   The grammar is a somewhat broken subset of C/C++.
  12 * This file is a bit of a mess and probably needs to be rewritten at
  13 * some point.  Beware.
  14 * ----------------------------------------------------------------------------- */
  15
  16%{
  17
  18#define yylex yylex
  19
  20char cvsroot_parser_y[] = "$Id: parser.y 12926 2012-03-16 07:30:14Z wsfulton $";
  21
  22#include "swig.h"
  23#include "cparse.h"
  24#include "preprocessor.h"
  25#include <ctype.h>
  26
  27/* We do this for portability */
  28#undef alloca
  29#define alloca malloc
  30
  31/* -----------------------------------------------------------------------------
  32 *                               Externals
  33 * ----------------------------------------------------------------------------- */
  34
  35int  yyparse();
  36
  37/* NEW Variables */
  38
  39static Node    *top = 0;      /* Top of the generated parse tree */
  40static int      unnamed = 0;  /* Unnamed datatype counter */
  41static Hash    *extendhash = 0;     /* Hash table of added methods */
  42static Hash    *classes = 0;        /* Hash table of classes */
  43static Symtab  *prev_symtab = 0;
  44static Node    *current_class = 0;
  45String  *ModuleName = 0;
  46static Node    *module_node = 0;
  47static String  *Classprefix = 0;  
  48static String  *Namespaceprefix = 0;
  49static int      inclass = 0;
  50static int      nested_template = 0; /* template class/function definition within a class */
  51static char    *last_cpptype = 0;
  52static int      inherit_list = 0;
  53static Parm    *template_parameters = 0;
  54static int      extendmode   = 0;
  55static int      compact_default_args = 0;
  56static int      template_reduce = 0;
  57static int      cparse_externc = 0;
  58
  59static int      max_class_levels = 0;
  60static int      class_level = 0;
  61static Node   **class_decl = NULL;
  62
  63/* -----------------------------------------------------------------------------
  64 *                            Assist Functions
  65 * ----------------------------------------------------------------------------- */
  66
  67
  68 
  69/* Called by the parser (yyparse) when an error is found.*/
  70static void yyerror (const char *e) {
  71  (void)e;
  72}
  73
  74static Node *new_node(const_String_or_char_ptr tag) {
  75  Node *n = NewHash();
  76  set_nodeType(n,tag);
  77  Setfile(n,cparse_file);
  78  Setline(n,cparse_line);
  79  return n;
  80}
  81
  82/* Copies a node.  Does not copy tree links or symbol table data (except for
  83   sym:name) */
  84
  85static Node *copy_node(Node *n) {
  86  Node *nn;
  87  Iterator k;
  88  nn = NewHash();
  89  Setfile(nn,Getfile(n));
  90  Setline(nn,Getline(n));
  91  for (k = First(n); k.key; k = Next(k)) {
  92    String *ci;
  93    String *key = k.key;
  94    char *ckey = Char(key);
  95    if ((strcmp(ckey,"nextSibling") == 0) ||
  96	(strcmp(ckey,"previousSibling") == 0) ||
  97	(strcmp(ckey,"parentNode") == 0) ||
  98	(strcmp(ckey,"lastChild") == 0)) {
  99      continue;
 100    }
 101    if (Strncmp(key,"csym:",5) == 0) continue;
 102    /* We do copy sym:name.  For templates */
 103    if ((strcmp(ckey,"sym:name") == 0) || 
 104	(strcmp(ckey,"sym:weak") == 0) ||
 105	(strcmp(ckey,"sym:typename") == 0)) {
 106      String *ci = Copy(k.item);
 107      Setattr(nn,key, ci);
 108      Delete(ci);
 109      continue;
 110    }
 111    if (strcmp(ckey,"sym:symtab") == 0) {
 112      Setattr(nn,"sym:needs_symtab", "1");
 113    }
 114    /* We don't copy any other symbol table attributes */
 115    if (strncmp(ckey,"sym:",4) == 0) {
 116      continue;
 117    }
 118    /* If children.  We copy them recursively using this function */
 119    if (strcmp(ckey,"firstChild") == 0) {
 120      /* Copy children */
 121      Node *cn = k.item;
 122      while (cn) {
 123	Node *copy = copy_node(cn);
 124	appendChild(nn,copy);
 125	Delete(copy);
 126	cn = nextSibling(cn);
 127      }
 128      continue;
 129    }
 130    /* We don't copy the symbol table.  But we drop an attribute 
 131       requires_symtab so that functions know it needs to be built */
 132
 133    if (strcmp(ckey,"symtab") == 0) {
 134      /* Node defined a symbol table. */
 135      Setattr(nn,"requires_symtab","1");
 136      continue;
 137    }
 138    /* Can't copy nodes */
 139    if (strcmp(ckey,"node") == 0) {
 140      continue;
 141    }
 142    if ((strcmp(ckey,"parms") == 0) || (strcmp(ckey,"pattern") == 0) || (strcmp(ckey,"throws") == 0)
 143	|| (strcmp(ckey,"kwargs") == 0)) {
 144      ParmList *pl = CopyParmList(k.item);
 145      Setattr(nn,key,pl);
 146      Delete(pl);
 147      continue;
 148    }
 149    /* Looks okay.  Just copy the data using Copy */
 150    ci = Copy(k.item);
 151    Setattr(nn, key, ci);
 152    Delete(ci);
 153  }
 154  return nn;
 155}
 156
 157/* -----------------------------------------------------------------------------
 158 *                              Variables
 159 * ----------------------------------------------------------------------------- */
 160
 161static char  *typemap_lang = 0;    /* Current language setting */
 162
 163static int cplus_mode  = 0;
 164static String  *class_rename = 0;
 165
 166/* C++ modes */
 167
 168#define  CPLUS_PUBLIC    1
 169#define  CPLUS_PRIVATE   2
 170#define  CPLUS_PROTECTED 3
 171
 172/* include types */
 173static int   import_mode = 0;
 174
 175void SWIG_typemap_lang(const char *tm_lang) {
 176  typemap_lang = Swig_copy_string(tm_lang);
 177}
 178
 179void SWIG_cparse_set_compact_default_args(int defargs) {
 180  compact_default_args = defargs;
 181}
 182
 183int SWIG_cparse_template_reduce(int treduce) {
 184  template_reduce = treduce;
 185  return treduce;  
 186}
 187
 188/* -----------------------------------------------------------------------------
 189 *                           Assist functions
 190 * ----------------------------------------------------------------------------- */
 191
 192static int promote_type(int t) {
 193  if (t <= T_UCHAR || t == T_CHAR) return T_INT;
 194  return t;
 195}
 196
 197/* Perform type-promotion for binary operators */
 198static int promote(int t1, int t2) {
 199  t1 = promote_type(t1);
 200  t2 = promote_type(t2);
 201  return t1 > t2 ? t1 : t2;
 202}
 203
 204static String *yyrename = 0;
 205
 206/* Forward renaming operator */
 207
 208static String *resolve_node_scope(String *cname);
 209
 210
 211Hash *Swig_cparse_features(void) {
 212  static Hash   *features_hash = 0;
 213  if (!features_hash) features_hash = NewHash();
 214  return features_hash;
 215}
 216
 217/* Fully qualify any template parameters */
 218static String *feature_identifier_fix(String *s) {
 219  String *tp = SwigType_istemplate_templateprefix(s);
 220  if (tp) {
 221    String *ts, *ta, *tq;
 222    ts = SwigType_templatesuffix(s);
 223    ta = SwigType_templateargs(s);
 224    tq = Swig_symbol_type_qualify(ta,0);
 225    Append(tp,tq);
 226    Append(tp,ts);
 227    Delete(ts);
 228    Delete(ta);
 229    Delete(tq);
 230    return tp;
 231  } else {
 232    return NewString(s);
 233  }
 234}
 235
 236/* Generate the symbol table name for an object */
 237/* This is a bit of a mess. Need to clean up */
 238static String *add_oldname = 0;
 239
 240
 241
 242static String *make_name(Node *n, String *name,SwigType *decl) {
 243  int destructor = name && (*(Char(name)) == '~');
 244
 245  if (yyrename) {
 246    String *s = NewString(yyrename);
 247    Delete(yyrename);
 248    yyrename = 0;
 249    if (destructor  && (*(Char(s)) != '~')) {
 250      Insert(s,0,"~");
 251    }
 252    return s;
 253  }
 254
 255  if (!name) return 0;
 256  return Swig_name_make(n,Namespaceprefix,name,decl,add_oldname);
 257}
 258
 259/* Generate an unnamed identifier */
 260static String *make_unnamed() {
 261  unnamed++;
 262  return NewStringf("$unnamed%d$",unnamed);
 263}
 264
 265/* Return if the node is a friend declaration */
 266static int is_friend(Node *n) {
 267  return Cmp(Getattr(n,"storage"),"friend") == 0;
 268}
 269
 270static int is_operator(String *name) {
 271  return Strncmp(name,"operator ", 9) == 0;
 272}
 273
 274
 275/* Add declaration list to symbol table */
 276static int  add_only_one = 0;
 277
 278static void add_symbols(Node *n) {
 279  String *decl;
 280  String *wrn = 0;
 281
 282  if (nested_template) {
 283    if (!(n && Equal(nodeType(n), "template"))) {
 284      return;
 285    }
 286    /* continue if template function, but not template class, declared within a class */
 287  }
 288
 289  if (inclass && n) {
 290    cparse_normalize_void(n);
 291  }
 292  while (n) {
 293    String *symname = 0;
 294    /* for friends, we need to pop the scope once */
 295    String *old_prefix = 0;
 296    Symtab *old_scope = 0;
 297    int isfriend = inclass && is_friend(n);
 298    int iscdecl = Cmp(nodeType(n),"cdecl") == 0;
 299    int only_csymbol = 0;
 300    if (extendmode) {
 301      Setattr(n,"isextension","1");
 302    }
 303    
 304    if (inclass) {
 305      String *name = Getattr(n, "name");
 306      if (isfriend) {
 307	/* for friends, we need to add the scopename if needed */
 308	String *prefix = name ? Swig_scopename_prefix(name) : 0;
 309	old_prefix = Namespaceprefix;
 310	old_scope = Swig_symbol_popscope();
 311	Namespaceprefix = Swig_symbol_qualifiedscopename(0);
 312	if (!prefix) {
 313	  if (name && !is_operator(name) && Namespaceprefix) {
 314	    String *nname = NewStringf("%s::%s", Namespaceprefix, name);
 315	    Setattr(n,"name",nname);
 316	    Delete(nname);
 317	  }
 318	} else {
 319	  Symtab *st = Swig_symbol_getscope(prefix);
 320	  String *ns = st ? Getattr(st,"name") : prefix;
 321	  String *base  = Swig_scopename_last(name);
 322	  String *nname = NewStringf("%s::%s", ns, base);
 323	  Setattr(n,"name",nname);
 324	  Delete(nname);
 325	  Delete(base);
 326	  Delete(prefix);
 327	}
 328	Namespaceprefix = 0;
 329      } else {
 330	/* for member functions, we need to remove the redundant
 331	   class scope if provided, as in
 332	   
 333	   struct Foo {
 334	   int Foo::method(int a);
 335	   };
 336	   
 337	*/
 338	String *prefix = name ? Swig_scopename_prefix(name) : 0;
 339	if (prefix) {
 340	  if (Classprefix && (Equal(prefix,Classprefix))) {
 341	    String *base = Swig_scopename_last(name);
 342	    Setattr(n,"name",base);
 343	    Delete(base);
 344	  }
 345	  Delete(prefix);
 346	}
 347
 348        /*
 349	if (!Getattr(n,"parentNode") && class_level) set_parentNode(n,class_decl[class_level - 1]);
 350        */
 351	Setattr(n,"ismember","1");
 352      }
 353    }
 354    if (!isfriend && inclass) {
 355      if ((cplus_mode != CPLUS_PUBLIC)) {
 356	only_csymbol = 1;
 357	if (cplus_mode == CPLUS_PROTECTED) {
 358	  Setattr(n,"access", "protected");
 359	  only_csymbol = !Swig_need_protected(n);
 360	} else {
 361	  Setattr(n,"access", "private");
 362	  /* private are needed only when they are pure virtuals - why? */
 363	  if ((Cmp(Getattr(n,"storage"),"virtual") == 0) && (Cmp(Getattr(n,"value"),"0") == 0)) {
 364	    only_csymbol = 0;
 365	  }
 366	}
 367      } else {
 368	  Setattr(n,"access", "public");
 369      }
 370    }
 371    if (Getattr(n,"sym:name")) {
 372      n = nextSibling(n);
 373      continue;
 374    }
 375    decl = Getattr(n,"decl");
 376    if (!SwigType_isfunction(decl)) {
 377      String *name = Getattr(n,"name");
 378      String *makename = Getattr(n,"parser:makename");
 379      if (iscdecl) {	
 380	String *storage = Getattr(n, "storage");
 381	if (Cmp(storage,"typedef") == 0) {
 382	  Setattr(n,"kind","typedef");
 383	} else {
 384	  SwigType *type = Getattr(n,"type");
 385	  String *value = Getattr(n,"value");
 386	  Setattr(n,"kind","variable");
 387	  if (value && Len(value)) {
 388	    Setattr(n,"hasvalue","1");
 389	  }
 390	  if (type) {
 391	    SwigType *ty;
 392	    SwigType *tmp = 0;
 393	    if (decl) {
 394	      ty = tmp = Copy(type);
 395	      SwigType_push(ty,decl);
 396	    } else {
 397	      ty = type;
 398	    }
 399	    if (!SwigType_ismutable(ty)) {
 400	      SetFlag(n,"hasconsttype");
 401	      SetFlag(n,"feature:immutable");
 402	    }
 403	    if (tmp) Delete(tmp);
 404	  }
 405	  if (!type) {
 406	    Printf(stderr,"notype name %s\n", name);
 407	  }
 408	}
 409      }
 410      Swig_features_get(Swig_cparse_features(), Namespaceprefix, name, 0, n);
 411      if (makename) {
 412	symname = make_name(n, makename,0);
 413        Delattr(n,"parser:makename"); /* temporary information, don't leave it hanging around */
 414      } else {
 415        makename = name;
 416	symname = make_name(n, makename,0);
 417      }
 418      
 419      if (!symname) {
 420	symname = Copy(Getattr(n,"unnamed"));
 421      }
 422      if (symname) {
 423	wrn = Swig_name_warning(n, Namespaceprefix, symname,0);
 424      }
 425    } else {
 426      String *name = Getattr(n,"name");
 427      SwigType *fdecl = Copy(decl);
 428      SwigType *fun = SwigType_pop_function(fdecl);
 429      if (iscdecl) {	
 430	Setattr(n,"kind","function");
 431      }
 432      
 433      Swig_features_get(Swig_cparse_features(),Namespaceprefix,name,fun,n);
 434
 435      symname = make_name(n, name,fun);
 436      wrn = Swig_name_warning(n, Namespaceprefix,symname,fun);
 437      
 438      Delete(fdecl);
 439      Delete(fun);
 440      
 441    }
 442    if (!symname) {
 443      n = nextSibling(n);
 444      continue;
 445    }
 446    if (only_csymbol || GetFlag(n,"feature:ignore")) {
 447      /* Only add to C symbol table and continue */
 448      Swig_symbol_add(0, n);
 449    } else if (strncmp(Char(symname),"$ignore",7) == 0) {
 450      char *c = Char(symname)+7;
 451      SetFlag(n,"feature:ignore");
 452      if (strlen(c)) {
 453	SWIG_WARN_NODE_BEGIN(n);
 454	Swig_warning(0,Getfile(n), Getline(n), "%s\n",c+1);
 455	SWIG_WARN_NODE_END(n);
 456      }
 457      Swig_symbol_add(0, n);
 458    } else {
 459      Node *c;
 460      if ((wrn) && (Len(wrn))) {
 461	String *metaname = symname;
 462	if (!Getmeta(metaname,"already_warned")) {
 463	  SWIG_WARN_NODE_BEGIN(n);
 464	  Swig_warning(0,Getfile(n),Getline(n), "%s\n", wrn);
 465	  SWIG_WARN_NODE_END(n);
 466	  Setmeta(metaname,"already_warned","1");
 467	}
 468      }
 469      c = Swig_symbol_add(symname,n);
 470
 471      if (c != n) {
 472        /* symbol conflict attempting to add in the new symbol */
 473        if (Getattr(n,"sym:weak")) {
 474          Setattr(n,"sym:name",symname);
 475        } else {
 476          String *e = NewStringEmpty();
 477          String *en = NewStringEmpty();
 478          String *ec = NewStringEmpty();
 479          int redefined = Swig_need_redefined_warn(n,c,inclass);
 480          if (redefined) {
 481            Printf(en,"Identifier '%s' redefined (ignored)",symname);
 482            Printf(ec,"previous definition of '%s'",symname);
 483          } else {
 484            Printf(en,"Redundant redeclaration of '%s'",symname);
 485            Printf(ec,"previous declaration of '%s'",symname);
 486          }
 487          if (Cmp(symname,Getattr(n,"name"))) {
 488            Printf(en," (Renamed from '%s')", SwigType_namestr(Getattr(n,"name")));
 489          }
 490          Printf(en,",");
 491          if (Cmp(symname,Getattr(c,"name"))) {
 492            Printf(ec," (Renamed from '%s')", SwigType_namestr(Getattr(c,"name")));
 493          }
 494          Printf(ec,".");
 495	  SWIG_WARN_NODE_BEGIN(n);
 496          if (redefined) {
 497            Swig_warning(WARN_PARSE_REDEFINED,Getfile(n),Getline(n),"%s\n",en);
 498            Swig_warning(WARN_PARSE_REDEFINED,Getfile(c),Getline(c),"%s\n",ec);
 499          } else if (!is_friend(n) && !is_friend(c)) {
 500            Swig_warning(WARN_PARSE_REDUNDANT,Getfile(n),Getline(n),"%s\n",en);
 501            Swig_warning(WARN_PARSE_REDUNDANT,Getfile(c),Getline(c),"%s\n",ec);
 502          }
 503	  SWIG_WARN_NODE_END(n);
 504          Printf(e,"%s:%d:%s\n%s:%d:%s\n",Getfile(n),Getline(n),en,
 505                 Getfile(c),Getline(c),ec);
 506          Setattr(n,"error",e);
 507	  Delete(e);
 508          Delete(en);
 509          Delete(ec);
 510        }
 511      }
 512    }
 513    /* restore the class scope if needed */
 514    if (isfriend) {
 515      Swig_symbol_setscope(old_scope);
 516      if (old_prefix) {
 517	Delete(Namespaceprefix);
 518	Namespaceprefix = old_prefix;
 519      }
 520    }
 521    Delete(symname);
 522
 523    if (add_only_one) return;
 524    n = nextSibling(n);
 525  }
 526}
 527
 528
 529/* add symbols a parse tree node copy */
 530
 531static void add_symbols_copy(Node *n) {
 532  String *name;
 533  int    emode = 0;
 534  while (n) {
 535    char *cnodeType = Char(nodeType(n));
 536
 537    if (strcmp(cnodeType,"access") == 0) {
 538      String *kind = Getattr(n,"kind");
 539      if (Strcmp(kind,"public") == 0) {
 540	cplus_mode = CPLUS_PUBLIC;
 541      } else if (Strcmp(kind,"private") == 0) {
 542	cplus_mode = CPLUS_PRIVATE;
 543      } else if (Strcmp(kind,"protected") == 0) {
 544	cplus_mode = CPLUS_PROTECTED;
 545      }
 546      n = nextSibling(n);
 547      continue;
 548    }
 549
 550    add_oldname = Getattr(n,"sym:name");
 551    if ((add_oldname) || (Getattr(n,"sym:needs_symtab"))) {
 552      int old_inclass = -1;
 553      Node *old_current_class = 0;
 554      if (add_oldname) {
 555	DohIncref(add_oldname);
 556	/*  Disable this, it prevents %rename to work with templates */
 557	/* If already renamed, we used that name  */
 558	/*
 559	if (Strcmp(add_oldname, Getattr(n,"name")) != 0) {
 560	  Delete(yyrename);
 561	  yyrename = Copy(add_oldname);
 562	}
 563	*/
 564      }
 565      Delattr(n,"sym:needs_symtab");
 566      Delattr(n,"sym:name");
 567
 568      add_only_one = 1;
 569      add_symbols(n);
 570
 571      if (Getattr(n,"partialargs")) {
 572	Swig_symbol_cadd(Getattr(n,"partialargs"),n);
 573      }
 574      add_only_one = 0;
 575      name = Getattr(n,"name");
 576      if (Getattr(n,"requires_symtab")) {
 577	Swig_symbol_newscope();
 578	Swig_symbol_setscopename(name);
 579	Delete(Namespaceprefix);
 580	Namespaceprefix = Swig_symbol_qualifiedscopename(0);
 581      }
 582      if (strcmp(cnodeType,"class") == 0) {
 583	old_inclass = inclass;
 584	inclass = 1;
 585	old_current_class = current_class;
 586	current_class = n;
 587	if (Strcmp(Getattr(n,"kind"),"class") == 0) {
 588	  cplus_mode = CPLUS_PRIVATE;
 589	} else {
 590	  cplus_mode = CPLUS_PUBLIC;
 591	}
 592      }
 593      if (strcmp(cnodeType,"extend") == 0) {
 594	emode = cplus_mode;
 595	cplus_mode = CPLUS_PUBLIC;
 596      }
 597      add_symbols_copy(firstChild(n));
 598      if (strcmp(cnodeType,"extend") == 0) {
 599	cplus_mode = emode;
 600      }
 601      if (Getattr(n,"requires_symtab")) {
 602	Setattr(n,"symtab", Swig_symbol_popscope());
 603	Delattr(n,"requires_symtab");
 604	Delete(Namespaceprefix);
 605	Namespaceprefix = Swig_symbol_qualifiedscopename(0);
 606      }
 607      if (add_oldname) {
 608	Delete(add_oldname);
 609	add_oldname = 0;
 610      }
 611      if (strcmp(cnodeType,"class") == 0) {
 612	inclass = old_inclass;
 613	current_class = old_current_class;
 614      }
 615    } else {
 616      if (strcmp(cnodeType,"extend") == 0) {
 617	emode = cplus_mode;
 618	cplus_mode = CPLUS_PUBLIC;
 619      }
 620      add_symbols_copy(firstChild(n));
 621      if (strcmp(cnodeType,"extend") == 0) {
 622	cplus_mode = emode;
 623      }
 624    }
 625    n = nextSibling(n);
 626  }
 627}
 628
 629/* Extension merge.  This function is used to handle the %extend directive
 630   when it appears before a class definition.   To handle this, the %extend
 631   actually needs to take precedence.  Therefore, we will selectively nuke symbols
 632   from the current symbol table, replacing them with the added methods */
 633
 634static void merge_extensions(Node *cls, Node *am) {
 635  Node *n;
 636  Node *csym;
 637
 638  n = firstChild(am);
 639  while (n) {
 640    String *symname;
 641    if (Strcmp(nodeType(n),"constructor") == 0) {
 642      symname = Getattr(n,"sym:name");
 643      if (symname) {
 644	if (Strcmp(symname,Getattr(n,"name")) == 0) {
 645	  /* If the name and the sym:name of a constructor are the same,
 646             then it hasn't been renamed.  However---the name of the class
 647             itself might have been renamed so we need to do a consistency
 648             check here */
 649	  if (Getattr(cls,"sym:name")) {
 650	    Setattr(n,"sym:name", Getattr(cls,"sym:name"));
 651	  }
 652	}
 653      } 
 654    }
 655
 656    symname = Getattr(n,"sym:name");
 657    DohIncref(symname);
 658    if ((symname) && (!Getattr(n,"error"))) {
 659      /* Remove node from its symbol table */
 660      Swig_symbol_remove(n);
 661      csym = Swig_symbol_add(symname,n);
 662      if (csym != n) {
 663	/* Conflict with previous definition.  Nuke previous definition */
 664	String *e = NewStringEmpty();
 665	String *en = NewStringEmpty();
 666	String *ec = NewStringEmpty();
 667	Printf(ec,"Identifier '%s' redefined by %%extend (ignored),",symname);
 668	Printf(en,"%%extend definition of '%s'.",symname);
 669	SWIG_WARN_NODE_BEGIN(n);
 670	Swig_warning(WARN_PARSE_REDEFINED,Getfile(csym),Getline(csym),"%s\n",ec);
 671	Swig_warning(WARN_PARSE_REDEFINED,Getfile(n),Getline(n),"%s\n",en);
 672	SWIG_WARN_NODE_END(n);
 673	Printf(e,"%s:%d:%s\n%s:%d:%s\n",Getfile(csym),Getline(csym),ec, 
 674	       Getfile(n),Getline(n),en);
 675	Setattr(csym,"error",e);
 676	Delete(e);
 677	Delete(en);
 678	Delete(ec);
 679	Swig_symbol_remove(csym);              /* Remove class definition */
 680	Swig_symbol_add(symname,n);            /* Insert extend definition */
 681      }
 682    }
 683    n = nextSibling(n);
 684  }
 685}
 686
 687static void append_previous_extension(Node *cls, Node *am) {
 688  Node *n, *ne;
 689  Node *pe = 0;
 690  Node *ae = 0;
 691
 692  if (!am) return;
 693  
 694  n = firstChild(am);
 695  while (n) {
 696    ne = nextSibling(n);
 697    set_nextSibling(n,0);
 698    /* typemaps and fragments need to be prepended */
 699    if (((Cmp(nodeType(n),"typemap") == 0) || (Cmp(nodeType(n),"fragment") == 0)))  {
 700      if (!pe) pe = new_node("extend");
 701      appendChild(pe, n);
 702    } else {
 703      if (!ae) ae = new_node("extend");
 704      appendChild(ae, n);
 705    }    
 706    n = ne;
 707  }
 708  if (pe) prependChild(cls,pe);
 709  if (ae) appendChild(cls,ae);
 710}
 711 
 712
 713/* Check for unused %extend.  Special case, don't report unused
 714   extensions for templates */
 715 
 716static void check_extensions() {
 717  Iterator ki;
 718
 719  if (!extendhash) return;
 720  for (ki = First(extendhash); ki.key; ki = Next(ki)) {
 721    if (!Strchr(ki.key,'<')) {
 722      SWIG_WARN_NODE_BEGIN(ki.item);
 723      Swig_warning(WARN_PARSE_EXTEND_UNDEF,Getfile(ki.item), Getline(ki.item), "%%extend defined for an undeclared class %s.\n", ki.key);
 724      SWIG_WARN_NODE_END(ki.item);
 725    }
 726  }
 727}
 728
 729/* Check a set of declarations to see if any are pure-abstract */
 730
 731static List *pure_abstract(Node *n) {
 732  List *abs = 0;
 733  while (n) {
 734    if (Cmp(nodeType(n),"cdecl") == 0) {
 735      String *decl = Getattr(n,"decl");
 736      if (SwigType_isfunction(decl)) {
 737	String *init = Getattr(n,"value");
 738	if (Cmp(init,"0") == 0) {
 739	  if (!abs) {
 740	    abs = NewList();
 741	  }
 742	  Append(abs,n);
 743	  Setattr(n,"abstract","1");
 744	}
 745      }
 746    } else if (Cmp(nodeType(n),"destructor") == 0) {
 747      if (Cmp(Getattr(n,"value"),"0") == 0) {
 748	if (!abs) {
 749	  abs = NewList();
 750	}
 751	Append(abs,n);
 752	Setattr(n,"abstract","1");
 753      }
 754    }
 755    n = nextSibling(n);
 756  }
 757  return abs;
 758}
 759
 760/* Make a classname */
 761
 762static String *make_class_name(String *name) {
 763  String *nname = 0;
 764  String *prefix;
 765  if (Namespaceprefix) {
 766    nname= NewStringf("%s::%s", Namespaceprefix, name);
 767  } else {
 768    nname = NewString(name);
 769  }
 770  prefix = SwigType_istemplate_templateprefix(nname);
 771  if (prefix) {
 772    String *args, *qargs;
 773    args   = SwigType_templateargs(nname);
 774    qargs  = Swig_symbol_type_qualify(args,0);
 775    Append(prefix,qargs);
 776    Delete(nname);
 777    Delete(args);
 778    Delete(qargs);
 779    nname = prefix;
 780  }
 781  return nname;
 782}
 783
 784static List *make_inherit_list(String *clsname, List *names) {
 785  int i, ilen;
 786  String *derived;
 787  List *bases = NewList();
 788
 789  if (Namespaceprefix) derived = NewStringf("%s::%s", Namespaceprefix,clsname);
 790  else derived = NewString(clsname);
 791
 792  ilen = Len(names);
 793  for (i = 0; i < ilen; i++) {
 794    Node *s;
 795    String *base;
 796    String *n = Getitem(names,i);
 797    /* Try to figure out where this symbol is */
 798    s = Swig_symbol_clookup(n,0);
 799    if (s) {
 800      while (s && (Strcmp(nodeType(s),"class") != 0)) {
 801	/* Not a class.  Could be a typedef though. */
 802	String *storage = Getattr(s,"storage");
 803	if (storage && (Strcmp(storage,"typedef") == 0)) {
 804	  String *nn = Getattr(s,"type");
 805	  s = Swig_symbol_clookup(nn,Getattr(s,"sym:symtab"));
 806	} else {
 807	  break;
 808	}
 809      }
 810      if (s && ((Strcmp(nodeType(s),"class") == 0) || (Strcmp(nodeType(s),"template") == 0))) {
 811	String *q = Swig_symbol_qualified(s);
 812	Append(bases,s);
 813	if (q) {
 814	  base = NewStringf("%s::%s", q, Getattr(s,"name"));
 815	  Delete(q);
 816	} else {
 817	  base = NewString(Getattr(s,"name"));
 818	}
 819      } else {
 820	base = NewString(n);
 821      }
 822    } else {
 823      base = NewString(n);
 824    }
 825    if (base) {
 826      Swig_name_inherit(base,derived);
 827      Delete(base);
 828    }
 829  }
 830  return bases;
 831}
 832
 833/* If the class name is qualified.  We need to create or lookup namespace entries */
 834
 835static Symtab *set_scope_to_global() {
 836  Symtab *symtab = Swig_symbol_global_scope();
 837  Swig_symbol_setscope(symtab);
 838  return symtab;
 839}
 840 
 841/* Remove the block braces, { and }, if the 'noblock' attribute is set.
 842 * Node *kw can be either a Hash or Parmlist. */
 843static String *remove_block(Node *kw, const String *inputcode) {
 844  String *modified_code = 0;
 845  while (kw) {
 846   String *name = Getattr(kw,"name");
 847   if (name && (Cmp(name,"noblock") == 0)) {
 848     char *cstr = Char(inputcode);
 849     size_t len = Len(inputcode);
 850     if (len && cstr[0] == '{') {
 851       --len; ++cstr; 
 852       if (len && cstr[len - 1] == '}') { --len; }
 853       /* we now remove the extra spaces */
 854       while (len && isspace((int)cstr[0])) { --len; ++cstr; }
 855       while (len && isspace((int)cstr[len - 1])) { --len; }
 856       modified_code = NewStringWithSize(cstr, len);
 857       break;
 858     }
 859   }
 860   kw = nextSibling(kw);
 861  }
 862  return modified_code;
 863}
 864
 865
 866static Node *nscope = 0;
 867static Node *nscope_inner = 0;
 868
 869/* Remove the scope prefix from cname and return the base name without the prefix.
 870 * The scopes specified in the prefix are found, or created in the current namespace.
 871 * So ultimately the scope is changed to that required for the base name.
 872 * For example AA::BB::CC as input returns CC and creates the namespace AA then inner 
 873 * namespace BB in the current scope. If no scope separator (::) in the input, then nothing happens! */
 874static String *resolve_node_scope(String *cname) {
 875  Symtab *gscope = 0;
 876  nscope = 0;
 877  nscope_inner = 0;  
 878  if (Swig_scopename_check(cname)) {
 879    Node   *ns;
 880    String *prefix = Swig_scopename_prefix(cname);
 881    String *base = Swig_scopename_last(cname);
 882    if (prefix && (Strncmp(prefix,"::",2) == 0)) {
 883      /* Use the global scope */
 884      String *nprefix = NewString(Char(prefix)+2);
 885      Delete(prefix);
 886      prefix= nprefix;
 887      gscope = set_scope_to_global();
 888    }    
 889    if (!prefix || (Len(prefix) == 0)) {
 890      /* Use the global scope, but we need to add a 'global' namespace.  */
 891      if (!gscope) gscope = set_scope_to_global();
 892      /* note that this namespace is not the "unnamed" one,
 893	 and we don't use Setattr(nscope,"name", ""),
 894	 because the unnamed namespace is private */
 895      nscope = new_node("namespace");
 896      Setattr(nscope,"symtab", gscope);;
 897      nscope_inner = nscope;
 898      return base;
 899    }
 900    /* Try to locate the scope */
 901    ns = Swig_symbol_clookup(prefix,0);
 902    if (!ns) {
 903      Swig_error(cparse_file,cparse_line,"Undefined scope '%s'\n", prefix);
 904    } else {
 905      Symtab *nstab = Getattr(ns,"symtab");
 906      if (!nstab) {
 907	Swig_error(cparse_file,cparse_line,
 908		   "'%s' is not defined as a valid scope.\n", prefix);
 909	ns = 0;
 910      } else {
 911	/* Check if the node scope is the current scope */
 912	String *tname = Swig_symbol_qualifiedscopename(0);
 913	String *nname = Swig_symbol_qualifiedscopename(nstab);
 914	if (tname && (Strcmp(tname,nname) == 0)) {
 915	  ns = 0;
 916	  cname = base;
 917	}
 918	Delete(tname);
 919	Delete(nname);
 920      }
 921      if (ns) {
 922	/* we will try to create a new node using the namespaces we
 923	   can find in the scope name */
 924	List *scopes;
 925	String *sname;
 926	Iterator si;
 927	String *name = NewString(prefix);
 928	scopes = NewList();
 929	while (name) {
 930	  String *base = Swig_scopename_last(name);
 931	  String *tprefix = Swig_scopename_prefix(name);
 932	  Insert(scopes,0,base);
 933	  Delete(base);
 934	  Delete(name);
 935	  name = tprefix;
 936	}
 937	for (si = First(scopes); si.item; si = Next(si)) {
 938	  Node *ns1,*ns2;
 939	  sname = si.item;
 940	  ns1 = Swig_symbol_clookup(sname,0);
 941	  assert(ns1);
 942	  if (Strcmp(nodeType(ns1),"namespace") == 0) {
 943	    if (Getattr(ns1,"alias")) {
 944	      ns1 = Getattr(ns1,"namespace");
 945	    }
 946	  } else {
 947	    /* now this last part is a class */
 948	    si = Next(si);
 949	    ns1 = Swig_symbol_clookup(sname,0);
 950	    /*  or a nested class tree, which is unrolled here */
 951	    for (; si.item; si = Next(si)) {
 952	      if (si.item) {
 953		Printf(sname,"::%s",si.item);
 954	      }
 955	    }
 956	    /* we get the 'inner' class */
 957	    nscope_inner = Swig_symbol_clookup(sname,0);
 958	    /* set the scope to the inner class */
 959	    Swig_symbol_setscope(Getattr(nscope_inner,"symtab"));
 960	    /* save the last namespace prefix */
 961	    Delete(Namespaceprefix);
 962	    Namespaceprefix = Swig_symbol_qualifiedscopename(0);
 963	    /* and return the node name, including the inner class prefix */
 964	    break;
 965	  }
 966	  /* here we just populate the namespace tree as usual */
 967	  ns2 = new_node("namespace");
 968	  Setattr(ns2,"name",sname);
 969	  Setattr(ns2,"symtab", Getattr(ns1,"symtab"));
 970	  add_symbols(ns2);
 971	  Swig_symbol_setscope(Getattr(ns1,"symtab"));
 972	  Delete(Namespaceprefix);
 973	  Namespaceprefix = Swig_symbol_qualifiedscopename(0);
 974	  if (nscope_inner) {
 975	    if (Getattr(nscope_inner,"symtab") != Getattr(ns2,"symtab")) {
 976	      appendChild(nscope_inner,ns2);
 977	      Delete(ns2);
 978	    }
 979	  }
 980	  nscope_inner = ns2;
 981	  if (!nscope) nscope = ns2;
 982	}
 983	cname = base;
 984	Delete(scopes);
 985      }
 986    }
 987    Delete(prefix);
 988  }
 989  return cname;
 990}
 991 
 992
 993
 994/* Structures for handling code fragments built for nested classes */
 995
 996typedef struct Nested {
 997  String   *code;        /* Associated code fragment */
 998  int      line;         /* line number where it starts */
 999  const char *name;      /* Name associated with this nested class */
1000  const char *kind;      /* Kind of class */
1001  int      unnamed;      /* unnamed class */
1002  SwigType *type;        /* Datatype associated with the name */
1003  struct Nested   *next; /* Next code fragment in list */
1004} Nested;
1005
1006/* Some internal variables for saving nested class information */
1007
1008static Nested      *nested_list = 0;
1009
1010/* Add a function to the nested list */
1011
1012static void add_nested(Nested *n) {
1013  if (!nested_list) {
1014    nested_list = n;
1015  } else {
1016    Nested *n1 = nested_list;
1017    while (n1->next)
1018      n1 = n1->next;
1019    n1->next = n;
1020  }
1021}
1022
1023/* -----------------------------------------------------------------------------
1024 * nested_new_struct()
1025 *
1026 * Nested struct handling for C code only creates a global struct from the nested struct.
1027 *
1028 * Nested structure. This is a sick "hack". If we encounter
1029 * a nested structure, we're going to grab the text of its definition and
1030 * feed it back into the scanner.  In the meantime, we need to grab
1031 * variable declaration information and generate the associated wrapper
1032 * code later.  Yikes!
1033 *
1034 * This really only works in a limited sense.   Since we use the
1035 * code attached to the nested class to generate both C code
1036 * it can't have any SWIG directives in it.  It also needs to be parsable
1037 * by SWIG or this whole thing is going to puke.
1038 * ----------------------------------------------------------------------------- */
1039
1040static void nested_new_struct(const char *kind, String *struct_code, Node *cpp_opt_declarators) {
1041  String *name;
1042  String *decl;
1043
1044  /* Create a new global struct declaration which is just a copy of the nested struct */
1045  Nested *nested = (Nested *) malloc(sizeof(Nested));
1046  Nested *n = nested;
1047
1048  name = Getattr(cpp_opt_declarators, "name");
1049  decl = Getattr(cpp_opt_declarators, "decl");
1050
1051  n->code = NewStringEmpty();
1052  Printv(n->code, "typedef ", kind, " ", struct_code, " $classname_", name, ";\n", NIL);
1053  n->name = Swig_copy_string(Char(name));
1054  n->line = cparse_start_line;
1055  n->type = NewStringEmpty();
1056  n->kind = kind;
1057  n->unnamed = 0;
1058  SwigType_push(n->type, decl);
1059  n->next = 0;
1060
1061  /* Repeat for any multiple instances of the nested struct */
1062  {
1063    Node *p = cpp_opt_declarators;
1064    p = nextSibling(p);
1065    while (p) {
1066      Nested *nn = (Nested *) malloc(sizeof(Nested));
1067
1068      name = Getattr(p, "name");
1069      decl = Getattr(p, "decl");
1070
1071      nn->code = NewStringEmpty();
1072      Printv(nn->code, "typedef ", kind, " ", struct_code, " $classname_", name, ";\n", NIL);
1073      nn->name = Swig_copy_string(Char(name));
1074      nn->line = cparse_start_line;
1075      nn->type = NewStringEmpty();
1076      nn->kind = kind;
1077      nn->unnamed = 0;
1078      SwigType_push(nn->type, decl);
1079      nn->next = 0;
1080      n->next = nn;
1081      n = nn;
1082      p = nextSibling(p);
1083    }
1084  }
1085
1086  add_nested(nested);
1087}
1088
1089/* -----------------------------------------------------------------------------
1090 * nested_forward_declaration()
1091 * 
1092 * Nested struct handling for C++ code only.
1093 *
1094 * Treat the nested class/struct/union as a forward declaration until a proper 
1095 * nested class solution is implemented.
1096 * ----------------------------------------------------------------------------- */
1097
1098static Node *nested_forward_declaration(const char *storage, const char *kind, String *sname, const char *name, Node *cpp_opt_declarators) {
1099  Node *nn = 0;
1100  int warned = 0;
1101
1102  if (sname) {
1103    /* Add forward declaration of the nested type */
1104    Node *n = new_node("classforward");
1105    Setfile(n, cparse_file);
1106    Setline(n, cparse_line);
1107    Setattr(n, "kind", kind);
1108    Setattr(n, "name", sname);
1109    Setattr(n, "storage", storage);
1110    Setattr(n, "sym:weak", "1");
1111    add_symbols(n);
1112    nn = n;
1113  }
1114
1115  /* Add any variable instances. Also add in any further typedefs of the nested type.
1116     Note that anonymous typedefs (eg typedef struct {...} a, b;) are treated as class forward declarations */
1117  if (cpp_opt_declarators) {
1118    int storage_typedef = (storage && (strcmp(storage, "typedef") == 0));
1119    int variable_of_anonymous_type = !sname && !storage_typedef;
1120    if (!variable_of_anonymous_type) {
1121      int anonymous_typedef = !sname && (storage && (strcmp(storage, "typedef") == 0));
1122      Node *n = cpp_opt_declarators;
1123      SwigType *type = NewString(name);
1124      while (n) {
1125	Setattr(n, "type", type);
1126	Setattr(n, "storage", storage);
1127	if (anonymous_typedef) {
1128	  Setattr(n, "nodeType", "classforward");
1129	  Setattr(n, "sym:weak", "1");
1130	}
1131	n = nextSibling(n);
1132      }
1133      Delete(type);
1134      add_symbols(cpp_opt_declarators);
1135
1136      if (nn) {
1137	set_nextSibling(nn, cpp_opt_declarators);
1138      } else {
1139	nn = cpp_opt_declarators;
1140      }
1141    }
1142  }
1143
1144  if (nn && Equal(nodeType(nn), "classforward")) {
1145    Node *n = nn;
1146    if (GetFlag(n, "feature:nestedworkaround")) {
1147      Swig_symbol_remove(n);
1148      nn = 0;
1149      warned = 1;
1150    } else {
1151      SWIG_WARN_NODE_BEGIN(n);
1152      Swig_warning(WARN_PARSE_NAMED_NESTED_CLASS, cparse_file, cparse_line,"Nested %s not currently supported (%s ignored)\n", kind, sname ? sname : name);
1153      SWIG_WARN_NODE_END(n);
1154      warned = 1;
1155    }
1156  }
1157
1158  if (!warned)
1159    Swig_warning(WARN_PARSE_UNNAMED_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", kind);
1160
1161  return nn;
1162}
1163
1164/* Strips C-style and C++-style comments from string in-place. */
1165static void strip_comments(char *string) {
1166  int state = 0; /* 
1167                  * 0 - not in comment
1168                  * 1 - in c-style comment
1169                  * 2 - in c++-style comment
1170                  * 3 - in string
1171                  * 4 - after reading / not in comments
1172                  * 5 - after reading * in c-style comments
1173                  * 6 - after reading \ in strings
1174                  */
1175  char * c = string;
1176  while (*c) {
1177    switch (state) {
1178    case 0:
1179      if (*c == '\"')
1180        state = 3;
1181      else if (*c == '/')
1182        state = 4;
1183      break;
1184    case 1:
1185      if (*c == '*')
1186        state = 5;
1187      *c = ' ';
1188      break;
1189    case 2:
1190      if (*c == '\n')
1191        state = 0;
1192      else
1193        *c = ' ';
1194      break;
1195    case 3:
1196      if (*c == '\"')
1197        state = 0;
1198      else if (*c == '\\')
1199        state = 6;
1200      break;
1201    case 4:
1202      if (*c == '/') {
1203        *(c-1) = ' ';
1204        *c = ' ';
1205        state = 2;
1206      } else if (*c == '*') {
1207        *(c-1) = ' ';
1208        *c = ' ';
1209        state = 1;
1210      } else
1211        state = 0;
1212      break;
1213    case 5:
1214      if (*c == '/')
1215        state = 0;
1216      else 
1217        state = 1;
1218      *c = ' ';
1219      break;
1220    case 6:
1221      state = 3;
1222      break;
1223    }
1224    ++c;
1225  }
1226}
1227
1228/* Dump all of the nested class declarations to the inline processor
1229 * However.  We need to do a few name replacements and other munging
1230 * first.  This function must be called before closing a class! */
1231
1232static Node *dump_nested(const char *parent) {
1233  Nested *n,*n1;
1234  Node *ret = 0;
1235  Node *last = 0;
1236  n = nested_list;
1237  if (!parent) {
1238    nested_list = 0;
1239    return 0;
1240  }
1241  while (n) {
1242    Node *retx;
1243    SwigType *nt;
1244    /* Token replace the name of the parent class */
1245    Replace(n->code, "$classname", parent, DOH_REPLACE_ANY);
1246
1247    /* Fix up the name of the datatype (for building typedefs and other stuff) */
1248    Append(n->type,parent);
1249    Append(n->type,"_");
1250    Append(n->type,n->name);
1251
1252    /* Add the appropriate declaration to the C++ processor */
1253    retx = new_node("cdecl");
1254    Setattr(retx,"name",n->name);
1255    nt = Copy(n->type);
1256    Setattr(retx,"type",nt);
1257    Delete(nt);
1258    Setattr(retx,"nested",parent);
1259    if (n->unnamed) {
1260      Setattr(retx,"unnamed","1");
1261    }
1262    
1263    add_symbols(retx);
1264    if (ret) {
1265      set_nextSibling(last, retx);
1266      Delete(retx);
1267    } else {
1268      ret = retx;
1269    }
1270    last = retx;
1271
1272    /* Strip comments - further code may break in presence of comments. */
1273    strip_comments(Char(n->code));
1274
1275    /* Make all SWIG created typedef structs/unions/classes unnamed else 
1276       redefinition errors occur - nasty hack alert.*/
1277
1278    {
1279      const char* types_array[3] = {"struct", "union", "class"};
1280      int i;
1281      for (i=0; i<3; i++) {
1282	char* code_ptr = Char(n->code);
1283	while (code_ptr) {
1284	  /* Replace struct name (as in 'struct name {...}' ) with whitespace
1285	     name will be between struct and opening brace */
1286	
1287	  code_ptr = strstr(code_ptr, types_array[i]);
1288	  if (code_ptr) {
1289	    char *open_bracket_pos;
1290	    code_ptr += strlen(types_array[i]);
1291	    open_bracket_pos = strchr(code_ptr, '{');
1292	    if (open_bracket_pos) { 
1293	      /* Make sure we don't have something like struct A a; */
1294	      char* semi_colon_pos = strchr(code_ptr, ';');
1295	      if (!(semi_colon_pos && (semi_colon_pos < open_bracket_pos)))
1296		while (code_ptr < open_bracket_pos)
1297		  *code_ptr++ = ' ';
1298	    }
1299	  }
1300	}
1301      }
1302    }
1303    
1304    {
1305      /* Remove SWIG directive %constant which may be left in the SWIG created typedefs */
1306      char* code_ptr = Char(n->code);
1307      while (code_ptr) {
1308	code_ptr = strstr(code_ptr, "%constant");
1309	if (code_ptr) {
1310	  char* directive_end_pos = strchr(code_ptr, ';');
1311	  if (directive_end_pos) { 
1312            while (code_ptr <= directive_end_pos)
1313              *code_ptr++ = ' ';
1314	  }
1315	}
1316      }
1317    }
1318    {
1319      Node *newnode = new_node("insert");
1320      String *code = NewStringEmpty();
1321      Wrapper_pretty_print(n->code, code);
1322      Setattr(newnode,"code", code);
1323      Delete(code);
1324      set_nextSibling(last, newnode);
1325      Delete(newnode);      
1326      last = newnode;
1327    }
1328      
1329    /* Dump the code to the scanner */
1330    start_inline(Char(Getattr(last, "code")),n->line);
1331
1332    n1 = n->next;
1333    Delete(n->code);
1334    free(n);
1335    n = n1;
1336  }
1337  nested_list = 0;
1338  return ret;
1339}
1340
1341Node *Swig_cparse(File *f) {
1342  scanner_file(f);
1343  top = 0;
1344  yyparse();
1345  return top;
1346}
1347
1348static void single_new_feature(const char *featurename, String *val, Hash *featureattribs, char *declaratorid, SwigType *type, ParmList *declaratorparms, String *qualifier) {
1349  String *fname;
1350  String *name;
1351  String *fixname;
1352  SwigType *t = Copy(type);
1353
1354  /* Printf(stdout, "single_new_feature: [%s] [%s] [%s] [%s] [%s] [%s]\n", featurename, val, declaratorid, t, ParmList_str_defaultargs(declaratorparms), qualifier); */
1355
1356  fname = NewStringf("feature:%s",featurename);
1357  if (declaratorid) {
1358    fixname = feature_identifier_fix(declaratorid);
1359  } else {
1360    fixname = NewStringEmpty();
1361  }
1362  if (Namespaceprefix) {
1363    name = NewStringf("%s::%s",Namespaceprefix, fixname);
1364  } else {
1365    name = fixname;
1366  }
1367
1368  if (declaratorparms) Setmeta(val,"parms",declaratorparms);
1369  if (!Len(t)) t = 0;
1370  if (t) {
1371    if (qualifier) SwigType_push(t,qualifier);
1372    if (SwigType_isfunction(t)) {
1373      SwigType *decl = SwigType_pop_function(t);
1374      if (SwigType_ispointer(t)) {
1375	String *nname = NewStringf("*%s",name);
1376	Swig_feature_set(Swig_cparse_features(), nname, decl, fname, val, featureattribs);
1377	Delete(nname);
1378      } else {
1379	Swig_feature_set(Swig_cparse_features(), name, decl, fname, val, featureattribs);
1380      }
1381      Delete(decl);
1382    } else if (SwigType_ispointer(t)) {
1383      String *nname = NewStringf("*%s",name);
1384      Swig_feature_set(Swig_cparse_features(),nname,0,fname,val, featureattribs);
1385      Delete(nname);
1386    }
1387  } else {
1388    /* Global feature, that is, feature not associated with any particular symbol */
1389    Swig_feature_set(Swig_cparse_features(),name,0,fname,val, featureattribs);
1390  }
1391  Delete(fname);
1392  Delete(name);
1393}
1394
1395/* Add a new feature to the Hash. Additional features are added if the feature has a parameter list (declaratorparms)
1396 * and one or more of the parameters have a default argument. An extra feature is added for each defaulted parameter,
1397 * simulating the equivalent overloaded method. */
1398static void new_feature(const char *featurename, String *val, Hash *featureattribs, char *declaratorid, SwigType *type, ParmList *declaratorparms, String *qualifier) {
1399
1400  ParmList *declparms = declaratorparms;
1401
1402  /* remove the { and } braces if the noblock attribute is set */
1403  String *newval = remove_block(featureattribs, val);
1404  val = newval ? newval : val;
1405
1406  /* Add the feature */
1407  single_new_feature(featurename, val, featureattribs, declaratorid, type, declaratorparms, qualifier);
1408
1409  /* Add extra features if there are default parameters in the parameter list */
1410  if (type) {
1411    while (declparms) {
1412      if (ParmList_has_defaultargs(declparms)) {
1413
1414        /* Create a parameter list for the new feature by copying all
1415           but the last (defaulted) parameter */
1416        ParmList* newparms = CopyParmListMax(declparms, ParmList_len(declparms)-1);
1417
1418        /* Create new declaration - with the last parameter removed */
1419        SwigType *newtype = Copy(type);
1420        Delete(SwigType_pop_function(newtype)); /* remove the old parameter list from newtype */
1421        SwigType_add_function(newtype,newparms);
1422
1423        single_new_feature(featurename, Copy(val), featureattribs, declaratorid, newtype, newparms, qualifier);
1424        declparms = newparms;
1425      } else {
1426        declparms = 0;
1427      }
1428    }
1429  }
1430}
1431
1432/* check if a function declaration is a plain C object */
1433static int is_cfunction(Node *n) {
1434  if (!cparse_cplusplus || cparse_externc) return 1;
1435  if (Cmp(Getattr(n,"storage"),"externc") == 0) {
1436    return 1;
1437  }
1438  return 0;
1439}
1440
1441/* If the Node is a function with parameters, check to see if any of the parameters
1442 * have default arguments. If so create a new function for each defaulted argument. 
1443 * The additional functions form a linked list of nodes with the head being the original Node n. */
1444static void default_arguments(Node *n) {
1445  Node *function = n;
1446
1447  if (function) {
1448    ParmList *varargs = Getattr(function,"feature:varargs");
1449    if (varargs) {
1450      /* Handles the %varargs directive by looking for "feature:varargs" and 
1451       * substituting ... with an alternative set of arguments.  */
1452      Parm     *p = Getattr(function,"parms");
1453      Parm     *pp = 0;
1454      while (p) {
1455	SwigType *t = Getattr(p,"type");
1456	if (Strcmp(t,"v(...)") == 0) {
1457	  if (pp) {
1458	    ParmList *cv = Copy(varargs);
1459	    set_nextSibling(pp,cv);
1460	    Delete(cv);
1461	  } else {
1462	    ParmList *cv =  Copy(varargs);
1463	    Setattr(function,"parms", cv);
1464	    Delete(cv);
1465	  }
1466	  break;
1467	}
1468	pp = p;
1469	p = nextSibling(p);
1470      }
1471    }
1472
1473    /* Do not add in functions if kwargs is being used or if user wants old default argument wrapping
1474       (one wrapped method per function irrespective of number of default arguments) */
1475    if (compact_default_args 
1476	|| is_cfunction(function) 
1477	|| GetFlag(function,"feature:compactdefaultargs") 
1478	|| GetFlag(function,"feature:kwargs")) {
1479      ParmList *p = Getattr(function,"parms");
1480      if (p) 
1481        Setattr(p,"compactdefargs", "1"); /* mark parameters for special handling */
1482      function = 0; /* don't add in extra methods */
1483    }
1484  }
1485
1486  while (function) {
1487    ParmList *parms = Getattr(function,"parms");
1488    if (ParmList_has_defaultargs(parms)) {
1489
1490      /* Create a parameter list for the new function by copying all
1491         but the last (defaulted) parameter */
1492      ParmList* newparms = CopyParmListMax(parms,ParmList_len(parms)-1);
1493
1494      /* Create new function and add to symbol table */
1495      {
1496	SwigType *ntype = Copy(nodeType(function));
1497	char *cntype = Char(ntype);
1498        Node *new_function = new_node(ntype);
1499        SwigType *decl = Copy(Getattr(function,"decl"));
1500        int constqualifier = SwigType_isconst(decl);
1501	String *ccode = Copy(Getattr(function,"code"));
1502	String *cstorage = Copy(Getattr(function,"storage"));
1503	String *cvalue = Copy(Getattr(function,"value"));
1504	SwigType *ctype = Copy(Getattr(function,"type"));
1505	String *cthrow = Copy(Getattr(function,"throw"));
1506
1507        Delete(SwigType_pop_function(decl)); /* remove the old parameter list from decl */
1508        SwigType_add_function(decl,newparms);
1509        if (constqualifier)
1510          SwigType_add_qualifier(decl,"const");
1511
1512        Setattr(new_function,"name", Getattr(function,"name"));
1513        Setattr(new_function,"code", ccode);
1514        Setattr(new_function,"decl", decl);
1515        Setattr(new_function,"parms", newparms);
1516        Setattr(new_function,"storage", cstorage);
1517        Setattr(new_function,"value", cvalue);
1518        Setattr(new_function,"type", ctype);
1519        Setattr(new_function,"throw", cthrow);
1520
1521	Delete(ccode);
1522	Delete(cstorage);
1523	Delete(cvalue);
1524	Delete(ctype);
1525	Delete(cthrow);
1526	Delete(decl);
1527
1528        {
1529          Node *throws = Getattr(function,"throws");
1530	  ParmList *pl = CopyParmList(throws);
1531          if (throws) Setattr(new_function,"throws",pl);
1532	  Delete(pl);
1533        }
1534
1535        /* copy specific attributes for global (or in a namespace) template functions - these are not templated class methods */
1536        if (strcmp(cntype,"template") == 0) {
1537          Node *templatetype = Getattr(function,"templatetype");
1538          Node *symtypename = Getattr(function,"sym:typename");
1539          Parm *templateparms = Getattr(function,"templateparms");
1540          if (templatetype) {
1541	    Node *tmp = Copy(templatetype);
1542	    Setattr(new_function,"templatetype",tmp);
1543	    Delete(tmp);
1544	  }
1545          if (symtypename) {
1546	    Node *tmp = Copy(symtypename);
1547	    Setattr(new_function,"sym:typename",tmp);
1548	    Delete(tmp);
1549	  }
1550          if (templateparms) {
1551	    Parm *tmp = CopyParmList(templateparms);
1552	    Setattr(new_function,"templateparms",tmp);
1553	    Delete(tmp);
1554	  }
1555        } else if (strcmp(cntype,"constructor") == 0) {
1556          /* only copied for constructors as this is not a user defined feature - it is hard coded in the parser */
1557          if (GetFlag(function,"feature:new")) SetFlag(new_function,"feature:new");
1558        }
1559
1560        add_symbols(new_function);
1561        /* mark added functions as ones with overloaded parameters and point to the parsed method */
1562        Setattr(new_function,"defaultargs", n);
1563
1564        /* Point to the new function, extending the linked list */
1565        set_nextSibling(function, new_function);
1566	Delete(new_function);
1567        function = new_function;
1568	
1569	Delete(ntype);
1570      }
1571    } else {
1572      function = 0;
1573    }
1574  }
1575}
1576
1577/* -----------------------------------------------------------------------------
1578 * tag_nodes()
1579 *
1580 * Used by the parser to mark subtypes with extra information.
1581 * ----------------------------------------------------------------------------- */
1582
1583static void tag_nodes(Node *n, const_String_or_char_ptr attrname, DOH *value) {
1584  while (n) {
1585    Setattr(n, attrname, value);
1586    tag_nodes(firstChild(n), attrname, value);
1587    n = nextSibling(n);
1588  }
1589}
1590
1591%}
1592
1593%union {
1594  char  *id;
1595  List  *bases;
1596  struct Define {
1597    String *val;
1598    String *rawval;
1599    int     type;
1600    String *qualifier;
1601    String *bitfield;
1602    Parm   *throws;
1603    String *throwf;
1604  } dtype;
1605  struct {
1606    char *type;
1607    String *filename;
1608    int   line;
1609  } loc;
1610  struct {
1611    char      *id;
1612    SwigType  *type;
1613    String    *defarg;
1614    ParmList  *parms;
1615    short      have_parms;
1616    ParmList  *throws;
1617    String    *throwf;
1618  } decl;
1619  Parm         *tparms;
1620  struct {
1621    String     *method;
1622    Hash       *kwargs;
1623  } tmap;
1624  struct {
1625    String     *type;
1626    String     *us;
1627  } ptype;
1628  SwigType     *type;
1629  String       *str;
1630  Parm         *p;
1631  ParmList     *pl;
1632  int           intvalue;
1633  Node         *node;
1634};
1635
1636%token <id> ID
1637%token <str> HBLOCK
1638%token <id> POUND 
1639%token <id> STRING
1640%token <loc> INCLUDE IMPORT INSERT
1641%token <str> CHARCONST 
1642%token <dtype> NUM_INT NUM_FLOAT NUM_UNSIGNED NUM_LONG NUM_ULONG NUM_LONGLONG NUM_ULONGLONG NUM_BOOL
1643%token <intvalue> TYPEDEF
1644%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
1645%token LPAREN RPAREN COMMA SEMI EXTERN INIT LBRACE RBRACE PERIOD
1646%token CONST_QUAL VOLATILE REGISTER STRUCT UNION EQUAL SIZEOF MODULE LBRACKET RBRACKET
1647%token BEGINFILE ENDOFFILE
1648%token ILLEGAL CONSTANT
1649%token NAME RENAME NAMEWARN EXTEND PRAGMA FEATURE VARARGS
1650%token ENUM
1651%token CLASS TYPENAME PRIVATE PUBLIC PROTECTED COLON STATIC VIRTUAL FRIEND THROW CATCH EXPLICIT
1652%token USING
1653%token <node> NAMESPACE
1654%token NATIVE INLINE
1655%token TYPEMAP EXCEPT ECHO APPLY CLEAR SWIGTEMPLATE FRAGMENT
1656%token WARN 
1657%token LESSTHAN GREATERTHAN DELETE_KW
1658%token LESSTHANOREQUALTO GREATERTHANOREQUALTO EQUALTO NOTEQUALTO
1659%token QUESTIONMARK
1660%token TYPES PARMS
1661%token NONID DSTAR DCNOT
1662%token <intvalue> TEMPLATE
1663%token <str> OPERATOR
1664%token <str> COPERATOR
1665%token PARSETYPE PARSEPARM PARSEPARMS
1666
1667%left  CAST
1668%left  QUESTIONMARK
1669%left  LOR
1670%left  LAND
1671%left  OR
1672%left  XOR
1673%left  AND
1674%left  EQUALTO NOTEQUALTO
1675%left  GREATERTHAN LESSTHAN GREATERTHANOREQUALTO LESSTHANOREQUALTO
1676%left  LSHIFT RSHIFT
1677%left  PLUS MINUS
1678%left  STAR SLASH MODULO
1679%left  UMINUS NOT LNOT
1680%left  DCOLON
1681
1682%type <node>     program interface declaration swig_directive ;
1683
1684/* SWIG directives */
1685%type <node>     extend_directive apply_directive clear_directive constant_directive ;
1686%type <node>     echo_directive except_directive fragment_directive include_directive inline_directive ;
1687%type <node>     insert_directive module_directive name_directive native_directive ;
1688%type <node>     pragma_directive rename_directive feature_directive varargs_directive typemap_directive ;
1689%type <node>     types_directive template_directive warn_directive ;
1690
1691/* C declarations */
1692%type <node>     c_declaration c_decl c_decl_tail c_enum_decl c_enum_forward_decl c_constructor_decl ;
1693%type <n…

Large files files are truncated, but you can click here to view the full file