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