PageRenderTime 223ms CodeModel.GetById 83ms app.highlight 127ms RepoModel.GetById 1ms app.codeStats 1ms

/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