/* ----------------------------------------------------------------------------- * 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. * * c.cxx * * C language module for SWIG. * ----------------------------------------------------------------------------- */ #include #include "swigmod.h" int SwigType_isbuiltin(SwigType *t) { const char* builtins[] = { "void", "short", "int", "long", "char", "float", "double", "bool", 0 }; int i = 0; char *c = Char(t); if (!t) return 0; while (builtins[i]) { if (strcmp(c, builtins[i]) == 0) return 1; i++; } return 0; } // Private helpers, could be made public and reused from other language modules in the future. namespace { // Delete a DOH object on scope exit. class scoped_dohptr { public: scoped_dohptr() : obj_(NULL) {} explicit scoped_dohptr(DOH* obj) : obj_(obj) {} ~scoped_dohptr() { Delete(obj_); } // This is an std::auto_ptr<>-like "destructive" copy ctor which allows to return objects of this type from functions. scoped_dohptr(scoped_dohptr const& other) : obj_(other.release()) {} // Same for the assignment operator. scoped_dohptr& operator=(scoped_dohptr const& other) { reset(other.release()); return *this; } // Assignment operator takes ownership of the pointer, just as the ctor does. scoped_dohptr& operator=(DOH* obj) { reset(obj); return *this; } DOH* get() const { return obj_; } DOH* release() const /* not really */ { DOH* obj = obj_; const_cast(const_cast(this)->obj_) = NULL; return obj; } void reset(DOH* obj = NULL) { if (obj != obj_) { Delete(obj_); obj_ = obj; } } operator DOH*() const { return obj_; } protected: DOH* obj_; }; // Wrapper for a DOH object which can be owned or not. class maybe_owned_dohptr : public scoped_dohptr { public: explicit maybe_owned_dohptr(DOH* obj = NULL) : scoped_dohptr(obj), owned_(true) {} maybe_owned_dohptr(maybe_owned_dohptr const& other) : scoped_dohptr(other) { owned_ = other.owned_; // We can live other.owned_ unchanged, as its pointer is null now anyhow. } maybe_owned_dohptr& operator=(maybe_owned_dohptr const& other) { reset(other.release()); owned_ = other.owned_; return *this; } ~maybe_owned_dohptr() { if (!owned_) obj_ = NULL; // Prevent it from being deleted by the base class dtor. } void assign_owned(DOH* obj) { reset(obj); } void assign_non_owned(DOH* obj) { reset(obj); owned_ = false; } private: bool owned_; }; // Helper class to output "begin" fragment in the ctor and "end" in the dtor. class begin_end_output_guard { public: begin_end_output_guard(File* f, const_String_or_char_ptr begin, const_String_or_char_ptr end) : f_(f), end_(NewString(end)) { String* const s = NewString(begin); Dump(s, f_); Delete(s); } ~begin_end_output_guard() { Dump(end_, f_); Delete(end_); } private: // Non copyable. begin_end_output_guard(const begin_end_output_guard&); begin_end_output_guard& operator=(const begin_end_output_guard&); File* const f_; String* const end_; }; // Subclass to output extern "C" guards when compiling as C++. class cplusplus_output_guard : private begin_end_output_guard { public: explicit cplusplus_output_guard(File* f) : begin_end_output_guard( f, "#ifdef __cplusplus\n" "extern \"C\" {\n" "#endif\n\n", "#ifdef __cplusplus\n" "}\n" "#endif\n\n" ) { } }; // String containing one indentation level for the generated code. const char* const cindent = " "; } // anonymous namespace class C:public Language { static const char *usage; // These files contain types used by the wrappers declarations and the declarations themselves and end up in the output header file. File *f_wrappers_types; File *f_wrappers_decl; // This one contains wrapper functions definitions and end up in the output C++ file. File *f_wrappers; String *empty_string; // Prefix used for all symbols, if defined. String *ns_prefix; // Prefix for module-level symbols, currently just the module name. String *module_prefix; // Used only while generating wrappers for an enum and contains the prefix to use for enum elements if non-null. String *enum_prefix; // Used only while generating wrappers for an enum, as we don't know if enum will have any elements or not in advance and we must not generate an empty enum, // so we accumulate the full declaration here and then write it to f_wrappers_types at once only if there are any elements. String *enum_decl; // Selects between the wrappers (public) declarations and (private) definitions. enum { output_wrapper_decl, output_wrapper_def } current_output; public: /* ----------------------------------------------------------------------------- * C() * ----------------------------------------------------------------------------- */ C() : empty_string(NewString("")), ns_prefix(NULL), module_prefix(NULL) { } ~C() { Delete(ns_prefix); Delete(module_prefix); } // Return the name to be used in proxy code and cache it as "proxyname". String *getProxyName(Node *n) { if (!n) return 0; String *proxyname = NULL; if ((proxyname = Getattr(n, "proxyname"))) return Copy(proxyname); String *symname = Getattr(n, "sym:name"); String *nspace = Getattr(n, "sym:nspace"); if (nspace) { scoped_dohptr nspace_mangled(Swig_string_mangle(nspace)); proxyname = NewStringf("%s_%s", (DOH*)nspace_mangled, symname); } else if (ns_prefix) { proxyname = NewStringf("%s_%s", ns_prefix, symname); } else { proxyname = Copy(symname); } Setattr(n, "proxyname", proxyname); return proxyname; } // Construct the name to be used for a function with the given name in C wrappers. // // The returned string must be freed by caller. maybe_owned_dohptr getFunctionWrapperName(Node *n, String *name) const { maybe_owned_dohptr wname; // The basic idea here is that for class members we don't need to use any prefix at all, as they're already prefixed by the class name, which has the // appropriate prefix, but we need to use a prefix for the other symbols. // // However there are a couple of special cases complicating this: // // - Friend functions are declared inside the class, but are not member functions, so we have to check for both the current class and "ismember" property. // - Destructors and implicitly generated constructors don't have "ismember" for some reason, so we need to check for them specifically. // - Variable getters and setters don't need to use the prefix as they don't clash with anything. if ((getCurrentClass() && (Checkattr(n, "ismember", "1") || Checkattr(n, "nodeType", "constructor") || Checkattr(n, "nodeType", "destructor"))) || - Checkattr(n, "varget", "1") || Checkattr(n, "varset", "1")) { wname.assign_non_owned(name); return wname; } // Use namespace as the prefix if feature:nspace is in use. scoped_dohptr scopename_prefix; if (GetFlag(parentNode(n), "feature:nspace")) { scopename_prefix = Swig_scopename_prefix(Getattr(n, "name")); if (scopename_prefix) { scoped_dohptr mangled_prefix(Swig_string_mangle(scopename_prefix)); scopename_prefix = mangled_prefix; } } // Fall back to the module name if we don't use feature:nspace and don't have the global prefix neither. // // Note that we really, really need to use some prefix, as wrapper function can't have the same name as the original function being wrapped. String* const prefix = scopename_prefix ? scopename_prefix : ns_prefix ? ns_prefix : module_prefix; wname.assign_owned(NewStringf("%s_%s", prefix, name)); return wname; } /* ----------------------------------------------------------------------------- * getClassProxyName() * * Test to see if a type corresponds to something wrapped with a proxy class. * Return NULL if not, otherwise the proxy class name to be freed by the caller. * ----------------------------------------------------------------------------- */ String *getClassProxyName(SwigType *t) { Node *n = classLookup(t); return n ? getProxyName(n) : NULL; } /* ----------------------------------------------------------------------------- * getEnumName() * * Return the name to use for the enum in the generated code. * Also caches it in the node for subsequent access. * Returns NULL if the node doesn't correspond to an enum. * ----------------------------------------------------------------------------- */ String *getEnumName(Node *n) { String *enumname = NULL; if (n) { enumname = Getattr(n, "enumname"); if (!enumname) { String *symname = Getattr(n, "sym:name"); if (symname) { // Add in class scope when referencing enum if not a global enum String *proxyname = 0; if (String *name = Getattr(n, "name")) { if (String *scopename_prefix = Swig_scopename_prefix(name)) { proxyname = getClassProxyName(scopename_prefix); Delete(scopename_prefix); } } if (proxyname) { enumname = NewStringf("%s_%s", proxyname, symname); Delete(proxyname); } else { // global enum or enum in a namespace enumname = getProxyName(n); } Setattr(n, "enumname", enumname); Delete(enumname); } } } return enumname; } /* ----------------------------------------------------------------------------- * substituteResolvedTypeSpecialVariable() * ----------------------------------------------------------------------------- */ void substituteResolvedTypeSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable) { if (!CPlusPlus) { // Just use the original C type when not using C++, we know that this type can be used in the wrappers. Clear(tm); String* const s = SwigType_str(classnametype, 0); Append(tm, s); Delete(s); return; } if (SwigType_isenum(classnametype)) { String *enumname = getEnumName(enumLookup(classnametype)); if (enumname) Replaceall(tm, classnamespecialvariable, enumname); else Replaceall(tm, classnamespecialvariable, NewStringf("int")); } else { scoped_dohptr btype(SwigType_base(classnametype)); String* typestr = NIL; if (current_output == output_wrapper_def || Cmp(btype, "SwigObj") == 0) { // Special case, just leave it unchanged. typestr = NewString("SwigObj"); } else { typestr = getClassProxyName(classnametype); if (!typestr) { if (SwigType_isbuiltin(btype)) { // This should work just as well in C without any changes. typestr = SwigType_str(classnametype, 0); } else { // Swig doesn't know anything about this type, use descriptor for it. typestr = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype)); // And make sure it is declared before it is used. Printf(f_wrappers_types, "typedef struct %s %s;\n\n", typestr, typestr); } } } Replaceall(tm, classnamespecialvariable, typestr); Delete(typestr); } } /* ----------------------------------------------------------------------------- * substituteResolvedType() * * Substitute the special variable $csclassname with the proxy class name for classes/structs/unions * that SWIG knows about. Also substitutes enums with enum name. * Otherwise use the $descriptor name for the C# class name. Note that the $&csclassname substitution * is the same as a $&descriptor substitution, ie one pointer added to descriptor name. * Inputs: * pt - parameter type * tm - typemap contents that might contain the special variable to be replaced * Outputs: * tm - typemap contents complete with the special variable substitution * ----------------------------------------------------------------------------- */ void substituteResolvedType(SwigType *pt, String *tm) { SwigType *type = SwigType_typedef_resolve_all(pt); SwigType *strippedtype = SwigType_strip_qualifiers(type); if (Strstr(tm, "$resolved_type")) { SwigType *classnametype = Copy(strippedtype); substituteResolvedTypeSpecialVariable(classnametype, tm, "$resolved_type"); Delete(classnametype); } if (Strstr(tm, "$*resolved_type")) { SwigType *classnametype = Copy(strippedtype); Delete(SwigType_pop(classnametype)); if (Len(classnametype) > 0) { substituteResolvedTypeSpecialVariable(classnametype, tm, "$*resolved_type"); } Delete(classnametype); } if (Strstr(tm, "$&resolved_type")) { SwigType *classnametype = Copy(strippedtype); SwigType_add_pointer(classnametype); substituteResolvedTypeSpecialVariable(classnametype, tm, "$&resolved_type"); Delete(classnametype); } Delete(strippedtype); Delete(type); } /*---------------------------------------------------------------------- * replaceSpecialVariables() * * Override the base class method to ensure that $resolved_type is expanded correctly inside $typemap(). *--------------------------------------------------------------------*/ virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) { (void)method; SwigType *type = Getattr(parm, "type"); substituteResolvedType(type, tm); } /* ------------------------------------------------------------ * main() * ------------------------------------------------------------ */ virtual void main(int argc, char *argv[]) { bool except_flag = CPlusPlus; // look for certain command line options for (int i = 1; i < argc; i++) { if (argv[i]) { if (strcmp(argv[i], "-help") == 0) { Printf(stdout, "%s\n", usage); } else if (strcmp(argv[i], "-namespace") == 0) { if (argv[i + 1]) { scoped_dohptr ns(NewString(argv[i + 1])); ns_prefix = Swig_string_mangle(ns); Swig_mark_arg(i); Swig_mark_arg(i + 1); i++; } else { Swig_arg_error(); } } else if (strcmp(argv[i], "-noexcept") == 0) { except_flag = false; Swig_mark_arg(i); } } } // add a symbol to the parser for conditional compilation Preprocessor_define("SWIGC 1", 0); if (except_flag) Preprocessor_define("SWIG_C_EXCEPT 1", 0); if (CPlusPlus) Preprocessor_define("SWIG_CPPMODE 1", 0); SWIG_library_directory("c"); // add typemap definitions SWIG_typemap_lang("c"); SWIG_config_file("c.swg"); String* const ns_prefix_ = ns_prefix ? NewStringf("%s_", ns_prefix) : NewString(""); // The default naming convention is to use new_Foo(), copy_Foo() and delete_Foo() for the default/copy ctor and dtor of the class Foo, but we prefer to // start all Foo methods with the same prefix, so change this. Notice that new/delete are chosen to ensure that we avoid conflicts with the existing class // methods, more natural create/destroy, for example, could result in errors if the class already had a method with the same name, but this is impossible // for the chosen names as they're keywords in C++ ("copy" is still a problem but we'll just have to live with it). Swig_name_register("construct", NewStringf("%s%%n%%c_new", ns_prefix_)); Swig_name_register("copy", NewStringf("%s%%n%%c_copy", ns_prefix_)); Swig_name_register("destroy", NewStringf("%s%%n%%c_delete", ns_prefix_)); // These ones are only needed when using a global prefix, as otherwise the defaults are fine. if (ns_prefix) { Swig_name_register("member", NewStringf("%s%%n%%c_%%m", ns_prefix_)); Swig_name_register("type", NewStringf("%s%%c", ns_prefix_)); } allow_overloading(); } /* --------------------------------------------------------------------- * top() * --------------------------------------------------------------------- */ virtual int top(Node *n) { String *module = Getattr(n, "name"); module_prefix = Copy(module); String *outfile = Getattr(n, "outfile"); // initialize I/O const scoped_dohptr f_wrappers_cxx(NewFile(outfile, "w", SWIG_output_files())); if (!f_wrappers_cxx) { FileErrorDisplay(outfile); SWIG_exit(EXIT_FAILURE); } Swig_banner(f_wrappers_cxx); // Open the file where all wrapper declarations will be written to in the end. String* const outfile_h = Getattr(n, "outfile_h"); const scoped_dohptr f_wrappers_h(NewFile(outfile_h, "w", SWIG_output_files())); if (!f_wrappers_h) { FileErrorDisplay(outfile_h); SWIG_exit(EXIT_FAILURE); } Swig_banner(f_wrappers_h); // Associate file with the SWIG sections with the same name, so that e.g. "%header" contents end up in f_header etc. const scoped_dohptr f_begin(NewStringEmpty()); const scoped_dohptr f_header(NewStringEmpty()); const scoped_dohptr f_runtime(NewStringEmpty()); const scoped_dohptr f_init(NewStringEmpty()); // This one is used outside of this function, so it's a member variable rather than a local one. f_wrappers = NewStringEmpty(); Swig_register_filebyname("begin", f_begin); Swig_register_filebyname("header", f_header); Swig_register_filebyname("wrapper", f_wrappers); Swig_register_filebyname("runtime", f_runtime); Swig_register_filebyname("init", f_init); // This one is C-specific and goes directly to the output header file. Swig_register_filebyname("cheader", f_wrappers_h); { String* const include_guard_name = NewStringf("SWIG_%s_WRAP_H_", Char(module)); String* const include_guard_begin = NewStringf( "#ifndef %s\n" "#define %s\n\n", include_guard_name, include_guard_name ); String* const include_guard_end = NewStringf( "\n" "#endif /* %s */\n", include_guard_name ); begin_end_output_guard include_guard_wrappers_h(f_wrappers_h, include_guard_begin, include_guard_end); // All the struct types used by the functions go to f_wrappers_types so that they're certain to be defined before they're used by any functions. All the // functions declarations go directly to f_wrappers_decl and f_wrappers_h_body combines both of them. const scoped_dohptr f_wrappers_h_body(NewStringEmpty()); f_wrappers_types = NewString(""); f_wrappers_decl = NewString(""); { cplusplus_output_guard cplusplus_guard_wrappers(f_wrappers), cplusplus_guard_wrappers_h(f_wrappers_h_body); // emit code for children Language::top(n); Dump(f_wrappers_types, f_wrappers_h_body); Delete(f_wrappers_types); Dump(f_wrappers_decl, f_wrappers_h_body); Delete(f_wrappers_decl); } // close extern "C" guards Dump(f_wrappers_h_body, f_wrappers_h); } // close wrapper header guard // write all to the file Dump(f_begin, f_wrappers_cxx); Dump(f_runtime, f_wrappers_cxx); Dump(f_header, f_wrappers_cxx); Dump(f_wrappers, f_wrappers_cxx); Dump(f_init, f_wrappers_cxx); return SWIG_OK; } /* ----------------------------------------------------------------------- * globalvariableHandler() * ------------------------------------------------------------------------ */ virtual int globalvariableHandler(Node *n) { // Don't export static globals, they won't be accessible when using a shared library, for example. if (Checkattr(n, "storage", "static")) return SWIG_NOWRAP; // We can't export variables defined inside namespaces to C directly, whatever their type, and we can only export them under their original name, so we // can't do it when using a global namespace prefix neither. if (!ns_prefix && !scoped_dohptr(Swig_scopename_prefix(Getattr(n, "name")))) { // If we can export the variable directly, do it, this will be more convenient to use from C code than accessor functions. if (String* const var_decl = make_c_var_decl(n)) { Printv(f_wrappers_decl, "SWIGIMPORT ", var_decl, ";\n\n", NIL); Delete(var_decl); return SWIG_OK; } } // We have to prepend the global prefix to the names of the accessors for this variable, if we use one. // // Note that we can't just register the name format using the prefix for "get" and "set", as we do it for "member", and using it for both would result in // the prefix being used twice for the member variables getters and setters, so we have to work around it here instead. if (ns_prefix && !getCurrentClass()) { Swig_require("c:globalvariableHandler", n, "*sym:name", NIL); Setattr(n, "sym:name", NewStringf("%s_%s", ns_prefix, Getattr(n, "sym:name"))); } // Otherwise, e.g. if it's of a C++-only type, or a reference, generate accessor functions for it. int const rc = Language::globalvariableHandler(n); if (Getattr(n, "view")) Swig_restore(n); return rc; } /* ---------------------------------------------------------------------- * prepend_feature() * ---------------------------------------------------------------------- */ String* prepend_feature(Node *n) { String *prepend_str = Getattr(n, "feature:prepend"); if (prepend_str) { char *t = Char(prepend_str); if (*t == '{') { Delitem(prepend_str, 0); Delitem(prepend_str, DOH_END); } } return (prepend_str ? prepend_str : empty_string); } /* ---------------------------------------------------------------------- * append_feature() * ---------------------------------------------------------------------- */ String* append_feature(Node *n) { String *append_str = Getattr(n, "feature:append"); if (append_str) { char *t = Char(append_str); if (*t == '{') { Delitem(append_str, 0); Delitem(append_str, DOH_END); } } return (append_str ? append_str : empty_string); } /* ---------------------------------------------------------------------- * get_mangled_type() * ---------------------------------------------------------------------- */ String *get_mangled_type(SwigType *type_arg) { String *result = NewString(""); SwigType *type = 0; SwigType *tdtype = SwigType_typedef_resolve_all(type_arg); if (tdtype) type = tdtype; else type = Copy(type_arg); // special cases for ptr to function as an argument if (SwigType_ismemberpointer(type)) { SwigType_del_memberpointer(type); SwigType_add_pointer(type); } if (SwigType_ispointer(type)) { SwigType_del_pointer(type); if (SwigType_isfunction(type)) { Printf(result, "f"); Delete(type); return result; } Delete(type); type = Copy(type_arg); } SwigType *prefix = SwigType_prefix(type); if (Len(prefix)) { Replaceall(prefix, ".", ""); Replaceall(prefix, "const", "c"); Replaceall(prefix, "volatile", "v"); Replaceall(prefix, "a(", "a"); Replaceall(prefix, "m(", "m"); Replaceall(prefix, "q(", ""); Replaceall(prefix, ")", ""); Replaceall(prefix, " ", ""); Printf(result, "%s", prefix); } type = SwigType_base(type); if (SwigType_isbuiltin(type)) { Printf(result, "%c", *Char(SwigType_base(type))); } else if (SwigType_isenum(type)) { String* enumname = Swig_scopename_last(type); const char* s = Char(enumname); static const int len_enum_prefix = strlen("enum "); if (strncmp(s, "enum ", len_enum_prefix) == 0) s += len_enum_prefix; Printf(result, "e%s", s); } else { Printf(result, "%s", Char(Swig_name_mangle(SwigType_base(type)))); } Delete(prefix); Delete(type); return result; } void functionWrapperCSpecific(Node *n) { // this is C function, we don't apply typemaps to it String *name = Getattr(n, "sym:name"); maybe_owned_dohptr wname = getFunctionWrapperName(n, name); SwigType *type = Getattr(n, "type"); SwigType *return_type = NULL; String *arg_names = NULL; ParmList *parms = Getattr(n, "parms"); Parm *p; String *proto = NewString(""); int gencomma = 0; bool is_void_return = (SwigType_type(type) == T_VOID); // create new function wrapper object Wrapper *wrapper = NewWrapper(); // create new wrapper name Setattr(n, "wrap:name", wname); //Necessary to set this attribute? Apparently, it's never read! // create function call arg_names = Swig_cfunction_call(empty_string, parms); if (arg_names) { Delitem(arg_names, 0); Delitem(arg_names, DOH_END); } return_type = SwigType_str(type, 0); // emit wrapper prototype and code for (p = parms, gencomma = 0; p; p = nextSibling(p)) { Printv(proto, gencomma ? ", " : "", SwigType_str(Getattr(p, "type"), 0), " ", Getattr(p, "lname"), NIL); gencomma = 1; } Printv(wrapper->def, return_type, " ", wname.get(), "(", proto, ") {\n", NIL); // attach 'check' typemaps Swig_typemap_attach_parms("check", parms, wrapper); // insert constraint checking for (p = parms; p; ) { String *tm; if ((tm = Getattr(p, "tmap:check"))) { Replaceall(tm, "$target", Getattr(p, "lname")); Replaceall(tm, "$name", name); Printv(wrapper->code, tm, "\n", NIL); p = Getattr(p, "tmap:check:next"); } else { p = nextSibling(p); } } Append(wrapper->code, prepend_feature(n)); if (!is_void_return) { Printv(wrapper->code, return_type, " result;\n", NIL); Printf(wrapper->code, "result = "); } Printv(wrapper->code, Getattr(n, "name"), "(", arg_names, ");\n", NIL); Append(wrapper->code, append_feature(n)); if (!is_void_return) Printf(wrapper->code, "return result;\n"); Printf(wrapper->code, "}"); Wrapper_print(wrapper, f_wrappers); emit_wrapper_func_decl(n, wname); // cleanup Delete(proto); Delete(arg_names); Delete(return_type); DelWrapper(wrapper); } void functionWrapperAppendOverloaded(String *name, Parm* first_param) { String *over_suffix = NewString(""); Parm *p; String *mangled; for (p = first_param; p; p = nextSibling(p)) { mangled = get_mangled_type(Getattr(p, "type")); Printv(over_suffix, "_", mangled, NIL); } Append(name, over_suffix); Delete(over_suffix); } scoped_dohptr get_wrapper_func_return_type(Node *n) { SwigType *type = Getattr(n, "type"); String *return_type; if ((return_type = Swig_typemap_lookup("ctype", n, "", 0))) { substituteResolvedType(type, return_type); } else { Swig_warning(WARN_C_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(type, 0)); return_type = NewString(""); } Replaceall(return_type, "::", "_"); return scoped_dohptr(return_type); } /* ---------------------------------------------------------------------- * get_wrapper_func_proto() * * Return the function signature, i.e. the comma-separated list of argument types and names surrounded by parentheses. * If a non-null wrapper is specified, it is used to emit typemap-defined code in it and it also determines whether we're generating the prototype for the * declarations or the definitions, which changes the type used for the C++ objects. * ---------------------------------------------------------------------- */ scoped_dohptr get_wrapper_func_proto(Node *n, Wrapper* wrapper = NULL) { ParmList *parms = Getattr(n, "parms"); Parm *p; String *proto = NewString("("); int gencomma = 0; // attach the standard typemaps if (wrapper) { emit_attach_parmmaps(parms, wrapper); } else { // We can't call emit_attach_parmmaps() without a wrapper, it would just crash. // Attach "in" manually, we need it for tmap:in:numinputs below. Swig_typemap_attach_parms("in", parms, 0); } Setattr(n, "wrap:parms", parms); //never read again?! // attach 'ctype' typemaps Swig_typemap_attach_parms("ctype", parms, 0); // prepare function definition for (p = parms, gencomma = 0; p; ) { String *tm; SwigType *type = NULL; while (p && checkAttribute(p, "tmap:in:numinputs", "0")) { p = Getattr(p, "tmap:in:next"); } if (!p) break; type = Getattr(p, "type"); if (SwigType_type(type) == T_VOID) { p = nextSibling(p); continue; } if (SwigType_type(type) == T_VARARGS) { Swig_error(Getfile(n), Getline(n), "Vararg function %s not supported.\n", Getattr(n, "name")); return scoped_dohptr(NULL); } String *lname = Getattr(p, "lname"); String *c_parm_type = 0; String *arg_name = NewString(""); Printf(arg_name, "c%s", lname); if ((tm = Getattr(p, "tmap:ctype"))) { // set the appropriate type for parameter c_parm_type = Copy(tm); substituteResolvedType(type, c_parm_type); // We prefer to keep typedefs in the wrapper functions signatures as it makes them more readable, but we can't do it for nested typedefs as // they're not valid in C, so resolve them in this case. if (strstr(Char(c_parm_type), "::")) { SwigType* const tdtype = SwigType_typedef_resolve_all(c_parm_type); Delete(c_parm_type); c_parm_type = tdtype; } // template handling Replaceall(c_parm_type, "$tt", SwigType_lstr(type, 0)); } else { Swig_warning(WARN_C_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(type, 0)); } Printv(proto, gencomma ? ", " : "", c_parm_type, " ", arg_name, NIL); gencomma = 1; // apply typemaps for input parameter if ((tm = Getattr(p, "tmap:in"))) { Replaceall(tm, "$input", arg_name); if (wrapper) { Setattr(p, "emit:input", arg_name); Printf(wrapper->code, "%s\n", tm); } p = Getattr(p, "tmap:in:next"); } else { Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(type, 0)); p = nextSibling(p); } Delete(arg_name); Delete(c_parm_type); } Printv(proto, ")", NIL); return scoped_dohptr(proto); } /* ---------------------------------------------------------------------- * emit_wrapper_func_decl() * * Declares the wrapper function, using the C types used for it, in the header. * The node here is a function declaration. * ---------------------------------------------------------------------- */ void emit_wrapper_func_decl(Node *n, String *wname) { current_output = output_wrapper_decl; // add function declaration to the proxy header file Printv(f_wrappers_decl, "SWIGIMPORT ", get_wrapper_func_return_type(n).get(), " ", wname, get_wrapper_func_proto(n).get(), ";\n\n", NIL); } void functionWrapperCPPSpecific(Node *n) { ParmList *parms = Getattr(n, "parms"); String *name = Copy(Getattr(n, "sym:name")); // mangle name if function is overloaded if (Getattr(n, "sym:overloaded")) { if (!Getattr(n, "copy_constructor")) { Parm* first_param = (Parm*)parms; if (first_param) { // Skip the first "this" parameter of the wrapped methods, it doesn't participate in overload resolution and would just result in extra long // and ugly names. // // We need to avoid dropping the first argument of static methods which don't have "this" pointer, in spite of being members (and we have to // use "cplus:staticbase" for this instead of just using Swig_storage_isstatic() because "storage" is reset in staticmemberfunctionHandler() // and so is not available here. // // Of course, the constructors don't have the extra first parameter neither. if (!Checkattr(n, "nodeType", "constructor") && Checkattr(n, "ismember", "1") && !Getattr(n, "cplus:staticbase")) { first_param = nextSibling(first_param); // A special case of overloading on const/non-const "this" pointer only, we still need to distinguish between those. if (SwigType_isconst(Getattr(n, "decl"))) { const char * const nonconst = Char(Getattr(n, "decl")) + 9 /* strlen("q(const).") */; for (Node* nover = Getattr(n, "sym:overloaded"); nover; nover = Getattr(nover, "sym:nextSibling")) { if (nover == n) continue; if (Cmp(Getattr(nover, "decl"), nonconst) == 0) { // We have an overload differing by const only, disambiguate. Append(name, "_const"); break; } } } } functionWrapperAppendOverloaded(name, first_param); } } } // make sure lnames are set Parm *p; int index = 1; String *lname = 0; for (p = (Parm*)parms, index = 1; p; (p = nextSibling(p)), index++) { if(!(lname = Getattr(p, "lname"))) { lname = NewStringf("arg%d", index); Setattr(p, "lname", lname); } } // C++ function wrapper current_output = output_wrapper_def; SwigType *type = Getattr(n, "type"); scoped_dohptr return_type = get_wrapper_func_return_type(n); maybe_owned_dohptr wname = getFunctionWrapperName(n, name); bool is_void_return = (SwigType_type(type) == T_VOID); // create new function wrapper object Wrapper *wrapper = NewWrapper(); // create new wrapper name Setattr(n, "wrap:name", wname); // add variable for holding result of original function 'cppresult' if (!is_void_return) { SwigType *value_type = cplus_value_type(type); SwigType* cppresult_type = value_type ? value_type : type; SwigType* ltype = SwigType_ltype(cppresult_type); Wrapper_add_local(wrapper, "cppresult", SwigType_str(ltype, "cppresult")); Delete(ltype); Delete(value_type); } // create wrapper function prototype Printv(wrapper->def, "SWIGEXPORTC ", return_type.get(), " ", wname.get(), NIL); Printv(wrapper->def, get_wrapper_func_proto(n, wrapper).get(), NIL); Printv(wrapper->def, " {", NIL); // emit variables for holding parameters emit_parameter_variables(parms, wrapper); // emit variable for holding function return value emit_return_variable(n, return_type, wrapper); // insert constraint checking for (p = parms; p; ) { String *tm; if ((tm = Getattr(p, "tmap:check"))) { Replaceall(tm, "$target", Getattr(p, "lname")); Replaceall(tm, "$name", name); Printv(wrapper->code, tm, "\n", NIL); p = Getattr(p, "tmap:check:next"); } else { p = nextSibling(p); } } // create action code String *action = Getattr(n, "wrap:action"); if (!action) action = NewString(""); String *cbase_name = Getattr(n, "c:base_name"); if (cbase_name) { Replaceall(action, "arg1)->", NewStringf("(%s*)arg1)->", Getattr(n, "c:inherited_from"))); Replaceall(action, Getattr(n, "name"), cbase_name); } Replaceall(action, "result =", "cppresult ="); // prepare action code to use, e.g. insert try-catch blocks action = emit_action(n); // emit output typemap if needed if (!is_void_return) { String *tm; if ((tm = Swig_typemap_lookup_out("out", n, "cppresult", wrapper, action))) { // This is ugly, but the type of our result variable is not always the same as the actual return type currently because // get_wrapper_func_return_type() applies ctype typemap to it. These types are more or less compatible though, so we should be able to cast // between them explicitly. const char* start = Char(tm); const char* p = strstr(start, "$result = "); if (p == start || (p && p[-1] == ' ')) { Insert(tm, p - start + strlen("$result = "), NewStringf("(%s)", return_type.get())); } Replaceall(tm, "$result", "result"); Replaceall(tm, "$owner", GetFlag(n, "feature:new") ? "1" : "0"); Printf(wrapper->code, "%s", tm); if (Len(tm)) Printf(wrapper->code, "\n"); } else { Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(type, 0), Getattr(n, "name")); } } else { Append(wrapper->code, action); } // insert cleanup code for (p = parms; p; ) { String *tm; if ((tm = Getattr(p, "tmap:freearg"))) { if (tm && (Len(tm) != 0)) { String *input = NewStringf("c%s", Getattr(p, "lname")); Replaceall(tm, "$source", Getattr(p, "lname")); Replaceall(tm, "$input", input); Delete(input); Printv(wrapper->code, tm, "\n", NIL); } p = Getattr(p, "tmap:freearg:next"); } else { p = nextSibling(p); } } if (is_void_return) { Replaceall(wrapper->code, "$null", ""); } else { Replaceall(wrapper->code, "$null", "0"); Append(wrapper->code, "return result;\n"); } Append(wrapper->code, "}\n"); Wrapper_print(wrapper, f_wrappers); // cleanup DelWrapper(wrapper); emit_wrapper_func_decl(n, wname); Delete(name); } /* ---------------------------------------------------------------------- * functionWrapper() * ---------------------------------------------------------------------- */ virtual int functionWrapper(Node *n) { if (!Getattr(n, "sym:overloaded")) { if (!addSymbol(Getattr(n, "sym:name"), n)) return SWIG_ERROR; } if (CPlusPlus) { functionWrapperCPPSpecific(n); } else { functionWrapperCSpecific(n); } return SWIG_OK; } /* --------------------------------------------------------------------- * copy_node() * * This is not a general-purpose node copying function, but just a helper of classHandler(). * --------------------------------------------------------------------- */ Node *copy_node(Node *node) { Node *new_node = NewHash(); Setattr(new_node, "name", Copy(Getattr(node, "name"))); Setattr(new_node, "ismember", Copy(Getattr(node, "ismember"))); Setattr(new_node, "view", Copy(Getattr(node, "view"))); Setattr(new_node, "kind", Copy(Getattr(node, "kind"))); Setattr(new_node, "access", Copy(Getattr(node, "access"))); Setattr(new_node, "parms", Copy(Getattr(node, "parms"))); Setattr(new_node, "type", Copy(Getattr(node, "type"))); Setattr(new_node, "decl", Copy(Getattr(node, "decl"))); Node* const parent = parentNode(node); Setattr(new_node, "c:inherited_from", Getattr(parent, "name")); Setattr(new_node, "sym:name", Getattr(node, "sym:name")); Setattr(new_node, "sym:symtab", Getattr(parent, "symtab")); set_nodeType(new_node, "cdecl"); return new_node; } /* --------------------------------------------------------------------- * is_in() * * tests if given name already exists in one of child nodes of n * --------------------------------------------------------------------- */ Hash *is_in(String *name, Node *n) { Hash *h; for (h = firstChild(n); h; h = nextSibling(h)) { if (Cmp(name, Getattr(h, "name")) == 0) return h; } return 0; } /* --------------------------------------------------------------------- * make_c_var_decl() * * Return the C declaration for the given node of "variable" kind. * * If the variable has a type not representable in C, returns NULL, the caller must check for this! * * This function accounts for two special cases: * 1. If the type is an anonymous enum, "int" is used instead. * 2. If the type is an array, its bounds are stripped. * --------------------------------------------------------------------- */ String *make_c_var_decl(Node *n) { String *name = Getattr(n, "name"); SwigType *type = Getattr(n, "type"); String *type_str = SwigType_str(type, 0); if (Getattr(n, "unnamedinstance")) { // If this is an anonymous enum, we can declare the variable as int even though we can't reference this type. if (Strncmp(type_str, "enum $", 6) != 0) { // Otherwise we're out of luck, with the current approach of exposing the variables directly we simply can't do it, we would need to use accessor // functions instead to support this. Swig_error(Getfile(n), Getline(n), "Variables of anonymous non-enum types are not supported.\n"); return SWIG_ERROR; } const char * const unnamed_end = strchr(Char(type_str) + 6, '$'); if (!unnamed_end) { Swig_error(Getfile(n), Getline(n), "Unsupported anonymous enum type \"%s\".\n", type_str); return SWIG_ERROR; } String* const int_type_str = NewStringf("int%s", unnamed_end + 1); Delete(type_str); type_str = int_type_str; } else { scoped_dohptr btype(SwigType_base(type)); if (SwigType_isenum(btype)) { // Enums are special as they can be unknown, i.e. not wrapped by SWIG. In this case we just use int instead. if (!enumLookup(btype)) { Replaceall(type_str, btype, "int"); } } else { // Don't bother with checking if type is representable in C if we're wrapping C and not C++ anyhow: of course it is. if (CPlusPlus) { if (SwigType_isreference(type)) return NIL; if (!SwigType_isbuiltin(btype)) return NIL; // Final complication: define bool if it is used here. if (Cmp(btype, "bool") == 0) { Printv(f_wrappers_types, "#include \n\n", NIL); } } } } String* const var_decl = NewStringEmpty(); if (SwigType_isarray(type)) { String *dims = Strchr(type_str, '['); char *c = Char(type_str); c[Len(type_str) - Len(dims) - 1] = '\0'; Printv(var_decl, c, " ", name, "[]", NIL); } else { Printv(var_decl, type_str, " ", name, NIL); } Delete(type_str); return var_decl; } /* --------------------------------------------------------------------- * emit_c_struct_def() * * Append the declarations of C struct members to the given string. * Notice that this function has a side effect of outputting all enum declarations inside the struct into f_wrappers_types directly. * This is done to avoid gcc warnings "declaration does not declare anything" given for the anonymous enums inside the structs. * --------------------------------------------------------------------- */ void emit_c_struct_def(String* out, Node *n) { for ( Node* node = firstChild(n); node; node = nextSibling(node)) { String* const ntype = nodeType(node); if (Cmp(ntype, "cdecl") == 0) { SwigType* t = NewString(Getattr(node, "type")); SwigType_push(t, Getattr(node, "decl")); t = SwigType_typedef_resolve_all(t); if (SwigType_isfunction(t)) { Swig_warning(WARN_C_UNSUPPORTTED, input_file, line_number, "Extending C struct with %s is not currently supported, ignored.\n", SwigType_str(t, 0)); } else { String* const var_decl = make_c_var_decl(node); Printv(out, cindent, var_decl, ";\n", NIL); Delete(var_decl); } } else if (Cmp(ntype, "enum") == 0) { // This goes directly into f_wrappers_types, before this struct declaration. emit_one(node); } else { // WARNING: proxy declaration can be different than original code if (Cmp(nodeType(node), "extend") == 0) emit_c_struct_def(out, node); } } } /* --------------------------------------------------------------------- * classHandler() * --------------------------------------------------------------------- */ virtual int classHandler(Node *n) { String *name = getProxyName(n); if (CPlusPlus) { // inheritance support: attach all members from base classes to this class if (List *baselist = Getattr(n, "bases")) { Iterator i; for (i = First(baselist); i.item; i = Next(i)) { // look for member variables and functions Node *node; for (node = firstChild(i.item); node; node = nextSibling(node)) { if ((Cmp(Getattr(node, "kind"), "variable") == 0) || (Cmp(Getattr(node, "kind"), "function") == 0)) { if ((Cmp(Getattr(node, "access"), "public") == 0) && (Cmp(Getattr(node, "storage"), "static") != 0)) { // Assignment operators are not inherited in C++ and symbols without sym:name should be ignored, not copied into the derived class. if (Getattr(node, "sym:name") && Cmp(Getattr(node, "name"), "operator =") != 0) { String *parent_name = Getattr(parentNode(node), "name"); Hash *dupl_name_node = is_in(Getattr(node, "name"), n); // if there's a duplicate inherited name, due to the C++ multiple // inheritance, change both names to avoid ambiguity if (dupl_name_node) { String *cif = Getattr(dupl_name_node, "c:inherited_from"); String *old_name = Getattr(dupl_name_node, "sym:name"); if (cif && parent_name && (Cmp(cif, parent_name) != 0)) { Setattr(dupl_name_node, "sym:name", NewStringf("%s%s", cif ? cif : "", old_name)); Setattr(dupl_name_node, "c:base_name", old_name); Node *new_node = copy_node(node); Setattr(new_node, "name", NewStringf("%s%s", parent_name, old_name)); Setattr(new_node, "c:base_name", old_name); appendChild(n, new_node); } } else { appendChild(n, copy_node(node)); } } } } } } } // declare type for specific class in the proxy header Printv(f_wrappers_types, "typedef struct SwigObj_", name, " ", name, ";\n\n", NIL); Delete(name); return Language::classHandler(n); } else { // this is C struct, just declare it in the proxy String* struct_def = NewStringEmpty(); String* const tdname = Getattr(n, "tdname"); if (tdname) Append(struct_def, "typedef struct {\n"); else Printv(struct_def, "struct ", name, " {\n", NIL); emit_c_struct_def(struct_def, n); if (tdname) Printv(struct_def, "} ", tdname, ";\n\n", NIL); else Append(struct_def, "};\n\n"); Printv(f_wrappers_types, struct_def, NIL); Delete(struct_def); Delete(name); } return SWIG_OK; } /* --------------------------------------------------------------------- * staticmembervariableHandler() * --------------------------------------------------------------------- */ virtual int staticmembervariableHandler(Node *n) { SwigType *type = Getattr(n, "type"); SwigType *tdtype = SwigType_typedef_resolve_all(type); if (tdtype) { type = tdtype; Setattr(n, "type", type); } SwigType *btype = SwigType_base(type); if (SwigType_isarray(type) && !SwigType_isbuiltin(btype)) { // this hack applies to member objects array (not ptrs.) SwigType_add_pointer(btype); SwigType_add_array(btype, NewStringf("%s", SwigType_array_getdim(type, 0))); Setattr(n, "type", btype); } Delete(type); Delete(btype); return Language::staticmembervariableHandler(n); } /* --------------------------------------------------------------------- * membervariableHandler() * --------------------------------------------------------------------- */ virtual int membervariableHandler(Node *n) { SwigType *type = Getattr(n, "type"); SwigType *tdtype = SwigType_typedef_resolve_all(type); if (tdtype) { type = tdtype; Setattr(n, "type", type); } SwigType *btype = SwigType_base(type); if (SwigType_isarray(type) && !SwigType_isbuiltin(btype)) { // this hack applies to member objects array (not ptrs.) SwigType_add_pointer(btype); SwigType_add_array(btype, NewStringf("%s", SwigType_array_getdim(type, 0))); Setattr(n, "type", btype); } Delete(type); Delete(btype); return Language::membervariableHandler(n); } /* --------------------------------------------------------------------- * constructorHandler() * --------------------------------------------------------------------- */ virtual int constructorHandler(Node *n) { // For some reason, the base class implementation of constructorDeclaration() only takes care of the copy ctor automatically for the languages not // supporting overloading (i.e. not calling allow_overloading(), as we do). So duplicate the relevant part of its code here, if (!Abstract && Getattr(n, "copy_constructor")) { return Language::copyconstructorHandler(n); } if (GetFlag(n, "feature:extend")) { // Pretend that all ctors added via %extend are overloaded to avoid clash between the functions created for them and the actual exported function, that // could have the same "Foo_new" name otherwise. SetFlag(n, "sym:overloaded"); } return Language::constructorHandler(n); } /* ---------------------------------------------------------------------- * Language::enumforwardDeclaration() * ---------------------------------------------------------------------- */ virtual int enumforwardDeclaration(Node *n) { // Base implementation of this function calls enumDeclaration() for "missing" enums, i.e. those without any definition at all. This results in invalid (at // least in C++) enum declarations in the output, so simply don't do this here. (void) n; return SWIG_OK; } /* --------------------------------------------------------------------- * enumDeclaration() * --------------------------------------------------------------------- */ virtual int enumDeclaration(Node *n) { if (ImportMode) return SWIG_OK; if (getCurrentClass() && (cplus_mode != PUBLIC)) return SWIG_NOWRAP; // We don't know here if we're going to have any non-ignored enum elements, so generate enum declaration in a temporary string. enum_decl = NewStringEmpty(); // Preserve the typedef if we have it in the input. maybe_owned_dohptr tdname; tdname.assign_non_owned(Getattr(n, "tdname")); if (tdname) { Printv(enum_decl, "typedef ", NIL); } Printv(enum_decl, "enum", NIL); if (Node* const klass = getCurrentClass()) { enum_prefix = getProxyName(klass); } else { enum_prefix = ns_prefix; // Possibly NULL, but that's fine. } if (tdname && enum_prefix) { tdname.assign_owned(NewStringf("%s_%s", enum_prefix, tdname.get())); } scoped_dohptr enumname; // Unnamed enums may just have no name at all or have a synthesized invalid name of the form "$unnamedN$ which is indicated by "unnamed" attribute. // // Also note that we use "name" here and not "sym:name" because the latter is the name of typedef if there is one, while we want to use the name of enum // itself here and, even more importantly, use the enum, and not the typedef, name as prefix for its elements. if (String* const name = Getattr(n, "unnamed") ? NIL : Getattr(n, "name")) { // But the name may included the containing class, so get rid of it. enumname = Swig_scopename_last(name); if (enum_prefix) { enumname = NewStringf("%s_%s", enum_prefix, enumname.get()); } Printv(enum_decl, " ", enumname.get(), NIL); // For scoped enums, their name should be prefixed to their elements in addition to any other prefix we use. if (Getattr(n, "scopedenum")) { enum_prefix = enumname.get(); } } Printv(enum_decl, " {\n", NIL); int const len_orig = Len(enum_decl); // Emit each enum item. Language::enumDeclaration(n); // Only emit the enum declaration if there were actually any items. if (Len(enum_decl) > len_orig) { Printv(enum_decl, "\n}", NIL); if (tdname) { Printv(enum_decl, " ", tdname.get(), NIL); } Printv(enum_decl, ";\n\n", NIL); Append(f_wrappers_types, enum_decl); } enum_prefix = NULL; Delete(enum_decl); return SWIG_OK; } /* --------------------------------------------------------------------- * enumvalueDeclaration() * --------------------------------------------------------------------- */ virtual int enumvalueDeclaration(Node *n) { if (Cmp(Getattr(n, "ismember"), "1") == 0 && Cmp(Getattr(n, "access"), "public") != 0) return SWIG_NOWRAP; Swig_require("enumvalueDeclaration", n, "?enumvalueex", "?enumvalue", NIL); if (!GetFlag(n, "firstenumitem")) Printv(enum_decl, ",\n", NIL); maybe_owned_dohptr wname; String* const symname = Getattr(n, "sym:name"); if (enum_prefix) { wname.assign_owned(NewStringf("%s_%s", enum_prefix, symname)); } else { wname.assign_non_owned(symname); } Printv(enum_decl, cindent, wname.get(), NIL); // We only use "enumvalue", which comes from the input, and not "enumvalueex" synthesized by SWIG itself because C should use the correct value for the enum // items without an explicit one anyhow (and "enumvalueex" can't be always used as is in C code for enum elements inside a class or even a namespace). String *value = Getattr(n, "enumvalue"); if (value) { // We can't always use the raw value, check its type to see if we need to transform it. maybe_owned_dohptr cvalue; switch (SwigType_type(Getattr(n, "type"))) { case T_BOOL: // Boolean constants can't appear in C code, so replace them with their values in the simplest possible case. This is not exhaustive, of course, // but better than nothing and doing the right thing is not simple at all as we'd need to really parse the expression, just textual substitution wouldn't // be enough (consider e.g. an enum element called "very_true" and another one using it as its value). if (Cmp(value, "true") == 0) { cvalue.assign_owned(NewString("1")); } else if (Cmp(value, "false") == 0) { cvalue.assign_owned(NewString("0")); } else { Swig_error(Getfile(n), Getline(n), "Unsupported boolean enum value \"%s\".\n", value); } break; case T_CHAR: // SWIG parser doesn't put single quotes around char values, for some reason, so add them here. cvalue.assign_owned(NewStringf("'%(escape)s'", value)); break; default: cvalue.assign_non_owned(value); } Printv(enum_decl, " = ", cvalue.get(), NIL); } Swig_restore(n); return SWIG_OK; } /* --------------------------------------------------------------------- * constantWrapper() * --------------------------------------------------------------------- */ virtual int constantWrapper(Node *n) { String *name = Getattr(n, "sym:name"); // If it's a #define or a %constant, use raw value and hope that it will work in C as well as in C++. This is not ideal, but using "value" is even worse, as // it doesn't even work for simple char constants such as "#define MY_X 'x'", that would end up unquoted in the generated code. String *value = Getattr(n, "rawval"); if (!value) { // Check if it's not a static member variable because its "value" is a reference to a C++ variable and won't translate to C correctly. // // Arguably, those should be handled in overridden memberconstantHandler() and not here. value = Getattr(n, "staticmembervariableHandler:value"); if (value && Equal(Getattr(n, "valuetype"), "char")) { // We need to quote this value. const unsigned char c = *Char(value); Clear(value); if (isalnum(c)) { Printf(value, "'%c'", c); } else { Printf(value, "'\\x%x%x'", c / 0x10, c % 0x10); } } } if (!value) { // Fall back on whatever SWIG parsed the value as for all the rest. value = Getattr(n, "value"); } Printv(f_wrappers_decl, "#define ", name, " ", value, "\n", NIL); return SWIG_OK; } }; /* class C */ /* ----------------------------------------------------------------------------- * swig_c() - Instantiate module * ----------------------------------------------------------------------------- */ static Language *new_swig_c() { return new C(); } extern "C" Language *swig_c(void) { return new_swig_c(); } /* ----------------------------------------------------------------------------- * Static member variables * ----------------------------------------------------------------------------- */ const char *C::usage = (char *) "\ C Options (available with -c)\n\ -namespace ns - use prefix based on the provided namespace\n\ -noexcept - do not generate exception handling code\n\ \n";