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 16char 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 31int yyparse(); 32 33/* NEW Variables */ 34 35static Node *top = 0; /* Top of the generated parse tree */ 36static int unnamed = 0; /* Unnamed datatype counter */ 37static Hash *extendhash = 0; /* Hash table of added methods */ 38static Hash *classes = 0; /* Hash table of classes */ 39static Symtab *prev_symtab = 0; 40static Node *current_class = 0; 41String *ModuleName = 0; 42static Node *module_node = 0; 43static String *Classprefix = 0; 44static String *Namespaceprefix = 0; 45static int inclass = 0; 46static char *last_cpptype = 0; 47static int inherit_list = 0; 48static Parm *template_parameters = 0; 49static int extendmode = 0; 50static int compact_default_args = 0; 51static int template_reduce = 0; 52static int cparse_externc = 0; 53 54static int max_class_levels = 0; 55static int class_level = 0; 56static Node **class_decl = NULL; 57 58/* ----------------------------------------------------------------------------- 59 * Assist Functions 60 * ----------------------------------------------------------------------------- */ 61 62 63 64/* Called by the parser (yyparse) when an error is found.*/ 65static void yyerror (const char *e) { 66 (void)e; 67} 68 69static 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 80static 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 156static char *typemap_lang = 0; /* Current language setting */ 157 158static int cplus_mode = 0; 159static 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 */ 168static int import_mode = 0; 169 170void SWIG_typemap_lang(const char *tm_lang) { 171 typemap_lang = Swig_copy_string(tm_lang); 172} 173 174void SWIG_cparse_set_compact_default_args(int defargs) { 175 compact_default_args = defargs; 176} 177 178int SWIG_cparse_template_reduce(int treduce) { 179 template_reduce = treduce; 180 return treduce; 181} 182 183/* ----------------------------------------------------------------------------- 184 * Assist functions 185 * ----------------------------------------------------------------------------- */ 186 187static 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 */ 193static int promote(int t1, int t2) { 194 t1 = promote_type(t1); 195 t2 = promote_type(t2); 196 return t1 > t2 ? t1 : t2; 197} 198 199static String *yyrename = 0; 200 201/* Forward renaming operator */ 202 203static String *resolve_node_scope(String *cname); 204 205 206Hash *Swig_cparse_features(void) { 207 static Hash *features_hash = 0; 208 if (!features_hash) features_hash = NewHash(); 209 return features_hash; 210} 211 212static 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 */ 232static String *add_oldname = 0; 233 234 235 236static 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 */ 254static String *make_unnamed() { 255 unnamed++; 256 return NewStringf("$unnamed%d$",unnamed); 257} 258 259/* Return if the node is a friend declaration */ 260static int is_friend(Node *n) { 261 return Cmp(Getattr(n,"storage"),"friend") == 0; 262} 263 264static int is_operator(String *name) { 265 return Strncmp(name,"operator ", 9) == 0; 266} 267 268 269/* Add declaration list to symbol table */ 270static int add_only_one = 0; 271 272static 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 517static 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 616static 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 669static 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 698static 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 713static 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 744static 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 765static 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 816static 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. */ 830static 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 853static Node *nscope = 0; 854static Node *nscope_inner = 0; 855static 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 979typedef 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 991static Nested *nested_list = 0; 992 993/* Add a function to the nested list */ 994 995static 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. */ 1006static 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 1073static 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 1188Node *Swig_cparse(File *f) { 1189 scanner_file(f); 1190 top = 0; 1191 yyparse(); 1192 return top; 1193} 1194 1195static 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. */ 1245static 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 */ 1280static 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. */ 1291static 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 1430static 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 1593program : 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 1627interface : 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 1637declaration : 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 1673swig_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 1700extend_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 1772apply_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 1782clear_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 1793constant_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 1847echo_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 1875except_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 */ 1899stringtype : string LBRACE parm RBRACE { 1900 $$ = NewHash(); 1901 Setattr($$,"value",$1); 1902 Setattr($$,"type",Getattr($3,"type")); 1903 } 1904 ; 1905 1906fname : 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 1923fragment_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 1960include_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 2015includetype : INCLUDE { $$.type = (char *) "include"; } 2016 | IMPORT { $$.type = (char *) "import"; ++import_mode;} 2017 ; 2018 2019/* ------------------------------------------------------------ 2020 %inline %{ ... %} 2021 ------------------------------------------------------------ */ 2022 2023inline_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 2074insert_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 2111module_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 2151name_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 2170native_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 2202pragma_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 2215pragma_arg : string { $$ = NewString($1); } 2216 | HBLOCK { $$ = $1; } 2217 ; 2218 2219pragma_lang : LPAREN ID RPAREN { $$ = $2; } 2220 | empty { $$ = (char *) "swig"; } 2221 ; 2222 2223/* ------------------------------------------------------------ 2224 %rename identifier newname; 2225 %rename identifier "newname"; 2226 ------------------------------------------------------------ */ 2227 2228rename_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 2331rename_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 */ 2361feature_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 2413stringbracesemi : stringbrace { $$ = $1; } 2414 | SEMI { $$ = 0; } 2415 | PARMS LPAREN parms RPAREN SEMI { $$ = $3; } 2416 ; 2417 2418featattr : 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 2433varargs_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 2469varargs_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 2500typemap_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 2538typemap_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 2563tm_list : typemap_parm tm_tail { 2564 $$ = $1; 2565 set_nextSibling($$,$2); 2566 } 2567 ; 2568 2569tm_tail : COMMA typemap_parm tm_tail { 2570 $$ = $2; 2571 set_nextSibling($$,$3); 2572 } 2573 | empty { $$ = 0;} 2574 ; 2575 2576typemap_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 2605types_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 2617template_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 2890warn_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 2900c_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 2943c_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 3004c_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 3036initializer : 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 3067c_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 3082c_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 3170c_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 3221cpp_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 3229cpp_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 3586cpp_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 3599cpp_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 3619cpp_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 3860cpp_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 3880template_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 3910templateparameters : templateparameter templateparameterstail { 3911 set_nextSibling($1,$2); 3912 $$ = $1; 3913 } 3914 | empty { $$ = 0; } 3915 ; 3916 3917templateparameter : templcpptype { 3918 $$ = NewParm(NewString($1), 0); 3919 } 3920 | parm { 3921 $$ = $1; 3922 } 3923 ; 3924 3925templateparameterstail : COMMA templateparameter templateparameterstail { 3926 set_nextSibling($2,$3); 3927 $$ = $2; 3928 } 3929 | empty { $$ = 0; } 3930 ; 3931 3932/* Namespace support */ 3933 3934cpp_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 3975cpp_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 4053cpp_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 4096cpp_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 4138cpp_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 4163cpp_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 */ 4228cpp_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 4280cpp_catch_decl : CATCH LPAREN parms RPAREN LBRACE { 4281 skip_balanced('{','}'); 4282 $$ = 0; 4283 } 4284 ; 4285 4286/* public: */ 4287cpp_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 4325cpp_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 4409nested_decl : declarator { $$ = $1;} 4410 | empty { $$.id = 0; } 4411 ; 4412 4413 4414/* These directives can be included inside a class definition */ 4415 4416cpp_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 4436cpp_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 4448cpp_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 4475anonymous_bitfield : storage_class type COLON expr SEMI { }; 4476 4477/* ====================================================================== 4478 * PRIMITIVES 4479 * ====================================================================== */ 4480 4481storage_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 4502parms : 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 4513rawparms : parm ptail { 4514 set_nextSibling($1,$2); 4515 $$ = $1; 4516 } 4517 | empty { $$ = 0; } 4518 ; 4519 4520ptail : COMMA parm ptail { 4521 set_nextSibling($2,$3); 4522 $$ = $2; 4523 } 4524 | empty { $$ = 0; } 4525 ; 4526 4527 4528parm : 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 4554valparms : 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 4567rawvalparms : valparm valptail { 4568 set_nextSibling($1,$2); 4569 $$ = $1; 4570 } 4571 | empty { $$ = 0; } 4572 ; 4573 4574valptail : COMMA valparm valptail { 4575 set_nextSibling($2,$3); 4576 $$ = $2; 4577 } 4578 | empty { $$ = 0; } 4579 ; 4580 4581 4582valparm : 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 4618def_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 4670parameter_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 4685typemap_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 4727declarator : 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 4803notso_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 4894direct_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 4986abstract_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 5061direct_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 5127pointer : 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 5151type_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 5161type_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 5169type : rawtype { 5170 $$ = $1; 5171 Replace($$,"typename ","", DOH_REPLACE_ANY); 5172 } 5173 ; 5174 5175rawtype : 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 5191type_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 5208primitive_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 5233primitive_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 5290type_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 5348definetype : { /* 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 5374ename : ID { $$ = $1; } 5375 | empty { $$ = (char *) 0;} 5376 ; 5377 5378enumlist : 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 5399edecl : 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 5427etype : 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 5442expr : 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 5462valexpr : 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 5543exprnum : 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 5552exprcompound : 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 5667inherit : raw_inherit { 5668 $$ = $1; 5669 } 5670 ; 5671 5672raw_inherit : COLON { inherit_list = 1; } base_list { $$ = $3; inherit_list = 0; } 5673 | empty { $$ = 0; } 5674 ; 5675 5676base_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 5702base_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 5728access_specifier : PUBLIC { $$ = (char*)"public"; } 5729 | PRIVATE { $$ = (char*)"private"; } 5730 | PROTECTED { $$ = (char*)"protected"; } 5731 ; 5732 5733 5734templcpptype : 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 5744cpptype : 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 5757opt_virtual : VIRTUAL 5758 | empty 5759 ; 5760 5761cpp_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 5783ctor_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 5821ctor_initializer : COLON mem_initializer_list 5822 | empty 5823 ; 5824 5825mem_initializer_list : mem_initializer 5826 | mem_initializer_list COMMA mem_initializer 5827 ; 5828 5829mem_initializer : idcolon LPAREN { 5830 skip_balanced('(',')'); 5831 Clear(scanner_ccode); 5832 } 5833 ; 5834 5835template_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 5844idstring : ID { $$ = $1; } 5845 | string { $$ = $1; } 5846 ; 5847 5848idstringopt : idstring { $$ = $1; } 5849 | empty { $$ = 0; } 5850 ; 5851 5852idcolon : 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 5875idcolontail : 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 5895idtemplate : 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 */ 5904idcolonnt : 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 5927idcolontailnt : 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 */ 5943string : string STRING { 5944 $$ = (char *) malloc(strlen($1)+strlen($2)+1); 5945 strcpy($$,$1); 5946 strcat($$,$2); 5947 } 5948 | STRING { $$ = $1;} 5949 ; 5950 5951stringbrace : string { 5952 $$ = NewString($1); 5953 } 5954 | LBRACE { 5955 skip_balanced('{','}'); 5956 $$ = NewString(scanner_ccode); 5957 } 5958 | HBLOCK { 5959 $$ = $1; 5960 } 5961 ; 5962 5963options : 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 */ 5980kwargs : 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 6011stringnum : string { 6012 $$ = $1; 6013 } 6014 | exprnum { 6015 $$ = Char($1.val); 6016 } 6017 ; 6018 6019empty : ; 6020 6021%% 6022 6023SwigType *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 6036Parm *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 6050ParmList *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 6067