/trunk/Source/Modules/go.cxx
C++ | 2221 lines | 1701 code | 259 blank | 261 comment | 364 complexity | 78793f1dd6d1ffe0524db92217de5307 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
- /* -----------------------------------------------------------------------------
- * 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.
- * ----------------------------------------------------------------------------- */
- char cvsroot_go_cxx[] = "$Id";
- #include "swigmod.h"
- #include "cparse.h"
- #include <ctype.h>
- #ifdef HAVE_GCCGO_46
- #define GCCGO_46_DEFAULT true
- #else
- #define GCCGO_46_DEFAULT false
- #endif
- class GO:public Language {
- static const char *const usage;
- // Go package name.
- String *package;
- // Flag for generating gccgo output.
- bool gccgo_flag;
- // Flag for generating gccgo 4.6 output.
- bool gccgo_46_flag;
- // Prefix to use with gccgo.
- String *go_prefix;
- // Name of shared library to import.
- String *soname;
- // Size in bits of the C type "long".
- int long_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_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 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;
- public:
- GO():package(NULL),
- gccgo_flag(false),
- gccgo_46_flag(GCCGO_46_DEFAULT),
- go_prefix(NULL),
- soname(NULL),
- long_type_size(32),
- 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_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_types(NULL),
- defined_types(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");
- // 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], "-gccgo-46") == 0) {
- Swig_mark_arg(i);
- gccgo_46_flag = true;
- } else if (strcmp(argv[i], "-no-gccgo-46") == 0) {
- Swig_mark_arg(i);
- gccgo_46_flag = false;
- } else if (strcmp(argv[i], "-go-prefix") == 0) {
- if (argv[i + 1]) {
- go_prefix = NewString(argv[i + 1]);
- Swig_mark_arg(i);
- Swig_mark_arg(i + 1);
- i++;
- } else {
- Swig_arg_error();
- }
- } 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) {
- if (argv[i + 1]) {
- long_type_size = atoi(argv[i + 1]);
- if (long_type_size != 32 && long_type_size != 64) {
- Printf(stderr, "-longsize 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) {
- Printf(stdout, "%s\n", usage);
- }
- }
- }
- if (gccgo_flag && !go_prefix) {
- go_prefix = NewString("go");
- }
- // Add preprocessor symbol to parser.
- Preprocessor_define("SWIGGO 1", 0);
- if (gccgo_flag) {
- Preprocessor_define("SWIGGO_GCCGO 1", 0);
- }
- if (long_type_size == 32) {
- Preprocessor_define("SWIGGO_LONG_TYPE_SIZE 32", 0);
- } else {
- Preprocessor_define("SWIGGO_LONG_TYPE_SIZE 64", 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"));
- }
- String *module = Getattr(n, "name");
- if (!package) {
- package = Copy(module);
- }
- if (!soname) {
- soname = Copy(package);
- Append(soname, ".so");
- }
- // Get filenames.
- 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_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_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 (directorsEnabled()) {
- Printf(f_c_runtime, "#define SWIG_DIRECTORS\n");
- Swig_banner(f_c_directors_h);
- 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");
- Printf(f_c_directors, "#include \"%s\"\n\n", Swig_file_filename(c_filename_h));
- }
- Swig_banner(f_go_begin);
- if (!gccgo_flag) {
- Swig_banner(f_gc_begin);
- 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);
- // 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_types = NewHash();
- defined_types = NewHash();
- // Emit code.
- Language::top(n);
- // Write out definitions for the types not defined by SWIG.
- 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_types);
- Delete(defined_types);
- /* Write and cleanup */
- Dump(f_c_header, f_c_runtime);
- if (directorsEnabled()) {
- Printf(f_c_directors_h, "#endif\n");
- Close(f_c_directors_h);
- Delete(f_c_directors_h);
- f_c_directors_h = NULL;
- Dump(f_c_directors, f_c_runtime);
- Close(f_c_directors);
- 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_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_runtime);
- Delete(f_go_header);
- Delete(f_go_wrappers);
- if (!gccgo_flag) {
- Delete(f_gc_runtime);
- Delete(f_gc_header);
- Delete(f_gc_wrappers);
- }
- Close(f_c_begin);
- Delete(f_c_begin);
- Close(f_go_begin);
- Delete(f_go_begin);
- if (!gccgo_flag) {
- Close(f_gc_begin);
- 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) {
- Printv(f_go_begin, "import \"", modname, "\"\n", NULL);
- imported_package = modname;
- saw_import = true;
- }
- int r = Language::importDirective(n);
- imported_package = hold_import;
- return r;
- }
- /* ----------------------------------------------------------------------
- * 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);
- bool needs_wrapper;
- int r = goFunctionWrapper(n, name, go_name, overname, wname, base, parms, result, is_static, &needs_wrapper);
- if (r != SWIG_OK) {
- return r;
- }
- if (!gccgo_flag) {
- r = gcFunctionWrapper(n, name, go_name, overname, wname, parms, result, is_static, needs_wrapper);
- 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, bool *p_needs_wrapper) {
- Wrapper *dummy = NewWrapper();
- emit_attach_parmmaps(parms, dummy);
- Swig_typemap_attach_parms("default", parms, dummy);
- Swig_typemap_attach_parms("gotype", parms, dummy);
- int parm_count = emit_num_arguments(parms);
- 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;
- }
- 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);
- // 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.
- if (!needs_wrapper) {
- Parm *p = parms;
- for (int i = 0; i < parm_count; ++i) {
- p = getParm(p);
- String *ty = Getattr(p, "type");
- if (goTypeIsInterface(p, ty)) {
- needs_wrapper = true;
- break;
- }
- p = nextParm(p);
- }
- }
- if (goTypeIsInterface(n, result)) {
- needs_wrapper = true;
- }
- *p_needs_wrapper = needs_wrapper;
- // 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 && !gccgo_46_flag) {
- Printv(f_go_wrappers, "//extern ", go_prefix, "_", wname, "\n", NULL);
- }
- Printv(f_go_wrappers, "func ", wrapper_name, "(", NULL);
- if (parm_count > required_count) {
- Printv(f_go_wrappers, "int", NULL);
- }
- Parm *p = getParm(parms);
- Swig_cparm_name(p, 0);
- int i = 0;
- if (is_destructor) {
- if (parm_count > required_count) {
- Printv(f_go_wrappers, ", ", NULL);
- }
- Printv(f_go_wrappers, "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, receiver, NULL);
- if (!base) {
- ++i;
- p = nextParm(p);
- }
- }
- for (; i < parm_count; ++i) {
- p = getParm(p);
- // Give the parameter a name we will use below.
- Swig_cparm_name(p, i);
- 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, tm, NULL);
- Delete(tm);
- p = nextParm(p);
- }
- Printv(f_go_wrappers, ")", NULL);
- if (is_constructor) {
- Printv(f_go_wrappers, " ", class_receiver, NULL);
- } else {
- if (SwigType_type(result) != T_VOID) {
- String *tm = goWrapperType(n, result, true);
- Printv(f_go_wrappers, " ", tm, NULL);
- Delete(tm);
- }
- }
- if (gccgo_flag && gccgo_46_flag) {
- Printv(f_go_wrappers, " __asm__ (\"", go_prefix, "_", wname, "\")", NULL);
- }
- Printv(f_go_wrappers, "\n\n", NULL);
- }
- // Start defining the Go function.
- if (!needs_wrapper && gccgo_flag && !gccgo_46_flag) {
- Printv(f_go_wrappers, "//extern ", go_prefix, "_", wname, "\n", NULL);
- }
- Printv(f_go_wrappers, "func ", NULL);
- Parm *p = parms;
- int pi = 0;
- // Add the receiver if this is a method.
- if (receiver) {
- Printv(f_go_wrappers, "(", NULL);
- if (base && receiver) {
- Printv(f_go_wrappers, "_swig_base", NULL);
- } else {
- Printv(f_go_wrappers, Getattr(p, "lname"), NULL);
- 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);
- Delete(cl);
- } else {
- if (pi > (receiver && !base ? 1 : 0)) {
- Printv(parm_print, ", ", NULL);
- }
- if (pi >= required_count) {
- Printv(parm_print, "_swig_args ...interface{}", NULL);
- break;
- }
- if (needs_wrapper) {
- Printv(parm_print, Getattr(p, "lname"), " ", NULL);
- }
- 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, " ", cl, NULL);
- Delete(cl);
- } else {
- if (SwigType_type(result) != T_VOID) {
- String *tm = goType(n, result);
- Printv(parm_print, " ", tm, NULL);
- 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);
- }
- }
- if (gccgo_flag && !gccgo_46_flag) {
- Printv(f_go_wrappers, "\tsyscall.Entersyscall()\n", NULL);
- Printv(f_go_wrappers, "\tdefer syscall.Exitsyscall()\n", NULL);
- }
- Printv(f_go_wrappers, "\t", NULL);
- if (SwigType_type(result) != T_VOID) {
- Printv(f_go_wrappers, "return ", NULL);
- }
- Printv(f_go_wrappers, wrapper_name, "(", NULL);
- if (parm_count > required_count) {
- Printv(f_go_wrappers, "len(_swig_args)", NULL);
- }
- if (base && receiver) {
- if (parm_count > required_count) {
- Printv(f_go_wrappers, ", ", NULL);
- }
- Printv(f_go_wrappers, "_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(f_go_wrappers, ", ", NULL);
- }
- Printv(f_go_wrappers, Getattr(p, "lname"), NULL);
- // If this is a destructor, then the C function expects the
- // C++ value, and we have the interface. We need to get the
- // C++ value. The same is true for a type represented as an
- // interface.
- if ((i == 0 && is_destructor) || ((i > 0 || !receiver || base || is_constructor) && goTypeIsInterface(p, Getattr(p, "type")))) {
- Printv(f_go_wrappers, ".Swigcptr()", NULL);
- }
- p = nextParm(p);
- }
- Printv(f_go_wrappers, ")\n", NULL);
- Printv(f_go_wrappers, "}\n", NULL);
- } else {
- if (gccgo_flag && gccgo_46_flag) {
- Printv(f_go_wrappers, " __asm__ (\"", go_prefix, "_", wname, "\")\n", NULL);
- }
- }
- Printv(f_go_wrappers, "\n", NULL);
- Delete(wrapper_name);
- DelWrapper(dummy);
- return SWIG_OK;
- }
- /* ----------------------------------------------------------------------
- * gcFunctionWrapper()
- *
- * This is used for 6g/8g, not for gccgo. Write out the function
- * wrapper which will be compiled with 6c/8c.
- * ---------------------------------------------------------------------- */
- int gcFunctionWrapper(Node *n, String *name, String *go_name, String *overname, String *wname, ParmList *parms, SwigType *result, bool is_static, bool needs_wrapper) {
- Wrapper *f = NewWrapper();
- Printv(f->def, "#pragma dynimport ", wname, " ", wname, " \"\"\n", NULL);
- Printv(f->def, "extern void (*", wname, ")(void*);\n", NULL);
- Printv(f->def, "static void (*x", wname, ")(void*) = ", wname, ";\n", NULL);
- Printv(f->def, "\n", NULL);
- Printv(f->def, "void\n", NULL);
- Wrapper *dummy = NewWrapper();
- emit_attach_parmmaps(parms, dummy);
- Swig_typemap_attach_parms("default", parms, dummy);
- Swig_typemap_attach_parms("gosize", parms, dummy);
- int parm_count = emit_num_arguments(parms);
- int required_count = emit_num_required(parms);
- String *parm_size = NewString("");
- if (parm_count > required_count) {
- Append(parm_size, "SWIG_PARM_SIZE");
- }
- if (class_receiver && !is_static) {
- if (Len(parm_size) > 0) {
- Append(parm_size, " + ");
- }
- Append(parm_size, "SWIG_PARM_SIZE");
- }
- Parm *p = parms;
- for (int i = 0; i < parm_count; ++i) {
- p = getParm(p);
- addGcTypeSize(p, Getattr(p, "type"), parm_size);
- p = nextParm(p);
- }
- if (SwigType_type(result) != T_VOID) {
- addGcTypeSize(n, result, parm_size);
- }
- if (Len(parm_size) == 0) {
- Append(parm_size, "1");
- }
- String *fn_name;
- if (!needs_wrapper) {
- fn_name = Copy(go_name);
- if (overname) {
- Append(fn_name, overname);
- }
- } else {
- fn_name = buildGoWrapperName(name, overname);
- }
- // \xc2\xb7 is UTF-8 for U+00B7 which is Unicode 'Middle Dot'
- Printv(f->def, "\xc2\xb7", fn_name, "(struct { uint8 x[", parm_size, "];} p)", NULL);
- Delete(fn_name);
- Delete(parm_size);
- Printv(f->code, "{\n", NULL);
- Printv(f->code, "\truntime\xc2\xb7" "cgocall(x", wname, ", &p);\n", NULL);
- Printv(f->code, "}\n", NULL);
- Printv(f->code, "\n", NULL);
- Wrapper_print(f, f_gc_wrappers);
- DelWrapper(f);
- DelWrapper(dummy);
- return SWIG_OK;
- }
- /* ----------------------------------------------------------------------
- * getGcTypeSize()
- *
- * Return the size to use when passing a type from 6g/8g to 6c/8c.
- * ---------------------------------------------------------------------- */
- String *addGcTypeSize(Node *n, SwigType *type, String *orig) {
- if (Len(orig) > 0) {
- Append(orig, " + ");
- }
- String *go = goType(n, type);
- if (Cmp(go, "string") == 0) {
- // A string has a pointer and a length.
- Append(orig, "(2 * SWIG_PARM_SIZE)");
- } else if (Strncmp(go, "[]", 2) == 0) {
- // A slice has a pointer, a length, and a capacity. The
- // length and capacity are always 4 bytes.
- Append(orig, "(SWIG_PARM_SIZE + 8)");
- } else if (Strcmp(go, "float64") == 0) {
- Append(orig, "8");
- } else if (Strcmp(go, "complex64") == 0) {
- Append(orig, "8");
- } else if (Strcmp(go, "complex128") == 0) {
- Append(orig, "16");
- } else {
- Append(orig, "SWIG_PARM_SIZE");
- }
- return orig;
- }
- /* ----------------------------------------------------------------------
- * 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\tint _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);
- }
- 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);
- 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);
- }
- }
- 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_prefix, "_", wname, "(", NULL);
- if (parm_count > required_count) {
- Printv(fnname, "int _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);
- if (SwigType_type(result) == T_VOID) {
- Printv(f->def, "void ", fnname, NULL);
- } else {
- String *ct = gccgoCTypeForGoValue(n, result, fnname);
- Printv(f->def, ct, NULL);
- Delete(ct);
- }
- Printv(f->def, " {\n", NULL);
- Delete(fnname);
- if (SwigType_type(result) != T_VOID) {
- String *ln = NewString("go_result");
- String *ct = gccgoCTypeForGoValue(n, result, ln);
- Wrapper_add_local(f, "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);
- 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);
- }
- }
- 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 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 {
- Replaceall(tm, "$input", Getattr(p, "emit:input"));
- Printv(f->code, tm, "\n\n", NULL);
- p = Getattr(p, "tmap:check:next");
- }
- }
- }
- /* -----------------------------------------------------------------------
- * getGoAction()
- *
- * Get the action of the function. This is used for C/C++ function.
- * ----------------------------------------------------------------------- */
- void emitGoAction(Node *n, List *base, ParmList *parms, SwigType *result, Wrapper *f) {
- 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 {
- if (!gccgo_flag) {
- static const String *swig_a_result = NewStringf("swig_a->%s", Swig_cresult_name());
- Replaceall(tm, "$result", swig_a_result);
- } else {
- Replaceall(tm, "$result", "go_result");
- }
- if (GetFlag(n, "feature:new")) {
- Replaceall(tm, "$owner", "1");
- } else {
- Replaceall(tm, "$owner", "0");
- }
- Printv(f->code, tm, "\n", NULL);
- Delete(tm);
- }
- 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 {
- Replaceall(tm, "$result", Swig_cresult_name());
- Replaceall(tm, "$input", Getattr(p, "emit:input"));
- Printv(f->code, tm, "\n", NULL);
- p = Getattr(p, "tmap:argout: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 {
- Replaceall(tm, "$input", Getattr(p, "emit:input"));
- Printv(ret, tm, "\n", NULL);
- 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 (Getattr(n, "storage") && Strcmp(Getattr(n, "storage"), "static") == 0) {
- 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);
- Printf(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) {
- continue;
- }
- String *storage = Getattr(ni, "storage");
- if (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 (is_non_virtual_protected_access(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",