summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorAnthony Li <tuesdayslineara@gmail.com>2014-10-06 19:26:07 +0800
committerAnthony Li <tuesdayslineara@gmail.com>2014-10-06 19:26:07 +0800
commit60da096a079ffc547d2ee6a7825624682e0c68ac (patch)
treea14bc8a9d8a22fc806fcff073b89688f8b714d2a /Source
parentafa9affcd97ea05d4bac538407b47a06df6f09a1 (diff)
downloadswig-60da096a079ffc547d2ee6a7825624682e0c68ac.tar.gz
GoLang:fix overload functions with polymorphic issue
Diffstat (limited to 'Source')
-rw-r--r--Source/Modules/go.cxx2
-rw-r--r--Source/Modules/go.cxx~5385
2 files changed, 5386 insertions, 1 deletions
diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx
index c9910ab05..26cf015f7 100644
--- a/Source/Modules/go.cxx
+++ b/Source/Modules/go.cxx
@@ -4363,7 +4363,7 @@ private:
}
fn = i + 1;
- Printf(f_go_wrappers, "\t\tif _, ok := a[%d].(%s); !ok {\n", j, tm);
+ Printf(f_go_wrappers, "\t\tif _, ok := a[%d].(%s); !ok {\n", j, goType(pj, Getattr(pj, "type")));
Printf(f_go_wrappers, "\t\t\tgoto check_%d\n", fn);
Printv(f_go_wrappers, "\t\t}\n", NULL);
}
diff --git a/Source/Modules/go.cxx~ b/Source/Modules/go.cxx~
new file mode 100644
index 000000000..c9910ab05
--- /dev/null
+++ b/Source/Modules/go.cxx~
@@ -0,0 +1,5385 @@
+/* -----------------------------------------------------------------------------
+ * See the LICENSE file for information on copyright, usage and redistribution
+ * of SWIG, and the README file for authors - http://www.swig.org/release.html.
+ *
+ * go.cxx
+ *
+ * Go language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+#include <ctype.h>
+
+class GO:public Language {
+ static const char *const usage;
+
+ // Go package name.
+ String *package;
+ // SWIG module name.
+ String *module;
+ // Flag for generating gccgo output.
+ bool gccgo_flag;
+ // Prefix to use with gccgo.
+ String *go_prefix;
+ // -fgo-prefix option.
+ String *prefix_option;
+ // -fgo-pkgpath option.
+ String *pkgpath_option;
+ // Whether to use a shared library.
+ bool use_shlib;
+ // Name of shared library to import.
+ String *soname;
+ // Size in bits of the Go type "int". 0 if not specified.
+ int intgo_type_size;
+
+ /* Output files */
+ File *f_c_begin;
+ File *f_go_begin;
+ File *f_gc_begin;
+
+ /* Output fragments */
+ File *f_c_runtime;
+ File *f_c_header;
+ File *f_c_wrappers;
+ File *f_c_init;
+ File *f_c_directors;
+ File *f_c_directors_h;
+ File *f_go_imports;
+ File *f_go_runtime;
+ File *f_go_header;
+ File *f_go_wrappers;
+ File *f_gc_runtime;
+ File *f_gc_header;
+ File *f_gc_wrappers;
+
+ // True if we imported a module.
+ bool saw_import;
+ // If not NULL, name of import package being processed.
+ String *imported_package;
+ // Build interface methods while handling a class. This is only
+ // non-NULL when we are handling methods.
+ String *interfaces;
+ // The class node while handling a class. This is only non-NULL
+ // when we are handling methods.
+ Node *class_node;
+ // The class name while handling a class. This is only non-NULL
+ // when we are handling methods. This is the name of the class as
+ // SWIG sees it.
+ String *class_name;
+ // The receiver name while handling a class. This is only non-NULL
+ // when we are handling methods. This is the name of the class
+ // as run through goCPointerType.
+ String *class_receiver;
+ // A hash table of method names that we have seen when processing a
+ // class. This lets us detect base class methods that we don't want
+ // to use.
+ Hash *class_methods;
+ // True when we are generating the wrapper functions for a variable.
+ bool making_variable_wrappers;
+ // True when working with a static member function.
+ bool is_static_member_function;
+ // A hash table of enum types that we have seen but which may not have
+ // been defined. The index is a SwigType.
+ Hash *undefined_enum_types;
+ // A hash table of types that we have seen but which may not have
+ // been defined. The index is a SwigType.
+ Hash *undefined_types;
+ // A hash table of classes which were defined. The index is a Go
+ // type name.
+ Hash *defined_types;
+ // A hash table of all the go_imports already imported. The index is a full
+ // import name e.g. '"runtime"' or '_ "runtime/cgo"' or 'sc "syscall"'.
+ Hash *go_imports;
+
+public:
+ GO():package(NULL),
+ module(NULL),
+ gccgo_flag(false),
+ go_prefix(NULL),
+ prefix_option(NULL),
+ pkgpath_option(NULL),
+ use_shlib(false),
+ soname(NULL),
+ intgo_type_size(0),
+ f_c_begin(NULL),
+ f_go_begin(NULL),
+ f_gc_begin(NULL),
+ f_c_runtime(NULL),
+ f_c_header(NULL),
+ f_c_wrappers(NULL),
+ f_c_init(NULL),
+ f_c_directors(NULL),
+ f_c_directors_h(NULL),
+ f_go_imports(NULL),
+ f_go_runtime(NULL),
+ f_go_header(NULL),
+ f_go_wrappers(NULL),
+ f_gc_runtime(NULL),
+ f_gc_header(NULL),
+ f_gc_wrappers(NULL),
+ saw_import(false),
+ imported_package(NULL),
+ interfaces(NULL),
+ class_node(NULL),
+ class_name(NULL),
+ class_receiver(NULL),
+ class_methods(NULL),
+ making_variable_wrappers(false),
+ is_static_member_function(false),
+ undefined_enum_types(NULL),
+ undefined_types(NULL),
+ defined_types(NULL),
+ go_imports(NULL) {
+ director_multiple_inheritance = 1;
+ director_language = 1;
+ director_prot_ctor_code = NewString("_swig_gopanic(\"accessing abstract class or protected constructor\");");
+ }
+
+private:
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+ virtual void main(int argc, char *argv[]) {
+
+ SWIG_library_directory("go");
+ bool display_help = false;
+
+ // Process command line options.
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-package") == 0) {
+ if (argv[i + 1]) {
+ package = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-gccgo") == 0) {
+ Swig_mark_arg(i);
+ gccgo_flag = true;
+ } else if (strcmp(argv[i], "-go-prefix") == 0) {
+ if (argv[i + 1]) {
+ prefix_option = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-go-pkgpath") == 0) {
+ if (argv[i + 1]) {
+ pkgpath_option = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-use-shlib") == 0) {
+ Swig_mark_arg(i);
+ use_shlib = true;
+ } else if (strcmp(argv[i], "-soname") == 0) {
+ if (argv[i + 1]) {
+ soname = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-longsize") == 0) {
+ // Ignore for backward compatibility.
+ if (argv[i + 1]) {
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ ++i;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-intgosize") == 0) {
+ if (argv[i + 1]) {
+ intgo_type_size = atoi(argv[i + 1]);
+ if (intgo_type_size != 32 && intgo_type_size != 64) {
+ Printf(stderr, "-intgosize not 32 or 64\n");
+ Swig_arg_error();
+ }
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ ++i;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-help") == 0) {
+ display_help = true;
+ Printf(stdout, "%s\n", usage);
+ }
+ }
+ }
+
+ if (gccgo_flag && !pkgpath_option && !prefix_option) {
+ prefix_option = NewString("go");
+ }
+
+ // Add preprocessor symbol to parser.
+ Preprocessor_define("SWIGGO 1", 0);
+
+ if (gccgo_flag) {
+ Preprocessor_define("SWIGGO_GCCGO 1", 0);
+ }
+
+ // This test may be removed in the future, when we can assume that
+ // everybody has upgraded to Go 1.1. The code below is prepared
+ // for this test to simply be taken out.
+ if (intgo_type_size == 0 && !display_help) {
+ Printf(stderr, "SWIG -go: -intgosize option required but not specified\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ if (intgo_type_size == 32) {
+ Preprocessor_define("SWIGGO_INTGO_SIZE 32", 0);
+ } else if (intgo_type_size == 64) {
+ Preprocessor_define("SWIGGO_INTGO_SIZE 64", 0);
+ } else {
+ Preprocessor_define("SWIGGO_INTGO_SIZE 0", 0);
+ }
+
+ // Add typemap definitions.
+ SWIG_typemap_lang("go");
+ SWIG_config_file("go.swg");
+
+ allow_overloading();
+ }
+
+ /* ---------------------------------------------------------------------
+ * top()
+ *
+ * For 6g/8g, we are going to create the following files:
+ *
+ * 1) A .c or .cxx file compiled with gcc. This file will contain
+ * function wrappers. Each wrapper will take a pointer to a
+ * struct holding the arguments, unpack them, and call the real
+ * function.
+ *
+ * 2) A .go file which defines the Go form of all types, and which
+ * defines Go function wrappers. Each wrapper will call the C
+ * function wrapper in the second file.
+ *
+ * 3) A .c file compiled with 6c/8c. This file will define
+ * Go-callable C function wrappers. Each wrapper will use
+ * cgocall to call the function wrappers in the first file.
+ *
+ * When generating code for gccgo, we don't need the third file, and
+ * the function wrappers in the first file have a different form.
+ *
+ * --------------------------------------------------------------------- */
+
+ virtual int top(Node *n) {
+ Node *optionsnode = Getattr(Getattr(n, "module"), "options");
+ if (optionsnode) {
+ if (Getattr(optionsnode, "directors")) {
+ allow_directors();
+ }
+ if (Getattr(optionsnode, "dirprot")) {
+ allow_dirprot();
+ }
+ allow_allprotected(GetFlag(optionsnode, "allprotected"));
+ }
+
+ module = Getattr(n, "name");
+ if (!package) {
+ package = Copy(module);
+ }
+ if (!soname && use_shlib) {
+ soname = Copy(package);
+ Append(soname, ".so");
+ }
+
+ if (gccgo_flag) {
+ String *pref;
+ if (pkgpath_option) {
+ pref = pkgpath_option;
+ } else {
+ pref = prefix_option;
+ }
+ go_prefix = NewString("");
+ for (char *p = Char(pref); *p != '\0'; p++) {
+ if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9') || *p == '.' || *p == '$') {
+ Putc(*p, go_prefix);
+ } else {
+ Putc('_', go_prefix);
+ }
+ }
+ if (!pkgpath_option) {
+ Append(go_prefix, ".");
+ Append(go_prefix, package);
+ }
+ }
+
+ // Get filenames.
+
+ String *swig_filename = Getattr(n, "infile");
+ String *c_filename = Getattr(n, "outfile");
+ String *c_filename_h = Getattr(n, "outfile_h");
+
+ String *go_filename = NewString("");
+ Printf(go_filename, "%s%s.go", SWIG_output_directory(), module);
+
+ String *gc_filename = NULL;
+ if (!gccgo_flag) {
+ gc_filename = NewString("");
+ Printf(gc_filename, "%s%s_gc.c", SWIG_output_directory(), module);
+ }
+
+ // Open files.
+
+ f_c_begin = NewFile(c_filename, "w", SWIG_output_files());
+ if (!f_c_begin) {
+ FileErrorDisplay(c_filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ if (directorsEnabled()) {
+ if (!c_filename_h) {
+ Printf(stderr, "Unable to determine outfile_h\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+ f_c_directors_h = NewFile(c_filename_h, "w", SWIG_output_files());
+ if (!f_c_directors_h) {
+ FileErrorDisplay(c_filename_h);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+
+ f_go_begin = NewFile(go_filename, "w", SWIG_output_files());
+ if (!f_go_begin) {
+ FileErrorDisplay(go_filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ if (!gccgo_flag) {
+ f_gc_begin = NewFile(gc_filename, "w", SWIG_output_files());
+ if (!f_gc_begin) {
+ FileErrorDisplay(gc_filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+
+ f_c_runtime = NewString("");
+ f_c_header = NewString("");
+ f_c_wrappers = NewString("");
+ f_c_init = NewString("");
+ f_c_directors = NewString("");
+ f_go_imports = NewString("");
+ f_go_runtime = NewString("");
+ f_go_header = NewString("");
+ f_go_wrappers = NewString("");
+ if (!gccgo_flag) {
+ f_gc_runtime = NewString("");
+ f_gc_header = NewString("");
+ f_gc_wrappers = NewString("");
+ }
+
+ Swig_register_filebyname("begin", f_c_begin);
+ Swig_register_filebyname("runtime", f_c_runtime);
+ Swig_register_filebyname("header", f_c_header);
+ Swig_register_filebyname("wrapper", f_c_wrappers);
+ Swig_register_filebyname("init", f_c_init);
+ Swig_register_filebyname("director", f_c_directors);
+ Swig_register_filebyname("director_h", f_c_directors_h);
+ Swig_register_filebyname("go_begin", f_go_begin);
+ Swig_register_filebyname("go_imports", f_go_imports);
+ Swig_register_filebyname("go_runtime", f_go_runtime);
+ Swig_register_filebyname("go_header", f_go_header);
+ Swig_register_filebyname("go_wrapper", f_go_wrappers);
+ if (!gccgo_flag) {
+ Swig_register_filebyname("gc_begin", f_gc_begin);
+ Swig_register_filebyname("gc_runtime", f_gc_runtime);
+ Swig_register_filebyname("gc_header", f_gc_header);
+ Swig_register_filebyname("gc_wrapper", f_gc_wrappers);
+ }
+
+ Swig_banner(f_c_begin);
+ if (CPlusPlus) {
+ Printf(f_c_begin, "\n// source: %s\n\n", swig_filename);
+ } else {
+ Printf(f_c_begin, "\n/* source: %s */\n\n", swig_filename);
+ }
+
+ Printf(f_c_runtime, "#define SWIGMODULE %s\n", module);
+ if (gccgo_flag) {
+ Printf(f_c_runtime, "#define SWIGGO_PREFIX %s\n", go_prefix);
+ }
+
+ if (directorsEnabled()) {
+ Printf(f_c_runtime, "#define SWIG_DIRECTORS\n");
+
+ Swig_banner(f_c_directors_h);
+ Printf(f_c_directors_h, "\n// source: %s\n\n", swig_filename);
+
+ Printf(f_c_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module);
+ Printf(f_c_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module);
+
+ Printf(f_c_directors, "\n// C++ director class methods.\n");
+ String *filename = Swig_file_filename(c_filename_h);
+ Printf(f_c_directors, "#include \"%s\"\n\n", filename);
+ Delete(filename);
+ }
+
+ Swig_banner(f_go_begin);
+ Printf(f_go_begin, "\n// source: %s\n", swig_filename);
+
+ if (!gccgo_flag && soname) {
+ Swig_banner(f_gc_begin);
+ Printf(f_gc_begin, "\n/* source: %s */\n\n", swig_filename);
+ Printf(f_gc_begin, "\n/* This file should be compiled with 6c/8c. */\n");
+ Printf(f_gc_begin, "#pragma dynimport _ _ \"%s\"\n", soname);
+ }
+
+ // Output module initialization code.
+
+ Printf(f_go_begin, "\npackage %s\n\n", package);
+
+ if (gccgo_flag) {
+ Printf(f_go_runtime, "func SwigCgocall()\n");
+ Printf(f_go_runtime, "func SwigCgocallDone()\n");
+ Printf(f_go_runtime, "func SwigCgocallBack()\n");
+ Printf(f_go_runtime, "func SwigCgocallBackDone()\n\n");
+ }
+
+ // All the C++ wrappers should be extern "C".
+
+ Printv(f_c_wrappers, "#ifdef __cplusplus\n", "extern \"C\" {\n", "#endif\n\n", NULL);
+
+ // Set up the hash table for types not defined by SWIG.
+
+ undefined_enum_types = NewHash();
+ undefined_types = NewHash();
+ defined_types = NewHash();
+ go_imports = NewHash();
+
+ // Emit code.
+
+ Language::top(n);
+
+ Delete(go_imports);
+
+ // Write out definitions for the types not defined by SWIG.
+
+ if (Len(undefined_enum_types) > 0)
+ Printv(f_go_wrappers, "\n", NULL);
+ for (Iterator p = First(undefined_enum_types); p.key; p = Next(p)) {
+ String *name = p.item;
+ Printv(f_go_wrappers, "type ", name, " int\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "\n", NULL);
+ for (Iterator p = First(undefined_types); p.key; p = Next(p)) {
+ String *ty = goType(NULL, p.key);
+ if (!Getattr(defined_types, ty)) {
+ String *cp = goCPointerType(p.key, false);
+ if (!Getattr(defined_types, cp)) {
+ Printv(f_go_wrappers, "type ", cp, " uintptr\n", NULL);
+ Printv(f_go_wrappers, "type ", ty, " interface {\n", NULL);
+ Printv(f_go_wrappers, "\tSwigcptr() uintptr;\n", NULL);
+ Printv(f_go_wrappers, "}\n", NULL);
+ Printv(f_go_wrappers, "func (p ", cp, ") Swigcptr() uintptr {\n", NULL);
+ Printv(f_go_wrappers, "\treturn uintptr(p)\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+ }
+ Delete(cp);
+ }
+ Delete(ty);
+ }
+ Delete(undefined_enum_types);
+ Delete(undefined_types);
+ Delete(defined_types);
+
+ /* Write and cleanup */
+
+ Dump(f_c_header, f_c_runtime);
+
+ if (directorsEnabled()) {
+ Printf(f_c_directors_h, "#endif\n");
+ Delete(f_c_directors_h);
+ f_c_directors_h = NULL;
+
+ Dump(f_c_directors, f_c_runtime);
+ Delete(f_c_directors);
+ f_c_directors = NULL;
+ }
+
+ // End the extern "C".
+ Printv(f_c_wrappers, "#ifdef __cplusplus\n", "}\n", "#endif\n\n", NULL);
+
+ Dump(f_c_runtime, f_c_begin);
+ Dump(f_c_wrappers, f_c_begin);
+ Dump(f_c_init, f_c_begin);
+ Dump(f_go_imports, f_go_begin);
+ Dump(f_go_header, f_go_begin);
+ Dump(f_go_runtime, f_go_begin);
+ Dump(f_go_wrappers, f_go_begin);
+ if (!gccgo_flag) {
+ Dump(f_gc_header, f_gc_begin);
+ Dump(f_gc_runtime, f_gc_begin);
+ Dump(f_gc_wrappers, f_gc_begin);
+ }
+
+ Delete(f_c_runtime);
+ Delete(f_c_header);
+ Delete(f_c_wrappers);
+ Delete(f_c_init);
+ Delete(f_go_imports);
+ Delete(f_go_runtime);
+ Delete(f_go_header);
+ Delete(f_go_wrappers);
+ if (!gccgo_flag) {
+ Delete(f_gc_runtime);
+ Delete(f_gc_header);
+ Delete(f_gc_wrappers);
+ }
+
+ Delete(f_c_begin);
+ Delete(f_go_begin);
+ if (!gccgo_flag) {
+ Delete(f_gc_begin);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * importDirective()
+ *
+ * Handle a SWIG import statement by generating a Go import
+ * statement.
+ * ------------------------------------------------------------ */
+
+ virtual int importDirective(Node *n) {
+ String *hold_import = imported_package;
+ String *modname = Getattr(n, "module");
+ if (modname) {
+ if (!Getattr(go_imports, modname)) {
+ Setattr(go_imports, modname, modname);
+ Printv(f_go_imports, "import \"", modname, "\"\n", NULL);
+ }
+ imported_package = modname;
+ saw_import = true;
+ }
+ int r = Language::importDirective(n);
+ imported_package = hold_import;
+ return r;
+ }
+
+ /* ----------------------------------------------------------------------
+ * Language::insertDirective()
+ *
+ * If the section is go_imports, store them for later.
+ * ---------------------------------------------------------------------- */
+ virtual int insertDirective(Node *n) {
+ char *section = Char(Getattr(n, "section"));
+ if ((ImportMode && !Getattr(n, "generated")) ||
+ !section || (strcmp(section, "go_imports") != 0)) {
+ return Language::insertDirective(n);
+ }
+
+ char *code = Char(Getattr(n, "code"));
+ char *pch = strtok(code, ",");
+ while (pch != NULL) {
+ // Do not import same thing more than once.
+ if (!Getattr(go_imports, pch)) {
+ Setattr(go_imports, pch, pch);
+ Printv(f_go_imports, "import ", pch, "\n", NULL);
+ }
+ pch = strtok(NULL, ",");
+ }
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * functionWrapper()
+ *
+ * Implement a function.
+ * ---------------------------------------------------------------------- */
+
+ virtual int functionWrapper(Node *n) {
+ if (GetFlag(n, "feature:ignore")) {
+ return SWIG_OK;
+ }
+
+ // We don't need explicit calls.
+ if (GetFlag(n, "explicitcall")) {
+ return SWIG_OK;
+ }
+
+ String *name = Getattr(n, "sym:name");
+ String *nodetype = Getattr(n, "nodeType");
+ bool is_static = is_static_member_function || isStatic(n);
+ bool is_friend = isFriend(n);
+ bool is_ctor_dtor = false;
+
+ SwigType *result = Getattr(n, "type");
+
+ // For some reason SWIG changs the "type" value during the call to
+ // functionWrapper. We need to remember the type for possible
+ // overload processing.
+ Setattr(n, "go:type", Copy(result));
+
+ String *go_name;
+
+ String *r1 = NULL;
+ if (making_variable_wrappers) {
+ // Change the name of the variable setter and getter functions
+ // to be more Go like.
+
+ bool is_set = Strcmp(Char(name) + Len(name) - 4, "_set") == 0;
+ assert(is_set || Strcmp(Char(name) + Len(name) - 4, "_get") == 0);
+
+ // Start with Set or Get.
+ go_name = NewString(is_set ? "Set" : "Get");
+
+ // If this is a static variable, put in the class name,
+ // capitalized.
+ if (is_static && class_name) {
+ String *ccn = exportedName(class_name);
+ Append(go_name, ccn);
+ Delete(ccn);
+ }
+
+ // Add the rest of the name, capitalized, dropping the _set or
+ // _get.
+ String *c1 = removeClassname(name);
+ String *c2 = exportedName(c1);
+ char *p = Char(c2);
+ int len = Len(p);
+ for (int i = 0; i < len - 4; ++i) {
+ Putc(p[i], go_name);
+ }
+ Delete(c2);
+ Delete(c1);
+
+ if (!checkIgnoredParameters(n, go_name)) {
+ Delete(go_name);
+ return SWIG_NOWRAP;
+ }
+ } else if (Cmp(nodetype, "constructor") == 0) {
+ is_ctor_dtor = true;
+
+ // Change the name of a constructor to be more Go like. Change
+ // new_ to New, and capitalize the class name.
+ assert(Strncmp(name, "new_", 4) == 0);
+ String *c1 = NewString(Char(name) + 4);
+ String *c2 = exportedName(c1);
+ go_name = NewString("New");
+ Append(go_name, c2);
+ Delete(c2);
+ Delete(c1);
+
+ if (Swig_methodclass(n) && Swig_directorclass(n)
+ && Strcmp(Char(Getattr(n, "wrap:action")), director_prot_ctor_code) != 0) {
+ // The core SWIG code skips the first parameter when
+ // generating the $nondirector_new string. Recreate the
+ // action in this case. But don't it if we are using the
+ // special code for an abstract class.
+ String *call = Swig_cppconstructor_call(getClassType(),
+ Getattr(n, "parms"));
+ SwigType *type = Copy(getClassType());
+ SwigType_add_pointer(type);
+ String *cres = Swig_cresult(type, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ }
+ } else if (Cmp(nodetype, "destructor") == 0) {
+ // No need to emit protected destructors.
+ if (!is_public(n)) {
+ return SWIG_OK;
+ }
+
+ is_ctor_dtor = true;
+
+ // Change the name of a destructor to be more Go like. Change
+ // delete_ to Delete and capitalize the class name.
+ assert(Strncmp(name, "delete_", 7) == 0);
+ String *c1 = NewString(Char(name) + 7);
+ String *c2 = exportedName(c1);
+ go_name = NewString("Delete");
+ Append(go_name, c2);
+ Delete(c2);
+ Delete(c1);
+
+ result = NewString("void");
+ r1 = result;
+ } else {
+ if (!checkFunctionVisibility(n, NULL)) {
+ return SWIG_OK;
+ }
+
+ go_name = buildGoName(name, is_static, is_friend);
+
+ if (!checkIgnoredParameters(n, go_name)) {
+ Delete(go_name);
+ return SWIG_NOWRAP;
+ }
+ }
+
+ String *overname = NULL;
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ String *scope;
+ if (!class_name || is_static || is_ctor_dtor) {
+ scope = NULL;
+ } else {
+ scope = NewString("swiggoscope.");
+ Append(scope, class_name);
+ }
+ if (!checkNameConflict(go_name, n, scope)) {
+ Delete(go_name);
+ return SWIG_NOWRAP;
+ }
+ }
+
+ String *wname = Swig_name_wrapper(name);
+ if (overname) {
+ Append(wname, overname);
+ }
+ Setattr(n, "wrap:name", wname);
+
+ ParmList *parms = Getattr(n, "parms");
+ Setattr(n, "wrap:parms", parms);
+
+ int r = makeWrappers(n, name, go_name, overname, wname, NULL, parms, result, is_static);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ if (Getattr(n, "sym:overloaded") && !Getattr(n, "sym:nextSibling")) {
+ String *scope ;
+ if (!class_name || is_static || is_ctor_dtor) {
+ scope = NULL;
+ } else {
+ scope = NewString("swiggoscope.");
+ Append(scope, class_name);
+ }
+ if (!checkNameConflict(go_name, n, scope)) {
+ Delete(go_name);
+ return SWIG_NOWRAP;
+ }
+
+ String *receiver = class_receiver;
+ if (is_static || is_ctor_dtor) {
+ receiver = NULL;
+ }
+ r = makeDispatchFunction(n, go_name, receiver, is_static, NULL, false);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ Delete(wname);
+ Delete(go_name);
+ Delete(r1);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ *
+ * For some reason the language code removes the "storage" attribute
+ * for a static function before calling functionWrapper, which means
+ * that we have no way of knowing whether a function is static or
+ * not. That makes no sense in the Go context. Here we note that a
+ * function is static.
+ * ---------------------------------------------------------------------- */
+
+ int staticmemberfunctionHandler(Node *n) {
+ assert(!is_static_member_function);
+ is_static_member_function = true;
+ int r = Language::staticmemberfunctionHandler(n);
+ is_static_member_function = false;
+ return r;
+ }
+
+ /* ----------------------------------------------------------------------
+ * makeWrappers()
+ *
+ * Write out the various function wrappers.
+ * n: The function we are emitting.
+ * name: The function name.
+ * go_name: The name of the function in Go.
+ * overname: The overload string for overloaded function.
+ * wname: The SWIG wrapped name--the name of the C function.
+ * base: A list of the names of base classes, in the case where this
+ * is is a vritual method not defined in the current class.
+ * parms: The parameters.
+ * result: The result type.
+ * is_static: Whether this is a static method or member.
+ * ---------------------------------------------------------------------- */
+
+ int makeWrappers(Node *n, String *name, String *go_name, String *overname, String *wname, List *base, ParmList *parms, SwigType *result, bool is_static) {
+
+ assert(result);
+
+ int r = goFunctionWrapper(n, name, go_name, overname, wname, base, parms, result, is_static);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ if (!gccgo_flag) {
+ r = gcFunctionWrapper(wname);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ r = gccFunctionWrapper(n, base, wname, parms, result);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ } else {
+ r = gccgoFunctionWrapper(n, base, wname, parms, result);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ if (class_methods) {
+ Setattr(class_methods, Getattr(n, "name"), NewString(""));
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * goFunctionWrapper()
+ *
+ * Write out a function wrapper in Go. When not implementing a
+ * method, the actual code is all in C; here we just declare the C
+ * function. When implementing a method, we have to call the C
+ * function, because it will have a different name. If base is not
+ * NULL, then we are being called to forward a virtual method to a
+ * base class.
+ * ---------------------------------------------------------------------- */
+
+ int goFunctionWrapper(Node *n, String *name, String *go_name, String *overname, String *wname, List *base, ParmList *parms, SwigType *result, bool is_static) {
+ Wrapper *dummy = NewWrapper();
+ emit_attach_parmmaps(parms, dummy);
+
+ Parm *p = parms;
+ int parm_count = emit_num_arguments(parms);
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ Swig_cparm_name(p, i);
+ p = nextParm(p);
+ }
+
+ Swig_typemap_attach_parms("default", parms, dummy);
+ Swig_typemap_attach_parms("gotype", parms, dummy);
+ Swig_typemap_attach_parms("goin", parms, dummy);
+ Swig_typemap_attach_parms("goargout", parms, dummy);
+ Swig_typemap_attach_parms("imtype", parms, dummy);
+
+ int required_count = emit_num_required(parms);
+
+ String *receiver = class_receiver;
+ if (receiver && is_static) {
+ receiver = NULL;
+ }
+
+ String *nodetype = Getattr(n, "nodeType");
+ bool is_constructor = Cmp(nodetype, "constructor") == 0;
+ bool is_destructor = Cmp(nodetype, "destructor") == 0;
+ if (is_constructor || is_destructor) {
+ assert(class_receiver);
+ assert(!base);
+ receiver = NULL;
+ }
+
+ String *goout = Swig_typemap_lookup("goout", n, "swig_r", NULL);
+
+ bool add_to_interface = (interfaces && !is_constructor && !is_destructor && !is_static && !overname && checkFunctionVisibility(n, NULL));
+
+ bool needs_wrapper = (gccgo_flag || receiver || is_constructor || is_destructor || parm_count > required_count);
+
+ bool has_goout = false;
+ if (goout) {
+ has_goout = true;
+ }
+
+ // See whether any of the function parameters are represented by
+ // interface values. When calling the C++ code, we need to convert
+ // back to a uintptr.
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *ty = Getattr(p, "type");
+ if (Getattr(p, "tmap:goargout")) {
+ has_goout = true;
+ needs_wrapper = true;
+ } else if (goTypeIsInterface(p, ty) || Getattr(p, "tmap:goin")) {
+ needs_wrapper = true;
+ }
+ p = nextParm(p);
+ }
+ if (goTypeIsInterface(n, result) || goout != NULL) {
+ needs_wrapper = true;
+ }
+
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, "var ", wname, " unsafe.Pointer\n\n", NULL);
+ }
+
+ // If this is a method, first declare the C function we will call.
+ // If we do not need a wrapper, then we will only be writing a
+ // declaration.
+ String *wrapper_name = NULL;
+ if (needs_wrapper) {
+ wrapper_name = buildGoWrapperName(name, overname);
+
+ if (gccgo_flag) {
+ Printv(f_go_wrappers, "//extern ", go_prefix, "_", wname, "\n", NULL);
+ }
+
+ bool arg = false;
+ Printv(f_go_wrappers, "func ", wrapper_name, "(", NULL);
+ if (parm_count > required_count) {
+ Printv(f_go_wrappers, argName(&arg), " int", NULL);
+ }
+ Parm *p = getParm(parms);
+ int i = 0;
+ if (is_destructor) {
+ if (parm_count > required_count) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ Printv(f_go_wrappers, argName(&arg), " uintptr", NULL);
+ ++i;
+ p = nextParm(p);
+ } else if (receiver && (base || !is_constructor)) {
+ if (parm_count > required_count) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ Printv(f_go_wrappers, argName(&arg), " ", receiver, NULL);
+ if (!base) {
+ ++i;
+ p = nextParm(p);
+ }
+ }
+ for (; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0 || (base && receiver) || parm_count > required_count) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ String *tm = goWrapperType(p, Getattr(p, "type"), false);
+ Printv(f_go_wrappers, argName(&arg), " ", tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+ Printv(f_go_wrappers, ")", NULL);
+ if (is_constructor) {
+ Printv(f_go_wrappers, " (", argName(&arg), " ", class_receiver, ")", NULL);
+ } else {
+ if (SwigType_type(result) != T_VOID) {
+ String *tm = goWrapperType(n, result, true);
+ Printv(f_go_wrappers, " (", argName(&arg), " ", tm, ")", NULL);
+ Delete(tm);
+ }
+ }
+
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, " {\n", NULL);
+ if (arg) {
+ Printv(f_go_wrappers, "\t_swig_p := uintptr(unsafe.Pointer(&base))\n", NULL);
+ } else {
+ Printv(f_go_wrappers, "\tvar _swig_p uintptr\n", NULL);
+ }
+ Printv(f_go_wrappers, "\t_cgo_runtime_cgocall(", wname, ", _swig_p)\n", NULL);
+ Printv(f_go_wrappers, "\treturn\n", NULL);
+ Printv(f_go_wrappers, "}", NULL);
+ }
+
+ Printv(f_go_wrappers, "\n\n", NULL);
+ }
+
+ // Start defining the Go function.
+
+ if (!needs_wrapper && gccgo_flag) {
+ Printv(f_go_wrappers, "//extern ", go_prefix, "_", wname, "\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "func ", NULL);
+
+ p = parms;
+ int pi = 0;
+
+ // Add the receiver if this is a method.
+ String *first = NULL;
+ if (receiver) {
+ Printv(f_go_wrappers, "(", NULL);
+ if (base && receiver) {
+ Printv(f_go_wrappers, "_swig_base", NULL);
+ if (first == NULL) {
+ first = NewString("_swig_base");
+ }
+ } else {
+ Printv(f_go_wrappers, Getattr(p, "lname"), NULL);
+ if (first == NULL) {
+ first = Copy(Getattr(p, "lname"));
+ }
+ p = nextParm(p);
+ ++pi;
+ }
+ Printv(f_go_wrappers, " ", receiver, ") ", NULL);
+ }
+
+ Printv(f_go_wrappers, go_name, NULL);
+ if (overname) {
+ Printv(f_go_wrappers, overname, NULL);
+ }
+ Printv(f_go_wrappers, "(", NULL);
+
+ // If we are doing methods, add this function to the interface.
+ if (add_to_interface) {
+ Printv(interfaces, "\t", go_name, "(", NULL);
+ }
+
+ // Write out the parameters to both the function definition and
+ // the interface.
+
+ String *parm_print = NewString("");
+
+ for (; pi < parm_count; ++pi) {
+ p = getParm(p);
+ if (pi == 0 && is_destructor) {
+ String *cl = exportedName(class_name);
+ Printv(parm_print, Getattr(p, "lname"), " ", cl, NULL);
+ if (first == NULL) {
+ first = Copy(Getattr(p, "lname"));
+ }
+ Delete(cl);
+ } else {
+ if (pi > (receiver && !base ? 1 : 0)) {
+ Printv(parm_print, ", ", NULL);
+ }
+ if (pi >= required_count) {
+ Printv(parm_print, "_swig_args ...interface{}", NULL);
+ if (first == NULL) {
+ first = NewString("_swig_args");
+ }
+ break;
+ }
+ Printv(parm_print, Getattr(p, "lname"), " ", NULL);
+ if (first == NULL) {
+ first = Copy(Getattr(p, "lname"));
+ }
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(parm_print, tm, NULL);
+ Delete(tm);
+ }
+ p = nextParm(p);
+ }
+
+ Printv(parm_print, ")", NULL);
+
+ // Write out the result type.
+ if (is_constructor) {
+ String *cl = exportedName(class_name);
+ Printv(parm_print, " (_swig_ret ", cl, ")", NULL);
+ if (first == NULL) {
+ first = NewString("_swig_ret");
+ }
+ Delete(cl);
+ } else {
+ if (SwigType_type(result) != T_VOID) {
+ String *tm = goType(n, result);
+ Printv(parm_print, " (_swig_ret ", tm, ")", NULL);
+ if (first == NULL) {
+ first = NewString("_swig_ret");
+ }
+ Delete(tm);
+ }
+ }
+
+ Printv(f_go_wrappers, parm_print, NULL);
+ if (add_to_interface) {
+ Printv(interfaces, parm_print, "\n", NULL);
+ }
+
+ // If this is a wrapper, we need to actually call the C function.
+ if (needs_wrapper) {
+ Printv(f_go_wrappers, " {\n", NULL);
+
+ if (parm_count > required_count) {
+ Parm *p = parms;
+ int i;
+ for (i = 0; i < required_count; ++i) {
+ p = getParm(p);
+ p = nextParm(p);
+ }
+ for (; i < parm_count; ++i) {
+ p = getParm(p);
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(f_go_wrappers, "\tvar ", Getattr(p, "lname"), " ", tm, "\n", NULL);
+ Printf(f_go_wrappers, "\tif len(_swig_args) > %d {\n", i - required_count);
+ Printf(f_go_wrappers, "\t\t%s = _swig_args[%d].(%s)\n", Getattr(p, "lname"), i - required_count, tm);
+ Printv(f_go_wrappers, "\t}\n", NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+ }
+
+ String *call = NewString("");
+
+ bool need_return_var = SwigType_type(result) != T_VOID && ((gccgo_flag && is_constructor) || has_goout);
+ if (need_return_var) {
+ Printv(f_go_wrappers, "\tvar swig_r ", NULL);
+ if (is_constructor) {
+ String *cl = exportedName(class_name);
+ Printv(f_go_wrappers, cl, NULL);
+ Delete(cl);
+ } else {
+ Printv(f_go_wrappers, goImType(n, result), NULL);
+ }
+ Printv(f_go_wrappers, "\n", NULL);
+ }
+
+ if (gccgo_flag) {
+ if (has_goout || is_constructor) {
+ Printv(call, "\tfunc() {\n", NULL);
+ }
+ Printv(call, "\tdefer SwigCgocallDone()\n", NULL);
+ Printv(call, "\tSwigCgocall()\n", NULL);
+ }
+
+ Printv(call, "\t", NULL);
+ if (SwigType_type(result) != T_VOID) {
+ if (need_return_var) {
+ Printv(call, "swig_r = ", NULL);
+ } else {
+ Printv(call, "return ", NULL);
+ }
+ }
+
+ Printv(call, wrapper_name, "(", NULL);
+
+ if (parm_count > required_count) {
+ Printv(call, "len(_swig_args)", NULL);
+ }
+
+ if (base && receiver) {
+ if (parm_count > required_count) {
+ Printv(call, ", ", NULL);
+ }
+ Printv(call, "_swig_base", NULL);
+ }
+
+ Parm *p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0 || (base && receiver)
+ || parm_count > required_count) {
+ Printv(call, ", ", NULL);
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+
+ String *goin = Getattr(p, "tmap:goin");
+ if (goin == NULL) {
+ Printv(call, ln, NULL);
+ if ((i == 0 && is_destructor) || ((i > 0 || !receiver || base || is_constructor) && goTypeIsInterface(p, pt))) {
+ Printv(call, ".Swigcptr()", NULL);
+ }
+ Setattr(p, "emit:goinput", ln);
+ } else {
+ String *ivar = NewString("");
+ Printf(ivar, "_swig_i_%d", i);
+ String *itm = goImType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(f_go_wrappers, goin, NULL);
+ Delete(goin);
+ Printv(call, ivar, NULL);
+ Setattr(p, "emit:goinput", ivar);
+ }
+
+ p = nextParm(p);
+ }
+ Printv(call, ")\n", NULL);
+
+ if (gccgo_flag && (has_goout || is_constructor)) {
+ Printv(call, "\t}()\n", NULL);
+ }
+
+ Printv(f_go_wrappers, call, NULL);
+ Delete(call);
+
+ goargout(parms, parm_count);
+
+ if (need_return_var) {
+ if (goout == NULL) {
+ Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ } else {
+ String *tm = goType(n, result);
+ Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+ Replaceall(goout, "$input", "swig_r");
+ Replaceall(goout, "$result", "swig_r_1");
+ Printv(f_go_wrappers, goout, NULL);
+ Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+ }
+ }
+
+ Printv(f_go_wrappers, "}\n", NULL);
+ } else if (!gccgo_flag) {
+ // We don't need a wrapper. If we're using gccgo, the function
+ // declaration is all we need--it has a //extern comment to
+ // GCC-compiled wrapper. If we're not using gccgo, we need to
+ // call the GCC-compiled wrapper here.
+ Printv(f_go_wrappers, " {\n", NULL);
+ if (first == NULL) {
+ Printv(f_go_wrappers, "\tvar _swig_p uintptr\n", NULL);
+ } else {
+ Printv(f_go_wrappers, "\t_swig_p := uintptr(unsafe.Pointer(&", first, "))\n", NULL);
+ }
+ Printv(f_go_wrappers, "\t_cgo_runtime_cgocall(", wname, ", _swig_p)\n", NULL);
+ Printv(f_go_wrappers, "\treturn\n", NULL);
+ Printv(f_go_wrappers, "}", NULL);
+ }
+
+ Printv(f_go_wrappers, "\n", NULL);
+
+ Delete(wrapper_name);
+ DelWrapper(dummy);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * argName()
+ *
+ * A helper for goFunctionWrapper to output the first argument name
+ * as "base" and all others as "_".
+ * ---------------------------------------------------------------------- */
+
+ const char *argName(bool *arg) {
+ if (*arg) {
+ return "_";
+ }
+ *arg = true;
+ return "base";
+ }
+
+ /* ----------------------------------------------------------------------
+ * gcFunctionWrapper()
+ *
+ * This is used for 6g/8g, not for gccgo. Write out the function
+ * redirector that will be compiled with 6c/8c. This used to write
+ * out a real function wrapper, but that has moved into Go code.
+ * ---------------------------------------------------------------------- */
+
+ int gcFunctionWrapper(String *wname) {
+ Wrapper *f = NewWrapper();
+
+ Printv(f->def, "#pragma dynimport ", wname, " ", wname, " \"\"\n", NULL);
+ Printv(f->def, "#pragma cgo_import_static ", wname, "\n", NULL);
+ Printv(f->def, "extern void ", wname, "(void*);\n", NULL);
+ // Declare this as a uintptr, since it is not a pointer into the
+ // Go heap.
+ // \xc2\xb7 is UTF-8 for U+00B7 which is Unicode 'Middle Dot'
+ Printv(f->def, "uintptr \xc2\xb7", wname, " = (uintptr)", wname, ";\n", NULL);
+
+ Wrapper_print(f, f_gc_wrappers);
+
+ DelWrapper(f);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * gccFunctionWrapper()
+ *
+ * This is used for 6g/8g, not for gccgo. Write out the function
+ * wrapper which will be compiled with gcc. If the base parameter
+ * is not NULL, this is calls the base class method rather than
+ * executing the SWIG wrapper code.
+ * ---------------------------------------------------------------------- */
+
+ int gccFunctionWrapper(Node *n, List *base, String *wname, ParmList *parms, SwigType *result) {
+ Wrapper *f = NewWrapper();
+
+ Swig_save("gccFunctionWrapper", n, "parms", NULL);
+
+ Parm *base_parm = NULL;
+ if (base && !isStatic(n)) {
+ SwigType *base_type = Copy(getClassType());
+ SwigType_add_pointer(base_type);
+ base_parm = NewParm(base_type, NewString("arg1"), n);
+ set_nextSibling(base_parm, parms);
+ parms = base_parm;
+ }
+
+ emit_parameter_variables(parms, f);
+ emit_attach_parmmaps(parms, f);
+ int parm_count = emit_num_arguments(parms);
+ int required_count = emit_num_required(parms);
+
+ emit_return_variable(n, result, f);
+
+ // Start the function definition.
+
+ Printv(f->def, "void\n", wname, "(void *swig_v)\n", "{\n", NULL);
+
+ // The single function parameter is a pointer to the real argument
+ // values. Define the structure that it points to.
+
+ Printv(f->code, "\tstruct swigargs {\n", NULL);
+
+ if (parm_count > required_count) {
+ Printv(f->code, "\t\tintgo _swig_optargc;\n", NULL);
+ }
+
+ Parm *p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *ln = Getattr(p, "lname");
+ SwigType *pt = Getattr(p, "type");
+ String *ct = gcCTypeForGoValue(p, pt, ln);
+ Printv(f->code, "\t\t\t", ct, ";\n", NULL);
+ Delete(ct);
+ p = nextParm(p);
+ }
+ if (SwigType_type(result) != T_VOID) {
+ Printv(f->code, "\t\tlong : 0;\n", NULL);
+ String *ln = NewString(Swig_cresult_name());
+ String *ct = gcCTypeForGoValue(n, result, ln);
+ Delete(ln);
+ Printv(f->code, "\t\t", ct, ";\n", NULL);
+ Delete(ct);
+
+ ln = NewString("_swig_go_result");
+ ct = gcCTypeForGoValue(n, result, ln);
+ Wrapper_add_local(f, "_swig_go_result", ct);
+ Delete(ct);
+ Delete(ln);
+ }
+ Printv(f->code, "\t} *swig_a = (struct swigargs *) swig_v;\n", NULL);
+
+ Printv(f->code, "\n", NULL);
+
+ // Copy the input arguments out of the structure into the
+ // parameter variables.
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+
+ String *tm = Getattr(p, "tmap:in");
+ if (!tm) {
+ 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));
+ } else {
+ String *ln = Getattr(p, "lname");
+ String *input = NewString("");
+ Printv(input, "swig_a->", ln, NULL);
+ tm = Copy(tm);
+ Replaceall(tm, "$input", input);
+ Setattr(p, "emit:input", input);
+ if (i < required_count) {
+ Printv(f->code, "\t", tm, "\n", NULL);
+ } else {
+ Printf(f->code, "\tif (swig_a->_swig_optargc > %d) {\n", i - required_count);
+ Printv(f->code, "\t\t", tm, "\n", NULL);
+ Printv(f->code, "\t}\n", NULL);
+ }
+ Delete(tm);
+ }
+ p = nextParm(p);
+ }
+
+ Printv(f->code, "\n", NULL);
+
+ // Do the real work of the function.
+
+ checkConstraints(parms, f);
+
+ emitGoAction(n, base, parms, result, f);
+
+ argout(parms, f);
+
+ cleanupFunction(n, f, parms);
+
+ Printv(f->code, "}\n", NULL);
+
+ Wrapper_print(f, f_c_wrappers);
+
+ Swig_restore(n);
+
+ DelWrapper(f);
+ Delete(base_parm);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * gccgoFunctionWrapper()
+ *
+ * This is used for gccgo, not 6g/8g. Write out the function
+ * wrapper which will be compiled with gcc. If the base parameter
+ * is not NULL, this is calls the base class method rather than
+ * executing the SWIG wrapper code.
+ * ---------------------------------------------------------------------- */
+
+ int gccgoFunctionWrapper(Node *n, List *base, String *wname, ParmList *parms, SwigType *result) {
+ Wrapper *f = NewWrapper();
+
+ Swig_save("gccgoFunctionWrapper", n, "parms", NULL);
+
+ Parm *base_parm = NULL;
+ if (base && !isStatic(n)) {
+ SwigType *base_type = Copy(getClassType());
+ SwigType_add_pointer(base_type);
+ base_parm = NewParm(base_type, NewString("arg1"), n);
+ set_nextSibling(base_parm, parms);
+ parms = base_parm;
+ }
+
+ emit_parameter_variables(parms, f);
+ emit_attach_parmmaps(parms, f);
+ int parm_count = emit_num_arguments(parms);
+ int required_count = emit_num_required(parms);
+
+ emit_return_variable(n, result, f);
+
+ // Start the function definition.
+
+ String *fnname = NewString("");
+ Printv(fnname, "go_", wname, "(", NULL);
+
+ if (parm_count > required_count) {
+ Printv(fnname, "intgo _swig_optargc", NULL);
+ }
+
+ Parm *p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ SwigType *pt = Copy(Getattr(p, "type"));
+ if (SwigType_isarray(pt)) {
+ SwigType_del_array(pt);
+ SwigType_add_pointer(pt);
+ }
+ String *pn = NewString("g");
+ Append(pn, Getattr(p, "lname"));
+ String *ct = gccgoCTypeForGoValue(p, pt, pn);
+ if (i > 0 || parm_count > required_count) {
+ Printv(fnname, ", ", NULL);
+ }
+ Printv(fnname, ct, NULL);
+ Delete(ct);
+ Delete(pn);
+ Delete(pt);
+ p = nextParm(p);
+ }
+
+ Printv(fnname, ")", NULL);
+
+ String *fndef = NewString("");
+ if (SwigType_type(result) == T_VOID) {
+ Printv(fndef, "void ", fnname, NULL);
+ } else {
+ String *ct = gccgoCTypeForGoValue(n, result, fnname);
+ Printv(fndef, ct, NULL);
+ Delete(ct);
+ }
+
+ Printv(f->def, fndef, " __asm__(\"", go_prefix, "_", wname, "\");\n", NULL);
+
+ Printv(f->def, fndef, " {\n", NULL);
+
+ Delete(fnname);
+ Delete(fndef);
+
+ if (SwigType_type(result) != T_VOID) {
+ String *ln = NewString("_swig_go_result");
+ String *ct = gccgoCTypeForGoValue(n, result, ln);
+ Wrapper_add_local(f, "_swig_go_result", ct);
+ Delete(ct);
+ Delete(ln);
+ }
+
+ // Copy the parameters into the variables which hold their values,
+ // applying appropriate transformations.
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+
+ String *tm = Getattr(p, "tmap:in");
+ if (!tm) {
+ 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));
+ } else {
+ String *ln = Getattr(p, "lname");
+ String *pn = NewString("g");
+ Append(pn, ln);
+ tm = Copy(tm);
+ Replaceall(tm, "$input", pn);
+ Setattr(p, "emit:input", pn);
+ if (i < required_count) {
+ Printv(f->code, " ", tm, "\n", NULL);
+ } else {
+ Printf(f->code, " if (_swig_optargc > %d) {\n", i - required_count);
+ Printv(f->code, " ", tm, "\n", NULL);
+ Printv(f->code, " }\n", NULL);
+ }
+ Delete(tm);
+ }
+
+ p = nextParm(p);
+ }
+
+ Printv(f->code, "\n", NULL);
+
+ // Do the real work of the function.
+
+ checkConstraints(parms, f);
+
+ emitGoAction(n, base, parms, result, f);
+
+ argout(parms, f);
+
+ cleanupFunction(n, f, parms);
+
+ if (SwigType_type(result) != T_VOID) {
+ Printv(f->code, " return _swig_go_result;\n", NULL);
+ }
+
+ Printv(f->code, "}\n", NULL);
+
+ Wrapper_print(f, f_c_wrappers);
+
+ Swig_restore(n);
+
+ DelWrapper(f);
+ Delete(base_parm);
+
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * checkConstraints()
+ *
+ * Check parameter constraints if any. This is used for the C/C++
+ * function. This assumes that each parameter has an "emit:input"
+ * property with the name to use to refer to that parameter.
+ * ----------------------------------------------------------------------- */
+
+ void checkConstraints(ParmList *parms, Wrapper *f) {
+ Parm *p = parms;
+ while (p) {
+ String *tm = Getattr(p, "tmap:check");
+ if (!tm) {
+ p = nextSibling(p);
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(f->code, tm, "\n\n", NULL);
+ Delete(tm);
+ p = Getattr(p, "tmap:check:next");
+ }
+ }
+ }
+
+ /* -----------------------------------------------------------------------
+ * emitGoAction()
+ *
+ * Emit the action of the function. This is used for the C/C++ function.
+ * ----------------------------------------------------------------------- */
+
+ void emitGoAction(Node *n, List *base, ParmList *parms, SwigType *result, Wrapper *f) {
+ if (!gccgo_flag && SwigType_type(result) != T_VOID) {
+ Wrapper_add_local(f, "swig_stktop", "char *swig_stktop");
+ Printv(f->code, "\tswig_stktop = _swig_topofstack();\n", NULL);
+ }
+ String *actioncode;
+ if (!base || isStatic(n)) {
+ Swig_director_emit_dynamic_cast(n, f);
+ actioncode = emit_action(n);
+ } else {
+ // Call the base class method.
+ actioncode = NewString("");
+
+ String *current = NewString("");
+ if (!gccgo_flag) {
+ Printv(current, "swig_a->", NULL);
+ }
+ Printv(current, Getattr(parms, "lname"), NULL);
+
+ int vc = 0;
+ for (Iterator bi = First(base); bi.item; bi = Next(bi)) {
+ Printf(actioncode, " %s *swig_b%d = (%s *)%s;\n", bi.item, vc, bi.item, current);
+ Delete(current);
+ current = NewString("");
+ Printf(current, "swig_b%d", vc);
+ ++vc;
+ }
+
+ String *code = Copy(Getattr(n, "wrap:action"));
+ Replaceall(code, Getattr(parms, "lname"), current);
+ Printv(actioncode, code, "\n", NULL);
+ }
+
+ Swig_save("emitGoAction", n, "type", "tmap:out", NULL);
+
+ Setattr(n, "type", result);
+
+ String *tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode);
+ if (!tm) {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s\n", SwigType_str(result, 0));
+ } else {
+ Replaceall(tm, "$result", "_swig_go_result");
+ if (GetFlag(n, "feature:new")) {
+ Replaceall(tm, "$owner", "1");
+ } else {
+ Replaceall(tm, "$owner", "0");
+ }
+ Printv(f->code, tm, "\n", NULL);
+ Delete(tm);
+ }
+
+ if (!gccgo_flag && SwigType_type(result) != T_VOID) {
+ // If the function called back into the Go code, the stack might
+ // have been copied. We need to adjust swig_a accordingly here.
+ // This is what cgo does.
+ Printv(f->code, "\tswig_a = (struct swigargs*)((char*)swig_a + (_swig_topofstack() - swig_stktop));\n", NULL);
+ Printv(f->code, "\tswig_a->", Swig_cresult_name(), " = ", "_swig_go_result;\n", NULL);
+ }
+
+ Swig_restore(n);
+ }
+
+ /* -----------------------------------------------------------------------
+ * argout()
+ *
+ * Handle argument output code if any. This is used for the C/C++
+ * function. This assumes that each parameter has an "emit:input"
+ * property with the name to use to refer to that parameter.
+ * ----------------------------------------------------------------------- */
+
+ void argout(ParmList *parms, Wrapper *f) {
+ Parm *p = parms;
+ while (p) {
+ String *tm = Getattr(p, "tmap:argout");
+ if (!tm) {
+ p = nextSibling(p);
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$result", Swig_cresult_name());
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(f->code, tm, "\n", NULL);
+ Delete(tm);
+ p = Getattr(p, "tmap:argout:next");
+ }
+ }
+ }
+
+ /* -----------------------------------------------------------------------
+ * goargout()
+ *
+ * Handle Go argument output code if any. This is used for the Go
+ * function. This assumes that each parameter has an "emit:goinput"
+ * property with the name to use to refer to that parameter.
+ * ----------------------------------------------------------------------- */
+
+ void goargout(ParmList *parms, int parm_count) {
+ Parm *p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *tm = Getattr(p, "tmap:goargout");
+ if (!tm) {
+ p = nextSibling(p);
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$result", "swig_r");
+ Replaceall(tm, "$input", Getattr(p, "emit:goinput"));
+ Printv(f_go_wrappers, tm, NULL);
+ Delete(tm);
+ p = Getattr(p, "tmap:goargout:next");
+ }
+ }
+ }
+
+ /* -----------------------------------------------------------------------
+ * freearg()
+ *
+ * Handle argument cleanup code if any. This is used for the C/C++
+ * function. This assumes that each parameter has an "emit:input"
+ * property with the name to use to refer to that parameter.
+ * ----------------------------------------------------------------------- */
+
+ String *freearg(ParmList *parms) {
+ String *ret = NewString("");
+ Parm *p = parms;
+ while (p) {
+ String *tm = Getattr(p, "tmap:freearg");
+ if (!tm) {
+ p = nextSibling(p);
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(ret, tm, "\n", NULL);
+ Delete(tm);
+ p = Getattr(p, "tmap:freearg:next");
+ }
+ }
+ return ret;
+ }
+
+ /* -----------------------------------------------------------------------
+ * cleanupFunction()
+ *
+ * Final function cleanup code.
+ * ----------------------------------------------------------------------- */
+
+ void cleanupFunction(Node *n, Wrapper *f, ParmList *parms) {
+ String *cleanup = freearg(parms);
+ Printv(f->code, cleanup, NULL);
+
+ if (GetFlag(n, "feature:new")) {
+ String *tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0);
+ if (tm) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printv(f->code, tm, "\n", NULL);
+ Delete(tm);
+ }
+ }
+
+ Replaceall(f->code, "$cleanup", cleanup);
+ Delete(cleanup);
+
+ Replaceall(f->code, "$symname", Getattr(n, "sym:name"));
+ }
+
+ /* -----------------------------------------------------------------------
+ * variableHandler()
+ *
+ * This exists just to set the making_variable_wrappers flag.
+ * ----------------------------------------------------------------------- */
+
+ virtual int variableHandler(Node *n) {
+ assert(!making_variable_wrappers);
+ making_variable_wrappers = true;
+ int r = Language::variableHandler(n);
+ making_variable_wrappers = false;
+ return r;
+ }
+
+ /* -----------------------------------------------------------------------
+ * constantWrapper()
+ *
+ * Product a const declaration.
+ * ------------------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ SwigType *type = Getattr(n, "type");
+
+ if (!SwigType_issimple(type) && SwigType_type(type) != T_STRING) {
+ return goComplexConstant(n, type);
+ }
+
+ if (Swig_storage_isstatic(n)) {
+ return goComplexConstant(n, type);
+ }
+
+ String *go_name = buildGoName(Getattr(n, "sym:name"), false, false);
+
+ String *tm = goType(n, type);
+ String *value = Getattr(n, "value");
+
+ String *copy = NULL;
+ if (SwigType_type(type) == T_BOOL) {
+ if (Cmp(value, "true") != 0 && Cmp(value, "false") != 0) {
+ return goComplexConstant(n, type);
+ }
+ } else if (SwigType_type(type) == T_STRING || SwigType_type(type) == T_CHAR) {
+ // Backslash sequences are somewhat different in Go and C/C++.
+ if (Strchr(value, '\\') != 0) {
+ return goComplexConstant(n, type);
+ }
+ } else {
+ // Accept a 0x prefix, and strip combinations of u and l
+ // suffixes. Otherwise accept digits, decimal point, and
+ // exponentiation. Treat anything else as too complicated to
+ // handle as a Go constant.
+ char *p = Char(value);
+ int len = strlen(p);
+ bool need_copy = false;
+ while (len > 0) {
+ char c = p[len - 1];
+ if (c != 'l' && c != 'L' && c != 'u' && c != 'U') {
+ break;
+ }
+ --len;
+ need_copy = true;
+ }
+ bool is_hex = false;
+ int i = 0;
+ if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
+ i = 2;
+ is_hex = true;
+ }
+ for (; i < len; ++i) {
+ switch (p[i]) {
+ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'f': case 'A': case 'B': case 'C': case 'D': case 'F':
+ if (!is_hex) {
+ return goComplexConstant(n, type);
+ }
+ break;
+ case '.': case 'e': case 'E': case '+': case '-':
+ break;
+ default:
+ return goComplexConstant(n, type);
+ }
+ }
+ if (need_copy) {
+ copy = Copy(value);
+ Replaceall(copy, p + len, "");
+ value = copy;
+ }
+ }
+
+ if (!checkNameConflict(go_name, n, NULL)) {
+ Delete(tm);
+ Delete(go_name);
+ Delete(copy);
+ return SWIG_NOWRAP;
+ }
+
+ Printv(f_go_wrappers, "const ", go_name, " ", tm, " = ", NULL);
+ if (SwigType_type(type) == T_STRING) {
+ Printv(f_go_wrappers, "\"", value, "\"", NULL);
+ } else if (SwigType_type(type) == T_CHAR) {
+ Printv(f_go_wrappers, "'", value, "'", NULL);
+ } else {
+ Printv(f_go_wrappers, value, NULL);
+ }
+
+ Printv(f_go_wrappers, "\n", NULL);
+
+ Delete(tm);
+ Delete(go_name);
+ Delete(copy);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * enumDeclaration()
+ *
+ * A C++ enum type turns into a Named go int type.
+ * ---------------------------------------------------------------------- */
+
+ virtual int enumDeclaration(Node *n) {
+ String *name = goEnumName(n);
+ if (Strcmp(name, "int") != 0) {
+ if (!ImportMode || !imported_package) {
+ if (!checkNameConflict(name, n, NULL)) {
+ Delete(name);
+ return SWIG_NOWRAP;
+ }
+ Printv(f_go_wrappers, "type ", name, " int\n", NULL);
+ } else {
+ String *nw = NewString("");
+ Printv(nw, imported_package, ".", name, NULL);
+ Setattr(n, "go:enumname", nw);
+ }
+ }
+ Delete(name);
+
+ return Language::enumDeclaration(n);
+ }
+
+ /* -----------------------------------------------------------------------
+ * enumvalueDeclaration()
+ *
+ * Declare a single value of an enum type. We fetch the value by
+ * calling a C/C++ function.
+ * ------------------------------------------------------------------------ */
+
+ virtual int enumvalueDeclaration(Node *n) {
+ if (!is_public(n)) {
+ return SWIG_OK;
+ }
+ if (Getattr(parentNode(n), "unnamed")) {
+ Setattr(n, "type", NewString("int"));
+ } else {
+ Setattr(n, "type", Getattr(parentNode(n), "enumtype"));
+ }
+ return goComplexConstant(n, Getattr(n, "type"));
+ }
+
+ /* -----------------------------------------------------------------------
+ * goComplexConstant()
+ *
+ * Handle a const declaration for something which is not a Go constant.
+ * ------------------------------------------------------------------------ */
+
+ int goComplexConstant(Node *n, SwigType *type) {
+ String *symname = Getattr(n, "sym:name");
+ if (!symname) {
+ symname = Getattr(n, "name");
+ }
+
+ String *varname = buildGoName(symname, true, false);
+
+ if (!checkNameConflict(varname, n, NULL)) {
+ Delete(varname);
+ return SWIG_NOWRAP;
+ }
+
+ String *get = NewString("");
+ Printv(get, Swig_cresult_name(), " = ", NULL);
+
+ char quote;
+ if (Getattr(n, "wrappedasconstant")) {
+ quote = '\0';
+ } else if (SwigType_type(type) == T_CHAR) {
+ quote = '\'';
+ } else if (SwigType_type(type) == T_STRING) {
+ quote = '"';
+ } else {
+ quote = '\0';
+ }
+
+ if (quote != '\0') {
+ Printf(get, "%c", quote);
+ }
+
+ Printv(get, Getattr(n, "value"), NULL);
+
+ if (quote != '\0') {
+ Printf(get, "%c", quote);
+ }
+
+ Printv(get, ";\n", NULL);
+ Setattr(n, "wrap:action", get);
+
+ String *sname = Copy(symname);
+ if (class_name) {
+ Append(sname, "_");
+ Append(sname, class_name);
+ }
+
+ String *go_name = NewString("_swig_get");
+ if (class_name) {
+ Append(go_name, class_name);
+ Append(go_name, "_");
+ }
+ Append(go_name, sname);
+
+ String *wname = Swig_name_wrapper(sname);
+ Setattr(n, "wrap:name", wname);
+
+ int r = makeWrappers(n, sname, go_name, NULL, wname, NULL, NULL, type, true);
+
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ String *t = goType(n, type);
+ Printv(f_go_wrappers, "var ", varname, " ", t, " = ", go_name, "()\n", NULL);
+
+ Delete(varname);
+ Delete(t);
+ Delete(go_name);
+ Delete(sname);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ *
+ * For a C++ class, in Go we generate both a struct and an
+ * interface. The interface will declare all the class public
+ * methods. We will define all the methods on the struct, so that
+ * the struct meets the interface. We then expect users of the
+ * class to use the interface.
+ * ------------------------------------------------------------ */
+
+ virtual int classHandler(Node *n) {
+ class_node = n;
+
+ List *baselist = Getattr(n, "bases");
+ bool has_base_classes = baselist && Len(baselist) > 0;
+
+ String *name = Getattr(n, "sym:name");
+
+ String *go_name = exportedName(name);
+
+ if (!checkNameConflict(go_name, n, NULL)) {
+ Delete(go_name);
+ SetFlag(n, "go:conflict");
+ return SWIG_NOWRAP;
+ }
+
+ String *go_type_name = goCPointerType(Getattr(n, "classtypeobj"), true);
+
+ class_name = name;
+ class_receiver = go_type_name;
+ class_methods = NewHash();
+
+ int isdir = GetFlag(n, "feature:director");
+ int isnodir = GetFlag(n, "feature:nodirector");
+ bool is_director = isdir && !isnodir;
+
+ Printv(f_go_wrappers, "type ", go_type_name, " uintptr\n\n", NULL);
+
+ // A method to return the pointer to the C++ class. This is used
+ // by generated code to convert between the interface and the C++
+ // value.
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") Swigcptr() uintptr {\n", NULL);
+ Printv(f_go_wrappers, "\treturn (uintptr)(p)\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ // A method used as a marker for the class, to avoid invalid
+ // interface conversions when using multiple inheritance.
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") SwigIs", go_name, "() {\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ if (is_director) {
+ // Return the interface passed to the NewDirector function.
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") DirectorInterface() interface{} {\n", NULL);
+ Printv(f_go_wrappers, "\treturn nil\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+ }
+
+ // We have seen a definition for this type.
+ Setattr(defined_types, go_name, go_name);
+ Setattr(defined_types, go_type_name, go_type_name);
+
+ interfaces = NewString("");
+
+ int r = Language::classHandler(n);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ if (has_base_classes) {
+ // For each method defined in a base class but not defined in
+ // this class, we need to define the method in this class. We
+ // can't use anonymous field inheritance because it works
+ // differently in Go and in C++.
+
+ Hash *local = NewHash();
+ for (Node *ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
+
+ if (!is_public(ni)) {
+ continue;
+ }
+
+ String *type = Getattr(ni, "nodeType");
+ if (Cmp(type, "constructor") == 0 || Cmp(type, "destructor") == 0) {
+ continue;
+ }
+
+ String *cname = Getattr(ni, "sym:name");
+ if (!cname) {
+ cname = Getattr(ni, "name");
+ }
+ if (cname) {
+ Setattr(local, cname, NewString(""));
+ }
+ }
+
+ for (Iterator b = First(baselist); b.item; b = Next(b)) {
+ List *bases = NewList();
+ Append(bases, Getattr(b.item, "classtype"));
+ int r = addBase(n, b.item, bases, local);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ Delete(bases);
+ }
+
+ Delete(local);
+
+ Hash *parents = NewHash();
+ addFirstBaseInterface(n, parents, baselist);
+ int r = addExtraBaseInterfaces(n, parents, baselist);
+ Delete(parents);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ Printv(f_go_wrappers, "type ", go_name, " interface {\n", NULL);
+ Printv(f_go_wrappers, "\tSwigcptr() uintptr\n", NULL);
+ Printv(f_go_wrappers, "\tSwigIs", go_name, "()\n", NULL);
+
+ if (is_director) {
+ Printv(f_go_wrappers, "\tDirectorInterface() interface{}\n", NULL);
+ }
+
+ Append(f_go_wrappers, interfaces);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+ Delete(interfaces);
+
+ interfaces = NULL;
+ class_name = NULL;
+ class_receiver = NULL;
+ class_node = NULL;
+ Delete(class_methods);
+ class_methods = NULL;
+
+ Delete(go_type_name);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * addBase()
+ *
+ * Implement methods and members defined in a parent class for a
+ * child class.
+ * ------------------------------------------------------------ */
+
+ int addBase(Node *n, Node *base, List *bases, Hash *local) {
+ if (GetFlag(base, "feature:ignore")) {
+ return SWIG_OK;
+ }
+
+ for (Node *ni = Getattr(base, "firstChild"); ni; ni = nextSibling(ni)) {
+
+ if (GetFlag(ni, "feature:ignore")) {
+ continue;
+ }
+
+ if (!is_public(ni)) {
+ continue;
+ }
+
+ String *type = Getattr(ni, "nodeType");
+ if (Strcmp(type, "constructor") == 0 || Strcmp(type, "destructor") == 0 || Strcmp(type, "enum") == 0 || Strcmp(type, "using") == 0 || Strcmp(type, "classforward") == 0 || Strcmp(type, "template") == 0) {
+ continue;
+ }
+ String *storage = Getattr(ni, "storage");
+ if (storage && (Strcmp(storage, "typedef") == 0 || Strcmp(storage, "friend") == 0)) {
+ continue;
+ }
+
+ String *mname = Getattr(ni, "sym:name");
+ if (!mname) {
+ continue;
+ }
+
+ String *lname = Getattr(ni, "name");
+ if (Getattr(class_methods, lname)) {
+ continue;
+ }
+ if (Getattr(local, lname)) {
+ continue;
+ }
+ Setattr(local, lname, NewString(""));
+
+ String *ty = NewString(Getattr(ni, "type"));
+ SwigType_push(ty, Getattr(ni, "decl"));
+ String *fullty = SwigType_typedef_resolve_all(ty);
+ bool is_function = SwigType_isfunction(fullty) ? true : false;
+ Delete(ty);
+ Delete(fullty);
+
+ if (is_function) {
+ int r = goBaseMethod(n, bases, ni);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ if (Getattr(ni, "sym:overloaded")) {
+ for (Node *on = Getattr(ni, "sym:nextSibling"); on; on = Getattr(on, "sym:nextSibling")) {
+ r = goBaseMethod(n, bases, on);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ String *receiver = class_receiver;
+ bool is_static = isStatic(ni);
+ if (is_static) {
+ receiver = NULL;
+ }
+ String *go_name = buildGoName(Getattr(ni, "sym:name"), is_static, false);
+ r = makeDispatchFunction(ni, go_name, receiver, is_static, NULL, false);
+ Delete(go_name);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+ } else {
+ int r = goBaseVariable(n, bases, ni);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+ }
+
+ List *baselist = Getattr(base, "bases");
+ if (baselist && Len(baselist) > 0) {
+ for (Iterator b = First(baselist); b.item; b = Next(b)) {
+ List *nb = Copy(bases);
+ Append(nb, Getattr(b.item, "classtype"));
+ int r = addBase(n, b.item, nb, local);
+ Delete(nb);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * goBaseMethod()
+ *
+ * Implement a method defined in a parent class for a child class.
+ * ------------------------------------------------------------ */
+
+ int goBaseMethod(Node *method_class, List *bases, Node *method) {
+ String *symname = Getattr(method, "sym:name");
+ if (!validIdentifier(symname)) {
+ return SWIG_OK;
+ }
+
+ String *name = NewString("");
+ Printv(name, Getattr(method_class, "sym:name"), "_", symname, NULL);
+
+ bool is_static = isStatic(method);
+
+ String *go_name = buildGoName(name, is_static, false);
+
+ String *overname = NULL;
+ if (Getattr(method, "sym:overloaded")) {
+ overname = Getattr(method, "sym:overname");
+ }
+ String *wname = Swig_name_wrapper(name);
+ if (overname) {
+ Append(wname, overname);
+ }
+
+ String *result = NewString(Getattr(method, "type"));
+ SwigType_push(result, Getattr(method, "decl"));
+ if (SwigType_isqualifier(result)) {
+ Delete(SwigType_pop(result));
+ }
+ Delete(SwigType_pop_function(result));
+
+ // If the base method is imported, wrap:action may not be set.
+ Swig_save("goBaseMethod", method, "wrap:name", "wrap:action", "parms", NULL);
+ Setattr(method, "wrap:name", wname);
+ if (!Getattr(method, "wrap:action")) {
+ if (!is_static) {
+ Swig_MethodToFunction(method, getNSpace(), getClassType(), (Getattr(method, "template") ? SmartPointer : Extend | SmartPointer), NULL, false);
+ // Remove any self parameter that was just added.
+ ParmList *parms = Getattr(method, "parms");
+ if (parms && Getattr(parms, "self")) {
+ parms = CopyParmList(nextSibling(parms));
+ Setattr(method, "parms", parms);
+ }
+ } else {
+ String *call = Swig_cfunction_call(Getattr(method, "name"), Getattr(method, "parms"));
+ Setattr(method, "wrap:action", Swig_cresult(Getattr(method, "type"), Swig_cresult_name(), call));
+ }
+ }
+
+ int r = makeWrappers(method, name, go_name, overname, wname, bases, Getattr(method, "parms"), result, is_static);
+
+ Swig_restore(method);
+
+ Delete(result);
+ Delete(go_name);
+ Delete(name);
+
+ return r;
+ }
+
+ /* ------------------------------------------------------------
+ * goBaseVariable()
+ *
+ * Add accessors for a member variable defined in a parent class for
+ * a child class.
+ * ------------------------------------------------------------ */
+
+ int goBaseVariable(Node *var_class, List *bases, Node *var) {
+ if (isStatic(var)) {
+ return SWIG_OK;
+ }
+
+ String *var_name = buildGoName(Getattr(var, "sym:name"), false, false);
+
+ Swig_save("goBaseVariable", var, "type", "wrap:action", NULL);
+
+ // For a pointer type we apparently have to wrap in the decl.
+ SwigType *var_type = NewString(Getattr(var, "type"));
+ SwigType_push(var_type, Getattr(var, "decl"));
+ Setattr(var, "type", var_type);
+
+ SwigType *vt = Copy(var_type);
+ if (SwigType_isclass(vt)) {
+ SwigType_add_pointer(vt);
+ }
+
+ int flags = Extend | SmartPointer | use_naturalvar_mode(var);
+ if (isNonVirtualProtectedAccess(var)) {
+ flags |= CWRAP_ALL_PROTECTED_ACCESS;
+ }
+
+ String *mname = Swig_name_member(getNSpace(), Getattr(var_class, "sym:name"), var_name);
+
+ if (is_assignable(var)) {
+ for (Iterator ki = First(var); ki.key; ki = Next(ki)) {
+ if (Strncmp(ki.key, "tmap:", 5) == 0) {
+ Delattr(var, ki.key);
+ }
+ }
+ Swig_save("goBaseVariableSet", var, "name", "sym:name", "type", NULL);
+
+ String *mname_set = NewString("Set");
+ Append(mname_set, mname);
+
+ String *go_name = NewString("Set");
+ Append(go_name, var_name);
+
+ Swig_MembersetToFunction(var, class_name, flags);
+
+ String *wname = Swig_name_wrapper(mname_set);
+ ParmList *parms = NewParm(vt, var_name, var);
+ String *result = NewString("void");
+ int r = makeWrappers(var, mname_set, go_name, NULL, wname, bases, parms, result, false);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ Delete(wname);
+ Delete(parms);
+ Delete(result);
+ Delete(go_name);
+ Delete(mname_set);
+
+ Swig_restore(var);
+ for (Iterator ki = First(var); ki.key; ki = Next(ki)) {
+ if (Strncmp(ki.key, "tmap:", 5) == 0) {
+ Delattr(var, ki.key);
+ }
+ }
+ }
+
+ Swig_MembergetToFunction(var, class_name, flags);
+
+ String *mname_get = NewString("Get");
+ Append(mname_get, mname);
+
+ String *go_name = NewString("Get");
+ Append(go_name, var_name);
+
+ String *wname = Swig_name_wrapper(mname_get);
+
+ int r = makeWrappers(var, mname_get, go_name, NULL, wname, bases, NULL, vt, false);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ Delete(wname);
+ Delete(mname_get);
+ Delete(go_name);
+ Delete(mname);
+ Delete(var_name);
+ Delete(var_type);
+ Delete(vt);
+
+ Swig_restore(var);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * addFirstBaseInterface()
+ *
+ * When a C++ class uses multiple inheritance, we can use the C++
+ * pointer for the first base class but not for any subsequent base
+ * classes. However, the Go interface will match the interface for
+ * all the base classes. To avoid accidentally treating a class as
+ * a pointer to a base class other than the first one, we use an
+ * isClassname method. This function adds those methods as
+ * required.
+ *
+ * For convenience when using multiple inheritance, we also add
+ * functions to retrieve the base class pointers.
+ * ------------------------------------------------------------ */
+
+ void addFirstBaseInterface(Node *n, Hash *parents, List *bases) {
+ if (!bases || Len(bases) == 0) {
+ return;
+ }
+ Iterator b = First(bases);
+ if (!GetFlag(b.item, "feature:ignore")) {
+ String *go_name = buildGoName(Getattr(n, "sym:name"), false, false);
+ String *go_type_name = goCPointerType(Getattr(n, "classtypeobj"), true);
+ String *go_base_name = exportedName(Getattr(b.item, "sym:name"));
+ String *go_base_type = goType(n, Getattr(b.item, "classtypeobj"));
+ String *go_base_type_name = goCPointerType(Getattr(b.item, "classtypeobj"), true);
+
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") SwigIs", go_base_name, "() {\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(interfaces, "\tSwigIs", go_base_name, "()\n", NULL);
+
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") SwigGet", go_base_name, "() ", go_base_type, " {\n", NULL);
+ Printv(f_go_wrappers, "\treturn ", go_base_type_name, "(p.Swigcptr())\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(interfaces, "\tSwigGet", go_base_name, "() ", go_base_type, "\n", NULL);
+
+ Setattr(parents, go_base_name, NewString(""));
+
+ Delete(go_name);
+ Delete(go_type_name);
+ Delete(go_base_type);
+ Delete(go_base_type_name);
+ }
+
+ addFirstBaseInterface(n, parents, Getattr(b.item, "bases"));
+ }
+
+ /* ------------------------------------------------------------
+ * addExtraBaseInterfaces()
+ *
+ * Add functions to retrieve the base class pointers for all base
+ * classes other than the first.
+ * ------------------------------------------------------------ */
+
+ int addExtraBaseInterfaces(Node *n, Hash *parents, List *bases) {
+ Iterator b = First(bases);
+
+ Node *fb = b.item;
+
+ for (b = Next(b); b.item; b = Next(b)) {
+ if (GetFlag(b.item, "feature:ignore")) {
+ continue;
+ }
+
+ String *go_base_name = exportedName(Getattr(b.item, "sym:name"));
+
+ Swig_save("addExtraBaseInterface", n, "wrap:action", "wrap:name", "wrap:parms", NULL);
+
+ SwigType *type = Copy(Getattr(n, "classtypeobj"));
+ SwigType_add_pointer(type);
+ Parm *parm = NewParm(type, "self", n);
+ Setattr(n, "wrap:parms", parm);
+
+ String *pn = Swig_cparm_name(parm, 0);
+ String *action = NewString("");
+ Printv(action, Swig_cresult_name(), " = (", Getattr(b.item, "classtype"), "*)", pn, ";", NULL);
+ Delete(pn);
+
+ Setattr(n, "wrap:action", action);
+
+ String *name = Copy(class_name);
+ Append(name, "_SwigGet");
+ Append(name, go_base_name);
+
+ String *go_name = NewString("SwigGet");
+ String *c1 = exportedName(go_base_name);
+ Append(go_name, c1);
+ Delete(c1);
+
+ String *wname = Swig_name_wrapper(name);
+ Setattr(n, "wrap:name", wname);
+
+ SwigType *result = Copy(Getattr(b.item, "classtypeobj"));
+ SwigType_add_pointer(result);
+
+ int r = makeWrappers(n, name, go_name, NULL, wname, NULL, parm, result,
+ false);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ Swig_restore(n);
+
+ Setattr(parents, go_base_name, NewString(""));
+
+ Delete(go_name);
+ Delete(type);
+ Delete(parm);
+ Delete(action);
+ Delete(result);
+
+ String *ns = NewString("");
+ addParentExtraBaseInterfaces(n, parents, b.item, false, ns);
+ Delete(ns);
+ }
+
+ if (!GetFlag(fb, "feature:ignore")) {
+ String *ns = NewString("");
+ addParentExtraBaseInterfaces(n, parents, fb, true, ns);
+ Delete(ns);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * addParentExtraBaseInterfaces()
+ *
+ * Add functions to retrieve the base class pointers for all base
+ * classes of parents other than the first base class at each level.
+ * ------------------------------------------------------------ */
+
+ void addParentExtraBaseInterfaces(Node *n, Hash *parents, Node *base, bool is_base_first, String *sofar) {
+ List *baselist = Getattr(base, "bases");
+ if (!baselist || Len(baselist) == 0) {
+ return;
+ }
+
+ String *go_this_base_name = exportedName(Getattr(base, "sym:name"));
+
+ String *sf = NewString("");
+ Printv(sf, sofar, ".SwigGet", go_this_base_name, "()", NULL);
+
+ Iterator b = First(baselist);
+
+ if (is_base_first) {
+ if (!b.item) {
+ return;
+ }
+ if (!GetFlag(b.item, "feature:ignore")) {
+ addParentExtraBaseInterfaces(n, parents, b.item, true, sf);
+ }
+
+ b = Next(b);
+ }
+
+ String *go_name = buildGoName(Getattr(n, "sym:name"), false, false);
+ String *go_type_name = goCPointerType(Getattr(n, "classtypeobj"), true);
+
+ for (; b.item; b = Next(b)) {
+ if (GetFlag(b.item, "feature:ignore")) {
+ continue;
+ }
+
+ String *go_base_name = exportedName(Getattr(b.item, "sym:name"));
+
+ if (!Getattr(parents, go_base_name)) {
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") SwigGet", go_base_name, "() ", go_base_name, " {\n", NULL);
+ Printv(f_go_wrappers, "\treturn p", sf, ".SwigGet", go_base_name, "()\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(interfaces, "\tSwigGet", go_base_name, "() ", go_base_name, "\n", NULL);
+
+ addParentExtraBaseInterfaces(n, parents, b.item, false, sf);
+
+ Setattr(parents, go_base_name, NewString(""));
+ }
+ }
+
+ Delete(go_name);
+ Delete(go_type_name);
+ Delete(go_this_base_name);
+ Delete(sf);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorInit
+ *
+ * Add support for a director class.
+ *
+ * Virtual inheritance is different in Go and C++. We implement
+ * director classes by defining a new function in Go,
+ * NewDirectorClassname, which takes a empty interface value and
+ * creates an instance of a new child class. The new child class
+ * refers all methods back to Go. The Go code checks whether the
+ * value passed to NewDirectorClassname implements that method; if
+ * it does, it calls it, otherwise it calls back into C++.
+ * ------------------------------------------------------------ */
+
+ int classDirectorInit(Node *n) {
+ // Because we use a different function to handle inheritance in
+ // Go, ordinary creations of the object should not create a
+ // director object.
+ Delete(director_ctor_code);
+ director_ctor_code = NewString("$nondirector_new");
+
+ class_node = n;
+
+ String *name = Getattr(n, "sym:name");
+
+ assert(!class_name);
+ class_name = name;
+
+ String *go_name = exportedName(name);
+
+ String *go_type_name = goCPointerType(Getattr(n, "classtypeobj"), true);
+
+ assert(!class_receiver);
+ class_receiver = go_type_name;
+
+ String *director_struct_name = NewString("_swig_Director");
+ Append(director_struct_name, go_name);
+
+ String *cxx_director_name = NewString("SwigDirector_");
+ Append(cxx_director_name, name);
+
+ // The Go type of the director class.
+ Printv(f_go_wrappers, "type ", director_struct_name, " struct {\n", NULL);
+ Printv(f_go_wrappers, "\t", go_type_name, "\n", NULL);
+ Printv(f_go_wrappers, "\tv interface{}\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(f_go_wrappers, "func (p *", director_struct_name, ") Swigcptr() uintptr {\n", NULL);
+ Printv(f_go_wrappers, "\treturn p.", go_type_name, ".Swigcptr()\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(f_go_wrappers, "func (p *", director_struct_name, ") SwigIs", go_name, "() {\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(f_go_wrappers, "func (p *", director_struct_name, ") DirectorInterface() interface{} {\n", NULL);
+ Printv(f_go_wrappers, "\treturn p.v\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ // Start defining the director class.
+ Printv(f_c_directors_h, "class ", cxx_director_name, " : public ", Getattr(n, "classtype"), "\n", NULL);
+ Printv(f_c_directors_h, "{\n", NULL);
+ Printv(f_c_directors_h, " public:\n", NULL);
+
+ Delete(director_struct_name);
+ Delete(cxx_director_name);
+
+ class_methods = NewHash();
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorConstructor
+ *
+ * Emit a constructor for a director class.
+ * ------------------------------------------------------------ */
+
+ int classDirectorConstructor(Node *n) {
+ bool is_ignored = GetFlag(n, "feature:ignore") ? true : false;
+
+ String *name = Getattr(n, "sym:name");
+ if (!name) {
+ assert(is_ignored);
+ name = Getattr(n, "name");
+ }
+
+ String *overname = NULL;
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ }
+
+ String *go_name = exportedName(name);
+
+ ParmList *parms = Getattr(n, "parms");
+ Setattr(n, "wrap:parms", parms);
+
+ String *cn = exportedName(Getattr(parentNode(n), "sym:name"));
+
+ String *go_type_name = goCPointerType(Getattr(parentNode(n), "classtypeobj"), true);
+
+ String *director_struct_name = NewString("_swig_Director");
+ Append(director_struct_name, cn);
+
+ String *fn_name = NewString("_swig_NewDirector");
+ Append(fn_name, cn);
+ Append(fn_name, go_name);
+
+ if (!overname && !is_ignored) {
+ if (!checkNameConflict(fn_name, n, NULL)) {
+ return SWIG_NOWRAP;
+ }
+ }
+
+ String *wname = Swig_name_wrapper(fn_name);
+
+ if (overname) {
+ Append(wname, overname);
+ }
+ Setattr(n, "wrap:name", wname);
+
+ bool is_static = isStatic(n);
+
+ Wrapper *dummy = NewWrapper();
+ emit_attach_parmmaps(parms, dummy);
+ DelWrapper(dummy);
+
+ Swig_typemap_attach_parms("gotype", parms, NULL);
+ Swig_typemap_attach_parms("imtype", parms, NULL);
+ int parm_count = emit_num_arguments(parms);
+
+ String *func_name = NewString("NewDirector");
+ Append(func_name, go_name);
+
+ String *func_with_over_name = Copy(func_name);
+ if (overname) {
+ Append(func_with_over_name, overname);
+ }
+
+ SwigType *first_type = NewString("void");
+ SwigType_add_pointer(first_type);
+ Parm *first_parm = NewParm(first_type, "swig_p", n);
+ set_nextSibling(first_parm, parms);
+ Setattr(first_parm, "lname", "p");
+
+ Parm *p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ Swig_cparm_name(p, i);
+ p = nextParm(p);
+ }
+
+ if (!is_ignored) {
+ // Declare the C++ wrapper.
+
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, "var ", wname, " unsafe.Pointer\n\n", NULL);
+ } else {
+ Printv(f_go_wrappers, "//extern ", go_prefix, "_", wname, "\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "func ", fn_name, NULL);
+ if (overname) {
+ Printv(f_go_wrappers, overname, NULL);
+ }
+ Printv(f_go_wrappers, "(_swig_director *", director_struct_name, NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(f_go_wrappers, ", _ ", tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ") (_swig_ret ", go_type_name, ")", NULL);
+
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, " {\n", NULL);
+ Printv(f_go_wrappers, "\t_swig_p := uintptr(unsafe.Pointer(&_swig_director))\n", NULL);
+ Printv(f_go_wrappers, "\t_cgo_runtime_cgocall(", wname, ", _swig_p)\n", NULL);
+ Printv(f_go_wrappers, "\treturn\n", NULL);
+ Printv(f_go_wrappers, "}", NULL);
+ }
+
+ Printv(f_go_wrappers, "\n\n", NULL);
+
+ Printv(f_go_wrappers, "func ", func_with_over_name, "(v interface{}", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ // Set the lname parameter.
+ Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", NULL);
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(f_go_wrappers, tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ") ", cn, " {\n", NULL);
+
+ Printv(f_go_wrappers, "\tp := &", director_struct_name, "{0, v}\n", NULL);
+
+ if (gccgo_flag) {
+ Printv(f_go_wrappers, "\tdefer SwigCgocallDone()\n", NULL);
+ Printv(f_go_wrappers, "\tSwigCgocall()\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "\tp.", class_receiver, " = ", fn_name, NULL);
+ if (overname) {
+ Printv(f_go_wrappers, overname, NULL);
+ }
+ Printv(f_go_wrappers, "(p", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ Printv(f_go_wrappers, ", ", Getattr(p, "lname"), NULL);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ")\n", NULL);
+ Printv(f_go_wrappers, "\treturn p\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ SwigType *result = Copy(Getattr(parentNode(n), "classtypeobj"));
+ SwigType_add_pointer(result);
+
+ Swig_save("classDirectorConstructor", n, "wrap:name", "wrap:action", NULL);
+
+ Setattr(n, "wrap:name", Swig_name_wrapper(name));
+
+ String *action = NewString("");
+ Printv(action, Swig_cresult_name(), " = new SwigDirector_", class_name, "(", NULL);
+ String *pname = Swig_cparm_name(NULL, 0);
+ Printv(action, pname, NULL);
+ Delete(pname);
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *pname = Swig_cparm_name(NULL, i + 1);
+ Printv(action, ", ", NULL);
+ if (SwigType_isreference(Getattr(p, "type"))) {
+ Printv(action, "*", NULL);
+ }
+ Printv(action, pname, NULL);
+ Delete(pname);
+ p = nextParm(p);
+ }
+ Printv(action, ");", NULL);
+ Setattr(n, "wrap:action", action);
+
+ if (!gccgo_flag) {
+ int r = gcFunctionWrapper(wname);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ r = gccFunctionWrapper(n, NULL, wname, first_parm, result);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ } else {
+ int r = gccgoFunctionWrapper(n, NULL, wname, first_parm, result);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ Swig_restore(n);
+
+ Delete(result);
+ }
+
+ String *cxx_director_name = NewString("SwigDirector_");
+ Append(cxx_director_name, class_name);
+
+ String *decl = Swig_method_decl(NULL, Getattr(n, "decl"),
+ cxx_director_name, first_parm, 0, 0);
+ Printv(f_c_directors_h, " ", decl, ";\n", NULL);
+ Delete(decl);
+
+ decl = Swig_method_decl(NULL, Getattr(n, "decl"), cxx_director_name, first_parm, 0, 0);
+ Printv(f_c_directors, cxx_director_name, "::", decl, "\n", NULL);
+ Delete(decl);
+
+ Printv(f_c_directors, " : ", Getattr(parentNode(n), "classtype"), "(", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0) {
+ Printv(f_c_directors, ", ", NULL);
+ }
+ String *pn = Getattr(p, "name");
+ assert(pn);
+ Printv(f_c_directors, pn, NULL);
+ p = nextParm(p);
+ }
+ Printv(f_c_directors, "),\n", NULL);
+ Printv(f_c_directors, " go_val(swig_p)\n", NULL);
+ Printv(f_c_directors, "{ }\n\n", NULL);
+
+ if (Getattr(n, "sym:overloaded") && !Getattr(n, "sym:nextSibling")) {
+ int r = makeDispatchFunction(n, func_name, cn, is_static, Getattr(parentNode(n), "classtypeobj"), false);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ Delete(cxx_director_name);
+ Delete(go_name);
+ Delete(cn);
+ Delete(go_type_name);
+ Delete(director_struct_name);
+ Delete(fn_name);
+ Delete(func_name);
+ Delete(func_with_over_name);
+ Delete(wname);
+ Delete(first_type);
+ Delete(first_parm);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDestructor
+ *
+ * Emit a destructor for a director class.
+ * ------------------------------------------------------------ */
+
+ int classDirectorDestructor(Node *n) {
+ if (!is_public(n)) {
+ return SWIG_OK;
+ }
+
+ bool is_ignored = GetFlag(n, "feature:ignore") ? true : false;
+
+ if (!is_ignored) {
+ String *fnname = NewString("DeleteDirector");
+ String *c1 = exportedName(class_name);
+ Append(fnname, c1);
+ Delete(c1);
+
+ String *wname = Swig_name_wrapper(fnname);
+
+ Setattr(n, "wrap:name", fnname);
+
+ Swig_DestructorToFunction(n, getNSpace(), getClassType(), CPlusPlus, Extend);
+
+ ParmList *parms = Getattr(n, "parms");
+ Setattr(n, "wrap:parms", parms);
+
+ String *result = NewString("void");
+ int r = makeWrappers(n, fnname, fnname, NULL, wname, NULL, parms, result, isStatic(n));
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ Delete(result);
+ Delete(fnname);
+ Delete(wname);
+ }
+
+ // Generate the destructor for the C++ director class. Since the
+ // Go code is keeping a pointer to the C++ object, we need to call
+ // back to the Go code to let it know that the C++ object is gone.
+
+ String *wname = NewString("_swiggo_wrap_DeleteDirector_");
+ Append(wname, class_name);
+
+ String *go_name = NewString("Swiggo_DeleteDirector_");
+ Append(go_name, class_name);
+
+ String *cn = exportedName(class_name);
+
+ String *director_struct_name = NewString("_swig_Director");
+ Append(director_struct_name, cn);
+
+ Printv(f_c_directors_h, " virtual ~SwigDirector_", class_name, "()", NULL);
+
+ String *throws = buildThrow(n);
+ if (throws) {
+ Printv(f_c_directors_h, " ", throws, NULL);
+ }
+
+ Printv(f_c_directors_h, ";\n", NULL);
+
+ if (!is_ignored) {
+ if (!gccgo_flag) {
+ Printv(f_c_directors, "extern \"C\" void ", wname, "(void*, int);\n", NULL);
+ } else {
+ Printv(f_c_directors, "extern \"C\" void ", wname, "(void*) __asm__(\"", go_prefix, ".", go_name, "\");\n", NULL);
+ }
+ }
+
+ Printv(f_c_directors, "SwigDirector_", class_name, "::~SwigDirector_", class_name, "()", NULL);
+
+ if (throws) {
+ Printv(f_c_directors, " ", throws, NULL);
+ Delete(throws);
+ }
+
+ Printv(f_c_directors, "\n", NULL);
+ Printv(f_c_directors, "{\n", NULL);
+
+ if (!is_ignored) {
+ if (!gccgo_flag) {
+ Printv(f_c_directors, " struct { void *p; } a;\n", NULL);
+ Printv(f_c_directors, " a.p = go_val;\n", NULL);
+ Printv(f_c_directors, " crosscall2(", wname, ", &a, (int) sizeof a);\n", NULL);
+
+ Printv(f_gc_wrappers, "#pragma dynexport ", wname, " ", wname, "\n", NULL);
+ Printv(f_gc_wrappers, "#pragma cgo_export_static ", wname, " ", wname, "\n", NULL);
+ Printv(f_gc_wrappers, "#pragma textflag 7\n", NULL);
+ Printv(f_gc_wrappers, "extern void \xc2\xb7", go_name, "();\n", NULL);
+ Printv(f_gc_wrappers, "void\n", NULL);
+ Printv(f_gc_wrappers, wname, "(void *a, int32 n)\n", NULL);
+ Printv(f_gc_wrappers, "{\n", NULL);
+ Printv(f_gc_wrappers, "\truntime\xc2\xb7" "cgocallback(\xc2\xb7", go_name, ", a, n);\n", NULL);
+ Printv(f_gc_wrappers, "}\n\n", NULL);
+ } else {
+ Printv(f_c_directors, " ", wname, "(go_val);\n", NULL);
+ }
+ }
+
+ Printv(f_c_directors, "}\n\n", NULL);
+
+ if (!is_ignored) {
+ Printv(f_go_wrappers, "func ", go_name, "(p *", director_struct_name, ") {\n", NULL);
+ Printv(f_go_wrappers, "\tp.", class_receiver, " = 0\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+ }
+
+ Delete(wname);
+ Delete(go_name);
+ Delete(cn);
+ Delete(director_struct_name);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorMethod
+ *
+ * Emit a method for a director class, plus its overloads.
+ * ------------------------------------------------------------ */
+
+ int classDirectorMethod(Node *n, Node *parent, String *super) {
+ bool is_ignored = GetFlag(n, "feature:ignore") ? true : false;
+
+ // We don't need explicit calls.
+ if (GetFlag(n, "explicitcall")) {
+ return SWIG_OK;
+ }
+
+ String *name = Getattr(n, "sym:name");
+ if (!name) {
+ assert(is_ignored);
+ name = Getattr(n, "name");
+ }
+
+ bool overloaded = Getattr(n, "sym:overloaded") && !Getattr(n, "explicitcallnode");
+ if (!overloaded) {
+ int r = oneClassDirectorMethod(n, parent, super);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ } else {
+ // Handle overloaded methods here, because otherwise we will
+ // reject them in the class_methods hash table. We need to use
+ // class_methods so that we correctly handle cases where a
+ // function in one class hides a function of the same name in a
+ // parent class.
+ if (!Getattr(class_methods, name)) {
+ for (Node *on = Getattr(n, "sym:overloaded"); on; on = Getattr(on, "sym:nextSibling")) {
+ // Swig_overload_rank expects wrap:name and wrap:parms to be
+ // set.
+ String *wn = Swig_name_wrapper(Getattr(on, "sym:name"));
+ Append(wn, Getattr(on, "sym:overname"));
+ Setattr(on, "wrap:name", wn);
+ Delete(wn);
+ Setattr(on, "wrap:parms", Getattr(on, "parms"));
+ }
+ }
+
+ int r = oneClassDirectorMethod(n, parent, super);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ if (!Getattr(n, "sym:nextSibling"))
+ {
+ // Last overloaded function
+ Node *on = Getattr(n, "sym:overloaded");
+ bool is_static = isStatic(on);
+
+ String *cn = exportedName(Getattr(parent, "sym:name"));
+ String *go_name = buildGoName(name, is_static, false);
+
+ String *director_struct_name = NewString("_swig_Director");
+ Append(director_struct_name, cn);
+
+ int r = makeDispatchFunction(on, go_name, director_struct_name, is_static, director_struct_name, false);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ if (!GetFlag(n, "abstract")) {
+ String *go_upcall = NewString("Director");
+ Append(go_upcall, cn);
+ Append(go_upcall, go_name);
+ r = makeDispatchFunction(on, go_upcall, director_struct_name, is_static, director_struct_name, true);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ Delete(go_upcall);
+ }
+
+ Delete(director_struct_name);
+ Delete(go_name);
+ Delete(cn);
+ }
+ }
+ Setattr(class_methods, name, NewString(""));
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * oneClassDirectorMethod
+ *
+ * Emit a method for a director class.
+ * ------------------------------------------------------------ */
+
+ int oneClassDirectorMethod(Node *n, Node *parent, String *super) {
+ String *symname = Getattr(n, "sym:name");
+ if (!checkFunctionVisibility(n, parent)) {
+ return SWIG_OK;
+ }
+
+ bool is_ignored = GetFlag(n, "feature:ignore") ? true : false;
+ bool is_pure_virtual = (Cmp(Getattr(n, "storage"), "virtual") == 0 && Cmp(Getattr(n, "value"), "0") == 0);
+
+ String *name = Getattr(n, "sym:name");
+ if (!name) {
+ assert(is_ignored);
+ name = Getattr(n, "name");
+ }
+
+ String *overname = NULL;
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ }
+
+ String *cn = exportedName(Getattr(parent, "sym:name"));
+
+ String *go_type_name = goCPointerType(Getattr(parent, "classtypeobj"), true);
+
+ String *director_struct_name = NewString("_swig_Director");
+ Append(director_struct_name, cn);
+
+ bool is_static = isStatic(n);
+
+ String *go_name = buildGoName(name, is_static, false);
+
+ ParmList *parms = Getattr(n, "parms");
+ Setattr(n, "wrap:parms", parms);
+
+ Wrapper *dummy = NewWrapper();
+ emit_attach_parmmaps(parms, dummy);
+ DelWrapper(dummy);
+
+ Swig_typemap_attach_parms("gotype", parms, NULL);
+ Swig_typemap_attach_parms("imtype", parms, NULL);
+ int parm_count = emit_num_arguments(parms);
+
+ SwigType *result = Getattr(n, "type");
+
+ // Save the type for overload processing.
+ Setattr(n, "go:type", result);
+
+ String *interface_name = NewString("_swig_DirectorInterface");
+ Append(interface_name, cn);
+ Append(interface_name, go_name);
+ if (overname) {
+ Append(interface_name, overname);
+ }
+
+ String *callback_name = Copy(director_struct_name);
+ Append(callback_name, "_callback_");
+ Append(callback_name, name);
+ Replace(callback_name, "_swig", "Swig", DOH_REPLACE_FIRST);
+ if (overname) {
+ Append(callback_name, overname);
+ }
+
+ String *callback_wname = Swig_name_wrapper(callback_name);
+
+ String *upcall_name = Copy(director_struct_name);
+ Append(upcall_name, "_upcall_");
+ Append(upcall_name, go_name);
+
+ String *upcall_wname = Swig_name_wrapper(upcall_name);
+ if (overname) {
+ Append(upcall_wname, overname);
+ }
+
+ String *upcall_gc_name = buildGoWrapperName(upcall_name, overname);
+
+ String *go_with_over_name = Copy(go_name);
+ if (overname) {
+ Append(go_with_over_name, overname);
+ }
+
+ Parm *p = 0;
+ Wrapper *w = NewWrapper();
+
+ Swig_director_parms_fixup(parms);
+
+ Swig_typemap_attach_parms("directorin", parms, w);
+ Swig_typemap_attach_parms("directorargout", parms, w);
+ Swig_typemap_attach_parms("godirectorin", parms, w);
+ Swig_typemap_attach_parms("goin", parms, dummy);
+ Swig_typemap_attach_parms("goargout", parms, dummy);
+
+ if (!is_ignored) {
+ // We use an interface to see if this method is defined in Go.
+ Printv(f_go_wrappers, "type ", interface_name, " interface {\n", NULL);
+ Printv(f_go_wrappers, "\t", go_with_over_name, "(", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(f_go_wrappers, tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ")", NULL);
+
+ if (SwigType_type(result) != T_VOID) {
+ String *tm = goType(n, result);
+ Printv(f_go_wrappers, " ", tm, NULL);
+ Delete(tm);
+ }
+
+ Printv(f_go_wrappers, "\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ if (!GetFlag(n, "abstract")) {
+ // Declare the upcall function, which calls the method on the
+ // parent class.
+
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, "var ", upcall_wname, " unsafe.Pointer\n\n", NULL);
+ } else {
+ Printv(f_go_wrappers, "//extern ", go_prefix, "_", upcall_wname, "\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "func ", upcall_gc_name, "(_swig_ptr ", go_type_name, NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *tm = goWrapperType(p, Getattr(p, "type"), false);
+ Printv(f_go_wrappers, ", _ ", tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ")", NULL);
+
+ if (SwigType_type(result) != T_VOID) {
+ String *tm = goWrapperType(n, result, true);
+ Printv(f_go_wrappers, " (_swig_ret ", tm, ")", NULL);
+ Delete(tm);
+ }
+
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, " {\n", NULL);
+ Printv(f_go_wrappers, "\t_swig_p := uintptr(unsafe.Pointer(&_swig_ptr))\n", NULL);
+ Printv(f_go_wrappers, "\t_cgo_runtime_cgocall(", upcall_wname, ", _swig_p)\n", NULL);
+ Printv(f_go_wrappers, "\treturn\n", NULL);
+ Printv(f_go_wrappers, "}", NULL);
+ }
+
+ Printv(f_go_wrappers, "\n\n", NULL);
+ }
+
+ // Define the method on the director class in Go.
+
+ Printv(f_go_wrappers, "func (swig_p *", director_struct_name, ") ", go_with_over_name, "(", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ Printv(f_go_wrappers, Getattr(p, "lname"), " ", NULL);
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(f_go_wrappers, tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ")", NULL);
+
+ if (SwigType_type(result) != T_VOID) {
+ String *tm = goType(n, result);
+ Printv(f_go_wrappers, " ", tm, NULL);
+ Delete(tm);
+ }
+
+ Printv(f_go_wrappers, " {\n", NULL);
+
+ Printv(f_go_wrappers, "\tif swig_g, swig_ok := swig_p.v.(", interface_name, "); swig_ok {\n", NULL);
+ Printv(f_go_wrappers, "\t\t", NULL);
+ if (SwigType_type(result) != T_VOID) {
+ Printv(f_go_wrappers, "return ", NULL);
+ }
+ Printv(f_go_wrappers, "swig_g.", go_with_over_name, "(", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ Printv(f_go_wrappers, Getattr(p, "lname"), NULL);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ")\n", NULL);
+ if (SwigType_type(result) == T_VOID) {
+ Printv(f_go_wrappers, "\t\treturn\n", NULL);
+ }
+ Printv(f_go_wrappers, "\t}\n", NULL);
+
+ if (GetFlag(n, "abstract")) {
+ Printv(f_go_wrappers, "\tpanic(\"call to pure virtual method\")\n", NULL);
+ } else {
+ bool has_goout = false;
+ String *goout = NULL;
+ if (SwigType_type(result) != T_VOID) {
+ Printv(f_go_wrappers, "\tvar swig_r ", goImType(n, result), "\n", NULL);
+ goout = Swig_typemap_lookup("goout", n, "swig_r", NULL);
+ if (goout) {
+ has_goout = true;
+ }
+ }
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (Getattr(p, "tmap:goargout")) {
+ has_goout = true;
+ }
+ p = nextParm(p);
+ }
+
+ String *call = NewString("");
+
+ if (gccgo_flag) {
+ if (has_goout) {
+ Printv(call, "\tfunc() {\n", NULL);
+ }
+ Printv(call, "\tdefer SwigCgocallDone()\n", NULL);
+ Printv(call, "\tSwigCgocall()\n", NULL);
+ }
+
+ Printv(call, "\t", NULL);
+ if (SwigType_type(result) != T_VOID) {
+ Printv(call, "swig_r = ", NULL);
+ }
+ Printv(call, upcall_gc_name, "(swig_p.", go_type_name, NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ Printv(call, ", ", NULL);
+ p = getParm(p);
+ SwigType *pt = Getattr(p, "type");
+
+ String *ln = Getattr(p, "lname");
+
+ // This is an ordinary call from Go to C++, so adjust using
+ // the goin typemap.
+ String *goin = Getattr(p, "tmap:goin");
+ if (goin == NULL) {
+ Printv(call, ln, NULL);
+ if (goTypeIsInterface(p, pt)) {
+ Printv(call, ".Swigcptr()", NULL);
+ }
+ Setattr(p, "emit:goinput", ln);
+ } else {
+ String *ivar = NewString("");
+ Printf(ivar, "_swig_i_%d", i);
+ String *itm = goImType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(f_go_wrappers, goin, NULL);
+ Delete(goin);
+ Printv(call, ivar, NULL);
+ Setattr(p, "emit:goinput", ivar);
+ }
+
+ p = nextParm(p);
+ }
+
+ Printv(call, ")\n", NULL);
+
+ if (gccgo_flag && has_goout) {
+ Printv(call, "\t}()\n", NULL);
+ }
+
+ Printv(f_go_wrappers, call, NULL);
+ Delete(call);
+
+ goargout(parms, parm_count);
+
+ if (SwigType_type(result) != T_VOID) {
+ if (goout == NULL) {
+ Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ } else {
+ String *tm = goType(n, result);
+ Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+ Replaceall(goout, "$input", "swig_r");
+ Replaceall(goout, "$result", "swig_r_1");
+ Printv(f_go_wrappers, goout, NULL);
+ Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+ }
+ }
+ }
+
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ // Define a method in the C++ director class that the C++ upcall
+ // function can call. This permits an upcall to a protected
+ // method.
+
+ if (!GetFlag(n, "abstract")) {
+ String *upcall_method_name = NewString("_swig_upcall_");
+ Append(upcall_method_name, name);
+ if (overname) {
+ Append(upcall_method_name, overname);
+ }
+ SwigType *rtype = Getattr(n, "classDirectorMethods:type");
+ String *upcall_decl = Swig_method_decl(rtype, Getattr(n, "decl"), upcall_method_name, parms, 0, 0);
+ Printv(f_c_directors_h, " ", upcall_decl, " {\n", NULL);
+ Delete(upcall_decl);
+
+ Printv(f_c_directors_h, " ", NULL);
+ if (SwigType_type(result) != T_VOID) {
+ Printv(f_c_directors_h, "return ", NULL);
+ }
+
+ String *super_call = Swig_method_call(super, parms);
+ Printv(f_c_directors_h, super_call, ";\n", NULL);
+ Delete(super_call);
+
+ Printv(f_c_directors_h, " }\n", NULL);
+
+ // Define the C++ function that the Go function calls.
+
+ SwigType *first_type = NULL;
+ Parm *first_parm = parms;
+ if (!is_static) {
+ first_type = NewString("SwigDirector_");
+ Append(first_type, class_name);
+ SwigType_add_pointer(first_type);
+ first_parm = NewParm(first_type, "p", n);
+ set_nextSibling(first_parm, parms);
+ }
+
+ Swig_save("classDirectorMethod", n, "wrap:name", "wrap:action", NULL);
+
+ Setattr(n, "wrap:name", upcall_wname);
+
+ String *action = NewString("");
+ if (SwigType_type(result) != T_VOID) {
+ Printv(action, Swig_cresult_name(), " = (", SwigType_lstr(result, 0), ")", NULL);
+ if (SwigType_isreference(result)) {
+ Printv(action, "&", NULL);
+ }
+ }
+ Printv(action, Swig_cparm_name(NULL, 0), "->", upcall_method_name, "(", NULL);
+
+ p = parms;
+ int i = 0;
+ while (p != NULL) {
+ if (SwigType_type(Getattr(p, "type")) != T_VOID) {
+ String *pname = Swig_cparm_name(NULL, i + 1);
+ if (i > 0) {
+ Printv(action, ", ", NULL);
+ }
+
+ // A parameter whose type is a reference is converted into a
+ // pointer type by gcCTypeForGoValue. We are calling a
+ // function which expects a reference so we need to convert
+ // back.
+ if (SwigType_isreference(Getattr(p, "type"))) {
+ Printv(action, "*", NULL);
+ }
+
+ Printv(action, pname, NULL);
+ Delete(pname);
+ i++;
+ }
+ p = nextSibling(p);
+ }
+ Printv(action, ");", NULL);
+ Setattr(n, "wrap:action", action);
+
+ if (!gccgo_flag) {
+ // Write the upcall wrapper function. This is compiled by gc
+ // and calls the C++ function.
+ int r = gcFunctionWrapper(upcall_wname);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ r = gccFunctionWrapper(n, NULL, upcall_wname, first_parm, result);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ } else {
+ int r = gccgoFunctionWrapper(n, NULL, upcall_wname, first_parm, result);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ Delete(first_type);
+ if (first_parm != parms) {
+ Delete(first_parm);
+ }
+
+ Swig_restore(n);
+ Delete(upcall_method_name);
+
+ // Define a function that uses the Go director type that other
+ // methods in the Go type can call to get parent methods.
+
+ Printv(f_go_wrappers, "func Director", cn, go_with_over_name, "(p ", cn, NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", NULL);
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(f_go_wrappers, tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ")", NULL);
+
+ if (SwigType_type(result) != T_VOID) {
+ String *tm = goType(n, result);
+ Printv(f_go_wrappers, " ", tm, NULL);
+ Delete(tm);
+ }
+
+ Printv(f_go_wrappers, " {\n", NULL);
+
+ String *goout = NULL;
+ if (SwigType_type(result) != T_VOID) {
+ Printv(f_go_wrappers, "\tvar swig_r ", goImType(n, result), "\n", NULL);
+ goout = Swig_typemap_lookup("goout", n, "swig_r", NULL);
+ }
+
+ String *call = NewString("");
+
+ if (gccgo_flag) {
+ if (goout != NULL) {
+ Printv(call, "\tfunc() {\n", NULL);
+ }
+ Printv(call, "\tdefer SwigCgocallDone()\n", NULL);
+ Printv(call, "\tSwigCgocall()\n", NULL);
+ }
+
+ Printv(call, "\t", NULL);
+ if (SwigType_type(result) != T_VOID) {
+ Printv(call, "swig_r = ", NULL);
+ }
+ Printv(call, upcall_gc_name, "(p.(*", director_struct_name, ").", go_type_name, NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ Printv(call, ", ", NULL);
+ p = getParm(p);
+ SwigType *pt = Getattr(p, "type");
+
+ String *ln = Copy(Getattr(p, "lname"));
+ if (goTypeIsInterface(p, pt)) {
+ Printv(ln, ".Swigcptr()", NULL);
+ }
+
+ String *goin = Getattr(p, "tmap:goin");
+ if (goin == NULL) {
+ Printv(call, ln, NULL);
+ Setattr(p, "emit:goinput", ln);
+ } else {
+ String *ivar = NewString("");
+ Printf(ivar, "_swig_i_%d", i);
+ String *itm = goImType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(f_go_wrappers, goin, NULL);
+ Delete(goin);
+ Printv(call, ivar, NULL);
+ Setattr(p, "emit:goinput", ivar);
+ }
+
+ Delete(ln);
+
+ p = nextParm(p);
+ }
+
+ Printv(call, ")\n", NULL);
+
+ if (gccgo_flag && goout != NULL) {
+ Printv(call, "\t}()\n", NULL);
+ }
+
+ Printv(f_go_wrappers, call, NULL);
+ Delete(call);
+
+ goargout(parms, parm_count);
+
+ if (SwigType_type(result) != T_VOID) {
+ if (goout == NULL) {
+ Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ } else {
+ String *tm = goType(n, result);
+ Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+ Replaceall(goout, "$input", "swig_r");
+ Replaceall(goout, "$result", "swig_r_1");
+ Printv(f_go_wrappers, goout, NULL);
+ Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+ }
+ }
+
+ Printv(f_go_wrappers, "}\n\n", NULL);
+ }
+
+ // The Go function which invokes the method. This is called
+ // from by the C++ method on the director class.
+
+ Printv(f_go_wrappers, "func ", callback_name, "(p *", director_struct_name, NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *tm = goWrapperType(p, Getattr(p, "type"), false);
+ Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ") ", NULL);
+ String *result_wrapper = NULL;
+ if (SwigType_type(result) != T_VOID) {
+ result_wrapper = goWrapperType(n, result, true);
+ Printv(f_go_wrappers, "(swig_result ", result_wrapper, ") ", NULL);
+ }
+ Printv(f_go_wrappers, "{\n", NULL);
+
+ if (is_ignored) {
+ Printv(f_go_wrappers, "\treturn\n", NULL);
+ } else {
+ bool result_is_interface = false;
+ String *goout = NULL;
+ if (SwigType_type(result) != T_VOID) {
+ result_is_interface = goTypeIsInterface(NULL, result);
+ Printv(f_go_wrappers, "\tvar swig_r ", NULL);
+ if (!result_is_interface) {
+ Printv(f_go_wrappers, goType(n, result), NULL);
+ } else {
+ Printv(f_go_wrappers, result_wrapper, NULL);
+ }
+ Printv(f_go_wrappers, "\n", NULL);
+ goout = Swig_typemap_lookup("godirectorout", n, "swig_r", NULL);
+ }
+
+ String *call = NewString("");
+
+ if (gccgo_flag) {
+ if (goout != NULL) {
+ Printv(call, "\tfunc() {\n", NULL);
+ }
+ Printv(call, "\tSwigCgocallBack()\n", NULL);
+ Printv(call, "\tdefer SwigCgocallBackDone()\n", NULL);
+ }
+
+ Printv(call, "\t", NULL);
+
+ if (SwigType_type(result) != T_VOID) {
+ Printv(call, "swig_r = ", NULL);
+ if (result_is_interface) {
+ Printv(call, result_wrapper, "(", NULL);
+ }
+ }
+ Printv(call, "p.", go_with_over_name, "(", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0) {
+ Printv(call, ", ", NULL);
+ }
+ SwigType *pt = Getattr(p, "type");
+
+ String *ln = NewString("");
+
+ // If the Go representation is an interface type class, then
+ // we are receiving a uintptr, and must convert to the
+ // interface.
+ bool is_interface = goTypeIsInterface(p, pt);
+ if (is_interface) {
+ // Passing is_result as true to goWrapperType gives us the
+ // name of the Go type we need to convert to an interface.
+ String *wt = goWrapperType(p, pt, true);
+ Printv(ln, wt, "(", NULL);
+ Delete(wt);
+ }
+
+ Printv(ln, Getattr(p, "lname"), NULL);
+
+ if (is_interface) {
+ Printv(ln, ")", NULL);
+ }
+
+ String *goin = Getattr(p, "tmap:godirectorin");
+ if (goin == NULL) {
+ Printv(call, ln, NULL);
+ } else {
+ String *ivar = NewString("");
+ Printf(ivar, "_swig_i_%d", i);
+ String *itm = goType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(f_go_wrappers, goin, NULL);
+ Delete(goin);
+ Printv(call, ivar, NULL);
+ Delete(ivar);
+ }
+
+ Delete(ln);
+
+ p = nextParm(p);
+ }
+
+ Printv(call, ")", NULL);
+
+ if (result_is_interface) {
+ Printv(call, ".Swigcptr())", NULL);
+ }
+ Printv(call, "\n", NULL);
+
+ if (gccgo_flag && goout != NULL) {
+ Printv(call, "\t}()\n", NULL);
+ }
+
+ Printv(f_go_wrappers, call, NULL);
+ Delete(call);
+
+ if (SwigType_type(result) != T_VOID) {
+ if (goout == NULL) {
+ Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ } else {
+ String *tm = goImType(n, result);
+ Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+ Replaceall(goout, "$input", "swig_r");
+ Replaceall(goout, "$result", "swig_r_1");
+ Printv(f_go_wrappers, goout, NULL);
+ Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+ }
+ }
+ }
+
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Delete(result_wrapper);
+
+ Delete(upcall_wname);
+ Delete(upcall_gc_name);
+
+ // Build the C++ functions.
+
+ if (!gccgo_flag) {
+ Printv(f_c_directors, "extern \"C\" void ", callback_wname, "(void*, int);\n", NULL);
+ } else {
+ Printv(f_c_directors, "extern \"C\" ", NULL);
+
+ String *fnname = NewString("");
+ Printv(fnname, callback_wname, "(void*", NULL);
+
+ p = parms;
+ while (p) {
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+ String *cg = gccgoCTypeForGoValue(p, Getattr(p, "type"),
+ Getattr(p, "lname"));
+ Printv(fnname, ", ", cg, NULL);
+ Delete(cg);
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ Printv(fnname, ")", NULL);
+
+ if (SwigType_type(result) == T_VOID) {
+ Printv(f_c_directors, "void ", fnname, NULL);
+ } else {
+ String *tm = gccgoCTypeForGoValue(n, result, fnname);
+ Printv(f_c_directors, tm, NULL);
+ Delete(tm);
+ }
+
+ Delete(fnname);
+
+ Printv(f_c_directors, " __asm__(\"", go_prefix, ".", callback_name, "\");\n", NULL);
+ }
+
+ Delete(go_with_over_name);
+ }
+
+ if (!is_ignored || is_pure_virtual) {
+ // Declare the method for the director class.
+
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ String *decl = Swig_method_decl(rtype, Getattr(n, "decl"), Getattr(n, "name"), parms, 0, 0);
+ Printv(f_c_directors_h, " virtual ", decl, NULL);
+ Delete(decl);
+
+ String *qname = NewString("");
+ Printv(qname, "SwigDirector_", class_name, "::", Getattr(n, "name"), NULL);
+ decl = Swig_method_decl(rtype, Getattr(n, "decl"), qname, parms, 0, 0);
+ Printv(w->def, decl, NULL);
+ Delete(decl);
+ Delete(qname);
+
+ String *throws = buildThrow(n);
+ if (throws) {
+ Printv(f_c_directors_h, " ", throws, NULL);
+ Printv(w->def, " ", throws, NULL);
+ Delete(throws);
+ }
+
+ Printv(f_c_directors_h, ";\n", NULL);
+
+ Printv(w->def, " {\n", NULL);
+
+ if (SwigType_type(result) != T_VOID) {
+ Wrapper_add_local(w, "c_result", SwigType_lstr(result, "c_result"));
+ }
+
+ if (!is_ignored) {
+ if (!gccgo_flag) {
+ Printv(w->code, " struct {\n", NULL);
+ Printv(w->code, " void *go_val;\n", NULL);
+
+ p = parms;
+ while (p) {
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+ String *ln = Getattr(p, "lname");
+ String *cg = gcCTypeForGoValue(p, Getattr(p, "type"), ln);
+ Printv(w->code, " ", cg, ";\n", NULL);
+ Delete(cg);
+ p = Getattr(p, "tmap:directorin:next");
+ }
+ if (SwigType_type(result) != T_VOID) {
+ Printv(w->code, " long : 0;\n", NULL);
+ String *rname = NewString(Swig_cresult_name());
+ String *cg = gcCTypeForGoValue(n, result, rname);
+ Printv(w->code, " ", cg, ";\n", NULL);
+ Delete(cg);
+ Delete(rname);
+ }
+
+ Printv(w->code, " } swig_a;\n", NULL);
+ Printv(w->code, " swig_a.go_val = go_val;\n", NULL);
+
+ p = parms;
+ while (p) {
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+ String *tm = Getattr(p, "tmap:directorin");
+ if (!tm) {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file,
+ line_number, "Unable to use type %s as director method argument\n", SwigType_str(Getattr(p, "type"), 0));
+ } else {
+ tm = Copy(tm);
+ String *ln = Getattr(p, "lname");
+ String *input = NewString("");
+ Printv(input, "swig_a.", ln, NULL);
+ Setattr(p, "emit:directorinput", input);
+ Replaceall(tm, "$input", input);
+ Replaceall(tm, "$owner", "0");
+ Delete(input);
+ Printv(w->code, "\t", tm, "\n", NULL);
+ Delete(tm);
+ }
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ Printv(w->code, " crosscall2(", callback_wname, ", &swig_a, (int) sizeof swig_a);\n", NULL);
+
+ /* Marshal outputs */
+ for (p = parms; p;) {
+ String *tm;
+ if ((tm = Getattr(p, "tmap:directorargout"))) {
+ tm = Copy(tm);
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ Delete(tm);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ if (SwigType_type(result) != T_VOID) {
+ String *result_str = NewString("c_result");
+ String *tm = Swig_typemap_lookup("directorout", n, result_str, NULL);
+ if (!tm) {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use type %s as director method result\n", SwigType_str(result, 0));
+ } else {
+ static const String *swig_a_result = NewStringf("swig_a.%s", Swig_cresult_name());
+ Replaceall(tm, "$input", swig_a_result);
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, " ", tm, "\n", NULL);
+ String *retstr = SwigType_rcaststr(result, "c_result");
+ Printv(w->code, " return ", retstr, ";\n", NULL);
+ Delete(retstr);
+ Delete(tm);
+ }
+ Delete(result_str);
+ }
+
+ // The C wrapper code which calls the Go function.
+ Printv(f_gc_wrappers, "#pragma dynexport ", callback_wname, " ", callback_wname, "\n", NULL);
+ Printv(f_gc_wrappers, "#pragma cgo_export_static ", callback_wname, " ", callback_wname, "\n", NULL);
+ Printv(f_gc_wrappers, "#pragma textflag 7\n", NULL);
+ Printv(f_gc_wrappers, "extern void \xc2\xb7", callback_name, "();\n", NULL);
+ Printv(f_gc_wrappers, "void\n", NULL);
+ Printv(f_gc_wrappers, callback_wname, "(void *a, int32 n)\n", NULL);
+ Printv(f_gc_wrappers, "{\n", NULL);
+ Printv(f_gc_wrappers, "\truntime\xc2\xb7" "cgocallback(\xc2\xb7", callback_name, ", a, n);\n", NULL);
+ Printv(f_gc_wrappers, "}\n\n", NULL);
+ } else {
+ if (SwigType_type(result) != T_VOID) {
+ String *r = NewString(Swig_cresult_name());
+ String *tm = gccgoCTypeForGoValue(n, result, r);
+ Wrapper_add_local(w, r, tm);
+ Delete(tm);
+ Delete(r);
+ }
+
+ String *args = NewString("");
+
+ p = parms;
+ while (p) {
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ String *pn = NewString("g");
+ Append(pn, Getattr(p, "lname"));
+ Setattr(p, "emit:directorinput", pn);
+
+ String *tm = gccgoCTypeForGoValue(n, Getattr(p, "type"), pn);
+ Wrapper_add_local(w, pn, tm);
+ Delete(tm);
+
+ tm = Getattr(p, "tmap:directorin");
+ if (!tm) {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file,
+ line_number, "Unable to use type %s as director method argument\n", SwigType_str(Getattr(p, "type"), 0));
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$input", pn);
+ Replaceall(tm, "$owner", 0);
+ Printv(w->code, " ", tm, "\n", NULL);
+ Delete(tm);
+
+ Printv(args, ", ", pn, NULL);
+ }
+
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ Printv(w->code, " ", NULL);
+ if (SwigType_type(result) != T_VOID) {
+ Printv(w->code, Swig_cresult_name(), " = ", NULL);
+ }
+ Printv(w->code, callback_wname, "(go_val", args, ");\n", NULL);
+
+ /* Marshal outputs */
+ for (p = parms; p;) {
+ String *tm;
+ if ((tm = Getattr(p, "tmap:directorargout"))) {
+ tm = Copy(tm);
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ Delete(tm);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ if (SwigType_type(result) != T_VOID) {
+ String *result_str = NewString("c_result");
+ String *tm = Swig_typemap_lookup("directorout", n, result_str, NULL);
+ if (!tm) {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use type %s as director method result\n", SwigType_str(result, 0));
+ } else {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, " ", tm, "\n", NULL);
+ String *retstr = SwigType_rcaststr(result, "c_result");
+ Printv(w->code, " return ", retstr, ";\n", NULL);
+ Delete(retstr);
+ Delete(tm);
+ }
+ Delete(result_str);
+ }
+ }
+ } else {
+ assert(is_pure_virtual);
+ Printv(w->code, " _swig_gopanic(\"call to pure virtual function ", Getattr(parent, "sym:name"), name, "\");\n", NULL);
+ if (SwigType_type(result) != T_VOID) {
+ String *retstr = SwigType_rcaststr(result, "c_result");
+ Printv(w->code, " return ", retstr, ";\n", NULL);
+ Delete(retstr);
+ }
+ }
+
+ Printv(w->code, "}", NULL);
+
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_c_directors);
+ }
+
+ Delete(cn);
+ Delete(go_type_name);
+ Delete(director_struct_name);
+ Delete(interface_name);
+ Delete(upcall_name);
+ Delete(callback_wname);
+ Delete(go_name);
+ DelWrapper(w);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorEnd
+ *
+ * Complete support for a director class.
+ * ------------------------------------------------------------ */
+
+ int classDirectorEnd(Node *n) {
+ (void) n;
+
+ Printv(f_c_directors_h, " private:\n", NULL);
+ Printv(f_c_directors_h, " void *go_val;\n", NULL);
+ Printv(f_c_directors_h, "};\n\n", NULL);
+
+ class_name = NULL;
+ class_node = NULL;
+
+ Delete(class_receiver);
+ class_receiver = NULL;
+
+ Delete(class_methods);
+ class_methods = NULL;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDisown
+ *
+ * I think Go does not require a disown method.
+ * ------------------------------------------------------------ */
+
+ int classDirectorDisown(Node *n) {
+ (void) n;
+ return SWIG_OK;
+ }
+
+ /*----------------------------------------------------------------------
+ * buildThrow()
+ *
+ * Build and return a throw clause if needed.
+ *--------------------------------------------------------------------*/
+
+ String *buildThrow(Node *n) {
+ ParmList *throw_parm_list = Getattr(n, "throws");
+ if (!throw_parm_list && !Getattr(n, "throw"))
+ return NULL;
+ String *ret = NewString("throw(");
+ if (throw_parm_list) {
+ Swig_typemap_attach_parms("throws", throw_parm_list, NULL);
+ }
+ bool first = true;
+ for (Parm *p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (first) {
+ first = false;
+ } else {
+ Printv(ret, ", ", NULL);
+ }
+ String *s = SwigType_str(Getattr(p, "type"), 0);
+ Printv(ret, s, NULL);
+ Delete(s);
+ }
+ }
+ Printv(ret, ")", NULL);
+ return ret;
+ }
+
+ /*----------------------------------------------------------------------
+ * extraDirectorProtectedCPPMethodsRequired()
+ *
+ * We don't need to check upcall when calling methods.
+ *--------------------------------------------------------------------*/
+
+ bool extraDirectorProtectedCPPMethodsRequired() const {
+ return false;
+ }
+
+ /*----------------------------------------------------------------------
+ * makeDispatchFunction
+ *
+ * Make a dispatch function for an overloaded C++ function. The
+ * receiver parameter is the receiver for a method, unless is_upcall
+ * is true. If is_upcall is true, then the receiver parameter is
+ * the type of the first argument to the function.
+ *--------------------------------------------------------------------*/
+
+ int makeDispatchFunction(Node *n, String *go_name, String *receiver, bool is_static, SwigType *director_struct, bool is_upcall) {
+ bool is_director = director_struct ? true : false;
+
+ String *nodetype = Getattr(n, "nodeType");
+ bool is_constructor = Cmp(nodetype, "constructor") == 0;
+ bool is_destructor = Cmp(nodetype, "destructor") == 0;
+
+ bool can_use_receiver = (!is_constructor && !is_destructor && !is_upcall);
+
+ bool use_receiver = (!is_static && can_use_receiver);
+
+ bool add_to_interface = (interfaces && !is_constructor && !is_destructor && !is_static && !is_upcall);
+
+ List *dispatch = Swig_overload_rank(n, false);
+ int nfunc = Len(dispatch);
+
+ SwigType *all_result;
+ bool mismatch;
+ if (is_constructor) {
+ assert(!is_upcall);
+ if (!is_director) {
+ all_result = Copy(Getattr(class_node, "classtypeobj"));
+ } else {
+ all_result = Copy(director_struct);
+ }
+ mismatch = false;
+ } else {
+ all_result = NULL;
+ mismatch = false;
+ bool any_void = false;
+ for (int i = 0; i < nfunc; ++i) {
+ Node *nn = Getitem(dispatch, i);
+ Node *ni = Getattr(nn, "directorNode") ? Getattr(nn, "directorNode") : nn;
+ SwigType *result = Getattr(ni, "go:type");
+ assert(result);
+
+ if (SwigType_type(result) == T_VOID) {
+ if (all_result) {
+ mismatch = true;
+ }
+ any_void = true;
+ } else {
+ if (any_void) {
+ mismatch = true;
+ } else if (!all_result) {
+ all_result = Copy(result);
+ } else if (Cmp(result, all_result) != 0) {
+ mismatch = true;
+ }
+ }
+ }
+ if (mismatch) {
+ Delete(all_result);
+ all_result = NULL;
+ } else if (all_result) {
+ ;
+ } else {
+ all_result = NewString("void");
+ }
+ }
+
+ Printv(f_go_wrappers, "func ", NULL);
+
+ if (receiver && use_receiver) {
+ Printv(f_go_wrappers, "(p ", receiver, ") ", NULL);
+ }
+
+ Printv(f_go_wrappers, go_name, "(", NULL);
+ if (is_director && is_constructor) {
+ Printv(f_go_wrappers, "abi interface{}, ", NULL);
+ assert(!add_to_interface);
+ }
+ if (is_upcall) {
+ Printv(f_go_wrappers, "p *", receiver, ", ", NULL);
+ assert(!add_to_interface);
+ }
+ Printv(f_go_wrappers, "a ...interface{})", NULL);
+
+ if (add_to_interface) {
+ Printv(interfaces, "\t", go_name, "(a ...interface{})", NULL);
+ }
+
+ if (mismatch) {
+ Printv(f_go_wrappers, " interface{}", NULL);
+ if (add_to_interface) {
+ Printv(interfaces, " interface{}", NULL);
+ }
+ } else if (all_result && SwigType_type(all_result) != T_VOID) {
+ if (is_director && is_constructor) {
+ Printv(f_go_wrappers, " ", receiver, NULL);
+ if (add_to_interface) {
+ Printv(interfaces, " ", receiver, NULL);
+ }
+ } else {
+ String *tm = goType(n, all_result);
+ Printv(f_go_wrappers, " ", tm, NULL);
+ if (add_to_interface) {
+ Printv(interfaces, " ", tm, NULL);
+ }
+ Delete(tm);
+ }
+ }
+ Printv(f_go_wrappers, " {\n", NULL);
+ if (add_to_interface) {
+ Printv(interfaces, "\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "\targc := len(a)\n", NULL);
+
+ for (int i = 0; i < nfunc; ++i) {
+ int fn = 0;
+ Node *nn = Getitem(dispatch, i);
+ Node *ni = Getattr(nn, "directorNode") ? Getattr(nn, "directorNode") : nn;
+ Parm *pi = Getattr(ni, "wrap:parms");
+
+ // If we are using a receiver, we want to ignore a leading self
+ // parameter. Because of the way this is called, there may or
+ // may not be a self parameter at this point.
+ if (use_receiver && pi && Getattr(pi, "self")) {
+ pi = getParm(pi);
+ if (pi) {
+ pi = nextParm(pi);
+ }
+ }
+
+ int num_required = emit_num_required(pi);
+ int num_arguments = emit_num_arguments(pi);
+ bool varargs = emit_isvarargs(pi) ? true : false;
+
+ if (varargs) {
+ Printf(f_go_wrappers, "\tif argc >= %d {\n", num_required);
+ } else {
+ if (num_required == num_arguments) {
+ Printf(f_go_wrappers, "\tif argc == %d {\n", num_required);
+ } else {
+ Printf(f_go_wrappers, "\tif argc >= %d && argc <= %d {\n", num_required, num_arguments);
+ }
+ }
+
+ // Build list of collisions with the same number of arguments.
+ List *coll = NewList();
+ for (int k = i + 1; k < nfunc; ++k) {
+ Node *nnk = Getitem(dispatch, k);
+ Node *nk = Getattr(nnk, "directorNode") ? Getattr(nnk, "directorNode") : nnk;
+ Parm *pk = Getattr(nk, "wrap:parms");
+ if (use_receiver && pk && Getattr(pk, "self")) {
+ pk = getParm(pk);
+ if (pk) {
+ pk = nextParm(pk);
+ }
+ }
+ int nrk = emit_num_required(pk);
+ int nak = emit_num_arguments(pk);
+ if ((nrk >= num_required && nrk <= num_arguments)
+ || (nak >= num_required && nak <= num_arguments)
+ || (nrk <= num_required && nak >= num_arguments)
+ || (varargs && nrk >= num_required)) {
+ Append(coll, nk);
+ }
+ }
+
+ int num_braces = 0;
+ if (Len(coll) > 0 && num_arguments > 0) {
+ int j = 0;
+ Parm *pj = pi;
+ while (pj) {
+ pj = getParm(pj);
+ if (!pj) {
+ break;
+ }
+
+ // If all the wrappers have the same type in this position,
+ // we can omit the check.
+ SwigType *tm = goWrapperType(pj, Getattr(pj, "type"), true);
+ bool emitcheck = false;
+ for (int k = 0; k < Len(coll) && !emitcheck; ++k) {
+ Node *nk = Getitem(coll, k);
+ Parm *pk = Getattr(nk, "wrap:parms");
+ if (use_receiver && pk && Getattr(pk, "self")) {
+ pk = getParm(pk);
+ if (pk) {
+ pk = nextParm(pk);
+ }
+ }
+ int nak = emit_num_arguments(pk);
+ if (nak <= j)
+ continue;
+ int l = 0;
+ Parm *pl = pk;
+ while (pl && l <= j) {
+ pl = getParm(pl);
+ if (!pl) {
+ break;
+ }
+ if (l == j) {
+ SwigType *tml = goWrapperType(pl, Getattr(pl, "type"), true);
+ if (Cmp(tm, tml) != 0) {
+ emitcheck = true;
+ }
+ Delete(tml);
+ }
+ pl = nextParm(pl);
+ ++l;
+ }
+ }
+
+ if (emitcheck) {
+ if (j >= num_required) {
+ Printf(f_go_wrappers, "\t\tif argc > %d {\n", j);
+ ++num_braces;
+ }
+
+ fn = i + 1;
+ Printf(f_go_wrappers, "\t\tif _, ok := a[%d].(%s); !ok {\n", j, tm);
+ Printf(f_go_wrappers, "\t\t\tgoto check_%d\n", fn);
+ Printv(f_go_wrappers, "\t\t}\n", NULL);
+ }
+
+ Delete(tm);
+
+ pj = nextParm(pj);
+
+ ++j;
+ }
+ }
+
+ for (; num_braces > 0; --num_braces) {
+ Printv(f_go_wrappers, "\t\t}\n", NULL);
+ }
+
+ // We may need to generate multiple calls if there are variable
+ // argument lists involved. Build the start of the call.
+
+ String *start = NewString("");
+
+ SwigType *result = Getattr(ni, "go:type");
+
+ if (is_constructor) {
+ result = all_result;
+ } else if (is_destructor) {
+ result = NULL;
+ }
+
+ if (result && SwigType_type(result) != T_VOID && (!all_result || SwigType_type(all_result) != T_VOID)) {
+ Printv(start, "return ", NULL);
+ }
+
+ bool advance_parm = false;
+
+ if (receiver && use_receiver) {
+ Printv(start, "p.", go_name, NULL);
+ } else if (can_use_receiver && !isStatic(ni) && pi && Getattr(pi, "self")) {
+ // This is an overload of a static function and a non-static
+ // function.
+ assert(num_required > 0);
+ SwigType *tm = goWrapperType(pi, Getattr(pi, "type"), true);
+ String *nm = buildGoName(Getattr(ni, "sym:name"), false, isFriend(ni));
+ Printv(start, "a[0].(", tm, ").", nm, NULL);
+ Delete(nm);
+ Delete(tm);
+ advance_parm = true;
+ } else {
+ Printv(start, go_name, NULL);
+ }
+
+ Printv(start, Getattr(ni, "sym:overname"), "(", NULL);
+
+ bool need_comma = false;
+
+ if (is_director && is_constructor) {
+ Printv(start, "abi", NULL);
+ need_comma = true;
+ }
+ if (is_upcall) {
+ Printv(start, "p", NULL);
+ need_comma = true;
+ }
+ Parm *p = pi;
+ int pn = 0;
+ if (advance_parm) {
+ p = getParm(p);
+ if (p) {
+ p = nextParm(p);
+ }
+ ++pn;
+ }
+ while (pn < num_required) {
+ p = getParm(p);
+
+ if (need_comma) {
+ Printv(start, ", ", NULL);
+ }
+
+ SwigType *tm = goType(p, Getattr(p, "type"));
+ Printf(start, "a[%d].(%s)", pn, tm);
+ Delete(tm);
+
+ need_comma = true;
+ ++pn;
+ p = nextParm(p);
+ }
+
+ String *end = NULL;
+ if (!result || SwigType_type(result) == T_VOID || (all_result && SwigType_type(all_result) == T_VOID)) {
+ end = NewString("");
+ Printv(end, "return", NULL);
+ if (!all_result || SwigType_type(all_result) != T_VOID) {
+ Printv(end, " 0", NULL);
+ }
+ }
+
+ if (num_required == num_arguments) {
+ Printv(f_go_wrappers, "\t\t", start, ")\n", NULL);
+ if (end) {
+ Printv(f_go_wrappers, "\t\t", end, "\n", NULL);
+ }
+ } else {
+ Printv(f_go_wrappers, "\t\tswitch argc {\n", NULL);
+ for (int j = num_required; j <= num_arguments; ++j) {
+ Printf(f_go_wrappers, "\t\tcase %d:\n", j);
+ Printv(f_go_wrappers, "\t\t\t", start, NULL);
+ bool nc = need_comma;
+ for (int k = num_required; k < j; ++k) {
+ if (nc) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ Printf(f_go_wrappers, "a[%d]", k);
+ nc = true;
+ }
+ Printv(f_go_wrappers, ")\n", NULL);
+ if (end) {
+ Printv(f_go_wrappers, "\t\t\t", end, "\n", NULL);
+ }
+ }
+ Printv(f_go_wrappers, "\t\t}\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "\t}\n", NULL);
+
+ if (fn != 0) {
+ Printf(f_go_wrappers, "check_%d:\n", fn);
+ }
+
+ Delete(coll);
+ }
+
+ Printv(f_go_wrappers, "\tpanic(\"No match for overloaded function call\")\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Delete(all_result);
+ Delete(dispatch);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * checkFunctionVisibility()
+ *
+ * Return true if we should write out a function based on its
+ * visibility, false otherwise.
+ * ---------------------------------------------------------------------- */
+
+ bool checkFunctionVisibility(Node *n, Node *parent) {
+ // Write out a public function.
+ if (is_public(n))
+ return true;
+ // Don't write out a private function.
+ if (is_private(n))
+ return false;
+ // Write a protected function for a director class in
+ // dirprot_mode.
+ if (parent == NULL) {
+ return false;
+ }
+ if (dirprot_mode() && Swig_directorclass(parent))
+ return true;
+ // Otherwise don't write out a protected function.
+ return false;
+ }
+
+
+ /* ----------------------------------------------------------------------
+ * exportedName()
+ *
+ * Given a C/C++ name, return a name in Go which will be exported.
+ * If the first character is an upper case letter, this returns a
+ * copy of its argment. If the first character is a lower case
+ * letter, this forces it to upper case. Otherwise, this prepends
+ * 'X'.
+ * ---------------------------------------------------------------------- */
+
+ String *exportedName(String *name) {
+ String *copy = Copy(name);
+ char c = *Char(copy);
+ if (islower(c)) {
+ char l[2];
+ char u[2];
+ l[0] = c;
+ l[1] = '\0';
+ u[0] = toupper(c);
+ u[1] = '\0';
+ Replace(copy, l, u, DOH_REPLACE_FIRST);
+ } else if (!isalpha(c)) {
+ char l[2];
+ char u[3];
+ l[0] = c;
+ l[1] = '\0';
+ u[0] = 'X';
+ u[1] = c;
+ u[2] = '\0';
+ Replace(copy, l, u, DOH_REPLACE_FIRST);
+ }
+ String *ret = Swig_name_mangle(copy);
+ Delete(copy);
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * removeClassname()
+ *
+ * If the name starts with the current class name, followed by an
+ * underscore, remove it. If there is no current class name, this
+ * simply returns a copy of the name. This undoes Swig's way of
+ * recording the class name in a member name.
+ * ---------------------------------------------------------------------- */
+
+ String *removeClassname(String *name) {
+ String *copy = Copy(name);
+ if (class_name) {
+ char *p = Char(name);
+ if (Strncmp(name, class_name, Len(class_name)) == 0 && p[Len(class_name)] == '_') {
+ Replace(copy, class_name, "", DOH_REPLACE_FIRST);
+ Replace(copy, "_", "", DOH_REPLACE_FIRST);
+ }
+ }
+ return copy;
+ }
+
+ /* ----------------------------------------------------------------------
+ * buildGoName()
+ *
+ * Build the name to use for an ordinary function, variable, or
+ * whatever in Go. The name argument is something like the sym:name
+ * attribute of the node. If is_static is false, this could be a
+ * method, and the returned name will be the name of the
+ * method--i.e., it will not include the class name.
+ * ---------------------------------------------------------------------- */
+
+ String *buildGoName(String *name, bool is_static, bool is_friend) {
+ String *nw = NewString("");
+ if (is_static && !is_friend && class_name) {
+ String *c1 = exportedName(class_name);
+ Append(nw, c1);
+ Delete(c1);
+ }
+ String *c2 = removeClassname(name);
+ String *c3 = exportedName(c2);
+ Append(nw, c3);
+ Delete(c2);
+ Delete(c3);
+ String *ret = Swig_name_mangle(nw);
+ Delete(nw);
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * buildGoWrapperName()
+ *
+ * Build the name to use for a Go wrapper function. This is a
+ * function called by the real Go function in order to convert C++
+ * classes from interfaces to pointers, and other such conversions
+ * between the Go type and the C++ type.
+ * ---------------------------------------------------------------------- */
+
+ String *buildGoWrapperName(String *name, String *overname) {
+ String *s1 = NewString("_swig_wrap_");
+ Append(s1, name);
+ String *s2 = Swig_name_mangle(s1);
+ Delete(s1);
+ if (overname) {
+ Append(s2, overname);
+ }
+ return s2;
+ }
+
+ /* ----------------------------------------------------------------------
+ * checkNameConflict()
+ *
+ * Check for a name conflict on the name we are going to use in Go.
+ * These conflicts are likely because of the enforced
+ * capitalization. When we find one, issue a warning and return
+ * false. If the name is OK, return true.
+ * ---------------------------------------------------------------------- */
+
+ bool checkNameConflict(String* name, Node* n, const_String_or_char_ptr scope) {
+ Node *lk = symbolLookup(name, scope);
+ if (lk) {
+ String *n1 = Getattr(n, "sym:name");
+ if (!n1) {
+ n1 = Getattr(n, "name");
+ }
+ String *n2 = Getattr(lk, "sym:name");
+ if (!n2) {
+ n2 = Getattr(lk, "name");
+ }
+ Swig_warning(WARN_GO_NAME_CONFLICT, input_file, line_number,
+ "Ignoring '%s' due to Go name ('%s') conflict with '%s'\n",
+ n1, name, n2);
+ return false;
+ }
+ bool r = addSymbol(name, n, scope) ? true : false;
+ assert(r);
+ return true;
+ }
+
+ /* ----------------------------------------------------------------------
+ * checkIgnoredParameters()
+ *
+ * If any of the parameters of this function, or the return type,
+ * are ignored due to a name conflict, give a warning and return
+ * false.
+ * ---------------------------------------------------------------------- */
+
+ bool checkIgnoredParameters(Node *n, String *go_name) {
+ ParmList *parms = Getattr(n, "parms");
+ if (parms) {
+ Wrapper *dummy = NewWrapper();
+ emit_attach_parmmaps(parms, dummy);
+ int parm_count = emit_num_arguments(parms);
+ Parm *p = parms;
+
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (!checkIgnoredType(n, go_name, Getattr(p, "type"))) {
+ DelWrapper(dummy);
+ return false;
+ }
+ p = nextParm(p);
+ }
+
+ DelWrapper(dummy);
+ }
+
+ if (!checkIgnoredType(n, go_name, Getattr(n, "type"))) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /* ----------------------------------------------------------------------
+ * checkIgnoredType()
+ *
+ * If this type is being ignored due to a name conflict, give a
+ * warning and return false.
+ * ---------------------------------------------------------------------- */
+
+ bool checkIgnoredType(Node *n, String *go_name, SwigType *type) {
+ if (hasGoTypemap(n, type)) {
+ return true;
+ }
+
+ SwigType *t = SwigType_typedef_resolve_all(type);
+
+ bool ret = true;
+ bool is_conflict = false;
+ Node *e = Language::enumLookup(t);
+ if (e) {
+ if (GetFlag(e, "go:conflict")) {
+ is_conflict = true;
+ }
+ } else if (SwigType_issimple(t)) {
+ Node *cn = classLookup(t);
+ if (cn) {
+ if (GetFlag(cn, "go:conflict")) {
+ is_conflict = true;
+ }
+ }
+ } else if (SwigType_ispointer(t) || SwigType_isarray(t) || SwigType_isqualifier(t) || SwigType_isreference(t)) {
+ SwigType *r = Copy(t);
+ if (SwigType_ispointer(r)) {
+ SwigType_del_pointer(r);
+ } else if (SwigType_isarray(r)) {
+ SwigType_del_array(r);
+ } else if (SwigType_isqualifier(r)) {
+ SwigType_del_qualifier(r);
+ } else {
+ SwigType_del_reference(r);
+ }
+
+ if (!checkIgnoredType(n, go_name, r)) {
+ ret = false;
+ }
+
+ Delete(r);
+ }
+
+ if (is_conflict) {
+ String *s = SwigType_str(t, NULL);
+ Swig_warning(WARN_GO_NAME_CONFLICT, input_file, line_number,
+ "Ignoring '%s' (Go name '%s') due to Go name conflict for parameter or result type '%s'\n",
+ Getattr(n, "name"), go_name, s);
+ Delete(s);
+ ret = false;
+ }
+
+ Delete(t);
+
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * goType()
+ *
+ * Given a SWIG type, return a string for the type in Go.
+ * ---------------------------------------------------------------------- */
+
+ String *goType(Node *n, SwigType *type) {
+ return goTypeWithInfo(n, type, false, NULL);
+ }
+
+ /* ----------------------------------------------------------------------
+ * goImType()
+ *
+ * Given a SWIG type, return a string for the intermediate Go type
+ * to pass to C/C++. This is like goType except that it looks for
+ * an imtype typemap entry first.
+ * ---------------------------------------------------------------------- */
+
+ String *goImType(Node *n, SwigType *type) {
+ return goTypeWithInfo(n, type, true, NULL);
+ }
+
+ /* ----------------------------------------------------------------------
+ * goTypeWithInfo()
+ *
+ * Like goType, but return some more information.
+ *
+ * If use_imtype is true, this look for a imtype typemap entry.
+ *
+ * If the p_is_interface parameter is not NULL, this sets
+ * *p_is_interface to indicate whether this type is going to be
+ * represented by a Go interface type. These are cases where the Go
+ * code needs to make some adjustments when passing values back and
+ * forth with C/C++.
+ * ---------------------------------------------------------------------- */
+
+ String *goTypeWithInfo(Node *n, SwigType *type, bool use_imtype, bool *p_is_interface) {
+ if (p_is_interface) {
+ *p_is_interface = false;
+ }
+
+ String *ret = NULL;
+ if (use_imtype) {
+ if (n && Cmp(type, Getattr(n, "type")) == 0) {
+ if (Strcmp(Getattr(n, "nodeType"), "parm") == 0) {
+ ret = Getattr(n, "tmap:imtype");
+ }
+ if (!ret) {
+ ret = Swig_typemap_lookup("imtype", n, "", NULL);
+ }
+ } else {
+ Parm *p = NewParm(type, "goImType", n);
+ ret = Swig_typemap_lookup("imtype", p, "", NULL);
+ Delete(p);
+ }
+ }
+ if (!ret) {
+ if (n && Cmp(type, Getattr(n, "type")) == 0) {
+ if (Strcmp(Getattr(n, "nodeType"), "parm") == 0) {
+ ret = Getattr(n, "tmap:gotype");
+ }
+ if (!ret) {
+ ret = Swig_typemap_lookup("gotype", n, "", NULL);
+ }
+ } else {
+ Parm *p = NewParm(type, "goType", n);
+ ret = Swig_typemap_lookup("gotype", p, "", NULL);
+ Delete(p);
+ }
+ }
+
+ if (ret && Strstr(ret, "$gotypename") != 0) {
+ ret = NULL;
+ }
+
+ if (ret) {
+ return Copy(ret);
+ }
+
+ SwigType *t = SwigType_typedef_resolve_all(type);
+
+ if (SwigType_isenum(t)) {
+ Node *e = Language::enumLookup(t);
+ if (e) {
+ ret = goEnumName(e);
+ } else if (Strcmp(t, "enum ") == 0) {
+ ret = NewString("int");
+ } else {
+ // An unknown enum - one that has not been parsed (neither a C enum forward reference nor a definition) or an ignored enum
+ String *tt = Copy(t);
+ Replace(tt, "enum ", "", DOH_REPLACE_ANY);
+ ret = exportedName(tt);
+ Setattr(undefined_enum_types, t, ret);
+ Delete(tt);
+ }
+ } else if (SwigType_isfunctionpointer(type) || SwigType_isfunction(type)) {
+ ret = NewString("_swig_fnptr");
+ } else if (SwigType_ismemberpointer(type)) {
+ ret = NewString("_swig_memberptr");
+ } else if (SwigType_issimple(t)) {
+ Node *cn = classLookup(t);
+ if (cn) {
+ ret = Getattr(cn, "sym:name");
+ if (!ret) {
+ ret = Getattr(cn, "name");
+ }
+ ret = exportedName(ret);
+
+ Node *cnmod = Getattr(cn, "module");
+ if (!cnmod || Strcmp(Getattr(cnmod, "name"), module) == 0) {
+ Setattr(undefined_types, t, t);
+ } else {
+ String *nw = NewString("");
+ Printv(nw, Getattr(cnmod, "name"), ".", ret, NULL);
+ Delete(ret);
+ ret = nw;
+ }
+ } else {
+ // SWIG does not know about this type.
+ ret = exportedName(t);
+ Setattr(undefined_types, t, t);
+ }
+ if (p_is_interface) {
+ *p_is_interface = true;
+ }
+ } else if (SwigType_ispointer(t) || SwigType_isarray(t)) {
+ SwigType *r = Copy(t);
+ if (SwigType_ispointer(r)) {
+ SwigType_del_pointer(r);
+ } else {
+ SwigType_del_array(r);
+ }
+
+ if (SwigType_type(r) == T_VOID) {
+ ret = NewString("uintptr");
+ } else {
+ bool is_interface;
+ String *base = goTypeWithInfo(n, r, false, &is_interface);
+
+ // At the Go level, an unknown or class type is handled as an
+ // interface wrapping a pointer. This means that if a
+ // function returns the C type X, we will be wrapping the C
+ // type X*. In Go we will call that type X. That means that
+ // if a C function expects X*, we can pass the Go type X. And
+ // that means that when we see the C type X*, we should use
+ // the Go type X.
+
+ // The is_interface variable tells us this. However, it will
+ // be true both for the case of X and for the case of X*. If
+ // r is a pointer here, then we are looking at X**. There is
+ // really no good way for us to handle that.
+ bool is_pointer_to_pointer = false;
+ if (is_interface) {
+ SwigType *c = Copy(r);
+ if (SwigType_isqualifier(c)) {
+ SwigType_del_qualifier(c);
+ if (SwigType_ispointer(c) || SwigType_isarray(c)) {
+ is_pointer_to_pointer = true;
+ }
+ }
+ Delete(c);
+ }
+
+ if (is_interface) {
+ if (!is_pointer_to_pointer) {
+ ret = base;
+ if (p_is_interface) {
+ *p_is_interface = true;
+ }
+ } else {
+ ret = NewString("uintptr");
+ }
+ } else {
+ ret = NewString("*");
+ Append(ret, base);
+ Delete(base);
+ }
+ }
+
+ Delete(r);
+ } else if (SwigType_isreference(t)) {
+ SwigType *r = Copy(t);
+ SwigType_del_reference(r);
+
+ // If this is a const reference, and we are looking at a pointer
+ // to it, then we just use the pointer we already have.
+ bool add_pointer = true;
+ if (SwigType_isqualifier(r)) {
+ String *q = SwigType_parm(r);
+ if (Strcmp(q, "const") == 0) {
+ SwigType *c = Copy(r);
+ SwigType_del_qualifier(c);
+ if (SwigType_ispointer(c)) {
+ add_pointer = false;
+ }
+ Delete(c);
+ }
+ }
+ if (add_pointer) {
+ SwigType_add_pointer(r);
+ }
+ ret = goTypeWithInfo(n, r, false, p_is_interface);
+ Delete(r);
+ } else if (SwigType_isqualifier(t)) {
+ SwigType *r = Copy(t);
+ SwigType_del_qualifier(r);
+ ret = goTypeWithInfo(n, r, false, p_is_interface);
+ Delete(r);
+ } else if (SwigType_isvarargs(t)) {
+ ret = NewString("[]interface{}");
+ }
+
+ Delete(t);
+
+ if (!ret) {
+ Swig_warning(WARN_LANG_NATIVE_UNIMPL, input_file, line_number, "No Go typemap defined for %s\n", SwigType_str(type, 0));
+ ret = NewString("uintptr");
+ }
+
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * goWrapperType()
+ *
+ * Given a type, return a string for the type to use for the wrapped
+ * Go function. This function exists because for a C++ class we
+ * need to convert interface and reference types.
+ * ---------------------------------------------------------------------- */
+
+ String *goWrapperType(Node *n, SwigType *type, bool is_result) {
+ bool is_interface;
+ String *ret = goTypeWithInfo(n, type, true, &is_interface);
+
+ // If this is an interface, we want to pass the real type.
+ if (is_interface) {
+ Delete(ret);
+ if (!is_result) {
+ ret = NewString("uintptr");
+ } else {
+ SwigType *ty = SwigType_typedef_resolve_all(type);
+ while (true) {
+ if (SwigType_ispointer(ty)) {
+ SwigType_del_pointer(ty);
+ } else if (SwigType_isarray(ty)) {
+ SwigType_del_array(ty);
+ } else if (SwigType_isreference(ty)) {
+ SwigType_del_reference(ty);
+ } else if (SwigType_isqualifier(ty)) {
+ SwigType_del_qualifier(ty);
+ } else {
+ break;
+ }
+ }
+ assert(SwigType_issimple(ty));
+ String *p = goCPointerType(ty, true);
+ Delete(ty);
+ ret = p;
+ }
+ }
+
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * goCPointerType()
+ *
+ * Return the name of the Go type to use for the C pointer value.
+ * The regular C type is the name of an interface type which wraps a
+ * pointer whose name is returned by this function.
+ * ---------------------------------------------------------------------- */
+
+ String *goCPointerType(SwigType *type, bool add_to_hash) {
+ SwigType *ty = SwigType_typedef_resolve_all(type);
+ Node *cn = classLookup(ty);
+ String *ex;
+ String *ret;
+ if (!cn) {
+ if (add_to_hash) {
+ Setattr(undefined_types, ty, ty);
+ }
+ ret = NewString("Swigcptr");
+ ex = exportedName(ty);
+ Append(ret, ex);
+ } else {
+ String *cname = Getattr(cn, "sym:name");
+ if (!cname) {
+ cname = Getattr(cn, "name");
+ }
+ ex = exportedName(cname);
+ Node *cnmod = Getattr(cn, "module");
+ if (!cnmod || Strcmp(Getattr(cnmod, "name"), module) == 0) {
+ if (add_to_hash) {
+ Setattr(undefined_types, ty, ty);
+ }
+ ret = NewString("Swigcptr");
+ Append(ret, ex);
+ } else {
+ ret = NewString("");
+ Printv(ret, Getattr(cnmod, "name"), ".Swigcptr", ex, NULL);
+ }
+ }
+ Delete(ty);
+ Delete(ex);
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * gcCTypeForGoValue()
+ *
+ * Given a type, return the C/C++ type which will be used to catch
+ * the value in Go. This is the 6g/8g version.
+ * ---------------------------------------------------------------------- */
+
+ String *gcCTypeForGoValue(Node *n, SwigType *type, String *name) {
+ bool is_interface;
+ String *gt = goTypeWithInfo(n, type, true, &is_interface);
+
+ String *tail = NewString("");
+ SwigType *t = SwigType_typedef_resolve_all(type);
+ if (!SwigType_isreference(t)) {
+ while (Strncmp(gt, "*", 1) == 0) {
+ Replace(gt, "*", "", DOH_REPLACE_FIRST);
+ Printv(tail, "*", NULL);
+ }
+ }
+ Delete(t);
+
+ bool is_string = Strcmp(gt, "string") == 0;
+ bool is_slice = Strncmp(gt, "[]", 2) == 0;
+ bool is_function = Strcmp(gt, "_swig_fnptr") == 0;
+ bool is_member = Strcmp(gt, "_swig_memberptr") == 0;
+ bool is_complex64 = Strcmp(gt, "complex64") == 0;
+ bool is_complex128 = Strcmp(gt, "complex128") == 0;
+ bool is_int8 = false;
+ bool is_int16 = false;
+ bool is_int = Strcmp(gt, "int") == 0 || Strcmp(gt, "uint") == 0;
+ bool is_int32 = false;
+ bool is_int64 = false;
+ bool is_float32 = false;
+ bool is_float64 = false;
+ if ((n != NULL && Getattr(n, "tmap:gotype") != NULL) || hasGoTypemap(n, type)) {
+ is_int8 = Strcmp(gt, "int8") == 0 || Strcmp(gt, "uint8") == 0 || Strcmp(gt, "byte") == 0;
+ is_int16 = Strcmp(gt, "int16") == 0 || Strcmp(gt, "uint16") == 0;
+ is_int32 = Strcmp(gt, "int32") == 0 || Strcmp(gt, "uint32") == 0;
+ is_int64 = Strcmp(gt, "int64") == 0 || Strcmp(gt, "uint64") == 0;
+ is_float32 = Strcmp(gt, "float32") == 0;
+ is_float64 = Strcmp(gt, "float64") == 0;
+ }
+ Delete(gt);
+
+ String *ret;
+ if (is_string) {
+ // Note that we don't turn a reference to a string into a
+ // pointer to a string. Strings are immutable anyhow.
+ ret = NewString("");
+ Printv(ret, "_gostring_", tail, " ", name, NULL);
+ Delete(tail);
+ return ret;
+ } else if (is_slice) {
+ // Slices are always passed as a _goslice_, whether or not references
+ // are involved.
+ ret = NewString("");
+ Printv(ret, "_goslice_", tail, " ", name, NULL);
+ Delete(tail);
+ return ret;
+ } else if (is_function || is_member) {
+ ret = NewString("");
+ Printv(ret, "void*", tail, " ", name, NULL);
+ Delete(tail);
+ return ret;
+ } else if (is_complex64) {
+ ret = NewString("_Complex float ");
+ } else if (is_complex128) {
+ ret = NewString("_Complex double ");
+ } else if (is_interface) {
+ SwigType *t = SwigType_typedef_resolve_all(type);
+ if (SwigType_ispointer(t)) {
+ SwigType_del_pointer(t);
+ }
+ if (SwigType_isreference(t)) {
+ SwigType_del_reference(t);
+ }
+ SwigType_add_pointer(t);
+ ret = SwigType_lstr(t, name);
+ Delete(t);
+ Delete(tail);
+ return ret;
+ } else {
+ SwigType *t = SwigType_typedef_resolve_all(type);
+ if (SwigType_isreference(t)) {
+ // A const reference to a known type, or to a pointer, is not
+ // mapped to a pointer.
+ SwigType_del_reference(t);
+ if (SwigType_isqualifier(t)) {
+ String *q = SwigType_parm(t);
+ if (Strcmp(q, "const") == 0) {
+ SwigType_del_qualifier(t);
+ if (hasGoTypemap(n, t) || SwigType_ispointer(t)) {
+ if (is_int) {
+ ret = NewString("intgo ");
+ Append(ret, name);
+ } else if (is_int64) {
+ ret = NewString("long long ");
+ Append(ret, name);
+ } else {
+ ret = SwigType_lstr(t, name);
+ }
+ Delete(q);
+ Delete(t);
+ Delete(tail);
+ return ret;
+ }
+ }
+ Delete(q);
+ }
+ }
+
+ if (Language::enumLookup(t) != NULL) {
+ is_int = true;
+ } else {
+ SwigType *tstripped = SwigType_strip_qualifiers(t);
+ if (SwigType_isenum(tstripped))
+ is_int = true;
+ Delete(tstripped);
+ }
+
+ Delete(t);
+ if (is_int8) {
+ ret = NewString("char ");
+ } else if (is_int16) {
+ ret = NewString("short ");
+ } else if (is_int) {
+ ret = NewString("intgo ");
+ } else if (is_int32) {
+ ret = NewString("int ");
+ } else if (is_int64) {
+ ret = NewString("long long ");
+ } else if (is_float32) {
+ ret = NewString("float ");
+ } else if (is_float64) {
+ ret = NewString("double ");
+ } else {
+ Delete(tail);
+ return SwigType_lstr(type, name);
+ }
+ }
+
+ Append(ret, tail);
+ if (SwigType_isreference(type)) {
+ Append(ret, "* ");
+ }
+ Append(ret, name);
+ Delete(tail);
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * gccgoCTypeForGoValue()
+ *
+ * Given a type, return the C/C++ type which will be used to catch
+ * the value in Go. This is the gccgo version.
+ * ---------------------------------------------------------------------- */
+
+ String *gccgoCTypeForGoValue(Node *n, SwigType *type, String *name) {
+ return gcCTypeForGoValue(n, type, name);
+ }
+
+ /* ----------------------------------------------------------------------
+ * goTypeIsInterface
+ *
+ * Return whether this C++ type is represented as an interface type
+ * in Go. These types require adjustments in the Go code when
+ * passing them back and forth between Go and C++.
+ * ---------------------------------------------------------------------- */
+
+ bool goTypeIsInterface(Node *n, SwigType *type) {
+ bool is_interface;
+ Delete(goTypeWithInfo(n, type, false, &is_interface));
+ return is_interface;
+ }
+
+ /* ----------------------------------------------------------------------
+ * hasGoTypemap
+ *
+ * Return whether a type has a "gotype" typemap entry.
+ * ---------------------------------------------------------------------- */
+
+ bool hasGoTypemap(Node *n, SwigType *type) {
+ Parm *p = NewParm(type, "test", n);
+ SwigType *tm = Swig_typemap_lookup("gotype", p, "", NULL);
+ Delete(p);
+ if (tm && Strstr(tm, "$gotypename") == 0) {
+ Delete(tm);
+ return true;
+ }
+ Delete(tm);
+ return false;
+ }
+
+ /* ----------------------------------------------------------------------
+ * goEnumName()
+ *
+ * Given an enum node, return a string to use for the enum type in Go.
+ * ---------------------------------------------------------------------- */
+
+ String *goEnumName(Node *n) {
+ String *ret = Getattr(n, "go:enumname");
+ if (ret) {
+ return Copy(ret);
+ }
+
+ if (Equal(Getattr(n, "type"), "enum ")) {
+ return NewString("int");
+ }
+
+ String *type = Getattr(n, "enumtype");
+ assert(type);
+ char *p = Char(type);
+ int len = Len(type);
+ String *s = NewString("");
+ bool capitalize = true;
+ for (int i = 0; i < len; ++i, ++p) {
+ if (*p == ':') {
+ ++i;
+ ++p;
+ assert(*p == ':');
+ capitalize = true;
+ } else if (capitalize) {
+ Putc(toupper(*p), s);
+ capitalize = false;
+ } else {
+ Putc(*p, s);
+ }
+ }
+
+ ret = Swig_name_mangle(s);
+ Delete(s);
+ return ret;
+ }
+
+
+ /* ----------------------------------------------------------------------
+ * getParm()
+ *
+ * Get the real parameter to use.
+ * ---------------------------------------------------------------------- */
+
+ Parm *getParm(Parm *p) {
+ while (p && checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+ return p;
+ }
+
+ /* ----------------------------------------------------------------------
+ * nextParm()
+ *
+ * Return the next parameter.
+ * ---------------------------------------------------------------------- */
+
+ Parm *nextParm(Parm *p) {
+ if (!p) {
+ return NULL;
+ } else if (Getattr(p, "tmap:in")) {
+ return Getattr(p, "tmap:in:next");
+ } else {
+ return nextSibling(p);
+ }
+ }
+
+ /* ----------------------------------------------------------------------
+ * isStatic
+ *
+ * Return whether a node should be considered as static rather than
+ * as a member.
+ * ---------------------------------------------------------------------- */
+
+ bool isStatic(Node *n) {
+ String *storage = Getattr(n, "storage");
+ return (storage && (Swig_storage_isstatic(n) || Strcmp(storage, "friend") == 0) && (!SmartPointer || !Getattr(n, "allocate:smartpointeraccess")));
+ }
+
+ /* ----------------------------------------------------------------------
+ * isFriend
+ *
+ * Return whether a node is a friend.
+ * ---------------------------------------------------------------------- */
+
+ bool isFriend(Node *n) {
+ String *storage = Getattr(n, "storage");
+ return storage && Strcmp(storage, "friend") == 0;
+ }
+
+}; /* class GO */
+
+/* -----------------------------------------------------------------------------
+ * swig_go() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_go() {
+ return new GO();
+}
+extern "C" Language *swig_go(void) {
+ return new_swig_go();
+}
+
+/* -----------------------------------------------------------------------------
+ * Static member variables
+ * ----------------------------------------------------------------------------- */
+
+// Usage message.
+const char * const GO::usage = "\
+Go Options (available with -go)\n\
+ -gccgo - Generate code for gccgo rather than 6g/8g\n\
+ -go-pkgpath <p> - Like gccgo -fgo-pkgpath option\n\
+ -go-prefix <p> - Like gccgo -fgo-prefix option\n\
+ -intgosize <s> - Set size of Go int type--32 or 64 bits\n\
+ -package <name> - Set name of the Go package to <name>\n\
+ -use-shlib - Force use of a shared library\n\
+ -soname <name> - Set shared library holding C/C++ code to <name>\n\
+\n";