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