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 * pike.cxx 6 * 7 * Pike language module for SWIG. 8 * ----------------------------------------------------------------------------- */ 9 10/* 11 * Notes: 12 * 13 * - The current approach used for "out" typemaps is inconsistent with 14 * how "out" typemaps are handled by other language modules. Instead 15 * of converting the C/C++ type ($1) to a Pike object type (e.g. a 16 * struct svalue), we're just calling the appropriate push_XXX 17 * (e.g. push_int) to push the return value onto the stack. 18 * 19 * - Pike classes can't have static member functions or data, so we need 20 * to find some other appropriate mapping for C++ static member functions 21 * and data. 22 * 23 * - Pike doesn't seem to provide any default way to print the memory 24 * address, etc. for extension objects. Should we do something here? 25 * 26 */ 27 28char cvsroot_pike_cxx[] = "$Id: pike.cxx 11133 2009-02-20 07:52:24Z wsfulton $"; 29 30#include "swigmod.h" 31 32#include <ctype.h> // for isalnum() 33 34static const char *usage = (char *) "\ 35Pike Options (available with -pike)\n\ 36 [None]\n\ 37\n"; 38 39class PIKE:public Language { 40private: 41 42 File *f_begin; 43 File *f_runtime; 44 File *f_header; 45 File *f_wrappers; 46 File *f_init; 47 File *f_classInit; 48 49 String *PrefixPlusUnderscore; 50 int current; 51 52 // Wrap modes 53 enum { 54 NO_CPP, 55 MEMBER_FUNC, 56 CONSTRUCTOR, 57 DESTRUCTOR, 58 MEMBER_VAR, 59 CLASS_CONST, 60 STATIC_FUNC, 61 STATIC_VAR 62 }; 63 64public: 65 66 /* --------------------------------------------------------------------- 67 * PIKE() 68 * 69 * Initialize member data 70 * --------------------------------------------------------------------- */ 71 72 PIKE() { 73 f_begin = 0; 74 f_runtime = 0; 75 f_header = 0; 76 f_wrappers = 0; 77 f_init = 0; 78 f_classInit = 0; 79 PrefixPlusUnderscore = 0; 80 current = NO_CPP; 81 } 82 83 /* --------------------------------------------------------------------- 84 * main() 85 * 86 * Parse command line options and initializes variables. 87 * --------------------------------------------------------------------- */ 88 89 virtual void main(int argc, char *argv[]) { 90 91 /* Set location of SWIG library */ 92 SWIG_library_directory("pike"); 93 94 /* Look for certain command line options */ 95 for (int i = 1; i < argc; i++) { 96 if (argv[i]) { 97 if (strcmp(argv[i], "-help") == 0) { 98 fputs(usage, stdout); 99 } 100 } 101 } 102 103 /* Add a symbol to the parser for conditional compilation */ 104 Preprocessor_define("SWIGPIKE 1", 0); 105 106 /* Set language-specific configuration file */ 107 SWIG_config_file("pike.swg"); 108 109 /* Set typemap language */ 110 SWIG_typemap_lang("pike"); 111 112 /* Enable overloaded methods support */ 113 allow_overloading(); 114 } 115 116 /* --------------------------------------------------------------------- 117 * top() 118 * --------------------------------------------------------------------- */ 119 120 virtual int top(Node *n) { 121 /* Get the module name */ 122 String *module = Getattr(n, "name"); 123 124 /* Get the output file name */ 125 String *outfile = Getattr(n, "outfile"); 126 127 /* Open the output file */ 128 f_begin = NewFile(outfile, "w", SWIG_output_files()); 129 if (!f_begin) { 130 FileErrorDisplay(outfile); 131 SWIG_exit(EXIT_FAILURE); 132 } 133 f_runtime = NewString(""); 134 f_init = NewString(""); 135 f_classInit = NewString(""); 136 f_header = NewString(""); 137 f_wrappers = NewString(""); 138 139 /* Register file targets with the SWIG file handler */ 140 Swig_register_filebyname("header", f_header); 141 Swig_register_filebyname("wrapper", f_wrappers); 142 Swig_register_filebyname("begin", f_begin); 143 Swig_register_filebyname("runtime", f_runtime); 144 Swig_register_filebyname("init", f_init); 145 Swig_register_filebyname("classInit", f_classInit); 146 147 /* Standard stuff for the SWIG runtime section */ 148 Swig_banner(f_begin); 149 150 Printf(f_runtime, "\n"); 151 Printf(f_runtime, "#define SWIGPIKE\n"); 152 Printf(f_runtime, "\n"); 153 154 Printf(f_header, "#define SWIG_init pike_module_init\n"); 155 Printf(f_header, "#define SWIG_name \"%s\"\n\n", module); 156 157 /* Change naming scheme for constructors and destructors */ 158 Swig_name_register("construct", "%c_create"); 159 Swig_name_register("destroy", "%c_destroy"); 160 161 /* Current wrap type */ 162 current = NO_CPP; 163 164 /* Emit code for children */ 165 Language::top(n); 166 167 /* Close the initialization function */ 168 Printf(f_init, "}\n"); 169 SwigType_emit_type_table(f_runtime, f_wrappers); 170 171 /* Close all of the files */ 172 Dump(f_runtime, f_begin); 173 Dump(f_header, f_begin); 174 Dump(f_wrappers, f_begin); 175 Wrapper_pretty_print(f_init, f_begin); 176 177 Delete(f_header); 178 Delete(f_wrappers); 179 Delete(f_init); 180 Delete(f_classInit); 181 182 Close(f_begin); 183 Delete(f_runtime); 184 Delete(f_begin); 185 186 /* Done */ 187 return SWIG_OK; 188 } 189 190 /* ------------------------------------------------------------ 191 * validIdentifier() 192 * ------------------------------------------------------------ */ 193 194 virtual int validIdentifier(String *s) { 195 char *c = Char(s); 196 const char *c0 = c; 197 const char *c1 = c0 + 1; 198 while (*c) { 199 if (*c == '`' && c == c0) { 200 c++; 201 continue; 202 } 203 if ((*c == '+' || *c == '-' || *c == '*' || *c == '/') && c == c1) { 204 c++; 205 continue; 206 } 207 if (!(isalnum(*c) || (*c == '_'))) 208 return 0; 209 c++; 210 } 211 return 1; 212 } 213 214 /* ------------------------------------------------------------ 215 * importDirective() 216 * ------------------------------------------------------------ */ 217 218 virtual int importDirective(Node *n) { 219 String *modname = Getattr(n, "module"); 220 if (modname) { 221 Printf(f_init, "pike_require(\"%s\");\n", modname); 222 } 223 return Language::importDirective(n); 224 } 225 226 /* ------------------------------------------------------------ 227 * strip() 228 * 229 * For names that begin with the current class prefix plus an 230 * underscore (e.g. "Foo_enum_test"), return the base function 231 * name (i.e. "enum_test"). 232 * ------------------------------------------------------------ */ 233 234 String *strip(const DOHconst_String_or_char_ptr name) { 235 String *s = Copy(name); 236 if (Strncmp(name, PrefixPlusUnderscore, Len(PrefixPlusUnderscore)) != 0) { 237 return s; 238 } 239 Replaceall(s, PrefixPlusUnderscore, ""); 240 return s; 241 } 242 243 /* ------------------------------------------------------------ 244 * add_method() 245 * ------------------------------------------------------------ */ 246 247 void add_method(const DOHconst_String_or_char_ptr name, const DOHconst_String_or_char_ptr function, const DOHconst_String_or_char_ptr description) { 248 String *rename = NULL; 249 switch (current) { 250 case NO_CPP: 251 rename = NewString(name); 252 Printf(f_init, "ADD_FUNCTION(\"%s\", %s, tFunc(%s), 0);\n", rename, function, description); 253 break; 254 case STATIC_FUNC: 255 case STATIC_VAR: 256 rename = NewString(name); 257 Printf(f_init, "ADD_FUNCTION(\"%s\", %s, tFunc(%s), 0);\n", rename, function, description); 258 break; 259 case CONSTRUCTOR: 260 case DESTRUCTOR: 261 case MEMBER_FUNC: 262 case MEMBER_VAR: 263 rename = strip(name); 264 Printf(f_classInit, "ADD_FUNCTION(\"%s\", %s, tFunc(%s), 0);\n", rename, function, description); 265 break; 266 case CLASS_CONST: 267 assert(false); // shouldn't have gotten here for CLASS_CONST nodes 268 default: 269 assert(false); // what is this? 270 } 271 Delete(rename); 272 } 273 274 /* --------------------------------------------------------------------- 275 * functionWrapper() 276 * 277 * Create a function declaration and register it with the interpreter. 278 * --------------------------------------------------------------------- */ 279 280 virtual int functionWrapper(Node *n) { 281 282 String *name = Getattr(n, "name"); 283 String *iname = Getattr(n, "sym:name"); 284 SwigType *d = Getattr(n, "type"); 285 ParmList *l = Getattr(n, "parms"); 286 287 Parm *p; 288 String *tm; 289 int i; 290 291 String *overname = 0; 292 if (Getattr(n, "sym:overloaded")) { 293 overname = Getattr(n, "sym:overname"); 294 } else { 295 if (!addSymbol(iname, n)) 296 return SWIG_ERROR; 297 } 298 299 Wrapper *f = NewWrapper(); 300 301 // Emit all of the local variables for holding arguments. 302 emit_parameter_variables(l, f); 303 304 /* Attach the standard typemaps */ 305 emit_attach_parmmaps(l, f); 306 Setattr(n, "wrap:parms", l); 307 308 /* Get number of required and total arguments */ 309 int num_arguments = emit_num_arguments(l); 310 int varargs = emit_isvarargs(l); 311 312 /* Which input argument to start with? */ 313 int start = (current == MEMBER_FUNC || current == MEMBER_VAR || current == DESTRUCTOR) ? 1 : 0; 314 315 /* Offset to skip over the attribute name */ 316 // int offset = (current == MEMBER_VAR) ? 1 : 0; 317 int offset = 0; 318 319 String *wname = Swig_name_wrapper(iname); 320 if (overname) { 321 Append(wname, overname); 322 } 323 Setattr(n, "wrap:name", wname); 324 325 Printv(f->def, "static void ", wname, "(INT32 args) {", NIL); 326 327 /* Generate code for argument marshalling */ 328 String *description = NewString(""); 329 char source[64]; 330 for (i = 0, p = l; i < num_arguments; i++) { 331 332 while (checkAttribute(p, "tmap:in:numinputs", "0")) { 333 p = Getattr(p, "tmap:in:next"); 334 } 335 336 SwigType *pt = Getattr(p, "type"); 337 String *ln = Getattr(p, "lname"); 338 339 if (i < start) { 340 String *lstr = SwigType_lstr(pt, 0); 341 Printf(f->code, "%s = (%s) THIS;\n", ln, lstr); 342 Delete(lstr); 343 } else { 344 /* Look for an input typemap */ 345 sprintf(source, "Pike_sp[%d-args]", i - start + offset); 346 if ((tm = Getattr(p, "tmap:in"))) { 347 Replaceall(tm, "$source", source); 348 Replaceall(tm, "$target", ln); 349 Replaceall(tm, "$input", source); 350 Setattr(p, "emit:input", source); 351 Printf(f->code, "%s\n", tm); 352 String *pikedesc = Getattr(p, "tmap:in:pikedesc"); 353 if (pikedesc) { 354 Printv(description, pikedesc, " ", NIL); 355 } 356 p = Getattr(p, "tmap:in:next"); 357 continue; 358 } else { 359 Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0)); 360 break; 361 } 362 } 363 p = nextSibling(p); 364 } 365 366 /* Check for trailing varargs */ 367 if (varargs) { 368 if (p && (tm = Getattr(p, "tmap:in"))) { 369 Replaceall(tm, "$input", "varargs"); 370 Printv(f->code, tm, "\n", NIL); 371 } 372 } 373 374 /* Insert constraint checking code */ 375 for (p = l; p;) { 376 if ((tm = Getattr(p, "tmap:check"))) { 377 Replaceall(tm, "$target", Getattr(p, "lname")); 378 Printv(f->code, tm, "\n", NIL); 379 p = Getattr(p, "tmap:check:next"); 380 } else { 381 p = nextSibling(p); 382 } 383 } 384 385 /* Insert cleanup code */ 386 String *cleanup = NewString(""); 387 for (p = l; p;) { 388 if ((tm = Getattr(p, "tmap:freearg"))) { 389 Replaceall(tm, "$source", Getattr(p, "lname")); 390 Printv(cleanup, tm, "\n", NIL); 391 p = Getattr(p, "tmap:freearg:next"); 392 } else { 393 p = nextSibling(p); 394 } 395 } 396 397 /* Insert argument output code */ 398 String *outarg = NewString(""); 399 for (p = l; p;) { 400 if ((tm = Getattr(p, "tmap:argout"))) { 401 Replaceall(tm, "$source", Getattr(p, "lname")); 402 Replaceall(tm, "$target", "resultobj"); 403 Replaceall(tm, "$arg", Getattr(p, "emit:input")); 404 Replaceall(tm, "$input", Getattr(p, "emit:input")); 405 Printv(outarg, tm, "\n", NIL); 406 p = Getattr(p, "tmap:argout:next"); 407 } else { 408 p = nextSibling(p); 409 } 410 } 411 412 /* Emit the function call */ 413 String *actioncode = emit_action(n); 414 415 /* Clear the return stack */ 416 Printf(actioncode, "pop_n_elems(args);\n"); 417 418 /* Return the function value */ 419 if (current == CONSTRUCTOR) { 420 Printv(actioncode, "THIS = (void *) result;\n", NIL); 421 Printv(description, ", tVoid", NIL); 422 } else if (current == DESTRUCTOR) { 423 Printv(description, ", tVoid", NIL); 424 } else { 425 Printv(description, ", ", NIL); 426 if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { 427 actioncode = 0; 428 Replaceall(tm, "$source", "result"); 429 Replaceall(tm, "$target", "resultobj"); 430 Replaceall(tm, "$result", "resultobj"); 431 if (GetFlag(n, "feature:new")) { 432 Replaceall(tm, "$owner", "1"); 433 } else { 434 Replaceall(tm, "$owner", "0"); 435 } 436 String *pikedesc = Getattr(n, "tmap:out:pikedesc"); 437 if (pikedesc) { 438 Printv(description, pikedesc, NIL); 439 } 440 Printf(f->code, "%s\n", tm); 441 } else { 442 Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name); 443 } 444 } 445 if (actioncode) { 446 Append(f->code, actioncode); 447 Delete(actioncode); 448 } 449 emit_return_variable(n, d, f); 450 451 /* Output argument output code */ 452 Printv(f->code, outarg, NIL); 453 454 /* Output cleanup code */ 455 Printv(f->code, cleanup, NIL); 456 457 /* Look to see if there is any newfree cleanup code */ 458 if (GetFlag(n, "feature:new")) { 459 if ((tm = Swig_typemap_lookup("newfree", n, "result", 0))) { 460 Replaceall(tm, "$source", "result"); 461 Printf(f->code, "%s\n", tm); 462 } 463 } 464 465 /* See if there is any return cleanup code */ 466 if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) { 467 Replaceall(tm, "$source", "result"); 468 Printf(f->code, "%s\n", tm); 469 } 470 471 /* Close the function */ 472 Printf(f->code, "}\n"); 473 474 /* Substitute the cleanup code */ 475 Replaceall(f->code, "$cleanup", cleanup); 476 477 /* Substitute the function name */ 478 Replaceall(f->code, "$symname", iname); 479 Replaceall(f->code, "$result", "resultobj"); 480 481 /* Dump the function out */ 482 Wrapper_print(f, f_wrappers); 483 484 /* Now register the function with the interpreter. */ 485 if (!Getattr(n, "sym:overloaded")) { 486 add_method(iname, wname, description); 487 } else { 488 if (!Getattr(n, "sym:nextSibling")) { 489 dispatchFunction(n); 490 } 491 } 492 493 Delete(cleanup); 494 Delete(outarg); 495 Delete(description); 496 Delete(wname); 497 DelWrapper(f); 498 499 return SWIG_OK; 500 } 501 502 /* ------------------------------------------------------------ 503 * dispatchFunction() 504 * 505 * Emit overloading dispatch function 506 * ------------------------------------------------------------ */ 507 508 void dispatchFunction(Node *n) { 509 /* Last node in overloaded chain */ 510 511 int maxargs; 512 String *tmp = NewString(""); 513 String *dispatch = Swig_overload_dispatch(n, "%s(args); return;", &maxargs); 514 515 /* Generate a dispatch wrapper for all overloaded functions */ 516 517 Wrapper *f = NewWrapper(); 518 String *symname = Getattr(n, "sym:name"); 519 String *wname = Swig_name_wrapper(symname); 520 521 Printf(f->def, "static void %s(INT32 args) {", wname); 522 523 Wrapper_add_local(f, "argc", "INT32 argc"); 524 Printf(tmp, "struct svalue argv[%d]", maxargs); 525 Wrapper_add_local(f, "argv", tmp); 526 Wrapper_add_local(f, "ii", "INT32 ii"); 527 528 Printf(f->code, "argc = args;\n"); 529 Printf(f->code, "for (ii = 0; (ii < argc) && (ii < %d); ii++) {\n", maxargs); 530 Printf(f->code, "argv[ii] = Pike_sp[ii-args];\n"); 531 Printf(f->code, "}\n"); 532 533 Replaceall(dispatch, "$args", "self, args"); 534 Printv(f->code, dispatch, "\n", NIL); 535 Printf(f->code, "Pike_error(\"No matching function for overloaded '%s'.\");\n", symname); 536 Printv(f->code, "}\n", NIL); 537 538 Wrapper_print(f, f_wrappers); 539 540 String *description = NewString(""); 541 Printf(description, "tAny,"); 542 if (current == CONSTRUCTOR || current == DESTRUCTOR) { 543 Printf(description, " tVoid"); 544 } else { 545 String *pd = Getattr(n, "tmap:out:pikedesc"); 546 if (pd) 547 Printf(description, " %s", pd); 548 } 549 add_method(symname, wname, description); 550 Delete(description); 551 552 DelWrapper(f); 553 Delete(dispatch); 554 Delete(tmp); 555 Delete(wname); 556 } 557 558 /* ------------------------------------------------------------ 559 * variableWrapper() 560 * ------------------------------------------------------------ */ 561 562 virtual int variableWrapper(Node *n) { 563 return Language::variableWrapper(n); 564 } 565 566 /* ------------------------------------------------------------ 567 * constantWrapper() 568 * ------------------------------------------------------------ */ 569 570 virtual int constantWrapper(Node *n) { 571 572 Swig_require("constantWrapper", n, "*sym:name", "type", "value", NIL); 573 574 String *symname = Getattr(n, "sym:name"); 575 SwigType *type = Getattr(n, "type"); 576 String *value = Getattr(n, "value"); 577 578 /* Special hook for member pointer */ 579 if (SwigType_type(type) == T_MPOINTER) { 580 String *wname = Swig_name_wrapper(symname); 581 Printf(f_header, "static %s = %s;\n", SwigType_str(type, wname), value); 582 value = wname; 583 } 584 585 /* Perform constant typemap substitution */ 586 String *tm = Swig_typemap_lookup("constant", n, value, 0); 587 if (tm) { 588 Replaceall(tm, "$source", value); 589 Replaceall(tm, "$target", symname); 590 Replaceall(tm, "$symname", symname); 591 Replaceall(tm, "$value", value); 592 Printf(f_init, "%s\n", tm); 593 } else { 594 Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value %s = %s\n", SwigType_str(type, 0), value); 595 } 596 597 Swig_restore(n); 598 599 return SWIG_OK; 600 } 601 602 /* ------------------------------------------------------------ 603 * nativeWrapper() 604 * ------------------------------------------------------------ */ 605 606 virtual int nativeWrapper(Node *n) { 607 // return Language::nativeWrapper(n); 608 String *name = Getattr(n, "sym:name"); 609 String *wrapname = Getattr(n, "wrap:name"); 610 611 if (!addSymbol(wrapname, n)) 612 return SWIG_ERROR; 613 614 add_method(name, wrapname, 0); 615 return SWIG_OK; 616 } 617 618 /* ------------------------------------------------------------ 619 * enumDeclaration() 620 * ------------------------------------------------------------ */ 621 622 virtual int enumDeclaration(Node *n) { 623 return Language::enumDeclaration(n); 624 } 625 626 /* ------------------------------------------------------------ 627 * enumvalueDeclaration() 628 * ------------------------------------------------------------ */ 629 630 virtual int enumvalueDeclaration(Node *n) { 631 return Language::enumvalueDeclaration(n); 632 } 633 634 /* ------------------------------------------------------------ 635 * classDeclaration() 636 * ------------------------------------------------------------ */ 637 638 virtual int classDeclaration(Node *n) { 639 return Language::classDeclaration(n); 640 } 641 642 /* ------------------------------------------------------------ 643 * classHandler() 644 * ------------------------------------------------------------ */ 645 646 virtual int classHandler(Node *n) { 647 648 String *symname = Getattr(n, "sym:name"); 649 if (!addSymbol(symname, n)) 650 return SWIG_ERROR; 651 652 PrefixPlusUnderscore = NewStringf("%s_", getClassPrefix()); 653 654 Printf(f_classInit, "start_new_program();\n"); 655 656 /* Handle inheritance */ 657 List *baselist = Getattr(n, "bases"); 658 if (baselist && Len(baselist) > 0) { 659 Iterator base = First(baselist); 660 while (base.item) { 661 String *basename = Getattr(base.item, "name"); 662 SwigType *basetype = NewString(basename); 663 SwigType_add_pointer(basetype); 664 SwigType_remember(basetype); 665 String *basemangle = SwigType_manglestr(basetype); 666 Printf(f_classInit, "low_inherit((struct program *) SWIGTYPE%s->clientdata, 0, 0, 0, 0, 0);\n", basemangle); 667 Delete(basemangle); 668 Delete(basetype); 669 base = Next(base); 670 } 671 } else { 672 Printf(f_classInit, "ADD_STORAGE(swig_object_wrapper);\n"); 673 } 674 675 Language::classHandler(n); 676 677 /* Accessors for member variables */ 678 /* 679 List *membervariables = Getattr(n,"membervariables"); 680 if (membervariables && Len(membervariables) > 0) { 681 membervariableAccessors(membervariables); 682 } 683 */ 684 685 /* Done, close the class and dump its definition to the init function */ 686 Printf(f_classInit, "add_program_constant(\"%s\", pr = end_program(), 0);\n", symname); 687 Dump(f_classInit, f_init); 688 Clear(f_classInit); 689 690 SwigType *tt = NewString(symname); 691 SwigType_add_pointer(tt); 692 SwigType_remember(tt); 693 String *tm = SwigType_manglestr(tt); 694 Printf(f_init, "SWIG_TypeClientData(SWIGTYPE%s, (void *) pr);\n", tm); 695 Delete(tm); 696 Delete(tt); 697 698 Delete(PrefixPlusUnderscore); 699 PrefixPlusUnderscore = 0; 700 701 return SWIG_OK; 702 } 703 704 /* ------------------------------------------------------------ 705 * memberfunctionHandler() 706 * 707 * Method for adding C++ member function 708 * ------------------------------------------------------------ */ 709 710 virtual int memberfunctionHandler(Node *n) { 711 current = MEMBER_FUNC; 712 Language::memberfunctionHandler(n); 713 current = NO_CPP; 714 return SWIG_OK; 715 } 716 717 /* ------------------------------------------------------------ 718 * constructorHandler() 719 * 720 * Method for adding C++ member constructor 721 * ------------------------------------------------------------ */ 722 723 virtual int constructorHandler(Node *n) { 724 current = CONSTRUCTOR; 725 Language::constructorHandler(n); 726 current = NO_CPP; 727 return SWIG_OK; 728 } 729 730 /* ------------------------------------------------------------ 731 * destructorHandler() 732 * ------------------------------------------------------------ */ 733 734 virtual int destructorHandler(Node *n) { 735 current = DESTRUCTOR; 736 Language::destructorHandler(n); 737 current = NO_CPP; 738 return SWIG_OK; 739 } 740 741 /* ------------------------------------------------------------ 742 * membervariableAccessors() 743 * ------------------------------------------------------------ */ 744 745 void membervariableAccessors(List *membervariables) { 746 String *name; 747 Iterator i; 748 bool need_setter; 749 String *funcname; 750 751 /* If at least one of them is mutable, we need a setter */ 752 need_setter = false; 753 i = First(membervariables); 754 while (i.item) { 755 if (!GetFlag(i.item, "feature:immutable")) { 756 need_setter = true; 757 break; 758 } 759 i = Next(i); 760 } 761 762 /* Create a function to set the values of the (mutable) variables */ 763 if (need_setter) { 764 Wrapper *wrapper = NewWrapper(); 765 String *setter = Swig_name_member(getClassPrefix(), (char *) "`->="); 766 String *wname = Swig_name_wrapper(setter); 767 Printv(wrapper->def, "static void ", wname, "(INT32 args) {", NIL); 768 Printf(wrapper->locals, "char *name = (char *) STR0(Pike_sp[0-args].u.string);\n"); 769 770 i = First(membervariables); 771 while (i.item) { 772 if (!GetFlag(i.item, "feature:immutable")) { 773 name = Getattr(i.item, "name"); 774 funcname = Swig_name_wrapper(Swig_name_set(Swig_name_member(getClassPrefix(), name))); 775 Printf(wrapper->code, "if (!strcmp(name, \"%s\")) {\n", name); 776 Printf(wrapper->code, "%s(args);\n", funcname); 777 Printf(wrapper->code, "return;\n"); 778 Printf(wrapper->code, "}\n"); 779 Delete(funcname); 780 } 781 i = Next(i); 782 } 783 784 /* Close the function */ 785 Printf(wrapper->code, "pop_n_elems(args);\n"); 786 Printf(wrapper->code, "}\n"); 787 788 /* Dump wrapper code to the output file */ 789 Wrapper_print(wrapper, f_wrappers); 790 791 /* Register it with Pike */ 792 String *description = NewString("tStr tFloat, tVoid"); 793 add_method("`->=", wname, description); 794 Delete(description); 795 796 /* Clean up */ 797 Delete(wname); 798 Delete(setter); 799 DelWrapper(wrapper); 800 } 801 802 /* Create a function to get the values of the (mutable) variables */ 803 Wrapper *wrapper = NewWrapper(); 804 String *getter = Swig_name_member(getClassPrefix(), (char *) "`->"); 805 String *wname = Swig_name_wrapper(getter); 806 Printv(wrapper->def, "static void ", wname, "(INT32 args) {", NIL); 807 Printf(wrapper->locals, "char *name = (char *) STR0(Pike_sp[0-args].u.string);\n"); 808 809 i = First(membervariables); 810 while (i.item) { 811 name = Getattr(i.item, "name"); 812 funcname = Swig_name_wrapper(Swig_name_get(Swig_name_member(getClassPrefix(), name))); 813 Printf(wrapper->code, "if (!strcmp(name, \"%s\")) {\n", name); 814 Printf(wrapper->code, "%s(args);\n", funcname); 815 Printf(wrapper->code, "return;\n"); 816 Printf(wrapper->code, "}\n"); 817 Delete(funcname); 818 i = Next(i); 819 } 820 821 /* Close the function */ 822 Printf(wrapper->code, "pop_n_elems(args);\n"); 823 Printf(wrapper->code, "}\n"); 824 825 /* Dump wrapper code to the output file */ 826 Wrapper_print(wrapper, f_wrappers); 827 828 /* Register it with Pike */ 829 String *description = NewString("tStr, tMix"); 830 add_method("`->", wname, description); 831 Delete(description); 832 833 /* Clean up */ 834 Delete(wname); 835 Delete(getter); 836 DelWrapper(wrapper); 837 } 838 839 /* ------------------------------------------------------------ 840 * membervariableHandler() 841 * ------------------------------------------------------------ */ 842 843 virtual int membervariableHandler(Node *n) { 844 List *membervariables = Getattr(getCurrentClass(), "membervariables"); 845 if (!membervariables) { 846 membervariables = NewList(); 847 Setattr(getCurrentClass(), "membervariables", membervariables); 848 } 849 Append(membervariables, n); 850 current = MEMBER_VAR; 851 Language::membervariableHandler(n); 852 current = NO_CPP; 853 return SWIG_OK; 854 } 855 856 /* ----------------------------------------------------------------------- 857 * staticmemberfunctionHandler() 858 * 859 * Wrap a static C++ function 860 * ---------------------------------------------------------------------- */ 861 862 virtual int staticmemberfunctionHandler(Node *n) { 863 current = STATIC_FUNC; 864 Language::staticmemberfunctionHandler(n); 865 current = NO_CPP; 866 return SWIG_OK; 867 } 868 869 /* ------------------------------------------------------------ 870 * memberconstantHandler() 871 * 872 * Create a C++ constant 873 * ------------------------------------------------------------ */ 874 875 virtual int memberconstantHandler(Node *n) { 876 current = CLASS_CONST; 877 constantWrapper(n); 878 current = NO_CPP; 879 return SWIG_OK; 880 } 881 882 /* --------------------------------------------------------------------- 883 * staticmembervariableHandler() 884 * --------------------------------------------------------------------- */ 885 886 virtual int staticmembervariableHandler(Node *n) { 887 current = STATIC_VAR; 888 Language::staticmembervariableHandler(n); 889 current = NO_CPP; 890 return SWIG_OK; 891 } 892}; 893 894/* ----------------------------------------------------------------------------- 895 * swig_pike() - Instantiate module 896 * ----------------------------------------------------------------------------- */ 897 898static Language *new_swig_pike() { 899 return new PIKE(); 900} 901extern "C" Language *swig_pike(void) { 902 return new_swig_pike(); 903} 904