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 * ruby.cxx 6 * 7 * Ruby language module for SWIG. 8 * ----------------------------------------------------------------------------- */ 9 10char cvsroot_ruby_cxx[] = "$Id: ruby.cxx 11246 2009-06-05 17:19:29Z wsfulton $"; 11 12#include "swigmod.h" 13#include "cparse.h" 14static int treduce = SWIG_cparse_template_reduce(0); 15 16#define SWIG_PROTECTED_TARGET_METHODS 1 17 18#include <ctype.h> 19#include <string.h> 20#include <limits.h> /* for INT_MAX */ 21 22class RClass { 23private: 24 String *temp; 25 26public: 27 String *name; /* class name (renamed) */ 28 String *cname; /* original C class/struct name */ 29 String *mname; /* Mangled name */ 30 31 /** 32 * The C variable name used in the SWIG-generated wrapper code to refer to 33 * this class; usually it is of the form "SwigClassXXX.klass", where SwigClassXXX 34 * is a swig_class struct instance and klass is a member of that struct. 35 */ 36 String *vname; 37 38 /** 39 * The C variable name used in the SWIG-generated wrapper code to refer to 40 * the module that implements this class's methods (when we're trying to 41 * support C++ multiple inheritance). Usually it is of the form 42 * "SwigClassClassName.mImpl", where SwigClassXXX is a swig_class struct instance 43 * and mImpl is a member of that struct. 44 */ 45 String *mImpl; 46 47 String *type; 48 String *prefix; 49 String *init; 50 51 52 int constructor_defined; 53 int destructor_defined; 54 55 RClass() { 56 temp = NewString(""); 57 name = NewString(""); 58 cname = NewString(""); 59 mname = NewString(""); 60 vname = NewString(""); 61 mImpl = NewString(""); 62 type = NewString(""); 63 prefix = NewString(""); 64 init = NewString(""); 65 constructor_defined = 0; 66 destructor_defined = 0; 67 } 68 69 ~RClass() { 70 Delete(name); 71 Delete(cname); 72 Delete(vname); 73 Delete(mImpl); 74 Delete(mname); 75 Delete(type); 76 Delete(prefix); 77 Delete(init); 78 Delete(temp); 79 } 80 81 void set_name(const_String_or_char_ptr cn, const_String_or_char_ptr rn, const_String_or_char_ptr valn) { 82 /* Original C/C++ class (or struct) name */ 83 Clear(cname); 84 Append(cname, cn); 85 86 /* Mangled name */ 87 Delete(mname); 88 mname = Swig_name_mangle(cname); 89 90 /* Renamed class name */ 91 Clear(name); 92 Append(name, valn); 93 94 /* Variable name for the VALUE that refers to the Ruby Class object */ 95 Clear(vname); 96 Printf(vname, "SwigClass%s.klass", name); 97 98 /* Variable name for the VALUE that refers to the Ruby Class object */ 99 Clear(mImpl); 100 Printf(mImpl, "SwigClass%s.mImpl", name); 101 102 /* Prefix */ 103 Clear(prefix); 104 Printv(prefix, (rn ? rn : cn), "_", NIL); 105 } 106 107 char *strip(const_String_or_char_ptr s) { 108 Clear(temp); 109 Append(temp, s); 110 if (Strncmp(s, prefix, Len(prefix)) == 0) { 111 Replaceall(temp, prefix, ""); 112 } 113 return Char(temp); 114 } 115}; 116 117 118/* flags for the make_autodoc function */ 119enum autodoc_t { 120 AUTODOC_CLASS, 121 AUTODOC_CTOR, 122 AUTODOC_DTOR, 123 AUTODOC_STATICFUNC, 124 AUTODOC_FUNC, 125 AUTODOC_METHOD, 126 AUTODOC_GETTER, 127 AUTODOC_SETTER 128}; 129 130static const char *usage = "\ 131Ruby Options (available with -ruby)\n\ 132 -globalmodule - Wrap everything into the global module\n\ 133 -minherit - Attempt to support multiple inheritance\n\ 134 -nocppcast - Disable C++ casting operators, useful for generating bugs\n\ 135 -cppcast - Enable C++ casting operators (default)\n\ 136 -autorename - Enable renaming of classes and methods to follow Ruby coding standards\n\ 137 -noautorename - Disable renaming of classes and methods (default)\n\ 138 -prefix <name> - Set a prefix <name> to be prepended to all names\n\ 139 -initname <name> - Set entry function to Init_<name> (used by `require')\n"; 140 141 142#define RCLASS(hash, name) (RClass*)(Getattr(hash, name) ? Data(Getattr(hash, name)) : 0) 143#define SET_RCLASS(hash, name, klass) Setattr(hash, name, NewVoid(klass, 0)) 144 145 146class RUBY:public Language { 147private: 148 149 String *module; 150 String *modvar; 151 String *feature; 152 String *prefix; 153 int current; 154 Hash *classes; /* key=cname val=RClass */ 155 RClass *klass; /* Currently processing class */ 156 Hash *special_methods; /* Python style special method name table */ 157 158 File *f_directors; 159 File *f_directors_h; 160 File *f_directors_helpers; 161 File *f_begin; 162 File *f_runtime; 163 File *f_runtime_h; 164 File *f_header; 165 File *f_wrappers; 166 File *f_init; 167 File *f_initbeforefunc; 168 169 bool useGlobalModule; 170 bool multipleInheritance; 171 172 // Wrap modes 173 enum WrapperMode { 174 NO_CPP, 175 MEMBER_FUNC, 176 CONSTRUCTOR_ALLOCATE, 177 CONSTRUCTOR_INITIALIZE, 178 DESTRUCTOR, 179 MEMBER_VAR, 180 CLASS_CONST, 181 STATIC_FUNC, 182 STATIC_VAR 183 }; 184 185 /* ------------------------------------------------------------ 186 * autodoc level declarations 187 * ------------------------------------------------------------ */ 188 189 enum autodoc_l { 190 NO_AUTODOC = -2, // no autodoc 191 STRING_AUTODOC = -1, // use provided string 192 NAMES_AUTODOC = 0, // only parameter names 193 TYPES_AUTODOC = 1, // parameter names and types 194 EXTEND_AUTODOC = 2, // extended documentation and parameter names 195 EXTEND_TYPES_AUTODOC = 3 // extended documentation and parameter types + names 196 }; 197 198 autodoc_t last_mode; 199 String* last_autodoc; 200 201 202 203 autodoc_l autodoc_level(String *autodoc) { 204 autodoc_l dlevel = NO_AUTODOC; 205 if (autodoc) { 206 char *c = Char(autodoc); 207 if (c && isdigit(c[0])) { 208 dlevel = (autodoc_l) atoi(c); 209 } else { 210 if (strcmp(c, "extended") == 0) { 211 dlevel = EXTEND_AUTODOC; 212 } else { 213 dlevel = STRING_AUTODOC; 214 } 215 } 216 } 217 return dlevel; 218 } 219 220 221 222 /* ------------------------------------------------------------ 223 * have_docstring() 224 * Check if there is a docstring directive and it has text, 225 * or there is an autodoc flag set 226 * ------------------------------------------------------------ */ 227 228 bool have_docstring(Node *n) { 229 String *str = Getattr(n, "feature:docstring"); 230 return (str != NULL && Len(str) > 0) || (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc")); 231 } 232 233 /* ------------------------------------------------------------ 234 * docstring() 235 * Get the docstring text, stripping off {} if neccessary, 236 * and enclose in triple double quotes. If autodoc is also 237 * set then it will build a combined docstring. 238 * ------------------------------------------------------------ */ 239 240 String *docstring(Node *n, autodoc_t ad_type) { 241 242 String *str = Getattr(n, "feature:docstring"); 243 bool have_ds = (str != NULL && Len(str) > 0); 244 bool have_auto = (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc")); 245 String *autodoc = NULL; 246 String *doc = NULL; 247 248 if (have_ds) { 249 char *t = Char(str); 250 if (*t == '{') { 251 Delitem(str, 0); 252 Delitem(str, DOH_END); 253 } 254 } 255 256 if (have_auto) { 257 autodoc = make_autodoc(n, ad_type); 258 have_auto = (autodoc != NULL && Len(autodoc) > 0); 259 } 260 // If there is more than one line then make docstrings like this: 261 // 262 // This is line1 263 // And here is line2 followed by the rest of them 264 // 265 // otherwise, put it all on a single line 266 // 267 if (have_auto && have_ds) { // Both autodoc and docstring are present 268 doc = NewString(""); 269 Printv(doc, "\n", autodoc, "\n", str, NIL); 270 } else if (!have_auto && have_ds) { // only docstring 271 if (Strchr(str, '\n') == NULL) { 272 doc = NewString(str); 273 } else { 274 doc = NewString(""); 275 Printv(doc, str, NIL); 276 } 277 } else if (have_auto && !have_ds) { // only autodoc 278 if (Strchr(autodoc, '\n') == NULL) { 279 doc = NewStringf("%s", autodoc); 280 } else { 281 doc = NewString(""); 282 Printv(doc, "\n", autodoc, NIL); 283 } 284 } else 285 doc = NewString(""); 286 287 // Save the generated strings in the parse tree in case they are used later 288 // by post processing tools 289 Setattr(n, "ruby:docstring", doc); 290 Setattr(n, "ruby:autodoc", autodoc); 291 return doc; 292 } 293 294 /* ------------------------------------------------------------ 295 * make_autodocParmList() 296 * Generate the documentation for the function parameters 297 * ------------------------------------------------------------ */ 298 299 String *make_autodocParmList(Node *n, bool showTypes) { 300 String *doc = NewString(""); 301 String *pdocs = Copy(Getattr(n, "feature:pdocs")); 302 ParmList *plist = CopyParmList(Getattr(n, "parms")); 303 Parm *p; 304 Parm *pnext; 305 Node *lookup; 306 int lines = 0; 307 const int maxwidth = 50; 308 309 if (pdocs) 310 Append(pdocs, ".\n"); 311 312 313 Swig_typemap_attach_parms("in", plist, 0); 314 Swig_typemap_attach_parms("doc", plist, 0); 315 316 for (p = plist; p; p = pnext) { 317 String *name = 0; 318 String *type = 0; 319 String *value = 0; 320 String *ptype = 0; 321 String *pdoc = Getattr(p, "tmap:doc"); 322 if (pdoc) { 323 name = Getattr(p, "tmap:doc:name"); 324 type = Getattr(p, "tmap:doc:type"); 325 value = Getattr(p, "tmap:doc:value"); 326 ptype = Getattr(p, "tmap:doc:pytype"); 327 } 328 329 name = name ? name : Getattr(p, "name"); 330 type = type ? type : Getattr(p, "type"); 331 value = value ? value : Getattr(p, "value"); 332 333 334 String *tm = Getattr(p, "tmap:in"); 335 if (tm) { 336 pnext = Getattr(p, "tmap:in:next"); 337 } else { 338 pnext = nextSibling(p); 339 } 340 341 // Skip ignored input attributes 342 if (checkAttribute(p, "tmap:in:numinputs", "0")) 343 continue; 344 345 // Skip the 'self' parameter which in ruby is implicit 346 if ( Cmp(name, "self") == 0 ) 347 continue; 348 349 // Make __p parameters just p (as used in STL) 350 Replace( name, "__", "", DOH_REPLACE_FIRST ); 351 352 if (Len(doc)) { 353 // add a comma to the previous one if any 354 Append(doc, ", "); 355 356 // Do we need to wrap a long line? 357 if ((Len(doc) - lines * maxwidth) > maxwidth) { 358 Printf(doc, "\n%s", tab4); 359 lines += 1; 360 } 361 } 362 // Do the param type too? 363 if (showTypes) { 364 type = SwigType_base(type); 365 lookup = Swig_symbol_clookup(type, 0); 366 if (lookup) 367 type = Getattr(lookup, "sym:name"); 368 Printf(doc, "%s ", type); 369 } 370 371 if (name) { 372 Append(doc, name); 373 if (pdoc) { 374 if (!pdocs) 375 pdocs = NewString("Parameters:\n"); 376 Printf(pdocs, " %s.\n", pdoc); 377 } 378 } else { 379 Append(doc, "?"); 380 } 381 382 if (value) { 383 if (Strcmp(value, "NULL") == 0) 384 value = NewString("nil"); 385 else if (Strcmp(value, "true") == 0 || Strcmp(value, "TRUE") == 0) 386 value = NewString("true"); 387 else if (Strcmp(value, "false") == 0 || Strcmp(value, "FALSE") == 0) 388 value = NewString("false"); 389 else { 390 lookup = Swig_symbol_clookup(value, 0); 391 if (lookup) 392 value = Getattr(lookup, "sym:name"); 393 } 394 Printf(doc, "=%s", value); 395 } 396 } 397 if (pdocs) 398 Setattr(n, "feature:pdocs", pdocs); 399 Delete(plist); 400 return doc; 401 } 402 403 /* ------------------------------------------------------------ 404 * make_autodoc() 405 * Build a docstring for the node, using parameter and other 406 * info in the parse tree. If the value of the autodoc 407 * attribute is "0" then do not include parameter types, if 408 * it is "1" (the default) then do. If it has some other 409 * value then assume it is supplied by the extension writer 410 * and use it directly. 411 * ------------------------------------------------------------ */ 412 413 String *make_autodoc(Node *n, autodoc_t ad_type) { 414 int extended = 0; 415 // If the function is overloaded then this funciton is called 416 // for the last one. Rewind to the first so the docstrings are 417 // in order. 418 while (Getattr(n, "sym:previousSibling")) 419 n = Getattr(n, "sym:previousSibling"); 420 421 Node *pn = Swig_methodclass(n); 422 String* super_names = NewString(""); 423 String* class_name = Getattr(pn, "sym:name") ; 424 425 if ( !class_name ) class_name = NewString(""); 426 else 427 { 428 class_name = Copy(class_name); 429 List *baselist = Getattr(pn, "bases"); 430 if (baselist && Len(baselist)) { 431 Iterator base = First(baselist); 432 while (base.item && GetFlag(base.item, "feature:ignore")) { 433 base = Next(base); 434 } 435 436 int count = 0; 437 for ( ;base.item; ++count) { 438 if ( count ) Append(super_names, ", "); 439 String *basename = Getattr(base.item, "sym:name"); 440 441 String* basenamestr = NewString(basename); 442 Node* parent = parentNode(base.item); 443 while (parent) 444 { 445 String *parent_name = Copy( Getattr(parent, "sym:name") ); 446 if ( !parent_name ) { 447 Node* mod = Getattr(parent, "module"); 448 if ( mod ) 449 parent_name = Copy( Getattr(mod, "name") ); 450 if ( parent_name ) 451 { 452 (Char(parent_name))[0] = (char)toupper((Char(parent_name))[0]); 453 } 454 } 455 if ( parent_name ) 456 { 457 Insert(basenamestr, 0, "::"); 458 Insert(basenamestr, 0, parent_name); 459 Delete(parent_name); 460 } 461 parent = parentNode(parent); 462 } 463 464 Append(super_names, basenamestr ); 465 Delete(basenamestr); 466 base = Next(base); 467 } 468 } 469 } 470 String* full_name; 471 if ( module ) { 472 full_name = NewString(module); 473 if (class_name && Len(class_name) > 0) Append(full_name, "::"); 474 } 475 else 476 full_name = NewString(""); 477 Append(full_name, class_name); 478 479 String* symname = Getattr(n, "sym:name"); 480 if ( Getattr( special_methods, symname ) ) 481 symname = Getattr( special_methods, symname ); 482 483 String* methodName = NewString(full_name); 484 Append(methodName, symname); 485 486 487 // Each overloaded function will try to get documented, 488 // so we keep the name of the last overloaded function and its type. 489 // Documenting just from functionWrapper() is not possible as 490 // sym:name has already been changed to include the class name 491 if ( last_mode == ad_type && Cmp(methodName, last_autodoc) == 0 ) { 492 Delete(full_name); 493 Delete(class_name); 494 Delete(super_names); 495 Delete(methodName); 496 return NewString(""); 497 } 498 499 500 last_mode = ad_type; 501 last_autodoc = Copy(methodName); 502 503 String *doc = NewString("/*\n"); 504 int counter = 0; 505 bool skipAuto = false; 506 Node* on = n; 507 for ( ; n; ++counter ) { 508 skipAuto = false; 509 bool showTypes = false; 510 String *autodoc = Getattr(n, "feature:autodoc"); 511 autodoc_l dlevel = autodoc_level(autodoc); 512 switch (dlevel) { 513 case NO_AUTODOC: 514 break; 515 case NAMES_AUTODOC: 516 showTypes = false; 517 break; 518 case TYPES_AUTODOC: 519 showTypes = true; 520 break; 521 case EXTEND_AUTODOC: 522 extended = 1; 523 showTypes = false; 524 break; 525 case EXTEND_TYPES_AUTODOC: 526 extended = 1; 527 showTypes = true; 528 break; 529 case STRING_AUTODOC: 530 skipAuto = true; 531 break; 532 } 533 534 SwigType *type = Getattr(n, "type"); 535 536 if (type) { 537 if (Strcmp(type, "void") == 0) 538 type = NULL; 539 else { 540 SwigType *qt = SwigType_typedef_resolve_all(type); 541 if (SwigType_isenum(qt)) 542 type = NewString("int"); 543 else { 544 type = SwigType_base(type); 545 Node *lookup = Swig_symbol_clookup(type, 0); 546 if (lookup) 547 type = Getattr(lookup, "sym:name"); 548 } 549 } 550 } 551 552 if (counter == 0) { 553 switch (ad_type) { 554 case AUTODOC_CLASS: 555 Printf(doc, " Document-class: %s", full_name); 556 if ( Len(super_names) > 0 ) 557 Printf( doc, " < %s", super_names); 558 Append(doc, "\n\n"); 559 break; 560 case AUTODOC_CTOR: 561 Printf(doc, " Document-method: %s.new\n\n", full_name); 562 break; 563 564 case AUTODOC_DTOR: 565 break; 566 567 case AUTODOC_STATICFUNC: 568 Printf(doc, " Document-method: %s.%s\n\n", full_name, symname); 569 break; 570 571 case AUTODOC_FUNC: 572 case AUTODOC_METHOD: 573 case AUTODOC_GETTER: 574 Printf(doc, " Document-method: %s.%s\n\n", full_name, symname); 575 break; 576 case AUTODOC_SETTER: 577 Printf(doc, " Document-method: %s.%s=\n\n", full_name, symname); 578 break; 579 } 580 } 581 582 583 if (skipAuto) { 584 if ( counter == 0 ) Printf(doc, " call-seq:\n"); 585 switch( ad_type ) 586 { 587 case AUTODOC_STATICFUNC: 588 case AUTODOC_FUNC: 589 case AUTODOC_METHOD: 590 case AUTODOC_GETTER: 591 { 592 String *paramList = make_autodocParmList(n, showTypes); 593 if (Len(paramList)) 594 Printf(doc, " %s(%s)", symname, paramList); 595 else 596 Printf(doc, " %s", symname); 597 if (type) 598 Printf(doc, " -> %s", type); 599 break; 600 } 601 case AUTODOC_SETTER: 602 { 603 Printf(doc, " %s=(x)", symname); 604 if (type) Printf(doc, " -> %s", type); 605 break; 606 } 607 default: 608 break; 609 } 610 } 611 else { 612 switch (ad_type) { 613 case AUTODOC_CLASS: 614 { 615 // Only do the autodoc if there isn't a docstring for the class 616 String *str = Getattr(n, "feature:docstring"); 617 if (counter == 0 && (str == NULL || Len(str) == 0)) { 618 if (CPlusPlus) { 619 Printf(doc, " Proxy of C++ %s class", full_name); 620 } else { 621 Printf(doc, " Proxy of C %s struct", full_name); 622 } 623 } 624 } 625 break; 626 case AUTODOC_CTOR: 627 if (counter == 0) Printf(doc, " call-seq:\n"); 628 if (Strcmp(class_name, symname) == 0) { 629 String *paramList = make_autodocParmList(n, showTypes); 630 if (Len(paramList)) 631 Printf(doc, " %s.new(%s)", class_name, paramList); 632 else 633 Printf(doc, " %s.new", class_name); 634 } else 635 Printf(doc, " %s.new(%s)", class_name, 636 make_autodocParmList(n, showTypes)); 637 break; 638 639 case AUTODOC_DTOR: 640 break; 641 642 case AUTODOC_STATICFUNC: 643 case AUTODOC_FUNC: 644 case AUTODOC_METHOD: 645 case AUTODOC_GETTER: 646 { 647 if (counter == 0) Printf(doc, " call-seq:\n"); 648 String *paramList = make_autodocParmList(n, showTypes); 649 if (Len(paramList)) 650 Printf(doc, " %s(%s)", symname, paramList); 651 else 652 Printf(doc, " %s", symname); 653 if (type) 654 Printf(doc, " -> %s", type); 655 break; 656 } 657 case AUTODOC_SETTER: 658 { 659 Printf(doc, " call-seq:\n"); 660 Printf(doc, " %s=(x)", symname); 661 if (type) Printf(doc, " -> %s", type); 662 break; 663 } 664 } 665 } 666 667 // if it's overloaded then get the next decl and loop around again 668 n = Getattr(n, "sym:nextSibling"); 669 if (n) 670 Append(doc, "\n"); 671 } 672 673 Printf(doc, "\n\n"); 674 if (!skipAuto) { 675 switch (ad_type) { 676 case AUTODOC_CLASS: 677 case AUTODOC_DTOR: 678 break; 679 case AUTODOC_CTOR: 680 Printf(doc, "Class constructor.\n"); 681 break; 682 case AUTODOC_STATICFUNC: 683 Printf(doc, "A class method.\n"); 684 break; 685 case AUTODOC_FUNC: 686 Printf(doc, "A module function.\n"); 687 break; 688 case AUTODOC_METHOD: 689 Printf(doc, "An instance method.\n"); 690 break; 691 case AUTODOC_GETTER: 692 Printf(doc, "Get value of attribute.\n"); 693 break; 694 case AUTODOC_SETTER: 695 Printf(doc, "Set new value for attribute.\n"); 696 break; 697 } 698 } 699 700 701 n = on; 702 while ( n ) { 703 String *autodoc = Getattr(n, "feature:autodoc"); 704 autodoc_l dlevel = autodoc_level(autodoc); 705 706 symname = Getattr(n, "sym:name"); 707 if ( Getattr( special_methods, symname ) ) 708 symname = Getattr( special_methods, symname ); 709 710 switch (dlevel) { 711 case NO_AUTODOC: 712 case NAMES_AUTODOC: 713 case TYPES_AUTODOC: 714 extended = 0; 715 break; 716 case STRING_AUTODOC: 717 extended = 2; 718 Replaceall( autodoc, "$class", class_name ); 719 Printv(doc, autodoc, ".", NIL); 720 break; 721 case EXTEND_AUTODOC: 722 case EXTEND_TYPES_AUTODOC: 723 extended = 1; 724 break; 725 } 726 727 728 if (extended) { 729 String *pdocs = Getattr(n, "feature:pdocs"); 730 if (pdocs) { 731 Printv(doc, "\n\n", pdocs, NULL); 732 break; 733 } 734 if ( extended == 2 ) break; 735 } 736 n = Getattr(n, "sym:nextSibling"); 737 } 738 739 Append(doc, "\n*/\n"); 740 Delete(full_name); 741 Delete(class_name); 742 Delete(super_names); 743 Delete(methodName); 744 745 return doc; 746 } 747 748public: 749 750 /* --------------------------------------------------------------------- 751 * RUBY() 752 * 753 * Initialize member data 754 * --------------------------------------------------------------------- */ 755 756 RUBY() { 757 module = 0; 758 modvar = 0; 759 feature = 0; 760 prefix = 0; 761 last_autodoc = NewString(""); 762 current = NO_CPP; 763 classes = 0; 764 klass = 0; 765 special_methods = 0; 766 f_begin = 0; 767 f_runtime = 0; 768 f_header = 0; 769 f_wrappers = 0; 770 f_init = 0; 771 f_initbeforefunc = 0; 772 useGlobalModule = false; 773 multipleInheritance = false; 774 director_prot_ctor_code = NewString(""); 775 Printv(director_prot_ctor_code, 776 "if ( $comparison ) { /* subclassed */\n", 777 " $director_new \n", 778 "} else {\n", " rb_raise(rb_eRuntimeError,\"accessing abstract class or protected constructor\"); \n", " return Qnil;\n", "}\n", NIL); 779 director_multiple_inheritance = 0; 780 director_language = 1; 781 } 782 783 /* --------------------------------------------------------------------- 784 * main() 785 * 786 * Parse command line options and initializes variables. 787 * --------------------------------------------------------------------- */ 788 789 virtual void main(int argc, char *argv[]) { 790 791 int cppcast = 1; 792 int autorename = 0; 793 794 /* Set location of SWIG library */ 795 SWIG_library_directory("ruby"); 796 797 /* Look for certain command line options */ 798 for (int i = 1; i < argc; i++) { 799 if (argv[i]) { 800 if (strcmp(argv[i], "-initname") == 0) { 801 if (argv[i + 1]) { 802 char *name = argv[i + 1]; 803 feature = NewString(name); 804 Swig_mark_arg(i); 805 Swig_mark_arg(i + 1); 806 i++; 807 } else { 808 Swig_arg_error(); 809 } 810 } 811 else if (strcmp(argv[i], "-feature") == 0) { 812 fprintf( stderr, "Warning: Ruby -feature option is deprecated, " 813 "please use -initname instead.\n"); 814 if (argv[i + 1]) { 815 char *name = argv[i + 1]; 816 feature = NewString(name); 817 Swig_mark_arg(i); 818 Swig_mark_arg(i + 1); 819 i++; 820 } else { 821 Swig_arg_error(); 822 } 823 } else if (strcmp(argv[i], "-globalmodule") == 0) { 824 useGlobalModule = true; 825 Swig_mark_arg(i); 826 } else if (strcmp(argv[i], "-minherit") == 0) { 827 multipleInheritance = true; 828 director_multiple_inheritance = 1; 829 Swig_mark_arg(i); 830 } else if (strcmp(argv[i], "-cppcast") == 0) { 831 cppcast = 1; 832 Swig_mark_arg(i); 833 } else if (strcmp(argv[i], "-nocppcast") == 0) { 834 cppcast = 0; 835 Swig_mark_arg(i); 836 } else if (strcmp(argv[i], "-autorename") == 0) { 837 autorename = 1; 838 Swig_mark_arg(i); 839 } else if (strcmp(argv[i], "-noautorename") == 0) { 840 autorename = 0; 841 Swig_mark_arg(i); 842 } else if (strcmp(argv[i], "-prefix") == 0) { 843 if (argv[i + 1]) { 844 char *name = argv[i + 1]; 845 prefix = NewString(name); 846 Swig_mark_arg(i); 847 Swig_mark_arg(i + 1); 848 i++; 849 } else { 850 Swig_arg_error(); 851 } 852 } else if (strcmp(argv[i], "-help") == 0) { 853 Printf(stdout, "%s\n", usage); 854 } 855 } 856 } 857 858 if (cppcast) { 859 /* Turn on cppcast mode */ 860 Preprocessor_define((DOH *) "SWIG_CPLUSPLUS_CAST", 0); 861 } 862 863 if (autorename) { 864 /* Turn on the autorename mode */ 865 Preprocessor_define((DOH *) "SWIG_RUBY_AUTORENAME", 0); 866 } 867 868 /* Add a symbol to the parser for conditional compilation */ 869 Preprocessor_define("SWIGRUBY 1", 0); 870 871 /* Add typemap definitions */ 872 SWIG_typemap_lang("ruby"); 873 SWIG_config_file("ruby.swg"); 874 allow_overloading(); 875 } 876 877 /** 878 * Generate initialization code to define the Ruby module(s), 879 * accounting for nested modules as necessary. 880 */ 881 void defineRubyModule() { 882 List *modules = Split(module, ':', INT_MAX); 883 if (modules != 0 && Len(modules) > 0) { 884 String *mv = 0; 885 Iterator m; 886 m = First(modules); 887 while (m.item) { 888 if (Len(m.item) > 0) { 889 if (mv != 0) { 890 Printv(f_init, tab4, modvar, " = rb_define_module_under(", modvar, ", \"", m.item, "\");\n", NIL); 891 } else { 892 Printv(f_init, tab4, modvar, " = rb_define_module(\"", m.item, "\");\n", NIL); 893 mv = NewString(modvar); 894 } 895 } 896 m = Next(m); 897 } 898 Delete(mv); 899 Delete(modules); 900 } 901 } 902 903 void registerMagicMethods() { 904 905 special_methods = NewHash(); 906 907 /* Python->Ruby style special method name. */ 908 /* Basic */ 909 Setattr(special_methods, "__repr__", "inspect"); 910 Setattr(special_methods, "__str__", "to_s"); 911 Setattr(special_methods, "__cmp__", "<=>"); 912 Setattr(special_methods, "__hash__", "hash"); 913 Setattr(special_methods, "__nonzero__", "nonzero?"); 914 915 /* Callable */ 916 Setattr(special_methods, "__call__", "call"); 917 918 /* Collection */ 919 Setattr(special_methods, "__len__", "length"); 920 Setattr(special_methods, "__getitem__", "[]"); 921 Setattr(special_methods, "__setitem__", "[]="); 922 923 /* Operators */ 924 Setattr(special_methods, "__add__", "+"); 925 Setattr(special_methods, "__pos__", "+@"); 926 Setattr(special_methods, "__sub__", "-"); 927 Setattr(special_methods, "__neg__", "-@"); 928 Setattr(special_methods, "__mul__", "*"); 929 Setattr(special_methods, "__div__", "/"); 930 Setattr(special_methods, "__mod__", "%"); 931 Setattr(special_methods, "__lshift__", "<<"); 932 Setattr(special_methods, "__rshift__", ">>"); 933 Setattr(special_methods, "__and__", "&"); 934 Setattr(special_methods, "__or__", "|"); 935 Setattr(special_methods, "__xor__", "^"); 936 Setattr(special_methods, "__invert__", "~"); 937 Setattr(special_methods, "__lt__", "<"); 938 Setattr(special_methods, "__le__", "<="); 939 Setattr(special_methods, "__gt__", ">"); 940 Setattr(special_methods, "__ge__", ">="); 941 Setattr(special_methods, "__eq__", "=="); 942 943 /* Other numeric */ 944 Setattr(special_methods, "__divmod__", "divmod"); 945 Setattr(special_methods, "__pow__", "**"); 946 Setattr(special_methods, "__abs__", "abs"); 947 Setattr(special_methods, "__int__", "to_i"); 948 Setattr(special_methods, "__float__", "to_f"); 949 Setattr(special_methods, "__coerce__", "coerce"); 950 } 951 952 /* --------------------------------------------------------------------- 953 * top() 954 * --------------------------------------------------------------------- */ 955 956 virtual int top(Node *n) { 957 958 /** 959 * See if any Ruby module options have been specified as options 960 * to the %module directive. 961 */ 962 Node *swigModule = Getattr(n, "module"); 963 if (swigModule) { 964 Node *options = Getattr(swigModule, "options"); 965 if (options) { 966 if (Getattr(options, "directors")) { 967 allow_directors(); 968 } 969 if (Getattr(options, "dirprot")) { 970 allow_dirprot(); 971 } 972 if (Getattr(options, "ruby_globalmodule")) { 973 useGlobalModule = true; 974 } 975 if (Getattr(options, "ruby_minherit")) { 976 multipleInheritance = true; 977 director_multiple_inheritance = 1; 978 } 979 } 980 } 981 982 /* Set comparison with none for ConstructorToFunction */ 983 984 985 setSubclassInstanceCheck(NewStringf("strcmp(rb_obj_classname(self), classname) != 0")); 986 // setSubclassInstanceCheck(NewString("CLASS_OF(self) != cFoo.klass")); 987 988 /* Initialize all of the output files */ 989 String *outfile = Getattr(n, "outfile"); 990 String *outfile_h = Getattr(n, "outfile_h"); 991 992 if (!outfile) { 993 Printf(stderr, "Unable to determine outfile\n"); 994 SWIG_exit(EXIT_FAILURE); 995 } 996 997 f_begin = NewFile(outfile, "w", SWIG_output_files()); 998 if (!f_begin) { 999 FileErrorDisplay(outfile); 1000 SWIG_exit(EXIT_FAILURE); 1001 } 1002 1003 f_runtime = NewString(""); 1004 f_init = NewString(""); 1005 f_header = NewString(""); 1006 f_wrappers = NewString(""); 1007 f_directors_h = NewString(""); 1008 f_directors = NewString(""); 1009 f_directors_helpers = NewString(""); 1010 f_initbeforefunc = NewString(""); 1011 1012 if (directorsEnabled()) { 1013 if (!outfile_h) { 1014 Printf(stderr, "Unable to determine outfile_h\n"); 1015 SWIG_exit(EXIT_FAILURE); 1016 } 1017 f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files()); 1018 if (!f_runtime_h) { 1019 FileErrorDisplay(outfile_h); 1020 SWIG_exit(EXIT_FAILURE); 1021 } 1022 } 1023 1024 /* Register file targets with the SWIG file handler */ 1025 Swig_register_filebyname("header", f_header); 1026 Swig_register_filebyname("wrapper", f_wrappers); 1027 Swig_register_filebyname("begin", f_begin); 1028 Swig_register_filebyname("runtime", f_runtime); 1029 Swig_register_filebyname("init", f_init); 1030 Swig_register_filebyname("director", f_directors); 1031 Swig_register_filebyname("director_h", f_directors_h); 1032 Swig_register_filebyname("director_helpers", f_directors_helpers); 1033 Swig_register_filebyname("initbeforefunc", f_initbeforefunc); 1034 1035 modvar = 0; 1036 current = NO_CPP; 1037 klass = 0; 1038 classes = NewHash(); 1039 1040 registerMagicMethods(); 1041 1042 Swig_banner(f_begin); 1043 1044 Printf(f_runtime, "\n"); 1045 Printf(f_runtime, "#define SWIGRUBY\n"); 1046 1047 if (directorsEnabled()) { 1048 Printf(f_runtime, "#define SWIG_DIRECTORS\n"); 1049 } 1050 1051 Printf(f_runtime, "\n"); 1052 1053 /* typedef void *VALUE */ 1054 SwigType *value = NewSwigType(T_VOID); 1055 SwigType_add_pointer(value); 1056 SwigType_typedef(value, (char *) "VALUE"); 1057 Delete(value); 1058 1059 /* Set module name */ 1060 set_module(Char(Getattr(n, "name"))); 1061 1062 if (directorsEnabled()) { 1063 /* Build a version of the module name for use in a C macro name. */ 1064 String *module_macro = Copy(module); 1065 Replaceall(module_macro, "::", "__"); 1066 1067 Swig_banner(f_directors_h); 1068 Printf(f_directors_h, "\n"); 1069 Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_macro); 1070 Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_macro); 1071 Printf(f_directors_h, "namespace Swig {\n"); 1072 Printf(f_directors_h, " class Director;\n"); 1073 Printf(f_directors_h, "}\n\n"); 1074 1075 Printf(f_directors_helpers, "/* ---------------------------------------------------\n"); 1076 Printf(f_directors_helpers, " * C++ director class helpers\n"); 1077 Printf(f_directors_helpers, " * --------------------------------------------------- */\n\n"); 1078 1079 Printf(f_directors, "\n\n"); 1080 Printf(f_directors, "/* ---------------------------------------------------\n"); 1081 Printf(f_directors, " * C++ director class methods\n"); 1082 Printf(f_directors, " * --------------------------------------------------- */\n\n"); 1083 if (outfile_h) 1084 Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h)); 1085 1086 Delete(module_macro); 1087 } 1088 1089 Printf(f_header, "#define SWIG_init Init_%s\n", feature); 1090 Printf(f_header, "#define SWIG_name \"%s\"\n\n", module); 1091 Printf(f_header, "static VALUE %s;\n", modvar); 1092 1093 /* Start generating the initialization function */ 1094 String* docs = docstring(n, AUTODOC_CLASS); 1095 Printf(f_init, "/*\n%s\n*/", docs ); 1096 Printv(f_init, "\n", "#ifdef __cplusplus\n", "extern \"C\"\n", "#endif\n", "SWIGEXPORT void Init_", feature, "(void) {\n", "size_t i;\n", "\n", NIL); 1097 1098 Printv(f_init, tab4, "SWIG_InitRuntime();\n", NIL); 1099 1100 if (!useGlobalModule) 1101 defineRubyModule(); 1102 1103 Printv(f_init, "\n", "SWIG_InitializeModule(0);\n", "for (i = 0; i < swig_module.size; i++) {\n", "SWIG_define_class(swig_module.types[i]);\n", "}\n", NIL); 1104 Printf(f_init, "\n"); 1105 1106 /* Initialize code to keep track of objects */ 1107 Printf(f_init, "SWIG_RubyInitializeTrackings();\n"); 1108 1109 Language::top(n); 1110 1111 if (directorsEnabled()) { 1112 // Insert director runtime into the f_runtime file (make it occur before %header section) 1113 Swig_insert_file("director.swg", f_runtime); 1114 } 1115 1116 /* Finish off our init function */ 1117 Printf(f_init, "}\n"); 1118 SwigType_emit_type_table(f_runtime, f_wrappers); 1119 1120 /* Close all of the files */ 1121 Dump(f_runtime, f_begin); 1122 Dump(f_header, f_begin); 1123 1124 if (directorsEnabled()) { 1125 Dump(f_directors_helpers, f_begin); 1126 Dump(f_directors, f_begin); 1127 Dump(f_directors_h, f_runtime_h); 1128 Printf(f_runtime_h, "\n"); 1129 Printf(f_runtime_h, "#endif\n"); 1130 Close(f_runtime_h); 1131 } 1132 1133 Dump(f_wrappers, f_begin); 1134 Dump(f_initbeforefunc, f_begin); 1135 Wrapper_pretty_print(f_init, f_begin); 1136 1137 Delete(f_header); 1138 Delete(f_wrappers); 1139 Delete(f_init); 1140 Delete(f_initbeforefunc); 1141 Close(f_begin); 1142 Delete(f_runtime); 1143 Delete(f_begin); 1144 1145 return SWIG_OK; 1146 } 1147 1148 /* ----------------------------------------------------------------------------- 1149 * importDirective() 1150 * ----------------------------------------------------------------------------- */ 1151 1152 virtual int importDirective(Node *n) { 1153 String *modname = Getattr(n, "module"); 1154 if (modname) { 1155 if (prefix) { 1156 Insert(modname, 0, prefix); 1157 } 1158 1159 List *modules = Split(modname, ':', INT_MAX); 1160 if (modules && Len(modules) > 0) { 1161 modname = NewString(""); 1162 String *last = NULL; 1163 Iterator m = First(modules); 1164 while (m.item) { 1165 if (Len(m.item) > 0) { 1166 if (last) { 1167 Append(modname, "/"); 1168 } 1169 Append(modname, m.item); 1170 last = m.item; 1171 } 1172 m = Next(m); 1173 } 1174 Printf(f_init, "rb_require(\"%s\");\n", modname); 1175 Delete(modname); 1176 } 1177 Delete(modules); 1178 } 1179 return Language::importDirective(n); 1180 } 1181 1182 /* --------------------------------------------------------------------- 1183 * set_module(const char *mod_name) 1184 * 1185 * Sets the module name. Does nothing if it's already set (so it can 1186 * be overridden as a command line option). 1187 *---------------------------------------------------------------------- */ 1188 1189 void set_module(const char *s) { 1190 String *mod_name = NewString(s); 1191 if (module == 0) { 1192 /* Start with the empty string */ 1193 module = NewString(""); 1194 1195 if (prefix) { 1196 Insert(mod_name, 0, prefix); 1197 } 1198 1199 /* Account for nested modules */ 1200 List *modules = Split(mod_name, ':', INT_MAX); 1201 if (modules != 0 && Len(modules) > 0) { 1202 String *last = 0; 1203 Iterator m = First(modules); 1204 while (m.item) { 1205 if (Len(m.item) > 0) { 1206 String *cap = NewString(m.item); 1207 (Char(cap))[0] = (char)toupper((Char(cap))[0]); 1208 if (last != 0) { 1209 Append(module, "::"); 1210 } 1211 Append(module, cap); 1212 last = m.item; 1213 } 1214 m = Next(m); 1215 } 1216 if (feature == 0) { 1217 feature = Copy(last); 1218 } 1219 (Char(last))[0] = (char)toupper((Char(last))[0]); 1220 modvar = NewStringf("m%s", last); 1221 Delete(modules); 1222 } 1223 } 1224 Delete(mod_name); 1225 } 1226 1227 /* -------------------------------------------------------------------------- 1228 * nativeWrapper() 1229 * -------------------------------------------------------------------------- */ 1230 virtual int nativeWrapper(Node *n) { 1231 String *funcname = Getattr(n, "wrap:name"); 1232 Swig_warning(WARN_LANG_NATIVE_UNIMPL, input_file, line_number, "Adding native function %s not supported (ignored).\n", funcname); 1233 return SWIG_NOWRAP; 1234 } 1235 1236 /** 1237 * Process the comma-separated list of aliases (if any). 1238 */ 1239 void defineAliases(Node *n, const_String_or_char_ptr iname) { 1240 String *aliasv = Getattr(n, "feature:alias"); 1241 if (aliasv) { 1242 List *aliases = Split(aliasv, ',', INT_MAX); 1243 if (aliases && Len(aliases) > 0) { 1244 Iterator alias = First(aliases); 1245 while (alias.item) { 1246 if (Len(alias.item) > 0) { 1247 Printv(klass->init, tab4, "rb_define_alias(", klass->vname, ", \"", alias.item, "\", \"", iname, "\");\n", NIL); 1248 } 1249 alias = Next(alias); 1250 } 1251 } 1252 Delete(aliases); 1253 } 1254 } 1255 1256 /* --------------------------------------------------------------------- 1257 * create_command(Node *n, char *iname) 1258 * 1259 * Creates a new command from a C function. 1260 * iname = Name of function in scripting language 1261 * 1262 * A note about what "protected" and "private" mean in Ruby: 1263 * 1264 * A private method is accessible only within the class or its subclasses, 1265 * and it is callable only in "function form", with 'self' (implicit or 1266 * explicit) as a receiver. 1267 * 1268 * A protected method is callable only from within its class, but unlike 1269 * a private method, it can be called with a receiver other than self, such 1270 * as another instance of the same class. 1271 * --------------------------------------------------------------------- */ 1272 1273 void create_command(Node *n, const_String_or_char_ptr iname) { 1274 1275 String *alloc_func = Swig_name_wrapper(iname); 1276 String *wname = Swig_name_wrapper(iname); 1277 if (CPlusPlus) { 1278 Insert(wname, 0, "VALUEFUNC("); 1279 Append(wname, ")"); 1280 } 1281 if (current != NO_CPP) 1282 iname = klass->strip(iname); 1283 if (Getattr(special_methods, iname)) { 1284 iname = GetChar(special_methods, iname); 1285 } 1286 1287 String *s = NewString(""); 1288 String *temp = NewString(""); 1289 1290#ifdef SWIG_PROTECTED_TARGET_METHODS 1291 const char *rb_define_method = is_public(n) ? "rb_define_method" : "rb_define_protected_method"; 1292#else 1293 const char *rb_define_method = "rb_define_method"; 1294#endif 1295 switch (current) { 1296 case MEMBER_FUNC: 1297 { 1298 if (multipleInheritance) { 1299 Printv(klass->init, tab4, rb_define_method, "(", klass->mImpl, ", \"", iname, "\", ", wname, ", -1);\n", NIL); 1300 } else { 1301 Printv(klass->init, tab4, rb_define_method, "(", klass->vname, ", \"", iname, "\", ", wname, ", -1);\n", NIL); 1302 } 1303 } 1304 break; 1305 case CONSTRUCTOR_ALLOCATE: 1306 Printv(s, tab4, "rb_define_alloc_func(", klass->vname, ", ", alloc_func, ");\n", NIL); 1307 Replaceall(klass->init, "$allocator", s); 1308 break; 1309 case CONSTRUCTOR_INITIALIZE: 1310 Printv(s, tab4, rb_define_method, "(", klass->vname, ", \"initialize\", ", wname, ", -1);\n", NIL); 1311 Replaceall(klass->init, "$initializer", s); 1312 break; 1313 case MEMBER_VAR: 1314 Append(temp, iname); 1315 /* Check for _set or _get at the end of the name. */ 1316 if (Len(temp) > 4) { 1317 const char *p = Char(temp) + (Len(temp) - 4); 1318 if (strcmp(p, "_set") == 0) { 1319 Delslice(temp, Len(temp) - 4, DOH_END); 1320 Append(temp, "="); 1321 } else if (strcmp(p, "_get") == 0) { 1322 Delslice(temp, Len(temp) - 4, DOH_END); 1323 } 1324 } 1325 if (multipleInheritance) { 1326 Printv(klass->init, tab4, "rb_define_method(", klass->mImpl, ", \"", temp, "\", ", wname, ", -1);\n", NIL); 1327 } else { 1328 Printv(klass->init, tab4, "rb_define_method(", klass->vname, ", \"", temp, "\", ", wname, ", -1);\n", NIL); 1329 } 1330 break; 1331 case STATIC_FUNC: 1332 Printv(klass->init, tab4, "rb_define_singleton_method(", klass->vname, ", \"", iname, "\", ", wname, ", -1);\n", NIL); 1333 break; 1334 case NO_CPP: 1335 if (!useGlobalModule) { 1336 Printv(s, tab4, "rb_define_module_function(", modvar, ", \"", iname, "\", ", wname, ", -1);\n", NIL); 1337 Printv(f_init, s, NIL); 1338 } else { 1339 Printv(s, tab4, "rb_define_global_function(\"", iname, "\", ", wname, ", -1);\n", NIL); 1340 Printv(f_init, s, NIL); 1341 } 1342 break; 1343 case DESTRUCTOR: 1344 case CLASS_CONST: 1345 case STATIC_VAR: 1346 assert(false); // Should not have gotten here for these types 1347 default: 1348 assert(false); 1349 } 1350 1351 defineAliases(n, iname); 1352 1353 Delete(temp); 1354 Delete(s); 1355 Delete(wname); 1356 Delete(alloc_func); 1357 } 1358 1359 /* --------------------------------------------------------------------- 1360 * applyInputTypemap() 1361 * 1362 * Look up the appropriate "in" typemap for this parameter (p), 1363 * substitute the correct strings for the $target and $input typemap 1364 * parameters, and dump the resulting code to the wrapper file. 1365 * --------------------------------------------------------------------- */ 1366 1367 Parm *applyInputTypemap(Parm *p, String *ln, String *source, Wrapper *f, String *symname) { 1368 String *tm; 1369 SwigType *pt = Getattr(p, "type"); 1370 if ((tm = Getattr(p, "tmap:in"))) { 1371 Replaceall(tm, "$target", ln); 1372 Replaceall(tm, "$source", source); 1373 Replaceall(tm, "$input", source); 1374 Replaceall(tm, "$symname", symname); 1375 1376 if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) { 1377 Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN"); 1378 } else { 1379 Replaceall(tm, "$disown", "0"); 1380 } 1381 1382 Setattr(p, "emit:input", Copy(source)); 1383 Printf(f->code, "%s\n", tm); 1384 p = Getattr(p, "tmap:in:next"); 1385 } else { 1386 Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0)); 1387 p = nextSibling(p); 1388 } 1389 return p; 1390 } 1391 1392 Parm *skipIgnoredArgs(Parm *p) { 1393 while (checkAttribute(p, "tmap:in:numinputs", "0")) { 1394 p = Getattr(p, "tmap:in:next"); 1395 } 1396 return p; 1397 } 1398 1399 /* --------------------------------------------------------------------- 1400 * marshalInputArgs() 1401 * 1402 * Process all of the arguments passed into the scripting language 1403 * method and convert them into C/C++ function arguments using the 1404 * supplied typemaps. 1405 * --------------------------------------------------------------------- */ 1406 1407 void marshalInputArgs(Node *n, ParmList *l, int numarg, int numreq, String *kwargs, bool allow_kwargs, Wrapper *f) { 1408 int i; 1409 Parm *p; 1410 String *tm; 1411 String *source; 1412 String *target; 1413 1414 source = NewString(""); 1415 target = NewString(""); 1416 1417 bool ctor_director = (current == CONSTRUCTOR_INITIALIZE && Swig_directorclass(n)); 1418 1419 /** 1420 * The 'start' value indicates which of the C/C++ function arguments 1421 * produced here corresponds to the first value in Ruby's argv[] array. 1422 * The value of start is either zero or one. If start is zero, then 1423 * the first argument (with name arg1) is based on the value of argv[0]. 1424 * If start is one, then arg1 is based on the value of argv[1]. 1425 */ 1426 int start = (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) ? 1 : 0; 1427 1428 int varargs = emit_isvarargs(l); 1429 1430 Printf(kwargs, "{ "); 1431 for (i = 0, p = l; i < numarg; i++) { 1432 1433 p = skipIgnoredArgs(p); 1434 1435 String *pn = Getattr(p, "name"); 1436 String *ln = Getattr(p, "lname"); 1437 1438 /* Produce string representation of source argument */ 1439 Clear(source); 1440 1441 /* First argument is a special case */ 1442 if (i == 0) { 1443 Printv(source, (start == 0) ? "argv[0]" : "self", NIL); 1444 } else { 1445 Printf(source, "argv[%d]", i - start); 1446 } 1447 1448 /* Produce string representation of target argument */ 1449 Clear(target); 1450 Printf(target, "%s", Char(ln)); 1451 1452 if (i >= (numreq)) { /* Check if parsing an optional argument */ 1453 Printf(f->code, " if (argc > %d) {\n", i - start); 1454 } 1455 1456 /* Record argument name for keyword argument handling */ 1457 if (Len(pn)) { 1458 Printf(kwargs, "\"%s\",", pn); 1459 } else { 1460 Printf(kwargs, "\"arg%d\",", i + 1); 1461 } 1462 1463 /* Look for an input typemap */ 1464 p = applyInputTypemap(p, ln, source, f, Getattr(n, "name")); 1465 if (i >= numreq) { 1466 Printf(f->code, "}\n"); 1467 } 1468 } 1469 1470 /* Finish argument marshalling */ 1471 Printf(kwargs, " NULL }"); 1472 if (allow_kwargs) { 1473 Printv(f->locals, tab4, "char *kwnames[] = ", kwargs, ";\n", NIL); 1474 } 1475 1476 /* Trailing varargs */ 1477 if (varargs) { 1478 if (p && (tm = Getattr(p, "tmap:in"))) { 1479 Clear(source); 1480 Printf(source, "argv[%d]", i - start); 1481 Replaceall(tm, "$input", source); 1482 Setattr(p, "emit:input", Copy(source)); 1483 Printf(f->code, "if (argc > %d) {\n", i - start); 1484 Printv(f->code, tm, "\n", NIL); 1485 Printf(f->code, "}\n"); 1486 } 1487 } 1488 1489 Delete(source); 1490 Delete(target); 1491 } 1492 1493 /* --------------------------------------------------------------------- 1494 * insertConstraintCheckingCode(ParmList *l, Wrapper *f) 1495 * 1496 * Checks each of the parameters in the parameter list for a "check" 1497 * typemap and (if it finds one) inserts the typemapping code into 1498 * the function wrapper. 1499 * --------------------------------------------------------------------- */ 1500 1501 void insertConstraintCheckingCode(ParmList *l, Wrapper *f) { 1502 Parm *p; 1503 String *tm; 1504 for (p = l; p;) { 1505 if ((tm = Getattr(p, "tmap:check"))) { 1506 Replaceall(tm, "$target", Getattr(p, "lname")); 1507 Printv(f->code, tm, "\n", NIL); 1508 p = Getattr(p, "tmap:check:next"); 1509 } else { 1510 p = nextSibling(p); 1511 } 1512 } 1513 } 1514 1515 /* --------------------------------------------------------------------- 1516 * insertCleanupCode(ParmList *l, String *cleanup) 1517 * 1518 * Checks each of the parameters in the parameter list for a "freearg" 1519 * typemap and (if it finds one) inserts the typemapping code into 1520 * the function wrapper. 1521 * --------------------------------------------------------------------- */ 1522 1523 void insertCleanupCode(ParmList *l, String *cleanup) { 1524 String *tm; 1525 for (Parm *p = l; p;) { 1526 if ((tm = Getattr(p, "tmap:freearg"))) { 1527 if (Len(tm) != 0) { 1528 Replaceall(tm, "$source", Getattr(p, "lname")); 1529 Printv(cleanup, tm, "\n", NIL); 1530 } 1531 p = Getattr(p, "tmap:freearg:next"); 1532 } else { 1533 p = nextSibling(p); 1534 } 1535 } 1536 } 1537 1538 /* --------------------------------------------------------------------- 1539 * insertArgOutputCode(ParmList *l, String *outarg, int& need_result) 1540 * 1541 * Checks each of the parameters in the parameter list for a "argout" 1542 * typemap and (if it finds one) inserts the typemapping code into 1543 * the function wrapper. 1544 * --------------------------------------------------------------------- */ 1545 1546 void insertArgOutputCode(ParmList *l, String *outarg, int &need_result) { 1547 String *tm; 1548 for (Parm *p = l; p;) { 1549 if ((tm = Getattr(p, "tmap:argout"))) { 1550 Replaceall(tm, "$source", Getattr(p, "lname")); 1551 Replaceall(tm, "$target", "vresult"); 1552 Replaceall(tm, "$result", "vresult"); 1553 Replaceall(tm, "$arg", Getattr(p, "emit:input")); 1554 Replaceall(tm, "$input", Getattr(p, "emit:input")); 1555 1556 Printv(outarg, tm, "\n", NIL); 1557 need_result += 1; 1558 p = Getattr(p, "tmap:argout:next"); 1559 } else { 1560 p = nextSibling(p); 1561 } 1562 } 1563 } 1564 1565 /* --------------------------------------------------------------------- 1566 * validIdentifier() 1567 * 1568 * Is this a valid identifier in the scripting language? 1569 * Ruby method names can include any combination of letters, numbers 1570 * and underscores. A Ruby method name may optionally end with 1571 * a question mark ("?"), exclamation point ("!") or equals sign ("="). 1572 * 1573 * Methods whose names end with question marks are, by convention, 1574 * predicate methods that return true or false (e.g. Array#empty?). 1575 * 1576 * Methods whose names end with exclamation points are, by convention, 1577 * called bang methods that modify the instance in place (e.g. Array#sort!). 1578 * 1579 * Methods whose names end with an equals sign are attribute setters 1580 * (e.g. Thread#critical=). 1581 * --------------------------------------------------------------------- */ 1582 1583 virtual int validIdentifier(String *s) { 1584 char *c = Char(s); 1585 while (*c) { 1586 if (!(isalnum(*c) || (*c == '_') || (*c == '?') || (*c == '!') || (*c == '='))) 1587 return 0; 1588 c++; 1589 } 1590 return 1; 1591 } 1592 1593 /* --------------------------------------------------------------------- 1594 * functionWrapper() 1595 * 1596 * Create a function declaration and register it with the interpreter. 1597 * --------------------------------------------------------------------- */ 1598 1599 virtual int functionWrapper(Node *n) { 1600 1601 String *nodeType; 1602 bool constructor; 1603 bool destructor; 1604 String *storage; 1605 1606 String *symname = Copy(Getattr(n, "sym:name")); 1607 SwigType *t = Getattr(n, "type"); 1608 ParmList *l = Getattr(n, "parms"); 1609 int director_method = 0; 1610 String *tm; 1611 1612 int need_result = 0; 1613 1614 /* Ruby needs no destructor wrapper */ 1615 if (current == DESTRUCTOR) 1616 return SWIG_NOWRAP; 1617 1618 nodeType = Getattr(n, "nodeType"); 1619 constructor = (!Cmp(nodeType, "constructor")); 1620 destructor = (!Cmp(nodeType, "destructor")); 1621 storage = Getattr(n, "storage"); 1622 1623 /* If the C++ class constructor is overloaded, we only want to 1624 * write out the "new" singleton method once since it is always 1625 * the same. (It's the "initialize" method that will handle the 1626 * overloading). */ 1627 1628 if (current == CONSTRUCTOR_ALLOCATE && Swig_symbol_isoverloaded(n) && Getattr(n, "sym:nextSibling") != 0) 1629 return SWIG_OK; 1630 1631 String *overname = 0; 1632 if (Getattr(n, "sym:overloaded")) { 1633 overname = Getattr(n, "sym:overname"); 1634 } else { 1635 if (!addSymbol(symname, n)) 1636 return SWIG_ERROR; 1637 } 1638 1639 String *cleanup = NewString(""); 1640 String *outarg = NewString(""); 1641 String *kwargs = NewString(""); 1642 Wrapper *f = NewWrapper(); 1643 1644 /* Rename predicate methods */ 1645 if (GetFlag(n, "feature:predicate")) { 1646 Append(symname, "?"); 1647 } 1648 1649 /* Rename bang methods */ 1650 if (GetFlag(n, "feature:bang")) { 1651 Append(symname, "!"); 1652 } 1653 1654 /* Determine the name of the SWIG wrapper function */ 1655 String *wname = Swig_name_wrapper(symname); 1656 if (overname && current != CONSTRUCTOR_ALLOCATE) { 1657 Append(wname, overname); 1658 } 1659 1660 /* Emit arguments */ 1661 if (current != CONSTRUCTOR_ALLOCATE) { 1662 emit_parameter_variables(l, f); 1663 } 1664 1665 /* Attach standard typemaps */ 1666 if (current != CONSTRUCTOR_ALLOCATE) { 1667 emit_attach_parmmaps(l, f); 1668 } 1669 Setattr(n, "wrap:parms", l); 1670 1671 /* Get number of arguments */ 1672 int numarg = emit_num_arguments(l); 1673 int numreq = emit_num_required(l); 1674 int varargs = emit_isvarargs(l); 1675 bool allow_kwargs = GetFlag(n, "feature:kwargs") ? true : false; 1676 1677 bool ctor_director = (current == CONSTRUCTOR_INITIALIZE && Swig_directorclass(n)); 1678 int start = (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) ? 1 : 0; 1679 1680 /* Now write the wrapper function itself */ 1681 if (current == CONSTRUCTOR_ALLOCATE) { 1682 Printf(f->def, "#ifdef HAVE_RB_DEFINE_ALLOC_FUNC\n"); 1683 Printv(f->def, "SWIGINTERN VALUE\n", wname, "(VALUE self) {", NIL); 1684 Printf(f->def, "#else\n"); 1685 Printv(f->def, "SWIGINTERN VALUE\n", wname, "(int argc, VALUE *argv, VALUE self) {", NIL); 1686 Printf(f->def, "#endif\n"); 1687 } else if (current == CONSTRUCTOR_INITIALIZE) { 1688 Printv(f->def, "SWIGINTERN VALUE\n", wname, "(int argc, VALUE *argv, VALUE self) {", NIL); 1689 if (!varargs) { 1690 Printf(f->code, "if ((argc < %d) || (argc > %d)) ", numreq - start, numarg - start); 1691 } else { 1692 Printf(f->code, "if (argc < %d) ", numreq - start); 1693 } 1694 Printf(f->code, "{rb_raise(rb_eArgError, \"wrong # of arguments(%%d for %d)\",argc); SWIG_fail;}\n", numreq - start); 1695 } else { 1696 1697 if ( current == NO_CPP ) 1698 { 1699 String* docs = docstring(n, AUTODOC_FUNC); 1700 Printf(f_wrappers, "%s", docs); 1701 Delete(docs); 1702 } 1703 1704 Printv(f->def, "SWIGINTERN VALUE\n", wname, "(int argc, VALUE *argv, VALUE self) {", NIL); 1705 if (!varargs) { 1706 Printf(f->code, "if ((argc < %d) || (argc > %d)) ", numreq - start, numarg - start); 1707 } else { 1708 Printf(f->code, "if (argc < %d) ", numreq - start); 1709 } 1710 Printf(f->code, "{rb_raise(rb_eArgError, \"wrong # of arguments(%%d for %d)\",argc); SWIG_fail;}\n", numreq - start); 1711 } 1712 1713 /* Now walk the function parameter list and generate code */ 1714 /* to get arguments */ 1715 if (current != CONSTRUCTOR_ALLOCATE) { 1716 marshalInputArgs(n, l, numarg, numreq, kwargs, allow_kwargs, f); 1717 } 1718 // FIXME? 1719 if (ctor_director) { 1720 numarg--; 1721 numreq--; 1722 } 1723 1724 /* Insert constraint checking code */ 1725 insertConstraintCheckingCode(l, f); 1726 1727 /* Insert cleanup code */ 1728 insertCleanupCode(l, cleanup); 1729 1730 /* Insert argument output code */ 1731 insertArgOutputCode(l, outarg, need_result); 1732 1733 /* if the object is a director, and the method call originated from its 1734 * underlying Ruby object, resolve the call by going up the c++ 1735 * inheritance chain. otherwise try to resolve the method in python. 1736 * without this check an infinite loop is set up between the director and 1737 * shadow class method calls. 1738 */ 1739 1740 // NOTE: this code should only be inserted if this class is the 1741 // base class of a director class. however, in general we haven't 1742 // yet analyzed all classes derived from this one to see if they are 1743 // directors. furthermore, this class may be used as the base of 1744 // a director class defined in a completely different module at a 1745 // later time, so this test must be included whether or not directorbase 1746 // is true. we do skip this code if directors have not been enabled 1747 // at the command line to preserve source-level compatibility with 1748 // non-polymorphic swig. also, if this wrapper is for a smart-pointer 1749 // method, there is no need to perform the test since the calling object 1750 // (the smart-pointer) and the director object (the "pointee") are 1751 // distinct. 1752 1753 director_method = is_member_director(n) && !is_smart_pointer() && !destructor; 1754 if (director_method) { 1755 Wrapper_add_local(f, "director", "Swig::Director *director = 0"); 1756 Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n"); 1757 Wrapper_add_local(f, "upcall", "bool upcall = false"); 1758 Append(f->code, "upcall = (director && (director->swig_get_self() == self));\n"); 1759 } 1760 1761 /* Now write code to make the function call */ 1762 if (current != CONSTRUCTOR_ALLOCATE) { 1763 if (current == CONSTRUCTOR_INITIALIZE) { 1764 Node *pn = Swig_methodclass(n); 1765 String *symname = Getattr(pn, "sym:name"); 1766 String *action = Getattr(n, "wrap:action"); 1767 if (directorsEnabled()) { 1768 String *classname = NewStringf("const char *classname SWIGUNUSED = \"%s::%s\"", module, symname); 1769 Wrapper_add_local(f, "classname", classname); 1770 } 1771 if (action) { 1772 Append(action, "\nDATA_PTR(self) = result;"); 1773 if (GetFlag(pn, "feature:trackobjects")) { 1774 Append(action, "\nSWIG_RubyAddTracking(result, self);"); 1775 } 1776 } 1777 } 1778 1779 /* Emit the function call */ 1780 if (director_method) { 1781 Printf(f->code, "try {\n"); 1782 } 1783 1784 Setattr(n, "wrap:name", wname); 1785 1786 Swig_director_emit_dynamic_cast(n, f); 1787 String *actioncode = emit_action(n); 1788 1789 if (director_method) { 1790 Printf(actioncode, "} catch (Swig::DirectorException& e) {\n"); 1791 Printf(actioncode, " rb_exc_raise(e.getError());\n"); 1792 Printf(actioncode, " SWIG_fail;\n"); 1793 Printf(actioncode, "}\n"); 1794 } 1795 1796 /* Return value if necessary */ 1797 if (SwigType_type(t) != T_VOID && current != CONSTRUCTOR_INITIALIZE) { 1798 need_result = 1; 1799 if (GetFlag(n, "feature:predicate")) { 1800 Printv(actioncode, tab4, "vresult = (result ? Qtrue : Qfalse);\n", NIL); 1801 } else { 1802 tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode); 1803 actioncode = 0; 1804 if (tm) { 1805 Replaceall(tm, "$result", "vresult"); 1806 Replaceall(tm, "$source", "result"); 1807 Replaceall(tm, "$target", "vresult"); 1808 1809 if (GetFlag(n, "feature:new")) 1810 Replaceall(tm, "$owner", "SWIG_POINTER_OWN"); 1811 else 1812 Replaceall(tm, "$owner", "0"); 1813 1814#if 1 1815 // FIXME: this will not try to unwrap directors returned as non-director 1816 // base class pointers! 1817 1818 /* New addition to unwrap director return values so that the original 1819 * Ruby object is returned instead. 1820 */ 1821 bool unwrap = false; 1822 String *decl = Getattr(n, "decl"); 1823 int is_pointer = SwigType_ispointer_return(decl); 1824 int is_reference = SwigType_isreference_return(decl); 1825 if (is_pointer || is_reference) { 1826 String *type = Getattr(n, "type"); 1827 Node *parent = Swig_methodclass(n); 1828 Node *modname = Getattr(parent, "module"); 1829 Node *target = Swig_directormap(modname, type); 1830 if (target) 1831 unwrap = true; 1832 } 1833 if (unwrap) { 1834 Wrapper_add_local(f, "director", "Swig::Director *director = 0"); 1835 Printf(f->code, "director = dynamic_cast<Swig::Director *>(result);\n"); 1836 Printf(f->code, "if (director) {\n"); 1837 Printf(f->code, " vresult = director->swig_get_self();\n"); 1838 Printf(f->code, "} else {\n"); 1839 Printf(f->code, "%s\n", tm); 1840 Printf(f->code, "}\n"); 1841 director_method = 0; 1842 } else { 1843 Printf(f->code, "%s\n", tm); 1844 } 1845#else 1846 Printf(f->code, "%s\n", tm); 1847#endif 1848 Delete(tm); 1849 } else { 1850 Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s.\n", SwigType_str(t, 0)); 1851 } 1852 } 1853 } 1854 if (actioncode) { 1855 Append(f->code, actioncode); 1856 Delete(actioncode); 1857 } 1858 emit_return_variable(n, t, f); 1859 } 1860 1861 /* Extra code needed for new and initialize methods */ 1862 if (current == CONSTRUCTOR_ALLOCATE) { 1863 need_result = 1; 1864 Printf(f->code, "VALUE vresult = SWIG_NewClassInstance(self, SWIGTYPE%s);\n", Char(SwigType_manglestr(t))); 1865 Printf(f->code, "#ifndef HAVE_RB_DEFINE_ALLOC_FUNC\n"); 1866 Printf(f->code, "rb_obj_call_init(vresult, argc, argv);\n"); 1867 Printf(f->code, "#endif\n"); 1868 } else if (current == CONSTRUCTOR_INITIALIZE) { 1869 need_result = 1; 1870 // Printf(f->code, "DATA_PTR(self) = result;\n"); 1871 } 1872 else 1873 { 1874 if ( need_result > 1 ) { 1875 if ( SwigType_type(t) == T_VOID ) 1876 Printf(f->code, "vresult = rb_ary_new();\n"); 1877 else 1878 { 1879 Printf(f->code, "if (vresult == Qnil) vresult = rb_ary_new();\n"); 1880 Printf(f->code, "else vresult = SWIG_Ruby_AppendOutput( " 1881 "rb_ary_new(), vresult);\n"); 1882 } 1883 } 1884 } 1885 1886 /* Dump argument output code; */ 1887 Printv(f->code, outarg, NIL); 1888 1889 /* Dump the argument cleanup code */ 1890 int need_cleanup = (current != CONSTRUCTOR_ALLOCATE) && (Len(cleanup) != 0); 1891 if (need_cleanup) { 1892 Printv(f->code, cleanup, NIL); 1893 } 1894 1895 1896 /* Look for any remaining cleanup. This processes the %new directive */ 1897 if (current != CONSTRUCTOR_ALLOCATE && GetFlag(n, "feature:new")) { 1898 tm = Swig_typemap_lookup("newfree", n, "result", 0); 1899 if (tm) { 1900 Replaceall(tm, "$source", "result"); 1901 Printv(f->code, tm, "\n", NIL); 1902 Delete(tm); 1903 } 1904 } 1905 1906 /* Special processing on return value. */ 1907 tm = Swig_typemap_lookup("ret", n, "result", 0); 1908 if (tm) { 1909 Replaceall(tm, "$source", "result"); 1910 Printv(f->code, tm, NIL); 1911 Delete(tm); 1912 } 1913 1914 if (director_method) { 1915 if ((tm = Swig_typemap_lookup("directorfree", n, "result", 0))) { 1916 Replaceall(tm, "$input", "result"); 1917 Replaceall(tm, "$result", "vresult"); 1918 Printf(f->code, "%s\n", tm); 1919 } 1920 } 1921 1922 1923 /* Wrap things up (in a manner of speaking) */ 1924 if (need_result) { 1925 if (current == CONSTRUCTOR_ALLOCATE) { 1926 Printv(f->code, tab4, "return vresult;\n", NIL); 1927 } else if (current == CONSTRUCTOR_INITIALIZE) { 1928 Printv(f->code, tab4, "return self;\n", NIL); 1929 Printv(f->code, "fail:\n", NIL); 1930 if (need_cleanup) { 1931 Printv(f->code, cleanup, NIL); 1932 } 1933 Printv(f->code, tab4, "return Qnil;\n", NIL); 1934 } else { 1935 Wrapper_add_local(f, "vresult", "VALUE vresult = Qnil"); 1936 Printv(f->code, tab4, "return vresult;\n", NIL); 1937 Printv(f->code, "fail:\n", NIL); 1938 if (need_cleanup) { 1939 Printv(f->code, cleanup, NIL); 1940 } 1941 Printv(f->code, tab4, "return Qnil;\n", NIL); 1942 } 1943 } else { 1944 Printv(f->code, tab4, "return Qnil;\n", NIL); 1945 Printv(f->code, "fail:\n", NIL); 1946 if (need_cleanup) { 1947 Printv(f->code, cleanup, NIL); 1948 } 1949 Printv(f->code, tab4, "return Qnil;\n", NIL); 1950 } 1951 1952 Printf(f->code, "}\n"); 1953 1954 /* Substitute the cleanup code */ 1955 Replaceall(f->code, "$cleanup", cleanup); 1956 1957 /* Substitute the function name */ 1958 Replaceall(f->code, "$symname", symname); 1959 1960 /* Emit the function */ 1961 Wrapper_print(f, f_wrappers); 1962 1963 /* Now register the function with the interpreter */ 1964 if (!Swig_symbol_isoverloaded(n)) { 1965 create_command(n, symname); 1966 } else { 1967 if (current == CONSTRUCTOR_ALLOCATE) { 1968 create_command(n, symname); 1969 } else { 1970 if (!Getattr(n, "sym:nextSibling")) 1971 dispatchFunction(n); 1972 } 1973 } 1974 1975 Delete(kwargs); 1976 Delete(cleanup); 1977 Delete(outarg); 1978 DelWrapper(f); 1979 Delete(symname); 1980 1981 return SWIG_OK; 1982 } 1983 1984 /* ------------------------------------------------------------ 1985 * dispatchFunction() 1986 * ------------------------------------------------------------ */ 1987 1988 void dispatchFunction(Node *n) { 1989 /* Last node in overloaded chain */ 1990 1991 int maxargs; 1992 String *tmp = NewString(""); 1993 String *dispatch = Swig_overload_dispatch(n, "return %s(nargs, args, self);", &maxargs); 1994 1995 /* Generate a dispatch wrapper for all overloaded functions */ 1996 1997 Wrapper *f = NewWrapper(); 1998 String *symname = Getattr(n, "sym:name"); 1999 String *wname = Swig_name_wrapper(symname); 2000 2001 Printv(f->def, "SWIGINTERN VALUE ", wname, "(int nargs, VALUE *args, VALUE self) {", NIL); 2002 2003 Wrapper_add_local(f, "argc", "int argc"); 2004 bool ctor_director = (current == CONSTRUCTOR_INITIALIZE && Swig_directorclass(n)); 2005 if (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) { 2006 Printf(tmp, "VALUE argv[%d]", maxargs + 1); 2007 } else { 2008 Printf(tmp, "VALUE argv[%d]", maxargs); 2009 } 2010 Wrapper_add_local(f, "argv", tmp); 2011 Wrapper_add_local(f, "ii", "int ii"); 2012 2013 if (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) { 2014 maxargs += 1; 2015 Printf(f->code, "argc = nargs + 1;\n"); 2016 Printf(f->code, "argv[0] = self;\n"); 2017 Printf(f->code, "if (argc > %d) SWIG_fail;\n", maxargs); 2018 Printf(f->code, "for (ii = 1; (ii < argc); ++ii) {\n"); 2019 Printf(f->code, "argv[ii] = args[ii-1];\n"); 2020 Printf(f->code, "}\n"); 2021 } else { 2022 Printf(f->code, "argc = nargs;\n"); 2023 Printf(f->code, "if (argc > %d) SWIG_fail;\n", maxargs); 2024 Printf(f->code, "for (ii = 0; (ii < argc); ++ii) {\n"); 2025 Printf(f->code, "argv[ii] = args[ii];\n"); 2026 Printf(f->code, "}\n"); 2027 } 2028 2029 Replaceall(dispatch, "$args", "nargs, args, self"); 2030 Printv(f->code, dispatch, "\n", NIL); 2031 2032 2033 2034 // Generate prototype list, go to first node 2035 Node *sibl = n; 2036 2037 String* type = SwigType_str(Getattr(sibl,"type"),NULL); 2038 2039 while (Getattr(sibl, "sym:previousSibling")) 2040 sibl = Getattr(sibl, "sym:previousSibling"); // go all the way up 2041 2042 // Constructors will be treated specially 2043 const bool isCtor = Cmp(Getattr(sibl,"feature:new"), "1") == 0; 2044 const bool isMethod = ( Cmp(Getattr(sibl, "ismember"), "1") == 0 && 2045 (!isCtor) ); 2046 2047 // Construct real method name 2048 String* methodName = NewString(""); 2049 if ( isMethod ) 2050 Printv( methodName, Getattr(parentNode(sibl),"sym:name"), ".", NIL ); 2051 Append( methodName, Getattr(sibl,"sym:name" ) ); 2052 if ( isCtor ) Append( methodName, ".new" ); 2053 2054 // Generate prototype list 2055 String *protoTypes = NewString(""); 2056 do { 2057 Append( protoTypes, "\n\" "); 2058 if ( !isCtor ) Printv( protoTypes, type, " ", NIL ); 2059 Printv(protoTypes, methodName, NIL ); 2060 Parm* p = Getattr(sibl, "wrap:parms"); 2061 if (p && (current == MEMBER_FUNC || current == MEMBER_VAR || 2062 ctor_director) ) 2063 p = nextSibling(p); // skip self 2064 Append( protoTypes, "(" ); 2065 while(p) 2066 { 2067 Append( protoTypes, SwigType_str(Getattr(p,"type"), Getattr(p,"name")) ); 2068 if ( ( p = nextSibling(p)) ) Append(protoTypes, ", "); 2069 } 2070 Append( protoTypes, ")\\n\"" ); 2071 } while ((sibl = Getattr(sibl, "sym:nextSibling"))); 2072 2073 Append(f->code, "fail:\n"); 2074 Printf(f->code, "Ruby_Format_OverloadedError( argc, %d, \"%s\", %s);\n", 2075 maxargs, methodName, protoTypes); 2076 Append(f->code, "\nreturn Qnil;\n"); 2077 2078 Delete(methodName); 2079 Delete(type); 2080 Delete(protoTypes); 2081 2082 Printv(f->code, "}\n", NIL); 2083 Wrapper_print(f, f_wrappers); 2084 create_command(n, Char(symname)); 2085 2086 DelWrapper(f); 2087 Delete(dispatch); 2088 Delete(tmp); 2089 Delete(wname); 2090 } 2091 2092 /* --------------------------------------------------------------------- 2093 * variableWrapper() 2094 * --------------------------------------------------------------------- */ 2095 2096 virtual int variableWrapper(Node *n) { 2097 String* docs = docstring(n, AUTODOC_GETTER); 2098 Printf(f_wrappers, "%s", docs); 2099 Delete(docs); 2100 2101 2102 char *name = GetChar(n, "name"); 2103 char *iname = GetChar(n, "sym:name"); 2104 SwigType *t = Getattr(n, "type"); 2105 String *tm; 2106 String *getfname, *setfname; 2107 Wrapper *getf, *setf; 2108 2109 getf = NewWrapper(); 2110 setf = NewWrapper(); 2111 2112 /* create getter */ 2113 int addfail = 0; 2114 String *getname = Swig_name_get(iname); 2115 getfname = Swig_name_wrapper(getname); 2116 Setattr(n, "wrap:name", getfname); 2117 Printv(getf->def, "SWIGINTERN VALUE\n", getfname, "(", NIL); 2118 Printf(getf->def, "VALUE self"); 2119 Printf(getf->def, ") {"); 2120 Wrapper_add_local(getf, "_val", "VALUE _val"); 2121 2122 tm = Swig_typemap_lookup("varout", n, name, 0); 2123 if (tm) { 2124 Replaceall(tm, "$result", "_val"); 2125 Replaceall(tm, "$target", "_val"); 2126 Replaceall(tm, "$source", name); 2127 /* Printv(getf->code,tm, NIL); */ 2128 addfail = emit_action_code(n, getf->code, tm); 2129 } else { 2130 Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0)); 2131 } 2132 Printv(getf->code, tab4, "return _val;\n", NIL); 2133 if (addfail) { 2134 Append(getf->code, "fail:\n"); 2135 Append(getf->code, " return Qnil;\n"); 2136 } 2137 Append(getf->code, "}\n"); 2138 2139 Wrapper_print(getf, f_wrappers); 2140 2141 if (!is_assignable(n)) { 2142 setfname = NewString("NULL"); 2143 } else { 2144 /* create setter */ 2145 String* docs = docstring(n, AUTODOC_SETTER); 2146 Printf(f_wrappers, "%s", docs); 2147 Delete(docs); 2148 2149 String *setname = Swig_name_set(iname); 2150 setfname = Swig_name_wrapper(setname); 2151 Setattr(n, "wrap:name", setfname); 2152 Printv(setf->def, "SWIGINTERN VALUE\n", setfname, "(VALUE self, ", NIL); 2153 Printf(setf->def, "VALUE _val) {"); 2154 tm = Swig_typemap_lookup("varin", n, name, 0); 2155 if (tm) { 2156 Replaceall(tm, "$input", "_val"); 2157 Replaceall(tm, "$source", "_val"); 2158 Replaceall(tm, "$target", name); 2159 /* Printv(setf->code,tm,"\n",NIL); */ 2160 emit_action_code(n, setf->code, tm); 2161 } else { 2162 Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s\n", SwigType_str(t, 0)); 2163 } 2164 Printv(setf->code, tab4, "return _val;\n", NIL); 2165 Printf(setf->code, "fail:\n"); 2166 Printv(setf->code, tab4, "return Qnil;\n", NIL); 2167 Printf(setf->code, "}\n"); 2168 Wrapper_print(setf, f_wrappers); 2169 Delete(setname); 2170 } 2171 2172 /* define accessor method */ 2173 if (CPlusPlus) { 2174 Insert(getfname, 0, "VALUEFUNC("); 2175 Append(getfname, ")"); 2176 Insert(setfname, 0, "VALUEFUNC("); 2177 Append(setfname, ")"); 2178 } 2179 2180 String *s = NewString(""); 2181 switch (current) { 2182 case STATIC_VAR: 2183 /* C++ class variable */ 2184 Printv(s, tab4, "rb_define_singleton_method(", klass->vname, ", \"", klass->strip(iname), "\", ", getfname, ", 0);\n", NIL); 2185 if (!GetFlag(n, "feature:immutable")) { 2186 Printv(s, tab4, "rb_define_singleton_method(", klass->vname, ", \"", klass->strip(iname), "=\", ", setfname, ", 1);\n", NIL); 2187 } 2188 Printv(klass->init, s, NIL); 2189 break; 2190 default: 2191 /* C global variable */ 2192 /* wrapped in Ruby module attribute */ 2193 assert(current == NO_CPP); 2194 if (!useGlobalModule) { 2195 Printv(s, tab4, "rb_define_singleton_method(", modvar, ", \"", iname, "\", ", getfname, ", 0);\n", NIL); 2196 if (!GetFlag(n, "feature:immutable")) { 2197 Printv(s, tab4, "rb_define_singleton_method(", modvar, ", \"", iname, "=\", ", setfname, ", 1);\n", NIL); 2198 } 2199 } else { 2200 Printv(s, tab4, "rb_define_global_method(\"", iname, "\", ", getfname, ", 0);\n", NIL); 2201 if (!GetFlag(n, "feature:immutable")) { 2202 Printv(s, tab4, "rb_define_global_method(\"", iname, "=\", ", setfname, ", 1);\n", NIL); 2203 } 2204 } 2205 Printv(f_init, s, NIL); 2206 Delete(s); 2207 break; 2208 } 2209 Delete(getname); 2210 Delete(getfname); 2211 Delete(setfname); 2212 DelWrapper(setf); 2213 DelWrapper(getf); 2214 return SWIG_OK; 2215 } 2216 2217 2218 /* --------------------------------------------------------------------- 2219 * validate_const_name(char *name) 2220 * 2221 * Validate constant name. 2222 * --------------------------------------------------------------------- */ 2223 2224 char *validate_const_name(char *name, const char *reason) { 2225 if (!name || name[0] == '\0') 2226 return name; 2227 2228 if (isupper(name[0])) 2229 return name; 2230 2231 if (islower(name[0])) { 2232 name[0] = (char)toupper(name[0]); 2233 Swig_warning(WARN_RUBY_WRONG_NAME, input_file, line_number, "Wrong %s name (corrected to `%s')\n", reason, name); 2234 return name; 2235 } 2236 2237 Swig_warning(WARN_RUBY_WRONG_NAME, input_file, line_number, "Wrong %s name %s\n", reason, name); 2238 2239 return name; 2240 } 2241 2242 /* --------------------------------------------------------------------- 2243 * constantWrapper() 2244 * --------------------------------------------------------------------- */ 2245 2246 virtual int constantWrapper(Node *n) { 2247 Swig_require("constantWrapper", n, "*sym:name", "type", "value", NIL); 2248 2249 char *iname = GetChar(n, "sym:name"); 2250 SwigType *type = Getattr(n, "type"); 2251 String *rawval = Getattr(n, "rawval"); 2252 String *value = rawval ? rawval : Getattr(n, "value"); 2253 2254 if (current == CLASS_CONST) { 2255 iname = klass->strip(iname); 2256 } 2257 validate_const_name(iname, "constant"); 2258 SetChar(n, "sym:name", iname); 2259 2260 /* Special hook for member pointer */ 2261 if (SwigType_type(type) == T_MPOINTER) { 2262 String *wname = Swig_name_wrapper(iname); 2263 Printf(f_header, "static %s = %s;\n", SwigType_str(type, wname), value); 2264 value = Char(wname); 2265 } 2266 String *tm = Swig_typemap_lookup("constant", n, value, 0); 2267 if (!tm) 2268 tm = Swig_typemap_lookup("constcode", n, value, 0); 2269 if (tm) { 2270 Replaceall(tm, "$source", value); 2271 Replaceall(tm, "$target", iname); 2272 Replaceall(tm, "$symname", iname); 2273 Replaceall(tm, "$value", value); 2274 if (current == CLASS_CONST) { 2275 if (multipleInheritance) { 2276 Replaceall(tm, "$module", klass->mImpl); 2277 Printv(klass->init, tm, "\n", NIL); 2278 } else { 2279 Replaceall(tm, "$module", klass->vname); 2280 Printv(klass->init, tm, "\n", NIL); 2281 } 2282 } else { 2283 if (!useGlobalModule) { 2284 Replaceall(tm, "$module", modvar); 2285 } else { 2286 Replaceall(tm, "$module", "rb_cObject"); 2287 } 2288 Printf(f_init, "%s\n", tm); 2289 } 2290 } else { 2291 Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value %s = %s\n", SwigType_str(type, 0), value); 2292 } 2293 Swig_restore(n); 2294 return SWIG_OK; 2295 } 2296 2297 /* ----------------------------------------------------------------------------- 2298 * classDeclaration() 2299 * 2300 * Records information about classes---even classes that might be defined in 2301 * other modules referenced by %import. 2302 * ----------------------------------------------------------------------------- */ 2303 2304 virtual int classDeclaration(Node *n) { 2305 if (!Getattr(n, "feature:onlychildren")) { 2306 String *name = Getattr(n, "name"); 2307 String *symname = Getattr(n, "sym:name"); 2308 String *tdname = Getattr(n, "tdname"); 2309 2310 name = tdname ? tdname : name; 2311 String *namestr = SwigType_namestr(name); 2312 klass = RCLASS(classes, Char(namestr)); 2313 if (!klass) { 2314 klass = new RClass(); 2315 String *valid_name = NewString(symname ? symname : namestr); 2316 validate_const_name(Char(valid_name), "class"); 2317 klass->set_name(namestr, symname, valid_name); 2318 SET_RCLASS(classes, Char(namestr), klass); 2319 Delete(valid_name); 2320 } 2321 Delete(namestr); 2322 } 2323 return Language::classDeclaration(n); 2324 } 2325 2326 /** 2327 * Process the comma-separated list of mixed-in module names (if any). 2328 */ 2329 void includeRubyModules(Node *n) { 2330 String *mixin = Getattr(n, "feature:mixin"); 2331 if (mixin) { 2332 List *modules = Split(mixin, ',', INT_MAX); 2333 if (modules && Len(modules) > 0) { 2334 Iterator mod = First(modules); 2335 while (mod.item) { 2336 if (Len(mod.item) > 0) { 2337 Printf(klass->init, "rb_include_module(%s, rb_eval_string(\"%s\"));\n", klass->vname, mod.item); 2338 } 2339 mod = Next(mod); 2340 } 2341 } 2342 Delete(modules); 2343 } 2344 } 2345 2346 void handleBaseClasses(Node *n) { 2347 List *baselist = Getattr(n, "bases"); 2348 if (baselist && Len(baselist)) { 2349 Iterator base = First(baselist); 2350 while (base.item && GetFlag(base.item, "feature:ignore")) { 2351 base = Next(base); 2352 } 2353 while (base.item) { 2354 String *basename = Getattr(base.item, "name"); 2355 String *basenamestr = SwigType_namestr(basename); 2356 RClass *super = RCLASS(classes, Char(basenamestr)); 2357 Delete(basenamestr); 2358 if (super) { 2359 SwigType *btype = NewString(basename); 2360 SwigType_add_pointer(btype); 2361 SwigType_remember(btype); 2362 if (multipleInheritance) { 2363 String *bmangle = SwigType_manglestr(btype); 2364 Insert(bmangle, 0, "((swig_class *) SWIGTYPE"); 2365 Append(bmangle, "->clientdata)->mImpl"); 2366 Printv(klass->init, "rb_include_module(", klass->mImpl, ", ", bmangle, ");\n", NIL); 2367 Delete(bmangle); 2368 } else { 2369 String *bmangle = SwigType_manglestr(btype); 2370 Insert(bmangle, 0, "((swig_class *) SWIGTYPE"); 2371 Append(bmangle, "->clientdata)->klass"); 2372 Replaceall(klass->init, "$super", bmangle); 2373 Delete(bmangle); 2374 } 2375 Delete(btype); 2376 } 2377 base = Next(base); 2378 while (base.item && GetFlag(base.item, "feature:ignore")) { 2379 base = Next(base); 2380 } 2381 if (!multipleInheritance) { 2382 /* Warn about multiple inheritance for additional base class(es) */ 2383 while (base.item) { 2384 if (GetFlag(base.item, "feature:ignore")) { 2385 base = Next(base); 2386 continue; 2387 } 2388 String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0); 2389 String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0); 2390 Swig_warning(WARN_RUBY_MULTIPLE_INHERITANCE, input_file, line_number, 2391 "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Ruby.\n", proxyclassname, baseclassname); 2392 base = Next(base); 2393 } 2394 } 2395 } 2396 } 2397 } 2398 2399 /** 2400 * Check to see if a %markfunc was specified. 2401 */ 2402 void handleMarkFuncDirective(Node *n) { 2403 String *markfunc = Getattr(n, "feature:markfunc"); 2404 if (markfunc) { 2405 Printf(klass->init, "SwigClass%s.mark = (void (*)(void *)) %s;\n", klass->name, markfunc); 2406 } else { 2407 Printf(klass->init, "SwigClass%s.mark = 0;\n", klass->name); 2408 } 2409 } 2410 2411 /** 2412 * Check to see if a %freefunc was specified. 2413 */ 2414 void handleFreeFuncDirective(Node *n) { 2415 String *freefunc = Getattr(n, "feature:freefunc"); 2416 if (freefunc) { 2417 Printf(klass->init, "SwigClass%s.destroy = (void (*)(void *)) %s;\n", klass->name, freefunc); 2418 } else { 2419 if (klass->destructor_defined) { 2420 Printf(klass->init, "SwigClass%s.destroy = (void (*)(void *)) free_%s;\n", klass->name, klass->mname); 2421 } 2422 } 2423 } 2424 2425 /** 2426 * Check to see if tracking is enabled for this class. 2427 */ 2428 void handleTrackDirective(Node *n) { 2429 int trackObjects = GetFlag(n, "feature:trackobjects"); 2430 if (trackObjects) { 2431 Printf(klass->init, "SwigClass%s.trackObjects = 1;\n", klass->name); 2432 } else { 2433 Printf(klass->init, "SwigClass%s.trackObjects = 0;\n", klass->name); 2434 } 2435 } 2436 2437 /* ---------------------------------------------------------------------- 2438 * classHandler() 2439 * ---------------------------------------------------------------------- */ 2440 2441 virtual int classHandler(Node *n) { 2442 String* docs = docstring(n, AUTODOC_CLASS); 2443 Printf(f_wrappers, "%s", docs); 2444 Delete(docs); 2445 2446 String *name = Getattr(n, "name"); 2447 String *symname = Getattr(n, "sym:name"); 2448 String *namestr = SwigType_namestr(name); // does template expansion 2449 2450 klass = RCLASS(classes, Char(namestr)); 2451 assert(klass != 0); 2452 Delete(namestr); 2453 String *valid_name = NewString(symname); 2454 validate_const_name(Char(valid_name), "class"); 2455 2456 Clear(klass->type); 2457 Printv(klass->type, Getattr(n, "classtype"), NIL); 2458 Printv(f_wrappers, "swig_class SwigClass", valid_name, ";\n\n", NIL); 2459 Printv(klass->init, "\n", tab4, NIL); 2460 2461 if (!useGlobalModule) { 2462 Printv(klass->init, klass->vname, " = rb_define_class_under(", modvar, ", \"", klass->name, "\", $super);\n", NIL); 2463 } else { 2464 Printv(klass->init, klass->vname, " = rb_define_class(\"", klass->name, 2465 "\", $super);\n", NIL); 2466 } 2467 2468 if (multipleInheritance) { 2469 Printv(klass->init, klass->mImpl, " = rb_define_module_under(", klass->vname, ", \"Impl\");\n", NIL); 2470 } 2471 2472 SwigType *tt = NewString(name); 2473 SwigType_add_pointer(tt); 2474 SwigType_remember(tt); 2475 String *tm = SwigType_manglestr(tt); 2476 Printf(klass->init, "SWIG_TypeClientData(SWIGTYPE%s, (void *) &SwigClass%s);\n", tm, valid_name); 2477 Delete(tm); 2478 Delete(tt); 2479 Delete(valid_name); 2480 2481 includeRubyModules(n); 2482 2483 Printv(klass->init, "$allocator", NIL); 2484 Printv(klass->init, "$initializer", NIL); 2485 2486 Language::classHandler(n); 2487 2488 handleBaseClasses(n); 2489 handleMarkFuncDirective(n); 2490 handleFreeFuncDirective(n); 2491 handleTrackDirective(n); 2492 2493 if (multipleInheritance) { 2494 Printv(klass->init, "rb_include_module(", klass->vname, ", ", klass->mImpl, ");\n", NIL); 2495 } 2496 2497 String *s = NewString(""); 2498 Printv(s, tab4, "rb_undef_alloc_func(", klass->vname, ");\n", NIL); 2499 Replaceall(klass->init, "$allocator", s); 2500 Replaceall(klass->init, "$initializer", ""); 2501 2502 if (GetFlag(n, "feature:exceptionclass")) { 2503 Replaceall(klass->init, "$super", "rb_eRuntimeError"); 2504 } else { 2505 Replaceall(klass->init, "$super", "rb_cObject"); 2506 } 2507 Delete(s); 2508 2509 Printv(f_init, klass->init, NIL); 2510 klass = 0; 2511 return SWIG_OK; 2512 } 2513 2514 /* ---------------------------------------------------------------------- 2515 * memberfunctionHandler() 2516 * 2517 * Method for adding C++ member function 2518 * 2519 * By default, we're going to create a function of the form : 2520 * 2521 * Foo_bar(this,args) 2522 * 2523 * Where Foo is the classname, bar is the member name and the this pointer 2524 * is explicitly attached to the beginning. 2525 * 2526 * The renaming only applies to the member function part, not the full 2527 * classname. 2528 * 2529 * --------------------------------------------------------------------- */ 2530 2531 virtual int memberfunctionHandler(Node *n) { 2532 current = MEMBER_FUNC; 2533 2534 String* docs = docstring(n, AUTODOC_METHOD); 2535 Printf(f_wrappers, "%s", docs); 2536 Delete(docs); 2537 2538 Language::memberfunctionHandler(n); 2539 current = NO_CPP; 2540 return SWIG_OK; 2541 } 2542 2543 /* --------------------------------------------------------------------- 2544 * constructorHandler() 2545 * 2546 * Method for adding C++ member constructor 2547 * -------------------------------------------------------------------- */ 2548 2549 void set_director_ctor_code(Node *n) { 2550 /* director ctor code is specific for each class */ 2551 Delete(director_prot_ctor_code); 2552 director_prot_ctor_code = NewString(""); 2553 Node *pn = Swig_methodclass(n); 2554 String *symname = Getattr(pn, "sym:name"); 2555 String *name = Copy(symname); 2556 char *cname = Char(name); 2557 if (cname) 2558 cname[0] = (char)toupper(cname[0]); 2559 Printv(director_prot_ctor_code, 2560 "if ( $comparison ) { /* subclassed */\n", 2561 " $director_new \n", 2562 "} else {\n", " rb_raise(rb_eNameError,\"accessing abstract class or protected constructor\"); \n", " return Qnil;\n", "}\n", NIL); 2563 Delete(director_ctor_code); 2564 director_ctor_code = NewString(""); 2565 Printv(director_ctor_code, "if ( $comparison ) { /* subclassed */\n", " $director_new \n", "} else {\n", " $nondirector_new \n", "}\n", NIL); 2566 Delete(name); 2567 } 2568 2569 virtual int constructorHandler(Node *n) { 2570 int use_director = Swig_directorclass(n); 2571 if (use_director) { 2572 set_director_ctor_code(n); 2573 } 2574 2575 /* First wrap the allocate method */ 2576 current = CONSTRUCTOR_ALLOCATE; 2577 Swig_name_register((const_String_or_char_ptr ) "construct", (const_String_or_char_ptr ) "%c_allocate"); 2578 2579 2580 Language::constructorHandler(n); 2581 2582 /* 2583 * If we're wrapping the constructor of a C++ director class, prepend a new parameter 2584 * to receive the scripting language object (e.g. 'self') 2585 * 2586 */ 2587 Swig_save("ruby:constructorHandler", n, "parms", NIL); 2588 if (use_director) { 2589 Parm *parms = Getattr(n, "parms"); 2590 Parm *self; 2591 String *name = NewString("self"); 2592 String *type = NewString("VALUE"); 2593 self = NewParm(type, name); 2594 Delete(type); 2595 Delete(name); 2596 Setattr(self, "lname", "Qnil"); 2597 if (parms) 2598 set_nextSibling(self, parms); 2599 Setattr(n, "parms", self); 2600 Setattr(n, "wrap:self", "1"); 2601 Delete(self); 2602 } 2603 2604 2605 2606 /* Now do the instance initialize method */ 2607 String* docs = docstring(n, AUTODOC_CTOR); 2608 Printf(f_wrappers, "%s", docs); 2609 Delete(docs); 2610 2611 current = CONSTRUCTOR_INITIALIZE; 2612 Swig_name_register((const_String_or_char_ptr ) "construct", (const_String_or_char_ptr ) "new_%c"); 2613 Language::constructorHandler(n); 2614 2615 /* Restore original parameter list */ 2616 Delattr(n, "wrap:self"); 2617 Swig_restore(n); 2618 2619 /* Done */ 2620 Swig_name_unregister((const_String_or_char_ptr ) "construct"); 2621 current = NO_CPP; 2622 klass->constructor_defined = 1; 2623 return SWIG_OK; 2624 } 2625 2626 virtual int copyconstructorHandler(Node *n) { 2627 int use_director = Swig_directorclass(n); 2628 if (use_director) { 2629 set_director_ctor_code(n); 2630 } 2631 2632 /* First wrap the allocate method */ 2633 current = CONSTRUCTOR_ALLOCATE; 2634 Swig_name_register((const_String_or_char_ptr ) "construct", (const_String_or_char_ptr ) "%c_allocate"); 2635 2636 return Language::copyconstructorHandler(n); 2637 } 2638 2639 2640 /* --------------------------------------------------------------------- 2641 * destructorHandler() 2642 * -------------------------------------------------------------------- */ 2643 2644 virtual int destructorHandler(Node *n) { 2645 2646 /* Do no spit free function if user defined his own for this class */ 2647 Node *pn = Swig_methodclass(n); 2648 String *freefunc = Getattr(pn, "feature:freefunc"); 2649 if (freefunc) return SWIG_OK; 2650 2651 current = DESTRUCTOR; 2652 Language::destructorHandler(n); 2653 2654 freefunc = NewString(""); 2655 String *freebody = NewString(""); 2656 String *pname0 = Swig_cparm_name(0, 0); 2657 2658 Printv(freefunc, "free_", klass->mname, NIL); 2659 Printv(freebody, "SWIGINTERN void\n", freefunc, "(", klass->type, " *", pname0, ") {\n", tab4, NIL); 2660 2661 /* Check to see if object tracking is activated for the class 2662 that owns this destructor. */ 2663 if (GetFlag(pn, "feature:trackobjects")) { 2664 Printf(freebody, "SWIG_RubyRemoveTracking(%s);\n", pname0); 2665 Printv(freebody, tab4, NIL); 2666 } 2667 2668 if (Extend) { 2669 String *wrap = Getattr(n, "wrap:code"); 2670 if (wrap) { 2671 Printv(f_wrappers, wrap, NIL); 2672 } 2673 /* Printv(freebody, Swig_name_destroy(name), "(", pname0, ")", NIL); */ 2674 Printv(freebody, Getattr(n, "wrap:action"), "\n", NIL); 2675 } else { 2676 String *action = Getattr(n, "wrap:action"); 2677 if (action) { 2678 Printv(freebody, action, "\n", NIL); 2679 } else { 2680 /* In the case swig emits no destroy function. */ 2681 if (CPlusPlus) 2682 Printf(freebody, "delete %s;\n", pname0); 2683 else 2684 Printf(freebody, "free((char*) %s);\n", pname0); 2685 } 2686 } 2687 2688 Printv(freebody, "}\n\n", NIL); 2689 2690 Printv(f_wrappers, freebody, NIL); 2691 2692 klass->destructor_defined = 1; 2693 current = NO_CPP; 2694 Delete(freefunc); 2695 Delete(freebody); 2696 Delete(pname0); 2697 return SWIG_OK; 2698 } 2699 2700 /* --------------------------------------------------------------------- 2701 * membervariableHandler() 2702 * 2703 * This creates a pair of functions to set/get the variable of a member. 2704 * -------------------------------------------------------------------- */ 2705 2706 virtual int membervariableHandler(Node *n) { 2707 String* docs = docstring(n, AUTODOC_GETTER); 2708 Printf(f_wrappers, "%s", docs); 2709 Delete(docs); 2710 2711 if (is_assignable(n)) { 2712 String* docs = docstring(n, AUTODOC_SETTER); 2713 Printf(f_wrappers, "%s", docs); 2714 Delete(docs); 2715 } 2716 2717 current = MEMBER_VAR; 2718 Language::membervariableHandler(n); 2719 current = NO_CPP; 2720 return SWIG_OK; 2721 } 2722 2723 /* ----------------------------------------------------------------------- 2724 * staticmemberfunctionHandler() 2725 * 2726 * Wrap a static C++ function 2727 * ---------------------------------------------------------------------- */ 2728 2729 virtual int staticmemberfunctionHandler(Node *n) { 2730 String* docs = docstring(n, AUTODOC_STATICFUNC); 2731 Printf(f_wrappers, "%s", docs); 2732 Delete(docs); 2733 2734 current = STATIC_FUNC; 2735 Language::staticmemberfunctionHandler(n); 2736 current = NO_CPP; 2737 return SWIG_OK; 2738 } 2739 2740 /* ---------------------------------------------------------------------- 2741 * memberconstantHandler() 2742 * 2743 * Create a C++ constant 2744 * --------------------------------------------------------------------- */ 2745 2746 virtual int memberconstantHandler(Node *n) { 2747 String* docs = docstring(n, AUTODOC_STATICFUNC); 2748 Printf(f_wrappers, "%s", docs); 2749 Delete(docs); 2750 2751 current = CLASS_CONST; 2752 Language::memberconstantHandler(n); 2753 current = NO_CPP; 2754 return SWIG_OK; 2755 } 2756 2757 /* --------------------------------------------------------------------- 2758 * staticmembervariableHandler() 2759 * --------------------------------------------------------------------- */ 2760 2761 virtual int staticmembervariableHandler(Node *n) { 2762 String* docs = docstring(n, AUTODOC_GETTER); 2763 Printf(f_wrappers, "%s", docs); 2764 Delete(docs); 2765 2766 if (is_assignable(n)) { 2767 String* docs = docstring(n, AUTODOC_SETTER); 2768 Printf(f_wrappers, "%s", docs); 2769 Delete(docs); 2770 } 2771 2772 current = STATIC_VAR; 2773 Language::staticmembervariableHandler(n); 2774 current = NO_CPP; 2775 return SWIG_OK; 2776 } 2777 2778 /* C++ director class generation */ 2779 virtual int classDirector(Node *n) { 2780 return Language::classDirector(n); 2781 } 2782 2783 virtual int classDirectorInit(Node *n) { 2784 String *declaration; 2785 declaration = Swig_director_declaration(n); 2786 Printf(f_directors_h, "\n"); 2787 Printf(f_directors_h, "%s\n", declaration); 2788 Printf(f_directors_h, "public:\n"); 2789 Delete(declaration); 2790 return Language::classDirectorInit(n); 2791 } 2792 2793 virtual int classDirectorEnd(Node *n) { 2794 Printf(f_directors_h, "};\n\n"); 2795 return Language::classDirectorEnd(n); 2796 } 2797 2798 /* ------------------------------------------------------------ 2799 * classDirectorConstructor() 2800 * ------------------------------------------------------------ */ 2801 2802 virtual int classDirectorConstructor(Node *n) { 2803 Node *parent = Getattr(n, "parentNode"); 2804 String *sub = NewString(""); 2805 String *decl = Getattr(n, "decl"); 2806 String *supername = Swig_class_name(parent); 2807 String *classname = NewString(""); 2808 Printf(classname, "SwigDirector_%s", supername); 2809 2810 /* insert self parameter */ 2811 Parm *p; 2812 ParmList *superparms = Getattr(n, "parms"); 2813 ParmList *parms = CopyParmList(superparms); 2814 String *type = NewString("VALUE"); 2815 p = NewParm(type, NewString("self")); 2816 set_nextSibling(p, parms); 2817 parms = p; 2818 2819 if (!Getattr(n, "defaultargs")) { 2820 /* constructor */ 2821 { 2822 Wrapper *w = NewWrapper(); 2823 String *call; 2824 String *basetype = Getattr(parent, "classtype"); 2825 String *target = Swig_method_decl(0, decl, classname, parms, 0, 0); 2826 call = Swig_csuperclass_call(0, basetype, superparms); 2827 Printf(w->def, "%s::%s: %s, Swig::Director(self) { }", classname, target, call); 2828 Delete(target); 2829 Wrapper_print(w, f_directors); 2830 Delete(call); 2831 DelWrapper(w); 2832 } 2833 2834 /* constructor header */ 2835 { 2836 String *target = Swig_method_decl(0, decl, classname, parms, 0, 1); 2837 Printf(f_directors_h, " %s;\n", target); 2838 Delete(target); 2839 } 2840 } 2841 2842 Delete(sub); 2843 Delete(classname); 2844 Delete(supername); 2845 Delete(parms); 2846 return Language::classDirectorConstructor(n); 2847 } 2848 2849 /* ------------------------------------------------------------ 2850 * classDirectorDefaultConstructor() 2851 * ------------------------------------------------------------ */ 2852 2853 virtual int classDirectorDefaultConstructor(Node *n) { 2854 String *classname; 2855 Wrapper *w; 2856 classname = Swig_class_name(n); 2857 w = NewWrapper(); 2858 Printf(w->def, "SwigDirector_%s::SwigDirector_%s(VALUE self) : Swig::Director(self) { }", classname, classname); 2859 Wrapper_print(w, f_directors); 2860 DelWrapper(w); 2861 Printf(f_directors_h, " SwigDirector_%s(VALUE self);\n", classname); 2862 Delete(classname); 2863 return Language::classDirectorDefaultConstructor(n); 2864 } 2865 2866 /* --------------------------------------------------------------- 2867 * exceptionSafeMethodCall() 2868 * 2869 * Emit a virtual director method to pass a method call on to the 2870 * underlying Ruby instance. 2871 * 2872 * --------------------------------------------------------------- */ 2873 2874 void exceptionSafeMethodCall(String *className, Node *n, Wrapper *w, int argc, String *args, bool initstack) { 2875 Wrapper *body = NewWrapper(); 2876 Wrapper *rescue = NewWrapper(); 2877 2878 String *methodName = Getattr(n, "sym:name"); 2879 2880 String *bodyName = NewStringf("%s_%s_body", className, methodName); 2881 String *rescueName = NewStringf("%s_%s_rescue", className, methodName); 2882 String *depthCountName = NewStringf("%s_%s_call_depth", className, methodName); 2883 2884 // Check for an exception typemap of some kind 2885 String *tm = Swig_typemap_lookup("director:except", n, "result", 0); 2886 if (!tm) { 2887 tm = Getattr(n, "feature:director:except"); 2888 } 2889 2890 if ((tm != 0) && (Len(tm) > 0) && (Strcmp(tm, "1") != 0)) { 2891 // Declare a global to hold the depth count 2892 if (!Getattr(n, "sym:nextSibling")) { 2893 Printf(body->def, "static int %s = 0;\n", depthCountName); 2894 2895 // Function body 2896 Printf(body->def, "VALUE %s(VALUE data) {\n", bodyName); 2897 Wrapper_add_localv(body, "args", "Swig::body_args *", "args", "= reinterpret_cast<Swig::body_args *>(data)", NIL); 2898 Wrapper_add_localv(body, "result", "VALUE", "result", "= Qnil", NIL); 2899 Printf(body->code, "%s++;\n", depthCountName); 2900 Printv(body->code, "result = rb_funcall2(args->recv, args->id, args->argc, args->argv);\n", NIL); 2901 Printf(body->code, "%s--;\n", depthCountName); 2902 Printv(body->code, "return result;\n", NIL); 2903 Printv(body->code, "}", NIL); 2904 2905 // Exception handler 2906 Printf(rescue->def, "VALUE %s(VALUE args, VALUE error) {\n", rescueName); 2907 Replaceall(tm, "$error", "error"); 2908 Printf(rescue->code, "%s--;\n", depthCountName); 2909 Printf(rescue->code, "if (%s == 0) ", depthCountName); 2910 Printv(rescue->code, Str(tm), "\n", NIL); 2911 Printv(rescue->code, "rb_exc_raise(error);\n", NIL); 2912 Printv(rescue->code, "}", NIL); 2913 } 2914 2915 // Main code 2916 Wrapper_add_localv(w, "args", "Swig::body_args", "args", NIL); 2917 Wrapper_add_localv(w, "status", "int", "status", NIL); 2918 Printv(w->code, "args.recv = swig_get_self();\n", NIL); 2919 Printf(w->code, "args.id = rb_intern(\"%s\");\n", methodName); 2920 Printf(w->code, "args.argc = %d;\n", argc); 2921 if (argc > 0) { 2922 Printf(w->code, "args.argv = new VALUE[%d];\n", argc); 2923 for (int i = 0; i < argc; i++) { 2924 Printf(w->code, "args.argv[%d] = obj%d;\n", i, i); 2925 } 2926 } else { 2927 Printv(w->code, "args.argv = 0;\n", NIL); 2928 } 2929 Printf(w->code, "result = rb_protect(PROTECTFUNC(%s), reinterpret_cast<VALUE>(&args), &status);\n", bodyName); 2930 if ( initstack ) Printf(w->code, "SWIG_RELEASE_STACK;\n"); 2931 Printf(w->code, "if (status) {\n"); 2932 Printf(w->code, "VALUE lastErr = rb_gv_get(\"$!\");\n"); 2933 Printf(w->code, "%s(reinterpret_cast<VALUE>(&args), lastErr);\n", rescueName); 2934 Printf(w->code, "}\n"); 2935 if (argc > 0) { 2936 Printv(w->code, "delete [] args.argv;\n", NIL); 2937 } 2938 // Dump wrapper code 2939 Wrapper_print(body, f_directors_helpers); 2940 Wrapper_print(rescue, f_directors_helpers); 2941 } else { 2942 if (argc > 0) { 2943 Printf(w->code, "result = rb_funcall(swig_get_self(), rb_intern(\"%s\"), %d%s);\n", methodName, argc, args); 2944 } else { 2945 Printf(w->code, "result = rb_funcall(swig_get_self(), rb_intern(\"%s\"), 0, NULL);\n", methodName); 2946 } 2947 if ( initstack ) Printf(w->code, "SWIG_RELEASE_STACK;\n"); 2948 } 2949 2950 // Clean up 2951 Delete(bodyName); 2952 Delete(rescueName); 2953 Delete(depthCountName); 2954 DelWrapper(body); 2955 DelWrapper(rescue); 2956 } 2957 2958 virtual int classDirectorMethod(Node *n, Node *parent, String *super) { 2959 int is_void = 0; 2960 int is_pointer = 0; 2961 String *decl; 2962 String *type; 2963 String *name; 2964 String *classname; 2965 String *c_classname = Getattr(parent, "name"); 2966 String *declaration; 2967 ParmList *l; 2968 Wrapper *w; 2969 String *tm; 2970 String *wrap_args = NewString(""); 2971 String *return_type; 2972 Parm *p; 2973 String *value = Getattr(n, "value"); 2974 String *storage = Getattr(n, "storage"); 2975 bool pure_virtual = false; 2976 int status = SWIG_OK; 2977 int idx; 2978 bool ignored_method = GetFlag(n, "feature:ignore") ? true : false; 2979 bool asvoid = checkAttribute( n, "feature:numoutputs", "0") ? true : false; 2980 bool initstack = checkAttribute( n, "feature:initstack", "1") ? true : false; 2981 2982 if (Cmp(storage, "virtual") == 0) { 2983 if (Cmp(value, "0") == 0) { 2984 pure_virtual = true; 2985 } 2986 } 2987 String *overnametmp = NewString(Getattr(n, "sym:name")); 2988 if (Getattr(n, "sym:overloaded")) { 2989 Printf(overnametmp, "::%s", Getattr(n, "sym:overname")); 2990 } 2991 2992 classname = Getattr(parent, "sym:name"); 2993 type = Getattr(n, "type"); 2994 name = Getattr(n, "name"); 2995 2996 w = NewWrapper(); 2997 declaration = NewString(""); 2998 2999 /* determine if the method returns a pointer */ 3000 decl = Getattr(n, "decl"); 3001 is_pointer = SwigType_ispointer_return(decl); 3002 is_void = (!Cmp(type, "void") && !is_pointer); 3003 3004 /* form complete return type */ 3005 return_type = Copy(type); 3006 { 3007 SwigType *t = Copy(decl); 3008 SwigType *f = 0; 3009 f = SwigType_pop_function(t); 3010 SwigType_push(return_type, t); 3011 Delete(f); 3012 Delete(t); 3013 } 3014 3015 /* virtual method definition */ 3016 l = Getattr(n, "parms"); 3017 String *target; 3018 String *pclassname = NewStringf("SwigDirector_%s", classname); 3019 String *qualified_name = NewStringf("%s::%s", pclassname, name); 3020 SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : type; 3021 target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0); 3022 Printf(w->def, "%s", target); 3023 Delete(qualified_name); 3024 Delete(target); 3025 /* header declaration */ 3026 target = Swig_method_decl(rtype, decl, name, l, 0, 1); 3027 Printf(declaration, " virtual %s", target); 3028 Delete(target); 3029 3030 // Get any exception classes in the throws typemap 3031 ParmList *throw_parm_list = 0; 3032 3033 if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { 3034 Parm *p; 3035 int gencomma = 0; 3036 3037 Append(w->def, " throw("); 3038 Append(declaration, " throw("); 3039 3040 if (throw_parm_list) 3041 Swig_typemap_attach_parms("throws", throw_parm_list, 0); 3042 for (p = throw_parm_list; p; p = nextSibling(p)) { 3043 if ((tm = Getattr(p, "tmap:throws"))) { 3044 if (gencomma++) { 3045 Append(w->def, ", "); 3046 Append(declaration, ", "); 3047 } 3048 3049 Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0)); 3050 Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0)); 3051 } 3052 } 3053 3054 Append(w->def, ")"); 3055 Append(declaration, ")"); 3056 } 3057 3058 Append(w->def, " {"); 3059 Append(declaration, ";\n"); 3060 3061 if (initstack && !(ignored_method && !pure_virtual)) { 3062 Append(w->def, "\nSWIG_INIT_STACK;\n"); 3063 } 3064 3065 /* declare method return value 3066 * if the return value is a reference or const reference, a specialized typemap must 3067 * handle it, including declaration of c_result ($result). 3068 */ 3069 if (!is_void) { 3070 if (!(ignored_method && !pure_virtual)) { 3071 Wrapper_add_localv(w, "c_result", SwigType_lstr(return_type, "c_result"), NIL); 3072 } 3073 } 3074 3075 if (ignored_method) { 3076 if (!pure_virtual) { 3077 if (!is_void) 3078 Printf(w->code, "return "); 3079 String *super_call = Swig_method_call(super, l); 3080 Printf(w->code, "%s;\n", super_call); 3081 Delete(super_call); 3082 } else { 3083 Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname), 3084 SwigType_namestr(name)); 3085 } 3086 } else { 3087 /* attach typemaps to arguments (C/C++ -> Ruby) */ 3088 String *arglist = NewString(""); 3089 3090 /** 3091 * For each parameter to the C++ member function, copy the parameter name 3092 * to its "lname"; this ensures that Swig_typemap_attach_parms() will do 3093 * the right thing when it sees strings like "$1" in your "directorin" typemaps. 3094 * Not sure if it's OK to leave it like this, but seems OK so far. 3095 */ 3096 typemap_copy_pname_to_lname(l); 3097 3098 Swig_typemap_attach_parms("in", l, 0); 3099 Swig_typemap_attach_parms("directorin", l, 0); 3100 Swig_typemap_attach_parms("directorargout", l, w); 3101 3102 char source[256]; 3103 3104 int outputs = 0; 3105 if (!is_void && !asvoid) 3106 outputs++; 3107 3108 /* build argument list and type conversion string */ 3109 idx = 0; p = l; 3110 while ( p ) { 3111 3112 if (Getattr(p, "tmap:ignore")) { 3113 p = Getattr(p, "tmap:ignore:next"); 3114 continue; 3115 } 3116 3117 if (Getattr(p, "tmap:directorargout") != 0) 3118 outputs++; 3119 3120 if ( checkAttribute( p, "tmap:in:numinputs", "0") ) 3121 { 3122 p = Getattr(p, "tmap:in:next"); 3123 continue; 3124 } 3125 3126 String *parameterName = Getattr(p, "name"); 3127 String *parameterType = Getattr(p, "type"); 3128 3129 Putc(',', arglist); 3130 if ((tm = Getattr(p, "tmap:directorin")) != 0) { 3131 sprintf(source, "obj%d", idx++); 3132 Replaceall(tm, "$input", source); 3133 Replaceall(tm, "$owner", "0"); 3134 Printv(wrap_args, tm, "\n", NIL); 3135 Wrapper_add_localv(w, source, "VALUE", source, "= Qnil", NIL); 3136 Printv(arglist, source, NIL); 3137 p = Getattr(p, "tmap:directorin:next"); 3138 continue; 3139 } else if (Cmp(parameterType, "void")) { 3140 /** 3141 * Special handling for pointers to other C++ director classes. 3142 * Ideally this would be left to a typemap, but there is currently no 3143 * way to selectively apply the dynamic_cast<> to classes that have 3144 * directors. In other words, the type "SwigDirector_$1_lname" only exists 3145 * for classes with directors. We avoid the problem here by checking 3146 * module.wrap::directormap, but it's not clear how to get a typemap to 3147 * do something similar. Perhaps a new default typemap (in addition 3148 * to SWIGTYPE) called DIRECTORTYPE? 3149 */ 3150 if (SwigType_ispointer(parameterType) || SwigType_isreference(parameterType)) { 3151 Node *modname = Getattr(parent, "module"); 3152 Node *target = Swig_directormap(modname, parameterType); 3153 sprintf(source, "obj%d", idx++); 3154 String *nonconst = 0; 3155 /* strip pointer/reference --- should move to Swig/stype.c */ 3156 String *nptype = NewString(Char(parameterType) + 2); 3157 /* name as pointer */ 3158 String *ppname = Copy(parameterName); 3159 if (SwigType_isreference(parameterType)) { 3160 Insert(ppname, 0, "&"); 3161 } 3162 /* if necessary, cast away const since Ruby doesn't support it! */ 3163 if (SwigType_isconst(nptype)) { 3164 nonconst = NewStringf("nc_tmp_%s", parameterName); 3165 String *nonconst_i = NewStringf("= const_cast<%s>(%s)", SwigType_lstr(parameterType, 0), ppname); 3166 Wrapper_add_localv(w, nonconst, SwigType_lstr(parameterType, 0), nonconst, nonconst_i, NIL); 3167 Delete(nonconst_i); 3168 Swig_warning(WARN_LANG_DISCARD_CONST, input_file, line_number, 3169 "Target language argument '%s' discards const in director method %s::%s.\n", SwigType_str(parameterType, parameterName), 3170 SwigType_namestr(c_classname), SwigType_namestr(name)); 3171 } else { 3172 nonconst = Copy(ppname); 3173 } 3174 Delete(nptype); 3175 Delete(ppname); 3176 String *mangle = SwigType_manglestr(parameterType); 3177 if (target) { 3178 String *director = NewStringf("director_%s", mangle); 3179 Wrapper_add_localv(w, director, "Swig::Director *", director, "= 0", NIL); 3180 Wrapper_add_localv(w, source, "VALUE", source, "= Qnil", NIL); 3181 Printf(wrap_args, "%s = dynamic_cast<Swig::Director *>(%s);\n", director, nonconst); 3182 Printf(wrap_args, "if (!%s) {\n", director); 3183 Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle); 3184 Printf(wrap_args, "} else {\n"); 3185 Printf(wrap_args, "%s = %s->swig_get_self();\n", source, director); 3186 Printf(wrap_args, "}\n"); 3187 Delete(director); 3188 Printv(arglist, source, NIL); 3189 } else { 3190 Wrapper_add_localv(w, source, "VALUE", source, "= Qnil", NIL); 3191 Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle); 3192 //Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE_p_%s, 0);\n", 3193 // source, nonconst, base); 3194 Printv(arglist, source, NIL); 3195 } 3196 Delete(mangle); 3197 Delete(nonconst); 3198 } else { 3199 Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number, 3200 "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(parameterType, 0), 3201 SwigType_namestr(c_classname), SwigType_namestr(name)); 3202 status = SWIG_NOWRAP; 3203 break; 3204 } 3205 } 3206 p = nextSibling(p); 3207 } 3208 3209 /* declare Ruby return value */ 3210 Wrapper_add_local(w, "result", "VALUE result"); 3211 3212 /* wrap complex arguments to VALUEs */ 3213 Printv(w->code, wrap_args, NIL); 3214 3215 /* pass the method call on to the Ruby object */ 3216 exceptionSafeMethodCall(classname, n, w, idx, arglist, initstack); 3217 3218 /* 3219 * Ruby method may return a simple object, or an Array of objects. 3220 * For in/out arguments, we have to extract the appropriate VALUEs from the Array, 3221 * then marshal everything back to C/C++ (return value and output arguments). 3222 */ 3223 3224 /* Marshal return value and other outputs (if any) from VALUE to C/C++ type */ 3225 3226 String *cleanup = NewString(""); 3227 String *outarg = NewString(""); 3228 3229 if (outputs > 1) { 3230 Wrapper_add_local(w, "output", "VALUE output"); 3231 Printf(w->code, "if (TYPE(result) != T_ARRAY) {\n"); 3232 Printf(w->code, "Ruby_DirectorTypeMismatchException(\"Ruby method failed to return an array.\");\n"); 3233 Printf(w->code, "}\n"); 3234 } 3235 3236 idx = 0; 3237 3238 /* Marshal return value */ 3239 if (!is_void) { 3240 /* This seems really silly. The node's type excludes qualifier/pointer/reference markers, 3241 * which have to be retrieved from the decl field to construct return_type. But the typemap 3242 * lookup routine uses the node's type, so we have to swap in and out the correct type. 3243 * It's not just me, similar silliness also occurs in Language::cDeclaration(). 3244 */ 3245 Setattr(n, "type", return_type); 3246 tm = Swig_typemap_lookup("directorout", n, "result", w); 3247 Setattr(n, "type", type); 3248 if (tm != 0) { 3249 if (outputs > 1 && !asvoid ) { 3250 Printf(w->code, "output = rb_ary_entry(result, %d);\n", idx++); 3251 Replaceall(tm, "$input", "output"); 3252 } else { 3253 Replaceall(tm, "$input", "result"); 3254 } 3255 /* TODO check this */ 3256 if (Getattr(n, "wrap:disown")) { 3257 Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN"); 3258 } else { 3259 Replaceall(tm, "$disown", "0"); 3260 } 3261 Replaceall(tm, "$result", "c_result"); 3262 Printv(w->code, tm, "\n", NIL); 3263 } else { 3264 Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number, 3265 "Unable to use return type %s in director method %s::%s (skipping method).\n", SwigType_str(return_type, 0), 3266 SwigType_namestr(c_classname), SwigType_namestr(name)); 3267 status = SWIG_ERROR; 3268 } 3269 } 3270 3271 /* Marshal outputs */ 3272 for (p = l; p;) { 3273 if ((tm = Getattr(p, "tmap:directorargout")) != 0) { 3274 if (outputs > 1) { 3275 Printf(w->code, "output = rb_ary_entry(result, %d);\n", idx++); 3276 Replaceall(tm, "$input", "output"); 3277 } else { 3278 Replaceall(tm, "$input", "result"); 3279 } 3280 Replaceall(tm, "$result", Getattr(p, "name")); 3281 Printv(w->code, tm, "\n", NIL); 3282 p = Getattr(p, "tmap:directorargout:next"); 3283 } else { 3284 p = nextSibling(p); 3285 } 3286 } 3287 3288 Delete(arglist); 3289 Delete(cleanup); 3290 Delete(outarg); 3291 } 3292 3293 /* any existing helper functions to handle this? */ 3294 if (!is_void) { 3295 if (!(ignored_method && !pure_virtual)) { 3296 String *rettype = SwigType_str(return_type, 0); 3297 if (!SwigType_isreference(return_type)) { 3298 Printf(w->code, "return (%s) c_result;\n", rettype); 3299 } else { 3300 Printf(w->code, "return (%s) *c_result;\n", rettype); 3301 } 3302 Delete(rettype); 3303 } 3304 } 3305 3306 Printf(w->code, "}\n"); 3307 3308 // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method 3309 String *inline_extra_method = NewString(""); 3310 if (dirprot_mode() && !is_public(n) && !pure_virtual) { 3311 Printv(inline_extra_method, declaration, NIL); 3312 String *extra_method_name = NewStringf("%sSwigPublic", name); 3313 Replaceall(inline_extra_method, name, extra_method_name); 3314 Replaceall(inline_extra_method, ";\n", " {\n "); 3315 if (!is_void) 3316 Printf(inline_extra_method, "return "); 3317 String *methodcall = Swig_method_call(super, l); 3318 Printv(inline_extra_method, methodcall, ";\n }\n", NIL); 3319 Delete(methodcall); 3320 Delete(extra_method_name); 3321 } 3322 3323 /* emit the director method */ 3324 if (status == SWIG_OK) { 3325 if (!Getattr(n, "defaultargs")) { 3326 Wrapper_print(w, f_directors); 3327 Printv(f_directors_h, declaration, NIL); 3328 Printv(f_directors_h, inline_extra_method, NIL); 3329 } 3330 } 3331 3332 /* clean up */ 3333 Delete(wrap_args); 3334 Delete(return_type); 3335 Delete(pclassname); 3336 DelWrapper(w); 3337 return status; 3338 } 3339 3340 virtual int classDirectorConstructors(Node *n) { 3341 return Language::classDirectorConstructors(n); 3342 } 3343 3344 virtual int classDirectorMethods(Node *n) { 3345 return Language::classDirectorMethods(n); 3346 } 3347 3348 virtual int classDirectorDisown(Node *n) { 3349 return Language::classDirectorDisown(n); 3350 } 3351 3352 void typemap_copy_pname_to_lname(ParmList *parms) { 3353 Parm *p; 3354 String *pname; 3355 String *lname; 3356 3357 p = parms; 3358 while (p) { 3359 pname = Getattr(p, "name"); 3360 lname = Copy(pname); 3361 Setattr(p, "lname", lname); 3362 p = nextSibling(p); 3363 } 3364 } 3365 3366 String *runtimeCode() { 3367 String *s = NewString(""); 3368 String *shead = Swig_include_sys("rubyhead.swg"); 3369 if (!shead) { 3370 Printf(stderr, "*** Unable to open 'rubyhead.swg'\n"); 3371 } else { 3372 Append(s, shead); 3373 Delete(shead); 3374 } 3375 String *serrors = Swig_include_sys("rubyerrors.swg"); 3376 if (!serrors) { 3377 Printf(stderr, "*** Unable to open 'rubyerrors.swg'\n"); 3378 } else { 3379 Append(s, serrors); 3380 Delete(serrors); 3381 } 3382 String *strack = Swig_include_sys("rubytracking.swg"); 3383 if (!strack) { 3384 Printf(stderr, "*** Unable to open 'rubytracking.swg'\n"); 3385 } else { 3386 Append(s, strack); 3387 Delete(strack); 3388 } 3389 String *sapi = Swig_include_sys("rubyapi.swg"); 3390 if (!sapi) { 3391 Printf(stderr, "*** Unable to open 'rubyapi.swg'\n"); 3392 } else { 3393 Append(s, sapi); 3394 Delete(sapi); 3395 } 3396 String *srun = Swig_include_sys("rubyrun.swg"); 3397 if (!srun) { 3398 Printf(stderr, "*** Unable to open 'rubyrun.swg'\n"); 3399 } else { 3400 Append(s, srun); 3401 Delete(srun); 3402 } 3403 return s; 3404 } 3405 3406 String *defaultExternalRuntimeFilename() { 3407 return NewString("swigrubyrun.h"); 3408 } 3409}; /* class RUBY */ 3410 3411/* ----------------------------------------------------------------------------- 3412 * swig_ruby() - Instantiate module 3413 * ----------------------------------------------------------------------------- */ 3414 3415static Language *new_swig_ruby() { 3416 return new RUBY(); 3417} 3418extern "C" Language *swig_ruby(void) { 3419 return new_swig_ruby(); 3420} 3421 3422 3423/* 3424 * Local Variables: 3425 * c-basic-offset: 2 3426 * End: 3427 */ 3428