/tags/rel-1-3-25/SWIG/Source/Swig/typemap.c
C | 1741 lines | 1227 code | 198 blank | 316 comment | 320 complexity | 6ca5b9bacdc9c9d6ac589f0fb9d411e3 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
1/* ----------------------------------------------------------------------------- 2 * typemap.c 3 * 4 * A somewhat generalized implementation of SWIG1.1 typemaps. 5 * 6 * Author(s) : David Beazley (beazley@cs.uchicago.edu) 7 * 8 * Copyright (C) 1999-2000. The University of Chicago 9 * See the file LICENSE for information on usage and redistribution. 10 * ----------------------------------------------------------------------------- */ 11 12char cvsroot_typemap_c[] = "$Header$"; 13 14#include "swig.h" 15#include "cparse.h" 16#include <ctype.h> 17 18static void replace_embedded_typemap(String *s); 19 20/* ----------------------------------------------------------------------------- 21 * Typemaps are stored in a collection of nested hash tables. Something like 22 * this: 23 * 24 * [ type ] 25 * +-------- [ name ] 26 * +-------- [ name ] 27 * 28 * Each hash table [ type ] or [ name ] then contains references to the 29 * different typemap methods. These are referenced by names such as 30 * "tmap:in", "tmap:out", "tmap:argout", and so forth. 31 * 32 * The object corresponding to a specific method has the following 33 * attributes: 34 * 35 * "type" - Typemap type 36 * "pname" - Parameter name 37 * "code" - Typemap code 38 * "typemap" - Descriptive text describing the actual map 39 * "locals" - Local variables (if any) 40 * 41 * ----------------------------------------------------------------------------- */ 42 43#define MAX_SCOPE 32 44 45 46static Hash *typemaps[MAX_SCOPE]; 47static int tm_scope = 0; 48 49static Hash* get_typemap(int tm_scope, SwigType* type) 50{ 51 Hash *tm = 0; 52 SwigType* dtype = 0; 53 if (SwigType_istemplate(type)) { 54 String *ty = Swig_symbol_template_deftype(type,0); 55 dtype = Swig_symbol_type_qualify(ty,0); 56 /* Printf(stderr,"gettm %s %s\n", type, dtype);*/ 57 type = dtype; 58 Delete(ty); 59 } 60 tm = Getattr(typemaps[tm_scope],type); 61 Delete(dtype); 62 return tm; 63} 64 65static void set_typemap(int tm_scope, SwigType* type, Hash* tm) 66{ 67 SwigType* dtype = 0; 68 if (SwigType_istemplate(type)) { 69 String *ty = Swig_symbol_template_deftype(type,0); 70 dtype = Swig_symbol_type_qualify(ty,0); 71 /* Printf(stderr,"settm %s %s\n", type, dtype);*/ 72 type = dtype; 73 Delete(ty); 74 } else { 75 dtype = Copy(type); 76 type = dtype; 77 } 78 Setattr(typemaps[tm_scope],type,tm); 79 Delete(dtype); 80} 81 82 83/* ----------------------------------------------------------------------------- 84 * Swig_typemap_init() 85 * 86 * Initialize the typemap system 87 * ----------------------------------------------------------------------------- */ 88 89void Swig_typemap_init() { 90 int i; 91 for (i = 0; i < MAX_SCOPE; i++) { 92 typemaps[i] = 0; 93 } 94 typemaps[0] = NewHash(); 95 tm_scope = 0; 96} 97 98static String *tmop_name(const String_or_char *op) { 99 static Hash *names = 0; 100 String *s; 101 /* Due to "interesting" object-identity semantics of DOH, 102 we have to make sure that we only intern strings without object 103 identity into the hash table. 104 105 (Swig_typemap_attach_kwargs calls tmop_name several times with 106 the "same" String *op (i.e., same object identity) but differing 107 string values.) 108 109 Most other callers work around this by using char* rather than 110 String *. 111 -- mkoeppe, Jun 17, 2003 112 */ 113 const char *op_without_object_identity = Char(op); 114 if (!names) names = NewHash(); 115 s = Getattr(names, op_without_object_identity); 116 if (s) return s; 117 s = NewStringf("tmap:%s",op); 118 Setattr(names,op_without_object_identity,s); 119 Delete(s); 120 return s; 121} 122 123/* ----------------------------------------------------------------------------- 124 * Swig_typemap_new_scope() 125 * 126 * Create a new typemap scope 127 * ----------------------------------------------------------------------------- */ 128 129void Swig_typemap_new_scope() { 130 tm_scope++; 131 typemaps[tm_scope] = NewHash(); 132} 133 134/* ----------------------------------------------------------------------------- 135 * Swig_typemap_pop_scope() 136 * 137 * Pop the last typemap scope off 138 * ----------------------------------------------------------------------------- */ 139 140Hash * 141Swig_typemap_pop_scope() { 142 if (tm_scope > 0) { 143 return typemaps[tm_scope--]; 144 } 145 return 0; 146} 147 148/* ----------------------------------------------------------------------------- 149 * Swig_typemap_register() 150 * 151 * Add a new multi-valued typemap 152 * ----------------------------------------------------------------------------- */ 153 154void 155Swig_typemap_register(const String_or_char *op, ParmList *parms, String_or_char *code, ParmList *locals, ParmList *kwargs) { 156 Hash *tm; 157 Hash *tm1; 158 Hash *tm2; 159 Parm *np; 160 String *tmop; 161 SwigType *type; 162 String *pname; 163 164 if (!parms) return; 165 tmop = tmop_name(op); 166 167 /* Register the first type in the parameter list */ 168 169 type = Getattr(parms,"type"); 170 pname = Getattr(parms,"name"); 171 172 /* See if this type has been seen before */ 173 tm = get_typemap(tm_scope,type); 174 if (!tm) { 175 tm = NewHash(); 176 set_typemap(tm_scope,type,tm); 177 Delete(tm); 178 } 179 if (pname) { 180 /* See if parameter has been seen before */ 181 tm1 = Getattr(tm,pname); 182 if (!tm1) { 183 tm1 = NewHash(); 184 Setattr(tm,pname,tm1); 185 Delete(tm1); 186 } 187 tm = tm1; 188 } 189 190 /* Now see if this typemap op has been seen before */ 191 tm2 = Getattr(tm,tmop); 192 if (!tm2) { 193 tm2 = NewHash(); 194 Setattr(tm,tmop,tm2); 195 Delete(tm2); 196 } 197 198 /* For a multi-valued typemap, the typemap code and information 199 is really only stored in the last argument. However, to 200 make this work, we perform a really neat trick using 201 the typemap operator name. 202 203 For example, consider this typemap 204 205 %typemap(in) (int foo, int *bar, char *blah[]) { 206 ... 207 } 208 209 To store it, we look at typemaps for the following: 210 211 operator type-name 212 ---------------------------------------------- 213 "in" int foo 214 "in-int+foo:" int *bar 215 "in-int+foo:-p.int+bar: char *blah[] 216 217 Notice how the operator expands to encode information about 218 previous arguments. 219 220 */ 221 222 np = nextSibling(parms); 223 if (np) { 224 /* Make an entirely new operator key */ 225 String *newop = NewStringf("%s-%s+%s:",op,type,pname); 226 /* Now reregister on the remaining arguments */ 227 Swig_typemap_register(newop,np,code,locals,kwargs); 228 229 /* Setattr(tm2,newop,newop); */ 230 Delete(newop); 231 } else { 232 String *str = SwigType_str(type,pname); 233 String *typemap = NewStringf("typemap(%s) %s", op, str); 234 ParmList *clocals = CopyParmList(locals); 235 ParmList *ckwargs = CopyParmList(kwargs); 236 237 Setattr(tm2,"code", code); 238 Setattr(tm2,"type", type); 239 Setattr(tm2,"typemap", typemap); 240 if (pname) { 241 Setattr(tm2,"pname", pname); 242 } 243 Setattr(tm2,"locals", clocals); 244 Setattr(tm2,"kwargs", ckwargs); 245 246 Delete(clocals); 247 Delete(ckwargs); 248 249 Delete(str); 250 Delete(typemap); 251 } 252} 253 254/* ----------------------------------------------------------------------------- 255 * Swig_typemap_get() 256 * 257 * Retrieve typemap information from current scope. 258 * ----------------------------------------------------------------------------- */ 259 260static Hash * 261Swig_typemap_get(SwigType *type, String_or_char *name, int scope) { 262 Hash *tm, *tm1; 263 /* See if this type has been seen before */ 264 if ((scope < 0) || (scope > tm_scope)) return 0; 265 tm = get_typemap(scope,type); 266 if (!tm) { 267 return 0; 268 } 269 if ((name) && Len(name)) { 270 tm1 = Getattr(tm, name); 271 return tm1; 272 } 273 return tm; 274} 275 276/* ----------------------------------------------------------------------------- 277 * Swig_typemap_copy() 278 * 279 * Copy a typemap 280 * ----------------------------------------------------------------------------- */ 281 282int 283Swig_typemap_copy(const String_or_char *op, ParmList *srcparms, ParmList *parms) { 284 Hash *tm = 0; 285 String *tmop; 286 Parm *p; 287 String *pname; 288 SwigType *ptype; 289 int ts = tm_scope; 290 String *tmops, *newop; 291 if (ParmList_len(parms) != ParmList_len(srcparms)) return -1; 292 293 tmop = tmop_name(op); 294 while (ts >= 0) { 295 p = srcparms; 296 tmops = NewString(tmop); 297 while (p) { 298 ptype = Getattr(p,"type"); 299 pname = Getattr(p,"name"); 300 301 /* Lookup the type */ 302 tm = Swig_typemap_get(ptype,pname,ts); 303 if (!tm) break; 304 305 tm = Getattr(tm,tmops); 306 if (!tm) break; 307 308 /* Got a match. Look for next typemap */ 309 newop = NewStringf("%s-%s+%s:",tmops,ptype,pname); 310 Delete(tmops); 311 tmops = newop; 312 p = nextSibling(p); 313 } 314 Delete(tmops); 315 316 if (!p && tm) { 317 318 /* Got some kind of match */ 319 Swig_typemap_register(op,parms, Getattr(tm,"code"), Getattr(tm,"locals"),Getattr(tm,"kwargs")); 320 return 0; 321 } 322 ts--; 323 } 324 /* Not found */ 325 return -1; 326 327} 328 329/* ----------------------------------------------------------------------------- 330 * Swig_typemap_clear() 331 * 332 * Delete a multi-valued typemap 333 * ----------------------------------------------------------------------------- */ 334 335void 336Swig_typemap_clear(const String_or_char *op, ParmList *parms) { 337 SwigType *type; 338 String *name; 339 Parm *p; 340 String *newop; 341 Hash *tm = 0; 342 343 /* This might not work */ 344 newop = NewString(op); 345 p = parms; 346 while (p) { 347 type = Getattr(p,"type"); 348 name = Getattr(p,"name"); 349 tm = Swig_typemap_get(type,name,tm_scope); 350 if (!tm) return; 351 p = nextSibling(p); 352 if (p) 353 Printf(newop,"-%s+%s:", type,name); 354 } 355 if (tm) { 356 tm = Getattr(tm, tmop_name(newop)); 357 if (tm) { 358 Delattr(tm,"code"); 359 Delattr(tm,"locals"); 360 Delattr(tm,"kwargs"); 361 } 362 } 363 Delete(newop); 364} 365 366/* ----------------------------------------------------------------------------- 367 * Swig_typemap_apply() 368 * 369 * Multi-argument %apply directive. This is pretty horrible so I sure hope 370 * it works. 371 * ----------------------------------------------------------------------------- */ 372 373static 374int count_args(String *s) { 375 /* Count up number of arguments */ 376 int na = 0; 377 char *c = Char(s); 378 while (*c) { 379 if (*c == '+') na++; 380 c++; 381 } 382 return na; 383} 384 385int 386Swig_typemap_apply(ParmList *src, ParmList *dest) { 387 String *ssig, *dsig; 388 Parm *p, *np, *lastp, *dp, *lastdp = 0; 389 int narg = 0; 390 int ts = tm_scope; 391 SwigType *type = 0, *name; 392 Hash *tm, *sm; 393 int match = 0; 394 395 /* Printf(stdout,"apply : %s --> %s\n", ParmList_str(src), ParmList_str(dest)); */ 396 397 /* Create type signature of source */ 398 ssig = NewString(""); 399 dsig = NewString(""); 400 p = src; 401 dp = dest; 402 lastp = 0; 403 while (p) { 404 lastp = p; 405 lastdp = dp; 406 np = nextSibling(p); 407 if (np) { 408 Printf(ssig,"-%s+%s:", Getattr(p,"type"), Getattr(p,"name")); 409 Printf(dsig,"-%s+%s:", Getattr(dp,"type"), Getattr(dp,"name")); 410 narg++; 411 } 412 p = np; 413 dp = nextSibling(dp); 414 } 415 416 /* make sure a typemap node exists for the last destination node */ 417 type = Getattr(lastdp,"type"); 418 tm = get_typemap(tm_scope,type); 419 if (!tm) { 420 tm = NewHash(); 421 set_typemap(tm_scope,type,tm); 422 Delete(tm); 423 } 424 name = Getattr(lastdp,"name"); 425 if (name) { 426 Hash *tm1 = Getattr(tm,name); 427 if (!tm1) { 428 tm1 = NewHash(); 429 Setattr(tm,NewString(name),tm1); 430 Delete(tm1); 431 } 432 tm = tm1; 433 } 434 435 /* This is a little nasty. We need to go searching for all possible typemaps in the 436 source and apply them to the target */ 437 438 type = Getattr(lastp,"type"); 439 name = Getattr(lastp,"name"); 440 441 while (ts >= 0) { 442 443 /* See if there is a matching typemap in this scope */ 444 sm = Swig_typemap_get(type,name,ts); 445 446 /* if there is not matching, look for a typemap in the 447 original typedef, if any, like in: 448 449 typedef unsigned long size_t; 450 ... 451 %apply(size_t) {my_size}; ==> %apply(unsigned long) {my_size}; 452 */ 453 if (!sm) { 454 SwigType *ntype = SwigType_typedef_resolve(type); 455 if (ntype && (Cmp(ntype,type) != 0)) { 456 sm = Swig_typemap_get(ntype,name,ts); 457 } 458 Delete(ntype); 459 } 460 461 if (sm) { 462 /* Got a typemap. Need to only merge attributes for methods that match our signature */ 463 Iterator ki; 464 match = 1; 465 for (ki = First(sm); ki.key; ki = Next(ki)) { 466 /* Check for a signature match with the source signature */ 467 if ((count_args(ki.key) == narg) && (Strstr(ki.key,ssig))) { 468 String *oldm; 469 /* A typemap we have to copy */ 470 String *nkey = Copy(ki.key); 471 Replace(nkey,ssig,dsig,DOH_REPLACE_ANY); 472 473 /* Make sure the typemap doesn't already exist in the target map */ 474 475 oldm = Getattr(tm,nkey); 476 if (!oldm || (!Getattr(tm,"code"))) { 477 String *code; 478 ParmList *locals; 479 ParmList *kwargs; 480 Hash *sm1 = ki.item; 481 482 code = Getattr(sm1,"code"); 483 locals = Getattr(sm1,"locals"); 484 kwargs = Getattr(sm1,"kwargs"); 485 if (code) { 486 Replace(nkey,dsig,"", DOH_REPLACE_ANY); 487 Replace(nkey,"tmap:","", DOH_REPLACE_ANY); 488 Swig_typemap_register(nkey,dest,code,locals,kwargs); 489 } 490 } 491 Delete(nkey); 492 } 493 } 494 } 495 ts--; 496 } 497 Delete(ssig); 498 Delete(dsig); 499 return match; 500} 501 502/* ----------------------------------------------------------------------------- 503 * Swig_typemap_clear_apply() 504 * 505 * %clear directive. Clears all typemaps for a type (in the current scope only). 506 * ----------------------------------------------------------------------------- */ 507 508/* Multi-argument %clear directive */ 509void 510Swig_typemap_clear_apply(Parm *parms) { 511 String *tsig; 512 Parm *p, *np, *lastp; 513 int narg = 0; 514 Hash *tm; 515 String *name; 516 517 /* Create a type signature of the parameters */ 518 tsig = NewString(""); 519 p = parms; 520 lastp = 0; 521 while (p) { 522 lastp = p; 523 np = nextSibling(p); 524 if (np) { 525 Printf(tsig,"-%s+%s:", Getattr(p,"type"), Getattr(p,"name")); 526 narg++; 527 } 528 p = np; 529 } 530 tm = get_typemap(tm_scope,Getattr(lastp,"type")); 531 if (!tm) { 532 Delete(tsig); 533 return; 534 } 535 name = Getattr(lastp,"name"); 536 if (name) { 537 tm = Getattr(tm,name); 538 } 539 if (tm) { 540 /* Clear typemaps that match our signature */ 541 Iterator ki, ki2; 542 543 for (ki = First(tm); ki.key; ki = Next(ki)) { 544 if (Strncmp(ki.key,"tmap:",5) == 0) { 545 int na = count_args(ki.key); 546 if ((na == narg) && Strstr(ki.key,tsig)) { 547 Hash *h = ki.item; 548 for (ki2 = First(h); ki2.key; ki2 = Next(ki2)) { 549 Delattr(h,ki2.key); 550 } 551 } 552 } 553 } 554 } 555 Delete(tsig); 556} 557 558/* Internal function to strip array dimensions. */ 559static SwigType *strip_arrays(SwigType *type) { 560 SwigType *t; 561 int ndim; 562 int i; 563 t = Copy(type); 564 ndim = SwigType_array_ndim(t); 565 for (i = 0; i < ndim; i++) { 566 SwigType_array_setdim(t,i,"ANY"); 567 } 568 return t; 569} 570 571/* ----------------------------------------------------------------------------- 572 * Swig_typemap_search() 573 * 574 * Search for a typemap match. Tries to find the most specific typemap 575 * that includes a 'code' attribute. 576 * ----------------------------------------------------------------------------- */ 577 578Hash * 579Swig_typemap_search(const String_or_char *op, SwigType *type, const String_or_char *name, SwigType **matchtype) { 580 Hash *result = 0, *tm, *tm1, *tma; 581 Hash *backup = 0; 582 SwigType *noarrays = 0; 583 SwigType *primitive = 0; 584 SwigType *ctype = 0; 585 int ts; 586 int isarray; 587 const String *cname = 0; 588 SwigType *unstripped = 0; 589 String *tmop = tmop_name(op); 590 591 if ((name) && Len(name)) cname = name; 592 ts = tm_scope; 593 594 while (ts >= 0) { 595 ctype = type; 596 while (ctype) { 597 /* Try to get an exact type-match */ 598 tm = get_typemap(ts,ctype); 599 if (tm && cname) { 600 tm1 = Getattr(tm,cname); 601 if (tm1) { 602 result = Getattr(tm1,tmop); /* See if there is a type-name match */ 603 if (result && Getattr(result,"code")) goto ret_result; 604 if (result) backup = result; 605 } 606 } 607 if (tm) { 608 result = Getattr(tm,tmop); /* See if there is simply a type match */ 609 if (result && Getattr(result,"code")) goto ret_result; 610 if (result) backup = result; 611 } 612 isarray = SwigType_isarray(ctype); 613 if (isarray) { 614 /* If working with arrays, strip away all of the dimensions and replace with "ANY". 615 See if that generates a match */ 616 if (!noarrays) { 617 noarrays = strip_arrays(ctype); 618 } 619 tma = get_typemap(ts,noarrays); 620 if (tma && cname) { 621 tm1 = Getattr(tma,cname); 622 if (tm1) { 623 result = Getattr(tm1,tmop); /* type-name match */ 624 if (result && Getattr(result,"code")) goto ret_result; 625 if (result) backup = result; 626 } 627 } 628 if (tma) { 629 result = Getattr(tma,tmop); /* type match */ 630 if (result && Getattr(result,"code")) goto ret_result; 631 if (result) backup = result; 632 } 633 Delete(noarrays); 634 noarrays = 0; 635 } 636 637 /* No match so far. If the type is unstripped, we'll strip its 638 qualifiers and check. Otherwise, we'll try to resolve a typedef */ 639 640 if (!unstripped) { 641 unstripped = ctype; 642 ctype = SwigType_strip_qualifiers(ctype); 643 if (Strcmp(ctype,unstripped) != 0) continue; /* Types are different */ 644 Delete(ctype); 645 ctype = unstripped; 646 unstripped = 0; 647 } 648 { 649 String *octype; 650 if (unstripped) { 651 Delete(ctype); 652 ctype = unstripped; 653 unstripped = 0; 654 } 655 octype = ctype; 656 ctype = SwigType_typedef_resolve(ctype); 657 if (octype != type) Delete(octype); 658 } 659 } 660 661 /* Hmmm. Well, no match seems to be found at all. See if there is some kind of default mapping */ 662 663 primitive = SwigType_default(type); 664 while (primitive) { 665 tm = get_typemap(ts,primitive); 666 if (tm && cname) { 667 tm1 = Getattr(tm,cname); 668 if (tm1) { 669 result = Getattr(tm1,tmop); /* See if there is a type-name match */ 670 if (result) goto ret_result; 671 } 672 } 673 if (tm) { /* See if there is simply a type match */ 674 result = Getattr(tm,tmop); 675 if (result) goto ret_result; 676 } 677 { 678 SwigType *nprim = SwigType_default(primitive); 679 Delete(primitive); 680 primitive = nprim; 681 } 682 } 683 if (ctype != type) { Delete(ctype); ctype = 0; } 684 ts--; /* Hmmm. Nothing found in this scope. Guess we'll go try another scope */ 685 } 686 result = backup; 687 688 ret_result: 689 if (noarrays) Delete(noarrays); 690 if (primitive) Delete(primitive); 691 if ((unstripped) && (unstripped != type)) Delete(unstripped); 692 if (matchtype) { 693 *matchtype = Copy(ctype); 694 } 695 if (type != ctype) Delete(ctype); 696 return result; 697} 698 699 700/* ----------------------------------------------------------------------------- 701 * Swig_typemap_search_multi() 702 * 703 * Search for a multi-valued typemap. 704 * ----------------------------------------------------------------------------- */ 705 706Hash * 707Swig_typemap_search_multi(const String_or_char *op, ParmList *parms, int *nmatch) { 708 SwigType *type; 709 SwigType *mtype = 0; 710 String *name; 711 String *newop; 712 Hash *tm, *tm1; 713 714 if (!parms) { 715 *nmatch = 0; 716 return 0; 717 } 718 type = Getattr(parms,"type"); 719 name = Getattr(parms,"name"); 720 721 /* Try to find a match on the first type */ 722 tm = Swig_typemap_search(op, type, name, &mtype); 723 if (tm) { 724 if (mtype && SwigType_isarray(mtype)) { 725 Setattr(parms,"tmap:match", mtype); 726 } 727 Delete(mtype); 728 newop = NewStringf("%s-%s+%s:", op, type,name); 729 tm1 = Swig_typemap_search_multi(newop, nextSibling(parms), nmatch); 730 if (tm1) tm = tm1; 731 if (Getattr(tm,"code")) { 732 *(nmatch) = *nmatch + 1; 733 } else { 734 tm = 0; 735 } 736 Delete(newop); 737 } 738 return tm; 739} 740 741 742/* ----------------------------------------------------------------------------- 743 * typemap_replace_vars() 744 * 745 * Replaces typemap variables on a string. index is the $n variable. 746 * type and pname are the type and parameter name. 747 * ----------------------------------------------------------------------------- */ 748 749static 750void replace_local_types(ParmList *p, const String *name, const String *rep) { 751 SwigType *t; 752 while (p) { 753 t = Getattr(p,"type"); 754 Replace(t,name,rep,DOH_REPLACE_ANY); 755 p = nextSibling(p); 756 } 757} 758 759static 760int check_locals(ParmList *p, const char *s) { 761 while (p) { 762 char *c = GetChar(p,"type"); 763 if (strstr(c,s)) return 1; 764 p = nextSibling(p); 765 } 766 return 0; 767} 768 769static 770void typemap_replace_vars(String *s, ParmList *locals, SwigType *type, SwigType *rtype, String *pname, String *lname, int index) 771{ 772 char var[512]; 773 char *varname; 774 SwigType *ftype; 775 776 Replaceall(s,"$typemap","$TYPEMAP"); 777 778 ftype = SwigType_typedef_resolve_all(type); 779 780 if (!pname) pname = lname; 781 { 782 Parm *p; 783 int rep = 0; 784 p = locals; 785 while (p) { 786 if (Strchr(Getattr(p,"type"),'$')) rep = 1; 787 p = nextSibling(p); 788 } 789 if (!rep) locals = 0; 790 } 791 792 sprintf(var,"$%d_",index); 793 varname = &var[strlen(var)]; 794 795 /* If the original datatype was an array. We're going to go through and substitute 796 its array dimensions */ 797 798 if (SwigType_isarray(type) || SwigType_isarray(ftype)) { 799 String *size; 800 int ndim; 801 int i; 802 if (SwigType_array_ndim(type) != SwigType_array_ndim(ftype)) type = ftype; 803 ndim = SwigType_array_ndim(type); 804 size = NewString(""); 805 for (i = 0; i < ndim; i++) { 806 String *dim = SwigType_array_getdim(type,i); 807 if (index == 1) { 808 char t[32]; 809 sprintf(t,"$dim%d",i); 810 Replace(s,t,dim,DOH_REPLACE_ANY); 811 replace_local_types(locals,t,dim); 812 } 813 sprintf(varname,"dim%d",i); 814 Replace(s,var,dim,DOH_REPLACE_ANY); 815 replace_local_types(locals,var,dim); 816 if (Len(size)) Putc('*',size); 817 Append(size,dim); 818 Delete(dim); 819 } 820 sprintf(varname,"size"); 821 Replace(s,var,size,DOH_REPLACE_ANY); 822 replace_local_types(locals,var,size); 823 Delete(size); 824 } 825 826 /* Parameter name substitution */ 827 if (index == 1) { 828 Replace(s,"$parmname",pname, DOH_REPLACE_ANY); 829 } 830 strcpy(varname,"name"); 831 Replace(s,var,pname,DOH_REPLACE_ANY); 832 833 /* Type-related stuff */ 834 { 835 SwigType *star_type, *amp_type, *base_type, *lex_type; 836 SwigType *ltype, *star_ltype, *amp_ltype; 837 String *mangle, *star_mangle, *amp_mangle, *base_mangle, *base_name; 838 String *descriptor, *star_descriptor, *amp_descriptor; 839 String *ts; 840 char *sc; 841 842 sc = Char(s); 843 844 if (strstr(sc,"type") || check_locals(locals,"type")) { 845 /* Given type : $type */ 846 ts = SwigType_str(type,0); 847 if (index == 1) { 848 Replace(s, "$type", ts, DOH_REPLACE_ANY); 849 replace_local_types(locals,"$type",type); 850 } 851 strcpy(varname,"type"); 852 Replace(s,var,ts,DOH_REPLACE_ANY); 853 replace_local_types(locals,var,type); 854 Delete(ts); 855 sc = Char(s); 856 } 857 if (strstr(sc,"ltype") || check_locals(locals,"ltype")) { 858 /* Local type: $ltype */ 859 ltype = SwigType_ltype(type); 860 ts = SwigType_str(ltype,0); 861 if (index == 1) { 862 Replace(s, "$ltype", ts, DOH_REPLACE_ANY); 863 replace_local_types(locals,"$ltype",ltype); 864 } 865 strcpy(varname,"ltype"); 866 Replace(s,var,ts,DOH_REPLACE_ANY); 867 replace_local_types(locals,var,ltype); 868 Delete(ts); 869 Delete(ltype); 870 sc = Char(s); 871 } 872 if (strstr(sc,"mangle") || strstr(sc,"descriptor")) { 873 /* Mangled type */ 874 875 mangle = SwigType_manglestr(type); 876 if (index == 1) 877 Replace(s, "$mangle", mangle, DOH_REPLACE_ANY); 878 strcpy(varname,"mangle"); 879 Replace(s,var,mangle,DOH_REPLACE_ANY); 880 881 descriptor = NewStringf("SWIGTYPE%s", mangle); 882 883 if (index == 1) 884 if (Replace(s, "$descriptor", descriptor, DOH_REPLACE_ANY)) 885 SwigType_remember(type); 886 887 strcpy(varname,"descriptor"); 888 if (Replace(s,var,descriptor,DOH_REPLACE_ANY)) 889 SwigType_remember(type); 890 891 Delete(descriptor); 892 Delete(mangle); 893 } 894 895 /* One pointer level removed */ 896 /* This creates variables of the form 897 $*n_type 898 $*n_ltype 899 */ 900 901 if (SwigType_ispointer(ftype) || (SwigType_isarray(ftype)) || (SwigType_isreference(ftype))) { 902 if (!(SwigType_isarray(type) || SwigType_ispointer(type) || SwigType_isreference(type))) { 903 star_type = Copy(ftype); 904 } else { 905 star_type = Copy(type); 906 } 907 if (!SwigType_isreference(star_type)) { 908 if (SwigType_isarray(star_type)) { 909 SwigType_del_element(star_type); 910 } else { 911 SwigType_del_pointer(star_type); 912 } 913 ts = SwigType_str(star_type,0); 914 if (index == 1) { 915 Replace(s, "$*type", ts, DOH_REPLACE_ANY); 916 replace_local_types(locals,"$*type",star_type); 917 } 918 sprintf(varname,"$*%d_type",index); 919 Replace(s,varname,ts,DOH_REPLACE_ANY); 920 replace_local_types(locals,varname,star_type); 921 Delete(ts); 922 } else { 923 SwigType_del_element(star_type); 924 } 925 star_ltype = SwigType_ltype(star_type); 926 ts = SwigType_str(star_ltype,0); 927 if (index == 1) { 928 Replace(s, "$*ltype", ts, DOH_REPLACE_ANY); 929 replace_local_types(locals,"$*ltype",star_ltype); 930 } 931 sprintf(varname,"$*%d_ltype",index); 932 Replace(s,varname,ts,DOH_REPLACE_ANY); 933 replace_local_types(locals,varname,star_ltype); 934 Delete(ts); 935 Delete(star_ltype); 936 937 star_mangle = SwigType_manglestr(star_type); 938 if (index == 1) 939 Replace(s, "$*mangle", star_mangle, DOH_REPLACE_ANY); 940 941 sprintf(varname,"$*%d_mangle",index); 942 Replace(s,varname,star_mangle,DOH_REPLACE_ANY); 943 944 star_descriptor = NewStringf("SWIGTYPE%s", star_mangle); 945 if (index == 1) 946 if (Replace(s, "$*descriptor", 947 star_descriptor, DOH_REPLACE_ANY)) 948 SwigType_remember(star_type); 949 sprintf(varname,"$*%d_descriptor",index); 950 if (Replace(s,varname,star_descriptor,DOH_REPLACE_ANY)) 951 SwigType_remember(star_type); 952 953 Delete(star_descriptor); 954 Delete(star_mangle); 955 Delete(star_type); 956 } 957 else { 958 /* TODO: Signal error if one of the $* substitutions is 959 requested */ 960 } 961 /* One pointer level added */ 962 amp_type = Copy(type); 963 SwigType_add_pointer(amp_type); 964 ts = SwigType_str(amp_type,0); 965 if (index == 1) { 966 Replace(s, "$&type", ts, DOH_REPLACE_ANY); 967 replace_local_types(locals,"$&type",amp_type); 968 } 969 sprintf(varname,"$&%d_type",index); 970 Replace(s,varname,ts,DOH_REPLACE_ANY); 971 replace_local_types(locals,varname,amp_type); 972 Delete(ts); 973 974 amp_ltype = SwigType_ltype(type); 975 SwigType_add_pointer(amp_ltype); 976 ts = SwigType_str(amp_ltype,0); 977 978 if (index == 1) { 979 Replace(s, "$<ype", ts, DOH_REPLACE_ANY); 980 replace_local_types(locals, "$<ype", amp_ltype); 981 } 982 sprintf(varname,"$&%d_ltype",index); 983 Replace(s,varname,ts,DOH_REPLACE_ANY); 984 replace_local_types(locals,varname,amp_ltype); 985 Delete(ts); 986 Delete(amp_ltype); 987 988 amp_mangle = SwigType_manglestr(amp_type); 989 if (index == 1) 990 Replace(s, "$&mangle", amp_mangle, DOH_REPLACE_ANY); 991 sprintf(varname,"$&%d_mangle",index); 992 Replace(s,varname,amp_mangle,DOH_REPLACE_ANY); 993 994 amp_descriptor = NewStringf("SWIGTYPE%s", amp_mangle); 995 if (index == 1) 996 if (Replace(s, "$&descriptor", 997 amp_descriptor, DOH_REPLACE_ANY)) 998 SwigType_remember(amp_type); 999 sprintf(varname,"$&%d_descriptor",index); 1000 if (Replace(s,varname,amp_descriptor,DOH_REPLACE_ANY)) 1001 SwigType_remember(amp_type); 1002 1003 Delete(amp_descriptor); 1004 Delete(amp_mangle); 1005 Delete(amp_type); 1006 1007 /* Base type */ 1008 if (SwigType_isarray(type)) { 1009 SwigType *bt = Copy(type); 1010 Delete(SwigType_pop_arrays(bt)); 1011 base_type = SwigType_str(bt,0); 1012 Delete(bt); 1013 } else { 1014 base_type = SwigType_base(type); 1015 } 1016 1017 base_name = SwigType_namestr(base_type); 1018 if (index == 1) { 1019 Replace(s,"$basetype", base_name, DOH_REPLACE_ANY); 1020 replace_local_types(locals,"$basetype", base_name); 1021 } 1022 strcpy(varname,"basetype"); 1023 Replace(s,var,base_type,DOH_REPLACE_ANY); 1024 replace_local_types(locals,var,base_name); 1025 1026 base_mangle = SwigType_manglestr(base_type); 1027 if (index == 1) 1028 Replace(s,"$basemangle", base_mangle, DOH_REPLACE_ANY); 1029 strcpy(varname,"basemangle"); 1030 Replace(s,var,base_mangle,DOH_REPLACE_ANY); 1031 Delete(base_mangle); 1032 Delete(base_type); 1033 Delete(base_name); 1034 1035 lex_type = SwigType_base(rtype); 1036 if (index == 1) 1037 Replace(s,"$lextype", lex_type, DOH_REPLACE_ANY); 1038 strcpy(varname,"lextype"); 1039 Replace(s,var,lex_type,DOH_REPLACE_ANY); 1040 Delete(lex_type); 1041 } 1042 1043 /* Replace any $n. with (&n)-> */ 1044 { 1045 char temp[64]; 1046 sprintf(var,"$%d.",index); 1047 sprintf(temp,"(&$%d)->", index); 1048 Replace(s,var,temp,DOH_REPLACE_ANY); 1049 } 1050 1051 /* Replace the bare $n variable */ 1052 sprintf(var,"$%d",index); 1053 Replace(s,var,lname,DOH_REPLACE_ANY); 1054 Delete(ftype); 1055} 1056 1057/* ------------------------------------------------------------------------ 1058 * static typemap_locals() 1059 * 1060 * Takes a string, a parameter list and a wrapper function argument and 1061 * creates the local variables. 1062 * ------------------------------------------------------------------------ */ 1063 1064static void typemap_locals(DOHString *s, ParmList *l, Wrapper *f, int argnum) { 1065 Parm *p; 1066 char *new_name; 1067 1068 p = l; 1069 while (p) { 1070 SwigType *pt = Getattr(p,"type"); 1071 SwigType *at = SwigType_alttype(pt, 1); 1072 String *pn = Getattr(p,"name"); 1073 String *value = Getattr(p,"value"); 1074 if (at) pt = at; 1075 if (pn) { 1076 if (Len(pn) > 0) { 1077 String *str; 1078 int isglobal = 0; 1079 1080 str = NewString(""); 1081 1082 if (Strncmp(pn,"_global_",8) == 0) { 1083 isglobal = 1; 1084 } 1085 1086 /* If the user gave us $type as the name of the local variable, we'll use 1087 the passed datatype instead */ 1088 1089 if ((argnum >= 0) && (!isglobal)) { 1090 Printf(str,"%s%d",pn,argnum); 1091 } else { 1092 Printf(str,"%s",pn); 1093 } 1094 if (isglobal && Wrapper_check_local(f,str)) { 1095 p = nextSibling(p); 1096 continue; 1097 } 1098 if (value) { 1099 String *pstr = SwigType_str(pt,str); 1100 new_name = Wrapper_new_localv(f,str, pstr, "=", value, NIL); 1101 Delete(pstr); 1102 } else { 1103 String *pstr = SwigType_str(pt,str); 1104 new_name = Wrapper_new_localv(f,str, pstr, NIL); 1105 Delete(pstr); 1106 } 1107 if (!isglobal) { 1108 /* Substitute */ 1109 Replace(s,pn,new_name,DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE); 1110 } 1111 Delete(str); 1112 } 1113 } 1114 p = nextSibling(p); 1115 Delete(at); 1116 } 1117} 1118 1119/* ----------------------------------------------------------------------------- 1120 * Swig_typemap_lookup() 1121 * 1122 * Perform a typemap lookup (ala SWIG1.1) 1123 * ----------------------------------------------------------------------------- */ 1124 1125String *Swig_typemap_lookup(const String_or_char *op, SwigType *type, String_or_char *pname, 1126 String_or_char *lname, String_or_char *source, 1127 String_or_char *target, Wrapper *f) 1128{ 1129 Hash *tm; 1130 String *s = 0; 1131 SwigType *mtype = 0; 1132 ParmList *locals; 1133 tm = Swig_typemap_search(op,type,pname,&mtype); 1134 if (!tm) return 0; 1135 1136 s = Getattr(tm,"code"); 1137 if (!s) return 0; 1138 1139 /* Blocked */ 1140 if (Cmp(s,"pass") == 0) return 0; 1141 1142 s = Copy(s); /* Make a local copy of the typemap code */ 1143 1144 locals = Getattr(tm,"locals"); 1145 if (locals) locals = CopyParmList(locals); 1146 1147 /* This is wrong. It replaces locals in place. Need to fix this */ 1148 if (mtype && SwigType_isarray(mtype)) { 1149 typemap_replace_vars(s,locals,mtype,type,pname,lname,1); 1150 } else { 1151 typemap_replace_vars(s,locals,type,type,pname,lname,1); 1152 } 1153 1154 if (locals && f) { 1155 typemap_locals(s,locals,f,-1); 1156 } 1157 1158 replace_embedded_typemap(s); 1159 1160 /* Now perform character replacements */ 1161 Replace(s,"$source",source,DOH_REPLACE_ANY); 1162 Replace(s,"$target",target,DOH_REPLACE_ANY); 1163 1164 /* { 1165 String *tmname = Getattr(tm,"typemap"); 1166 if (tmname) Replace(s,"$typemap",tmname, DOH_REPLACE_ANY); 1167 } 1168 */ 1169 1170 Replace(s,"$parmname",pname, DOH_REPLACE_ANY); 1171 /* Replace(s,"$name",pname,DOH_REPLACE_ANY); */ 1172 1173 Delete(locals); 1174 Delete(mtype); 1175 return s; 1176} 1177 1178/* ----------------------------------------------------------------------------- 1179 * Swig_typemap_lookup_new() 1180 * 1181 * Attach one or more typemaps to a node 1182 * op - typemap name, eg "out", "newfree" 1183 * node - the node to attach the typemaps to 1184 * lname - 1185 * f - 1186 * ----------------------------------------------------------------------------- */ 1187 1188String *Swig_typemap_lookup_new(const String_or_char *op, Node *node, const String_or_char *lname, Wrapper *f) 1189{ 1190 SwigType *type; 1191 SwigType *mtype = 0; 1192 String *pname; 1193 Hash *tm = 0; 1194 String *s = 0; 1195 String *sdef = 0; 1196 ParmList *locals; 1197 ParmList *kw; 1198 char temp[256]; 1199 String *symname; 1200 String *cname = 0; 1201 String *clname = 0; 1202#if 0 1203 String *qsn; 1204 Symtab *st; 1205#endif 1206 /* special case, we need to check for 'ref' call 1207 and set the default code 'sdef' */ 1208 if (Cmp(op,"newfree") == 0) { 1209 sdef = Swig_ref_call(node, lname); 1210 } 1211 1212 type = Getattr(node,"type"); 1213 if (!type) return sdef; 1214 1215 pname = Getattr(node,"name"); 1216 1217#if 0 1218 /* removed for now as it breaks old code and introduces 1219 inconsistencies and adds about 25% to the execution time of the 1220 test-suite - WSF This is my plan to fix this longer term: The 1221 following debug shows that some typemap lookups use fully qualified 1222 names and some do not. 1223 1224Printf(stdout, "Swig_typemap_lookup %s [%s %s]\n", op, type, pname ? pname : "NONAME"); 1225 1226 So even the current typemap lookups are inconsistent. The "name" 1227 attribute is often changed, particularly in lang.cxx. I hope to 1228 either remove this name changing to fix this or introduce a new 1229 attribute to use for the name. Possibly introduce a new attribute 1230 called fqname - fully qualified name, that holds the name to use for 1231 the Swig_typemap_search. If this typemap search fails then use the 1232 unqualified name. Need to check non-simple return types, eg 1233 pointers/references. 1234 */ 1235 st = Getattr(node,"sym:symtab"); 1236 qsn = st ? Swig_symbol_qualifiedscopename(st) : 0; 1237 if (qsn && Len(qsn)) { 1238 /* look qualified names first, such as 1239 1240 int *Foo::foo(int bar) -> Foo::foo 1241 */ 1242 String *qname = NewStringf("%s::%s",qsn,pname); 1243 tm = Swig_typemap_search(op,type,qname,&mtype); 1244 Delete(qname); 1245 } 1246 Delete(qsn); 1247 1248 /* look now for simple name, such as 1249 int *Foo::foo(int bar) -> foo 1250 */ 1251 if (!tm) 1252#endif 1253 tm = Swig_typemap_search(op,type,pname,&mtype); 1254 if (!tm) return sdef; 1255 1256 s = Getattr(tm,"code"); 1257 if (!s) return sdef; 1258 1259 /* Empty typemap. No match */ 1260 if (Cmp(s,"pass") == 0) return sdef; 1261 1262 s = Copy(s); /* Make a local copy of the typemap code */ 1263 1264 locals = Getattr(tm,"locals"); 1265 if (locals) locals = CopyParmList(locals); 1266 1267 if (pname) { 1268 if (SwigType_istemplate(pname)) { 1269 cname = SwigType_namestr(pname); 1270 pname = cname; 1271 } 1272 } 1273 if (SwigType_istemplate((char*)lname)) { 1274 clname = SwigType_namestr((char *)lname); 1275 lname = clname; 1276 } 1277 1278 if (mtype && SwigType_isarray(mtype)) { 1279 typemap_replace_vars(s,locals,mtype,type,pname,(char *) lname,1); 1280 } else { 1281 typemap_replace_vars(s,locals,type,type,pname,(char *) lname,1); 1282 } 1283 1284 if (locals && f) { 1285 typemap_locals(s,locals,f,-1); 1286 } 1287 replace_embedded_typemap(s); 1288 /* { 1289 String *tmname = Getattr(tm,"typemap"); 1290 if (tmname) Replace(s,"$typemap",tmname, DOH_REPLACE_ANY); 1291 }*/ 1292 1293 Replace(s,"$name",pname,DOH_REPLACE_ANY); 1294 1295 symname = Getattr(node,"sym:name"); 1296 if (symname) { 1297 Replace(s,"$symname",symname, DOH_REPLACE_ANY); 1298 } 1299 1300 Setattr(node,tmop_name(op),s); 1301 if (locals) { 1302 sprintf(temp,"%s:locals", Char(op)); 1303 Setattr(node,tmop_name(temp), locals); 1304 Delete(locals); 1305 } 1306 1307 if (checkAttribute(tm,"type","SWIGTYPE")) { 1308 sprintf(temp,"%s:SWIGTYPE", Char(op)); 1309 Setattr(node,tmop_name(temp),"1"); 1310 } 1311 1312 /* Attach kwargs */ 1313 kw = Getattr(tm,"kwargs"); 1314 while (kw) { 1315 String *value = Copy(Getattr(kw,"value")); 1316 String *type = Getattr(kw,"type"); 1317 if (type) { 1318 SwigType *rtype = SwigType_typedef_resolve_all(type); 1319 String *mangle = Swig_string_mangle(rtype); 1320 Printf(value,"%s",mangle); 1321 Delete(mangle); 1322 Delete(rtype); 1323 } 1324 sprintf(temp,"%s:%s",Char(op),Char(Getattr(kw,"name"))); 1325 Setattr(node,tmop_name(temp), value); 1326 kw = nextSibling(kw); 1327 } 1328 1329 /* Look for warnings */ 1330 { 1331 String *w; 1332 sprintf(temp,"%s:warning", Char(op)); 1333 w = Getattr(node,tmop_name(temp)); 1334 if (w) { 1335 Swig_warning(0,Getfile(node),Getline(node),"%s\n", w); 1336 } 1337 } 1338 1339 /* Look for code fragments */ 1340 { 1341 String *f; 1342 sprintf(temp,"%s:fragment", Char(op)); 1343 f = Getattr(node,tmop_name(temp)); 1344 if (f) { 1345 Swig_fragment_emit(f); 1346 } 1347 } 1348 1349 if (cname) Delete(cname); 1350 if (clname) Delete(clname); 1351 if (mtype) Delete(mtype); 1352 if (sdef) { /* put 'ref' and 'newfree' codes together */ 1353 String *p = NewStringf("%s\n%s", sdef, s); 1354 Delete(s); 1355 Delete(sdef); 1356 s = p; 1357 } 1358 return s; 1359} 1360 1361/* ----------------------------------------------------------------------------- 1362 * Swig_typemap_attach_kwargs() 1363 * 1364 * If this hash (tm) contains a linked list of parameters under its "kwargs" 1365 * attribute, add keys for each of those named keyword arguments to this 1366 * parameter for later use. 1367 * For example, attach the typemap attributes to p: 1368 * %typemap(in, foo="xyz") ... 1369 * A new attribute called "tmap:in:foo" with value "xyz" is attached to p. 1370 * ----------------------------------------------------------------------------- */ 1371 1372void 1373Swig_typemap_attach_kwargs(Hash *tm, const String_or_char *op, Parm *p) { 1374 String *temp = NewString(""); 1375 Parm *kw = Getattr(tm,"kwargs"); 1376 while (kw) { 1377 String *value = Copy(Getattr(kw,"value")); 1378 String *type = Getattr(kw,"type"); 1379 if (type) { 1380 Hash *v = NewHash(); 1381 Setattr(v,"value",value); 1382 Setattr(v,"type",type); 1383 value = v; 1384 } 1385 Clear(temp); 1386 Printf(temp,"%s:%s",op,Getattr(kw,"name")); 1387 Setattr(p,tmop_name(temp),value); 1388 kw = nextSibling(kw); 1389 } 1390 Delete(temp); 1391} 1392 1393/* ----------------------------------------------------------------------------- 1394 * Swig_typemap_warn() 1395 * 1396 * If any warning message is attached to this parameter's "tmap:op:warning" 1397 * attribute, print that warning message. 1398 * ----------------------------------------------------------------------------- */ 1399 1400static void 1401Swig_typemap_warn(const String_or_char *op, Parm *p) { 1402 String *temp = NewStringf("%s:warning",op); 1403 String *w = Getattr(p,tmop_name(temp)); 1404 Delete(temp); 1405 if (w) { 1406 Swig_warning(0,Getfile(p),Getline(p),"%s\n",w); 1407 } 1408} 1409 1410static void 1411Swig_typemap_emit_code_fragments(const String_or_char *op, Parm *p) { 1412 String *temp = NewStringf("%s:fragment",op); 1413 String *f = Getattr(p,tmop_name(temp)); 1414 if (f) { 1415 Swig_fragment_emit(f); 1416 } 1417 Delete(temp); 1418} 1419 1420/* ----------------------------------------------------------------------------- 1421 * Swig_typemap_attach_parms() 1422 * 1423 * Given a parameter list, this function attaches all of the typemaps for a 1424 * given typemap type 1425 * ----------------------------------------------------------------------------- */ 1426 1427void 1428Swig_typemap_attach_parms(const String_or_char *op, ParmList *parms, Wrapper *f) { 1429 Parm *p, *firstp; 1430 Hash *tm; 1431 int nmatch = 0; 1432 int i; 1433 String *s; 1434 ParmList *locals; 1435 int argnum = 0; 1436 char temp[256]; 1437 1438 p = parms; 1439 while (p) { 1440 argnum++; 1441 nmatch = 0; 1442 tm = Swig_typemap_search_multi(op,p,&nmatch); 1443 if (!tm) { 1444 p = nextSibling(p); 1445 continue; 1446 } 1447 s = Getattr(tm,"code"); 1448 if (!s) { 1449 p = nextSibling(p); 1450 continue; 1451 } 1452 1453 /* Empty typemap. No match */ 1454 if (Cmp(s,"pass") == 0) { 1455 p = nextSibling(p); 1456 continue; 1457 } 1458 1459 s = Copy(s); 1460 locals = Getattr(tm,"locals"); 1461 if (locals) locals = CopyParmList(locals); 1462 firstp = p; 1463 for (i = 0; i < nmatch; i++) { 1464 SwigType *type; 1465 String *pname; 1466 String *lname; 1467 SwigType *mtype; 1468 1469 type = Getattr(p,"type"); 1470 pname = Getattr(p,"name"); 1471 lname = Getattr(p,"lname"); 1472 mtype = Getattr(p,"tmap:match"); 1473 1474 if (mtype) { 1475 typemap_replace_vars(s,locals,mtype,type,pname,lname,i+1); 1476 Delattr(p,"tmap:match"); 1477 } else { 1478 typemap_replace_vars(s,locals,type,type,pname,lname,i+1); 1479 } 1480 1481 if (checkAttribute(tm,"type","SWIGTYPE")) { 1482 sprintf(temp,"%s:SWIGTYPE", Char(op)); 1483 Setattr(p,tmop_name(temp),"1"); 1484 } 1485 p = nextSibling(p); 1486 } 1487 1488 if (locals && f) { 1489 typemap_locals(s,locals,f,argnum); 1490 } 1491 1492 replace_embedded_typemap(s); 1493 1494 /* Replace the argument number */ 1495 sprintf(temp,"%d",argnum); 1496 Replace(s,"$argnum",temp, DOH_REPLACE_ANY); 1497 1498 /* Attach attributes to object */ 1499 Setattr(firstp,tmop_name(op),s); /* Code object */ 1500 1501 if (locals) { 1502 sprintf(temp,"%s:locals", Char(op)); 1503 Setattr(firstp,tmop_name(temp), locals); 1504 Delete(locals); 1505 } 1506 1507 /* Attach a link to the next parameter. Needed for multimaps */ 1508 sprintf(temp,"%s:next",Char(op)); 1509 Setattr(firstp,tmop_name(temp),p); 1510 1511 /* Attach kwargs */ 1512 Swig_typemap_attach_kwargs(tm,op,firstp); 1513 1514 /* Print warnings, if any */ 1515 Swig_typemap_warn(op,firstp); 1516 1517 /* Look for code fragments */ 1518 Swig_typemap_emit_code_fragments(op,firstp); 1519 1520 /* increase argnum to consider numinputs */ 1521 argnum += nmatch - 1; 1522 } 1523} 1524 1525/* ----------------------------------------------------------------------------- 1526 * split_embedded() 1527 * 1528 * This function replaces the special variable $typemap(....) with typemap 1529 * code. The general form of $typemap is as follows: 1530 * 1531 * $TYPEMAP(method, $var1=value, $var2=value, $var3=value,...) 1532 * 1533 * For example: 1534 * 1535 * $TYPEMAP(in, $1=int x, $input=y, ...) 1536 * 1537 * Note: this was added as an experiment and could be removed 1538 * ----------------------------------------------------------------------------- */ 1539 1540/* Splits the arguments of an embedded typemap */ 1541static List *split_embedded(String *s) { 1542 List *args = 0; 1543 char *c,*start; 1544 int level=0; 1545 int leading = 1; 1546 args = NewList(); 1547 1548 c = Strstr(s,"("); 1549 c++; 1550 1551 start = c; 1552 while (*c) { 1553 if (*c == '\"') { 1554 c++; 1555 while (*c) { 1556 if (*c == '\\') { 1557 c++; 1558 } else { 1559 if (*c == '\"') break; 1560 } 1561 c++; 1562 } 1563 } 1564 if ((level == 0) && ((*c == ',') || (*c == ')'))) { 1565 String *tmp = NewStringWithSize(start,c-start); 1566 Append(args,tmp); 1567 Delete(tmp); 1568 start = c+1; 1569 leading = 1; 1570 if (*c == ')') break; 1571 c++; 1572 continue; 1573 } 1574 if (*c == '(') level++; 1575 if (*c == ')') level--; 1576 if (isspace((int)*c) && leading) start++; 1577 if (!isspace((int)*c)) leading = 0; 1578 c++; 1579 } 1580 return args; 1581} 1582 1583static void split_var(String *s, String **name, String **value) { 1584 char *eq; 1585 char *c; 1586 1587 eq = Strstr(s,"="); 1588 if (!eq) { 1589 *name = 0; 1590 *value = 0; 1591 return; 1592 } 1593 c = Char(s); 1594 *name = NewStringWithSize(c,eq-c); 1595 1596 /* Look for $n variables */ 1597 if (isdigit((int)*(c))) { 1598 /* Parse the value as a type */ 1599 String *v; 1600 Parm *p; 1601 v = NewString(eq+1); 1602 p = Swig_cparse_parm(v); 1603 Delete(v); 1604 *value = p; 1605 } else { 1606 *value = NewString(eq+1); 1607 } 1608} 1609 1610static void replace_embedded_typemap(String *s) { 1611 while (Strstr(s,"$TYPEMAP(")) { 1612 1613 /* Gather the argument */ 1614 char *start, *end=0,*c; 1615 int level = 0; 1616 String *tmp; 1617 start = Strstr(s,"$TYPEMAP("); 1618 c = start; 1619 while (*c) { 1620 if (*c == '(') level++; 1621 if (*c == ')') { 1622 level--; 1623 if (level == 0) { 1624 end = c+1; 1625 break; 1626 } 1627 } 1628 c++; 1629 } 1630 if (end) { 1631 tmp = NewStringWithSize(start,(end-start)); 1632 } else { 1633 tmp = 0; 1634 } 1635 1636 /* Got a substitution. Split it apart into pieces */ 1637 if (tmp) { 1638 List *l; 1639 Hash *vars; 1640 String *method; 1641 int i; 1642 1643 l = split_embedded(tmp); 1644 vars = NewHash(); 1645 for (i = 1; i < Len(l); i++) { 1646 String *n, *v; 1647 split_var(Getitem(l,i),&n,&v); 1648 if (n && v) { 1649 Insert(n,0,"$"); 1650 Setattr(vars,n,v); 1651 } 1652 } 1653 1654 method = Getitem(l,0); 1655 /* Generate the parameter list for matching typemaps */ 1656 1657 { 1658 Parm *p = 0; 1659 Parm *first = 0; 1660 char temp[32]; 1661 int n = 1; 1662 while (1) { 1663 Hash *v; 1664 sprintf(temp,"$%d",n); 1665 v = Getattr(vars,temp); 1666 if (v) { 1667 if (p) { 1668 set_nextSibling(p,v); 1669 set_previousSibling(v,p); 1670 } 1671 p = v; 1672 Setattr(p,"lname",Getattr(p,"name")); 1673 if (Getattr(p,"value")) { 1674 Setattr(p,"name",Getattr(p,"value")); 1675 } 1676 if (!first) first = p; 1677 DohIncref(p); 1678 Delattr(vars,temp); 1679 } else { 1680 break; 1681 } 1682 n++; 1683 } 1684 /* Perform a typemap search */ 1685 if (first) { 1686 Swig_typemap_attach_parms(method,first,0); 1687 { 1688 String *tm; 1689 int match = 0; 1690 char attr[64]; 1691 sprintf(attr,"tmap:%s",Char(method)); 1692 1693 /* Look for the typemap code */ 1694 tm = Getattr(first,attr); 1695 if (tm) { 1696 sprintf(attr,"tmap:%s:next",Char(method)); 1697 if (!Getattr(first,attr)) { 1698 /* Should be no more matches. Hack??? */ 1699 /* Replace all of the remaining variables */ 1700 Iterator ki; 1701 for (ki = First(vars); ki.key; ki = Next(ki)) { 1702 Replace(tm,ki.key,ki.item, DOH_REPLACE_ANY); 1703 } 1704 /* Do the replacement */ 1705 Replace(s,tmp,tm, DOH_REPLACE_ANY); 1706 Delete(tm); 1707 match = 1; 1708 } 1709 } 1710 if (!match) { 1711 Swig_error(Getfile(s),Getline(s),"No typemap found for %s\n", tmp); 1712 } 1713 } 1714 } 1715 } 1716 Replace(s,tmp,"<embedded typemap>", DOH_REPLACE_ANY); 1717 Delete(vars); 1718 Delete(tmp); 1719 Delete(l); 1720 } 1721 } 1722} 1723 1724/* ----------------------------------------------------------------------------- 1725 * Swig_typemap_debug() 1726 * ----------------------------------------------------------------------------- */ 1727 1728void Swig_typemap_debug() { 1729 int ts; 1730 Printf(stdout,"---[ typemaps ]--------------------------------------------------------------\n"); 1731 1732 ts = tm_scope; 1733 while (ts >= 0) { 1734 Printf(stdout,"::: scope %d\n\n",ts); 1735 Printf(stdout,"%s\n", typemaps[ts]); 1736 ts--; 1737 } 1738 Printf(stdout,"-----------------------------------------------------------------------------\n"); 1739} 1740 1741