/trunk/Source/Modules/go.cxx
C++ | 2221 lines | 1701 code | 259 blank | 261 comment | 364 complexity | 78793f1dd6d1ffe0524db92217de5307 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
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 * go.cxx 6 * 7 * Go language module for SWIG. 8 * ----------------------------------------------------------------------------- */ 9 10char cvsroot_go_cxx[] = "$Id"; 11 12#include "swigmod.h" 13#include "cparse.h" 14#include <ctype.h> 15 16#ifdef HAVE_GCCGO_46 17 #define GCCGO_46_DEFAULT true 18#else 19 #define GCCGO_46_DEFAULT false 20#endif 21 22class GO:public Language { 23 static const char *const usage; 24 25 // Go package name. 26 String *package; 27 // Flag for generating gccgo output. 28 bool gccgo_flag; 29 // Flag for generating gccgo 4.6 output. 30 bool gccgo_46_flag; 31 // Prefix to use with gccgo. 32 String *go_prefix; 33 // Name of shared library to import. 34 String *soname; 35 // Size in bits of the C type "long". 36 int long_type_size; 37 38 /* Output files */ 39 File *f_c_begin; 40 File *f_go_begin; 41 File *f_gc_begin; 42 43 /* Output fragments */ 44 File *f_c_runtime; 45 File *f_c_header; 46 File *f_c_wrappers; 47 File *f_c_init; 48 File *f_c_directors; 49 File *f_c_directors_h; 50 File *f_go_runtime; 51 File *f_go_header; 52 File *f_go_wrappers; 53 File *f_gc_runtime; 54 File *f_gc_header; 55 File *f_gc_wrappers; 56 57 // True if we imported a module. 58 bool saw_import; 59 // If not NULL, name of import package being processed. 60 String *imported_package; 61 // Build interface methods while handling a class. This is only 62 // non-NULL when we are handling methods. 63 String *interfaces; 64 // The class node while handling a class. This is only non-NULL 65 // when we are handling methods. 66 Node *class_node; 67 // The class name while handling a class. This is only non-NULL 68 // when we are handling methods. This is the name of the class as 69 // SWIG sees it. 70 String *class_name; 71 // The receiver name while handling a class. This is only non-NULL 72 // when we are handling methods. This is the name of the class 73 // as run through goCPointerType. 74 String *class_receiver; 75 // A hash table of method names that we have seen when processing a 76 // class. This lets us detect base class methods that we don't want 77 // to use. 78 Hash *class_methods; 79 // True when we are generating the wrapper functions for a variable. 80 bool making_variable_wrappers; 81 // True when working with a static member function. 82 bool is_static_member_function; 83 // A hash table of types that we have seen but which may not have 84 // been defined. The index is a SwigType. 85 Hash *undefined_types; 86 // A hash table of classes which were defined. The index is a Go 87 // type name. 88 Hash *defined_types; 89 90public: 91 GO():package(NULL), 92 gccgo_flag(false), 93 gccgo_46_flag(GCCGO_46_DEFAULT), 94 go_prefix(NULL), 95 soname(NULL), 96 long_type_size(32), 97 f_c_begin(NULL), 98 f_go_begin(NULL), 99 f_gc_begin(NULL), 100 f_c_runtime(NULL), 101 f_c_header(NULL), 102 f_c_wrappers(NULL), 103 f_c_init(NULL), 104 f_c_directors(NULL), 105 f_c_directors_h(NULL), 106 f_go_runtime(NULL), 107 f_go_header(NULL), 108 f_go_wrappers(NULL), 109 f_gc_runtime(NULL), 110 f_gc_header(NULL), 111 f_gc_wrappers(NULL), 112 saw_import(false), 113 imported_package(NULL), 114 interfaces(NULL), 115 class_node(NULL), 116 class_name(NULL), 117 class_receiver(NULL), 118 class_methods(NULL), 119 making_variable_wrappers(false), 120 is_static_member_function(false), 121 undefined_types(NULL), 122 defined_types(NULL) { 123 director_multiple_inheritance = 1; 124 director_language = 1; 125 director_prot_ctor_code = NewString("_swig_gopanic(\"accessing abstract class or protected constructor\");"); 126 } 127 128private: 129 /* ------------------------------------------------------------ 130 * main() 131 * ------------------------------------------------------------ */ 132 virtual void main(int argc, char *argv[]) { 133 134 SWIG_library_directory("go"); 135 136 // Process command line options. 137 for (int i = 1; i < argc; i++) { 138 if (argv[i]) { 139 if (strcmp(argv[i], "-package") == 0) { 140 if (argv[i + 1]) { 141 package = NewString(argv[i + 1]); 142 Swig_mark_arg(i); 143 Swig_mark_arg(i + 1); 144 i++; 145 } else { 146 Swig_arg_error(); 147 } 148 } else if (strcmp(argv[i], "-gccgo") == 0) { 149 Swig_mark_arg(i); 150 gccgo_flag = true; 151 } else if (strcmp(argv[i], "-gccgo-46") == 0) { 152 Swig_mark_arg(i); 153 gccgo_46_flag = true; 154 } else if (strcmp(argv[i], "-no-gccgo-46") == 0) { 155 Swig_mark_arg(i); 156 gccgo_46_flag = false; 157 } else if (strcmp(argv[i], "-go-prefix") == 0) { 158 if (argv[i + 1]) { 159 go_prefix = NewString(argv[i + 1]); 160 Swig_mark_arg(i); 161 Swig_mark_arg(i + 1); 162 i++; 163 } else { 164 Swig_arg_error(); 165 } 166 } else if (strcmp(argv[i], "-soname") == 0) { 167 if (argv[i + 1]) { 168 soname = NewString(argv[i + 1]); 169 Swig_mark_arg(i); 170 Swig_mark_arg(i + 1); 171 i++; 172 } else { 173 Swig_arg_error(); 174 } 175 } else if (strcmp(argv[i], "-longsize") == 0) { 176 if (argv[i + 1]) { 177 long_type_size = atoi(argv[i + 1]); 178 if (long_type_size != 32 && long_type_size != 64) { 179 Printf(stderr, "-longsize not 32 or 64\n"); 180 Swig_arg_error(); 181 } 182 Swig_mark_arg(i); 183 Swig_mark_arg(i + 1); 184 ++i; 185 } else { 186 Swig_arg_error(); 187 } 188 } else if (strcmp(argv[i], "-help") == 0) { 189 Printf(stdout, "%s\n", usage); 190 } 191 } 192 } 193 194 if (gccgo_flag && !go_prefix) { 195 go_prefix = NewString("go"); 196 } 197 198 // Add preprocessor symbol to parser. 199 Preprocessor_define("SWIGGO 1", 0); 200 201 if (gccgo_flag) { 202 Preprocessor_define("SWIGGO_GCCGO 1", 0); 203 } 204 205 if (long_type_size == 32) { 206 Preprocessor_define("SWIGGO_LONG_TYPE_SIZE 32", 0); 207 } else { 208 Preprocessor_define("SWIGGO_LONG_TYPE_SIZE 64", 0); 209 } 210 211 // Add typemap definitions. 212 SWIG_typemap_lang("go"); 213 SWIG_config_file("go.swg"); 214 215 allow_overloading(); 216 } 217 218 /* --------------------------------------------------------------------- 219 * top() 220 * 221 * For 6g/8g, we are going to create the following files: 222 * 223 * 1) A .c or .cxx file compiled with gcc. This file will contain 224 * function wrappers. Each wrapper will take a pointer to a 225 * struct holding the arguments, unpack them, and call the real 226 * function. 227 * 228 * 2) A .go file which defines the Go form of all types, and which 229 * defines Go function wrappers. Each wrapper will call the C 230 * function wrapper in the second file. 231 * 232 * 3) A .c file compiled with 6c/8c. This file will define 233 * Go-callable C function wrappers. Each wrapper will use 234 * cgocall to call the function wrappers in the first file. 235 * 236 * When generating code for gccgo, we don't need the third file, and 237 * the function wrappers in the first file have a different form. 238 * 239 * --------------------------------------------------------------------- */ 240 241 virtual int top(Node *n) { 242 Node *optionsnode = Getattr(Getattr(n, "module"), "options"); 243 if (optionsnode) { 244 if (Getattr(optionsnode, "directors")) { 245 allow_directors(); 246 } 247 if (Getattr(optionsnode, "dirprot")) { 248 allow_dirprot(); 249 } 250 allow_allprotected(GetFlag(optionsnode, "allprotected")); 251 } 252 253 String *module = Getattr(n, "name"); 254 if (!package) { 255 package = Copy(module); 256 } 257 if (!soname) { 258 soname = Copy(package); 259 Append(soname, ".so"); 260 } 261 262 // Get filenames. 263 264 String *c_filename = Getattr(n, "outfile"); 265 String *c_filename_h = Getattr(n, "outfile_h"); 266 267 String *go_filename = NewString(""); 268 Printf(go_filename, "%s%s.go", SWIG_output_directory(), module); 269 270 String *gc_filename = NULL; 271 if (!gccgo_flag) { 272 gc_filename = NewString(""); 273 Printf(gc_filename, "%s%s_gc.c", SWIG_output_directory(), module); 274 } 275 276 // Open files. 277 278 f_c_begin = NewFile(c_filename, "w", SWIG_output_files()); 279 if (!f_c_begin) { 280 FileErrorDisplay(c_filename); 281 SWIG_exit(EXIT_FAILURE); 282 } 283 284 if (directorsEnabled()) { 285 if (!c_filename_h) { 286 Printf(stderr, "Unable to determine outfile_h\n"); 287 SWIG_exit(EXIT_FAILURE); 288 } 289 f_c_directors_h = NewFile(c_filename_h, "w", SWIG_output_files()); 290 if (!f_c_directors_h) { 291 FileErrorDisplay(c_filename_h); 292 SWIG_exit(EXIT_FAILURE); 293 } 294 } 295 296 f_go_begin = NewFile(go_filename, "w", SWIG_output_files()); 297 if (!f_go_begin) { 298 FileErrorDisplay(go_filename); 299 SWIG_exit(EXIT_FAILURE); 300 } 301 302 if (!gccgo_flag) { 303 f_gc_begin = NewFile(gc_filename, "w", SWIG_output_files()); 304 if (!f_gc_begin) { 305 FileErrorDisplay(gc_filename); 306 SWIG_exit(EXIT_FAILURE); 307 } 308 } 309 310 f_c_runtime = NewString(""); 311 f_c_header = NewString(""); 312 f_c_wrappers = NewString(""); 313 f_c_init = NewString(""); 314 f_c_directors = NewString(""); 315 f_go_runtime = NewString(""); 316 f_go_header = NewString(""); 317 f_go_wrappers = NewString(""); 318 if (!gccgo_flag) { 319 f_gc_runtime = NewString(""); 320 f_gc_header = NewString(""); 321 f_gc_wrappers = NewString(""); 322 } 323 324 Swig_register_filebyname("begin", f_c_begin); 325 Swig_register_filebyname("runtime", f_c_runtime); 326 Swig_register_filebyname("header", f_c_header); 327 Swig_register_filebyname("wrapper", f_c_wrappers); 328 Swig_register_filebyname("init", f_c_init); 329 Swig_register_filebyname("director", f_c_directors); 330 Swig_register_filebyname("director_h", f_c_directors_h); 331 Swig_register_filebyname("go_begin", f_go_begin); 332 Swig_register_filebyname("go_runtime", f_go_runtime); 333 Swig_register_filebyname("go_header", f_go_header); 334 Swig_register_filebyname("go_wrapper", f_go_wrappers); 335 if (!gccgo_flag) { 336 Swig_register_filebyname("gc_begin", f_gc_begin); 337 Swig_register_filebyname("gc_runtime", f_gc_runtime); 338 Swig_register_filebyname("gc_header", f_gc_header); 339 Swig_register_filebyname("gc_wrapper", f_gc_wrappers); 340 } 341 342 Swig_banner(f_c_begin); 343 344 if (directorsEnabled()) { 345 Printf(f_c_runtime, "#define SWIG_DIRECTORS\n"); 346 347 Swig_banner(f_c_directors_h); 348 Printf(f_c_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module); 349 Printf(f_c_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module); 350 351 Printf(f_c_directors, "\n// C++ director class methods.\n"); 352 Printf(f_c_directors, "#include \"%s\"\n\n", Swig_file_filename(c_filename_h)); 353 } 354 355 Swig_banner(f_go_begin); 356 357 if (!gccgo_flag) { 358 Swig_banner(f_gc_begin); 359 Printf(f_gc_begin, "\n/* This file should be compiled with 6c/8c. */\n"); 360 Printf(f_gc_begin, "#pragma dynimport _ _ \"%s\"\n", soname); 361 } 362 363 // Output module initialization code. 364 365 Printf(f_go_begin, "\npackage %s\n\n", package); 366 367 // All the C++ wrappers should be extern "C". 368 369 Printv(f_c_wrappers, "#ifdef __cplusplus\n", "extern \"C\" {\n", "#endif\n\n", NULL); 370 371 // Set up the hash table for types not defined by SWIG. 372 373 undefined_types = NewHash(); 374 defined_types = NewHash(); 375 376 // Emit code. 377 378 Language::top(n); 379 380 // Write out definitions for the types not defined by SWIG. 381 382 Printv(f_go_wrappers, "\n", NULL); 383 for (Iterator p = First(undefined_types); p.key; p = Next(p)) { 384 String *ty = goType(NULL, p.key); 385 if (!Getattr(defined_types, ty)) { 386 String *cp = goCPointerType(p.key, false); 387 if (!Getattr(defined_types, cp)) { 388 Printv(f_go_wrappers, "type ", cp, " uintptr\n", NULL); 389 Printv(f_go_wrappers, "type ", ty, " interface {\n", NULL); 390 Printv(f_go_wrappers, "\tSwigcptr() uintptr;\n", NULL); 391 Printv(f_go_wrappers, "}\n", NULL); 392 Printv(f_go_wrappers, "func (p ", cp, ") Swigcptr() uintptr {\n", NULL); 393 Printv(f_go_wrappers, "\treturn uintptr(p)\n", NULL); 394 Printv(f_go_wrappers, "}\n\n", NULL); 395 } 396 Delete(cp); 397 } 398 Delete(ty); 399 } 400 Delete(undefined_types); 401 Delete(defined_types); 402 403 /* Write and cleanup */ 404 405 Dump(f_c_header, f_c_runtime); 406 407 if (directorsEnabled()) { 408 Printf(f_c_directors_h, "#endif\n"); 409 Close(f_c_directors_h); 410 Delete(f_c_directors_h); 411 f_c_directors_h = NULL; 412 413 Dump(f_c_directors, f_c_runtime); 414 Close(f_c_directors); 415 Delete(f_c_directors); 416 f_c_directors = NULL; 417 } 418 419 // End the extern "C". 420 Printv(f_c_wrappers, "#ifdef __cplusplus\n", "}\n", "#endif\n\n", NULL); 421 422 Dump(f_c_runtime, f_c_begin); 423 Dump(f_c_wrappers, f_c_begin); 424 Dump(f_c_init, f_c_begin); 425 Dump(f_go_header, f_go_begin); 426 Dump(f_go_runtime, f_go_begin); 427 Dump(f_go_wrappers, f_go_begin); 428 if (!gccgo_flag) { 429 Dump(f_gc_header, f_gc_begin); 430 Dump(f_gc_runtime, f_gc_begin); 431 Dump(f_gc_wrappers, f_gc_begin); 432 } 433 434 Delete(f_c_runtime); 435 Delete(f_c_header); 436 Delete(f_c_wrappers); 437 Delete(f_c_init); 438 Delete(f_go_runtime); 439 Delete(f_go_header); 440 Delete(f_go_wrappers); 441 if (!gccgo_flag) { 442 Delete(f_gc_runtime); 443 Delete(f_gc_header); 444 Delete(f_gc_wrappers); 445 } 446 447 Close(f_c_begin); 448 Delete(f_c_begin); 449 Close(f_go_begin); 450 Delete(f_go_begin); 451 if (!gccgo_flag) { 452 Close(f_gc_begin); 453 Delete(f_gc_begin); 454 } 455 456 return SWIG_OK; 457 } 458 459 /* ------------------------------------------------------------ 460 * importDirective() 461 * 462 * Handle a SWIG import statement by generating a Go import 463 * statement. 464 * ------------------------------------------------------------ */ 465 466 virtual int importDirective(Node *n) { 467 String *hold_import = imported_package; 468 String *modname = Getattr(n, "module"); 469 if (modname) { 470 Printv(f_go_begin, "import \"", modname, "\"\n", NULL); 471 imported_package = modname; 472 saw_import = true; 473 } 474 int r = Language::importDirective(n); 475 imported_package = hold_import; 476 return r; 477 } 478 479 /* ---------------------------------------------------------------------- 480 * functionWrapper() 481 * 482 * Implement a function. 483 * ---------------------------------------------------------------------- */ 484 485 virtual int functionWrapper(Node *n) { 486 if (GetFlag(n, "feature:ignore")) { 487 return SWIG_OK; 488 } 489 490 // We don't need explicit calls. 491 if (GetFlag(n, "explicitcall")) { 492 return SWIG_OK; 493 } 494 495 String *name = Getattr(n, "sym:name"); 496 String *nodetype = Getattr(n, "nodeType"); 497 bool is_static = is_static_member_function || isStatic(n); 498 bool is_friend = isFriend(n); 499 bool is_ctor_dtor = false; 500 501 SwigType *result = Getattr(n, "type"); 502 503 // For some reason SWIG changs the "type" value during the call to 504 // functionWrapper. We need to remember the type for possible 505 // overload processing. 506 Setattr(n, "go:type", Copy(result)); 507 508 String *go_name; 509 510 String *r1 = NULL; 511 if (making_variable_wrappers) { 512 // Change the name of the variable setter and getter functions 513 // to be more Go like. 514 515 bool is_set = Strcmp(Char(name) + Len(name) - 4, "_set") == 0; 516 assert(is_set || Strcmp(Char(name) + Len(name) - 4, "_get") == 0); 517 518 // Start with Set or Get. 519 go_name = NewString(is_set ? "Set" : "Get"); 520 521 // If this is a static variable, put in the class name, 522 // capitalized. 523 if (is_static && class_name) { 524 String *ccn = exportedName(class_name); 525 Append(go_name, ccn); 526 Delete(ccn); 527 } 528 529 // Add the rest of the name, capitalized, dropping the _set or 530 // _get. 531 String *c1 = removeClassname(name); 532 String *c2 = exportedName(c1); 533 char *p = Char(c2); 534 int len = Len(p); 535 for (int i = 0; i < len - 4; ++i) { 536 Putc(p[i], go_name); 537 } 538 Delete(c2); 539 Delete(c1); 540 541 if (!checkIgnoredParameters(n, go_name)) { 542 Delete(go_name); 543 return SWIG_NOWRAP; 544 } 545 } else if (Cmp(nodetype, "constructor") == 0) { 546 is_ctor_dtor = true; 547 548 // Change the name of a constructor to be more Go like. Change 549 // new_ to New, and capitalize the class name. 550 assert(Strncmp(name, "new_", 4) == 0); 551 String *c1 = NewString(Char(name) + 4); 552 String *c2 = exportedName(c1); 553 go_name = NewString("New"); 554 Append(go_name, c2); 555 Delete(c2); 556 Delete(c1); 557 558 if (Swig_methodclass(n) && Swig_directorclass(n) 559 && Strcmp(Char(Getattr(n, "wrap:action")), director_prot_ctor_code) != 0) { 560 // The core SWIG code skips the first parameter when 561 // generating the $nondirector_new string. Recreate the 562 // action in this case. But don't it if we are using the 563 // special code for an abstract class. 564 String *call = Swig_cppconstructor_call(getClassType(), 565 Getattr(n, "parms")); 566 SwigType *type = Copy(getClassType()); 567 SwigType_add_pointer(type); 568 String *cres = Swig_cresult(type, Swig_cresult_name(), call); 569 Setattr(n, "wrap:action", cres); 570 } 571 } else if (Cmp(nodetype, "destructor") == 0) { 572 // No need to emit protected destructors. 573 if (!is_public(n)) { 574 return SWIG_OK; 575 } 576 577 is_ctor_dtor = true; 578 579 // Change the name of a destructor to be more Go like. Change 580 // delete_ to Delete and capitalize the class name. 581 assert(Strncmp(name, "delete_", 7) == 0); 582 String *c1 = NewString(Char(name) + 7); 583 String *c2 = exportedName(c1); 584 go_name = NewString("Delete"); 585 Append(go_name, c2); 586 Delete(c2); 587 Delete(c1); 588 589 result = NewString("void"); 590 r1 = result; 591 } else { 592 if (!checkFunctionVisibility(n, NULL)) { 593 return SWIG_OK; 594 } 595 596 go_name = buildGoName(name, is_static, is_friend); 597 598 if (!checkIgnoredParameters(n, go_name)) { 599 Delete(go_name); 600 return SWIG_NOWRAP; 601 } 602 } 603 604 String *overname = NULL; 605 if (Getattr(n, "sym:overloaded")) { 606 overname = Getattr(n, "sym:overname"); 607 } else { 608 String *scope; 609 if (!class_name || is_static || is_ctor_dtor) { 610 scope = NULL; 611 } else { 612 scope = NewString("swiggoscope."); 613 Append(scope, class_name); 614 } 615 if (!checkNameConflict(go_name, n, scope)) { 616 Delete(go_name); 617 return SWIG_NOWRAP; 618 } 619 } 620 621 String *wname = Swig_name_wrapper(name); 622 if (overname) { 623 Append(wname, overname); 624 } 625 Setattr(n, "wrap:name", wname); 626 627 ParmList *parms = Getattr(n, "parms"); 628 Setattr(n, "wrap:parms", parms); 629 630 int r = makeWrappers(n, name, go_name, overname, wname, NULL, parms, result, is_static); 631 if (r != SWIG_OK) { 632 return r; 633 } 634 635 if (Getattr(n, "sym:overloaded") && !Getattr(n, "sym:nextSibling")) { 636 String *scope ; 637 if (!class_name || is_static || is_ctor_dtor) { 638 scope = NULL; 639 } else { 640 scope = NewString("swiggoscope."); 641 Append(scope, class_name); 642 } 643 if (!checkNameConflict(go_name, n, scope)) { 644 Delete(go_name); 645 return SWIG_NOWRAP; 646 } 647 648 String *receiver = class_receiver; 649 if (is_static || is_ctor_dtor) { 650 receiver = NULL; 651 } 652 r = makeDispatchFunction(n, go_name, receiver, is_static, NULL, false); 653 if (r != SWIG_OK) { 654 return r; 655 } 656 } 657 658 Delete(wname); 659 Delete(go_name); 660 Delete(r1); 661 662 return SWIG_OK; 663 } 664 665 /* ---------------------------------------------------------------------- 666 * staticmemberfunctionHandler() 667 * 668 * For some reason the language code removes the "storage" attribute 669 * for a static function before calling functionWrapper, which means 670 * that we have no way of knowing whether a function is static or 671 * not. That makes no sense in the Go context. Here we note that a 672 * function is static. 673 * ---------------------------------------------------------------------- */ 674 675 int staticmemberfunctionHandler(Node *n) { 676 assert(!is_static_member_function); 677 is_static_member_function = true; 678 int r = Language::staticmemberfunctionHandler(n); 679 is_static_member_function = false; 680 return r; 681 } 682 683 /* ---------------------------------------------------------------------- 684 * makeWrappers() 685 * 686 * Write out the various function wrappers. 687 * n: The function we are emitting. 688 * name: The function name. 689 * go_name: The name of the function in Go. 690 * overname: The overload string for overloaded function. 691 * wname: The SWIG wrapped name--the name of the C function. 692 * base: A list of the names of base classes, in the case where this 693 * is is a vritual method not defined in the current class. 694 * parms: The parameters. 695 * result: The result type. 696 * is_static: Whether this is a static method or member. 697 * ---------------------------------------------------------------------- */ 698 699 int makeWrappers(Node *n, String *name, String *go_name, String *overname, String *wname, List *base, ParmList *parms, SwigType *result, bool is_static) { 700 701 assert(result); 702 703 bool needs_wrapper; 704 int r = goFunctionWrapper(n, name, go_name, overname, wname, base, parms, result, is_static, &needs_wrapper); 705 if (r != SWIG_OK) { 706 return r; 707 } 708 709 if (!gccgo_flag) { 710 r = gcFunctionWrapper(n, name, go_name, overname, wname, parms, result, is_static, needs_wrapper); 711 if (r != SWIG_OK) { 712 return r; 713 } 714 r = gccFunctionWrapper(n, base, wname, parms, result); 715 if (r != SWIG_OK) { 716 return r; 717 } 718 } else { 719 r = gccgoFunctionWrapper(n, base, wname, parms, result); 720 if (r != SWIG_OK) { 721 return r; 722 } 723 } 724 725 if (class_methods) { 726 Setattr(class_methods, Getattr(n, "name"), NewString("")); 727 } 728 729 return SWIG_OK; 730 } 731 732 /* ---------------------------------------------------------------------- 733 * goFunctionWrapper() 734 * 735 * Write out a function wrapper in Go. When not implementing a 736 * method, the actual code is all in C; here we just declare the C 737 * function. When implementing a method, we have to call the C 738 * function, because it will have a different name. If base is not 739 * NULL, then we are being called to forward a virtual method to a 740 * base class. 741 * ---------------------------------------------------------------------- */ 742 743 int goFunctionWrapper(Node *n, String *name, String *go_name, String *overname, String *wname, List *base, ParmList *parms, SwigType *result, bool is_static, bool *p_needs_wrapper) { 744 Wrapper *dummy = NewWrapper(); 745 emit_attach_parmmaps(parms, dummy); 746 Swig_typemap_attach_parms("default", parms, dummy); 747 Swig_typemap_attach_parms("gotype", parms, dummy); 748 int parm_count = emit_num_arguments(parms); 749 int required_count = emit_num_required(parms); 750 751 String *receiver = class_receiver; 752 if (receiver && is_static) { 753 receiver = NULL; 754 } 755 756 String *nodetype = Getattr(n, "nodeType"); 757 bool is_constructor = Cmp(nodetype, "constructor") == 0; 758 bool is_destructor = Cmp(nodetype, "destructor") == 0; 759 if (is_constructor || is_destructor) { 760 assert(class_receiver); 761 assert(!base); 762 receiver = NULL; 763 } 764 765 bool add_to_interface = (interfaces && !is_constructor && !is_destructor && !is_static && !overname && checkFunctionVisibility(n, NULL)); 766 767 bool needs_wrapper = (gccgo_flag || receiver || is_constructor || is_destructor || parm_count > required_count); 768 769 // See whether any of the function parameters are represented by 770 // interface values When calling the C++ code, we need to convert 771 // back to a uintptr. 772 if (!needs_wrapper) { 773 Parm *p = parms; 774 for (int i = 0; i < parm_count; ++i) { 775 p = getParm(p); 776 String *ty = Getattr(p, "type"); 777 if (goTypeIsInterface(p, ty)) { 778 needs_wrapper = true; 779 break; 780 } 781 p = nextParm(p); 782 } 783 } 784 if (goTypeIsInterface(n, result)) { 785 needs_wrapper = true; 786 } 787 788 *p_needs_wrapper = needs_wrapper; 789 790 // If this is a method, first declare the C function we will call. 791 // If we do not need a wrapper, then we will only be writing a 792 // declaration. 793 String *wrapper_name = NULL; 794 if (needs_wrapper) { 795 wrapper_name = buildGoWrapperName(name, overname); 796 797 if (gccgo_flag && !gccgo_46_flag) { 798 Printv(f_go_wrappers, "//extern ", go_prefix, "_", wname, "\n", NULL); 799 } 800 801 Printv(f_go_wrappers, "func ", wrapper_name, "(", NULL); 802 if (parm_count > required_count) { 803 Printv(f_go_wrappers, "int", NULL); 804 } 805 Parm *p = getParm(parms); 806 Swig_cparm_name(p, 0); 807 int i = 0; 808 if (is_destructor) { 809 if (parm_count > required_count) { 810 Printv(f_go_wrappers, ", ", NULL); 811 } 812 Printv(f_go_wrappers, "uintptr", NULL); 813 ++i; 814 p = nextParm(p); 815 } else if (receiver && (base || !is_constructor)) { 816 if (parm_count > required_count) { 817 Printv(f_go_wrappers, ", ", NULL); 818 } 819 Printv(f_go_wrappers, receiver, NULL); 820 if (!base) { 821 ++i; 822 p = nextParm(p); 823 } 824 } 825 for (; i < parm_count; ++i) { 826 p = getParm(p); 827 // Give the parameter a name we will use below. 828 Swig_cparm_name(p, i); 829 if (i > 0 || (base && receiver) || parm_count > required_count) { 830 Printv(f_go_wrappers, ", ", NULL); 831 } 832 String *tm = goWrapperType(p, Getattr(p, "type"), false); 833 Printv(f_go_wrappers, tm, NULL); 834 Delete(tm); 835 p = nextParm(p); 836 } 837 Printv(f_go_wrappers, ")", NULL); 838 if (is_constructor) { 839 Printv(f_go_wrappers, " ", class_receiver, NULL); 840 } else { 841 if (SwigType_type(result) != T_VOID) { 842 String *tm = goWrapperType(n, result, true); 843 Printv(f_go_wrappers, " ", tm, NULL); 844 Delete(tm); 845 } 846 } 847 848 if (gccgo_flag && gccgo_46_flag) { 849 Printv(f_go_wrappers, " __asm__ (\"", go_prefix, "_", wname, "\")", NULL); 850 } 851 852 Printv(f_go_wrappers, "\n\n", NULL); 853 } 854 855 // Start defining the Go function. 856 857 if (!needs_wrapper && gccgo_flag && !gccgo_46_flag) { 858 Printv(f_go_wrappers, "//extern ", go_prefix, "_", wname, "\n", NULL); 859 } 860 861 Printv(f_go_wrappers, "func ", NULL); 862 863 Parm *p = parms; 864 int pi = 0; 865 866 // Add the receiver if this is a method. 867 if (receiver) { 868 Printv(f_go_wrappers, "(", NULL); 869 if (base && receiver) { 870 Printv(f_go_wrappers, "_swig_base", NULL); 871 } else { 872 Printv(f_go_wrappers, Getattr(p, "lname"), NULL); 873 p = nextParm(p); 874 ++pi; 875 } 876 Printv(f_go_wrappers, " ", receiver, ") ", NULL); 877 } 878 879 Printv(f_go_wrappers, go_name, NULL); 880 if (overname) { 881 Printv(f_go_wrappers, overname, NULL); 882 } 883 Printv(f_go_wrappers, "(", NULL); 884 885 // If we are doing methods, add this function to the interface. 886 if (add_to_interface) { 887 Printv(interfaces, "\t", go_name, "(", NULL); 888 } 889 890 // Write out the parameters to both the function definition and 891 // the interface. 892 893 String *parm_print = NewString(""); 894 895 for (; pi < parm_count; ++pi) { 896 p = getParm(p); 897 if (pi == 0 && is_destructor) { 898 String *cl = exportedName(class_name); 899 Printv(parm_print, Getattr(p, "lname"), " ", cl, NULL); 900 Delete(cl); 901 } else { 902 if (pi > (receiver && !base ? 1 : 0)) { 903 Printv(parm_print, ", ", NULL); 904 } 905 if (pi >= required_count) { 906 Printv(parm_print, "_swig_args ...interface{}", NULL); 907 break; 908 } 909 if (needs_wrapper) { 910 Printv(parm_print, Getattr(p, "lname"), " ", NULL); 911 } 912 String *tm = goType(p, Getattr(p, "type")); 913 Printv(parm_print, tm, NULL); 914 Delete(tm); 915 } 916 p = nextParm(p); 917 } 918 919 Printv(parm_print, ")", NULL); 920 921 // Write out the result type. 922 if (is_constructor) { 923 String *cl = exportedName(class_name); 924 Printv(parm_print, " ", cl, NULL); 925 Delete(cl); 926 } else { 927 if (SwigType_type(result) != T_VOID) { 928 String *tm = goType(n, result); 929 Printv(parm_print, " ", tm, NULL); 930 Delete(tm); 931 } 932 } 933 934 Printv(f_go_wrappers, parm_print, NULL); 935 if (add_to_interface) { 936 Printv(interfaces, parm_print, "\n", NULL); 937 } 938 939 // If this is a wrapper, we need to actually call the C function. 940 if (needs_wrapper) { 941 Printv(f_go_wrappers, " {\n", NULL); 942 943 if (parm_count > required_count) { 944 Parm *p = parms; 945 int i; 946 for (i = 0; i < required_count; ++i) { 947 p = getParm(p); 948 p = nextParm(p); 949 } 950 for (; i < parm_count; ++i) { 951 p = getParm(p); 952 String *tm = goType(p, Getattr(p, "type")); 953 Printv(f_go_wrappers, "\tvar ", Getattr(p, "lname"), " ", tm, "\n", NULL); 954 Printf(f_go_wrappers, "\tif len(_swig_args) > %d {\n", i - required_count); 955 Printf(f_go_wrappers, "\t\t%s = _swig_args[%d].(%s)\n", Getattr(p, "lname"), i - required_count, tm); 956 Printv(f_go_wrappers, "\t}\n", NULL); 957 Delete(tm); 958 p = nextParm(p); 959 } 960 } 961 962 if (gccgo_flag && !gccgo_46_flag) { 963 Printv(f_go_wrappers, "\tsyscall.Entersyscall()\n", NULL); 964 Printv(f_go_wrappers, "\tdefer syscall.Exitsyscall()\n", NULL); 965 } 966 967 Printv(f_go_wrappers, "\t", NULL); 968 if (SwigType_type(result) != T_VOID) { 969 Printv(f_go_wrappers, "return ", NULL); 970 } 971 972 Printv(f_go_wrappers, wrapper_name, "(", NULL); 973 974 if (parm_count > required_count) { 975 Printv(f_go_wrappers, "len(_swig_args)", NULL); 976 } 977 978 if (base && receiver) { 979 if (parm_count > required_count) { 980 Printv(f_go_wrappers, ", ", NULL); 981 } 982 Printv(f_go_wrappers, "_swig_base", NULL); 983 } 984 985 Parm *p = parms; 986 for (int i = 0; i < parm_count; ++i) { 987 p = getParm(p); 988 if (i > 0 || (base && receiver) 989 || parm_count > required_count) { 990 Printv(f_go_wrappers, ", ", NULL); 991 } 992 Printv(f_go_wrappers, Getattr(p, "lname"), NULL); 993 994 // If this is a destructor, then the C function expects the 995 // C++ value, and we have the interface. We need to get the 996 // C++ value. The same is true for a type represented as an 997 // interface. 998 if ((i == 0 && is_destructor) || ((i > 0 || !receiver || base || is_constructor) && goTypeIsInterface(p, Getattr(p, "type")))) { 999 Printv(f_go_wrappers, ".Swigcptr()", NULL); 1000 } 1001 1002 p = nextParm(p); 1003 } 1004 Printv(f_go_wrappers, ")\n", NULL); 1005 Printv(f_go_wrappers, "}\n", NULL); 1006 } else { 1007 if (gccgo_flag && gccgo_46_flag) { 1008 Printv(f_go_wrappers, " __asm__ (\"", go_prefix, "_", wname, "\")\n", NULL); 1009 } 1010 } 1011 1012 Printv(f_go_wrappers, "\n", NULL); 1013 1014 Delete(wrapper_name); 1015 DelWrapper(dummy); 1016 1017 return SWIG_OK; 1018 } 1019 1020 /* ---------------------------------------------------------------------- 1021 * gcFunctionWrapper() 1022 * 1023 * This is used for 6g/8g, not for gccgo. Write out the function 1024 * wrapper which will be compiled with 6c/8c. 1025 * ---------------------------------------------------------------------- */ 1026 1027 int gcFunctionWrapper(Node *n, String *name, String *go_name, String *overname, String *wname, ParmList *parms, SwigType *result, bool is_static, bool needs_wrapper) { 1028 Wrapper *f = NewWrapper(); 1029 1030 Printv(f->def, "#pragma dynimport ", wname, " ", wname, " \"\"\n", NULL); 1031 Printv(f->def, "extern void (*", wname, ")(void*);\n", NULL); 1032 Printv(f->def, "static void (*x", wname, ")(void*) = ", wname, ";\n", NULL); 1033 Printv(f->def, "\n", NULL); 1034 Printv(f->def, "void\n", NULL); 1035 1036 Wrapper *dummy = NewWrapper(); 1037 emit_attach_parmmaps(parms, dummy); 1038 Swig_typemap_attach_parms("default", parms, dummy); 1039 Swig_typemap_attach_parms("gosize", parms, dummy); 1040 int parm_count = emit_num_arguments(parms); 1041 int required_count = emit_num_required(parms); 1042 1043 String *parm_size = NewString(""); 1044 1045 if (parm_count > required_count) { 1046 Append(parm_size, "SWIG_PARM_SIZE"); 1047 } 1048 1049 if (class_receiver && !is_static) { 1050 if (Len(parm_size) > 0) { 1051 Append(parm_size, " + "); 1052 } 1053 Append(parm_size, "SWIG_PARM_SIZE"); 1054 } 1055 1056 Parm *p = parms; 1057 for (int i = 0; i < parm_count; ++i) { 1058 p = getParm(p); 1059 addGcTypeSize(p, Getattr(p, "type"), parm_size); 1060 p = nextParm(p); 1061 } 1062 1063 if (SwigType_type(result) != T_VOID) { 1064 addGcTypeSize(n, result, parm_size); 1065 } 1066 1067 if (Len(parm_size) == 0) { 1068 Append(parm_size, "1"); 1069 } 1070 1071 String *fn_name; 1072 if (!needs_wrapper) { 1073 fn_name = Copy(go_name); 1074 if (overname) { 1075 Append(fn_name, overname); 1076 } 1077 } else { 1078 fn_name = buildGoWrapperName(name, overname); 1079 } 1080 1081 // \xc2\xb7 is UTF-8 for U+00B7 which is Unicode 'Middle Dot' 1082 Printv(f->def, "\xc2\xb7", fn_name, "(struct { uint8 x[", parm_size, "];} p)", NULL); 1083 1084 Delete(fn_name); 1085 Delete(parm_size); 1086 1087 Printv(f->code, "{\n", NULL); 1088 Printv(f->code, "\truntime\xc2\xb7" "cgocall(x", wname, ", &p);\n", NULL); 1089 Printv(f->code, "}\n", NULL); 1090 Printv(f->code, "\n", NULL); 1091 1092 Wrapper_print(f, f_gc_wrappers); 1093 1094 DelWrapper(f); 1095 DelWrapper(dummy); 1096 1097 return SWIG_OK; 1098 } 1099 1100 /* ---------------------------------------------------------------------- 1101 * getGcTypeSize() 1102 * 1103 * Return the size to use when passing a type from 6g/8g to 6c/8c. 1104 * ---------------------------------------------------------------------- */ 1105 1106 String *addGcTypeSize(Node *n, SwigType *type, String *orig) { 1107 if (Len(orig) > 0) { 1108 Append(orig, " + "); 1109 } 1110 1111 String *go = goType(n, type); 1112 if (Cmp(go, "string") == 0) { 1113 // A string has a pointer and a length. 1114 Append(orig, "(2 * SWIG_PARM_SIZE)"); 1115 } else if (Strncmp(go, "[]", 2) == 0) { 1116 // A slice has a pointer, a length, and a capacity. The 1117 // length and capacity are always 4 bytes. 1118 Append(orig, "(SWIG_PARM_SIZE + 8)"); 1119 } else if (Strcmp(go, "float64") == 0) { 1120 Append(orig, "8"); 1121 } else if (Strcmp(go, "complex64") == 0) { 1122 Append(orig, "8"); 1123 } else if (Strcmp(go, "complex128") == 0) { 1124 Append(orig, "16"); 1125 } else { 1126 Append(orig, "SWIG_PARM_SIZE"); 1127 } 1128 1129 return orig; 1130 } 1131 1132 /* ---------------------------------------------------------------------- 1133 * gccFunctionWrapper() 1134 * 1135 * This is used for 6g/8g, not for gccgo. Write out the function 1136 * wrapper which will be compiled with gcc. If the base parameter 1137 * is not NULL, this is calls the base class method rather than 1138 * executing the SWIG wrapper code. 1139 * ---------------------------------------------------------------------- */ 1140 1141 int gccFunctionWrapper(Node *n, List *base, String *wname, ParmList *parms, SwigType *result) { 1142 Wrapper *f = NewWrapper(); 1143 1144 Swig_save("gccFunctionWrapper", n, "parms", NULL); 1145 1146 Parm *base_parm = NULL; 1147 if (base && !isStatic(n)) { 1148 SwigType *base_type = Copy(getClassType()); 1149 SwigType_add_pointer(base_type); 1150 base_parm = NewParm(base_type, NewString("arg1"), n); 1151 set_nextSibling(base_parm, parms); 1152 parms = base_parm; 1153 } 1154 1155 emit_parameter_variables(parms, f); 1156 emit_attach_parmmaps(parms, f); 1157 int parm_count = emit_num_arguments(parms); 1158 int required_count = emit_num_required(parms); 1159 1160 emit_return_variable(n, result, f); 1161 1162 // Start the function definition. 1163 1164 Printv(f->def, "void\n", wname, "(void *swig_v)\n", "{\n", NULL); 1165 1166 // The single function parameter is a pointer to the real argument 1167 // values. Define the structure that it points to. 1168 1169 Printv(f->code, "\tstruct swigargs {\n", NULL); 1170 1171 if (parm_count > required_count) { 1172 Printv(f->code, "\t\tint _swig_optargc;\n", NULL); 1173 } 1174 1175 Parm *p = parms; 1176 for (int i = 0; i < parm_count; ++i) { 1177 p = getParm(p); 1178 String *ln = Getattr(p, "lname"); 1179 SwigType *pt = Getattr(p, "type"); 1180 String *ct = gcCTypeForGoValue(p, pt, ln); 1181 Printv(f->code, "\t\t\t", ct, ";\n", NULL); 1182 Delete(ct); 1183 p = nextParm(p); 1184 } 1185 if (SwigType_type(result) != T_VOID) { 1186 Printv(f->code, "\t\tlong : 0;\n", NULL); 1187 String *ln = NewString(Swig_cresult_name()); 1188 String *ct = gcCTypeForGoValue(n, result, ln); 1189 Delete(ln); 1190 Printv(f->code, "\t\t", ct, ";\n", NULL); 1191 Delete(ct); 1192 } 1193 Printv(f->code, "\t} *swig_a = (struct swigargs *) swig_v;\n", NULL); 1194 1195 Printv(f->code, "\n", NULL); 1196 1197 // Copy the input arguments out of the structure into the 1198 // parameter variables. 1199 1200 p = parms; 1201 for (int i = 0; i < parm_count; ++i) { 1202 p = getParm(p); 1203 1204 String *tm = Getattr(p, "tmap:in"); 1205 if (!tm) { 1206 Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument\n", SwigType_str(Getattr(p, "type"), 0)); 1207 } else { 1208 String *ln = Getattr(p, "lname"); 1209 String *input = NewString(""); 1210 Printv(input, "swig_a->", ln, NULL); 1211 Replaceall(tm, "$input", input); 1212 Setattr(p, "emit:input", input); 1213 if (i < required_count) { 1214 Printv(f->code, "\t", tm, "\n", NULL); 1215 } else { 1216 Printf(f->code, "\tif (swig_a->_swig_optargc > %d) {\n", i - required_count); 1217 Printv(f->code, "\t\t", tm, "\n", NULL); 1218 Printv(f->code, "\t}\n", NULL); 1219 } 1220 } 1221 p = nextParm(p); 1222 } 1223 1224 Printv(f->code, "\n", NULL); 1225 1226 // Do the real work of the function. 1227 1228 checkConstraints(parms, f); 1229 1230 emitGoAction(n, base, parms, result, f); 1231 1232 argout(parms, f); 1233 1234 cleanupFunction(n, f, parms); 1235 1236 Printv(f->code, "}\n", NULL); 1237 1238 Wrapper_print(f, f_c_wrappers); 1239 1240 Swig_restore(n); 1241 1242 DelWrapper(f); 1243 Delete(base_parm); 1244 1245 return SWIG_OK; 1246 } 1247 1248 /* ---------------------------------------------------------------------- 1249 * gccgoFunctionWrapper() 1250 * 1251 * This is used for gccgo, not 6g/8g. Write out the function 1252 * wrapper which will be compiled with gcc. If the base parameter 1253 * is not NULL, this is calls the base class method rather than 1254 * executing the SWIG wrapper code. 1255 * ---------------------------------------------------------------------- */ 1256 1257 int gccgoFunctionWrapper(Node *n, List *base, String *wname, ParmList *parms, SwigType *result) { 1258 Wrapper *f = NewWrapper(); 1259 1260 Swig_save("gccgoFunctionWrapper", n, "parms", NULL); 1261 1262 Parm *base_parm = NULL; 1263 if (base && !isStatic(n)) { 1264 SwigType *base_type = Copy(getClassType()); 1265 SwigType_add_pointer(base_type); 1266 base_parm = NewParm(base_type, NewString("arg1"), n); 1267 set_nextSibling(base_parm, parms); 1268 parms = base_parm; 1269 } 1270 1271 emit_parameter_variables(parms, f); 1272 emit_attach_parmmaps(parms, f); 1273 int parm_count = emit_num_arguments(parms); 1274 int required_count = emit_num_required(parms); 1275 1276 emit_return_variable(n, result, f); 1277 1278 // Start the function definition. 1279 1280 String *fnname = NewString(""); 1281 Printv(fnname, go_prefix, "_", wname, "(", NULL); 1282 1283 if (parm_count > required_count) { 1284 Printv(fnname, "int _swig_optargc", NULL); 1285 } 1286 1287 Parm *p = parms; 1288 for (int i = 0; i < parm_count; ++i) { 1289 p = getParm(p); 1290 SwigType *pt = Copy(Getattr(p, "type")); 1291 if (SwigType_isarray(pt)) { 1292 SwigType_del_array(pt); 1293 SwigType_add_pointer(pt); 1294 } 1295 String *pn = NewString("g"); 1296 Append(pn, Getattr(p, "lname")); 1297 String *ct = gccgoCTypeForGoValue(p, pt, pn); 1298 if (i > 0 || parm_count > required_count) { 1299 Printv(fnname, ", ", NULL); 1300 } 1301 Printv(fnname, ct, NULL); 1302 Delete(ct); 1303 Delete(pn); 1304 Delete(pt); 1305 p = nextParm(p); 1306 } 1307 1308 Printv(fnname, ")", NULL); 1309 1310 if (SwigType_type(result) == T_VOID) { 1311 Printv(f->def, "void ", fnname, NULL); 1312 } else { 1313 String *ct = gccgoCTypeForGoValue(n, result, fnname); 1314 Printv(f->def, ct, NULL); 1315 Delete(ct); 1316 } 1317 1318 Printv(f->def, " {\n", NULL); 1319 1320 Delete(fnname); 1321 1322 if (SwigType_type(result) != T_VOID) { 1323 String *ln = NewString("go_result"); 1324 String *ct = gccgoCTypeForGoValue(n, result, ln); 1325 Wrapper_add_local(f, "go_result", ct); 1326 Delete(ct); 1327 Delete(ln); 1328 } 1329 1330 // Copy the parameters into the variables which hold their values, 1331 // applying appropriate transformations. 1332 1333 p = parms; 1334 for (int i = 0; i < parm_count; ++i) { 1335 p = getParm(p); 1336 1337 String *tm = Getattr(p, "tmap:in"); 1338 if (!tm) { 1339 Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, 1340 "Unable to use type %s as a function argument\n", SwigType_str(Getattr(p, "type"), 0)); 1341 } else { 1342 String *ln = Getattr(p, "lname"); 1343 String *pn = NewString("g"); 1344 Append(pn, ln); 1345 Replaceall(tm, "$input", pn); 1346 Setattr(p, "emit:input", pn); 1347 if (i < required_count) { 1348 Printv(f->code, " ", tm, "\n", NULL); 1349 } else { 1350 Printf(f->code, " if (_swig_optargc > %d) {\n", i - required_count); 1351 Printv(f->code, " ", tm, "\n", NULL); 1352 Printv(f->code, " }\n", NULL); 1353 } 1354 } 1355 1356 p = nextParm(p); 1357 } 1358 1359 Printv(f->code, "\n", NULL); 1360 1361 // Do the real work of the function. 1362 1363 checkConstraints(parms, f); 1364 1365 emitGoAction(n, base, parms, result, f); 1366 1367 argout(parms, f); 1368 1369 cleanupFunction(n, f, parms); 1370 1371 if (SwigType_type(result) != T_VOID) { 1372 Printv(f->code, " return go_result;\n", NULL); 1373 } 1374 1375 Printv(f->code, "}\n", NULL); 1376 1377 Wrapper_print(f, f_c_wrappers); 1378 1379 Swig_restore(n); 1380 1381 DelWrapper(f); 1382 Delete(base_parm); 1383 1384 return SWIG_OK; 1385 } 1386 1387 /* ----------------------------------------------------------------------- 1388 * checkConstraints() 1389 * 1390 * Check parameter constraints if any. This is used for the C/C++ 1391 * function. This assumes that each parameter has an "emit:input" 1392 * property with the name to use to refer to that parameter. 1393 * ----------------------------------------------------------------------- */ 1394 1395 void checkConstraints(ParmList *parms, Wrapper *f) { 1396 Parm *p = parms; 1397 while (p) { 1398 String *tm = Getattr(p, "tmap:check"); 1399 if (!tm) { 1400 p = nextSibling(p); 1401 } else { 1402 Replaceall(tm, "$input", Getattr(p, "emit:input")); 1403 Printv(f->code, tm, "\n\n", NULL); 1404 p = Getattr(p, "tmap:check:next"); 1405 } 1406 } 1407 } 1408 1409 /* ----------------------------------------------------------------------- 1410 * getGoAction() 1411 * 1412 * Get the action of the function. This is used for C/C++ function. 1413 * ----------------------------------------------------------------------- */ 1414 1415 void emitGoAction(Node *n, List *base, ParmList *parms, SwigType *result, Wrapper *f) { 1416 String *actioncode; 1417 if (!base || isStatic(n)) { 1418 Swig_director_emit_dynamic_cast(n, f); 1419 actioncode = emit_action(n); 1420 } else { 1421 // Call the base class method. 1422 actioncode = NewString(""); 1423 1424 String *current = NewString(""); 1425 if (!gccgo_flag) { 1426 Printv(current, "swig_a->", NULL); 1427 } 1428 Printv(current, Getattr(parms, "lname"), NULL); 1429 1430 int vc = 0; 1431 for (Iterator bi = First(base); bi.item; bi = Next(bi)) { 1432 Printf(actioncode, " %s *swig_b%d = (%s *)%s;\n", bi.item, vc, bi.item, current); 1433 Delete(current); 1434 current = NewString(""); 1435 Printf(current, "swig_b%d", vc); 1436 ++vc; 1437 } 1438 1439 String *code = Copy(Getattr(n, "wrap:action")); 1440 Replaceall(code, Getattr(parms, "lname"), current); 1441 Printv(actioncode, code, "\n", NULL); 1442 } 1443 1444 Swig_save("emitGoAction", n, "type", "tmap:out", NULL); 1445 1446 Setattr(n, "type", result); 1447 1448 String *tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode); 1449 if (!tm) { 1450 Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s\n", SwigType_str(result, 0)); 1451 } else { 1452 if (!gccgo_flag) { 1453 static const String *swig_a_result = NewStringf("swig_a->%s", Swig_cresult_name()); 1454 Replaceall(tm, "$result", swig_a_result); 1455 } else { 1456 Replaceall(tm, "$result", "go_result"); 1457 } 1458 if (GetFlag(n, "feature:new")) { 1459 Replaceall(tm, "$owner", "1"); 1460 } else { 1461 Replaceall(tm, "$owner", "0"); 1462 } 1463 Printv(f->code, tm, "\n", NULL); 1464 Delete(tm); 1465 } 1466 1467 Swig_restore(n); 1468 } 1469 1470 /* ----------------------------------------------------------------------- 1471 * argout() 1472 * 1473 * Handle argument output code if any. This is used for the C/C++ 1474 * function. This assumes that each parameter has an "emit:input" 1475 * property with the name to use to refer to that parameter. 1476 * ----------------------------------------------------------------------- */ 1477 1478 void argout(ParmList *parms, Wrapper *f) { 1479 Parm *p = parms; 1480 while (p) { 1481 String *tm = Getattr(p, "tmap:argout"); 1482 if (!tm) { 1483 p = nextSibling(p); 1484 } else { 1485 Replaceall(tm, "$result", Swig_cresult_name()); 1486 Replaceall(tm, "$input", Getattr(p, "emit:input")); 1487 Printv(f->code, tm, "\n", NULL); 1488 p = Getattr(p, "tmap:argout:next"); 1489 } 1490 } 1491 } 1492 1493 /* ----------------------------------------------------------------------- 1494 * freearg() 1495 * 1496 * Handle argument cleanup code if any. This is used for the C/C++ 1497 * function. This assumes that each parameter has an "emit:input" 1498 * property with the name to use to refer to that parameter. 1499 * ----------------------------------------------------------------------- */ 1500 1501 String *freearg(ParmList *parms) { 1502 String *ret = NewString(""); 1503 Parm *p = parms; 1504 while (p) { 1505 String *tm = Getattr(p, "tmap:freearg"); 1506 if (!tm) { 1507 p = nextSibling(p); 1508 } else { 1509 Replaceall(tm, "$input", Getattr(p, "emit:input")); 1510 Printv(ret, tm, "\n", NULL); 1511 p = Getattr(p, "tmap:freearg:next"); 1512 } 1513 } 1514 return ret; 1515 } 1516 1517 /* ----------------------------------------------------------------------- 1518 * cleanupFunction() 1519 * 1520 * Final function cleanup code. 1521 * ----------------------------------------------------------------------- */ 1522 1523 void cleanupFunction(Node *n, Wrapper *f, ParmList *parms) { 1524 String *cleanup = freearg(parms); 1525 Printv(f->code, cleanup, NULL); 1526 1527 if (GetFlag(n, "feature:new")) { 1528 String *tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0); 1529 if (tm) { 1530 Replaceall(tm, "$source", Swig_cresult_name()); 1531 Printv(f->code, tm, "\n", NULL); 1532 Delete(tm); 1533 } 1534 } 1535 1536 Replaceall(f->code, "$cleanup", cleanup); 1537 Delete(cleanup); 1538 1539 Replaceall(f->code, "$symname", Getattr(n, "sym:name")); 1540 } 1541 1542 /* ----------------------------------------------------------------------- 1543 * variableHandler() 1544 * 1545 * This exists just to set the making_variable_wrappers flag. 1546 * ----------------------------------------------------------------------- */ 1547 1548 virtual int variableHandler(Node *n) { 1549 assert(!making_variable_wrappers); 1550 making_variable_wrappers = true; 1551 int r = Language::variableHandler(n); 1552 making_variable_wrappers = false; 1553 return r; 1554 } 1555 1556 /* ----------------------------------------------------------------------- 1557 * constantWrapper() 1558 * 1559 * Product a const declaration. 1560 * ------------------------------------------------------------------------ */ 1561 1562 virtual int constantWrapper(Node *n) { 1563 SwigType *type = Getattr(n, "type"); 1564 1565 if (!SwigType_issimple(type) && SwigType_type(type) != T_STRING) { 1566 return goComplexConstant(n, type); 1567 } 1568 1569 if (Getattr(n, "storage") && Strcmp(Getattr(n, "storage"), "static") == 0) { 1570 return goComplexConstant(n, type); 1571 } 1572 1573 String *go_name = buildGoName(Getattr(n, "sym:name"), false, false); 1574 1575 String *tm = goType(n, type); 1576 String *value = Getattr(n, "value"); 1577 1578 String *copy = NULL; 1579 if (SwigType_type(type) == T_BOOL) { 1580 if (Cmp(value, "true") != 0 && Cmp(value, "false") != 0) { 1581 return goComplexConstant(n, type); 1582 } 1583 } else if (SwigType_type(type) == T_STRING || SwigType_type(type) == T_CHAR) { 1584 // Backslash sequences are somewhat different in Go and C/C++. 1585 if (Strchr(value, '\\') != 0) { 1586 return goComplexConstant(n, type); 1587 } 1588 } else { 1589 // Accept a 0x prefix, and strip combinations of u and l 1590 // suffixes. Otherwise accept digits, decimal point, and 1591 // exponentiation. Treat anything else as too complicated to 1592 // handle as a Go constant. 1593 char *p = Char(value); 1594 int len = strlen(p); 1595 bool need_copy = false; 1596 while (len > 0) { 1597 char c = p[len - 1]; 1598 if (c != 'l' && c != 'L' && c != 'u' && c != 'U') { 1599 break; 1600 } 1601 --len; 1602 need_copy = true; 1603 } 1604 bool is_hex = false; 1605 int i = 0; 1606 if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { 1607 i = 2; 1608 is_hex = true; 1609 } 1610 for (; i < len; ++i) { 1611 switch (p[i]) { 1612 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': 1613 break; 1614 case 'a': case 'b': case 'c': case 'd': case 'f': case 'A': case 'B': case 'C': case 'D': case 'F': 1615 if (!is_hex) { 1616 return goComplexConstant(n, type); 1617 } 1618 break; 1619 case '.': case 'e': case 'E': case '+': case '-': 1620 break; 1621 default: 1622 return goComplexConstant(n, type); 1623 } 1624 } 1625 if (need_copy) { 1626 copy = Copy(value); 1627 Replaceall(copy, p + len, ""); 1628 value = copy; 1629 } 1630 } 1631 1632 if (!checkNameConflict(go_name, n, NULL)) { 1633 Delete(tm); 1634 Delete(go_name); 1635 Delete(copy); 1636 return SWIG_NOWRAP; 1637 } 1638 1639 Printv(f_go_wrappers, "const ", go_name, " ", tm, " = ", NULL); 1640 if (SwigType_type(type) == T_STRING) { 1641 Printv(f_go_wrappers, "\"", value, "\"", NULL); 1642 } else if (SwigType_type(type) == T_CHAR) { 1643 Printv(f_go_wrappers, "'", value, "'", NULL); 1644 } else { 1645 Printv(f_go_wrappers, value, NULL); 1646 } 1647 1648 Printv(f_go_wrappers, "\n", NULL); 1649 1650 Delete(tm); 1651 Delete(go_name); 1652 Delete(copy); 1653 1654 return SWIG_OK; 1655 } 1656 1657 /* ---------------------------------------------------------------------- 1658 * enumDeclaration() 1659 * 1660 * A C++ enum type turns into a Named go int type. 1661 * ---------------------------------------------------------------------- */ 1662 1663 virtual int enumDeclaration(Node *n) { 1664 String *name = goEnumName(n); 1665 if (Strcmp(name, "int") != 0) { 1666 if (!ImportMode || !imported_package) { 1667 if (!checkNameConflict(name, n, NULL)) { 1668 Delete(name); 1669 return SWIG_NOWRAP; 1670 } 1671 Printv(f_go_wrappers, "type ", name, " int\n", NULL); 1672 } else { 1673 String *nw = NewString(""); 1674 Printv(nw, imported_package, ".", name, NULL); 1675 Setattr(n, "go:enumname", nw); 1676 } 1677 } 1678 Delete(name); 1679 1680 return Language::enumDeclaration(n); 1681 } 1682 1683 /* ----------------------------------------------------------------------- 1684 * enumvalueDeclaration() 1685 * 1686 * Declare a single value of an enum type. We fetch the value by 1687 * calling a C/C++ function. 1688 * ------------------------------------------------------------------------ */ 1689 1690 virtual int enumvalueDeclaration(Node *n) { 1691 if (!is_public(n)) { 1692 return SWIG_OK; 1693 } 1694 if (Getattr(parentNode(n), "unnamed")) { 1695 Setattr(n, "type", NewString("…
Large files files are truncated, but you can click here to view the full file