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 * typesys.c 6 * 7 * SWIG type system management. These functions are used to manage 8 * the C++ type system including typenames, typedef, type scopes, 9 * inheritance, and namespaces. Generation of support code for the 10 * run-time type checker is also handled here. 11 * ----------------------------------------------------------------------------- */ 12 13char cvsroot_typesys_c[] = "$Id: typesys.c 11097 2009-01-30 10:27:37Z bhy $"; 14 15#include "swig.h" 16#include "cparse.h" 17 18/* ----------------------------------------------------------------------------- 19 * Synopsis 20 * 21 * The purpose of this module is to manage type names and scoping issues related 22 * to the C++ type system. The primary use is tracking typenames through typedef 23 * and inheritance. 24 * 25 * New typenames are introduced by typedef, class, and enum declarations. 26 * Each type is declared in a scope. This is either the global scope, a 27 * class, or a namespace. For example: 28 * 29 * typedef int A; // Typename A, in global scope 30 * namespace Foo { 31 * typedef int A; // Typename A, in scope Foo:: 32 * } 33 * class Bar { // Typename Bar, in global scope 34 * typedef int A; // Typename A, in scope Bar:: 35 * } 36 * 37 * To manage scopes, the type system is constructed as a tree of hash tables. Each 38 * hash table contains the following attributes: 39 * 40 * "name" - Scope name 41 * "qname" - Fully qualified typename 42 * "typetab" - Type table containing typenames and typedef information 43 * "symtab" - Hash table of symbols defined in a scope 44 * "inherit" - List of inherited scopes 45 * "parent" - Parent scope 46 * 47 * Typedef information is stored in the "typetab" hash table. For example, 48 * if you have these declarations: 49 * 50 * typedef int A; 51 * typedef A B; 52 * typedef B *C; 53 * 54 * typetab is built as follows: 55 * 56 * "A" : "int" 57 * "B" : "A" 58 * "C" : "p.B" 59 * 60 * To resolve a type back to its root type, one repeatedly expands on the type base. 61 * For example: 62 * 63 * C *[40] ---> a(40).p.C (string type representation, see stype.c) 64 * ---> a(40).p.p.B (C --> p.B) 65 * ---> a(40).p.p.A (B --> A) 66 * ---> a(40).p.p.int (A --> int) 67 * 68 * For inheritance, SWIG tries to resolve types back to the base class. For instance, if 69 * you have this: 70 * 71 * class Foo { 72 * public: 73 * typedef int Integer; 74 * }; 75 * 76 * class Bar : public Foo { 77 * void blah(Integer x); 78 * } 79 * 80 * The argument type of Bar::blah will be set to Foo::Integer. 81 * 82 * The scope-inheritance mechanism is used to manage C++ namespace aliases. 83 * For example, if you have this: 84 * 85 * namespace Foo { 86 * typedef int Integer; 87 * } 88 * 89 * namespace F = Foo; 90 * 91 * In this case, "F::" is defined as a scope that "inherits" from Foo. Internally, 92 * "F::" will merely be an empty scope that refers to Foo. SWIG will never 93 * place new type information into a namespace alias---attempts to do so 94 * will generate a warning message (in the parser) and will place information into 95 * Foo instead. 96 * 97 *----------------------------------------------------------------------------- */ 98 99static Typetab *current_scope = 0; /* Current type scope */ 100static Hash *current_typetab = 0; /* Current type table */ 101static Hash *current_symtab = 0; /* Current symbol table */ 102static Typetab *global_scope = 0; /* The global scope */ 103static Hash *scopes = 0; /* Hash table containing fully qualified scopes */ 104 105/* Performance optimization */ 106#define SWIG_TYPEDEF_RESOLVE_CACHE 107static Hash *typedef_resolve_cache = 0; 108static Hash *typedef_all_cache = 0; 109static Hash *typedef_qualified_cache = 0; 110 111static Typetab *SwigType_find_scope(Typetab *s, String *nameprefix); 112 113/* common attribute keys, to avoid calling find_key all the times */ 114 115/* 116 Enable this one if your language fully support SwigValueWrapper<T>. 117 118 Leaving at '0' keeps the old swig behavior, which is not 119 always safe, but is well known. 120 121 Setting at '1' activates the new scheme, which is always safe but 122 it requires all the typemaps to be ready for that. 123 124*/ 125static int value_wrapper_mode = 0; 126int Swig_value_wrapper_mode(int mode) { 127 value_wrapper_mode = mode; 128 return mode; 129} 130 131 132static void flush_cache() { 133 typedef_resolve_cache = 0; 134 typedef_all_cache = 0; 135 typedef_qualified_cache = 0; 136} 137 138/* Initialize the scoping system */ 139 140void SwigType_typesystem_init() { 141 if (global_scope) 142 Delete(global_scope); 143 if (scopes) 144 Delete(scopes); 145 146 current_scope = NewHash(); 147 global_scope = current_scope; 148 149 Setattr(current_scope, "name", ""); /* No name for global scope */ 150 current_typetab = NewHash(); 151 Setattr(current_scope, "typetab", current_typetab); 152 153 current_symtab = 0; 154 scopes = NewHash(); 155 Setattr(scopes, "", current_scope); 156} 157 158 159/* ----------------------------------------------------------------------------- 160 * SwigType_typedef() 161 * 162 * Defines a new typedef in the current scope. Returns -1 if the type name is 163 * already defined. 164 * ----------------------------------------------------------------------------- */ 165 166int SwigType_typedef(SwigType *type, const_String_or_char_ptr name) { 167 if (Getattr(current_typetab, name)) 168 return -1; /* Already defined */ 169 if (Strcmp(type, name) == 0) { /* Can't typedef a name to itself */ 170 return 0; 171 } 172 173 /* Check if 'type' is already a scope. If so, we create an alias in the type 174 system for it. This is needed to make strange nested scoping problems work 175 correctly. */ 176 { 177 Typetab *t = SwigType_find_scope(current_scope, type); 178 if (t) { 179 SwigType_new_scope(name); 180 SwigType_inherit_scope(t); 181 SwigType_pop_scope(); 182 } 183 } 184 Setattr(current_typetab, name, type); 185 flush_cache(); 186 return 0; 187} 188 189 190/* ----------------------------------------------------------------------------- 191 * SwigType_typedef_class() 192 * 193 * Defines a class in the current scope. 194 * ----------------------------------------------------------------------------- */ 195 196int SwigType_typedef_class(const_String_or_char_ptr name) { 197 String *cname; 198 /* Printf(stdout,"class : '%s'\n", name); */ 199 if (Getattr(current_typetab, name)) 200 return -1; /* Already defined */ 201 cname = NewString(name); 202 Setmeta(cname, "class", "1"); 203 Setattr(current_typetab, cname, cname); 204 Delete(cname); 205 flush_cache(); 206 return 0; 207} 208 209/* ----------------------------------------------------------------------------- 210 * SwigType_scope_name() 211 * 212 * Returns the qualified scope name of a type table 213 * ----------------------------------------------------------------------------- */ 214 215String *SwigType_scope_name(Typetab *ttab) { 216 String *qname = NewString(Getattr(ttab, "name")); 217 ttab = Getattr(ttab, "parent"); 218 while (ttab) { 219 String *pname = Getattr(ttab, "name"); 220 if (Len(pname)) { 221 Insert(qname, 0, "::"); 222 Insert(qname, 0, pname); 223 } 224 ttab = Getattr(ttab, "parent"); 225 } 226 return qname; 227} 228 229/* ----------------------------------------------------------------------------- 230 * SwigType_new_scope() 231 * 232 * Creates a new scope 233 * ----------------------------------------------------------------------------- */ 234 235void SwigType_new_scope(const_String_or_char_ptr name) { 236 Typetab *s; 237 Hash *ttab; 238 String *qname; 239 240 if (!name) { 241 name = "<unnamed>"; 242 } 243 s = NewHash(); 244 Setattr(s, "name", name); 245 Setattr(s, "parent", current_scope); 246 ttab = NewHash(); 247 Setattr(s, "typetab", ttab); 248 249 /* Build fully qualified name and */ 250 qname = SwigType_scope_name(s); 251 Setattr(scopes, qname, s); 252 Setattr(s, "qname", qname); 253 Delete(qname); 254 255 current_scope = s; 256 current_typetab = ttab; 257 current_symtab = 0; 258 flush_cache(); 259} 260 261/* ----------------------------------------------------------------------------- 262 * SwigType_inherit_scope() 263 * 264 * Makes the current scope inherit from another scope. This is used for both 265 * C++ class inheritance, namespaces, and namespace aliases. 266 * ----------------------------------------------------------------------------- */ 267 268void SwigType_inherit_scope(Typetab *scope) { 269 List *inherits; 270 int i, len; 271 inherits = Getattr(current_scope, "inherit"); 272 if (!inherits) { 273 inherits = NewList(); 274 Setattr(current_scope, "inherit", inherits); 275 Delete(inherits); 276 } 277 assert(scope != current_scope); 278 279 len = Len(inherits); 280 for (i = 0; i < len; i++) { 281 Node *n = Getitem(inherits, i); 282 if (n == scope) 283 return; 284 } 285 Append(inherits, scope); 286} 287 288/* ----------------------------------------------------------------------------- 289 * SwigType_scope_alias() 290 * 291 * Creates a scope-alias. 292 * ----------------------------------------------------------------------------- */ 293 294void SwigType_scope_alias(String *aliasname, Typetab *ttab) { 295 String *q; 296 /* Printf(stdout,"alias: '%s' '%x'\n", aliasname, ttab); */ 297 q = SwigType_scope_name(current_scope); 298 if (Len(q)) { 299 Append(q, "::"); 300 } 301 Append(q, aliasname); 302 Setattr(scopes, q, ttab); 303 flush_cache(); 304} 305 306/* ----------------------------------------------------------------------------- 307 * SwigType_using_scope() 308 * 309 * Import another scope into this scope. 310 * ----------------------------------------------------------------------------- */ 311 312void SwigType_using_scope(Typetab *scope) { 313 SwigType_inherit_scope(scope); 314 { 315 List *ulist; 316 int i, len; 317 ulist = Getattr(current_scope, "using"); 318 if (!ulist) { 319 ulist = NewList(); 320 Setattr(current_scope, "using", ulist); 321 Delete(ulist); 322 } 323 assert(scope != current_scope); 324 len = Len(ulist); 325 for (i = 0; i < len; i++) { 326 Typetab *n = Getitem(ulist, i); 327 if (n == scope) 328 return; 329 } 330 Append(ulist, scope); 331 } 332 flush_cache(); 333} 334 335/* ----------------------------------------------------------------------------- 336 * SwigType_pop_scope() 337 * 338 * Pop off the last scope and perform a merge operation. Returns the hash 339 * table for the scope that was popped off. 340 * ----------------------------------------------------------------------------- */ 341 342Typetab *SwigType_pop_scope() { 343 Typetab *t, *old = current_scope; 344 t = Getattr(current_scope, "parent"); 345 if (!t) 346 t = global_scope; 347 current_scope = t; 348 current_typetab = Getattr(t, "typetab"); 349 current_symtab = Getattr(t, "symtab"); 350 flush_cache(); 351 return old; 352} 353 354/* ----------------------------------------------------------------------------- 355 * SwigType_set_scope() 356 * 357 * Set the scope. Returns the old scope. 358 * ----------------------------------------------------------------------------- */ 359 360Typetab *SwigType_set_scope(Typetab *t) { 361 Typetab *old = current_scope; 362 if (!t) 363 t = global_scope; 364 current_scope = t; 365 current_typetab = Getattr(t, "typetab"); 366 current_symtab = Getattr(t, "symtab"); 367 flush_cache(); 368 return old; 369} 370 371/* ----------------------------------------------------------------------------- 372 * SwigType_attach_symtab() 373 * 374 * Attaches a symbol table to a type scope 375 * ----------------------------------------------------------------------------- */ 376 377void SwigType_attach_symtab(Symtab *sym) { 378 Setattr(current_scope, "symtab", sym); 379 current_symtab = sym; 380} 381 382/* ----------------------------------------------------------------------------- 383 * SwigType_print_scope() 384 * 385 * Debugging function for printing out current scope 386 * ----------------------------------------------------------------------------- */ 387 388void SwigType_print_scope(Typetab *t) { 389 Hash *ttab; 390 Iterator i, j; 391 392 for (i = First(scopes); i.key; i = Next(i)) { 393 t = i.item; 394 ttab = Getattr(i.item, "typetab"); 395 396 Printf(stdout, "Type scope '%s' (%x)\n", i.key, i.item); 397 { 398 List *inherit = Getattr(i.item, "inherit"); 399 if (inherit) { 400 Iterator j; 401 for (j = First(inherit); j.item; j = Next(j)) { 402 Printf(stdout, " Inherits from '%s' (%x)\n", Getattr(j.item, "qname"), j.item); 403 } 404 } 405 } 406 Printf(stdout, "-------------------------------------------------------------\n"); 407 for (j = First(ttab); j.key; j = Next(j)) { 408 Printf(stdout, "%40s -> %s\n", j.key, j.item); 409 } 410 } 411} 412 413static Typetab *SwigType_find_scope(Typetab *s, String *nameprefix) { 414 Typetab *ss; 415 String *nnameprefix = 0; 416 static int check_parent = 1; 417 418 /* Printf(stdout,"find_scope: %x(%s) '%s'\n", s, Getattr(s,"name"), nameprefix); */ 419 420 if (SwigType_istemplate(nameprefix)) { 421 nnameprefix = SwigType_typedef_resolve_all(nameprefix); 422 nameprefix = nnameprefix; 423 } 424 425 ss = s; 426 while (ss) { 427 String *full; 428 String *qname = Getattr(ss, "qname"); 429 if (qname) { 430 full = NewStringf("%s::%s", qname, nameprefix); 431 } else { 432 full = NewString(nameprefix); 433 } 434 if (Getattr(scopes, full)) { 435 s = Getattr(scopes, full); 436 } else { 437 s = 0; 438 } 439 Delete(full); 440 if (s) { 441 if (nnameprefix) 442 Delete(nnameprefix); 443 return s; 444 } 445 if (!s) { 446 /* Check inheritance */ 447 List *inherit; 448 inherit = Getattr(ss, "using"); 449 if (inherit) { 450 Typetab *ttab; 451 int i, len; 452 len = Len(inherit); 453 for (i = 0; i < len; i++) { 454 int oldcp = check_parent; 455 ttab = Getitem(inherit, i); 456 check_parent = 0; 457 s = SwigType_find_scope(ttab, nameprefix); 458 check_parent = oldcp; 459 if (s) { 460 if (nnameprefix) 461 Delete(nnameprefix); 462 return s; 463 } 464 } 465 } 466 } 467 if (!check_parent) 468 break; 469 ss = Getattr(ss, "parent"); 470 } 471 if (nnameprefix) 472 Delete(nnameprefix); 473 return 0; 474} 475 476/* ----------------------------------------------------------------------------- 477 * typedef_resolve() 478 * 479 * Resolves a typedef and returns a new type string. Returns 0 if there is no 480 * typedef mapping. base is a name without qualification. 481 * Internal function. 482 * ----------------------------------------------------------------------------- */ 483 484static Typetab *resolved_scope = 0; 485 486/* Internal function */ 487 488static SwigType *_typedef_resolve(Typetab *s, String *base, int look_parent) { 489 Hash *ttab; 490 SwigType *type = 0; 491 List *inherit; 492 Typetab *parent; 493 494 /* if (!s) return 0; *//* now is checked bellow */ 495 /* Printf(stdout,"Typetab %s : %s\n", Getattr(s,"name"), base); */ 496 497 if (!Getmark(s)) { 498 Setmark(s, 1); 499 500 ttab = Getattr(s, "typetab"); 501 type = Getattr(ttab, base); 502 if (type) { 503 resolved_scope = s; 504 Setmark(s, 0); 505 } else { 506 /* Hmmm. Not found in my scope. It could be in an inherited scope */ 507 inherit = Getattr(s, "inherit"); 508 if (inherit) { 509 int i, len; 510 len = Len(inherit); 511 for (i = 0; i < len; i++) { 512 type = _typedef_resolve(Getitem(inherit, i), base, 0); 513 if (type) { 514 Setmark(s, 0); 515 break; 516 } 517 } 518 } 519 if (!type) { 520 /* Hmmm. Not found in my scope. check parent */ 521 if (look_parent) { 522 parent = Getattr(s, "parent"); 523 type = parent ? _typedef_resolve(parent, base, 1) : 0; 524 } 525 } 526 Setmark(s, 0); 527 } 528 } 529 return type; 530} 531 532static SwigType *typedef_resolve(Typetab *s, String *base) { 533 return _typedef_resolve(s, base, 1); 534} 535 536 537/* ----------------------------------------------------------------------------- 538 * SwigType_typedef_resolve() 539 * ----------------------------------------------------------------------------- */ 540 541/* #define SWIG_DEBUG */ 542SwigType *SwigType_typedef_resolve(const SwigType *t) { 543 String *base; 544 String *type = 0; 545 String *r = 0; 546 Typetab *s; 547 Hash *ttab; 548 String *namebase = 0; 549 String *nameprefix = 0; 550 int newtype = 0; 551 552 /* 553 if (!noscope) { 554 noscope = NewStringEmpty(); 555 } 556 */ 557 558 resolved_scope = 0; 559 560#ifdef SWIG_TYPEDEF_RESOLVE_CACHE 561 if (!typedef_resolve_cache) { 562 typedef_resolve_cache = NewHash(); 563 } 564 r = Getattr(typedef_resolve_cache, t); 565 if (r) { 566 resolved_scope = Getmeta(r, "scope"); 567 return Copy(r); 568 } 569#endif 570 571 base = SwigType_base(t); 572 573#ifdef SWIG_DEBUG 574 Printf(stdout, "base = '%s' t='%s'\n", base, t); 575#endif 576 577 if (SwigType_issimple(base)) { 578 s = current_scope; 579 ttab = current_typetab; 580 if (strncmp(Char(base), "::", 2) == 0) { 581 s = global_scope; 582 ttab = Getattr(s, "typetab"); 583 Delitem(base, 0); 584 Delitem(base, 0); 585 } 586 /* Do a quick check in the local scope */ 587 type = Getattr(ttab, base); 588 if (type) { 589 resolved_scope = s; 590 } 591 if (!type) { 592 /* Didn't find in this scope. We need to do a little more searching */ 593 if (Swig_scopename_check(base)) { 594 /* A qualified name. */ 595 Swig_scopename_split(base, &nameprefix, &namebase); 596#ifdef SWIG_DEBUG 597 Printf(stdout, "nameprefix = '%s'\n", nameprefix); 598#endif 599 if (nameprefix) { 600 /* Name had a prefix on it. See if we can locate the proper scope for it */ 601 s = SwigType_find_scope(s, nameprefix); 602 603 /* Couldn't locate a scope for the type. */ 604 if (!s) { 605 Delete(base); 606 Delete(namebase); 607 Delete(nameprefix); 608 r = 0; 609 goto return_result; 610 } 611 /* Try to locate the name starting in the scope */ 612#ifdef SWIG_DEBUG 613 Printf(stdout, "namebase = '%s'\n", namebase); 614#endif 615 type = typedef_resolve(s, namebase); 616 if (type) { 617 /* we need to look for the resolved type, this will also 618 fix the resolved_scope if 'type' and 'namebase' are 619 declared in different scopes */ 620 String *rtype = 0; 621 rtype = typedef_resolve(resolved_scope, type); 622 if (rtype) 623 type = rtype; 624 } 625#ifdef SWIG_DEBUG 626 Printf(stdout, "%s type = '%s'\n", Getattr(s, "name"), type); 627#endif 628 if ((type) && (!Swig_scopename_check(type)) && resolved_scope) { 629 Typetab *rtab = resolved_scope; 630 String *qname = Getattr(resolved_scope, "qname"); 631 /* If qualified *and* the typename is defined from the resolved scope, we qualify */ 632 if ((qname) && typedef_resolve(resolved_scope, type)) { 633 type = Copy(type); 634 Insert(type, 0, "::"); 635 Insert(type, 0, qname); 636#ifdef SWIG_DEBUG 637 Printf(stdout, "qual %s \n", type); 638#endif 639 newtype = 1; 640 } 641 resolved_scope = rtab; 642 } 643 } else { 644 /* Name is unqualified. */ 645 type = typedef_resolve(s, base); 646 } 647 } else { 648 /* Name is unqualified. */ 649 type = typedef_resolve(s, base); 650 } 651 } 652 653 if (type && (Equal(base, type))) { 654 if (newtype) 655 Delete(type); 656 Delete(base); 657 Delete(namebase); 658 Delete(nameprefix); 659 r = 0; 660 goto return_result; 661 } 662 663 /* If the type is a template, and no typedef was found, we need to check the 664 template arguments one by one to see if they can be resolved. */ 665 666 if (!type && SwigType_istemplate(base)) { 667 List *tparms; 668 String *suffix; 669 int i, sz; 670 int rep = 0; 671 type = SwigType_templateprefix(base); 672 newtype = 1; 673 suffix = SwigType_templatesuffix(base); 674 Append(type, "<("); 675 tparms = SwigType_parmlist(base); 676 sz = Len(tparms); 677 for (i = 0; i < sz; i++) { 678 SwigType *tpr; 679 SwigType *tp = Getitem(tparms, i); 680 if (!rep) { 681 tpr = SwigType_typedef_resolve(tp); 682 } else { 683 tpr = 0; 684 } 685 if (tpr) { 686 Append(type, tpr); 687 Delete(tpr); 688 rep = 1; 689 } else { 690 Append(type, tp); 691 } 692 if ((i + 1) < sz) 693 Append(type, ","); 694 } 695 Append(type, ")>"); 696 Append(type, suffix); 697 Delete(suffix); 698 Delete(tparms); 699 if (!rep) { 700 Delete(type); 701 type = 0; 702 } 703 } 704 if (namebase) 705 Delete(namebase); 706 if (nameprefix) 707 Delete(nameprefix); 708 } else { 709 if (SwigType_isfunction(base)) { 710 List *parms; 711 int i, sz; 712 int rep = 0; 713 type = NewString("f("); 714 newtype = 1; 715 parms = SwigType_parmlist(base); 716 sz = Len(parms); 717 for (i = 0; i < sz; i++) { 718 SwigType *tpr; 719 SwigType *tp = Getitem(parms, i); 720 if (!rep) { 721 tpr = SwigType_typedef_resolve(tp); 722 } else { 723 tpr = 0; 724 } 725 if (tpr) { 726 Append(type, tpr); 727 Delete(tpr); 728 rep = 1; 729 } else { 730 Append(type, tp); 731 } 732 if ((i + 1) < sz) 733 Append(type, ","); 734 } 735 Append(type, ")."); 736 Delete(parms); 737 if (!rep) { 738 Delete(type); 739 type = 0; 740 } 741 } else if (SwigType_ismemberpointer(base)) { 742 String *rt; 743 String *mtype = SwigType_parm(base); 744 rt = SwigType_typedef_resolve(mtype); 745 if (rt) { 746 type = NewStringf("m(%s).", rt); 747 newtype = 1; 748 Delete(rt); 749 } 750 Delete(mtype); 751 } else { 752 type = 0; 753 } 754 } 755 r = SwigType_prefix(t); 756 if (!type) { 757 if (r && Len(r)) { 758 char *cr = Char(r); 759 if ((strstr(cr, "f(") || (strstr(cr, "m(")))) { 760 SwigType *rt = SwigType_typedef_resolve(r); 761 if (rt) { 762 Delete(r); 763 Append(rt, base); 764 Delete(base); 765 r = rt; 766 goto return_result; 767 } 768 } 769 } 770 Delete(r); 771 Delete(base); 772 r = 0; 773 goto return_result; 774 } 775 Delete(base); 776 Append(r, type); 777 if (newtype) { 778 Delete(type); 779 } 780 781return_result: 782#ifdef SWIG_TYPEDEF_RESOLVE_CACHE 783 { 784 String *key = NewString(t); 785 if (r) { 786 SwigType *r1; 787 Setattr(typedef_resolve_cache, key, r); 788 Setmeta(r, "scope", resolved_scope); 789 r1 = Copy(r); 790 Delete(r); 791 r = r1; 792 } 793 Delete(key); 794 } 795#endif 796 return r; 797} 798 799/* ----------------------------------------------------------------------------- 800 * SwigType_typedef_resolve_all() 801 * 802 * Fully resolve a type down to its most basic datatype 803 * ----------------------------------------------------------------------------- */ 804 805SwigType *SwigType_typedef_resolve_all(SwigType *t) { 806 SwigType *n; 807 SwigType *r; 808 809 /* Check to see if the typedef resolve has been done before by checking the cache */ 810 if (!typedef_all_cache) { 811 typedef_all_cache = NewHash(); 812 } 813 r = Getattr(typedef_all_cache, t); 814 if (r) { 815 return Copy(r); 816 } 817 818 /* Recursively resolve the typedef */ 819 r = NewString(t); 820 while ((n = SwigType_typedef_resolve(r))) { 821 Delete(r); 822 r = n; 823 } 824 825 /* Add the typedef to the cache for next time it is looked up */ 826 { 827 String *key; 828 SwigType *rr = Copy(r); 829 key = NewString(t); 830 Setattr(typedef_all_cache, key, rr); 831 Delete(key); 832 Delete(rr); 833 } 834 return r; 835} 836 837 838/* ----------------------------------------------------------------------------- 839 * SwigType_typedef_qualified() 840 * 841 * Given a type declaration, this function tries to fully qualify it according to 842 * typedef scope rules. 843 * Inconsistency to be fixed: ::Foo returns ::Foo, whereas ::Foo * returns Foo * 844 * ----------------------------------------------------------------------------- */ 845 846SwigType *SwigType_typedef_qualified(SwigType *t) { 847 List *elements; 848 String *result; 849 int i, len; 850 851 if (strncmp(Char(t), "::", 2) == 0) { 852 return Copy(t); 853 } 854 855 if (!typedef_qualified_cache) 856 typedef_qualified_cache = NewHash(); 857 result = Getattr(typedef_qualified_cache, t); 858 if (result) { 859 String *rc = Copy(result); 860 return rc; 861 } 862 863 result = NewStringEmpty(); 864 elements = SwigType_split(t); 865 len = Len(elements); 866 for (i = 0; i < len; i++) { 867 String *ty = 0; 868 String *e = Getitem(elements, i); 869 if (SwigType_issimple(e)) { 870 if (!SwigType_istemplate(e)) { 871 String *isenum = 0; 872 if (SwigType_isenum(e)) { 873 isenum = NewString("enum "); 874 ty = NewString(Char(e) + 5); 875 e = ty; 876 } 877 resolved_scope = 0; 878 if (typedef_resolve(current_scope, e)) { 879 /* resolved_scope contains the scope that actually resolved the symbol */ 880 String *qname = Getattr(resolved_scope, "qname"); 881 if (qname) { 882 Insert(e, 0, "::"); 883 Insert(e, 0, qname); 884 } 885 } else { 886 if (Swig_scopename_check(e)) { 887 String *qlast; 888 String *qname; 889 Swig_scopename_split(e, &qname, &qlast); 890 if (qname) { 891 String *tqname = SwigType_typedef_qualified(qname); 892 Clear(e); 893 Printf(e, "%s::%s", tqname, qlast); 894 Delete(qname); 895 Delete(tqname); 896 } 897 Delete(qlast); 898 899 /* Automatic template instantiation might go here??? */ 900 } else { 901 /* It's a bare name. It's entirely possible, that the 902 name is part of a namespace. We'll check this by unrolling 903 out of the current scope */ 904 905 Typetab *cs = current_scope; 906 while (cs) { 907 String *qs = SwigType_scope_name(cs); 908 if (Len(qs)) { 909 Append(qs, "::"); 910 } 911 Append(qs, e); 912 if (Getattr(scopes, qs)) { 913 Clear(e); 914 Append(e, qs); 915 Delete(qs); 916 break; 917 } 918 Delete(qs); 919 cs = Getattr(cs, "parent"); 920 } 921 } 922 } 923 if (isenum) { 924 Insert(e, 0, isenum); 925 Delete(isenum); 926 } 927 } else { 928 /* Template. We need to qualify template parameters as well as the template itself */ 929 String *tprefix, *qprefix; 930 String *tsuffix; 931 Iterator pi; 932 Parm *p; 933 List *parms; 934 ty = Swig_symbol_template_deftype(e, current_symtab); 935 e = ty; 936 parms = SwigType_parmlist(e); 937 tprefix = SwigType_templateprefix(e); 938 tsuffix = SwigType_templatesuffix(e); 939 qprefix = SwigType_typedef_qualified(tprefix); 940 Append(qprefix, "<("); 941 pi = First(parms); 942 while ((p = pi.item)) { 943 String *qt = SwigType_typedef_qualified(p); 944 if (Equal(qt, p)) { /* && (!Swig_scopename_check(qt))) */ 945 /* No change in value. It is entirely possible that the parameter is an integer value. 946 If there is a symbol table associated with this scope, we're going to check for this */ 947 948 if (current_symtab) { 949 Node *lastnode = 0; 950 String *value = Copy(p); 951 while (1) { 952 Node *n = Swig_symbol_clookup(value, current_symtab); 953 if (n == lastnode) 954 break; 955 lastnode = n; 956 if (n) { 957 char *ntype = Char(nodeType(n)); 958 if (strcmp(ntype, "enumitem") == 0) { 959 /* An enum item. Generate a fully qualified name */ 960 String *qn = Swig_symbol_qualified(n); 961 if (Len(qn)) { 962 Append(qn, "::"); 963 Append(qn, Getattr(n, "name")); 964 Delete(value); 965 value = qn; 966 continue; 967 } else { 968 Delete(qn); 969 break; 970 } 971 } else if ((strcmp(ntype, "cdecl") == 0) && (Getattr(n, "value"))) { 972 Delete(value); 973 value = Copy(Getattr(n, "value")); 974 continue; 975 } 976 } 977 break; 978 } 979 Append(qprefix, value); 980 Delete(value); 981 } else { 982 Append(qprefix, p); 983 } 984 } else { 985 Append(qprefix, qt); 986 } 987 Delete(qt); 988 pi = Next(pi); 989 if (pi.item) { 990 Append(qprefix, ","); 991 } 992 } 993 Append(qprefix, ")>"); 994 Append(qprefix, tsuffix); 995 Delete(tsuffix); 996 Clear(e); 997 Append(e, qprefix); 998 Delete(tprefix); 999 Delete(qprefix); 1000 Delete(parms); 1001 } 1002 if (strncmp(Char(e), "::", 2) == 0) { 1003 Delitem(e, 0); 1004 Delitem(e, 0); 1005 } 1006 Append(result, e); 1007 Delete(ty); 1008 } else if (SwigType_isfunction(e)) { 1009 List *parms = SwigType_parmlist(e); 1010 String *s = NewString("f("); 1011 Iterator pi; 1012 pi = First(parms); 1013 while (pi.item) { 1014 String *pq = SwigType_typedef_qualified(pi.item); 1015 Append(s, pq); 1016 Delete(pq); 1017 pi = Next(pi); 1018 if (pi.item) { 1019 Append(s, ","); 1020 } 1021 } 1022 Append(s, ")."); 1023 Append(result, s); 1024 Delete(s); 1025 Delete(parms); 1026 } else if (SwigType_isarray(e)) { 1027 String *ndim; 1028 String *dim = SwigType_parm(e); 1029 ndim = Swig_symbol_string_qualify(dim, 0); 1030 Printf(result, "a(%s).", ndim); 1031 Delete(dim); 1032 Delete(ndim); 1033 } else { 1034 Append(result, e); 1035 } 1036 } 1037 Delete(elements); 1038 { 1039 String *key, *cresult; 1040 key = NewString(t); 1041 cresult = NewString(result); 1042 Setattr(typedef_qualified_cache, key, cresult); 1043 Delete(key); 1044 Delete(cresult); 1045 } 1046 return result; 1047} 1048 1049/* ----------------------------------------------------------------------------- 1050 * SwigType_istypedef() 1051 * 1052 * Checks a typename to see if it is a typedef. 1053 * ----------------------------------------------------------------------------- */ 1054 1055int SwigType_istypedef(SwigType *t) { 1056 String *type; 1057 1058 type = SwigType_typedef_resolve(t); 1059 if (type) { 1060 Delete(type); 1061 return 1; 1062 } else { 1063 return 0; 1064 } 1065} 1066 1067 1068/* ----------------------------------------------------------------------------- 1069 * SwigType_typedef_using() 1070 * 1071 * Processes a 'using' declaration to import types from one scope into another. 1072 * Name is a qualified name like A::B. 1073 * ----------------------------------------------------------------------------- */ 1074 1075int SwigType_typedef_using(const_String_or_char_ptr name) { 1076 String *base; 1077 String *td; 1078 String *prefix; 1079 Typetab *s; 1080 Typetab *tt = 0; 1081 1082 String *defined_name = 0; 1083 1084 /* Printf(stdout,"using %s\n", name); */ 1085 1086 if (!Swig_scopename_check(name)) 1087 return -1; /* Not properly qualified */ 1088 base = Swig_scopename_last(name); 1089 1090 /* See if the base is already defined in this scope */ 1091 if (Getattr(current_typetab, base)) { 1092 Delete(base); 1093 return -1; 1094 } 1095 1096 /* See if the using name is a scope */ 1097 /* tt = SwigType_find_scope(current_scope,name); 1098 Printf(stdout,"tt = %x, name = '%s'\n", tt, name); */ 1099 1100 /* We set up a typedef B --> A::B */ 1101 Setattr(current_typetab, base, name); 1102 1103 /* Find the scope name where the symbol is defined */ 1104 td = SwigType_typedef_resolve(name); 1105 /* Printf(stdout,"td = '%s' %x\n", td, resolved_scope); */ 1106 if (resolved_scope) { 1107 defined_name = Getattr(resolved_scope, "qname"); 1108 if (defined_name) { 1109 defined_name = Copy(defined_name); 1110 Append(defined_name, "::"); 1111 Append(defined_name, base); 1112 /* Printf(stdout,"defined_name = '%s'\n", defined_name); */ 1113 tt = SwigType_find_scope(current_scope, defined_name); 1114 } 1115 } 1116 if (td) 1117 Delete(td); 1118 1119 1120 /* Figure out the scope the using directive refers to */ 1121 { 1122 prefix = Swig_scopename_prefix(name); 1123 s = SwigType_find_scope(current_scope, prefix); 1124 if (s) { 1125 Hash *ttab = Getattr(s, "typetab"); 1126 if (!Getattr(ttab, base) && defined_name) { 1127 Setattr(ttab, base, defined_name); 1128 } 1129 } 1130 } 1131 1132 if (tt) { 1133 /* Using directive had its own scope. We need to create a new scope for it */ 1134 SwigType_new_scope(base); 1135 SwigType_inherit_scope(tt); 1136 SwigType_pop_scope(); 1137 } 1138 1139 if (defined_name) 1140 Delete(defined_name); 1141 Delete(prefix); 1142 Delete(base); 1143 return 0; 1144} 1145 1146/* ----------------------------------------------------------------------------- 1147 * SwigType_isclass() 1148 * 1149 * Determines if a type defines a class or not. A class is defined by 1150 * its type-table entry maps to itself. Note: a pointer to a class is not 1151 * a class. 1152 * ----------------------------------------------------------------------------- */ 1153 1154int SwigType_isclass(SwigType *t) { 1155 SwigType *qty, *qtys; 1156 int isclass = 0; 1157 1158 qty = SwigType_typedef_resolve_all(t); 1159 qtys = SwigType_strip_qualifiers(qty); 1160 if (SwigType_issimple(qtys)) { 1161 String *td = SwigType_typedef_resolve(qtys); 1162 if (td) { 1163 Delete(td); 1164 } 1165 if (resolved_scope) { 1166 isclass = 1; 1167 } 1168 /* Hmmm. Not a class. If a template, it might be uninstantiated */ 1169 if (!isclass && SwigType_istemplate(qtys)) { 1170 String *tp = SwigType_templateprefix(qtys); 1171 if (Strcmp(tp, t) != 0) { 1172 isclass = SwigType_isclass(tp); 1173 } 1174 Delete(tp); 1175 } 1176 } 1177 Delete(qty); 1178 Delete(qtys); 1179 return isclass; 1180} 1181 1182/* ----------------------------------------------------------------------------- 1183 * SwigType_type() 1184 * 1185 * Returns an integer code describing the datatype. This is only used for 1186 * compatibility with SWIG1.1 language modules and is likely to go away once 1187 * everything is based on typemaps. 1188 * ----------------------------------------------------------------------------- */ 1189 1190int SwigType_type(SwigType *t) { 1191 char *c; 1192 /* Check for the obvious stuff */ 1193 c = Char(t); 1194 1195 if (strncmp(c, "p.", 2) == 0) { 1196 if (SwigType_type(c + 2) == T_CHAR) 1197 return T_STRING; 1198 else 1199 return T_POINTER; 1200 } 1201 if (strncmp(c, "a(", 2) == 0) 1202 return T_ARRAY; 1203 if (strncmp(c, "r.", 2) == 0) 1204 return T_REFERENCE; 1205 if (strncmp(c, "m(", 2) == 0) 1206 return T_MPOINTER; 1207 if (strncmp(c, "q(", 2) == 0) { 1208 while (*c && (*c != '.')) 1209 c++; 1210 if (*c) 1211 return SwigType_type(c + 1); 1212 return T_ERROR; 1213 } 1214 if (strncmp(c, "f(", 2) == 0) 1215 return T_FUNCTION; 1216 1217 /* Look for basic types */ 1218 if (strcmp(c, "int") == 0) 1219 return T_INT; 1220 if (strcmp(c, "long") == 0) 1221 return T_LONG; 1222 if (strcmp(c, "short") == 0) 1223 return T_SHORT; 1224 if (strcmp(c, "unsigned") == 0) 1225 return T_UINT; 1226 if (strcmp(c, "unsigned short") == 0) 1227 return T_USHORT; 1228 if (strcmp(c, "unsigned long") == 0) 1229 return T_ULONG; 1230 if (strcmp(c, "unsigned int") == 0) 1231 return T_UINT; 1232 if (strcmp(c, "char") == 0) 1233 return T_CHAR; 1234 if (strcmp(c, "signed char") == 0) 1235 return T_SCHAR; 1236 if (strcmp(c, "unsigned char") == 0) 1237 return T_UCHAR; 1238 if (strcmp(c, "float") == 0) 1239 return T_FLOAT; 1240 if (strcmp(c, "double") == 0) 1241 return T_DOUBLE; 1242 if (strcmp(c, "long double") == 0) 1243 return T_LONGDOUBLE; 1244 if (!cparse_cplusplus && (strcmp(c, "float complex") == 0)) 1245 return T_FLTCPLX; 1246 if (!cparse_cplusplus && (strcmp(c, "double complex") == 0)) 1247 return T_DBLCPLX; 1248 if (!cparse_cplusplus && (strcmp(c, "complex") == 0)) 1249 return T_COMPLEX; 1250 if (strcmp(c, "void") == 0) 1251 return T_VOID; 1252 if (strcmp(c, "bool") == 0) 1253 return T_BOOL; 1254 if (strcmp(c, "long long") == 0) 1255 return T_LONGLONG; 1256 if (strcmp(c, "unsigned long long") == 0) 1257 return T_ULONGLONG; 1258 if (strncmp(c, "enum ", 5) == 0) 1259 return T_INT; 1260 1261 if (strcmp(c, "v(...)") == 0) 1262 return T_VARARGS; 1263 /* Hmmm. Unknown type */ 1264 if (SwigType_istypedef(t)) { 1265 int r; 1266 SwigType *nt = SwigType_typedef_resolve(t); 1267 r = SwigType_type(nt); 1268 Delete(nt); 1269 return r; 1270 } 1271 return T_USER; 1272} 1273 1274/* ----------------------------------------------------------------------------- 1275 * SwigType_alttype() 1276 * 1277 * Returns the alternative value type needed in C++ for class value 1278 * types. When swig is not sure about using a plain $ltype value, 1279 * since the class doesn't have a default constructor, or it can't be 1280 * assigned, you will get back 'SwigValueWrapper<type >'. 1281 * 1282 * This is the default behavior unless: 1283 * 1284 * 1.- swig detects a default_constructor and 'setallocate:default_constructor' 1285 * attribute. 1286 * 1287 * 2.- swig doesn't mark 'type' as non-assignable. 1288 * 1289 * 3.- the user specify that the value wrapper is not needed by using 1290 * the %feature("novaluewrapper"), in that case the user need to type 1291 * 1292 * %feature("novaluewrapper") MyOpaqueClass; 1293 * class MyOpaqueClass; 1294 * 1295 * Users can also force the use of the value wrapper by using the 1296 * %feature("valuewrapper"). 1297 * ----------------------------------------------------------------------------- */ 1298 1299SwigType *SwigType_alttype(SwigType *t, int local_tmap) { 1300 Node *n; 1301 SwigType *w = 0; 1302 int use_wrapper = 0; 1303 SwigType *td = 0; 1304 1305 if (!cparse_cplusplus) 1306 return 0; 1307 1308 if (value_wrapper_mode == 0) { 1309 /* old partial use of SwigValueTypes, it can fail for opaque types */ 1310 if (local_tmap) 1311 return 0; 1312 if (SwigType_isclass(t)) { 1313 SwigType *ftd = SwigType_typedef_resolve_all(t); 1314 td = SwigType_strip_qualifiers(ftd); 1315 Delete(ftd); 1316 n = Swig_symbol_clookup(td, 0); 1317 if (n) { 1318 if (GetFlag(n, "feature:valuewrapper")) { 1319 use_wrapper = 1; 1320 } else { 1321 if (Checkattr(n, "nodeType", "class") 1322 && (!Getattr(n, "allocate:default_constructor") 1323 || (Getattr(n, "allocate:noassign")))) { 1324 use_wrapper = !GetFlag(n, "feature:novaluewrapper") || GetFlag(n, "feature:nodefault"); 1325 } 1326 } 1327 } else { 1328 if (SwigType_issimple(td) && SwigType_istemplate(td)) { 1329 use_wrapper = !n || !GetFlag(n, "feature:novaluewrapper"); 1330 } 1331 } 1332 } 1333 } else { 1334 /* safe use of SwigValueTypes, it can fail with some typemaps */ 1335 SwigType *ftd = SwigType_typedef_resolve_all(t); 1336 td = SwigType_strip_qualifiers(ftd); 1337 Delete(ftd); 1338 if (SwigType_type(td) == T_USER) { 1339 use_wrapper = 1; 1340 n = Swig_symbol_clookup(td, 0); 1341 if (n) { 1342 if ((Checkattr(n, "nodeType", "class") 1343 && !Getattr(n, "allocate:noassign") 1344 && (Getattr(n, "allocate:default_constructor"))) 1345 || (GetFlag(n, "feature:novaluewrapper"))) { 1346 use_wrapper = GetFlag(n, "feature:valuewrapper"); 1347 } 1348 } 1349 } 1350 } 1351 1352 if (use_wrapper) { 1353 /* Need a space before the type in case it starts "::" (since the <: 1354 * token is a digraph for [ in C++. Also need a space after the 1355 * type in case it ends with ">" since then we form the token ">>". 1356 */ 1357 w = NewStringf("SwigValueWrapper< %s >", td); 1358 } 1359 Delete(td); 1360 return w; 1361} 1362 1363/* ---------------------------------------------------------------------------- 1364 * * * * WARNING * * * *** 1365 * *** 1366 * Don't even think about modifying anything below this line unless you *** 1367 * are completely on top of *EVERY* subtle aspect of the C++ type system *** 1368 * and you are prepared to suffer endless hours of agony trying to *** 1369 * debug the SWIG run-time type checker after you break it. *** 1370 * ------------------------------------------------------------------------- */ 1371 1372/* ----------------------------------------------------------------------------- 1373 * SwigType_remember() 1374 * 1375 * This function "remembers" a datatype that was used during wrapper code generation 1376 * so that a type-checking table can be generated later on. It is up to the language 1377 * modules to actually call this function--it is not done automatically. 1378 * 1379 * Type tracking is managed through two separate hash tables. The hash 'r_mangled' 1380 * is mapping between mangled type names (used in the target language) and 1381 * fully-resolved C datatypes used in the source input. The second hash 'r_resolved' 1382 * is the inverse mapping that maps fully-resolved C datatypes to all of the mangled 1383 * names in the scripting languages. For example, consider the following set of 1384 * typedef declarations: 1385 * 1386 * typedef double Real; 1387 * typedef double Float; 1388 * typedef double Point[3]; 1389 * 1390 * Now, suppose that the types 'double *', 'Real *', 'Float *', 'double[3]', and 1391 * 'Point' were used in an interface file and "remembered" using this function. 1392 * The hash tables would look like this: 1393 * 1394 * r_mangled { 1395 * _p_double : [ p.double, a(3).double ] 1396 * _p_Real : [ p.double ] 1397 * _p_Float : [ p.double ] 1398 * _Point : [ a(3).double ] 1399 * 1400 * r_resolved { 1401 * p.double : [ _p_double, _p_Real, _p_Float ] 1402 * a(3).double : [ _p_double, _Point ] 1403 * } 1404 * 1405 * Together these two hash tables can be used to determine type-equivalency between 1406 * mangled typenames. To do this, we view the two hash tables as a large graph and 1407 * compute the transitive closure. 1408 * ----------------------------------------------------------------------------- */ 1409 1410static Hash *r_mangled = 0; /* Hash mapping mangled types to fully resolved types */ 1411static Hash *r_resolved = 0; /* Hash mapping resolved types to mangled types */ 1412static Hash *r_ltype = 0; /* Hash mapping mangled names to their local c type */ 1413static Hash *r_clientdata = 0; /* Hash mapping resolved types to client data */ 1414static Hash *r_mangleddata = 0; /* Hash mapping mangled types to client data */ 1415static Hash *r_remembered = 0; /* Hash of types we remembered already */ 1416 1417static void (*r_tracefunc) (SwigType *t, String *mangled, String *clientdata) = 0; 1418 1419void SwigType_remember_mangleddata(String *mangled, const_String_or_char_ptr clientdata) { 1420 if (!r_mangleddata) { 1421 r_mangleddata = NewHash(); 1422 } 1423 Setattr(r_mangleddata, mangled, clientdata); 1424} 1425 1426 1427void SwigType_remember_clientdata(SwigType *t, const_String_or_char_ptr clientdata) { 1428 String *mt; 1429 SwigType *lt; 1430 Hash *h; 1431 SwigType *fr; 1432 SwigType *qr; 1433 String *tkey; 1434 String *cd; 1435 Hash *lthash; 1436 1437 if (!r_mangled) { 1438 r_mangled = NewHash(); 1439 r_resolved = NewHash(); 1440 r_ltype = NewHash(); 1441 r_clientdata = NewHash(); 1442 r_remembered = NewHash(); 1443 } 1444 1445 { 1446 String *last; 1447 last = Getattr(r_remembered, t); 1448 if (last && (Cmp(last, clientdata) == 0)) 1449 return; 1450 } 1451 1452 tkey = Copy(t); 1453 cd = clientdata ? NewString(clientdata) : NewStringEmpty(); 1454 Setattr(r_remembered, tkey, cd); 1455 Delete(tkey); 1456 Delete(cd); 1457 1458 mt = SwigType_manglestr(t); /* Create mangled string */ 1459 1460 if (r_tracefunc) { 1461 (*r_tracefunc) (t, mt, (String *) clientdata); 1462 } 1463 1464 if (SwigType_istypedef(t)) { 1465 lt = Copy(t); 1466 } else { 1467 lt = SwigType_ltype(t); 1468 } 1469 1470 lthash = Getattr(r_ltype, mt); 1471 if (!lthash) { 1472 lthash = NewHash(); 1473 Setattr(r_ltype, mt, lthash); 1474 } 1475 Setattr(lthash, lt, "1"); 1476 Delete(lt); 1477 1478 fr = SwigType_typedef_resolve_all(t); /* Create fully resolved type */ 1479 qr = SwigType_typedef_qualified(fr); 1480 Delete(fr); 1481 1482 /* Added to deal with possible table bug */ 1483 fr = SwigType_strip_qualifiers(qr); 1484 Delete(qr); 1485 1486 /*Printf(stdout,"t = '%s'\n", t); 1487 Printf(stdout,"fr= '%s'\n\n", fr); */ 1488 1489 if (t) { 1490 char *ct = Char(t); 1491 if (strchr(ct, '<') && !(strstr(ct, "<("))) { 1492 Printf(stdout, "Bad template type passed to SwigType_remember: %s\n", t); 1493 assert(0); 1494 } 1495 } 1496 1497 h = Getattr(r_mangled, mt); 1498 if (!h) { 1499 h = NewHash(); 1500 Setattr(r_mangled, mt, h); 1501 Delete(h); 1502 } 1503 Setattr(h, fr, mt); 1504 1505 h = Getattr(r_resolved, fr); 1506 if (!h) { 1507 h = NewHash(); 1508 Setattr(r_resolved, fr, h); 1509 Delete(h); 1510 } 1511 Setattr(h, mt, fr); 1512 1513 if (clientdata) { 1514 String *cd = Getattr(r_clientdata, fr); 1515 if (cd) { 1516 if (Strcmp(clientdata, cd) != 0) { 1517 Printf(stderr, "*** Internal error. Inconsistent clientdata for type '%s'\n", SwigType_str(fr, 0)); 1518 Printf(stderr, "*** '%s' != '%s'\n", clientdata, cd); 1519 assert(0); 1520 } 1521 } else { 1522 String *cstr = NewString(clientdata); 1523 Setattr(r_clientdata, fr, cstr); 1524 Delete(cstr); 1525 } 1526 } 1527 1528 /* If the remembered type is a reference, we also remember the pointer version. 1529 This is to prevent odd problems with mixing pointers and references--especially 1530 when different functions are using different typenames (via typedef). */ 1531 1532 if (SwigType_isreference(t)) { 1533 SwigType *tt = Copy(t); 1534 SwigType_del_reference(tt); 1535 SwigType_add_pointer(tt); 1536 SwigType_remember_clientdata(tt, clientdata); 1537 } 1538} 1539 1540void SwigType_remember(SwigType *ty) { 1541 SwigType_remember_clientdata(ty, 0); 1542} 1543 1544void (*SwigType_remember_trace(void (*tf) (SwigType *, String *, String *))) (SwigType *, String *, String *) { 1545 void (*o) (SwigType *, String *, String *) = r_tracefunc; 1546 r_tracefunc = tf; 1547 return o; 1548} 1549 1550/* ----------------------------------------------------------------------------- 1551 * SwigType_equivalent_mangle() 1552 * 1553 * Return a list of all of the mangled typenames that are equivalent to another 1554 * mangled name. This works as follows: For each fully qualified C datatype 1555 * in the r_mangled hash entry, we collect all of the mangled names from the 1556 * r_resolved hash and combine them together in a list (removing duplicate entries). 1557 * ----------------------------------------------------------------------------- */ 1558 1559List *SwigType_equivalent_mangle(String *ms, Hash *checked, Hash *found) { 1560 List *l; 1561 Hash *h; 1562 Hash *ch; 1563 Hash *mh; 1564 1565 if (found) { 1566 h = found; 1567 } else { 1568 h = NewHash(); 1569 } 1570 if (checked) { 1571 ch = checked; 1572 } else { 1573 ch = NewHash(); 1574 } 1575 if (Getattr(ch, ms)) 1576 goto check_exit; /* Already checked this type */ 1577 Setattr(h, ms, "1"); 1578 Setattr(ch, ms, "1"); 1579 mh = Getattr(r_mangled, ms); 1580 if (mh) { 1581 Iterator ki; 1582 ki = First(mh); 1583 while (ki.key) { 1584 Hash *rh; 1585 if (Getattr(ch, ki.key)) { 1586 ki = Next(ki); 1587 continue; 1588 } 1589 Setattr(ch, ki.key, "1"); 1590 rh = Getattr(r_resolved, ki.key); 1591 if (rh) { 1592 Iterator rk; 1593 rk = First(rh); 1594 while (rk.key) { 1595 Setattr(h, rk.key, "1"); 1596 SwigType_equivalent_mangle(rk.key, ch, h); 1597 rk = Next(rk); 1598 } 1599 } 1600 ki = Next(ki); 1601 } 1602 } 1603check_exit: 1604 if (!found) { 1605 l = Keys(h); 1606 Delete(h); 1607 Delete(ch); 1608 return l; 1609 } else { 1610 return 0; 1611 } 1612} 1613 1614/* ----------------------------------------------------------------------------- 1615 * SwigType_clientdata_collect() 1616 * 1617 * Returns the clientdata field for a mangled type-string. 1618 * ----------------------------------------------------------------------------- */ 1619 1620static 1621String *SwigType_clientdata_collect(String *ms) { 1622 Hash *mh; 1623 String *clientdata = 0; 1624 1625 if (r_mangleddata) { 1626 clientdata = Getattr(r_mangleddata, ms); 1627 if (clientdata) 1628 return clientdata; 1629 } 1630 1631 mh = Getattr(r_mangled, ms); 1632 if (mh) { 1633 Iterator ki; 1634 ki = First(mh); 1635 while (ki.key) { 1636 clientdata = Getattr(r_clientdata, ki.key); 1637 if (clientdata) 1638 break; 1639 ki = Next(ki); 1640 } 1641 } 1642 return clientdata; 1643} 1644 1645 1646 1647 1648/* ----------------------------------------------------------------------------- 1649 * SwigType_inherit() 1650 * 1651 * Record information about inheritance. We keep a hash table that keeps 1652 * a mapping between base classes and all of the classes that are derived 1653 * from them. 1654 * 1655 * subclass is a hash that maps base-classes to all of the classes derived from them. 1656 * 1657 * derived - name of derived class 1658 * base - name of base class 1659 * cast - additional casting code when casting from derived to base 1660 * conversioncode - if set, overrides the default code in the function when casting 1661 * from derived to base 1662 * ----------------------------------------------------------------------------- */ 1663 1664static Hash *subclass = 0; 1665static Hash *conversions = 0; 1666 1667void SwigType_inherit(String *derived, String *base, String *cast, String *conversioncode) { 1668 Hash *h; 1669 String *dd = 0; 1670 String *bb = 0; 1671 if (!subclass) 1672 subclass = NewHash(); 1673 1674 /* Printf(stdout,"'%s' --> '%s' '%s'\n", derived, base, cast); */ 1675 1676 if (SwigType_istemplate(derived)) { 1677 String *ty = SwigType_typedef_resolve_all(derived); 1678 dd = SwigType_typedef_qualified(ty); 1679 derived = dd; 1680 Delete(ty); 1681 } 1682 if (SwigType_istemplate(base)) { 1683 String *ty = SwigType_typedef_resolve_all(base); 1684 bb = SwigType_typedef_qualified(ty); 1685 base = bb; 1686 Delete(ty); 1687 } 1688 1689 /* Printf(stdout,"'%s' --> '%s' '%s'\n", derived, base, cast); */ 1690 1691 h = Getattr(subclass, base); 1692 if (!h) { 1693 h = NewHash(); 1694 Setattr(subclass, base, h); 1695 Delete(h); 1696 } 1697 if (!Getattr(h, derived)) { 1698 Hash *c = NewHash(); 1699 if (cast) 1700 Setattr(c, "cast", cast); 1701 if (conversioncode) 1702 Setattr(c, "convcode", conversioncode); 1703 Setattr(h, derived, c); 1704 Delete(c); 1705 } 1706 1707 Delete(dd); 1708 Delete(bb); 1709} 1710 1711/* ----------------------------------------------------------------------------- 1712 * SwigType_issubtype() 1713 * 1714 * Determines if a t1 is a subtype of t2, ie, is t1 derived from t2 1715 * ----------------------------------------------------------------------------- */ 1716 1717int SwigType_issubtype(SwigType *t1, SwigType *t2) { 1718 SwigType *ft1, *ft2; 1719 String *b1, *b2; 1720 Hash *h; 1721 int r = 0; 1722 1723 if (!subclass) 1724 return 0; 1725 1726 ft1 = SwigType_typedef_resolve_all(t1); 1727 ft2 = SwigType_typedef_resolve_all(t2); 1728 b1 = SwigType_base(ft1); 1729 b2 = SwigType_base(ft2); 1730 1731 h = Getattr(subclass, b2); 1732 if (h) { 1733 if (Getattr(h, b1)) { 1734 r = 1; 1735 } 1736 } 1737 Delete(ft1); 1738 Delete(ft2); 1739 Delete(b1); 1740 Delete(b2); 1741 /* Printf(stdout, "issubtype(%s,%s) --> %d\n", t1, t2, r); */ 1742 return r; 1743} 1744 1745/* ----------------------------------------------------------------------------- 1746 * SwigType_inherit_equiv() 1747 * 1748 * Modify the type table to handle C++ inheritance 1749 * ----------------------------------------------------------------------------- */ 1750 1751void SwigType_inherit_equiv(File *out) { 1752 String *ckey; 1753 String *prefix, *base; 1754 String *mprefix, *mkey; 1755 Hash *sub; 1756 Hash *rh; 1757 List *rlist; 1758 Iterator rk, bk, ck; 1759 1760 if (!conversions) 1761 conversions = NewHash(); 1762 if (!subclass) 1763 subclass = NewHash(); 1764 1765 rk = First(r_resolved); 1766 while (rk.key) { 1767 /* rkey is a fully qualified type. We strip all of the type constructors off of it just to get the base */ 1768 base = SwigType_base(rk.key); 1769 /* Check to see whether the base is recorded in the subclass table */ 1770 sub = Getattr(subclass, base); 1771 Delete(base); 1772 if (!sub) { 1773 rk = Next(rk); 1774 continue; 1775 } 1776 1777 /* This type has subclasses. We now need to walk through these subtypes and generate pointer converion functions */ 1778 1779 rh = Getattr(r_resolved, rk.key); 1780 rlist = NewList(); 1781 for (ck = First(rh); ck.key; ck = Next(ck)) { 1782 Append(rlist, ck.key); 1783 } 1784 /* Printf(stdout,"rk.key = '%s'\n", rk.key); 1785 Printf(stdout,"rh = %x '%s'\n", rh,rh); */ 1786 1787 bk = First(sub); 1788 while (bk.key) { 1789 prefix = SwigType_prefix(rk.key); 1790 Append(prefix, bk.key); 1791 /* Printf(stdout,"set %x = '%s' : '%s'\n", rh, SwigType_manglestr(prefix),prefix); */ 1792 mprefix = SwigType_manglestr(prefix); 1793 Setattr(rh, mprefix, prefix); 1794 mkey = SwigType_manglestr(rk.key); 1795 ckey = NewStringf("%s+%s", mprefix, mkey); 1796 if (!Getattr(conversions, ckey)) { 1797 String *convname = NewStringf("%sTo%s", mprefix, mkey); 1798 String *lkey = SwigType_lstr(rk.key, 0); 1799 String *lprefix = SwigType_lstr(prefix, 0); 1800 Hash *subhash = Getattr(sub, bk.key); 1801 String *convcode = Getattr(subhash, "convcode"); 1802 if (convcode) { 1803 char *newmemoryused = Strstr(convcode, "newmemory"); /* see if newmemory parameter is used in order to avoid unused parameter warnings */ 1804 String *fn = Copy(convcode); 1805 Replaceall(fn, "$from", "x"); 1806 Printf(out, "static void *%s(void *x, int *%s) {", convname, newmemoryused ? "newmemory" : "SWIGUNUSEDPARM(newmemory)"); 1807 Printf(out, "%s", fn); 1808 } else { 1809 String *cast = Getattr(subhash, "cast"); 1810 Printf(out, "static void *%s(void *x, int *SWIGUNUSEDPARM(newmemory)) {", convname); 1811 Printf(out, "\n return (void *)((%s) ", lkey); 1812 if (cast) 1813 Printf(out, "%s", cast); 1814 Printf(out, " ((%s) x));\n", lprefix); 1815 } 1816 Printf(out, "}\n"); 1817 Setattr(conversions, ckey, convname); 1818 Delete(ckey); 1819 Delete(lkey); 1820 Delete(lprefix); 1821 1822 /* This inserts conversions for typedefs */ 1823 { 1824 Hash *r = Getattr(r_resolved, prefix); 1825 if (r) { 1826 Iterator rrk; 1827 rrk = First(r); 1828 while (rrk.key) { 1829 Iterator rlk; 1830 String *rkeymangle; 1831 1832 /* Make sure this name equivalence is not due to inheritance */ 1833 if (Cmp(prefix, Getattr(r, rrk.key)) == 0) { 1834 rkeymangle = Copy(mkey); 1835 ckey = NewStringf("%s+%s", rrk.key, rkeymangle); 1836 if (!Getattr(conversions, ckey)) { 1837 Setattr(conversions, ckey, convname); 1838 } 1839 Delete(ckey); 1840 for (rlk = First(rlist); rlk.item; rlk = Next(rlk)) { 1841 ckey = NewStringf("%s+%s", rrk.key, rlk.item); 1842 Setattr(conversions, ckey, convname); 1843 Delete(ckey); 1844 } 1845 Delete(rkeymangle); 1846 /* This is needed to pick up other alternative names for the same type. 1847 Needed to make templates work */ 1848 Setattr(rh, rrk.key, rrk.item); 1849 } 1850 rrk = Next(rrk); 1851 } 1852 } 1853 } 1854 Delete(convname); 1855 } 1856 Delete(prefix); 1857 Delete(mprefix); 1858 Delete(mkey); 1859 bk = Next(bk); 1860 } 1861 rk = Next(rk); 1862 Delete(rlist); 1863 } 1864} 1865 1866/* Helper function to sort the mangled list */ 1867static int SwigType_compare_mangled(const DOH *a, const DOH *b) { 1868 return strcmp((char *) Data(a), (char *) Data(b)); 1869} 1870 1871/* ----------------------------------------------------------------------------- 1872 * SwigType_get_sorted_mangled_list() 1873 * 1874 * Returns the sorted list of mangled type names that should be exported into the 1875 * wrapper file. 1876 * ----------------------------------------------------------------------------- */ 1877List *SwigType_get_sorted_mangled_list() { 1878 List *l = Keys(r_mangled); 1879 SortList(l, SwigType_compare_mangled); 1880 return l; 1881} 1882 1883 1884/* ----------------------------------------------------------------------------- 1885 * SwigType_type_table() 1886 * 1887 * Generate the type-table for the type-checker. 1888 * ----------------------------------------------------------------------------- */ 1889 1890void SwigType_emit_type_table(File *f_forward, File *f_table) { 1891 Iterator ki; 1892 String *types, *table, *cast, *cast_init, *cast_temp; 1893 Hash *imported_types; 1894 List *mangled_list; 1895 List *table_list = NewList(); 1896 int i = 0; 1897 1898 if (!r_mangled) { 1899 r_mangled = NewHash(); 1900 r_resolved = NewHash(); 1901 } 1902 1903 Printf(f_table, "\n/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */\n\n"); 1904 1905 SwigType_inherit_equiv(f_table); 1906 1907 /*#define DEBUG 1*/ 1908#ifdef DEBUG 1909 Printf(stdout, "---r_mangled---\n"); 1910 Printf(stdout, "%s\n", r_mangled); 1911 1912 Printf(stdout, "---r_resolved---\n"); 1913 Printf(stdout, "%s\n", r_resolved); 1914 1915 Printf(stdout, "---r_ltype---\n"); 1916 Printf(stdout, "%s\n", r_ltype); 1917 1918 Printf(stdout, "---subclass---\n"); 1919 Printf(stdout, "%s\n", subclass); 1920 1921 Printf(stdout, "---conversions---\n"); 1922 Printf(stdout, "%s\n", conversions); 1923 1924 Printf(stdout, "---r_clientdata---\n"); 1925 Printf(stdout, "%s\n", r_clientdata); 1926 1927#endif 1928 table = NewStringEmpty(); 1929 types = NewStringEmpty(); 1930 cast = NewStringEmpty(); 1931 cast_init = NewStringEmpty(); 1932 imported_types = NewHash(); 1933 1934 Printf(table, "static swig_type_info *swig_type_initial[] = {\n"); 1935 Printf(cast_init, "static swig_cast_info *swig_cast_initial[] = {\n"); 1936 1937 Printf(f_forward, "\n/* -------- TYPES TABLE (BEGIN) -------- */\n\n"); 1938 1939 mangled_list = SwigType_get_sorted_mangled_list(); 1940 for (ki = First(mangled_list); ki.item; ki = Next(ki)) { 1941 List *el; 1942 Iterator ei; 1943 SwigType *lt; 1944 SwigType *rt = 0; 1945 String *nt; 1946 String *ln; 1947 String *rn; 1948 const String *cd; 1949 Hash *lthash; 1950 Iterator ltiter; 1951 Hash *nthash; 1952 1953 cast_temp = NewStringEmpty(); 1954 1955 Printv(types, "static swig_type_info _swigt_", ki.item, " = {", NIL); 1956 Append(table_list, ki.item); 1957 Printf(cast_temp, "static swig_cast_info _swigc_%s[] = {", ki.item); 1958 i++; 1959 1960 cd = SwigType_clientdata_collect(ki.item); 1961 if (!cd) 1962 cd = "0"; 1963 1964 lthash = Getattr(r_ltype, ki.item); 1965 nt = 0; 1966 nthash = NewHash(); 1967 ltiter = First(lthash); 1968 while (ltiter.key) { 1969 lt = ltiter.key; 1970 rt = SwigType_typedef_resolve_all(lt); 1971 /* we save the original type and the fully resolved version */ 1972 ln = SwigType_lstr(lt, 0); 1973 rn = SwigType_lstr(rt, 0); 1974 if (Equal(ln, rn)) { 1975 Setattr(nthash, ln, "1"); 1976 } else { 1977 Setattr(nthash, rn, "1"); 1978 Setattr(nthash, ln, "1"); 1979 } 1980 if (SwigType_istemplate(rt)) { 1981 String *dt = Swig_symbol_template_deftype(rt, 0); 1982 String *dn = SwigType_lstr(dt, 0); 1983 if (!Equal(dn, rn) && !Equal(dn, ln)) { 1984 Setattr(nthash, dn, "1"); 1985 } 1986 Delete(dt); 1987 Delete(dn); 1988 } 1989 1990 ltiter = Next(ltiter); 1991 } 1992 1993 /* now build nt */ 1994 ltiter = First(nthash); 1995 nt = 0; 1996 while (ltiter.key) { 1997 if (nt) { 1998 Printf(nt, "|%s", ltiter.key); 1999 } else { 2000 nt = NewString(ltiter.key); 2001 } 2002 ltiter = Next(ltiter); 2003 } 2004 Delete(nthash); 2005 2006 Printf(types, "\"%s\", \"%s\", 0, 0, (void*)%s, 0};\n", ki.item, nt, cd); 2007 2008 el = SwigType_equivalent_mangle(ki.item, 0, 0); 2009 for (ei = First(el); ei.item; ei = Next(ei)) { 2010 String *ckey; 2011 String *conv; 2012 ckey = NewStringf("%s+%s", ei.item, ki.item); 2013 conv = Getattr(conversions, ckey); 2014 if (conv) { 2015 Printf(cast_temp, " {&_swigt_%s, %s, 0, 0},", ei.item, conv); 2016 } else { 2017 Printf(cast_temp, " {&_swigt_%s, 0, 0, 0},", ei.item); 2018 } 2019 Delete(ckey); 2020 2021 if (!Getattr(r_mangled, ei.item) && !Getattr(imported_types, ei.item)) { 2022 Printf(types, "static swig_type_info _swigt_%s = {\"%s\", 0, 0, 0, 0, 0};\n", ei.item, ei.item); 2023 Append(table_list, ei.item); 2024 2025 Printf(cast, "static swig_cast_info _swigc_%s[] = {{&_swigt_%s, 0, 0, 0},{0, 0, 0, 0}};\n", ei.item, ei.item); 2026 i++; 2027 2028 Setattr(imported_types, ei.item, "1"); 2029 } 2030 } 2031 Delete(el); 2032 Printf(cast, "%s{0, 0, 0, 0}};\n", cast_temp); 2033 Delete(cast_temp); 2034 Delete(nt); 2035 Delete(rt); 2036 } 2037 /* print the tables in the proper order */ 2038 SortList(table_list, SwigType_compare_mangled); 2039 i = 0; 2040 for (ki = First(table_list); ki.item; ki = Next(ki)) { 2041 Printf(f_forward, "#define SWIGTYPE%s swig_types[%d]\n", ki.item, i++); 2042 Printf(table, " &_swigt_%s,\n", ki.item); 2043 Printf(cast_init, " _swigc_%s,\n", ki.item); 2044 } 2045 if (i == 0) { 2046 /* empty arrays are not allowed by ISO C */ 2047 Printf(table, " NULL\n"); 2048 Printf(cast_init, " NULL\n"); 2049 } 2050 2051 Delete(table_list); 2052 2053 Delete(mangled_list); 2054 2055 Printf(table, "};\n"); 2056 Printf(cast_init, "};\n"); 2057 Printf(f_table, "%s\n", types); 2058 Printf(f_table, "%s\n", table); 2059 Printf(f_table, "%s\n", cast); 2060 Printf(f_table, "%s\n", cast_init); 2061 Printf(f_table, "\n/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */\n\n"); 2062 2063 Printf(f_forward, "static swig_type_info *swig_types[%d];\n", i + 1); 2064 Printf(f_forward, "static swig_module_info swig_module = {swig_types, %d, 0, 0, 0, 0};\n", i); 2065 Printf(f_forward, "#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)\n"); 2066 Printf(f_forward, "#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)\n"); 2067 Printf(f_forward, "\n/* -------- TYPES TABLE (END) -------- */\n\n"); 2068 2069 Delete(types); 2070 Delete(table); 2071 Delete(cast); 2072 Delete(cast_init); 2073 Delete(imported_types); 2074} 2075