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 * stype.c 6 * 7 * This file provides general support for datatypes that are encoded in 8 * the form of simple strings. 9 * ----------------------------------------------------------------------------- */ 10 11char cvsroot_stype_c[] = "$Id: stype.c 11080 2009-01-24 13:15:51Z bhy $"; 12 13#include "swig.h" 14#include "cparse.h" 15#include <ctype.h> 16 17/* ----------------------------------------------------------------------------- 18 * Synopsis 19 * 20 * The purpose of this module is to provide a general purpose type representation 21 * based on simple text strings. 22 * 23 * General idea: 24 * 25 * Types are represented by a base type (e.g., "int") and a collection of 26 * type operators applied to the base (e.g., pointers, arrays, etc...). 27 * 28 * Encoding: 29 * 30 * Types are encoded as strings of type constructors such as follows: 31 * 32 * String Encoding C Example 33 * --------------- --------- 34 * p.p.int int ** 35 * a(300).a(400).int int [300][400] 36 * p.q(const).char char const * 37 * 38 * All type constructors are denoted by a trailing '.': 39 * 40 * 'p.' = Pointer (*) 41 * 'r.' = Reference (&) 42 * 'a(n).' = Array of size n [n] 43 * 'f(..,..).' = Function with arguments (args) 44 * 'q(str).' = Qualifier (such as const or volatile) (const, volatile) 45 * 'm(qual).' = Pointer to member (qual::*) 46 * 47 * The encoding follows the order that you might describe a type in words. 48 * For example "p.a(200).int" is "A pointer to array of int's" and 49 * "p.q(const).char" is "a pointer to a const char". 50 * 51 * This representation of types is fairly convenient because ordinary string 52 * operations can be used for type manipulation. For example, a type could be 53 * formed by combining two strings such as the following: 54 * 55 * "p.p." + "a(400).int" = "p.p.a(400).int" 56 * 57 * Similarly, one could strip a 'const' declaration from a type doing something 58 * like this: 59 * 60 * Replace(t,"q(const).","",DOH_REPLACE_ANY) 61 * 62 * For the most part, this module tries to minimize the use of special 63 * characters (*, [, <, etc...) in its type encoding. One reason for this 64 * is that SWIG might be extended to encode data in formats such as XML 65 * where you might want to do this: 66 * 67 * <function> 68 * <type>p.p.int</type> 69 * ... 70 * </function> 71 * 72 * Or alternatively, 73 * 74 * <function type="p.p.int" ...>blah</function> 75 * 76 * In either case, it's probably best to avoid characters such as '&', '*', or '<'. 77 * 78 * Why not use C syntax? Well, C syntax is fairly complicated to parse 79 * and not particularly easy to manipulate---especially for adding, deleting and 80 * composing type constructors. The string representation presented here makes 81 * this pretty easy. 82 * 83 * Why not use a bunch of nested data structures? Are you kidding? How 84 * would that be easier to use than a few simple string operations? 85 * ----------------------------------------------------------------------------- */ 86 87 88SwigType *NewSwigType(int t) { 89 switch (t) { 90 case T_BOOL: 91 return NewString("bool"); 92 break; 93 case T_INT: 94 return NewString("int"); 95 break; 96 case T_UINT: 97 return NewString("unsigned int"); 98 break; 99 case T_SHORT: 100 return NewString("short"); 101 break; 102 case T_USHORT: 103 return NewString("unsigned short"); 104 break; 105 case T_LONG: 106 return NewString("long"); 107 break; 108 case T_ULONG: 109 return NewString("unsigned long"); 110 break; 111 case T_FLOAT: 112 return NewString("float"); 113 break; 114 case T_DOUBLE: 115 return NewString("double"); 116 break; 117 case T_COMPLEX: 118 return NewString("complex"); 119 break; 120 case T_CHAR: 121 return NewString("char"); 122 break; 123 case T_SCHAR: 124 return NewString("signed char"); 125 break; 126 case T_UCHAR: 127 return NewString("unsigned char"); 128 break; 129 case T_STRING:{ 130 SwigType *t = NewString("char"); 131 SwigType_add_pointer(t); 132 return t; 133 break; 134 } 135 case T_LONGLONG: 136 return NewString("long long"); 137 break; 138 case T_ULONGLONG: 139 return NewString("unsigned long long"); 140 break; 141 case T_VOID: 142 return NewString("void"); 143 break; 144 default: 145 break; 146 } 147 return NewStringEmpty(); 148} 149 150/* ----------------------------------------------------------------------------- 151 * SwigType_push() 152 * 153 * Push a type constructor onto the type 154 * ----------------------------------------------------------------------------- */ 155 156void SwigType_push(SwigType *t, String *cons) { 157 if (!cons) 158 return; 159 if (!Len(cons)) 160 return; 161 162 if (Len(t)) { 163 char *c = Char(cons); 164 if (c[strlen(c) - 1] != '.') 165 Insert(t, 0, "."); 166 } 167 Insert(t, 0, cons); 168} 169 170/* ----------------------------------------------------------------------------- 171 * SwigType_ispointer_return() 172 * 173 * Testing functions for querying a raw datatype 174 * ----------------------------------------------------------------------------- */ 175 176int SwigType_ispointer_return(SwigType *t) { 177 char *c; 178 int idx; 179 if (!t) 180 return 0; 181 c = Char(t); 182 idx = strlen(c) - 4; 183 if (idx >= 0) { 184 return (strcmp(c + idx, ").p.") == 0); 185 } 186 return 0; 187} 188 189int SwigType_isreference_return(SwigType *t) { 190 char *c; 191 int idx; 192 if (!t) 193 return 0; 194 c = Char(t); 195 idx = strlen(c) - 4; 196 if (idx >= 0) { 197 return (strcmp(c + idx, ").r.") == 0); 198 } 199 return 0; 200} 201 202int SwigType_isconst(SwigType *t) { 203 char *c; 204 if (!t) 205 return 0; 206 c = Char(t); 207 if (strncmp(c, "q(", 2) == 0) { 208 String *q = SwigType_parm(t); 209 if (strstr(Char(q), "const")) { 210 Delete(q); 211 return 1; 212 } 213 Delete(q); 214 } 215 /* Hmmm. Might be const through a typedef */ 216 if (SwigType_issimple(t)) { 217 int ret; 218 SwigType *td = SwigType_typedef_resolve(t); 219 if (td) { 220 ret = SwigType_isconst(td); 221 Delete(td); 222 return ret; 223 } 224 } 225 return 0; 226} 227 228int SwigType_ismutable(SwigType *t) { 229 int r; 230 SwigType *qt = SwigType_typedef_resolve_all(t); 231 if (SwigType_isreference(qt) || SwigType_isarray(qt)) { 232 Delete(SwigType_pop(qt)); 233 } 234 r = SwigType_isconst(qt); 235 Delete(qt); 236 return r ? 0 : 1; 237} 238 239int SwigType_isenum(SwigType *t) { 240 char *c = Char(t); 241 if (!t) 242 return 0; 243 if (strncmp(c, "enum ", 5) == 0) { 244 return 1; 245 } 246 return 0; 247} 248 249int SwigType_issimple(SwigType *t) { 250 char *c = Char(t); 251 if (!t) 252 return 0; 253 while (*c) { 254 if (*c == '<') { 255 int nest = 1; 256 c++; 257 while (*c && nest) { 258 if (*c == '<') 259 nest++; 260 if (*c == '>') 261 nest--; 262 c++; 263 } 264 c--; 265 } 266 if (*c == '.') 267 return 0; 268 c++; 269 } 270 return 1; 271} 272 273/* ----------------------------------------------------------------------------- 274 * SwigType_default() 275 * 276 * Create the default string for this datatype. This takes a type and strips it 277 * down to its most primitive form--resolving all typedefs and removing operators. 278 * 279 * Rules: 280 * Pointers: p.SWIGTYPE 281 * References: r.SWIGTYPE 282 * Arrays: a().SWIGTYPE 283 * Types: SWIGTYPE 284 * MemberPointer: m(CLASS).SWIGTYPE 285 * Enums: enum SWIGTYPE 286 * 287 * Note: if this function is applied to a primitive type, it returns NULL. This 288 * allows recursive application for special types like arrays. 289 * ----------------------------------------------------------------------------- */ 290 291#ifdef SWIG_DEFAULT_CACHE 292static Hash *default_cache = 0; 293#endif 294 295#define SWIG_NEW_TYPE_DEFAULT 296/* The new default type resolution method: 297 2981.- It preserves the original mixed types, then it goes 'backward' 299 first deleting the qualifier, then the inner types 300 301 typedef A *Aptr; 302 const Aptr&; 303 r.q(const).Aptr -> r.q(const).p.SWIGTYPE 304 r.q(const).p.SWIGTYPE -> r.p.SWIGTYPE 305 r.p.SWIGTYPE -> r.SWIGTYPE 306 r.SWIGTYPE -> SWIGTYPE 307 308 309 enum Hello {}; 310 const Hello& hi; 311 r.q(const).Hello -> r.q(const).enum SWIGTYPE 312 r.q(const).enum SWIGTYPE -> r.enum SWIGTYPE 313 r.enum SWIGTYPE -> r.SWIGTYPE 314 r.SWIGTYPE -> SWIGTYPE 315 316 int a[2][4]; 317 a(2).a(4).int -> a(ANY).a(ANY).SWIGTYPE 318 a(ANY).a(ANY).SWIGTYPE -> a(ANY).a().SWIGTYPE 319 a(ANY).a().SWIGTYPE -> a(ANY).p.SWIGTYPE 320 a(ANY).p.SWIGTYPE -> a(ANY).SWIGTYPE 321 a(ANY).SWIGTYPE -> a().SWIGTYPE 322 a().SWIGTYPE -> p.SWIGTYPE 323 p.SWIGTYPE -> SWIGTYPE 324*/ 325 326static 327void SwigType_add_default(String *def, SwigType *nr) { 328 if (Strcmp(nr, "SWIGTYPE") == 0) { 329 Append(def, "SWIGTYPE"); 330 } else { 331 String *q = SwigType_isqualifier(nr) ? SwigType_pop(nr) : 0; 332 if (q && strstr(Char(nr), "SWIGTYPE")) { 333 Append(def, nr); 334 } else { 335 String *nd = SwigType_default(nr); 336 if (nd) { 337 String *bdef = nd; 338 if (q) { 339 bdef = NewStringf("%s%s", q, nd); 340 if ((Strcmp(nr, bdef) == 0)) { 341 Delete(bdef); 342 bdef = nd; 343 } else { 344 Delete(nd); 345 } 346 } 347 Append(def, bdef); 348 Delete(bdef); 349 } else { 350 Append(def, nr); 351 } 352 } 353 Delete(q); 354 } 355} 356 357 358SwigType *SwigType_default(SwigType *t) { 359 String *r1, *def; 360 String *r = 0; 361 char *cr; 362 363#ifdef SWIG_DEFAULT_CACHE 364 if (!default_cache) 365 default_cache = NewHash(); 366 367 r = Getattr(default_cache, t); 368 if (r) { 369 return Copy(r); 370 } 371#endif 372 373 if (SwigType_isvarargs(t)) { 374 return 0; 375 } 376 377 r = t; 378 while ((r1 = SwigType_typedef_resolve(r))) { 379 if (r != t) 380 Delete(r); 381 r = r1; 382 } 383 if (SwigType_isqualifier(r)) { 384 String *q; 385 if (r == t) 386 r = Copy(t); 387 q = SwigType_pop(r); 388 if (strstr(Char(r), "SWIGTYPE")) { 389 Delete(q); 390 def = r; 391 return def; 392 } 393 Delete(q); 394 } 395 cr = Char(r); 396 if (strcmp(cr, "p.SWIGTYPE") == 0) { 397 def = NewString("SWIGTYPE"); 398 } else if (SwigType_ispointer(r)) { 399#ifdef SWIG_NEW_TYPE_DEFAULT 400 SwigType *nr = Copy(r); 401 SwigType_del_pointer(nr); 402 def = SwigType_isfunction(nr) ? NewStringEmpty() : NewString("p."); 403 SwigType_add_default(def, nr); 404 Delete(nr); 405#else 406 def = NewString("p.SWIGTYPE"); 407#endif 408 } else if (strcmp(cr, "r.SWIGTYPE") == 0) { 409 def = NewString("SWIGTYPE"); 410 } else if (SwigType_isreference(r)) { 411#ifdef SWIG_NEW_TYPE_DEFAULT 412 SwigType *nr = Copy(r); 413 SwigType_del_reference(nr); 414 def = NewString("r."); 415 SwigType_add_default(def, nr); 416 Delete(nr); 417#else 418 def = NewString("r.SWIGTYPE"); 419#endif 420 } else if (SwigType_isarray(r)) { 421 if (strcmp(cr, "a().SWIGTYPE") == 0) { 422 def = NewString("p.SWIGTYPE"); 423 } else if (strcmp(cr, "a(ANY).SWIGTYPE") == 0) { 424 def = NewString("a().SWIGTYPE"); 425 } else { 426 int i, empty = 0; 427 int ndim = SwigType_array_ndim(r); 428 SwigType *nr = Copy(r); 429 for (i = 0; i < ndim; i++) { 430 String *dim = SwigType_array_getdim(r, i); 431 if (!Len(dim)) { 432 char *c = Char(nr); 433 empty = strstr(c, "a(ANY).") != c; 434 } 435 Delete(dim); 436 } 437 if (empty) { 438 def = NewString("a()."); 439 } else { 440 def = NewString("a(ANY)."); 441 } 442#ifdef SWIG_NEW_TYPE_DEFAULT 443 SwigType_del_array(nr); 444 SwigType_add_default(def, nr); 445#else 446 Append(def, "SWIGTYPE"); 447#endif 448 Delete(nr); 449 } 450 } else if (SwigType_ismemberpointer(r)) { 451 if (strcmp(cr, "m(CLASS).SWIGTYPE") == 0) { 452 def = NewString("p.SWIGTYPE"); 453 } else { 454 def = NewString("m(CLASS).SWIGTYPE"); 455 } 456 } else if (SwigType_isenum(r)) { 457 if (strcmp(cr, "enum SWIGTYPE") == 0) { 458 def = NewString("SWIGTYPE"); 459 } else { 460 def = NewString("enum SWIGTYPE"); 461 } 462 } else if (SwigType_isfunction(r)) { 463 if (strcmp(cr, "f(ANY).SWIGTYPE") == 0) { 464 def = NewString("p.SWIGTYPE"); 465 } else { 466 def = NewString("p.f(ANY).SWIGTYPE"); 467 } 468 } else { 469 def = NewString("SWIGTYPE"); 470 } 471 if (r != t) 472 Delete(r); 473 if (Equal(def, t)) { 474 Delete(def); 475 def = 0; 476 } 477#ifdef SWIG_DEFAULT_CACHE 478 /* The cache produces strange results, see enum_template.i case */ 479 if (def) { 480 String *cdef = Copy(def); 481 Setattr(default_cache, t, cdef); 482 Delete(cdef); 483 } 484#endif 485 486 /* Printf(stderr,"type : def %s : %s\n", t, def); */ 487 488 return def; 489} 490 491/* ----------------------------------------------------------------------------- 492 * SwigType_namestr() 493 * 494 * Returns a string of the base type. Takes care of template expansions 495 * ----------------------------------------------------------------------------- */ 496 497String *SwigType_namestr(const SwigType *t) { 498 String *r; 499 String *suffix; 500 List *p; 501 int i, sz; 502 char *d = Char(t); 503 char *c = strstr(d, "<("); 504 505 if (!c || !strstr(c + 2, ")>")) 506 return NewString(t); 507 508 r = NewStringWithSize(d, c - d); 509 if (*(c - 1) == '<') 510 Putc(' ', r); 511 Putc('<', r); 512 513 p = SwigType_parmlist(c + 1); 514 sz = Len(p); 515 for (i = 0; i < sz; i++) { 516 String *str = SwigType_str(Getitem(p, i), 0); 517 /* Avoid creating a <: token, which is the same as [ in C++ - put a space after '<'. */ 518 if (i == 0 && Len(str)) 519 Putc(' ', r); 520 Append(r, str); 521 if ((i + 1) < sz) 522 Putc(',', r); 523 Delete(str); 524 } 525 Putc(' ', r); 526 Putc('>', r); 527 suffix = SwigType_templatesuffix(t); 528 Append(r, suffix); 529 Delete(suffix); 530 Delete(p); 531 return r; 532} 533 534/* ----------------------------------------------------------------------------- 535 * SwigType_str() 536 * 537 * Create a C string representation of a datatype. 538 * ----------------------------------------------------------------------------- */ 539 540String *SwigType_str(SwigType *s, const_String_or_char_ptr id) { 541 String *result; 542 String *element = 0, *nextelement; 543 List *elements; 544 int nelements, i; 545 546 if (id) { 547 result = NewString(id); 548 } else { 549 result = NewStringEmpty(); 550 } 551 552 elements = SwigType_split(s); 553 nelements = Len(elements); 554 555 if (nelements > 0) { 556 element = Getitem(elements, 0); 557 } 558 /* Now, walk the type list and start emitting */ 559 for (i = 0; i < nelements; i++) { 560 if (i < (nelements - 1)) { 561 nextelement = Getitem(elements, i + 1); 562 } else { 563 nextelement = 0; 564 } 565 if (SwigType_isqualifier(element)) { 566 DOH *q = 0; 567 q = SwigType_parm(element); 568 Insert(result, 0, " "); 569 Insert(result, 0, q); 570 Delete(q); 571 } else if (SwigType_ispointer(element)) { 572 Insert(result, 0, "*"); 573 if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { 574 Insert(result, 0, "("); 575 Append(result, ")"); 576 } 577 } else if (SwigType_ismemberpointer(element)) { 578 String *q; 579 q = SwigType_parm(element); 580 Insert(result, 0, "::*"); 581 Insert(result, 0, q); 582 if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { 583 Insert(result, 0, "("); 584 Append(result, ")"); 585 } 586 Delete(q); 587 } else if (SwigType_isreference(element)) { 588 Insert(result, 0, "&"); 589 if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { 590 Insert(result, 0, "("); 591 Append(result, ")"); 592 } 593 } else if (SwigType_isarray(element)) { 594 DOH *size; 595 Append(result, "["); 596 size = SwigType_parm(element); 597 Append(result, size); 598 Append(result, "]"); 599 Delete(size); 600 } else if (SwigType_isfunction(element)) { 601 DOH *parms, *p; 602 int j, plen; 603 Append(result, "("); 604 parms = SwigType_parmlist(element); 605 plen = Len(parms); 606 for (j = 0; j < plen; j++) { 607 p = SwigType_str(Getitem(parms, j), 0); 608 Append(result, p); 609 if (j < (plen - 1)) 610 Append(result, ","); 611 } 612 Append(result, ")"); 613 Delete(parms); 614 } else { 615 if (strcmp(Char(element), "v(...)") == 0) { 616 Insert(result, 0, "..."); 617 } else { 618 String *bs = SwigType_namestr(element); 619 Insert(result, 0, " "); 620 Insert(result, 0, bs); 621 Delete(bs); 622 } 623 } 624 element = nextelement; 625 } 626 Delete(elements); 627 Chop(result); 628 return result; 629} 630 631/* ----------------------------------------------------------------------------- 632 * SwigType_ltype(SwigType *ty) 633 * 634 * Create a locally assignable type 635 * ----------------------------------------------------------------------------- */ 636 637SwigType *SwigType_ltype(SwigType *s) { 638 String *result; 639 String *element; 640 SwigType *td, *tc = 0; 641 List *elements; 642 int nelements, i; 643 int firstarray = 1; 644 int notypeconv = 0; 645 646 result = NewStringEmpty(); 647 tc = Copy(s); 648 /* Nuke all leading qualifiers */ 649 while (SwigType_isqualifier(tc)) { 650 Delete(SwigType_pop(tc)); 651 } 652 if (SwigType_issimple(tc)) { 653 /* Resolve any typedef definitions */ 654 SwigType *tt = Copy(tc); 655 td = 0; 656 while ((td = SwigType_typedef_resolve(tt))) { 657 if (td && (SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td))) { 658 /* We need to use the typedef type */ 659 Delete(tt); 660 tt = td; 661 break; 662 } else if (td) { 663 Delete(tt); 664 tt = td; 665 } 666 } 667 if (td) { 668 Delete(tc); 669 tc = td; 670 } 671 } 672 elements = SwigType_split(tc); 673 nelements = Len(elements); 674 675 /* Now, walk the type list and start emitting */ 676 for (i = 0; i < nelements; i++) { 677 element = Getitem(elements, i); 678 /* when we see a function, we need to preserve the following types */ 679 if (SwigType_isfunction(element)) { 680 notypeconv = 1; 681 } 682 if (SwigType_isqualifier(element)) { 683 /* Do nothing. Ignore */ 684 } else if (SwigType_ispointer(element)) { 685 Append(result, element); 686 firstarray = 0; 687 } else if (SwigType_ismemberpointer(element)) { 688 Append(result, element); 689 firstarray = 0; 690 } else if (SwigType_isreference(element)) { 691 if (notypeconv) { 692 Append(result, element); 693 } else { 694 Append(result, "p."); 695 } 696 firstarray = 0; 697 } else if (SwigType_isarray(element) && firstarray) { 698 if (notypeconv) { 699 Append(result, element); 700 } else { 701 Append(result, "p."); 702 } 703 firstarray = 0; 704 } else if (SwigType_isenum(element)) { 705 int anonymous_enum = (Cmp(element, "enum ") == 0); 706 if (notypeconv || !anonymous_enum) { 707 Append(result, element); 708 } else { 709 Append(result, "int"); 710 } 711 } else { 712 Append(result, element); 713 } 714 } 715 Delete(elements); 716 Delete(tc); 717 return result; 718} 719 720/* ----------------------------------------------------------------------------- 721 * SwigType_lstr(DOH *s, DOH *id) 722 * 723 * Produces a type-string that is suitable as a lvalue in an expression. 724 * That is, a type that can be freely assigned a value without violating 725 * any C assignment rules. 726 * 727 * - Qualifiers such as 'const' and 'volatile' are stripped. 728 * - Arrays are converted into a *single* pointer (i.e., 729 * double [][] becomes double *). 730 * - References are converted into a pointer. 731 * - Typedef names that refer to read-only types will be replaced 732 * with an equivalent assignable version. 733 * -------------------------------------------------------------------- */ 734 735String *SwigType_lstr(SwigType *s, const_String_or_char_ptr id) { 736 String *result; 737 SwigType *tc; 738 739 tc = SwigType_ltype(s); 740 result = SwigType_str(tc, id); 741 Delete(tc); 742 return result; 743} 744 745/* ----------------------------------------------------------------------------- 746 * SwigType_rcaststr() 747 * 748 * Produces a casting string that maps the type returned by lstr() to the real 749 * datatype printed by str(). 750 * ----------------------------------------------------------------------------- */ 751 752String *SwigType_rcaststr(SwigType *s, const_String_or_char_ptr name) { 753 String *result, *cast; 754 String *element = 0, *nextelement; 755 SwigType *td, *rs, *tc = 0; 756 List *elements; 757 int nelements, i; 758 int clear = 1; 759 int firstarray = 1; 760 int isreference = 0; 761 int isarray = 0; 762 763 result = NewStringEmpty(); 764 765 if (SwigType_isconst(s)) { 766 tc = Copy(s); 767 Delete(SwigType_pop(tc)); 768 rs = tc; 769 } else { 770 rs = s; 771 } 772 773 if ((SwigType_isconst(rs) || SwigType_isarray(rs) || SwigType_isreference(rs))) { 774 td = 0; 775 } else { 776 td = SwigType_typedef_resolve(rs); 777 } 778 779 if (td) { 780 if ((SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td))) { 781 elements = SwigType_split(td); 782 } else { 783 elements = SwigType_split(rs); 784 } 785 Delete(td); 786 } else { 787 elements = SwigType_split(rs); 788 } 789 nelements = Len(elements); 790 if (nelements > 0) { 791 element = Getitem(elements, 0); 792 } 793 /* Now, walk the type list and start emitting */ 794 for (i = 0; i < nelements; i++) { 795 if (i < (nelements - 1)) { 796 nextelement = Getitem(elements, i + 1); 797 } else { 798 nextelement = 0; 799 } 800 if (SwigType_isqualifier(element)) { 801 DOH *q = 0; 802 q = SwigType_parm(element); 803 Insert(result, 0, " "); 804 Insert(result, 0, q); 805 Delete(q); 806 clear = 0; 807 } else if (SwigType_ispointer(element)) { 808 Insert(result, 0, "*"); 809 if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { 810 Insert(result, 0, "("); 811 Append(result, ")"); 812 } 813 firstarray = 0; 814 } else if (SwigType_ismemberpointer(element)) { 815 String *q; 816 Insert(result, 0, "::*"); 817 q = SwigType_parm(element); 818 Insert(result, 0, q); 819 Delete(q); 820 if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { 821 Insert(result, 0, "("); 822 Append(result, ")"); 823 } 824 firstarray = 0; 825 } else if (SwigType_isreference(element)) { 826 Insert(result, 0, "&"); 827 if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { 828 Insert(result, 0, "("); 829 Append(result, ")"); 830 } 831 isreference = 1; 832 } else if (SwigType_isarray(element)) { 833 DOH *size; 834 if (firstarray && !isreference) { 835 Append(result, "(*)"); 836 firstarray = 0; 837 } else { 838 Append(result, "["); 839 size = SwigType_parm(element); 840 Append(result, size); 841 Append(result, "]"); 842 Delete(size); 843 clear = 0; 844 } 845 isarray = 1; 846 } else if (SwigType_isfunction(element)) { 847 DOH *parms, *p; 848 int j, plen; 849 Append(result, "("); 850 parms = SwigType_parmlist(element); 851 plen = Len(parms); 852 for (j = 0; j < plen; j++) { 853 p = SwigType_str(Getitem(parms, j), 0); 854 Append(result, p); 855 Delete(p); 856 if (j < (plen - 1)) 857 Append(result, ","); 858 } 859 Append(result, ")"); 860 Delete(parms); 861 } else { 862 String *bs = SwigType_namestr(element); 863 Insert(result, 0, " "); 864 Insert(result, 0, bs); 865 Delete(bs); 866 } 867 element = nextelement; 868 } 869 Delete(elements); 870 if (clear) { 871 cast = NewStringEmpty(); 872 } else { 873 cast = NewStringf("(%s)", result); 874 } 875 if (name) { 876 if (isreference) { 877 if (isarray) 878 Clear(cast); 879 Append(cast, "*"); 880 } 881 Append(cast, name); 882 } 883 Delete(result); 884 Delete(tc); 885 return cast; 886} 887 888 889/* ----------------------------------------------------------------------------- 890 * SwigType_lcaststr() 891 * 892 * Casts a variable from the real type to the local datatype. 893 * ----------------------------------------------------------------------------- */ 894 895String *SwigType_lcaststr(SwigType *s, const_String_or_char_ptr name) { 896 String *result; 897 898 result = NewStringEmpty(); 899 900 if (SwigType_isarray(s)) { 901 String *lstr = SwigType_lstr(s, 0); 902 Printf(result, "(%s)%s", lstr, name); 903 Delete(lstr); 904 } else if (SwigType_isreference(s)) { 905 String *str = SwigType_str(s, 0); 906 Printf(result, "(%s)", str); 907 Delete(str); 908 if (name) 909 Append(result, name); 910 } else if (SwigType_isqualifier(s)) { 911 String *lstr = SwigType_lstr(s, 0); 912 Printf(result, "(%s)%s", lstr, name); 913 Delete(lstr); 914 } else { 915 if (name) 916 Append(result, name); 917 } 918 return result; 919} 920 921 922/* keep old mangling since Java codes need it */ 923String *SwigType_manglestr_default(SwigType *s) { 924 char *c; 925 String *result = 0; 926 String *base = 0; 927 SwigType *lt; 928 SwigType *sr = SwigType_typedef_qualified(s); 929 SwigType *ss = SwigType_typedef_resolve_all(sr); 930 931 s = ss; 932 933 if (SwigType_istemplate(ss)) { 934 SwigType *ty = Swig_symbol_template_deftype(ss, 0); 935 Delete(ss); 936 ss = ty; 937 s = ss; 938 } 939 Delete(sr); 940 941 lt = SwigType_ltype(s); 942 result = SwigType_prefix(lt); 943 base = SwigType_base(lt); 944 945 c = Char(result); 946 while (*c) { 947 if (!isalnum((int) *c)) 948 *c = '_'; 949 c++; 950 } 951 if (SwigType_istemplate(base)) { 952 String *b = SwigType_namestr(base); 953 Delete(base); 954 base = b; 955 } 956 957 Replace(base, "struct ", "", DOH_REPLACE_ANY); /* This might be problematic */ 958 Replace(base, "class ", "", DOH_REPLACE_ANY); 959 Replace(base, "union ", "", DOH_REPLACE_ANY); 960 Replace(base, "enum ", "", DOH_REPLACE_ANY); 961 962 c = Char(base); 963 while (*c) { 964 if (*c == '<') 965 *c = 'T'; 966 else if (*c == '>') 967 *c = 't'; 968 else if (*c == '*') 969 *c = 'p'; 970 else if (*c == '[') 971 *c = 'a'; 972 else if (*c == ']') 973 *c = 'A'; 974 else if (*c == '&') 975 *c = 'R'; 976 else if (*c == '(') 977 *c = 'f'; 978 else if (*c == ')') 979 *c = 'F'; 980 else if (!isalnum((int) *c)) 981 *c = '_'; 982 c++; 983 } 984 Append(result, base); 985 Insert(result, 0, "_"); 986 Delete(lt); 987 Delete(base); 988 if (ss) 989 Delete(ss); 990 return result; 991} 992 993String *SwigType_manglestr(SwigType *s) { 994 return SwigType_manglestr_default(s); 995} 996 997/* ----------------------------------------------------------------------------- 998 * SwigType_typename_replace() 999 * 1000 * Replaces a typename in a type with something else. Needed for templates. 1001 * ----------------------------------------------------------------------------- */ 1002 1003void SwigType_typename_replace(SwigType *t, String *pat, String *rep) { 1004 String *nt; 1005 int i, ilen; 1006 List *elem; 1007 1008 if (!Strstr(t, pat)) 1009 return; 1010 1011 if (Equal(t, pat)) { 1012 Replace(t, pat, rep, DOH_REPLACE_ANY); 1013 return; 1014 } 1015 nt = NewStringEmpty(); 1016 elem = SwigType_split(t); 1017 ilen = Len(elem); 1018 for (i = 0; i < ilen; i++) { 1019 String *e = Getitem(elem, i); 1020 if (SwigType_issimple(e)) { 1021 if (Equal(e, pat)) { 1022 /* Replaces a type of the form 'pat' with 'rep<args>' */ 1023 Replace(e, pat, rep, DOH_REPLACE_ANY); 1024 } else if (SwigType_istemplate(e)) { 1025 /* Replaces a type of the form 'pat<args>' with 'rep' */ 1026 if (Equal(e, pat)) { 1027 String *repbase = SwigType_templateprefix(rep); 1028 Replace(e, pat, repbase, DOH_REPLACE_ID | DOH_REPLACE_FIRST); 1029 Delete(repbase); 1030 } 1031 { 1032 String *tsuffix; 1033 List *tparms = SwigType_parmlist(e); 1034 int j, jlen; 1035 String *nt = SwigType_templateprefix(e); 1036 Append(nt, "<("); 1037 jlen = Len(tparms); 1038 for (j = 0; j < jlen; j++) { 1039 SwigType_typename_replace(Getitem(tparms, j), pat, rep); 1040 Append(nt, Getitem(tparms, j)); 1041 if (j < (jlen - 1)) 1042 Putc(',', nt); 1043 } 1044 tsuffix = SwigType_templatesuffix(e); 1045 Printf(nt, ")>%s", tsuffix); 1046 Delete(tsuffix); 1047 Clear(e); 1048 Append(e, nt); 1049 Delete(nt); 1050 Delete(tparms); 1051 } 1052 } else if (Swig_scopename_check(e)) { 1053 String *first, *rest; 1054 first = Swig_scopename_first(e); 1055 rest = Swig_scopename_suffix(e); 1056 SwigType_typename_replace(rest, pat, rep); 1057 SwigType_typename_replace(first, pat, rep); 1058 Clear(e); 1059 Printv(e, first, "::", rest, NIL); 1060 Delete(first); 1061 Delete(rest); 1062 } 1063 } else if (SwigType_isfunction(e)) { 1064 int j, jlen; 1065 List *fparms = SwigType_parmlist(e); 1066 Clear(e); 1067 Append(e, "f("); 1068 jlen = Len(fparms); 1069 for (j = 0; j < jlen; j++) { 1070 SwigType_typename_replace(Getitem(fparms, j), pat, rep); 1071 Append(e, Getitem(fparms, j)); 1072 if (j < (jlen - 1)) 1073 Putc(',', e); 1074 } 1075 Append(e, ")."); 1076 Delete(fparms); 1077 } else if (SwigType_isarray(e)) { 1078 Replace(e, pat, rep, DOH_REPLACE_ID); 1079 } 1080 Append(nt, e); 1081 } 1082 Clear(t); 1083 Append(t, nt); 1084 Delete(nt); 1085 Delete(elem); 1086} 1087 1088/* ----------------------------------------------------------------------------- 1089 * SwigType_check_decl() 1090 * 1091 * Checks type declarators for a match 1092 * ----------------------------------------------------------------------------- */ 1093 1094int SwigType_check_decl(SwigType *ty, const SwigType *decl) { 1095 SwigType *t, *t1, *t2; 1096 int r; 1097 t = SwigType_typedef_resolve_all(ty); 1098 t1 = SwigType_strip_qualifiers(t); 1099 t2 = SwigType_prefix(t1); 1100 r = Equal(t2, decl); 1101 Delete(t); 1102 Delete(t1); 1103 Delete(t2); 1104 return r == 1; 1105} 1106