summaryrefslogtreecommitdiffstats
path: root/contrib/tools/swig/Source/Modules
diff options
context:
space:
mode:
authorsay <[email protected]>2023-02-14 17:24:43 +0300
committersay <[email protected]>2023-02-14 17:24:43 +0300
commite0094c4ad6964e11564777bc0d859c68d8aa9de2 (patch)
tree5d2ad1a4df88da1f74385888891a2a5f9fbbc3ef /contrib/tools/swig/Source/Modules
parent65a08c9fdece8dba50da8beb4d7c81447211dd45 (diff)
Migrate black linter on custom_lint pipeline
Diffstat (limited to 'contrib/tools/swig/Source/Modules')
-rw-r--r--contrib/tools/swig/Source/Modules/README9
-rw-r--r--contrib/tools/swig/Source/Modules/allocate.cxx965
-rw-r--r--contrib/tools/swig/Source/Modules/browser.cxx421
-rw-r--r--contrib/tools/swig/Source/Modules/contract.cxx358
-rw-r--r--contrib/tools/swig/Source/Modules/csharp.cxx4598
-rw-r--r--contrib/tools/swig/Source/Modules/d.cxx4647
-rw-r--r--contrib/tools/swig/Source/Modules/directors.cxx241
-rw-r--r--contrib/tools/swig/Source/Modules/emit.cxx559
-rw-r--r--contrib/tools/swig/Source/Modules/go.cxx7010
-rw-r--r--contrib/tools/swig/Source/Modules/guile.cxx1683
-rw-r--r--contrib/tools/swig/Source/Modules/interface.cxx185
-rw-r--r--contrib/tools/swig/Source/Modules/java.cxx5002
-rw-r--r--contrib/tools/swig/Source/Modules/javascript.cxx2489
-rw-r--r--contrib/tools/swig/Source/Modules/lang.cxx3895
-rw-r--r--contrib/tools/swig/Source/Modules/lua.cxx2282
-rw-r--r--contrib/tools/swig/Source/Modules/main.cxx1416
-rw-r--r--contrib/tools/swig/Source/Modules/mzscheme.cxx819
-rw-r--r--contrib/tools/swig/Source/Modules/nested.cxx453
-rw-r--r--contrib/tools/swig/Source/Modules/ocaml.cxx1889
-rw-r--r--contrib/tools/swig/Source/Modules/octave.cxx1590
-rw-r--r--contrib/tools/swig/Source/Modules/overload.cxx866
-rw-r--r--contrib/tools/swig/Source/Modules/perl5.cxx2528
-rw-r--r--contrib/tools/swig/Source/Modules/php.cxx2876
-rw-r--r--contrib/tools/swig/Source/Modules/python.cxx5718
-rw-r--r--contrib/tools/swig/Source/Modules/r.cxx2897
-rw-r--r--contrib/tools/swig/Source/Modules/ruby.cxx3511
-rw-r--r--contrib/tools/swig/Source/Modules/scilab.cxx1156
-rw-r--r--contrib/tools/swig/Source/Modules/swigmain.cxx275
-rw-r--r--contrib/tools/swig/Source/Modules/swigmod.h462
-rw-r--r--contrib/tools/swig/Source/Modules/tcl8.cxx1310
-rw-r--r--contrib/tools/swig/Source/Modules/typepass.cxx1303
-rw-r--r--contrib/tools/swig/Source/Modules/utils.cxx218
-rw-r--r--contrib/tools/swig/Source/Modules/xml.cxx326
33 files changed, 63957 insertions, 0 deletions
diff --git a/contrib/tools/swig/Source/Modules/README b/contrib/tools/swig/Source/Modules/README
new file mode 100644
index 00000000000..058779d227d
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/README
@@ -0,0 +1,9 @@
+06/25/2002
+
+This directory contains all of the SWIG language modules. Many of these
+modules contain code that dates back to SWIG1.0. The module API has changed
+a lot in the development releases so this is fairly messy. We're working on
+cleaning it up, but you'll have to bear with us until it's done.
+
+-- Dave
+
diff --git a/contrib/tools/swig/Source/Modules/allocate.cxx b/contrib/tools/swig/Source/Modules/allocate.cxx
new file mode 100644
index 00000000000..23683c38596
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/allocate.cxx
@@ -0,0 +1,965 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * allocate.cxx
+ *
+ * This module tries to figure out which classes and structures support
+ * default constructors and destructors in C++. There are several rules that
+ * define this behavior including pure abstract methods, private sections,
+ * and non-default constructors in base classes. See the ARM or
+ * Doc/Manual/SWIGPlus.html for details.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+
+static int virtual_elimination_mode = 0; /* set to 0 on default */
+
+/* Set virtual_elimination_mode */
+void Wrapper_virtual_elimination_mode_set(int flag) {
+ virtual_elimination_mode = flag;
+}
+
+/* Helper function to assist with abstract class checking.
+ This is a major hack. Sorry. */
+
+extern "C" {
+ static String *search_decl = 0; /* Declarator being searched */
+ static int check_implemented(Node *n) {
+ String *decl;
+ if (!n)
+ return 0;
+ while (n) {
+ if (Strcmp(nodeType(n), "cdecl") == 0) {
+ decl = Getattr(n, "decl");
+ if (SwigType_isfunction(decl)) {
+ SwigType *decl1 = SwigType_typedef_resolve_all(decl);
+ SwigType *decl2 = SwigType_pop_function(decl1);
+ if (Strcmp(decl2, search_decl) == 0) {
+ if (!GetFlag(n, "abstract")) {
+ Delete(decl1);
+ Delete(decl2);
+ return 1;
+ }
+ }
+ Delete(decl1);
+ Delete(decl2);
+ }
+ }
+ n = Getattr(n, "csym:nextSibling");
+ }
+ return 0;
+ }
+}
+
+class Allocate:public Dispatcher {
+ Node *inclass;
+ int extendmode;
+
+ /* Checks if a function, n, is the same as any in the base class, ie if the method is polymorphic.
+ * Also checks for methods which will be hidden (ie a base has an identical non-virtual method).
+ * Both methods must have public access for a match to occur. */
+ int function_is_defined_in_bases(Node *n, Node *bases) {
+
+ if (!bases)
+ return 0;
+
+ String *this_decl = Getattr(n, "decl");
+ if (!this_decl)
+ return 0;
+
+ String *name = Getattr(n, "name");
+ String *this_type = Getattr(n, "type");
+ String *resolved_decl = SwigType_typedef_resolve_all(this_decl);
+
+ // Search all base classes for methods with same signature
+ for (int i = 0; i < Len(bases); i++) {
+ Node *b = Getitem(bases, i);
+ Node *base = firstChild(b);
+ while (base) {
+ if (Strcmp(nodeType(base), "extend") == 0) {
+ // Loop through all the %extend methods
+ Node *extend = firstChild(base);
+ while (extend) {
+ if (function_is_defined_in_bases_seek(n, b, extend, this_decl, name, this_type, resolved_decl)) {
+ Delete(resolved_decl);
+ return 1;
+ }
+ extend = nextSibling(extend);
+ }
+ } else if (Strcmp(nodeType(base), "using") == 0) {
+ // Loop through all the using declaration methods
+ Node *usingdecl = firstChild(base);
+ while (usingdecl) {
+ if (function_is_defined_in_bases_seek(n, b, usingdecl, this_decl, name, this_type, resolved_decl)) {
+ Delete(resolved_decl);
+ return 1;
+ }
+ usingdecl = nextSibling(usingdecl);
+ }
+ } else {
+ // normal methods
+ if (function_is_defined_in_bases_seek(n, b, base, this_decl, name, this_type, resolved_decl)) {
+ Delete(resolved_decl);
+ return 1;
+ }
+ }
+ base = nextSibling(base);
+ }
+ }
+ Delete(resolved_decl);
+ resolved_decl = 0;
+ for (int j = 0; j < Len(bases); j++) {
+ Node *b = Getitem(bases, j);
+ if (function_is_defined_in_bases(n, Getattr(b, "allbases")))
+ return 1;
+ }
+ return 0;
+ }
+
+ /* Helper function for function_is_defined_in_bases */
+ int function_is_defined_in_bases_seek(Node *n, Node *b, Node *base, String *this_decl, String *name, String *this_type, String *resolved_decl) {
+
+ String *base_decl = Getattr(base, "decl");
+ SwigType *base_type = Getattr(base, "type");
+ if (base_decl && base_type) {
+ if (checkAttribute(base, "name", name) && !GetFlag(b, "feature:ignore") /* whole class is ignored */ ) {
+ if (SwigType_isfunction(resolved_decl) && SwigType_isfunction(base_decl)) {
+ // We have found a method that has the same name as one in a base class
+ bool covariant_returntype = false;
+ bool returntype_match = Strcmp(base_type, this_type) == 0 ? true : false;
+ bool decl_match = Strcmp(base_decl, this_decl) == 0 ? true : false;
+ if (returntype_match && decl_match) {
+ // Exact match - we have found a method with identical signature
+ // No typedef resolution was done, but skipping it speeds things up slightly
+ } else {
+ // Either we have:
+ // 1) matching methods but are one of them uses a different typedef (return type or parameter) to the one in base class' method
+ // 2) matching polymorphic methods with covariant return type
+ // 3) a non-matching method (ie an overloaded method of some sort)
+ // 4) a matching method which is not polymorphic, ie it hides the base class' method
+
+ // Check if fully resolved return types match (including
+ // covariant return types)
+ if (!returntype_match) {
+ String *this_returntype = function_return_type(n);
+ String *base_returntype = function_return_type(base);
+ returntype_match = Strcmp(this_returntype, base_returntype) == 0 ? true : false;
+ if (!returntype_match) {
+ covariant_returntype = SwigType_issubtype(this_returntype, base_returntype) ? true : false;
+ returntype_match = covariant_returntype;
+ }
+ Delete(this_returntype);
+ Delete(base_returntype);
+ }
+ // The return types must match at this point, for the whole method to match
+ if (returntype_match && !decl_match) {
+ // Now need to check the parameter list
+ // First do an inexpensive parameter count
+ ParmList *this_parms = Getattr(n, "parms");
+ ParmList *base_parms = Getattr(base, "parms");
+ if (ParmList_len(this_parms) == ParmList_len(base_parms)) {
+ // Number of parameters are the same, now check that all the parameters match
+ SwigType *base_fn = NewString("");
+ SwigType *this_fn = NewString("");
+ SwigType_add_function(base_fn, base_parms);
+ SwigType_add_function(this_fn, this_parms);
+ base_fn = SwigType_typedef_resolve_all(base_fn);
+ this_fn = SwigType_typedef_resolve_all(this_fn);
+ if (Strcmp(base_fn, this_fn) == 0) {
+ // Finally check that the qualifiers match
+ int base_qualifier = SwigType_isqualifier(resolved_decl);
+ int this_qualifier = SwigType_isqualifier(base_decl);
+ if (base_qualifier == this_qualifier) {
+ decl_match = true;
+ }
+ }
+ Delete(base_fn);
+ Delete(this_fn);
+ }
+ }
+ }
+ //Printf(stderr,"look %s %s %d %d\n",base_decl, this_decl, returntype_match, decl_match);
+
+ if (decl_match && returntype_match) {
+ // Found an identical method in the base class
+ bool this_wrapping_protected_members = is_member_director(n) ? true : false; // This should really check for dirprot rather than just being a director method
+ bool base_wrapping_protected_members = is_member_director(base) ? true : false; // This should really check for dirprot rather than just being a director method
+ bool both_have_public_access = is_public(n) && is_public(base);
+ bool both_have_protected_access = (is_protected(n) && this_wrapping_protected_members) && (is_protected(base) && base_wrapping_protected_members);
+ bool both_have_private_access = is_private(n) && is_private(base);
+ if (checkAttribute(base, "storage", "virtual")) {
+ // Found a polymorphic method.
+ // Mark the polymorphic method, in case the virtual keyword was not used.
+ Setattr(n, "storage", "virtual");
+ if (!Getattr(b, "feature:interface")) { // interface implementation neither hides nor overrides
+ if (both_have_public_access || both_have_protected_access) {
+ if (!is_non_public_base(inclass, b))
+ Setattr(n, "override", base); // Note C# definition of override, ie access must be the same
+ }
+ else if (!both_have_private_access) {
+ // Different access
+ if (this_wrapping_protected_members || base_wrapping_protected_members)
+ if (!is_non_public_base(inclass, b))
+ Setattr(n, "hides", base); // Note C# definition of hiding, ie hidden if access is different
+ }
+ }
+ // Try and find the most base's covariant return type
+ SwigType *most_base_covariant_type = Getattr(base, "covariant");
+ if (!most_base_covariant_type && covariant_returntype)
+ most_base_covariant_type = function_return_type(base, false);
+
+ if (!most_base_covariant_type) {
+ // Eliminate the derived virtual method.
+ if (virtual_elimination_mode && !is_member_director(n))
+ if (both_have_public_access)
+ if (!is_non_public_base(inclass, b))
+ if (!Swig_symbol_isoverloaded(n)) {
+ // Don't eliminate if an overloaded method as this hides the method
+ // in the scripting languages: the dispatch function will hide the base method if ignored.
+ SetFlag(n, "feature:ignore");
+ }
+ } else {
+ // Some languages need to know about covariant return types
+ Setattr(n, "covariant", most_base_covariant_type);
+ }
+
+ } else {
+ // Found an identical method in the base class, but it is not polymorphic.
+ if (both_have_public_access || both_have_protected_access)
+ if (!is_non_public_base(inclass, b))
+ Setattr(n, "hides", base);
+ }
+ if (both_have_public_access || both_have_protected_access)
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ /* Determines whether the base class, b, is in the list of private
+ * or protected base classes for class n. */
+ bool is_non_public_base(Node *n, Node *b) {
+ bool non_public_base = false;
+ Node *bases = Getattr(n, "privatebases");
+ if (bases) {
+ for (int i = 0; i < Len(bases); i++) {
+ Node *base = Getitem(bases, i);
+ if (base == b)
+ non_public_base = true;
+ }
+ }
+ bases = Getattr(n, "protectedbases");
+ if (bases) {
+ for (int i = 0; i < Len(bases); i++) {
+ Node *base = Getitem(bases, i);
+ if (base == b)
+ non_public_base = true;
+ }
+ }
+ return non_public_base;
+ }
+
+ /* Returns the return type for a function. The node n should be a function.
+ If resolve is true the fully returned type is fully resolved.
+ Caller is responsible for deleting returned string. */
+ String *function_return_type(Node *n, bool resolve = true) {
+ String *decl = Getattr(n, "decl");
+ SwigType *type = Getattr(n, "type");
+ String *ty = NewString(type);
+ SwigType_push(ty, decl);
+ if (SwigType_isqualifier(ty))
+ Delete(SwigType_pop(ty));
+ Delete(SwigType_pop_function(ty));
+ if (resolve) {
+ String *unresolved = ty;
+ ty = SwigType_typedef_resolve_all(unresolved);
+ Delete(unresolved);
+ }
+ return ty;
+ }
+
+ /* Checks if a class member is the same as inherited from the class bases */
+ int class_member_is_defined_in_bases(Node *member, Node *classnode) {
+ Node *bases; /* bases is the closest ancestors of classnode */
+ int defined = 0;
+
+ bases = Getattr(classnode, "allbases");
+ if (!bases)
+ return 0;
+
+ {
+ int old_mode = virtual_elimination_mode;
+ if (is_member_director(classnode, member))
+ virtual_elimination_mode = 0;
+
+ if (function_is_defined_in_bases(member, bases)) {
+ defined = 1;
+ }
+
+ virtual_elimination_mode = old_mode;
+ }
+
+ if (defined)
+ return 1;
+ else
+ return 0;
+ }
+
+ /* Checks to see if a class is abstract through inheritance,
+ and saves the first node that seems to be abstract.
+ */
+ int is_abstract_inherit(Node *n, Node *base = 0, int first = 0) {
+ if (!first && (base == n))
+ return 0;
+ if (!base) {
+ /* Root node */
+ Symtab *stab = Getattr(n, "symtab"); /* Get symbol table for node */
+ Symtab *oldtab = Swig_symbol_setscope(stab);
+ int ret = is_abstract_inherit(n, n, 1);
+ Swig_symbol_setscope(oldtab);
+ return ret;
+ }
+ List *abstracts = Getattr(base, "abstracts");
+ if (abstracts) {
+ int dabstract = 0;
+ int len = Len(abstracts);
+ for (int i = 0; i < len; i++) {
+ Node *nn = Getitem(abstracts, i);
+ String *name = Getattr(nn, "name");
+ if (!name)
+ continue;
+ if (Strchr(name, '~'))
+ continue; /* Don't care about destructors */
+ String *base_decl = Getattr(nn, "decl");
+ if (base_decl)
+ base_decl = SwigType_typedef_resolve_all(base_decl);
+ if (SwigType_isfunction(base_decl))
+ search_decl = SwigType_pop_function(base_decl);
+ Node *dn = Swig_symbol_clookup_local_check(name, 0, check_implemented);
+ Delete(search_decl);
+ Delete(base_decl);
+
+ if (!dn) {
+ List *nabstracts = Getattr(n, "abstracts");
+ if (!nabstracts) {
+ nabstracts = NewList();
+ Setattr(n, "abstracts", nabstracts);
+ Delete(nabstracts);
+ }
+ Append(nabstracts, nn);
+ if (!Getattr(n, "abstracts:firstnode")) {
+ Setattr(n, "abstracts:firstnode", nn);
+ }
+ dabstract = base != n;
+ }
+ }
+ if (dabstract)
+ return 1;
+ }
+ List *bases = Getattr(base, "allbases");
+ if (!bases)
+ return 0;
+ for (int i = 0; i < Len(bases); i++) {
+ if (is_abstract_inherit(n, Getitem(bases, i))) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+
+ /* Grab methods used by smart pointers */
+
+ List *smart_pointer_methods(Node *cls, List *methods, int isconst, String *classname = 0) {
+ if (!methods) {
+ methods = NewList();
+ }
+
+ Node *c = firstChild(cls);
+
+ while (c) {
+ if (Getattr(c, "error") || GetFlag(c, "feature:ignore")) {
+ c = nextSibling(c);
+ continue;
+ }
+ if (!isconst && (Strcmp(nodeType(c), "extend") == 0)) {
+ methods = smart_pointer_methods(c, methods, isconst, Getattr(cls, "name"));
+ } else if (Strcmp(nodeType(c), "cdecl") == 0) {
+ if (!GetFlag(c, "feature:ignore")) {
+ String *storage = Getattr(c, "storage");
+ if (!((Cmp(storage, "typedef") == 0))
+ && !((Cmp(storage, "friend") == 0))) {
+ String *name = Getattr(c, "name");
+ String *symname = Getattr(c, "sym:name");
+ Node *e = Swig_symbol_clookup_local(name, 0);
+ if (e && is_public(e) && !GetFlag(e, "feature:ignore") && (Cmp(symname, Getattr(e, "sym:name")) == 0)) {
+ Swig_warning(WARN_LANG_DEREF_SHADOW, Getfile(e), Getline(e), "Declaration of '%s' shadows declaration accessible via operator->(),\n", name);
+ Swig_warning(WARN_LANG_DEREF_SHADOW, Getfile(c), Getline(c), "previous declaration of '%s'.\n", name);
+ } else {
+ /* Make sure node with same name doesn't already exist */
+ int k;
+ int match = 0;
+ for (k = 0; k < Len(methods); k++) {
+ e = Getitem(methods, k);
+ if (Cmp(symname, Getattr(e, "sym:name")) == 0) {
+ match = 1;
+ break;
+ }
+ if (!Getattr(e, "sym:name") && (Cmp(name, Getattr(e, "name")) == 0)) {
+ match = 1;
+ break;
+ }
+ }
+ if (!match) {
+ Node *cc = c;
+ while (cc) {
+ Node *cp = cc;
+ if (classname) {
+ Setattr(cp, "extendsmartclassname", classname);
+ }
+ Setattr(cp, "allocate:smartpointeraccess", "1");
+ /* If constant, we have to be careful */
+ if (isconst) {
+ SwigType *decl = Getattr(cp, "decl");
+ if (decl) {
+ if (SwigType_isfunction(decl)) { /* If method, we only add if it's a const method */
+ if (SwigType_isconst(decl)) {
+ Append(methods, cp);
+ }
+ } else {
+ Append(methods, cp);
+ }
+ } else {
+ Append(methods, cp);
+ }
+ } else {
+ Append(methods, cp);
+ }
+ cc = Getattr(cc, "sym:nextSibling");
+ }
+ }
+ }
+ }
+ }
+ }
+
+ c = nextSibling(c);
+ }
+ /* Look for methods in base classes */
+ {
+ Node *bases = Getattr(cls, "bases");
+ int k;
+ for (k = 0; k < Len(bases); k++) {
+ smart_pointer_methods(Getitem(bases, k), methods, isconst);
+ }
+ }
+ /* Remove protected/private members */
+ {
+ for (int i = 0; i < Len(methods);) {
+ Node *n = Getitem(methods, i);
+ if (!is_public(n)) {
+ Delitem(methods, i);
+ continue;
+ }
+ i++;
+ }
+ }
+ return methods;
+ }
+
+ void mark_exception_classes(ParmList *p) {
+ while (p) {
+ SwigType *ty = Getattr(p, "type");
+ SwigType *t = SwigType_typedef_resolve_all(ty);
+ if (SwigType_isreference(t) || SwigType_ispointer(t) || SwigType_isarray(t)) {
+ Delete(SwigType_pop(t));
+ }
+ Node *c = Swig_symbol_clookup(t, 0);
+ if (c) {
+ if (!GetFlag(c, "feature:exceptionclass")) {
+ SetFlag(c, "feature:exceptionclass");
+ }
+ }
+ p = nextSibling(p);
+ Delete(t);
+ }
+ }
+
+
+ void process_exceptions(Node *n) {
+ ParmList *catchlist = 0;
+ /*
+ the "catchlist" attribute is used to emit the block
+
+ try {$action;}
+ catch <list of catches>;
+
+ in emit.cxx
+
+ and is either constructed from the "feature:catches" feature
+ or copied from the node "throws" list.
+ */
+ String *scatchlist = Getattr(n, "feature:catches");
+ if (scatchlist) {
+ catchlist = Swig_cparse_parms(scatchlist, n);
+ if (catchlist) {
+ Setattr(n, "catchlist", catchlist);
+ mark_exception_classes(catchlist);
+ Delete(catchlist);
+ }
+ }
+ ParmList *throws = Getattr(n, "throws");
+ if (throws) {
+ /* if there is no explicit catchlist, we catch everything in the throws list */
+ if (!catchlist) {
+ Setattr(n, "catchlist", throws);
+ }
+ mark_exception_classes(throws);
+ }
+ }
+
+public:
+Allocate():
+ inclass(NULL), extendmode(0) {
+ }
+
+ virtual int top(Node *n) {
+ cplus_mode = PUBLIC;
+ inclass = 0;
+ extendmode = 0;
+ emit_children(n);
+ return SWIG_OK;
+ }
+
+ virtual int importDirective(Node *n) {
+ return emit_children(n);
+ }
+ virtual int includeDirective(Node *n) {
+ return emit_children(n);
+ }
+ virtual int externDeclaration(Node *n) {
+ return emit_children(n);
+ }
+ virtual int namespaceDeclaration(Node *n) {
+ return emit_children(n);
+ }
+ virtual int extendDirective(Node *n) {
+ extendmode = 1;
+ emit_children(n);
+ extendmode = 0;
+ return SWIG_OK;
+ }
+
+ virtual int classDeclaration(Node *n) {
+ Symtab *symtab = Swig_symbol_current();
+ Swig_symbol_setscope(Getattr(n, "symtab"));
+ save_value<Node*> oldInclass(inclass);
+ save_value<AccessMode> oldAcessMode(cplus_mode);
+ save_value<int> oldExtendMode(extendmode);
+ if (Getattr(n, "template"))
+ extendmode = 0;
+ if (!CPlusPlus) {
+ /* Always have default constructors/destructors in C */
+ Setattr(n, "allocate:default_constructor", "1");
+ Setattr(n, "allocate:default_destructor", "1");
+ }
+
+ if (Getattr(n, "allocate:visit"))
+ return SWIG_OK;
+ Setattr(n, "allocate:visit", "1");
+
+ /* Always visit base classes first */
+ {
+ List *bases = Getattr(n, "bases");
+ if (bases) {
+ for (int i = 0; i < Len(bases); i++) {
+ Node *b = Getitem(bases, i);
+ classDeclaration(b);
+ }
+ }
+ }
+ inclass = n;
+ String *kind = Getattr(n, "kind");
+ if (Strcmp(kind, "class") == 0) {
+ cplus_mode = PRIVATE;
+ } else {
+ cplus_mode = PUBLIC;
+ }
+
+ emit_children(n);
+
+ /* Check if the class is abstract via inheritance. This might occur if a class didn't have
+ any pure virtual methods of its own, but it didn't implement all of the pure methods in
+ a base class */
+ if (!Getattr(n, "abstracts") && is_abstract_inherit(n)) {
+ if (((Getattr(n, "allocate:public_constructor") || (!GetFlag(n, "feature:nodefault") && !Getattr(n, "allocate:has_constructor"))))) {
+ if (!GetFlag(n, "feature:notabstract")) {
+ Node *na = Getattr(n, "abstracts:firstnode");
+ if (na) {
+ Swig_warning(WARN_TYPE_ABSTRACT, Getfile(n), Getline(n),
+ "Class '%s' might be abstract, " "no constructors generated,\n", SwigType_namestr(Getattr(n, "name")));
+ Swig_warning(WARN_TYPE_ABSTRACT, Getfile(na), Getline(na), "Method %s might not be implemented.\n", Swig_name_decl(na));
+ if (!Getattr(n, "abstracts")) {
+ List *abstracts = NewList();
+ Append(abstracts, na);
+ Setattr(n, "abstracts", abstracts);
+ Delete(abstracts);
+ }
+ }
+ }
+ }
+ }
+
+ if (!Getattr(n, "allocate:has_constructor")) {
+ /* No constructor is defined. We need to check a few things */
+ /* If class is abstract. No default constructor. Sorry */
+ if (Getattr(n, "abstracts")) {
+ Delattr(n, "allocate:default_constructor");
+ }
+ if (!Getattr(n, "allocate:default_constructor")) {
+ /* Check base classes */
+ List *bases = Getattr(n, "allbases");
+ int allows_default = 1;
+
+ for (int i = 0; i < Len(bases); i++) {
+ Node *n = Getitem(bases, i);
+ /* If base class does not allow default constructor, we don't allow it either */
+ if (!Getattr(n, "allocate:default_constructor") && (!Getattr(n, "allocate:default_base_constructor"))) {
+ allows_default = 0;
+ }
+ }
+ if (allows_default) {
+ Setattr(n, "allocate:default_constructor", "1");
+ }
+ }
+ }
+ if (!Getattr(n, "allocate:has_copy_constructor")) {
+ if (Getattr(n, "abstracts")) {
+ Delattr(n, "allocate:copy_constructor");
+ }
+ if (!Getattr(n, "allocate:copy_constructor")) {
+ /* Check base classes */
+ List *bases = Getattr(n, "allbases");
+ int allows_copy = 1;
+
+ for (int i = 0; i < Len(bases); i++) {
+ Node *n = Getitem(bases, i);
+ /* If base class does not allow copy constructor, we don't allow it either */
+ if (!Getattr(n, "allocate:copy_constructor") && (!Getattr(n, "allocate:copy_base_constructor"))) {
+ allows_copy = 0;
+ }
+ }
+ if (allows_copy) {
+ Setattr(n, "allocate:copy_constructor", "1");
+ }
+ }
+ }
+
+ if (!Getattr(n, "allocate:has_destructor")) {
+ /* No destructor was defined */
+ List *bases = Getattr(n, "allbases");
+ int allows_destruct = 1;
+
+ for (int i = 0; i < Len(bases); i++) {
+ Node *n = Getitem(bases, i);
+ /* If base class does not allow default destructor, we don't allow it either */
+ if (!Getattr(n, "allocate:default_destructor") && (!Getattr(n, "allocate:default_base_destructor"))) {
+ allows_destruct = 0;
+ }
+ }
+ if (allows_destruct) {
+ Setattr(n, "allocate:default_destructor", "1");
+ }
+ }
+
+ if (!Getattr(n, "allocate:has_assign")) {
+ /* No assignment operator was defined */
+ List *bases = Getattr(n, "allbases");
+ int allows_assign = 1;
+
+ for (int i = 0; i < Len(bases); i++) {
+ Node *n = Getitem(bases, i);
+ /* If base class does not allow assignment, we don't allow it either */
+ if (Getattr(n, "allocate:has_assign")) {
+ allows_assign = !Getattr(n, "allocate:noassign");
+ }
+ }
+ if (!allows_assign) {
+ Setattr(n, "allocate:noassign", "1");
+ }
+ }
+
+ if (!Getattr(n, "allocate:has_new")) {
+ /* No new operator was defined */
+ List *bases = Getattr(n, "allbases");
+ int allows_new = 1;
+
+ for (int i = 0; i < Len(bases); i++) {
+ Node *n = Getitem(bases, i);
+ /* If base class does not allow new operator, we don't allow it either */
+ if (Getattr(n, "allocate:has_new")) {
+ allows_new = !Getattr(n, "allocate:nonew");
+ }
+ }
+ if (!allows_new) {
+ Setattr(n, "allocate:nonew", "1");
+ }
+ }
+
+ /* Check if base classes allow smart pointers, but might be hidden */
+ if (!Getattr(n, "allocate:smartpointer")) {
+ Node *sp = Swig_symbol_clookup("operator ->", 0);
+ if (sp) {
+ /* Look for parent */
+ Node *p = parentNode(sp);
+ if (Strcmp(nodeType(p), "extend") == 0) {
+ p = parentNode(p);
+ }
+ if (Strcmp(nodeType(p), "class") == 0) {
+ if (GetFlag(p, "feature:ignore")) {
+ Setattr(n, "allocate:smartpointer", Getattr(p, "allocate:smartpointer"));
+ }
+ }
+ }
+ }
+
+ Swig_interface_propagate_methods(n);
+
+ /* Only care about default behavior. Remove temporary values */
+ Setattr(n, "allocate:visit", "1");
+ Swig_symbol_setscope(symtab);
+ return SWIG_OK;
+ }
+
+ virtual int accessDeclaration(Node *n) {
+ String *kind = Getattr(n, "kind");
+ if (Cmp(kind, "public") == 0) {
+ cplus_mode = PUBLIC;
+ } else if (Cmp(kind, "private") == 0) {
+ cplus_mode = PRIVATE;
+ } else if (Cmp(kind, "protected") == 0) {
+ cplus_mode = PROTECTED;
+ }
+ return SWIG_OK;
+ }
+
+ virtual int usingDeclaration(Node *n) {
+
+ Node *c = 0;
+ for (c = firstChild(n); c; c = nextSibling(c)) {
+ if (Strcmp(nodeType(c), "cdecl") == 0) {
+ process_exceptions(c);
+
+ if (inclass)
+ class_member_is_defined_in_bases(c, inclass);
+ }
+ }
+
+ return SWIG_OK;
+ }
+
+ virtual int cDeclaration(Node *n) {
+
+ process_exceptions(n);
+
+ if (inclass) {
+ /* check whether the member node n is defined in class node in class's bases */
+ class_member_is_defined_in_bases(n, inclass);
+
+ /* Check to see if this is a static member or not. If so, we add an attribute
+ cplus:staticbase that saves the current class */
+
+ if (Swig_storage_isstatic(n)) {
+ Setattr(n, "cplus:staticbase", inclass);
+ }
+
+ String *name = Getattr(n, "name");
+ if (cplus_mode != PUBLIC) {
+ if (Strcmp(name, "operator =") == 0) {
+ /* Look for a private assignment operator */
+ if (!GetFlag(n, "deleted"))
+ Setattr(inclass, "allocate:has_assign", "1");
+ Setattr(inclass, "allocate:noassign", "1");
+ } else if (Strcmp(name, "operator new") == 0) {
+ /* Look for a private new operator */
+ if (!GetFlag(n, "deleted"))
+ Setattr(inclass, "allocate:has_new", "1");
+ Setattr(inclass, "allocate:nonew", "1");
+ }
+ } else {
+ if (Strcmp(name, "operator =") == 0) {
+ if (!GetFlag(n, "deleted"))
+ Setattr(inclass, "allocate:has_assign", "1");
+ else
+ Setattr(inclass, "allocate:noassign", "1");
+ } else if (Strcmp(name, "operator new") == 0) {
+ if (!GetFlag(n, "deleted"))
+ Setattr(inclass, "allocate:has_new", "1");
+ else
+ Setattr(inclass, "allocate:nonew", "1");
+ }
+ /* Look for smart pointer operator */
+ if ((Strcmp(name, "operator ->") == 0) && (!GetFlag(n, "feature:ignore"))) {
+ /* Look for version with no parameters */
+ Node *sn = n;
+ while (sn) {
+ if (!Getattr(sn, "parms")) {
+ SwigType *type = SwigType_typedef_resolve_all(Getattr(sn, "type"));
+ SwigType_push(type, Getattr(sn, "decl"));
+ Delete(SwigType_pop_function(type));
+ SwigType *base = SwigType_base(type);
+ Node *sc = Swig_symbol_clookup(base, 0);
+ if ((sc) && (Strcmp(nodeType(sc), "class") == 0)) {
+ if (SwigType_check_decl(type, "p.")) {
+ /* Need to check if type is a const pointer */
+ int isconst = 0;
+ Delete(SwigType_pop(type));
+ if (SwigType_isconst(type)) {
+ isconst = !Getattr(inclass, "allocate:smartpointermutable");
+ Setattr(inclass, "allocate:smartpointerconst", "1");
+ }
+ else {
+ Setattr(inclass, "allocate:smartpointermutable", "1");
+ }
+ List *methods = smart_pointer_methods(sc, 0, isconst);
+ Setattr(inclass, "allocate:smartpointer", methods);
+ Setattr(inclass, "allocate:smartpointerpointeeclassname", Getattr(sc, "name"));
+ } else {
+ /* Hmmm. The return value is not a pointer. If the type is a value
+ or reference. We're going to chase it to see if another operator->()
+ can be found */
+ if ((SwigType_check_decl(type, "")) || (SwigType_check_decl(type, "r."))) {
+ Node *nn = Swig_symbol_clookup("operator ->", Getattr(sc, "symtab"));
+ if (nn) {
+ Delete(base);
+ Delete(type);
+ sn = nn;
+ continue;
+ }
+ }
+ }
+ }
+ Delete(base);
+ Delete(type);
+ break;
+ }
+ }
+ }
+ }
+ }
+ return SWIG_OK;
+ }
+
+ virtual int constructorDeclaration(Node *n) {
+ if (!inclass)
+ return SWIG_OK;
+ Parm *parms = Getattr(n, "parms");
+
+ process_exceptions(n);
+ if (!extendmode) {
+ if (!ParmList_numrequired(parms)) {
+ /* Class does define a default constructor */
+ /* However, we had better see where it is defined */
+ if (cplus_mode == PUBLIC) {
+ Setattr(inclass, "allocate:default_constructor", "1");
+ } else if (cplus_mode == PROTECTED) {
+ Setattr(inclass, "allocate:default_base_constructor", "1");
+ }
+ }
+ /* Class defines some kind of constructor. May or may not be public */
+ Setattr(inclass, "allocate:has_constructor", "1");
+ if (cplus_mode == PUBLIC) {
+ Setattr(inclass, "allocate:public_constructor", "1");
+ }
+ } else {
+ Setattr(inclass, "allocate:has_constructor", "1");
+ Setattr(inclass, "allocate:public_constructor", "1");
+ }
+
+
+ /* See if this is a copy constructor */
+ if (parms && (ParmList_numrequired(parms) == 1)) {
+ /* Look for a few cases. X(const X &), X(X &), X(X *) */
+ int copy_constructor = 0;
+ SwigType *type = Getattr(inclass, "name");
+ String *tn = NewStringf("r.q(const).%s", type);
+ String *cc = SwigType_typedef_resolve_all(tn);
+ SwigType *rt = SwigType_typedef_resolve_all(Getattr(parms, "type"));
+ if (SwigType_istemplate(type)) {
+ String *tmp = Swig_symbol_template_deftype(cc, 0);
+ Delete(cc);
+ cc = tmp;
+ tmp = Swig_symbol_template_deftype(rt, 0);
+ Delete(rt);
+ rt = tmp;
+ }
+ if (Strcmp(cc, rt) == 0) {
+ copy_constructor = 1;
+ } else {
+ Delete(cc);
+ cc = NewStringf("r.%s", Getattr(inclass, "name"));
+ if (Strcmp(cc, Getattr(parms, "type")) == 0) {
+ copy_constructor = 1;
+ } else {
+ Delete(cc);
+ cc = NewStringf("p.%s", Getattr(inclass, "name"));
+ String *ty = SwigType_strip_qualifiers(Getattr(parms, "type"));
+ if (Strcmp(cc, ty) == 0) {
+ copy_constructor = 1;
+ }
+ Delete(ty);
+ }
+ }
+ Delete(cc);
+ Delete(rt);
+ Delete(tn);
+
+ if (copy_constructor) {
+ Setattr(n, "copy_constructor", "1");
+ Setattr(inclass, "allocate:has_copy_constructor", "1");
+ if (cplus_mode == PUBLIC) {
+ Setattr(inclass, "allocate:copy_constructor", "1");
+ } else if (cplus_mode == PROTECTED) {
+ Setattr(inclass, "allocate:copy_base_constructor", "1");
+ }
+ }
+ }
+ return SWIG_OK;
+ }
+
+ virtual int destructorDeclaration(Node *n) {
+ (void) n;
+ if (!inclass)
+ return SWIG_OK;
+ if (!extendmode) {
+ Setattr(inclass, "allocate:has_destructor", "1");
+ if (cplus_mode == PUBLIC) {
+ Setattr(inclass, "allocate:default_destructor", "1");
+ } else if (cplus_mode == PROTECTED) {
+ Setattr(inclass, "allocate:default_base_destructor", "1");
+ } else if (cplus_mode == PRIVATE) {
+ Setattr(inclass, "allocate:private_destructor", "1");
+ }
+ } else {
+ Setattr(inclass, "allocate:has_destructor", "1");
+ Setattr(inclass, "allocate:default_destructor", "1");
+ }
+ return SWIG_OK;
+ }
+};
+
+void Swig_default_allocators(Node *n) {
+ if (!n)
+ return;
+ Allocate *a = new Allocate;
+ a->top(n);
+ delete a;
+}
diff --git a/contrib/tools/swig/Source/Modules/browser.cxx b/contrib/tools/swig/Source/Modules/browser.cxx
new file mode 100644
index 00000000000..217b40a7ec0
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/browser.cxx
@@ -0,0 +1,421 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * browser.cxx
+ *
+ * A web-base parse tree browser using SWILL. This is an optional
+ * feature that's normally disabled.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+
+#ifdef SWIG_SWILL
+extern "C" {
+#include "swill.h"
+} static FILE *out = 0;
+static Node *view_top = 0;
+
+class Browser:public Dispatcher {
+ void show_checkbox(Node *t, Node *n) {
+ int v = 0;
+ if (Getmeta(n, "visible")) {
+ v = 1;
+ }
+ if (v) {
+ Printf(out, "<a name=\"n%p\"></a>[<a href=\"hide.html?node=%p&hn=%p#n%p\">-</a>] ", n, t, n, n);
+ } else {
+ Printf(out, "<a name=\"n%p\"></a>[<a href=\"show.html?node=%p&hn=%p#n%p\">+</a>] ", n, t, n, n);
+ }
+ }
+ void show_attributes(Node *obj) {
+ if (!Getmeta(obj, "visible"))
+ return;
+ String *os = NewString("");
+ String *k;
+ Iterator ki;
+ ki = First(obj);
+ while (ki.key) {
+ k = ki.key;
+ if ((Cmp(k, "nodeType") == 0) || (Cmp(k, "firstChild") == 0) || (Cmp(k, "lastChild") == 0) ||
+ (Cmp(k, "parentNode") == 0) || (Cmp(k, "nextSibling") == 0) || (Cmp(k, "previousSibling") == 0) || (*(Char(k)) == '$')) {
+ /* Do nothing */
+ } else if (Cmp(k, "parms") == 0) {
+ String *o = NewString("");
+ Printf(o, "%s", ParmList_protostr(Getattr(obj, k)));
+ Replaceall(o, "&", "&amp;");
+ Replaceall(o, "<", "&lt;");
+ Replaceall(o, ">", "&gt;");
+ Printf(os, "<a href=\"data.html?n=%p\">?</a> %-12s - %s\n", Getattr(obj, k), k, o);
+ Delete(o);
+ } else {
+ DOH *o;
+ char *trunc = "";
+ if (DohIsString(Getattr(obj, k))) {
+ o = Str(Getattr(obj, k));
+ if (Len(o) > 70) {
+ trunc = "...";
+ }
+ Replaceall(o, "&", "&amp;");
+ Replaceall(o, "<", "&lt;");
+ Printf(os, "<a href=\"data.html?n=%p\">?</a> %-12s - \"%(escape)-0.70s%s\"\n", Getattr(obj, k), k, o, trunc);
+ Delete(o);
+ } else {
+ Printf(os, "<a href=\"data.html?n=%p\">?</a> %-12s - %p\n", Getattr(obj, k), k, Getattr(obj, k));
+ }
+ }
+ ki = Next(ki);
+ }
+ Printf(out, "<FONT color=\"#660000\"><pre>\n%s</pre></FONT>\n", Char(os));
+ Delete(os);
+ }
+
+public:
+ virtual int emit_one(Node *n) {
+ char *tag = Char(nodeType(n));
+ char *file = Char(Getfile(n));
+ int line = Getline(n);
+ char *name = GetChar(n, "name");
+
+ show_checkbox(view_top, n);
+ Printf(out, "<b><a href=\"index.html?node=%p\">%s</a></b>", n, tag);
+ if (name) {
+ Printf(out, " (%s)", name);
+ }
+ Printf(out, ". %s:%d\n", file, line);
+ Printf(out, "<br>");
+ Dispatcher::emit_one(n);
+ return SWIG_OK;
+ }
+ virtual int emit_children(Node *n) {
+ if (Getmeta(n, "visible")) {
+ Printf(out, "<blockquote>\n");
+ Dispatcher::emit_children(n);
+ Printf(out, "</blockquote>\n");
+ }
+ return SWIG_OK;
+ }
+ virtual int defaultHandler(Node *n) {
+ show_attributes(n);
+ return SWIG_OK;
+ }
+ virtual int top(Node *n) {
+ show_attributes(n);
+ emit_children(n);
+ return SWIG_OK;
+ }
+ virtual int includeDirective(Node *n) {
+ show_attributes(n);
+ emit_children(n);
+ return SWIG_OK;
+ }
+ virtual int importDirective(Node *n) {
+ show_attributes(n);
+ emit_children(n);
+ return SWIG_OK;
+ }
+
+ virtual int extendDirective(Node *n) {
+ show_attributes(n);
+ emit_children(n);
+ return SWIG_OK;
+ }
+ virtual int classDeclaration(Node *n) {
+ show_attributes(n);
+ emit_children(n);
+ return SWIG_OK;
+ }
+
+ virtual int templateDeclaration(Node *n) {
+ show_attributes(n);
+ emit_children(n);
+ return SWIG_OK;
+ }
+
+ virtual int lambdaDeclaration(Node *n) {
+ show_attributes(n);
+ emit_children(n);
+ return SWIG_OK;
+ }
+
+ virtual int enumDeclaration(Node *n) {
+ show_attributes(n);
+ emit_children(n);
+ return SWIG_OK;
+ }
+ virtual int typemapDirective(Node *n) {
+ show_attributes(n);
+ emit_children(n);
+ return SWIG_OK;
+ }
+ virtual int namespaceDeclaration(Node *n) {
+ show_attributes(n);
+ emit_children(n);
+ return SWIG_OK;
+ }
+ virtual int usingDeclaration(Node *n) {
+ show_attributes(n);
+ emit_children(n);
+ return SWIG_OK;
+ }
+
+};
+
+static int browser_exit = 0;
+static Node *tree_top = 0;
+static Browser *browse = 0;
+
+/* ----------------------------------------------------------------------
+ * exit_handler() - Force the browser to exit
+ * ---------------------------------------------------------------------- */
+
+void exit_handler(FILE *f) {
+ browser_exit = 1;
+ Printf(f, "Terminated.\n");
+}
+
+/* ----------------------------------------------------------------------
+ * node_handler() - Generate information about a specific node
+ * ---------------------------------------------------------------------- */
+
+static void display(FILE *f, Node *n) {
+ /* Print standard HTML header */
+
+ Printf(f, "<HTML><HEAD><TITLE>SWIG-%s</TITLE></HEAD><BODY BGCOLOR=\"#ffffff\">\n", Swig_package_version());
+ Printf(f, "<b>SWIG-%s</b><br>\n", Swig_package_version());
+ Printf(f, "[ <a href=\"exit.html\">Exit</a> ]");
+ Printf(f, " [ <a href=\"index.html?node=%p\">Top</a> ]", tree_top);
+ if (n != tree_top) {
+ Printf(f, " [ <a href=\"index.html?node=%p\">Up</a> ]", parentNode(n));
+ }
+ Printf(f, " [ <a href=\"symbol.html\">Symbols</a> ]");
+ Printf(f, "<br><hr><p>\n");
+
+ out = f;
+
+ browse->emit_one(n);
+
+ /* Print standard footer */
+ Printf(f, "<br><hr></BODY></HTML>\n");
+
+}
+
+void node_handler(FILE *f) {
+ Node *n = 0;
+ if (!swill_getargs("p(node)", &n)) {
+ n = tree_top;
+ }
+ view_top = n;
+ display(f, n);
+}
+
+
+/* ----------------------------------------------------------------------
+ * hide_handler() - Hide a node
+ * ---------------------------------------------------------------------- */
+
+void hide_handler(FILE *f) {
+ Node *n = 0;
+ if (!swill_getargs("p(hn)", &n)) {
+ n = 0;
+ }
+ if (n) {
+ Delmeta(n, "visible");
+ }
+ node_handler(f);
+}
+
+void show_handler(FILE *f) {
+ Node *n = 0;
+ if (!swill_getargs("p(hn)", &n)) {
+ n = 0;
+ }
+ if (n) {
+ Setmeta(n, "visible", "1");
+ }
+ node_handler(f);
+}
+
+void raw_data(FILE *out, Node *obj) {
+ if (!obj)
+ return;
+ if (DohIsMapping(obj)) {
+ String *k;
+ Iterator ki;
+ String *os = NewString("");
+ Printf(os, "Hash {\n");
+ ki = First(obj);
+ while (ki.key) {
+ k = ki.key;
+ DOH *o;
+ const char *trunc = "";
+ if (DohIsString(Getattr(obj, k))) {
+ o = Str(Getattr(obj, k));
+ if (Len(o) > 70) {
+ trunc = "...";
+ }
+ Replaceall(o, "<", "&lt;");
+ Printf(os, " <a href=\"data.html?n=%p\">?</a> %-12s - \"%(escape)-0.70s%s\"\n", Getattr(obj, k), k, o, trunc);
+ Delete(o);
+ } else {
+ Printf(os, " <a href=\"data.html?n=%p\">?</a> %-12s - %p\n", Getattr(obj, k), k, Getattr(obj, k));
+ }
+ ki = Next(ki);
+ }
+ Printf(os, "}\n");
+ Printf(out, "<FONT color=\"#660000\"><pre>\n%s</pre></FONT>\n", Char(os));
+ Delete(os);
+ } else if (DohIsString(obj)) {
+ String *o = Str(obj);
+ Replaceall(o, "<", "&lt;");
+ Printf(out, "<FONT color=\"#660000\"><pre>\n%s</pre></FONT>\n", Char(o));
+ Delete(o);
+ } else if (DohIsSequence(obj)) {
+ int i;
+ String *os = NewString("");
+ Printf(os, "List [\n");
+ for (i = 0; i < Len(obj); i++) {
+ DOH *o = Getitem(obj, i);
+ const char *trunc = "";
+ if (DohIsString(o)) {
+ String *s = Str(o);
+ if (Len(s) > 70) {
+ trunc = "...";
+ }
+ Replaceall(o, "<", "&lt;");
+ Printf(os, " <a href=\"data.html?n=%p\">?</a> [%d] - \"%(escape)-0.70s%s\"\n", o, i, s, trunc);
+ Delete(s);
+ } else {
+ Printf(os, " <a href=\"data.html?n=%p\">?</a> [%d] - %p\n", o, i, o);
+ }
+ }
+ Printf(os, "\n]\n");
+ Printf(out, "<FONT color=\"#660000\"><pre>\n%s</pre></FONT>\n", Char(os));
+ Delete(os);
+ }
+}
+
+void data_handler(FILE *f) {
+ DOH *n = 0;
+ if (!swill_getargs("p(n)", &n)) {
+ n = 0;
+ }
+ Printf(f, "<HTML><HEAD><TITLE>SWIG-%s</TITLE></HEAD><BODY BGCOLOR=\"#ffffff\">\n", Swig_package_version());
+ Printf(f, "<b>SWIG-%s</b><br>\n", Swig_package_version());
+ Printf(f, "[ <a href=\"exit.html\">Exit</a> ]");
+ Printf(f, " [ <a href=\"index.html?node=%p\">Top</a> ]", tree_top);
+ Printf(f, "<br><hr><p>\n");
+ if (n) {
+ raw_data(f, n);
+ }
+ /* Print standard footer */
+ Printf(f, "<br><hr></BODY></HTML>\n");
+}
+
+void symbol_handler(FILE *f) {
+ Symtab *sym;
+ char *name = 0;
+
+ Printf(f, "<HTML><HEAD><TITLE>SWIG-%s</TITLE></HEAD><BODY BGCOLOR=\"#ffffff\">\n", Swig_package_version());
+ Printf(f, "<b>SWIG-%s</b><br>\n", Swig_package_version());
+ Printf(f, "[ <a href=\"exit.html\">Exit</a> ]");
+ Printf(f, " [ <a href=\"index.html?node=%p\">Top</a> ]", tree_top);
+ Printf(f, " [ <a href=\"symbol.html\">Symbols</a> ]");
+ Printf(f, "<br><hr><p>\n");
+
+ if (!swill_getargs("p(sym)|s(name)", &sym, &name)) {
+ sym = Swig_symbol_getscope("");
+ name = 0;
+ }
+ if (!sym) {
+ Printf(f, "No symbol table specified!\n");
+ return;
+ }
+ {
+ String *q = Swig_symbol_qualifiedscopename(sym);
+ if (!Len(q)) {
+ Printf(f, "<b>Symbol table: :: (global)</b><br>\n");
+ } else {
+ Printf(f, "<b>Symbol table: %s</b><br>\n", q);
+ }
+ Delete(q);
+ }
+
+ fprintf(f, "<p><form action=\"symbol.html\" method=GET>\n");
+ fprintf(f, "Symbol lookup: <input type=text name=name size=40></input><br>\n");
+ fprintf(f, "<input type=hidden name=sym value=\"%p\">\n", sym);
+ fprintf(f, "Submit : <input type=submit></input>\n");
+ fprintf(f, "</form>");
+
+ if (name) {
+ Node *n = Swig_symbol_clookup(name, sym);
+ Printf(f, "Symbol '%s':\n", name);
+ Printf(f, "<blockquote>\n");
+ if (!n) {
+ Printf(f, "Not defined!\n");
+ } else {
+ raw_data(f, n);
+ }
+ Printf(f, "</blockquote>\n");
+ }
+
+ Printf(f, "<p><b>Nested scopes</b><br>\n");
+ Printf(f, "<blockquote><pre>\n");
+ {
+ Hash *h;
+ h = firstChild(sym);
+ while (h) {
+ Printf(f, "<a href=\"symbol.html?sym=%p\">%s</a>\n", h, Getattr(h, "name"));
+ h = nextSibling(h);
+ }
+ }
+ Printf(f, "</pre></blockquote>\n");
+
+ Printf(f, "<p><b>Symbol table contents</b></br>\n");
+ raw_data(f, Getattr(sym, "symtab"));
+ Printf(f, "<br><hr></BODY></HTML>\n");
+
+}
+#endif
+
+void Swig_browser(Node *top, int port) {
+#ifdef SWIG_SWILL
+ int sport;
+ browser_exit = 0;
+
+ /* Initialize the server */
+ sport = swill_init(port);
+ if (sport < 0) {
+ Printf(stderr, "Couldn't open socket on port %d. Sorry.\n", port);
+ return;
+ }
+ browse = new Browser();
+ Setmeta(top, "visible", "1");
+ tree_top = top;
+
+ Printf(stderr, "SWIG: Tree browser listening on port %d\n", sport);
+
+ swill_handle("exit.html", exit_handler, 0);
+ swill_handle("index.html", node_handler, 0);
+ swill_handle("hide.html", hide_handler, 0);
+ swill_handle("show.html", show_handler, 0);
+ swill_handle("data.html", data_handler, 0);
+ swill_handle("symbol.html", symbol_handler, 0);
+ swill_netscape("index.html");
+
+ while (!browser_exit) {
+ swill_serve();
+ }
+ Printf(stderr, "Browser terminated.\n");
+ swill_close();
+ delete browse;
+ return;
+#else
+ (void) top;
+ (void) port;
+#endif
+}
diff --git a/contrib/tools/swig/Source/Modules/contract.cxx b/contrib/tools/swig/Source/Modules/contract.cxx
new file mode 100644
index 00000000000..7e0eaf9e074
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/contract.cxx
@@ -0,0 +1,358 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * contract.cxx
+ *
+ * Support for Wrap by Contract in SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+
+/* Contract structure. This holds rules about the different kinds of contract sections
+ and their combination rules */
+
+struct contract {
+ const char *section;
+ const char *combiner;
+};
+/* Contract rules. This table defines what contract sections are recognized as well as
+ how contracts are to combined via inheritance */
+
+static contract Rules[] = {
+ {"require:", "&&"},
+ {"ensure:", "||"},
+ {NULL, NULL}
+};
+
+/* ----------------------------------------------------------------------------
+ * class Contracts:
+ *
+ * This class defines the functions that need to be used in
+ * "wrap by contract" module.
+ * ------------------------------------------------------------------------- */
+
+class Contracts:public Dispatcher {
+ String *make_expression(String *s, Node *n);
+ void substitute_parms(String *s, ParmList *p, int method);
+public:
+ Hash *ContractSplit(Node *n);
+ int emit_contract(Node *n, int method);
+ int cDeclaration(Node *n);
+ int constructorDeclaration(Node *n);
+ int externDeclaration(Node *n);
+ int extendDirective(Node *n);
+ int importDirective(Node *n);
+ int includeDirective(Node *n);
+ int namespaceDeclaration(Node *n);
+ int classDeclaration(Node *n);
+ virtual int top(Node *n);
+};
+
+static int Contract_Mode = 0; /* contract option */
+static int InClass = 0; /* Parsing C++ or not */
+static int InConstructor = 0;
+static Node *CurrentClass = 0;
+
+/* Set the contract mode, default is 0 (not open) */
+/* Normally set in main.cxx, when get the "-contracts" option */
+void Swig_contract_mode_set(int flag) {
+ Contract_Mode = flag;
+}
+
+/* Get the contract mode */
+int Swig_contract_mode_get() {
+ return Contract_Mode;
+}
+
+/* Apply contracts */
+void Swig_contracts(Node *n) {
+
+ Contracts *a = new Contracts;
+ a->top(n);
+ delete a;
+}
+
+/* Split the whole contract into preassertion, postassertion and others */
+Hash *Contracts::ContractSplit(Node *n) {
+
+ String *contract = Getattr(n, "feature:contract");
+ Hash *result;
+ if (!contract)
+ return NULL;
+
+ result = NewHash();
+ String *current_section = NewString("");
+ const char *current_section_name = Rules[0].section;
+ List *l = SplitLines(contract);
+
+ Iterator i;
+ for (i = First(l); i.item; i = Next(i)) {
+ int found = 0;
+ if (Strchr(i.item, '{'))
+ continue;
+ if (Strchr(i.item, '}'))
+ continue;
+ for (int j = 0; Rules[j].section; j++) {
+ if (Strstr(i.item, Rules[j].section)) {
+ if (Len(current_section)) {
+ Setattr(result, current_section_name, current_section);
+ current_section = Getattr(result, Rules[j].section);
+ if (!current_section)
+ current_section = NewString("");
+ }
+ current_section_name = Rules[j].section;
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ Append(current_section, i.item);
+ }
+ if (Len(current_section))
+ Setattr(result, current_section_name, current_section);
+ return result;
+}
+
+/* This function looks in base classes and collects contracts found */
+void inherit_contracts(Node *c, Node *n, Hash *contracts, Hash *messages) {
+
+ Node *b, *temp;
+ String *name, *type, *local_decl, *base_decl;
+ List *bases;
+ int found = 0;
+
+ bases = Getattr(c, "bases");
+ if (!bases)
+ return;
+
+ name = Getattr(n, "name");
+ type = Getattr(n, "type");
+ local_decl = Getattr(n, "decl");
+ if (local_decl) {
+ local_decl = SwigType_typedef_resolve_all(local_decl);
+ } else {
+ return;
+ }
+ /* Width first search */
+ for (int i = 0; i < Len(bases); i++) {
+ b = Getitem(bases, i);
+ temp = firstChild(b);
+ while (temp) {
+ base_decl = Getattr(temp, "decl");
+ if (base_decl) {
+ base_decl = SwigType_typedef_resolve_all(base_decl);
+ if ((checkAttribute(temp, "storage", "virtual")) &&
+ (checkAttribute(temp, "name", name)) && (checkAttribute(temp, "type", type)) && (!Strcmp(local_decl, base_decl))) {
+ /* Yes, match found. */
+ Hash *icontracts = Getattr(temp, "contract:rules");
+ Hash *imessages = Getattr(temp, "contract:messages");
+ found = 1;
+ if (icontracts && imessages) {
+ /* Add inherited contracts and messages to the contract rules above */
+ int j = 0;
+ for (j = 0; Rules[j].section; j++) {
+ String *t = Getattr(contracts, Rules[j].section);
+ String *s = Getattr(icontracts, Rules[j].section);
+ if (s) {
+ if (t) {
+ Insert(t, 0, "(");
+ Printf(t, ") %s (%s)", Rules[j].combiner, s);
+ String *m = Getattr(messages, Rules[j].section);
+ Printf(m, " %s [%s from %s]", Rules[j].combiner, Getattr(imessages, Rules[j].section), Getattr(b, "name"));
+ } else {
+ Setattr(contracts, Rules[j].section, NewString(s));
+ Setattr(messages, Rules[j].section, NewStringf("[%s from %s]", Getattr(imessages, Rules[j].section), Getattr(b, "name")));
+ }
+ }
+ }
+ }
+ }
+ Delete(base_decl);
+ }
+ temp = nextSibling(temp);
+ }
+ }
+ Delete(local_decl);
+ if (!found) {
+ for (int j = 0; j < Len(bases); j++) {
+ b = Getitem(bases, j);
+ inherit_contracts(b, n, contracts, messages);
+ }
+ }
+}
+
+/* This function cleans up the assertion string by removing some extraneous characters.
+ Splitting the assertion into pieces */
+
+String *Contracts::make_expression(String *s, Node *n) {
+ String *str_assert, *expr = 0;
+ List *list_assert;
+
+ str_assert = NewString(s);
+ /* Omit all useless characters and split by ; */
+ Replaceall(str_assert, "\n", "");
+ Replaceall(str_assert, "{", "");
+ Replaceall(str_assert, "}", "");
+ Replace(str_assert, " ", "", DOH_REPLACE_ANY | DOH_REPLACE_NOQUOTE);
+ Replace(str_assert, "\t", "", DOH_REPLACE_ANY | DOH_REPLACE_NOQUOTE);
+
+ list_assert = Split(str_assert, ';', -1);
+ Delete(str_assert);
+
+ /* build up new assertion */
+ str_assert = NewString("");
+ Iterator ei;
+
+ for (ei = First(list_assert); ei.item; ei = Next(ei)) {
+ expr = ei.item;
+ if (Len(expr)) {
+ Replaceid(expr, Getattr(n, "name"), Swig_cresult_name());
+ if (Len(str_assert))
+ Append(str_assert, "&&");
+ Printf(str_assert, "(%s)", expr);
+ }
+ }
+ Delete(list_assert);
+ return str_assert;
+}
+
+/* This function substitutes parameter names for argument names in the
+ contract specification. Note: it is assumed that the wrapper code
+ uses arg1 for self and arg2..argn for arguments. */
+
+void Contracts::substitute_parms(String *s, ParmList *p, int method) {
+ int argnum = 1;
+ char argname[32];
+
+ if (method) {
+ Replaceid(s, "$self", "arg1");
+ argnum++;
+ }
+ while (p) {
+ sprintf(argname, "arg%d", argnum);
+ String *name = Getattr(p, "name");
+ if (name) {
+ Replaceid(s, name, argname);
+ }
+ argnum++;
+ p = nextSibling(p);
+ }
+}
+
+int Contracts::emit_contract(Node *n, int method) {
+ Hash *contracts;
+ Hash *messages;
+ String *c;
+
+ ParmList *cparms;
+
+ if (!Getattr(n, "feature:contract"))
+ return SWIG_ERROR;
+
+ /* Get contract parameters */
+ cparms = Getmeta(Getattr(n, "feature:contract"), "parms");
+
+ /* Split contract into preassert & postassert */
+ contracts = ContractSplit(n);
+ if (!contracts)
+ return SWIG_ERROR;
+
+ /* This messages hash is used to hold the error messages that will be displayed on
+ failed contract. */
+
+ messages = NewHash();
+
+ /* Take the different contract expressions and clean them up a bit */
+ Iterator i;
+ for (i = First(contracts); i.item; i = Next(i)) {
+ String *e = make_expression(i.item, n);
+ substitute_parms(e, cparms, method);
+ Setattr(contracts, i.key, e);
+
+ /* Make a string containing error messages */
+ Setattr(messages, i.key, NewString(e));
+ }
+
+ /* If we're in a class. We need to inherit other assertions. */
+ if (InClass) {
+ inherit_contracts(CurrentClass, n, contracts, messages);
+ }
+
+ /* Save information */
+ Setattr(n, "contract:rules", contracts);
+ Setattr(n, "contract:messages", messages);
+
+ /* Okay. Generate the contract runtime code. */
+
+ if ((c = Getattr(contracts, "require:"))) {
+ Setattr(n, "contract:preassert", NewStringf("SWIG_contract_assert(%s, \"Contract violation: require: %s\");\n", c, Getattr(messages, "require:")));
+ }
+ if ((c = Getattr(contracts, "ensure:"))) {
+ Setattr(n, "contract:postassert", NewStringf("SWIG_contract_assert(%s, \"Contract violation: ensure: %s\");\n", c, Getattr(messages, "ensure:")));
+ }
+ return SWIG_OK;
+}
+
+int Contracts::cDeclaration(Node *n) {
+ int ret = SWIG_OK;
+ String *decl = Getattr(n, "decl");
+
+ /* Not a function. Don't even bother with it (for now) */
+ if (!SwigType_isfunction(decl))
+ return SWIG_OK;
+
+ if (Getattr(n, "feature:contract"))
+ ret = emit_contract(n, InClass && !Swig_storage_isstatic(n));
+ return ret;
+}
+
+int Contracts::constructorDeclaration(Node *n) {
+ int ret = SWIG_OK;
+ InConstructor = 1;
+ if (Getattr(n, "feature:contract"))
+ ret = emit_contract(n, 0);
+ InConstructor = 0;
+ return ret;
+}
+
+int Contracts::externDeclaration(Node *n) {
+ return emit_children(n);
+}
+
+int Contracts::extendDirective(Node *n) {
+ return emit_children(n);
+}
+
+int Contracts::importDirective(Node *n) {
+ return emit_children(n);
+}
+
+int Contracts::includeDirective(Node *n) {
+ return emit_children(n);
+}
+
+int Contracts::namespaceDeclaration(Node *n) {
+ return emit_children(n);
+}
+
+int Contracts::classDeclaration(Node *n) {
+ int ret = SWIG_OK;
+ int oldInClass = InClass;
+ Node *oldClass = CurrentClass;
+ InClass = 1;
+ CurrentClass = n;
+ emit_children(n);
+ InClass = oldInClass;
+ CurrentClass = oldClass;
+ return ret;
+}
+
+int Contracts::top(Node *n) {
+ emit_children(n);
+ return SWIG_OK;
+}
diff --git a/contrib/tools/swig/Source/Modules/csharp.cxx b/contrib/tools/swig/Source/Modules/csharp.cxx
new file mode 100644
index 00000000000..27cc65b3245
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/csharp.cxx
@@ -0,0 +1,4598 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * csharp.cxx
+ *
+ * C# language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include <limits.h> // for INT_MAX
+#include "cparse.h"
+#include <ctype.h>
+
+/* Hash type used for upcalls from C/C++ */
+typedef DOH UpcallData;
+
+class CSHARP:public Language {
+ static const char *usage;
+ const String *empty_string;
+ const String *public_string;
+ const String *protected_string;
+
+ Hash *swig_types_hash;
+ File *f_begin;
+ File *f_runtime;
+ File *f_runtime_h;
+ File *f_header;
+ File *f_wrappers;
+ File *f_init;
+ File *f_directors;
+ File *f_directors_h;
+ File *f_single_out;
+ List *filenames_list;
+
+ bool proxy_flag; // Flag for generating proxy classes
+ bool native_function_flag; // Flag for when wrapping a native function
+ bool enum_constant_flag; // Flag for when wrapping an enum or constant
+ bool static_flag; // Flag for when wrapping a static functions or member variables
+ bool variable_wrapper_flag; // Flag for when wrapping a nonstatic member variable
+ bool wrapping_member_flag; // Flag for when wrapping a member variable/enum/const
+ bool global_variable_flag; // Flag for when wrapping a global variable
+ bool old_variable_names; // Flag for old style variable names in the intermediary class
+ bool generate_property_declaration_flag; // Flag for generating properties
+
+ String *imclass_name; // intermediary class name
+ String *module_class_name; // module class name
+ String *imclass_class_code; // intermediary class code
+ String *proxy_class_def;
+ String *proxy_class_code;
+ String *interface_class_code; // if %feature("interface") was declared for a class, here goes the interface declaration
+ String *module_class_code;
+ String *proxy_class_name; // proxy class name
+ String *full_imclass_name; // fully qualified intermediary class name when using nspace feature, otherwise same as imclass_name
+ String *variable_name; //Name of a variable being wrapped
+ String *proxy_class_constants_code;
+ String *module_class_constants_code;
+ String *enum_code;
+ String *dllimport; // DllImport attribute name
+ String *namespce; // Optional namespace name
+ String *imclass_imports; //intermediary class imports from %pragma
+ String *module_imports; //module imports from %pragma
+ String *imclass_baseclass; //inheritance for intermediary class class from %pragma
+ String *module_baseclass; //inheritance for module class from %pragma
+ String *imclass_interfaces; //interfaces for intermediary class class from %pragma
+ String *module_interfaces; //interfaces for module class from %pragma
+ String *imclass_class_modifiers; //class modifiers for intermediary class overridden by %pragma
+ String *module_class_modifiers; //class modifiers for module class overridden by %pragma
+ String *upcasts_code; //C++ casts for inheritance hierarchies C++ code
+ String *imclass_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code
+ String *director_callback_typedefs; // Director function pointer typedefs for callbacks
+ String *director_callbacks; // Director callback function pointer member variables
+ String *director_delegate_callback; // Director callback method that delegates are set to call
+ String *director_delegate_definitions; // Director delegates definitions in proxy class
+ String *director_delegate_instances; // Director delegates member variables in proxy class
+ String *director_method_types; // Director method types
+ String *director_connect_parms; // Director delegates parameter list for director connect call
+ String *destructor_call; //C++ destructor call if any
+ String *output_file; // File name for single file mode. If set all generated code will be written to this file
+
+ // Director method stuff:
+ List *dmethods_seq;
+ Hash *dmethods_table;
+ int n_dmethods;
+ int n_directors;
+ int first_class_dmethod;
+ int curr_class_dmethod;
+ int nesting_depth;
+
+ enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
+
+public:
+
+ /* -----------------------------------------------------------------------------
+ * CSHARP()
+ * ----------------------------------------------------------------------------- */
+
+ CSHARP():empty_string(NewString("")),
+ public_string(NewString("public")),
+ protected_string(NewString("protected")),
+ swig_types_hash(NULL),
+ f_begin(NULL),
+ f_runtime(NULL),
+ f_runtime_h(NULL),
+ f_header(NULL),
+ f_wrappers(NULL),
+ f_init(NULL),
+ f_directors(NULL),
+ f_directors_h(NULL),
+ f_single_out(NULL),
+ filenames_list(NULL),
+ proxy_flag(true),
+ native_function_flag(false),
+ enum_constant_flag(false),
+ static_flag(false),
+ variable_wrapper_flag(false),
+ wrapping_member_flag(false),
+ global_variable_flag(false),
+ old_variable_names(false),
+ generate_property_declaration_flag(false),
+ imclass_name(NULL),
+ module_class_name(NULL),
+ imclass_class_code(NULL),
+ proxy_class_def(NULL),
+ proxy_class_code(NULL),
+ interface_class_code(NULL),
+ module_class_code(NULL),
+ proxy_class_name(NULL),
+ full_imclass_name(NULL),
+ variable_name(NULL),
+ proxy_class_constants_code(NULL),
+ module_class_constants_code(NULL),
+ enum_code(NULL),
+ dllimport(NULL),
+ namespce(NULL),
+ imclass_imports(NULL),
+ module_imports(NULL),
+ imclass_baseclass(NULL),
+ module_baseclass(NULL),
+ imclass_interfaces(NULL),
+ module_interfaces(NULL),
+ imclass_class_modifiers(NULL),
+ module_class_modifiers(NULL),
+ upcasts_code(NULL),
+ imclass_cppcasts_code(NULL),
+ director_callback_typedefs(NULL),
+ director_callbacks(NULL),
+ director_delegate_callback(NULL),
+ director_delegate_definitions(NULL),
+ director_delegate_instances(NULL),
+ director_method_types(NULL),
+ director_connect_parms(NULL),
+ destructor_call(NULL),
+ output_file(NULL),
+ dmethods_seq(NULL),
+ dmethods_table(NULL),
+ n_dmethods(0),
+ n_directors(0),
+ first_class_dmethod(0),
+ curr_class_dmethod(0),
+ nesting_depth(0){
+ /* for now, multiple inheritance in directors is disabled, this
+ should be easy to implement though */
+ director_multiple_inheritance = 0;
+ director_language = 1;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getProxyName()
+ *
+ * Test to see if a type corresponds to something wrapped with a proxy class.
+ * Return NULL if not otherwise the proxy class name, fully qualified with
+ * a namespace if the nspace feature is used.
+ * ----------------------------------------------------------------------------- */
+
+ String *getProxyName(SwigType *t) {
+ String *proxyname = NULL;
+ if (proxy_flag) {
+ Node *n = classLookup(t);
+ if (n) {
+ proxyname = Getattr(n, "proxyname");
+ if (!proxyname) {
+ String *nspace = Getattr(n, "sym:nspace");
+ String *symname = Copy(Getattr(n, "sym:name"));
+ if (symname && !GetFlag(n, "feature:flatnested")) {
+ for (Node *outer_class = Getattr(n, "nested:outer"); outer_class; outer_class = Getattr(outer_class, "nested:outer")) {
+ if (String* name = Getattr(outer_class, "sym:name")) {
+ Push(symname, ".");
+ Push(symname, name);
+ }
+ else
+ return NULL;
+ }
+ }
+ if (nspace) {
+ if (namespce)
+ proxyname = NewStringf("%s.%s.%s", namespce, nspace, symname);
+ else
+ proxyname = NewStringf("%s.%s", nspace, symname);
+ } else {
+ proxyname = Copy(symname);
+ }
+ Setattr(n, "proxyname", proxyname);
+ Delete(proxyname);
+ Delete(symname);
+ }
+ }
+ }
+ return proxyname;
+ }
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+
+ SWIG_library_directory("csharp");
+
+ // Look for certain command line options
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-dllimport") == 0) {
+ if (argv[i + 1]) {
+ dllimport = NewString("");
+ Printf(dllimport, argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-namespace") == 0) {
+ if (argv[i + 1]) {
+ namespce = NewString("");
+ Printf(namespce, argv[i + 1]);
+ if (Len(namespce) == 0) {
+ Delete(namespce);
+ namespce = 0;
+ }
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if ((strcmp(argv[i], "-noproxy") == 0)) {
+ Swig_mark_arg(i);
+ proxy_flag = false;
+ } else if (strcmp(argv[i], "-oldvarnames") == 0) {
+ Swig_mark_arg(i);
+ old_variable_names = true;
+ } else if (strcmp(argv[i], "-outfile") == 0) {
+ if (argv[i + 1]) {
+ output_file = NewString("");
+ Printf(output_file, argv[i + 1]);
+ 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);
+ }
+ }
+ }
+
+ // Add a symbol to the parser for conditional compilation
+ Preprocessor_define("SWIGCSHARP 1", 0);
+
+ // Add typemap definitions
+ SWIG_typemap_lang("csharp");
+ SWIG_config_file("csharp.swg");
+
+ allow_overloading();
+ Swig_interface_feature_enable();
+ }
+
+ /* ---------------------------------------------------------------------
+ * top()
+ * --------------------------------------------------------------------- */
+
+ virtual int top(Node *n) {
+
+ // Get any options set in the module directive
+ Node *optionsnode = Getattr(Getattr(n, "module"), "options");
+
+ if (optionsnode) {
+ if (Getattr(optionsnode, "imclassname"))
+ imclass_name = Copy(Getattr(optionsnode, "imclassname"));
+ /* check if directors are enabled for this module. note: this
+ * is a "master" switch, without which no director code will be
+ * emitted. %feature("director") statements are also required
+ * to enable directors for individual classes or methods.
+ *
+ * use %module(directors="1") modulename at the start of the
+ * interface file to enable director generation.
+ */
+ if (Getattr(optionsnode, "directors")) {
+ allow_directors();
+ }
+ if (Getattr(optionsnode, "dirprot")) {
+ allow_dirprot();
+ }
+ allow_allprotected(GetFlag(optionsnode, "allprotected"));
+ }
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+ String *outfile_h = Getattr(n, "outfile_h");
+
+ if (!outfile) {
+ Printf(stderr, "Unable to determine outfile\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ if (directorsEnabled()) {
+ if (!outfile_h) {
+ Printf(stderr, "Unable to determine outfile_h\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+ f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
+ if (!f_runtime_h) {
+ FileErrorDisplay(outfile_h);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+ f_directors_h = NewString("");
+ f_directors = NewString("");
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+
+ swig_types_hash = NewHash();
+ filenames_list = NewList();
+
+ // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
+ if (!imclass_name) {
+ imclass_name = NewStringf("%sPINVOKE", Getattr(n, "name"));
+ module_class_name = Copy(Getattr(n, "name"));
+ } else {
+ // Rename the module name if it is the same as intermediary class name - a backwards compatibility solution
+ if (Cmp(imclass_name, Getattr(n, "name")) == 0)
+ module_class_name = NewStringf("%sModule", Getattr(n, "name"));
+ else
+ module_class_name = Copy(Getattr(n, "name"));
+ }
+
+ // module class and intermediary classes are always created
+ if (!addSymbol(imclass_name, n))
+ return SWIG_ERROR;
+ if (!addSymbol(module_class_name, n))
+ return SWIG_ERROR;
+
+ imclass_class_code = NewString("");
+ proxy_class_def = NewString("");
+ proxy_class_code = NewString("");
+ module_class_constants_code = NewString("");
+ imclass_baseclass = NewString("");
+ imclass_interfaces = NewString("");
+ imclass_class_modifiers = NewString("");
+ module_class_code = NewString("");
+ module_baseclass = NewString("");
+ module_interfaces = NewString("");
+ module_imports = NewString("");
+ module_class_modifiers = NewString("");
+ imclass_imports = NewString("");
+ imclass_cppcasts_code = NewString("");
+ director_connect_parms = NewString("");
+ upcasts_code = NewString("");
+ dmethods_seq = NewList();
+ dmethods_table = NewHash();
+ n_dmethods = 0;
+ n_directors = 0;
+ if (!dllimport)
+ dllimport = Copy(module_class_name);
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n\n#ifndef SWIGCSHARP\n#define SWIGCSHARP\n#endif\n\n");
+
+ if (directorsEnabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+
+ /* Emit initial director header and director code: */
+ Swig_banner(f_directors_h);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_class_name);
+ Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_class_name);
+
+ Printf(f_directors, "\n\n");
+ Printf(f_directors, "/* ---------------------------------------------------\n");
+ Printf(f_directors, " * C++ director class methods\n");
+ Printf(f_directors, " * --------------------------------------------------- */\n\n");
+ if (outfile_h) {
+ String *filename = Swig_file_filename(outfile_h);
+ Printf(f_directors, "#include \"%s\"\n\n", filename);
+ Delete(filename);
+ }
+ }
+
+ Printf(f_runtime, "\n");
+ if (namespce) {
+ String *wrapper_name = NewStringf("");
+ Printf(wrapper_name, "CSharp_%s_%%f", namespce);
+ Swig_name_register("wrapper", wrapper_name);
+ Delete(wrapper_name);
+ }
+ else {
+ Swig_name_register("wrapper", "CSharp_%f");
+ }
+
+ if (old_variable_names) {
+ Swig_name_register("set", "set_%n%v");
+ Swig_name_register("get", "get_%n%v");
+ }
+
+ Printf(f_wrappers, "\n#ifdef __cplusplus\n");
+ Printf(f_wrappers, "extern \"C\" {\n");
+ Printf(f_wrappers, "#endif\n\n");
+
+ /* Emit code */
+ Language::top(n);
+
+ if (directorsEnabled()) {
+ // Insert director runtime into the f_runtime file (make it occur before %header section)
+ Swig_insert_file("director_common.swg", f_runtime);
+ Swig_insert_file("director.swg", f_runtime);
+ }
+ // Generate the intermediary class
+ {
+ File *f_im = getOutputFile(SWIG_output_directory(), imclass_name);
+
+ addOpenNamespace(0, f_im);
+
+ if (imclass_imports)
+ Printf(f_im, "%s\n", imclass_imports);
+
+ if (Len(imclass_class_modifiers) > 0)
+ Printf(f_im, "%s ", imclass_class_modifiers);
+ Printf(f_im, "%s ", imclass_name);
+
+ if (imclass_baseclass && *Char(imclass_baseclass))
+ Printf(f_im, ": %s ", imclass_baseclass);
+ if (Len(imclass_interfaces) > 0)
+ Printv(f_im, "implements ", imclass_interfaces, " ", NIL);
+ Printf(f_im, "{\n");
+
+ // Add the intermediary class methods
+ Replaceall(imclass_class_code, "$module", module_class_name);
+ Replaceall(imclass_class_code, "$imclassname", imclass_name);
+ Replaceall(imclass_class_code, "$dllimport", dllimport);
+ Printv(f_im, imclass_class_code, NIL);
+ Printv(f_im, imclass_cppcasts_code, NIL);
+
+ // Finish off the class
+ Printf(f_im, "}\n");
+ addCloseNamespace(0, f_im);
+
+ if (f_im != f_single_out)
+ Delete(f_im);
+ f_im = NULL;
+ }
+
+ // Generate the C# module class
+ {
+ File *f_module = getOutputFile(SWIG_output_directory(), module_class_name);
+
+ addOpenNamespace(0, f_module);
+
+ if (module_imports)
+ Printf(f_module, "%s\n", module_imports);
+
+ if (Len(module_class_modifiers) > 0)
+ Printf(f_module, "%s ", module_class_modifiers);
+ Printf(f_module, "%s ", module_class_name);
+
+ if (module_baseclass && *Char(module_baseclass))
+ Printf(f_module, ": %s ", module_baseclass);
+ if (Len(module_interfaces) > 0)
+ Printv(f_module, "implements ", module_interfaces, " ", NIL);
+ Printf(f_module, "{\n");
+
+ Replaceall(module_class_code, "$module", module_class_name);
+ Replaceall(module_class_constants_code, "$module", module_class_name);
+
+ Replaceall(module_class_code, "$imclassname", imclass_name);
+ Replaceall(module_class_constants_code, "$imclassname", imclass_name);
+
+ Replaceall(module_class_code, "$dllimport", dllimport);
+ Replaceall(module_class_constants_code, "$dllimport", dllimport);
+
+ // Add the wrapper methods
+ Printv(f_module, module_class_code, NIL);
+
+ // Write out all the global constants
+ Printv(f_module, module_class_constants_code, NIL);
+
+ // Finish off the class
+ Printf(f_module, "}\n");
+ addCloseNamespace(0, f_module);
+
+ if (f_module != f_single_out)
+ Delete(f_module);
+ f_module = NULL;
+ }
+
+ if (upcasts_code)
+ Printv(f_wrappers, upcasts_code, NIL);
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n");
+ Printf(f_wrappers, "}\n");
+ Printf(f_wrappers, "#endif\n");
+
+ // Output a C# type wrapper class for each SWIG type
+ for (Iterator swig_type = First(swig_types_hash); swig_type.key; swig_type = Next(swig_type)) {
+ emitTypeWrapperClass(swig_type.key, swig_type.item);
+ }
+
+ // Check for overwriting file problems on filesystems that are case insensitive
+ Iterator it1;
+ Iterator it2;
+ for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) {
+ String *item1_lower = Swig_string_lower(it1.item);
+ for (it2 = Next(it1); it2.item; it2 = Next(it2)) {
+ String *item2_lower = Swig_string_lower(it2.item);
+ if (it1.item && it2.item) {
+ if (Strcmp(item1_lower, item2_lower) == 0) {
+ Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number,
+ "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as "
+ "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item);
+ }
+ }
+ Delete(item2_lower);
+ }
+ Delete(item1_lower);
+ }
+
+ Delete(swig_types_hash);
+ swig_types_hash = NULL;
+ Delete(filenames_list);
+ filenames_list = NULL;
+ Delete(imclass_name);
+ imclass_name = NULL;
+ Delete(imclass_class_code);
+ imclass_class_code = NULL;
+ Delete(proxy_class_def);
+ proxy_class_def = NULL;
+ Delete(proxy_class_code);
+ proxy_class_code = NULL;
+ Delete(module_class_constants_code);
+ module_class_constants_code = NULL;
+ Delete(imclass_baseclass);
+ imclass_baseclass = NULL;
+ Delete(imclass_interfaces);
+ imclass_interfaces = NULL;
+ Delete(imclass_class_modifiers);
+ imclass_class_modifiers = NULL;
+ Delete(module_class_name);
+ module_class_name = NULL;
+ Delete(module_class_code);
+ module_class_code = NULL;
+ Delete(module_baseclass);
+ module_baseclass = NULL;
+ Delete(module_interfaces);
+ module_interfaces = NULL;
+ Delete(module_imports);
+ module_imports = NULL;
+ Delete(module_class_modifiers);
+ module_class_modifiers = NULL;
+ Delete(imclass_imports);
+ imclass_imports = NULL;
+ Delete(imclass_cppcasts_code);
+ imclass_cppcasts_code = NULL;
+ Delete(upcasts_code);
+ upcasts_code = NULL;
+ Delete(dmethods_seq);
+ dmethods_seq = NULL;
+ Delete(dmethods_table);
+ dmethods_table = NULL;
+ Delete(namespce);
+ namespce = NULL;
+ n_dmethods = 0;
+
+ /* Close all of the files */
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+
+ if (directorsEnabled()) {
+ Dump(f_directors, f_begin);
+ Dump(f_directors_h, f_runtime_h);
+
+ Printf(f_runtime_h, "\n");
+ Printf(f_runtime_h, "#endif\n");
+
+ Delete(f_runtime_h);
+ f_runtime_h = NULL;
+ Delete(f_directors);
+ f_directors = NULL;
+ Delete(f_directors_h);
+ f_directors_h = NULL;
+ }
+
+ if (f_single_out) {
+ Dump(f_single_out, f_begin);
+ Delete(f_single_out);
+ f_single_out = NULL;
+ }
+
+ Dump(f_wrappers, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_runtime);
+ Delete(f_begin);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * emitBanner()
+ * ----------------------------------------------------------------------------- */
+
+ void emitBanner(File *f) {
+ Printf(f, "//------------------------------------------------------------------------------\n");
+ Printf(f, "// <auto-generated />\n");
+ Printf(f, "//\n");
+ Swig_banner_target_lang(f, "//");
+ Printf(f, "//------------------------------------------------------------------------------\n\n");
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getOutputFile()
+ *
+ * Prepares a File object by creating the file in the file system and
+ * writing the banner for auto-generated files to it (emitBanner).
+ * If '-outfile' is provided (single file mode) the supplied parameters will
+ * be ignored and the returned file will always be:
+ * <outdir>/<outfile>
+ * Otherwise the file will be:
+ * <dir>/<name>.cs
+ * ----------------------------------------------------------------------------- */
+
+ File *getOutputFile(const String *dir, const String *name) {
+ if (output_file) {
+ if (!f_single_out) {
+ String *filen = NewStringf("%s%s", SWIG_output_directory(), output_file);
+ f_single_out = NewFile(filen, "w", SWIG_output_files());
+ if (!f_single_out) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ emitBanner(f_single_out);
+ }
+ return f_single_out;
+ } else {
+ String *filen = NewStringf("%s%s.cs", dir, name);
+ File *f = NewFile(filen, "w", SWIG_output_files());
+ if (!f) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ emitBanner(f);
+ return f;
+ }
+ }
+
+ /*-----------------------------------------------------------------------
+ * Add new director upcall signature
+ *----------------------------------------------------------------------*/
+
+ UpcallData *addUpcallMethod(String *imclass_method, String *class_method, String *decl, String *overloaded_name) {
+ String *key = NewStringf("%s|%s", imclass_method, decl);
+
+ ++curr_class_dmethod;
+
+ String *class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
+ n_dmethods++;
+
+ Hash *new_udata = NewHash();
+ Append(dmethods_seq, new_udata);
+ Setattr(dmethods_table, key, new_udata);
+
+ Setattr(new_udata, "method", Copy(class_method));
+ Setattr(new_udata, "class_methodidx", class_methodidx);
+ Setattr(new_udata, "decl", Copy(decl));
+ Setattr(new_udata, "overname", Copy(overloaded_name));
+
+ Delete(key);
+ return new_udata;
+ }
+
+ /*-----------------------------------------------------------------------
+ * Get director upcall signature
+ *----------------------------------------------------------------------*/
+
+ /*
+ UpcallData * getUpcallMethodData(String *director_class, String *decl) {
+ String *key = NewStringf("%s|%s", director_class, decl);
+ UpcallData *udata = Getattr(dmethods_table, key);
+
+ Delete(key);
+ return udata;
+ }
+ */
+
+ /* ----------------------------------------------------------------------
+ * nativeWrapper()
+ * ---------------------------------------------------------------------- */
+
+ virtual int nativeWrapper(Node *n) {
+ String *wrapname = Getattr(n, "wrap:name");
+
+ if (!addSymbol(wrapname, n, imclass_name))
+ return SWIG_ERROR;
+
+ if (Getattr(n, "type")) {
+ Swig_save("nativeWrapper", n, "name", NIL);
+ Setattr(n, "name", wrapname);
+ native_function_flag = true;
+ functionWrapper(n);
+ Swig_restore(n);
+ native_function_flag = false;
+ } else {
+ Swig_error(input_file, line_number, "No return type for %%native method %s.\n", Getattr(n, "wrap:name"));
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * functionWrapper()
+ * ---------------------------------------------------------------------- */
+
+ virtual int functionWrapper(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ int i;
+ String *c_return_type = NewString("");
+ String *im_return_type = NewString("");
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ String *body = NewString("");
+ String *im_outattributes = 0;
+ int num_arguments = 0;
+ bool is_void_return;
+ String *overloaded_name = getOverloadedName(n);
+
+ if (!Getattr(n, "sym:overloaded")) {
+ if (!addSymbol(symname, n, imclass_name))
+ return SWIG_ERROR;
+ }
+
+ /*
+ The rest of this function deals with generating the intermediary class wrapper function (that wraps
+ a c/c++ function) and generating the PInvoke c code. Each C# wrapper function has a
+ matching PInvoke c function call.
+ */
+
+ // A new wrapper function object
+ Wrapper *f = NewWrapper();
+
+ // Make a wrapper name for this function
+ String *wname = Swig_name_wrapper(overloaded_name);
+
+ /* Attach the non-standard typemaps to the parameter list. */
+ Swig_typemap_attach_parms("ctype", l, f);
+ Swig_typemap_attach_parms("imtype", l, f);
+
+ /* Get return types */
+ if ((tm = Swig_typemap_lookup("ctype", n, "", 0))) {
+ String *ctypeout = Getattr(n, "tmap:ctype:out"); // the type in the ctype typemap's out attribute overrides the type in the typemap
+ if (ctypeout)
+ tm = ctypeout;
+ Printf(c_return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ if ((tm = Swig_typemap_lookup("imtype", n, "", 0))) {
+ String *imtypeout = Getattr(n, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap
+ if (imtypeout)
+ tm = imtypeout;
+ Printf(im_return_type, "%s", tm);
+ im_outattributes = Getattr(n, "tmap:imtype:outattributes");
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ is_void_return = (Cmp(c_return_type, "void") == 0);
+ if (!is_void_return)
+ Wrapper_add_localv(f, "jresult", c_return_type, "jresult", NIL);
+
+ Printv(f->def, " SWIGEXPORT ", c_return_type, " SWIGSTDCALL ", wname, "(", NIL);
+
+ // Emit all of the local variables for holding arguments.
+ emit_parameter_variables(l, f);
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+
+ // Parameter overloading
+ Setattr(n, "wrap:parms", l);
+ Setattr(n, "wrap:name", wname);
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
+ if (Getattr(n, "sym:overloaded")) {
+ // Emit warnings for the few cases that can't be overloaded in C# and give up on generating wrapper
+ Swig_overload_check(n);
+ if (Getattr(n, "overload:ignore")) {
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+ }
+
+ Printv(imclass_class_code, "\n [global::System.Runtime.InteropServices.DllImport(\"", dllimport, "\", EntryPoint=\"", wname, "\")]\n", NIL);
+
+ if (im_outattributes)
+ Printf(imclass_class_code, " %s\n", im_outattributes);
+
+ Printf(imclass_class_code, " public static extern %s %s(", im_return_type, overloaded_name);
+
+
+ /* Get number of required and total arguments */
+ num_arguments = emit_num_arguments(l);
+ int gencomma = 0;
+
+ // Now walk the function parameter list and generate code to get arguments
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+ String *im_param_type = NewString("");
+ String *c_param_type = NewString("");
+ String *arg = NewString("");
+
+ Printf(arg, "j%s", ln);
+
+ /* Get the ctype types of the parameter */
+ if ((tm = Getattr(p, "tmap:ctype"))) {
+ Printv(c_param_type, tm, NIL);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Get the intermediary class parameter types of the parameter */
+ if ((tm = Getattr(p, "tmap:imtype"))) {
+ const String *inattributes = Getattr(p, "tmap:imtype:inattributes");
+ Printf(im_param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to intermediary class method */
+ if (gencomma)
+ Printf(imclass_class_code, ", ");
+ Printf(imclass_class_code, "%s %s", im_param_type, arg);
+
+ // Add parameter to C function
+ Printv(f->def, gencomma ? ", " : "", c_param_type, " ", arg, NIL);
+
+ gencomma = 1;
+
+ // Get typemap for this argument
+ if ((tm = Getattr(p, "tmap:in"))) {
+ canThrow(n, "in", p);
+ Replaceall(tm, "$source", arg); /* deprecated */
+ Replaceall(tm, "$target", ln); /* deprecated */
+ Replaceall(tm, "$arg", arg); /* deprecated? */
+ Replaceall(tm, "$input", arg);
+ Setattr(p, "emit:input", arg);
+ Printf(f->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(pt, 0));
+ p = nextSibling(p);
+ }
+ Delete(im_param_type);
+ Delete(c_param_type);
+ Delete(arg);
+ }
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ canThrow(n, "check", p);
+ Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */
+ Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ canThrow(n, "freearg", p);
+ Replaceall(tm, "$source", Getattr(p, "emit:input")); /* deprecated */
+ Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert argument output code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ canThrow(n, "argout", p);
+ Replaceall(tm, "$source", Getattr(p, "emit:input")); /* deprecated */
+ Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */
+ Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Look for usage of throws typemap and the canthrow flag
+ ParmList *throw_parm_list = NULL;
+ if ((throw_parm_list = Getattr(n, "catchlist"))) {
+ Swig_typemap_attach_parms("throws", throw_parm_list, f);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ canThrow(n, "throws", p);
+ }
+ }
+ }
+
+ String *null_attribute = 0;
+ // Now write code to make the function call
+ if (!native_function_flag) {
+
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ /* Return value if necessary */
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ canThrow(n, "out", n);
+ Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */
+ Replaceall(tm, "$target", "jresult"); /* deprecated */
+ Replaceall(tm, "$result", "jresult");
+
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "1");
+ else
+ Replaceall(tm, "$owner", "0");
+
+ Printf(f->code, "%s", tm);
+ null_attribute = Getattr(n, "tmap:out:null");
+ if (Len(tm))
+ Printf(f->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(t, 0), Getattr(n, "name"));
+ }
+ emit_return_variable(n, t, f);
+ }
+
+ /* Output argument output code */
+ Printv(f->code, outarg, NIL);
+
+ /* Output cleanup code */
+ Printv(f->code, cleanup, NIL);
+
+ /* Look to see if there is any newfree cleanup code */
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ canThrow(n, "newfree", n);
+ Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if (!native_function_flag) {
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ canThrow(n, "ret", n);
+ Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* Finish C function and intermediary class function definitions */
+ Printf(imclass_class_code, ")");
+ Printf(imclass_class_code, ";\n");
+
+ Printf(f->def, ") {");
+
+ if (!is_void_return)
+ Printv(f->code, " return jresult;\n", NIL);
+ Printf(f->code, "}\n");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", symname);
+
+ /* Contract macro modification */
+ if (Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ") > 0) {
+ Setattr(n, "csharp:canthrow", "1");
+ }
+
+ if (!null_attribute)
+ Replaceall(f->code, "$null", "0");
+ else
+ Replaceall(f->code, "$null", null_attribute);
+
+ /* Dump the function out */
+ if (!native_function_flag) {
+ Wrapper_print(f, f_wrappers);
+
+ // Handle %csexception which sets the canthrow attribute
+ if (Getattr(n, "feature:except:canthrow"))
+ Setattr(n, "csharp:canthrow", "1");
+
+ // A very simple check (it is not foolproof) to help typemap/feature writers for
+ // throwing C# exceptions from unmanaged code. It checks for the common methods which
+ // set a pending C# exception... the 'canthrow' typemap/feature attribute must be set
+ // so that code which checks for pending exceptions is added in the C# proxy method.
+ if (!Getattr(n, "csharp:canthrow")) {
+ if (Strstr(f->code, "SWIG_exception")) {
+ Swig_warning(WARN_CSHARP_CANTHROW, input_file, line_number,
+ "Unmanaged code contains a call to SWIG_exception and C# code does not handle pending exceptions via the canthrow attribute.\n");
+ } else if (Strstr(f->code, "SWIG_CSharpSetPendingException")) {
+ Swig_warning(WARN_CSHARP_CANTHROW, input_file, line_number,
+ "Unmanaged code contains a call to a SWIG_CSharpSetPendingException method and C# code does not handle pending exceptions via the canthrow attribute.\n");
+ }
+ }
+ }
+
+ if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
+ moduleClassFunctionHandler(n);
+ }
+
+ /*
+ * Generate the proxy class properties for public member variables.
+ * Not for enums and constants.
+ */
+ if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
+ // Capitalize the first letter in the variable in the getter/setter function name
+ bool getter_flag = Cmp(symname, Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) != 0;
+
+ String *getter_setter_name = NewString("");
+ if (!getter_flag)
+ Printf(getter_setter_name, "set");
+ else
+ Printf(getter_setter_name, "get");
+ Putc(toupper((int) *Char(variable_name)), getter_setter_name);
+ Printf(getter_setter_name, "%s", Char(variable_name) + 1);
+
+ Setattr(n, "proxyfuncname", getter_setter_name);
+ Setattr(n, "imfuncname", symname);
+
+ proxyClassFunctionHandler(n);
+ Delete(getter_setter_name);
+ }
+
+ Delete(c_return_type);
+ Delete(im_return_type);
+ Delete(cleanup);
+ Delete(outarg);
+ Delete(body);
+ Delete(overloaded_name);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * variableWrapper()
+ * ----------------------------------------------------------------------- */
+
+ virtual int variableWrapper(Node *n) {
+ Language::variableWrapper(n);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * globalvariableHandler()
+ * ------------------------------------------------------------------------ */
+
+ virtual int globalvariableHandler(Node *n) {
+
+ generate_property_declaration_flag = true;
+ variable_name = Getattr(n, "sym:name");
+ global_variable_flag = true;
+ int ret = Language::globalvariableHandler(n);
+ global_variable_flag = false;
+ generate_property_declaration_flag = false;
+
+ if (proxy_flag) {
+ Printf(module_class_code, "\n }\n\n");
+ }
+
+ return ret;
+ }
+
+ String *getCurrentScopeName(String *nspace) {
+ String *scope = 0;
+ if (nspace || getCurrentClass()) {
+ scope = NewString("");
+ if (nspace)
+ Printf(scope, "%s", nspace);
+ if (Node *cls = getCurrentClass()) {
+ if (Node *outer = Getattr(cls, "nested:outer")) {
+ String *outerClassesPrefix = Copy(Getattr(outer, "sym:name"));
+ for (outer = Getattr(outer, "nested:outer"); outer != 0; outer = Getattr(outer, "nested:outer")) {
+ Push(outerClassesPrefix, ".");
+ Push(outerClassesPrefix, Getattr(outer, "sym:name"));
+ }
+ Printv(scope, nspace ? "." : "", outerClassesPrefix, ".", proxy_class_name, NIL);
+ Delete(outerClassesPrefix);
+ } else
+ Printv(scope, nspace ? "." : "", proxy_class_name, NIL);
+ }
+ }
+ return scope;
+ }
+
+ /* ----------------------------------------------------------------------
+ * enumDeclaration()
+ *
+ * C/C++ enums can be mapped in one of 4 ways, depending on the cs:enum feature specified:
+ * 1) Simple enums - simple constant within the proxy class or module class
+ * 2) Typeunsafe enums - simple constant in a C# class (class named after the c++ enum name)
+ * 3) Typesafe enum - typesafe enum pattern (class named after the c++ enum name)
+ * 4) Proper enums - proper C# enum
+ * Anonymous enums always default to 1)
+ * ---------------------------------------------------------------------- */
+
+ virtual int enumDeclaration(Node *n) {
+
+ if (!ImportMode) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ String *nspace = Getattr(n, "sym:nspace"); // NSpace/getNSpace() only works during Language::enumDeclaration call
+ if (proxy_flag && !is_wrapping_class()) {
+ // Global enums / enums in a namespace
+ assert(!full_imclass_name);
+
+ if (!nspace) {
+ full_imclass_name = NewStringf("%s", imclass_name);
+ } else {
+ if (namespce) {
+ full_imclass_name = NewStringf("%s.%s", namespce, imclass_name);
+ } else {
+ full_imclass_name = NewStringf("%s", imclass_name);
+ }
+ }
+ }
+
+ enum_code = NewString("");
+ String *symname = Getattr(n, "sym:name");
+ String *constants_code = (proxy_flag && is_wrapping_class())? proxy_class_constants_code : module_class_constants_code;
+ EnumFeature enum_feature = decodeEnumFeature(n);
+ String *typemap_lookup_type = Getattr(n, "name");
+
+ if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
+ // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum
+
+ String *scope = getCurrentScopeName(nspace);
+ if (!addSymbol(symname, n, scope))
+ return SWIG_ERROR;
+
+ // Pure C# baseclass and interfaces
+ const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE);
+ const String *pure_interfaces = typemapLookup(n, "csinterfaces", typemap_lookup_type, WARN_NONE);
+
+ // Class attributes
+ const String *csattributes = typemapLookup(n, "csattributes", typemap_lookup_type, WARN_NONE);
+ if (csattributes && *Char(csattributes))
+ Printf(enum_code, "%s\n", csattributes);
+
+ // Emit the enum
+ Printv(enum_code, typemapLookup(n, "csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers (enum modifiers really)
+ " ", symname, (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass, ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces
+ ", " : "", pure_interfaces, " {\n", NIL);
+ Delete(scope);
+ } else {
+ // Wrap C++ enum with integers - just indicate start of enum with a comment, no comment for anonymous enums of any sort
+ if (symname && !Getattr(n, "unnamedinstance"))
+ Printf(constants_code, " // %s \n", symname);
+ }
+
+ // Emit each enum item
+ Language::enumDeclaration(n);
+
+ if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
+ // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum
+ // Finish the enum declaration
+ // Typemaps are used to generate the enum definition in a similar manner to proxy classes.
+ Printv(enum_code, (enum_feature == ProperEnum) ? "\n" : typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
+ typemapLookup(n, "cscode", typemap_lookup_type, WARN_NONE), // extra C# code
+ "}", NIL);
+
+ Replaceall(enum_code, "$csclassname", symname);
+
+ // Substitute $enumvalues - intended usage is for typesafe enums
+ if (Getattr(n, "enumvalues"))
+ Replaceall(enum_code, "$enumvalues", Getattr(n, "enumvalues"));
+ else
+ Replaceall(enum_code, "$enumvalues", "");
+
+ if (proxy_flag && is_wrapping_class()) {
+ // Enums defined within the C++ class are defined within the proxy class
+
+ // Add extra indentation
+ Replaceall(enum_code, "\n", "\n ");
+ Replaceall(enum_code, " \n", "\n");
+
+ Printv(proxy_class_constants_code, " ", enum_code, "\n\n", NIL);
+ } else {
+ // Global enums are defined in their own file
+ String *output_directory = outputDirectory(nspace);
+ File *f_enum = getOutputFile(output_directory, symname);
+
+ addOpenNamespace(nspace, f_enum);
+
+ Printv(f_enum, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements
+ "\n", enum_code, "\n", NIL);
+
+ addCloseNamespace(nspace, f_enum);
+ if (f_enum != f_single_out)
+ Delete(f_enum);
+ f_enum = NULL;
+ Delete(output_directory);
+ }
+ } else {
+ // Wrap C++ enum with simple constant
+ Printf(enum_code, "\n");
+ if (proxy_flag && is_wrapping_class())
+ Printv(proxy_class_constants_code, enum_code, NIL);
+ else
+ Printv(module_class_constants_code, enum_code, NIL);
+ }
+
+ Delete(enum_code);
+ enum_code = NULL;
+
+ if (proxy_flag && !is_wrapping_class()) {
+ Delete(full_imclass_name);
+ full_imclass_name = 0;
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * enumvalueDeclaration()
+ * ---------------------------------------------------------------------- */
+
+ virtual int enumvalueDeclaration(Node *n) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
+ String *symname = Getattr(n, "sym:name");
+ String *value = Getattr(n, "value");
+ String *name = Getattr(n, "name");
+ Node *parent = parentNode(n);
+ int unnamedinstance = GetFlag(parent, "unnamedinstance");
+ String *parent_name = Getattr(parent, "name");
+ String *nspace = getNSpace();
+ String *newsymname = 0;
+ String *tmpValue;
+
+ // Strange hack from parent method
+ if (value)
+ tmpValue = NewString(value);
+ else
+ tmpValue = NewString(name);
+ // Note that this is used in enumValue() amongst other places
+ Setattr(n, "value", tmpValue);
+
+ // Deal with enum values that are not int
+ int swigtype = SwigType_type(Getattr(n, "type"));
+ if (swigtype == T_BOOL) {
+ const char *val = Equal(Getattr(n, "enumvalue"), "true") ? "1" : "0";
+ Setattr(n, "enumvalue", val);
+ } else if (swigtype == T_CHAR) {
+ String *val = NewStringf("'%(hexescape)s'", Getattr(n, "enumvalue"));
+ Setattr(n, "enumvalue", val);
+ Delete(val);
+ }
+
+ {
+ EnumFeature enum_feature = decodeEnumFeature(parent);
+
+ if ((enum_feature == SimpleEnum) && GetFlag(parent, "scopedenum")) {
+ newsymname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
+ symname = newsymname;
+ }
+
+ // Add to language symbol table
+ String *scope = 0;
+ if (unnamedinstance || !parent_name || enum_feature == SimpleEnum) {
+ String *enumClassPrefix = getEnumClassPrefix();
+ if (enumClassPrefix) {
+ scope = NewString("");
+ if (nspace)
+ Printf(scope, "%s.", nspace);
+ Printf(scope, "%s", enumClassPrefix);
+ } else {
+ scope = Copy(module_class_name);
+ }
+ } else {
+ scope = getCurrentScopeName(nspace);
+ if (!scope)
+ scope = Copy(Getattr(parent, "sym:name"));
+ else
+ Printf(scope, ".%s", Getattr(parent, "sym:name"));
+ }
+ if (!addSymbol(symname, n, scope))
+ return SWIG_ERROR;
+
+ const String *csattributes = Getattr(n, "feature:cs:attributes");
+
+ if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) {
+ // Wrap (non-anonymous) C/C++ enum with a proper C# enum
+ // Emit the enum item.
+ if (!GetFlag(n, "firstenumitem"))
+ Printf(enum_code, ",\n");
+
+ if (csattributes)
+ Printf(enum_code, " %s\n", csattributes);
+
+ Printf(enum_code, " %s", symname);
+
+ // Check for the %csconstvalue feature
+ String *value = Getattr(n, "feature:cs:constvalue");
+
+ // Note that the enum value must be a true constant and cannot be set from a PINVOKE call, thus no support for %csconst(0)
+ value = value ? value : Getattr(n, "enumvalue");
+ if (value) {
+ Printf(enum_code, " = %s", value);
+ }
+ } else {
+ // Wrap C/C++ enums with constant integers or use the typesafe enum pattern
+ SwigType *typemap_lookup_type = parent_name ? parent_name : NewString("enum ");
+ Setattr(n, "type", typemap_lookup_type);
+ const String *tm = typemapLookup(n, "cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF);
+
+ String *return_type = Copy(tm);
+ substituteClassname(typemap_lookup_type, return_type);
+ const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ if (csattributes)
+ Printf(enum_code, " %s\n", csattributes);
+
+ if ((enum_feature == TypesafeEnum) && parent_name && !unnamedinstance) {
+ // Wrap (non-anonymous) enum using the typesafe enum pattern
+ if (Getattr(n, "enumvalue")) {
+ String *value = enumValue(n);
+ Printf(enum_code, " %s static readonly %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value);
+ Delete(value);
+ } else {
+ Printf(enum_code, " %s static readonly %s %s = new %s(\"%s\");\n", methodmods, return_type, symname, return_type, symname);
+ }
+ } else {
+ // Simple integer constants
+ // Note these are always generated for anonymous enums, no matter what enum_feature is specified
+ // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later
+
+ // The %csconst feature determines how the constant value is obtained
+ int const_feature_flag = GetFlag(n, "feature:cs:const");
+
+ const char *const_readonly = const_feature_flag ? "const" : "static readonly";
+ String *value = enumValue(n);
+ Printf(enum_code, " %s %s %s %s = %s;\n", methodmods, const_readonly, return_type, symname, value);
+ Delete(value);
+ }
+ Delete(return_type);
+ }
+
+ // Add the enum value to the comma separated list being constructed in the enum declaration.
+ String *enumvalues = Getattr(parent, "enumvalues");
+ if (!enumvalues)
+ Setattr(parent, "enumvalues", Copy(symname));
+ else
+ Printv(enumvalues, ", ", symname, NIL);
+ Delete(scope);
+ }
+
+ Delete(newsymname);
+ Delete(tmpValue);
+ Swig_restore(n);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * constantWrapper()
+ * Used for wrapping constants - #define or %constant.
+ * Also for inline initialised const static primitive type member variables (short, int, double, enums etc).
+ * C# static const variables are generated for these.
+ * If the %csconst(1) feature is used then the C constant value is used to initialise the C# const variable.
+ * If not, a PINVOKE method is generated to get the C constant value for initialisation of the C# const variable.
+ * However, if the %csconstvalue feature is used, it overrides all other ways to generate the initialisation.
+ * Also note that this method might be called for wrapping enum items (when the enum is using %csconst(0)).
+ * ------------------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+ SwigType *valuetype = Getattr(n, "valuetype");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ String *return_type = NewString("");
+ String *constants_code = NewString("");
+ Swig_save("constantWrapper", n, "value", NIL);
+ Swig_save("constantWrapper", n, "tmap:ctype:out", "tmap:imtype:out", "tmap:cstype:out", "tmap:out:null", "tmap:imtype:outattributes", "tmap:cstype:outattributes", NIL);
+
+ bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
+
+ const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname;
+ if (!is_enum_item) {
+ String *scope = 0;
+ if (proxy_class_name) {
+ String *nspace = getNSpace();
+ scope = NewString("");
+ if (nspace)
+ Printf(scope, "%s.", nspace);
+ Printf(scope, "%s", proxy_class_name);
+ } else {
+ scope = Copy(module_class_name);
+ }
+ if (!addSymbol(itemname, n, scope))
+ return SWIG_ERROR;
+ Delete(scope);
+ }
+
+ // The %csconst feature determines how the constant value is obtained
+ int const_feature_flag = GetFlag(n, "feature:cs:const");
+
+ /* Adjust the enum type for the Swig_typemap_lookup.
+ * We want the same jstype typemap for all the enum items so we use the enum type (parent node). */
+ if (is_enum_item) {
+ t = Getattr(parentNode(n), "enumtype");
+ Setattr(n, "type", t);
+ }
+
+ /* Attach the non-standard typemaps to the parameter list. */
+ Swig_typemap_attach_parms("cstype", l, NULL);
+
+ /* Get C# return types */
+ bool classname_substituted_flag = false;
+
+ if ((tm = Swig_typemap_lookup("cstype", n, "", 0))) {
+ String *cstypeout = Getattr(n, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
+ if (cstypeout)
+ tm = cstypeout;
+ classname_substituted_flag = substituteClassname(t, tm);
+ Printf(return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ // Default (octal) escaping is no good - change to hex escaped value
+ String *hexescaped_value = Getattr(n, "rawvalue") ? NewStringf("%(hexescape)s", Getattr(n, "rawvalue")) : 0;
+ // Add the stripped quotes back in
+ String *new_value = NewString("");
+ if (SwigType_type(t) == T_STRING) {
+ Printf(new_value, "\"%s\"", hexescaped_value ? hexescaped_value : Copy(Getattr(n, "value")));
+ Setattr(n, "value", new_value);
+ } else if (SwigType_type(t) == T_CHAR) {
+ Printf(new_value, "\'%s\'", hexescaped_value ? hexescaped_value : Copy(Getattr(n, "value")));
+ Setattr(n, "value", new_value);
+ }
+
+ const String *outattributes = Getattr(n, "tmap:cstype:outattributes");
+ if (outattributes)
+ Printf(constants_code, " %s\n", outattributes);
+
+ const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ Printf(constants_code, " %s %s %s %s = ", methodmods, (const_feature_flag ? "const" : "static readonly"), return_type, itemname);
+
+ // Check for the %csconstvalue feature
+ String *value = Getattr(n, "feature:cs:constvalue");
+
+ if (value) {
+ Printf(constants_code, "%s;\n", value);
+ } else if (!const_feature_flag) {
+ // Default enum and constant handling will work with any type of C constant and initialises the C# variable from C through a PINVOKE call.
+
+ if (classname_substituted_flag) {
+ if (SwigType_isenum(t)) {
+ // This handles wrapping of inline initialised const enum static member variables (not when wrapping enum items - ignored later on)
+ Printf(constants_code, "(%s)%s.%s();\n", return_type, full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
+ } else {
+ // This handles function pointers using the %constant directive
+ Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
+ }
+ } else {
+ Printf(constants_code, "%s.%s();\n", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
+ }
+
+ // Each constant and enum value is wrapped with a separate PInvoke function call
+ SetFlag(n, "feature:immutable");
+ enum_constant_flag = true;
+ variableWrapper(n);
+ enum_constant_flag = false;
+ } else {
+ // Alternative constant handling will use the C syntax to make a true C# constant and hope that it compiles as C# code
+ if (Getattr(n, "wrappedasconstant")) {
+ if (SwigType_type(t) == T_CHAR) {
+ if (SwigType_type(valuetype) == T_CHAR)
+ Printf(constants_code, "\'%(hexescape)s\';\n", Getattr(n, "staticmembervariableHandler:value"));
+ else
+ Printf(constants_code, "(char)%s;\n", Getattr(n, "staticmembervariableHandler:value"));
+ } else {
+ Printf(constants_code, "%s;\n", Getattr(n, "staticmembervariableHandler:value"));
+ }
+ } else {
+ Printf(constants_code, "%s;\n", Getattr(n, "value"));
+ }
+ }
+
+ // Emit the generated code to appropriate place
+ // Enums only emit the intermediate and PINVOKE methods, so no proxy or module class wrapper methods needed
+ if (!is_enum_item) {
+ if (proxy_flag && wrapping_member_flag)
+ Printv(proxy_class_constants_code, constants_code, NIL);
+ else
+ Printv(module_class_constants_code, constants_code, NIL);
+ }
+ // Cleanup
+ Swig_restore(n);
+ Delete(new_value);
+ Delete(return_type);
+ Delete(constants_code);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * insertDirective()
+ * ----------------------------------------------------------------------------- */
+
+ virtual int insertDirective(Node *n) {
+ int ret = SWIG_OK;
+ String *code = Getattr(n, "code");
+ String *section = Getattr(n, "section");
+ Replaceall(code, "$module", module_class_name);
+ Replaceall(code, "$imclassname", imclass_name);
+ Replaceall(code, "$dllimport", dllimport);
+
+ if (!ImportMode && (Cmp(section, "proxycode") == 0)) {
+ if (proxy_class_code) {
+ Swig_typemap_replace_embedded_typemap(code, n);
+ int offset = Len(code) > 0 && *Char(code) == '\n' ? 1 : 0;
+ Printv(proxy_class_code, Char(code) + offset, "\n", NIL);
+ }
+ } else {
+ ret = Language::insertDirective(n);
+ }
+ return ret;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * pragmaDirective()
+ *
+ * Valid Pragmas:
+ * imclassbase - base (extends) for the intermediary class
+ * imclassclassmodifiers - class modifiers for the intermediary class
+ * imclasscode - text (C# code) is copied verbatim to the intermediary class
+ * imclassimports - import statements for the intermediary class
+ * imclassinterfaces - interface (implements) for the intermediary class
+ *
+ * modulebase - base (extends) for the module class
+ * moduleclassmodifiers - class modifiers for the module class
+ * modulecode - text (C# code) is copied verbatim to the module class
+ * moduleimports - import statements for the module class
+ * moduleinterfaces - interface (implements) for the module class
+ *
+ * ----------------------------------------------------------------------------- */
+
+ virtual int pragmaDirective(Node *n) {
+ if (!ImportMode) {
+ String *lang = Getattr(n, "lang");
+ String *code = Getattr(n, "name");
+ String *value = Getattr(n, "value");
+
+ if (Strcmp(lang, "csharp") == 0) {
+
+ String *strvalue = NewString(value);
+ Replaceall(strvalue, "\\\"", "\"");
+
+ if (Strcmp(code, "imclassbase") == 0) {
+ Delete(imclass_baseclass);
+ imclass_baseclass = Copy(strvalue);
+ } else if (Strcmp(code, "imclassclassmodifiers") == 0) {
+ Delete(imclass_class_modifiers);
+ imclass_class_modifiers = Copy(strvalue);
+ } else if (Strcmp(code, "imclasscode") == 0) {
+ Printf(imclass_class_code, "%s\n", strvalue);
+ } else if (Strcmp(code, "imclassimports") == 0) {
+ Delete(imclass_imports);
+ imclass_imports = Copy(strvalue);
+ } else if (Strcmp(code, "imclassinterfaces") == 0) {
+ Delete(imclass_interfaces);
+ imclass_interfaces = Copy(strvalue);
+ } else if (Strcmp(code, "modulebase") == 0) {
+ Delete(module_baseclass);
+ module_baseclass = Copy(strvalue);
+ } else if (Strcmp(code, "moduleclassmodifiers") == 0) {
+ Delete(module_class_modifiers);
+ module_class_modifiers = Copy(strvalue);
+ } else if (Strcmp(code, "modulecode") == 0) {
+ Printf(module_class_code, "%s\n", strvalue);
+ } else if (Strcmp(code, "moduleimports") == 0) {
+ Delete(module_imports);
+ module_imports = Copy(strvalue);
+ } else if (Strcmp(code, "moduleinterfaces") == 0) {
+ Delete(module_interfaces);
+ module_interfaces = Copy(strvalue);
+ } else {
+ Swig_error(input_file, line_number, "Unrecognized pragma.\n");
+ }
+ Delete(strvalue);
+ }
+ }
+ return Language::pragmaDirective(n);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getQualifiedInterfaceName()
+ * ----------------------------------------------------------------------------- */
+
+ String *getQualifiedInterfaceName(Node *n) {
+ String *ret = Getattr(n, "interface:qname");
+ if (!ret) {
+ String *nspace = Getattr(n, "sym:nspace");
+ String *interface_name = Getattr(n, "interface:name");
+ if (nspace) {
+ if (namespce)
+ ret = NewStringf("%s.%s.%s", namespce, nspace, interface_name);
+ else
+ ret = NewStringf("%s.%s", nspace, interface_name);
+ } else {
+ ret = Copy(interface_name);
+ }
+ Setattr(n, "interface:qname", ret);
+ }
+ return ret;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getInterfaceName()
+ * ----------------------------------------------------------------------------- */
+
+ String *getInterfaceName(SwigType *t, bool qualified) {
+ String *interface_name = NULL;
+ if (proxy_flag) {
+ Node *n = classLookup(t);
+ if (n && Getattr(n, "interface:name"))
+ interface_name = qualified ? getQualifiedInterfaceName(n) : Getattr(n, "interface:name");
+ }
+ return interface_name;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addInterfaceNameAndUpcasts()
+ * ----------------------------------------------------------------------------- */
+
+ void addInterfaceNameAndUpcasts(SwigType *smart, String *interface_list, String *interface_upcasts, Hash *base_list, SwigType *c_classname) {
+ List *keys = Keys(base_list);
+ for (Iterator it = First(keys); it.item; it = Next(it)) {
+ Node *base = Getattr(base_list, it.item);
+ SwigType *c_baseclassname = Getattr(base, "name");
+ String *interface_name = Getattr(base, "interface:name");
+ if (Len(interface_list))
+ Append(interface_list, ", ");
+ Append(interface_list, interface_name);
+
+ Node *attributes = NewHash();
+ String *interface_code = Copy(typemapLookup(base, "csinterfacecode", Getattr(base, "classtypeobj"), WARN_CSHARP_TYPEMAP_INTERFACECODE_UNDEF, attributes));
+ String *cptr_method_name = 0;
+ if (interface_code) {
+ Replaceall(interface_code, "$interfacename", interface_name);
+ Printv(interface_upcasts, interface_code, NIL);
+ cptr_method_name = Copy(Getattr(attributes, "tmap:csinterfacecode:cptrmethod"));
+ }
+ if (!cptr_method_name)
+ cptr_method_name = NewStringf("%s_GetInterfaceCPtr", interface_name);
+ Replaceall(cptr_method_name, ".", "_");
+ Replaceall(cptr_method_name, "$interfacename", interface_name);
+
+ String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), cptr_method_name);
+ upcastsCode(smart, upcast_method_name, c_classname, c_baseclassname);
+
+ Delete(upcast_method_name);
+ Delete(cptr_method_name);
+ Delete(interface_code);
+ }
+ Delete(keys);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * upcastsCode()
+ *
+ * Add code for C++ casting to base class
+ * ----------------------------------------------------------------------------- */
+
+ void upcastsCode(SwigType *smart, String *upcast_method_name, SwigType *c_classname, SwigType *c_baseclassname) {
+ String *wname = Swig_name_wrapper(upcast_method_name);
+
+ Printv(imclass_cppcasts_code, "\n [global::System.Runtime.InteropServices.DllImport(\"", dllimport, "\", EntryPoint=\"", wname, "\")]\n", NIL);
+ Printf(imclass_cppcasts_code, " public static extern global::System.IntPtr %s(global::System.IntPtr jarg1);\n", upcast_method_name);
+
+ Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name);
+
+ String *classname = SwigType_namestr(c_classname);
+ String *baseclassname = SwigType_namestr(c_baseclassname);
+ if (smart) {
+ String *smartnamestr = SwigType_namestr(smart);
+ String *bsmartnamestr = SwigType_namestr(smart);
+
+ // TODO: SwigType_typedef_resolve_all on a String instead of SwigType is incorrect for templates
+ SwigType *rclassname = SwigType_typedef_resolve_all(classname);
+ SwigType *rbaseclassname = SwigType_typedef_resolve_all(baseclassname);
+ Replaceall(bsmartnamestr, rclassname, rbaseclassname);
+
+ Printv(upcasts_code,
+ "SWIGEXPORT ", bsmartnamestr, " * SWIGSTDCALL ", wname, "(", smartnamestr, " *jarg1) {\n",
+ " return jarg1 ? new ", bsmartnamestr, "(*jarg1) : 0;\n"
+ "}\n", "\n", NIL);
+
+ Delete(rbaseclassname);
+ Delete(rclassname);
+ Delete(bsmartnamestr);
+ Delete(smartnamestr);
+ } else {
+ Printv(upcasts_code,
+ "SWIGEXPORT ", baseclassname, " * SWIGSTDCALL ", wname, "(", classname, " *jarg1) {\n",
+ " return (", baseclassname, " *)jarg1;\n"
+ "}\n", "\n", NIL);
+ }
+
+ Delete(baseclassname);
+ Delete(classname);
+ Delete(wname);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * emitProxyClassDefAndCPPCasts()
+ * ----------------------------------------------------------------------------- */
+
+ void emitProxyClassDefAndCPPCasts(Node *n) {
+ SwigType *c_classname = Getattr(n, "name");
+ SwigType *c_baseclassname = NULL;
+ String *baseclass = NULL;
+ String *interface_list = NewStringEmpty();
+ String *interface_upcasts = NewStringEmpty();
+ SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
+ bool feature_director = Swig_directorclass(n) ? true : false;
+ bool has_outerclass = Getattr(n, "nested:outer") != 0 && !GetFlag(n, "feature:flatnested");
+ SwigType *smart = Swig_cparse_smartptr(n);
+
+ // Inheritance from pure C# classes
+ Node *attributes = NewHash();
+ const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE, attributes);
+ bool purebase_replace = GetFlag(attributes, "tmap:csbase:replace") ? true : false;
+ bool purebase_notderived = GetFlag(attributes, "tmap:csbase:notderived") ? true : false;
+ Delete(attributes);
+
+ // C++ inheritance
+ if (!purebase_replace) {
+ List *baselist = Getattr(n, "bases");
+ if (baselist) {
+ Iterator base = First(baselist);
+ while (base.item) {
+ if (!(GetFlag(base.item, "feature:ignore") || Getattr(base.item, "feature:interface"))) {
+ SwigType *baseclassname = Getattr(base.item, "name");
+ if (!c_baseclassname) {
+ String *name = getProxyName(baseclassname);
+ if (name) {
+ c_baseclassname = baseclassname;
+ baseclass = name;
+ }
+ } else {
+ /* Warn about multiple inheritance for additional base class(es) */
+ String *proxyclassname = Getattr(n, "classtypeobj");
+ Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Warning for %s, base %s ignored. Multiple inheritance is not supported in C#.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname));
+ }
+ }
+ base = Next(base);
+ }
+ }
+ }
+ Hash *interface_bases = Getattr(n, "interface:bases");
+ if (interface_bases)
+ addInterfaceNameAndUpcasts(smart, interface_list, interface_upcasts, interface_bases, c_classname);
+
+ bool derived = baseclass != 0;
+ if (derived && purebase_notderived)
+ pure_baseclass = empty_string;
+ const String *wanted_base = baseclass ? baseclass : pure_baseclass;
+
+ if (purebase_replace) {
+ wanted_base = pure_baseclass;
+ derived = false;
+ baseclass = NULL;
+ if (purebase_notderived)
+ Swig_error(Getfile(n), Getline(n), "The csbase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type);
+ } else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
+ Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Warning for %s, base %s ignored. Multiple inheritance is not supported in C#. "
+ "Perhaps you need one of the 'replace' or 'notderived' attributes in the csbase typemap?\n", typemap_lookup_type, pure_baseclass);
+ }
+
+ // Pure C# interfaces
+ const String *pure_interfaces = typemapLookup(n, derived ? "csinterfaces_derived" : "csinterfaces", typemap_lookup_type, WARN_NONE);
+ if (*Char(interface_list) && *Char(pure_interfaces))
+ Append(interface_list, ", ");
+ Append(interface_list, pure_interfaces);
+ // Start writing the proxy class
+ if (!has_outerclass)
+ Printv(proxy_class_def, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements
+ "\n", NIL);
+
+ // Class attributes
+ const String *csattributes = typemapLookup(n, "csattributes", typemap_lookup_type, WARN_NONE);
+ if (csattributes && *Char(csattributes))
+ Printf(proxy_class_def, "%s\n", csattributes);
+
+ Printv(proxy_class_def, typemapLookup(n, "csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
+ " $csclassname", // Class name and base class
+ (*Char(wanted_base) || *Char(interface_list)) ? " : " : "", wanted_base, (*Char(wanted_base) && *Char(interface_list)) ? // Interfaces
+ ", " : "", interface_list, " {", derived ? typemapLookup(n, "csbody_derived", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF) : // main body of class
+ typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
+ NIL);
+
+ // C++ destructor is wrapped by the Finalize and Dispose methods
+
+ const char *tmap_method = derived ? "csdestruct_derived" : "csdestruct";
+ const String *tm = typemapExists(n, tmap_method, typemap_lookup_type);
+ if (tm) {
+ Swig_error(Getfile(tm), Getline(tm),
+ "A deprecated %s typemap was found for %s, please remove it and replace all csdestruct, csdestruct_derived and csfinalize typemaps by the csdispose, csdispose_derived, csdisposing and csdisposing_derived typemaps.\n",
+ tmap_method, proxy_class_name);
+ }
+ tmap_method = "csfinalize";
+ tm = typemapExists(n, tmap_method, typemap_lookup_type);
+ if (tm) {
+ Swig_error(Getfile(tm), Getline(tm),
+ "A deprecated %s typemap was found for %s, please remove it and replace all csdestruct, csdestruct_derived and csfinalize typemaps by the csdispose, csdispose_derived, csdisposing and csdisposing_derived typemaps.\n",
+ tmap_method, proxy_class_name);
+ }
+
+ tmap_method = derived ? "csdisposing_derived" : "csdisposing";
+ String *destruct = NewString("");
+ attributes = NewHash();
+ const String *destruct_methodname = NULL;
+ const String *destruct_methodmodifiers = NULL;
+ const String *destruct_parameters = NULL;
+ if (derived) {
+ tm = typemapLookup(n, "csdisposing_derived", typemap_lookup_type, WARN_NONE, attributes);
+ destruct_methodname = Getattr(attributes, "tmap:csdisposing_derived:methodname");
+ destruct_methodmodifiers = Getattr(attributes, "tmap:csdisposing_derived:methodmodifiers");
+ destruct_parameters = Getattr(attributes, "tmap:csdisposing_derived:parameters");
+ } else {
+ tm = typemapLookup(n, "csdisposing", typemap_lookup_type, WARN_NONE, attributes);
+ destruct_methodname = Getattr(attributes, "tmap:csdisposing:methodname");
+ destruct_methodmodifiers = Getattr(attributes, "tmap:csdisposing:methodmodifiers");
+ destruct_parameters = Getattr(attributes, "tmap:csdisposing:parameters");
+ }
+ if (tm && *Char(tm)) {
+ if (!destruct_methodname) {
+ Swig_error(Getfile(n), Getline(n), "No methodname attribute defined in %s typemap for %s\n", tmap_method, proxy_class_name);
+ }
+ if (!destruct_methodmodifiers) {
+ Swig_error(Getfile(n), Getline(n),
+ "No methodmodifiers attribute defined in %s typemap for %s.\n", tmap_method, proxy_class_name);
+ }
+ if (!destruct_parameters)
+ destruct_parameters = empty_string;
+ }
+ // Emit the Finalize and Dispose methods
+ if (tm) {
+ // Finalize and Dispose methods
+ Printv(proxy_class_def, typemapLookup(n, derived ? "csdispose_derived" : "csdispose", typemap_lookup_type, WARN_NONE), NIL);
+ // Dispose(bool disposing) method
+ Printv(destruct, tm, NIL);
+ if (*Char(destructor_call))
+ Replaceall(destruct, "$imcall", destructor_call);
+ else
+ Replaceall(destruct, "$imcall", "throw new global::System.MethodAccessException(\"C++ destructor does not have public access\")");
+ if (*Char(destruct)) {
+ Printv(proxy_class_def, "\n ", NIL);
+ const String *methodmods = Getattr(n, "destructmethodmodifiers");
+ if (methodmods)
+ Printv(proxy_class_def, methodmods, NIL);
+ else
+ Printv(proxy_class_def, destruct_methodmodifiers, " ", derived ? "override" : "virtual", NIL);
+ Printv(proxy_class_def, " void ", destruct_methodname, "(", destruct_parameters, ") ", destruct, "\n", NIL);
+ }
+ }
+ if (*Char(interface_upcasts))
+ Printv(proxy_class_def, interface_upcasts, NIL);
+
+ if (feature_director) {
+ // Generate director connect method
+ // put this in classDirectorEnd ???
+ Printf(proxy_class_code, " private void SwigDirectorConnect() {\n");
+
+ int i;
+ for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *method = Getattr(udata, "method");
+ String *methid = Getattr(udata, "class_methodidx");
+ String *overname = Getattr(udata, "overname");
+ Printf(proxy_class_code, " if (SwigDerivedClassHasMethod(\"%s\", swigMethodTypes%s))\n", method, methid);
+ Printf(proxy_class_code, " swigDelegate%s = new SwigDelegate%s_%s(SwigDirectorMethod%s);\n", methid, proxy_class_name, methid, overname);
+ }
+ String *director_connect_method_name = Swig_name_member(getNSpace(), getClassPrefix(), "director_connect");
+ Printf(proxy_class_code, " %s.%s(swigCPtr", imclass_name, director_connect_method_name);
+ for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *methid = Getattr(udata, "class_methodidx");
+ Printf(proxy_class_code, ", swigDelegate%s", methid);
+ }
+ Printf(proxy_class_code, ");\n");
+ Printf(proxy_class_code, " }\n");
+
+ if (first_class_dmethod < curr_class_dmethod) {
+ // Only emit if there is at least one director method
+ Printf(proxy_class_code, "\n");
+ Printf(proxy_class_code, " private bool SwigDerivedClassHasMethod(string methodName, global::System.Type[] methodTypes) {\n");
+ Printf(proxy_class_code,
+ " global::System.Reflection.MethodInfo methodInfo = this.GetType().GetMethod(methodName, global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance, null, methodTypes, null);\n");
+ Printf(proxy_class_code, " bool hasDerivedMethod = methodInfo.DeclaringType.IsSubclassOf(typeof(%s));\n", proxy_class_name);
+ /* Could add this code to cover corner case where the GetMethod() returns a method which allows type
+ * promotion, eg it will return foo(double), if looking for foo(int).
+ if (hasDerivedMethod) {
+ hasDerivedMethod = false;
+ if (methodInfo != null)
+ {
+ hasDerivedMethod = true;
+ ParameterInfo[] parameterArray1 = methodInfo.GetParameters();
+ for (int i=0; i<methodTypes.Length; i++)
+ {
+ if (parameterArray1[0].ParameterType != methodTypes[0])
+ {
+ hasDerivedMethod = false;
+ break;
+ }
+ }
+ }
+ }
+ */
+ Printf(proxy_class_code, " return hasDerivedMethod;\n");
+ Printf(proxy_class_code, " }\n");
+ }
+
+ if (Len(director_delegate_callback) > 0)
+ Printv(proxy_class_code, director_delegate_callback, NIL);
+ if (Len(director_delegate_definitions) > 0)
+ Printv(proxy_class_code, "\n", director_delegate_definitions, NIL);
+ if (Len(director_delegate_instances) > 0)
+ Printv(proxy_class_code, "\n", director_delegate_instances, NIL);
+ if (Len(director_method_types) > 0)
+ Printv(proxy_class_code, "\n", director_method_types, NIL);
+
+ Delete(director_callback_typedefs);
+ director_callback_typedefs = NULL;
+ Delete(director_callbacks);
+ director_callbacks = NULL;
+ Delete(director_delegate_callback);
+ director_delegate_callback = NULL;
+ Delete(director_delegate_definitions);
+ director_delegate_definitions = NULL;
+ Delete(director_delegate_instances);
+ director_delegate_instances = NULL;
+ Delete(director_method_types);
+ director_method_types = NULL;
+ Delete(director_connect_parms);
+ director_connect_parms = NULL;
+ Delete(director_connect_method_name);
+ }
+
+ Delete(interface_upcasts);
+ Delete(interface_list);
+ Delete(attributes);
+ Delete(destruct);
+
+ // Emit extra user code
+ Printv(proxy_class_def, typemapLookup(n, "cscode", typemap_lookup_type, WARN_NONE), // extra C# code
+ "\n", NIL);
+
+ if (derived) {
+ String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), smart != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast");
+ upcastsCode(smart, upcast_method_name, c_classname, c_baseclassname);
+ Delete(upcast_method_name);
+ }
+
+ Delete(smart);
+ }
+
+ /* ----------------------------------------------------------------------
+ * emitInterfaceDeclaration()
+ * ---------------------------------------------------------------------- */
+
+ void emitInterfaceDeclaration(Node *n, String *interface_name, File *f_interface) {
+ Printv(f_interface, typemapLookup(n, "csimports", Getattr(n, "classtypeobj"), WARN_NONE), "\n", NIL);
+ Printf(f_interface, "public interface %s", interface_name);
+ if (List *baselist = Getattr(n, "bases")) {
+ String *bases = 0;
+ for (Iterator base = First(baselist); base.item; base = Next(base)) {
+ if (GetFlag(base.item, "feature:ignore") || !Getattr(base.item, "feature:interface"))
+ continue; // TODO: warn about skipped non-interface bases
+ String *base_iname = Getattr(base.item, "interface:name");
+ if (!bases)
+ bases = NewStringf(" : %s", base_iname);
+ else {
+ Append(bases, ", ");
+ Append(bases, base_iname);
+ }
+ }
+ if (bases) {
+ Printv(f_interface, bases, NIL);
+ Delete(bases);
+ }
+ }
+ Printf(f_interface, " {\n");
+
+ Node *attributes = NewHash();
+ String *interface_code = Copy(typemapLookup(n, "csinterfacecode", Getattr(n, "classtypeobj"), WARN_CSHARP_TYPEMAP_INTERFACECODE_UNDEF, attributes));
+ if (interface_code) {
+ String *interface_declaration = Copy(Getattr(attributes, "tmap:csinterfacecode:declaration"));
+ if (interface_declaration) {
+ Replaceall(interface_declaration, "$interfacename", interface_name);
+ Printv(f_interface, interface_declaration, NIL);
+ Delete(interface_declaration);
+ }
+ Delete(interface_code);
+ }
+ }
+
+ /* ----------------------------------------------------------------------
+ * classHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int classHandler(Node *n) {
+ String *nspace = getNSpace();
+ File *f_proxy = NULL;
+ File *f_interface = NULL;
+ // save class local variables
+ String *old_proxy_class_name = proxy_class_name;
+ String *old_full_imclass_name = full_imclass_name;
+ String *old_destructor_call = destructor_call;
+ String *old_proxy_class_constants_code = proxy_class_constants_code;
+ String *old_proxy_class_def = proxy_class_def;
+ String *old_proxy_class_code = proxy_class_code;
+ bool has_outerclass = Getattr(n, "nested:outer") && !GetFlag(n, "feature:flatnested");
+ String *old_interface_class_code = interface_class_code;
+ interface_class_code = 0;
+
+ if (proxy_flag) {
+ proxy_class_name = NewString(Getattr(n, "sym:name"));
+ String *interface_name = Getattr(n, "feature:interface") ? Getattr(n, "interface:name") : 0;
+ if (Node *outer = Getattr(n, "nested:outer")) {
+ String *outerClassesPrefix = Copy(Getattr(outer, "sym:name"));
+ for (outer = Getattr(outer, "nested:outer"); outer != 0; outer = Getattr(outer, "nested:outer")) {
+ Push(outerClassesPrefix, ".");
+ Push(outerClassesPrefix, Getattr(outer, "sym:name"));
+ }
+ String *fnspace = nspace ? NewStringf("%s.%s", nspace, outerClassesPrefix) : outerClassesPrefix;
+ if (!addSymbol(proxy_class_name, n, fnspace))
+ return SWIG_ERROR;
+ if (interface_name && !addInterfaceSymbol(interface_name, n, fnspace))
+ return SWIG_ERROR;
+ if (nspace)
+ Delete(fnspace);
+ Delete(outerClassesPrefix);
+ } else {
+ if (!addSymbol(proxy_class_name, n, nspace))
+ return SWIG_ERROR;
+ if (interface_name && !addInterfaceSymbol(interface_name, n, nspace))
+ return SWIG_ERROR;
+ }
+
+ if (!nspace) {
+ full_imclass_name = NewStringf("%s", imclass_name);
+ if (Cmp(proxy_class_name, imclass_name) == 0) {
+ Printf(stderr, "Class name cannot be equal to intermediary class name: %s\n", proxy_class_name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ if (Cmp(proxy_class_name, module_class_name) == 0) {
+ Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ } else {
+ if (namespce) {
+ full_imclass_name = NewStringf("%s.%s", namespce, imclass_name);
+ } else {
+ full_imclass_name = NewStringf("%s", imclass_name);
+ }
+ }
+
+ if (!has_outerclass) {
+ String *output_directory = outputDirectory(nspace);
+ f_proxy = getOutputFile(output_directory, proxy_class_name);
+
+ addOpenNamespace(nspace, f_proxy);
+ Delete(output_directory);
+ }
+ else
+ ++nesting_depth;
+
+ proxy_class_def = NewString("");
+ proxy_class_code = NewString("");
+ destructor_call = NewString("");
+ proxy_class_constants_code = NewString("");
+
+ if (Getattr(n, "feature:interface")) {
+ interface_class_code = NewString("");
+ String *output_directory = outputDirectory(nspace);
+ f_interface = getOutputFile(output_directory, interface_name);
+ addOpenNamespace(nspace, f_interface);
+ emitInterfaceDeclaration(n, interface_name, interface_class_code);
+ Delete(output_directory);
+ }
+ }
+
+ Language::classHandler(n);
+
+ if (proxy_flag) {
+
+ emitProxyClassDefAndCPPCasts(n);
+
+ String *csclazzname = Swig_name_member(getNSpace(), getClassPrefix(), ""); // mangled full proxy class name
+
+ Replaceall(proxy_class_def, "$csclassname", proxy_class_name);
+ Replaceall(proxy_class_code, "$csclassname", proxy_class_name);
+ Replaceall(proxy_class_constants_code, "$csclassname", proxy_class_name);
+ Replaceall(interface_class_code, "$csclassname", proxy_class_name);
+
+ Replaceall(proxy_class_def, "$csclazzname", csclazzname);
+ Replaceall(proxy_class_code, "$csclazzname", csclazzname);
+ Replaceall(proxy_class_constants_code, "$csclazzname", csclazzname);
+ Replaceall(interface_class_code, "$csclazzname", csclazzname);
+
+ Replaceall(proxy_class_def, "$module", module_class_name);
+ Replaceall(proxy_class_code, "$module", module_class_name);
+ Replaceall(proxy_class_constants_code, "$module", module_class_name);
+ Replaceall(interface_class_code, "$module", module_class_name);
+
+ Replaceall(proxy_class_def, "$imclassname", full_imclass_name);
+ Replaceall(proxy_class_code, "$imclassname", full_imclass_name);
+ Replaceall(proxy_class_constants_code, "$imclassname", full_imclass_name);
+ Replaceall(interface_class_code, "$imclassname", full_imclass_name);
+
+ Replaceall(proxy_class_def, "$dllimport", dllimport);
+ Replaceall(proxy_class_code, "$dllimport", dllimport);
+ Replaceall(proxy_class_constants_code, "$dllimport", dllimport);
+ Replaceall(interface_class_code, "$dllimport", dllimport);
+
+ if (!has_outerclass)
+ Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
+ else {
+ Swig_offset_string(proxy_class_def, nesting_depth);
+ Append(old_proxy_class_code, proxy_class_def);
+ Swig_offset_string(proxy_class_code, nesting_depth);
+ Append(old_proxy_class_code, proxy_class_code);
+ }
+
+ // Write out all the constants
+ if (Len(proxy_class_constants_code) != 0) {
+ if (!has_outerclass)
+ Printv(f_proxy, proxy_class_constants_code, NIL);
+ else {
+ Swig_offset_string(proxy_class_constants_code, nesting_depth);
+ Append(old_proxy_class_code, proxy_class_constants_code);
+ }
+ }
+ if (!has_outerclass) {
+ Printf(f_proxy, "}\n");
+ addCloseNamespace(nspace, f_proxy);
+ if (f_proxy != f_single_out)
+ Delete(f_proxy);
+ f_proxy = NULL;
+ } else {
+ for (int i = 0; i < nesting_depth; ++i)
+ Append(old_proxy_class_code, " ");
+ Append(old_proxy_class_code, "}\n\n");
+ --nesting_depth;
+ }
+
+ if (f_interface) {
+ Printv(f_interface, interface_class_code, "}\n", NIL);
+ addCloseNamespace(nspace, f_interface);
+ if (f_interface != f_single_out)
+ Delete(f_interface);
+ f_interface = 0;
+ }
+
+ emitDirectorExtraMethods(n);
+
+ Delete(interface_class_code);
+ interface_class_code = old_interface_class_code;
+ Delete(csclazzname);
+ Delete(proxy_class_name);
+ proxy_class_name = old_proxy_class_name;
+ Delete(full_imclass_name);
+ full_imclass_name = old_full_imclass_name;
+ Delete(destructor_call);
+ destructor_call = old_destructor_call;
+ Delete(proxy_class_constants_code);
+ proxy_class_constants_code = old_proxy_class_constants_code;
+ Delete(proxy_class_def);
+ proxy_class_def = old_proxy_class_def;
+ Delete(proxy_class_code);
+ proxy_class_code = old_proxy_class_code;
+ }
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * memberfunctionHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int memberfunctionHandler(Node *n) {
+ Language::memberfunctionHandler(n);
+
+ if (proxy_flag) {
+ String *overloaded_name = getOverloadedName(n);
+ String *intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name);
+ Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
+ Setattr(n, "imfuncname", intermediary_function_name);
+ proxyClassFunctionHandler(n);
+ Delete(overloaded_name);
+ }
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+
+ static_flag = true;
+ Language::staticmemberfunctionHandler(n);
+
+ if (proxy_flag) {
+ String *overloaded_name = getOverloadedName(n);
+ String *intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name);
+ Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
+ Setattr(n, "imfuncname", intermediary_function_name);
+ proxyClassFunctionHandler(n);
+ Delete(overloaded_name);
+ }
+ static_flag = false;
+
+ return SWIG_OK;
+ }
+
+
+ /* -----------------------------------------------------------------------------
+ * proxyClassFunctionHandler()
+ *
+ * Function called for creating a C# wrapper function around a c++ function in the
+ * proxy class. Used for both static and non-static C++ class functions.
+ * C++ class static functions map to C# static functions.
+ * Two extra attributes in the Node must be available. These are "proxyfuncname" -
+ * the name of the C# class proxy function, which in turn will call "imfuncname" -
+ * the intermediary (PInvoke) function name in the intermediary class.
+ * ----------------------------------------------------------------------------- */
+
+ void proxyClassFunctionHandler(Node *n) {
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *intermediary_function_name = Getattr(n, "imfuncname");
+ String *proxy_function_name = Getattr(n, "proxyfuncname");
+ String *tm;
+ Parm *p;
+ Parm *last_parm = 0;
+ int i;
+ String *imcall = NewString("");
+ String *return_type = NewString("");
+ String *function_code = NewString("");
+ bool setter_flag = false;
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *terminator_code = NewString("");
+ bool is_interface = Getattr(parentNode(n), "feature:interface") != 0
+ && !static_flag && Getattr(n, "interface:owner") == 0;
+
+ if (!proxy_flag)
+ return;
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
+ if (Getattr(n, "overload:ignore"))
+ return;
+
+ // Don't generate proxy method for additional explicitcall method used in directors
+ if (GetFlag(n, "explicitcall"))
+ return;
+
+ if (l) {
+ if (SwigType_type(Getattr(l, "type")) == T_VOID) {
+ l = nextSibling(l);
+ }
+ }
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("in", l, NULL);
+ Swig_typemap_attach_parms("cstype", l, NULL);
+ Swig_typemap_attach_parms("csin", l, NULL);
+
+ /* Get return types */
+ if ((tm = Swig_typemap_lookup("cstype", n, "", 0))) {
+ // Note that in the case of polymorphic (covariant) return types, the method's return type is changed to be the base of the C++ return type
+ SwigType *covariant = Getattr(n, "covariant");
+ String *cstypeout = Getattr(n, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
+ if (cstypeout)
+ tm = cstypeout;
+ substituteClassname(covariant ? covariant : t, tm);
+ Printf(return_type, "%s", tm);
+ if (covariant)
+ Swig_warning(WARN_CSHARP_COVARIANT_RET, input_file, line_number,
+ "Covariant return types not supported in C#. Proxy method will return %s.\n", SwigType_str(covariant, 0));
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ if (wrapping_member_flag && !enum_constant_flag) {
+ // Properties
+ setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) == 0);
+ if (setter_flag)
+ Swig_typemap_attach_parms("csvarin", l, NULL);
+ }
+
+ /* Start generating the proxy function */
+ const String *outattributes = Getattr(n, "tmap:cstype:outattributes");
+ if (outattributes)
+ Printf(function_code, " %s\n", outattributes);
+ const String *csattributes = Getattr(n, "feature:cs:attributes");
+ if (csattributes)
+ Printf(function_code, " %s\n", csattributes);
+ const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
+ if (methodmods) {
+ if (is_smart_pointer()) {
+ // Smart pointer classes do not mirror the inheritance hierarchy of the underlying pointer type, so no virtual/override/new required.
+ String *mmods = Copy(methodmods);
+ Replaceall(mmods, "override", "");
+ Replaceall(mmods, "virtual", "");
+ Replaceall(mmods, "new", "");
+ Chop(mmods); // remove trailing whitespace
+ Printf(function_code, " %s ", mmods);
+ Delete(mmods);
+ } else {
+ Printf(function_code, " %s ", methodmods);
+ }
+ } else {
+ methodmods = (is_public(n) ? public_string : protected_string);
+ Printf(function_code, " %s ", methodmods);
+ if (!is_smart_pointer()) {
+ // Smart pointer classes do not mirror the inheritance hierarchy of the underlying pointer type, so no virtual/override/new required.
+ if (Getattr(n, "override"))
+ Printf(function_code, "override ");
+ else if (checkAttribute(n, "storage", "virtual"))
+ Printf(function_code, "virtual ");
+ if (Getattr(n, "hides"))
+ Printf(function_code, "new ");
+ }
+ }
+ if (static_flag)
+ Printf(function_code, "static ");
+ Printf(function_code, "%s %s(", return_type, proxy_function_name);
+ if (is_interface)
+ Printf(interface_class_code, " %s %s(", return_type, proxy_function_name);
+
+
+ Printv(imcall, full_imclass_name, ".$imfuncname(", NIL);
+ if (!static_flag)
+ Printf(imcall, "swigCPtr");
+
+ emit_mark_varargs(l);
+
+ int gencomma = !static_flag;
+
+ /* Output each parameter */
+ for (i = 0, p = l; p; i++) {
+
+ /* Ignored varargs */
+ if (checkAttribute(p, "varargs:ignore", "1")) {
+ p = nextSibling(p);
+ continue;
+ }
+
+ /* Ignored parameters */
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ /* Ignore the 'this' argument for variable wrappers */
+ if (!(variable_wrapper_flag && i == 0)) {
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+ if (setter_flag)
+ last_parm = p;
+
+ /* Get the C# parameter type */
+ if ((tm = Getattr(p, "tmap:cstype"))) {
+ substituteClassname(pt, tm);
+ const String *inattributes = Getattr(p, "tmap:cstype:inattributes");
+ Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ String *arg = makeParameterName(n, p, i, setter_flag);
+
+ // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
+ if ((tm = Getattr(p, "tmap:csin"))) {
+ substituteClassname(pt, tm);
+ Replaceall(tm, "$csinput", arg);
+ String *pre = Getattr(p, "tmap:csin:pre");
+ if (pre) {
+ substituteClassname(pt, pre);
+ Replaceall(pre, "$csinput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:csin:post");
+ if (post) {
+ substituteClassname(pt, post);
+ Replaceall(post, "$csinput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ String *terminator = Getattr(p, "tmap:csin:terminator");
+ if (terminator) {
+ substituteClassname(pt, terminator);
+ Replaceall(terminator, "$csinput", arg);
+ if (Len(terminator_code) > 0)
+ Insert(terminator_code, 0, "\n");
+ Insert(terminator_code, 0, terminator);
+ }
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to proxy function */
+ if (gencomma >= 2) {
+ Printf(function_code, ", ");
+ if (is_interface)
+ Printf(interface_class_code, ", ");
+ }
+ gencomma = 2;
+ Printf(function_code, "%s %s", param_type, arg);
+ if (is_interface)
+ Printf(interface_class_code, "%s %s", param_type, arg);
+
+ Delete(arg);
+ Delete(param_type);
+ }
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Printf(imcall, ")");
+ Printf(function_code, ")");
+ if (is_interface)
+ Printf(interface_class_code, ");\n");
+
+ // Transform return type used in PInvoke function (in intermediary class) to type used in C# wrapper function (in proxy class)
+ if ((tm = Swig_typemap_lookup("csout", n, "", 0))) {
+ excodeSubstitute(n, tm, "csout", n);
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ bool is_terminator_code = Len(terminator_code) > 0;
+ if (is_pre_code || is_post_code || is_terminator_code) {
+ Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
+ if (is_post_code) {
+ Insert(tm, 0, "\n try ");
+ Printv(tm, " finally {\n", post_code, "\n }", NIL);
+ } else {
+ Insert(tm, 0, "\n ");
+ }
+ if (is_pre_code) {
+ Insert(tm, 0, pre_code);
+ Insert(tm, 0, "\n");
+ }
+ if (is_terminator_code) {
+ Printv(tm, "\n", terminator_code, NIL);
+ }
+ Insert(tm, 0, "{");
+ Printf(tm, "\n }");
+ }
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ substituteClassname(t, tm);
+
+ // For director methods: generate code to selectively make a normal polymorphic call or
+ // an explicit method call - needed to prevent infinite recursion calls in director methods.
+ Node *explicit_n = Getattr(n, "explicitcallnode");
+ if (explicit_n) {
+ String *ex_overloaded_name = getOverloadedName(explicit_n);
+ String *ex_intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), ex_overloaded_name);
+
+ String *ex_imcall = Copy(imcall);
+ Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
+ Replaceall(imcall, "$imfuncname", intermediary_function_name);
+ String *excode = NewString("");
+ Node *directorNode = Getattr(n, "directorNode");
+ if (directorNode) {
+ UpcallData *udata = Getattr(directorNode, "upcalldata");
+ String *methid = Getattr(udata, "class_methodidx");
+
+ if (!Cmp(return_type, "void"))
+ Printf(excode, "if (SwigDerivedClassHasMethod(\"%s\", swigMethodTypes%s)) %s; else %s", proxy_function_name, methid, ex_imcall, imcall);
+ else
+ Printf(excode, "(SwigDerivedClassHasMethod(\"%s\", swigMethodTypes%s) ? %s : %s)", proxy_function_name, methid, ex_imcall, imcall);
+
+ Clear(imcall);
+ Printv(imcall, excode, NIL);
+ } else {
+ // probably an ignored method or nodirector
+ }
+ Delete(excode);
+ Delete(ex_overloaded_name);
+ } else {
+ Replaceall(imcall, "$imfuncname", intermediary_function_name);
+ }
+ Replaceall(tm, "$imcall", imcall);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ if (wrapping_member_flag && !enum_constant_flag) {
+ // Properties
+ if (generate_property_declaration_flag) { // Ensure the declaration is generated just once should the property contain both a set and get
+ // Get the C# variable type - obtained differently depending on whether a setter is required.
+ String *variable_type = return_type;
+ if (setter_flag) {
+ assert(last_parm); // (last parameter is the only parameter for properties)
+ /* Get variable type - ensure the variable name is fully resolved during typemap lookup via the symbol table set in NewParmNode */
+ SwigType *cvariable_type = Getattr(last_parm, "type");
+ Parm *variable_parm = NewParmNode(cvariable_type, n);
+ if ((tm = Swig_typemap_lookup("cstype", variable_parm, "", 0))) {
+ String *cstypeout = Getattr(variable_parm, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
+ if (cstypeout)
+ tm = cstypeout;
+ substituteClassname(cvariable_type, tm);
+ variable_type = tm;
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(cvariable_type, 0));
+ }
+ }
+ const String *csattributes = Getattr(n, "feature:cs:attributes");
+ if (csattributes)
+ Printf(proxy_class_code, " %s\n", csattributes);
+ const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
+ if (!methodmods)
+ methodmods = (is_public(n) ? public_string : protected_string);
+ Printf(proxy_class_code, " %s %s%s %s {", methodmods, static_flag ? "static " : "", variable_type, variable_name);
+ }
+ generate_property_declaration_flag = false;
+
+ if (setter_flag) {
+ // Setter method
+ assert(last_parm); // (last parameter is the only parameter for properties)
+ SwigType *cvariable_type = Getattr(last_parm, "type");
+ Parm *variable_parm = NewParmNode(cvariable_type, n);
+ if ((tm = Swig_typemap_lookup("csvarin", variable_parm, "", 0))) {
+ substituteClassname(cvariable_type, tm);
+ Replaceall(tm, "$csinput", "value");
+ Replaceall(tm, "$imcall", imcall);
+ excodeSubstitute(n, tm, "csvarin", variable_parm);
+ Printf(proxy_class_code, "%s", tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(cvariable_type, 0));
+ }
+ } else {
+ // Getter method
+ if ((tm = Swig_typemap_lookup("csvarout", n, "", 0))) {
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ substituteClassname(t, tm);
+ Replaceall(tm, "$imcall", imcall);
+ excodeSubstitute(n, tm, "csvarout", n);
+ Printf(proxy_class_code, "%s", tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+ }
+ } else {
+ // Normal function call
+ Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
+ Printv(proxy_class_code, function_code, NIL);
+ }
+
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(terminator_code);
+ Delete(function_code);
+ Delete(return_type);
+ Delete(imcall);
+ }
+
+ /* ----------------------------------------------------------------------
+ * constructorHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int constructorHandler(Node *n) {
+
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ int i;
+ String *function_code = NewString("");
+ String *helper_code = NewString(""); // Holds code for the constructor helper method generated only when the csin typemap has code in the pre or post attributes
+ String *helper_args = NewString("");
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *terminator_code = NewString("");
+ String *im_return_type = NewString("");
+ bool feature_director = (parentNode(n) && Swig_directorclass(n));
+
+ Language::constructorHandler(n);
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
+ if (Getattr(n, "overload:ignore"))
+ return SWIG_OK;
+
+ if (proxy_flag) {
+ String *overloaded_name = getOverloadedName(n);
+ String *mangled_overname = Swig_name_construct(getNSpace(), overloaded_name);
+ String *imcall = NewString("");
+
+ const String *csattributes = Getattr(n, "feature:cs:attributes");
+ if (csattributes) {
+ Printf(function_code, " %s\n", csattributes);
+ Printf(helper_code, " %s\n", csattributes);
+ }
+ const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ tm = Getattr(n, "tmap:imtype"); // typemaps were attached earlier to the node
+ String *imtypeout = Getattr(n, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap
+ if (imtypeout)
+ tm = imtypeout;
+ Printf(im_return_type, "%s", tm);
+
+ Printf(function_code, " %s %s(", methodmods, proxy_class_name);
+ Printf(helper_code, " static private %s SwigConstruct%s(", im_return_type, proxy_class_name);
+
+ Printv(imcall, full_imclass_name, ".", mangled_overname, "(", NIL);
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("in", l, NULL);
+ Swig_typemap_attach_parms("cstype", l, NULL);
+ Swig_typemap_attach_parms("csin", l, NULL);
+
+ emit_mark_varargs(l);
+
+ int gencomma = 0;
+
+ /* Output each parameter */
+ for (i = 0, p = l; p; i++) {
+
+ /* Ignored varargs */
+ if (checkAttribute(p, "varargs:ignore", "1")) {
+ p = nextSibling(p);
+ continue;
+ }
+
+ /* Ignored parameters */
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+
+ /* Get the C# parameter type */
+ if ((tm = Getattr(p, "tmap:cstype"))) {
+ substituteClassname(pt, tm);
+ const String *inattributes = Getattr(p, "tmap:cstype:inattributes");
+ Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ String *arg = makeParameterName(n, p, i, false);
+ String *cshin = 0;
+
+ // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
+ if ((tm = Getattr(p, "tmap:csin"))) {
+ substituteClassname(pt, tm);
+ Replaceall(tm, "$csinput", arg);
+ String *pre = Getattr(p, "tmap:csin:pre");
+ if (pre) {
+ substituteClassname(pt, pre);
+ Replaceall(pre, "$csinput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:csin:post");
+ if (post) {
+ substituteClassname(pt, post);
+ Replaceall(post, "$csinput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ String *terminator = Getattr(p, "tmap:csin:terminator");
+ if (terminator) {
+ substituteClassname(pt, terminator);
+ Replaceall(terminator, "$csinput", arg);
+ if (Len(terminator_code) > 0)
+ Insert(terminator_code, 0, "\n");
+ Insert(terminator_code, 0, terminator);
+ }
+ cshin = Getattr(p, "tmap:csin:cshin");
+ if (cshin)
+ Replaceall(cshin, "$csinput", arg);
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to proxy function */
+ if (gencomma) {
+ Printf(function_code, ", ");
+ Printf(helper_code, ", ");
+ Printf(helper_args, ", ");
+ }
+ Printf(function_code, "%s %s", param_type, arg);
+ Printf(helper_code, "%s %s", param_type, arg);
+ Printf(helper_args, "%s", cshin ? cshin : arg);
+ ++gencomma;
+
+ Delete(cshin);
+ Delete(arg);
+ Delete(param_type);
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Printf(imcall, ")");
+
+ Printf(function_code, ")");
+ Printf(helper_code, ")");
+
+ /* Insert the csconstruct typemap, doing the replacement for $directorconnect, as needed */
+ Hash *attributes = NewHash();
+ String *typemap_lookup_type = Getattr(getCurrentClass(), "classtypeobj");
+ String *construct_tm = Copy(typemapLookup(n, "csconstruct", typemap_lookup_type,
+ WARN_CSHARP_TYPEMAP_CSCONSTRUCT_UNDEF, attributes));
+ if (construct_tm) {
+ if (!feature_director) {
+ Replaceall(construct_tm, "$directorconnect", "");
+ } else {
+ String *connect_attr = Getattr(attributes, "tmap:csconstruct:directorconnect");
+
+ if (connect_attr) {
+ Replaceall(construct_tm, "$directorconnect", connect_attr);
+ } else {
+ Swig_warning(WARN_CSHARP_NO_DIRECTORCONNECT_ATTR, input_file, line_number, "\"directorconnect\" attribute missing in %s \"csconstruct\" typemap.\n",
+ Getattr(n, "name"));
+ Replaceall(construct_tm, "$directorconnect", "");
+ }
+ }
+
+ Printv(function_code, " ", construct_tm, NIL);
+ }
+
+ excodeSubstitute(n, function_code, "csconstruct", attributes);
+
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ bool is_terminator_code = Len(terminator_code) > 0;
+ if (is_pre_code || is_post_code || is_terminator_code) {
+ Printf(helper_code, " {\n");
+ if (is_pre_code) {
+ Printv(helper_code, pre_code, "\n", NIL);
+ }
+ if (is_post_code) {
+ Printf(helper_code, " try {\n");
+ Printv(helper_code, " return ", imcall, ";\n", NIL);
+ Printv(helper_code, " } finally {\n", post_code, "\n }", NIL);
+ } else {
+ Printv(helper_code, " return ", imcall, ";", NIL);
+ }
+ if (is_terminator_code) {
+ Printv(helper_code, "\n", terminator_code, NIL);
+ }
+ Printf(helper_code, "\n }\n");
+ String *helper_name = NewStringf("%s.SwigConstruct%s(%s)", proxy_class_name, proxy_class_name, helper_args);
+ String *im_outattributes = Getattr(n, "tmap:imtype:outattributes");
+ if (im_outattributes)
+ Printf(proxy_class_code, " %s\n", im_outattributes);
+ Printv(proxy_class_code, helper_code, "\n", NIL);
+ Replaceall(function_code, "$imcall", helper_name);
+ Delete(helper_name);
+ } else {
+ Replaceall(function_code, "$imcall", imcall);
+ }
+
+ Printv(proxy_class_code, function_code, "\n", NIL);
+
+ Delete(helper_args);
+ Delete(im_return_type);
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(terminator_code);
+ Delete(construct_tm);
+ Delete(attributes);
+ Delete(overloaded_name);
+ Delete(imcall);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * destructorHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int destructorHandler(Node *n) {
+ Language::destructorHandler(n);
+ String *symname = Getattr(n, "sym:name");
+
+ if (proxy_flag) {
+ Printv(destructor_call, full_imclass_name, ".", Swig_name_destroy(getNSpace(), symname), "(swigCPtr)", NIL);
+ const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
+ if (methodmods)
+ Setattr(getCurrentClass(), "destructmethodmodifiers", methodmods);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * membervariableHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int membervariableHandler(Node *n) {
+
+ generate_property_declaration_flag = true;
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ variable_wrapper_flag = true;
+ Language::membervariableHandler(n);
+ wrapping_member_flag = false;
+ variable_wrapper_flag = false;
+ generate_property_declaration_flag = false;
+
+ Printf(proxy_class_code, "\n }\n\n");
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * staticmembervariableHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int staticmembervariableHandler(Node *n) {
+
+ bool static_const_member_flag = (Getattr(n, "value") == 0);
+
+ generate_property_declaration_flag = true;
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ static_flag = true;
+ Language::staticmembervariableHandler(n);
+ wrapping_member_flag = false;
+ static_flag = false;
+ generate_property_declaration_flag = false;
+
+ if (static_const_member_flag)
+ Printf(proxy_class_code, "\n }\n\n");
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * memberconstantHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int memberconstantHandler(Node *n) {
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ Language::memberconstantHandler(n);
+ wrapping_member_flag = false;
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getOverloadedName()
+ * ----------------------------------------------------------------------------- */
+
+ String *getOverloadedName(Node *n) {
+
+ /* A C# HandleRef is used for all classes in the SWIG intermediary class.
+ * The intermediary class methods are thus mangled when overloaded to give
+ * a unique name. */
+ String *overloaded_name = NewStringf("%s", Getattr(n, "sym:name"));
+
+ if (Getattr(n, "sym:overloaded")) {
+ Printv(overloaded_name, Getattr(n, "sym:overname"), NIL);
+ }
+
+ return overloaded_name;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * moduleClassFunctionHandler()
+ * ----------------------------------------------------------------------------- */
+
+ void moduleClassFunctionHandler(Node *n) {
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ Parm *last_parm = 0;
+ int i;
+ String *imcall = NewString("");
+ String *return_type = NewString("");
+ String *function_code = NewString("");
+ int num_arguments = 0;
+ String *overloaded_name = getOverloadedName(n);
+ String *func_name = NULL;
+ bool setter_flag = false;
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *terminator_code = NewString("");
+
+ if (l) {
+ if (SwigType_type(Getattr(l, "type")) == T_VOID) {
+ l = nextSibling(l);
+ }
+ }
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("cstype", l, NULL);
+ Swig_typemap_attach_parms("csin", l, NULL);
+
+ /* Get return types */
+ if ((tm = Swig_typemap_lookup("cstype", n, "", 0))) {
+ String *cstypeout = Getattr(n, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
+ if (cstypeout)
+ tm = cstypeout;
+ substituteClassname(t, tm);
+ Printf(return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ /* Change function name for global variables */
+ if (proxy_flag && global_variable_flag) {
+ // Capitalize the first letter in the variable to create the getter/setter function name
+ func_name = NewString("");
+ setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), variable_name)) == 0);
+ if (setter_flag)
+ Printf(func_name, "set");
+ else
+ Printf(func_name, "get");
+ Putc(toupper((int) *Char(variable_name)), func_name);
+ Printf(func_name, "%s", Char(variable_name) + 1);
+ if (setter_flag)
+ Swig_typemap_attach_parms("csvarin", l, NULL);
+ } else {
+ func_name = Copy(Getattr(n, "sym:name"));
+ }
+
+ /* Start generating the function */
+ const String *outattributes = Getattr(n, "tmap:cstype:outattributes");
+ if (outattributes)
+ Printf(function_code, " %s\n", outattributes);
+ const String *csattributes = Getattr(n, "feature:cs:attributes");
+ if (csattributes)
+ Printf(function_code, " %s\n", csattributes);
+ const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+ Printf(function_code, " %s static %s %s(", methodmods, return_type, func_name);
+ Printv(imcall, imclass_name, ".", overloaded_name, "(", NIL);
+
+ /* Get number of required and total arguments */
+ num_arguments = emit_num_arguments(l);
+
+ bool global_or_member_variable = global_variable_flag || (wrapping_member_flag && !enum_constant_flag);
+ int gencomma = 0;
+
+ /* Output each parameter */
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ /* Ignored parameters */
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+ last_parm = p;
+
+ /* Get the C# parameter type */
+ if ((tm = Getattr(p, "tmap:cstype"))) {
+ substituteClassname(pt, tm);
+ const String *inattributes = Getattr(p, "tmap:cstype:inattributes");
+ Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ String *arg = makeParameterName(n, p, i, global_or_member_variable);
+
+ // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
+ if ((tm = Getattr(p, "tmap:csin"))) {
+ substituteClassname(pt, tm);
+ Replaceall(tm, "$csinput", arg);
+ String *pre = Getattr(p, "tmap:csin:pre");
+ if (pre) {
+ substituteClassname(pt, pre);
+ Replaceall(pre, "$csinput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:csin:post");
+ if (post) {
+ substituteClassname(pt, post);
+ Replaceall(post, "$csinput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ String *terminator = Getattr(p, "tmap:csin:terminator");
+ if (terminator) {
+ substituteClassname(pt, terminator);
+ Replaceall(terminator, "$csinput", arg);
+ if (Len(terminator_code) > 0)
+ Insert(terminator_code, 0, "\n");
+ Insert(terminator_code, 0, terminator);
+ }
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to module class function */
+ if (gencomma >= 2)
+ Printf(function_code, ", ");
+ gencomma = 2;
+ Printf(function_code, "%s %s", param_type, arg);
+
+ p = Getattr(p, "tmap:in:next");
+ Delete(arg);
+ Delete(param_type);
+ }
+
+ Printf(imcall, ")");
+ Printf(function_code, ")");
+
+ // Transform return type used in PInvoke function (in intermediary class) to type used in C# wrapper function (in module class)
+ if ((tm = Swig_typemap_lookup("csout", n, "", 0))) {
+ excodeSubstitute(n, tm, "csout", n);
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ bool is_terminator_code = Len(terminator_code) > 0;
+ if (is_pre_code || is_post_code || is_terminator_code) {
+ Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
+ if (is_post_code) {
+ Insert(tm, 0, "\n try ");
+ Printv(tm, " finally {\n", post_code, "\n }", NIL);
+ } else {
+ Insert(tm, 0, "\n ");
+ }
+ if (is_pre_code) {
+ Insert(tm, 0, pre_code);
+ Insert(tm, 0, "\n");
+ }
+ if (is_terminator_code) {
+ Printv(tm, "\n", terminator_code, NIL);
+ }
+ Insert(tm, 0, "{");
+ Printf(tm, "\n }");
+ }
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ substituteClassname(t, tm);
+ Replaceall(tm, "$imcall", imcall);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ if (proxy_flag && global_variable_flag) {
+ // Properties
+ if (generate_property_declaration_flag) { // Ensure the declaration is generated just once should the property contain both a set and get
+ // Get the C# variable type - obtained differently depending on whether a setter is required.
+ String *variable_type = return_type;
+ if (setter_flag) {
+ p = last_parm; // (last parameter is the only parameter for properties)
+ SwigType *pt = Getattr(p, "type");
+ if ((tm = Getattr(p, "tmap:cstype"))) {
+ substituteClassname(pt, tm);
+ String *cstypeout = Getattr(p, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
+ variable_type = cstypeout ? cstypeout : tm;
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+ }
+ const String *csattributes = Getattr(n, "feature:cs:attributes");
+ if (csattributes)
+ Printf(module_class_code, " %s\n", csattributes);
+ const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
+ if (!methodmods)
+ methodmods = (is_public(n) ? public_string : protected_string);
+ Printf(module_class_code, " %s static %s %s {", methodmods, variable_type, variable_name);
+ }
+ generate_property_declaration_flag = false;
+
+ if (setter_flag) {
+ // Setter method
+ p = last_parm; // (last parameter is the only parameter for properties)
+ SwigType *pt = Getattr(p, "type");
+ if ((tm = Getattr(p, "tmap:csvarin"))) {
+ substituteClassname(pt, tm);
+ Replaceall(tm, "$csinput", "value");
+ Replaceall(tm, "$imcall", imcall);
+ excodeSubstitute(n, tm, "csvarin", p);
+ Printf(module_class_code, "%s", tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+ } else {
+ // Getter method
+ if ((tm = Swig_typemap_lookup("csvarout", n, "", 0))) {
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ substituteClassname(t, tm);
+ Replaceall(tm, "$imcall", imcall);
+ excodeSubstitute(n, tm, "csvarout", n);
+ Printf(module_class_code, "%s", tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+ }
+ } else {
+ // Normal function call
+ Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
+ Printv(module_class_code, function_code, NIL);
+ }
+
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(terminator_code);
+ Delete(function_code);
+ Delete(return_type);
+ Delete(imcall);
+ Delete(func_name);
+ }
+
+ /*----------------------------------------------------------------------
+ * replaceSpecialVariables()
+ *--------------------------------------------------------------------*/
+
+ virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
+ (void)method;
+ SwigType *type = Getattr(parm, "type");
+ substituteClassname(type, tm);
+ }
+
+ /*----------------------------------------------------------------------
+ * decodeEnumFeature()
+ * Decode the possible enum features, which are one of:
+ * %csenum(simple)
+ * %csenum(typeunsafe) - default
+ * %csenum(typesafe)
+ * %csenum(proper)
+ *--------------------------------------------------------------------*/
+
+ EnumFeature decodeEnumFeature(Node *n) {
+ EnumFeature enum_feature = TypeunsafeEnum;
+ String *feature = Getattr(n, "feature:cs:enum");
+ if (feature) {
+ if (Cmp(feature, "simple") == 0)
+ enum_feature = SimpleEnum;
+ else if (Cmp(feature, "typesafe") == 0)
+ enum_feature = TypesafeEnum;
+ else if (Cmp(feature, "proper") == 0)
+ enum_feature = ProperEnum;
+ }
+ return enum_feature;
+ }
+
+ /* -----------------------------------------------------------------------
+ * enumValue()
+ * This method will return a string with an enum value to use in C# generated
+ * code. If the %csconst feature is not used, the string will contain the intermediary
+ * class call to obtain the enum value. The intermediary class and PINVOKE methods to obtain
+ * the enum value will be generated. Otherwise the C/C++ enum value will be used if there
+ * is one and hopefully it will compile as C# code - e.g. 20 as in: enum E{e=20};
+ * The %csconstvalue feature overrides all other ways to generate the constant value.
+ * The caller must delete memory allocated for the returned string.
+ * ------------------------------------------------------------------------ */
+
+ String *enumValue(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+
+ // Check for the %csconstvalue feature
+ String *value = Getattr(n, "feature:cs:constvalue");
+
+ if (!value) {
+ // The %csconst feature determines how the constant value is obtained
+ int const_feature_flag = GetFlag(n, "feature:cs:const");
+
+ if (const_feature_flag) {
+ // Use the C syntax to make a true C# constant and hope that it compiles as C# code
+ value = Getattr(n, "enumvalue") ? Copy(Getattr(n, "enumvalue")) : Copy(Getattr(n, "enumvalueex"));
+ } else {
+ String *newsymname = 0;
+ if (!getCurrentClass() || !proxy_flag) {
+ String *enumClassPrefix = getEnumClassPrefix();
+ if (enumClassPrefix) {
+ // A global scoped enum
+ newsymname = Swig_name_member(0, enumClassPrefix, symname);
+ symname = newsymname;
+ }
+ }
+
+ // Get the enumvalue from a PINVOKE call
+ if (!getCurrentClass() || !cparse_cplusplus || !proxy_flag) {
+ // Strange hack to change the name
+ Setattr(n, "name", Getattr(n, "value")); /* for wrapping of enums in a namespace when emit_action is used */
+ constantWrapper(n);
+ value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
+ } else {
+ memberconstantHandler(n);
+ value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), Swig_name_member(0, getEnumClassPrefix(), symname)));
+ }
+ }
+ }
+ return value;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getEnumName()
+ * ----------------------------------------------------------------------------- */
+
+ String *getEnumName(SwigType *t) {
+ Node *enumname = NULL;
+ Node *n = enumLookup(t);
+ 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 *scopename_prefix = Swig_scopename_prefix(Getattr(n, "name"));
+ String *proxyname = 0;
+ if (scopename_prefix) {
+ proxyname = getProxyName(scopename_prefix);
+ }
+ if (proxyname) {
+ enumname = NewStringf("%s.%s", proxyname, symname);
+ } else {
+ // global enum or enum in a namespace
+ String *nspace = Getattr(n, "sym:nspace");
+ if (nspace) {
+ if (namespce)
+ enumname = NewStringf("%s.%s.%s", namespce, nspace, symname);
+ else
+ enumname = NewStringf("%s.%s", nspace, symname);
+ } else {
+ enumname = Copy(symname);
+ }
+ }
+ Setattr(n, "enumname", enumname);
+ Delete(enumname);
+ Delete(scopename_prefix);
+ }
+ }
+ }
+
+ return enumname;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substituteClassname()
+ *
+ * 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
+ * Return:
+ * substitution_performed - flag indicating if a substitution was performed
+ * ----------------------------------------------------------------------------- */
+
+ bool substituteClassname(SwigType *pt, String *tm) {
+ bool substitution_performed = false;
+ SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
+ SwigType *strippedtype = SwigType_strip_qualifiers(type);
+
+ if (Strstr(tm, "$csclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ substituteClassnameSpecialVariable(classnametype, tm, "$csclassname");
+ substitution_performed = true;
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$*csclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ Delete(SwigType_pop(classnametype));
+ if (Len(classnametype) > 0) {
+ substituteClassnameSpecialVariable(classnametype, tm, "$*csclassname");
+ substitution_performed = true;
+ }
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$&csclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ SwigType_add_pointer(classnametype);
+ substituteClassnameSpecialVariable(classnametype, tm, "$&csclassname");
+ substitution_performed = true;
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$csinterfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$csinterfacename", true);
+ substitution_performed = true;
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$*csinterfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ Delete(SwigType_pop(interfacenametype));
+ if (Len(interfacenametype) > 0) {
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*csinterfacename", true);
+ substitution_performed = true;
+ }
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$&csinterfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ SwigType_add_pointer(interfacenametype);
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&csinterfacename", true);
+ substitution_performed = true;
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$interfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$interfacename", false);
+ substitution_performed = true;
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$*interfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ Delete(SwigType_pop(interfacenametype));
+ if (Len(interfacenametype) > 0) {
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*interfacename", false);
+ substitution_performed = true;
+ }
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$&interfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ SwigType_add_pointer(interfacenametype);
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&interfacename", false);
+ substitution_performed = true;
+ Delete(interfacenametype);
+ }
+
+ Delete(strippedtype);
+ Delete(type);
+
+ return substitution_performed;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substituteClassnameSpecialVariable()
+ * ----------------------------------------------------------------------------- */
+
+ void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable) {
+ String *replacementname;
+ if (SwigType_isenum(classnametype)) {
+ String *enumname = getEnumName(classnametype);
+ if (enumname) {
+ replacementname = Copy(enumname);
+ } else {
+ bool anonymous_enum = (Cmp(classnametype, "enum ") == 0);
+ if (anonymous_enum) {
+ replacementname = NewString("int");
+ } else {
+ // An unknown enum - one that has not been parsed (neither a C enum forward reference nor a definition) or an ignored enum
+ replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
+ Replace(replacementname, "enum ", "", DOH_REPLACE_ANY);
+ Setattr(swig_types_hash, replacementname, classnametype);
+ }
+ }
+ } else {
+ String *classname = getProxyName(classnametype); // getProxyName() works for pointers to classes too
+ if (classname) {
+ replacementname = Copy(classname);
+ } else {
+ // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
+ replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
+
+ // Add to hash table so that the type wrapper classes can be created later
+ Setattr(swig_types_hash, replacementname, classnametype);
+ }
+ }
+ Replaceall(tm, classnamespecialvariable, replacementname);
+
+ Delete(replacementname);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substituteInterfacenameSpecialVariable()
+ * ----------------------------------------------------------------------------- */
+
+ void substituteInterfacenameSpecialVariable(SwigType *interfacenametype, String *tm, const char *interfacenamespecialvariable, bool qualified) {
+
+ String *interfacename = getInterfaceName(interfacenametype, qualified);
+ if (interfacename) {
+ String *replacementname = Copy(interfacename);
+ Replaceall(tm, interfacenamespecialvariable, replacementname);
+ Delete(replacementname);
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * emitTypeWrapperClass()
+ * ----------------------------------------------------------------------------- */
+
+ void emitTypeWrapperClass(String *classname, SwigType *type) {
+ Node *n = NewHash();
+ Setfile(n, input_file);
+ Setline(n, line_number);
+
+ String *swigtype = NewString("");
+ File *f_swigtype = getOutputFile(SWIG_output_directory(), classname);
+
+ addOpenNamespace(0, f_swigtype);
+
+ // Pure C# baseclass and interfaces
+ const String *pure_baseclass = typemapLookup(n, "csbase", type, WARN_NONE);
+ const String *pure_interfaces = typemapLookup(n, "csinterfaces", type, WARN_NONE);
+
+ // Emit the class
+ Printv(swigtype, typemapLookup(n, "csimports", type, WARN_NONE), // Import statements
+ "\n", NIL);
+
+ // Class attributes
+ const String *csattributes = typemapLookup(n, "csattributes", type, WARN_NONE);
+ if (csattributes && *Char(csattributes))
+ Printf(swigtype, "%s\n", csattributes);
+
+ Printv(swigtype, typemapLookup(n, "csclassmodifiers", type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
+ " $csclassname", // Class name and base class
+ (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass, ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces
+ ", " : "", pure_interfaces, " {", typemapLookup(n, "csbody", type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
+ typemapLookup(n, "cscode", type, WARN_NONE), // extra C# code
+ "}\n", NIL);
+
+ Replaceall(swigtype, "$csclassname", classname);
+ Replaceall(swigtype, "$module", module_class_name);
+ Replaceall(swigtype, "$imclassname", imclass_name);
+ Replaceall(swigtype, "$dllimport", dllimport);
+
+ // For unknown enums
+ Replaceall(swigtype, "$enumvalues", "");
+
+ Printv(f_swigtype, swigtype, NIL);
+
+ addCloseNamespace(0, f_swigtype);
+ if (f_swigtype != f_single_out)
+ Delete(f_swigtype);
+ f_swigtype = NULL;
+ Delete(swigtype);
+ Delete(n);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * typemapLookup()
+ * n - for input only and must contain info for Getfile(n) and Getline(n) to work
+ * tmap_method - typemap method name
+ * type - typemap type to lookup
+ * warning - warning number to issue if no typemaps found
+ * typemap_attributes - the typemap attributes are attached to this node and will
+ * also be used for temporary storage if non null
+ * return is never NULL, unlike Swig_typemap_lookup()
+ * ----------------------------------------------------------------------------- */
+
+ const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) {
+ Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
+ Setattr(node, "type", type);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
+ if (!tm) {
+ tm = empty_string;
+ if (warning != WARN_NONE)
+ Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
+ }
+ if (!typemap_attributes)
+ Delete(node);
+ return tm;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * typemapExists()
+ * n - for input only and must contain info for Getfile(n) and Getline(n) to work
+ * tmap_method - typemap method name
+ * type - typemap type to lookup
+ * returns found typemap or NULL if not found
+ * ----------------------------------------------------------------------------- */
+
+ const String *typemapExists(Node *n, const_String_or_char_ptr tmap_method, SwigType *type) {
+ Node *node = NewHash();
+ Setattr(node, "type", type);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
+ Delete(node);
+ return tm;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * canThrow()
+ * Determine whether the code in the typemap can throw a C# exception.
+ * If so, note it for later when excodeSubstitute() is called.
+ * ----------------------------------------------------------------------------- */
+
+ void canThrow(Node *n, const String *typemap, Node *parameter) {
+ String *canthrow_attribute = NewStringf("tmap:%s:canthrow", typemap);
+ String *canthrow = Getattr(parameter, canthrow_attribute);
+ if (canthrow)
+ Setattr(n, "csharp:canthrow", "1");
+ Delete(canthrow_attribute);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * excodeSubstitute()
+ * If a method can throw a C# exception, additional exception code is added to
+ * check for the pending exception so that it can then throw the exception. The
+ * $excode special variable is replaced by the exception code in the excode
+ * typemap attribute.
+ * ----------------------------------------------------------------------------- */
+
+ void excodeSubstitute(Node *n, String *code, const String *typemap, Node *parameter) {
+ String *excode_attribute = NewStringf("tmap:%s:excode", typemap);
+ String *excode = Getattr(parameter, excode_attribute);
+ if (Getattr(n, "csharp:canthrow")) {
+ int count = Replaceall(code, "$excode", excode);
+ if (count < 1 || !excode) {
+ Swig_warning(WARN_CSHARP_EXCODE, input_file, line_number,
+ "C# exception may not be thrown - no $excode or excode attribute in '%s' typemap.\n", typemap);
+ }
+ } else {
+ Replaceall(code, "$excode", empty_string);
+ }
+ Delete(excode_attribute);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addOpenNamespace()
+ * ----------------------------------------------------------------------------- */
+
+ void addOpenNamespace(const String *nspace, File *file) {
+ if (namespce || nspace) {
+ Printf(file, "namespace ");
+ if (namespce)
+ Printv(file, namespce, nspace ? "." : "", NIL);
+ if (nspace)
+ Printv(file, nspace, NIL);
+ Printf(file, " {\n");
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addCloseNamespace()
+ * ----------------------------------------------------------------------------- */
+
+ void addCloseNamespace(const String *nspace, File *file) {
+ if (namespce || nspace)
+ Printf(file, "\n}\n");
+ }
+
+ /* -----------------------------------------------------------------------------
+ * outputDirectory()
+ *
+ * Return the directory to use for generating C# classes/enums and create the
+ * subdirectory (does not create if language specific outdir does not exist).
+ * ----------------------------------------------------------------------------- */
+
+ String *outputDirectory(String *nspace) {
+ String *output_directory = Copy(SWIG_output_directory());
+ if (nspace) {
+ String *nspace_subdirectory = Copy(nspace);
+ Replaceall(nspace_subdirectory, ".", SWIG_FILE_DELIMITER);
+ String *newdir_error = Swig_new_subdirectory(output_directory, nspace_subdirectory);
+ if (newdir_error) {
+ Printf(stderr, "%s\n", newdir_error);
+ Delete(newdir_error);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Printv(output_directory, nspace_subdirectory, SWIG_FILE_DELIMITER, 0);
+ Delete(nspace_subdirectory);
+ }
+ return output_directory;
+ }
+
+ /*----------------------------------------------------------------------
+ * Start of director methods
+ *--------------------------------------------------------------------*/
+
+#if 0
+ /*----------------------------------------------------------------------
+ * emitDirectorUpcalls()
+ *--------------------------------------------------------------------*/
+
+ void emitDirectorUpcalls() {
+ if (n_dmethods) {
+ Wrapper *w = NewWrapper();
+ String *dmethod_data = NewString("");
+ int n_methods = 0;
+ Iterator udata_iter;
+
+ udata_iter = First(dmethods_seq);
+ while (udata_iter.item) {
+ UpcallData *udata = udata_iter.item;
+ Printf(dmethod_data, " { \"%s\", \"%s\" }", Getattr(udata, "imclass_method"), Getattr(udata, "imclass_fdesc"));
+ ++n_methods;
+
+ udata_iter = Next(udata_iter);
+
+ if (udata_iter.item)
+ Putc(',', dmethod_data);
+ Putc('\n', dmethod_data);
+ }
+
+
+ Wrapper_print(w, f_wrappers);
+ Delete(dmethod_data);
+ Delete(swig_module_init);
+ DelWrapper(w);
+ }
+ }
+#endif
+
+ /*----------------------------------------------------------------------
+ * emitDirectorExtraMethods()
+ *
+ * This is where the director connect method is generated.
+ *--------------------------------------------------------------------*/
+ void emitDirectorExtraMethods(Node *n) {
+ if (!Swig_directorclass(n))
+ return;
+
+ // Output the director connect method:
+ String *norm_name = SwigType_namestr(Getattr(n, "name"));
+ String *dirclassname = directorClassName(n);
+ String *swig_director_connect = Swig_name_member(getNSpace(), getClassPrefix(), "director_connect");
+ String *wname = Swig_name_wrapper(swig_director_connect);
+ String *sym_name = Getattr(n, "sym:name");
+ String *qualified_classname = Copy(sym_name);
+ String *nspace = getNSpace();
+ String *dirClassName = directorClassName(n);
+ String *smartptr = Getattr(n, "feature:smartptr");
+ if (!GetFlag(n, "feature:flatnested")) {
+ for (Node *outer_class = Getattr(n, "nested:outer"); outer_class; outer_class = Getattr(outer_class, "nested:outer")) {
+
+ Push(qualified_classname, ".");
+ Push(qualified_classname, Getattr(outer_class, "sym:name"));
+ }
+ }
+ if (nspace)
+ Insert(qualified_classname, 0, NewStringf("%s.", nspace));
+
+ Printv(imclass_class_code, "\n [global::System.Runtime.InteropServices.DllImport(\"", dllimport, "\", EntryPoint=\"", wname, "\")]\n", NIL);
+ Printf(imclass_class_code, " public static extern void %s(global::System.Runtime.InteropServices.HandleRef jarg1", swig_director_connect);
+
+ Wrapper *code_wrap = NewWrapper();
+ Printf(code_wrap->def, "SWIGEXPORT void SWIGSTDCALL %s(void *objarg", wname);
+
+ if (smartptr) {
+ Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", smartptr, smartptr);
+ Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n");
+ Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n");
+ Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
+ } else {
+ Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", norm_name, norm_name);
+ Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName);
+ }
+
+ Printf(code_wrap->code, " director->swig_connect_director(");
+
+ for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *methid = Getattr(udata, "class_methodidx");
+
+ Printf(code_wrap->def, ", ");
+ if (i != first_class_dmethod)
+ Printf(code_wrap->code, ", ");
+ Printf(code_wrap->def, "%s::SWIG_Callback%s_t callback%s", dirclassname, methid, methid);
+ Printf(code_wrap->code, "callback%s", methid);
+ Printf(imclass_class_code, ", %s.SwigDelegate%s_%s delegate%s", qualified_classname, sym_name, methid, methid);
+ }
+
+ Printf(code_wrap->def, ") {\n");
+ Printf(code_wrap->code, ");\n");
+ Printf(imclass_class_code, ");\n");
+ Printf(code_wrap->code, "}\n");
+
+ Wrapper_print(code_wrap, f_wrappers);
+ DelWrapper(code_wrap);
+
+ Delete(wname);
+ Delete(swig_director_connect);
+ Delete(qualified_classname);
+ Delete(dirclassname);
+ }
+
+ /* ---------------------------------------------------------------
+ * classDirectorMethod()
+ *
+ * Emit a virtual director method to pass a method call on to the
+ * underlying C# object.
+ *
+ * --------------------------------------------------------------- */
+
+ int classDirectorMethod(Node *n, Node *parent, String *super) {
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ String *overloaded_name = getOverloadedName(n);
+ String *storage = Getattr(n, "storage");
+ String *value = Getattr(n, "value");
+ String *decl = Getattr(n, "decl");
+ String *declaration = NewString("");
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *terminator_code = NewString("");
+ String *tm;
+ Parm *p;
+ int i;
+ Wrapper *w = NewWrapper();
+ ParmList *l = Getattr(n, "parms");
+ bool is_void = !(Cmp(returntype, "void"));
+ String *qualified_return = 0;
+ bool pure_virtual = (!(Cmp(storage, "virtual")) && !(Cmp(value, "0")));
+ int status = SWIG_OK;
+ bool output_director = true;
+ String *dirclassname = directorClassName(parent);
+ String *qualified_name = NewStringf("%s::%s", dirclassname, name);
+ SwigType *c_ret_type = NULL;
+ String *jupcall_args = NewString("");
+ String *imclass_dmethod;
+ String *callback_typedef_parms = NewString("");
+ String *delegate_parms = NewString("");
+ String *proxy_method_types = NewString("");
+ String *callback_def = NewString("");
+ String *callback_code = NewString("");
+ String *imcall_args = NewString("");
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+
+ // Kludge Alert: functionWrapper sets sym:overload properly, but it
+ // isn't at this point, so we have to manufacture it ourselves. At least
+ // we're consistent with the sym:overload name in functionWrapper. (?? when
+ // does the overloaded method name get set?)
+
+ imclass_dmethod = NewStringf("SwigDirector_%s", Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name));
+
+ qualified_return = SwigType_rcaststr(returntype, "c_result");
+
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ String *base_typename = SwigType_base(returntype);
+ String *resolved_typename = SwigType_typedef_resolve_all(base_typename);
+ Symtab *symtab = Getattr(n, "sym:symtab");
+ Node *typenode = Swig_symbol_clookup(resolved_typename, symtab);
+
+ if (SwigType_ispointer(returntype) || (typenode && Getattr(typenode, "abstracts"))) {
+ /* initialize pointers to something sane. Same for abstract
+ classes when a reference is returned. */
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ } else {
+ /* If returning a reference, initialize the pointer to a sane
+ default - if a C# exception occurs, then the pointer returns
+ something other than a NULL-initialized reference. */
+ SwigType *noref_type = SwigType_del_reference(Copy(returntype));
+ String *noref_ltype = SwigType_lstr(noref_type, 0);
+ String *return_ltype = SwigType_lstr(returntype, 0);
+
+ Wrapper_add_localv(w, "result_default", "static", noref_ltype, "result_default", NIL);
+ Wrapper_add_localv(w, "c_result", return_ltype, "c_result", NIL);
+ Printf(w->code, "result_default = SwigValueInit< %s >();\n", noref_ltype);
+ Printf(w->code, "c_result = &result_default;\n");
+ Delete(return_ltype);
+ Delete(noref_ltype);
+ Delete(noref_type);
+ }
+
+ Delete(base_typename);
+ Delete(resolved_typename);
+ }
+ } else {
+ SwigType *vt;
+
+ vt = cplus_value_type(returntype);
+ if (!vt) {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(vt, "c_result"), NIL);
+ Delete(vt);
+ }
+ }
+ }
+
+ /* Create the intermediate class wrapper */
+ tm = Swig_typemap_lookup("imtype", n, "", 0);
+ if (tm) {
+ String *imtypeout = Getattr(n, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap
+ if (imtypeout)
+ tm = imtypeout;
+ const String *im_directoroutattributes = Getattr(n, "tmap:imtype:directoroutattributes");
+ if (im_directoroutattributes) {
+ Printf(callback_def, " %s\n", im_directoroutattributes);
+ if (!ignored_method)
+ Printf(director_delegate_definitions, " %s\n", im_directoroutattributes);
+ }
+
+ Printf(callback_def, " private %s SwigDirectorMethod%s(", tm, overloaded_name);
+ if (!ignored_method) {
+ const String *csdirectordelegatemodifiers = Getattr(n, "feature:csdirectordelegatemodifiers");
+ String *modifiers = (csdirectordelegatemodifiers ? NewStringf("%s%s", csdirectordelegatemodifiers, Len(csdirectordelegatemodifiers) > 0 ? " " : "") : NewStringf("public "));
+ Printf(director_delegate_definitions, " %sdelegate %s", modifiers, tm);
+ Delete(modifiers);
+ }
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(returntype, 0));
+ }
+
+ if ((c_ret_type = Swig_typemap_lookup("ctype", n, "", 0))) {
+ if (!is_void && !ignored_method) {
+ String *jretval_decl = NewStringf("%s jresult", c_ret_type);
+ Wrapper_add_localv(w, "jresult", jretval_decl, "= 0", NIL);
+ Delete(jretval_decl);
+ }
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Swig_director_parms_fixup(l);
+
+ /* Attach the standard typemaps */
+ Swig_typemap_attach_parms("out", l, 0);
+ Swig_typemap_attach_parms("ctype", l, 0);
+ Swig_typemap_attach_parms("imtype", l, 0);
+ Swig_typemap_attach_parms("cstype", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("csdirectorin", l, 0);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ /* Preamble code */
+ if (!ignored_method)
+ Printf(w->code, "if (!swig_callback%s) {\n", overloaded_name);
+
+ if (!pure_virtual) {
+ String *super_call = Swig_method_call(super, l);
+ if (is_void) {
+ Printf(w->code, "%s;\n", super_call);
+ if (!ignored_method)
+ Printf(w->code, "return;\n");
+ } else {
+ Printf(w->code, "return %s;\n", super_call);
+ }
+ Delete(super_call);
+ } else {
+ Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
+ if (!is_void)
+ Printf(w->code, "return %s;", qualified_return);
+ else if (!ignored_method)
+ Printf(w->code, "return;\n");
+ }
+
+ if (!ignored_method)
+ Printf(w->code, "} else {\n");
+
+ /* Go through argument list, convert from native to C# */
+ for (i = 0, p = l; p; ++i) {
+ /* Is this superfluous? */
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = makeParameterName(n, p, i, false);
+ String *c_param_type = NULL;
+ String *c_decl = NewString("");
+ String *arg = NewString("");
+
+ Printf(arg, "j%s", ln);
+
+ /* And add to the upcall args */
+ if (i > 0)
+ Printf(jupcall_args, ", ");
+ Printf(jupcall_args, "%s", arg);
+
+ /* Get parameter's intermediary C type */
+ if ((c_param_type = Getattr(p, "tmap:ctype"))) {
+ String *ctypeout = Getattr(p, "tmap:ctype:out"); // the type in the ctype typemap's out attribute overrides the type in the typemap
+ if (ctypeout)
+ c_param_type = ctypeout;
+
+ /* Add to local variables */
+ Printf(c_decl, "%s %s", c_param_type, arg);
+ if (!ignored_method)
+ Wrapper_add_localv(w, arg, c_decl, (!(SwigType_ispointer(pt) || SwigType_isreference(pt)) ? "" : "= 0"), NIL);
+
+ /* Add input marshalling code */
+ if ((tm = Getattr(p, "tmap:directorin"))) {
+
+ Setattr(p, "emit:directorinput", arg);
+ Replaceall(tm, "$input", arg);
+ Replaceall(tm, "$owner", "0");
+
+ if (Len(tm))
+ if (!ignored_method)
+ Printf(w->code, "%s\n", tm);
+
+ /* Add C type to callback typedef */
+ if (i > 0)
+ Printf(callback_typedef_parms, ", ");
+ Printf(callback_typedef_parms, "%s", c_param_type);
+
+ /* Add parameter to the intermediate class code if generating the
+ * intermediate's upcall code */
+ if ((tm = Getattr(p, "tmap:imtype"))) {
+
+ String *imtypeout = Getattr(p, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap
+ if (imtypeout)
+ tm = imtypeout;
+ const String *im_directorinattributes = Getattr(p, "tmap:imtype:directorinattributes");
+
+ String *din = Copy(Getattr(p, "tmap:csdirectorin"));
+
+ if (din) {
+ Replaceall(din, "$module", module_class_name);
+ Replaceall(din, "$imclassname", imclass_name);
+ substituteClassname(pt, din);
+ Replaceall(din, "$iminput", ln);
+
+ // pre and post attribute support
+ String *pre = Getattr(p, "tmap:csdirectorin:pre");
+ if (pre) {
+ substituteClassname(pt, pre);
+ Replaceall(pre, "$iminput", ln);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:csdirectorin:post");
+ if (post) {
+ substituteClassname(pt, post);
+ Replaceall(post, "$iminput", ln);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ String *terminator = Getattr(p, "tmap:csdirectorin:terminator");
+ if (terminator) {
+ substituteClassname(pt, terminator);
+ Replaceall(terminator, "$iminput", ln);
+ if (Len(terminator_code) > 0)
+ Insert(terminator_code, 0, "\n");
+ Insert(terminator_code, 0, terminator);
+ }
+
+ if (i > 0) {
+ Printf(delegate_parms, ", ");
+ Printf(proxy_method_types, ", ");
+ Printf(imcall_args, ", ");
+ }
+ Printf(delegate_parms, "%s%s %s", im_directorinattributes ? im_directorinattributes : empty_string, tm, ln);
+
+ if (Cmp(din, ln)) {
+ Printv(imcall_args, din, NIL);
+ } else
+ Printv(imcall_args, ln, NIL);
+
+ /* Get the C# parameter type */
+ if ((tm = Getattr(p, "tmap:cstype"))) {
+ substituteClassname(pt, tm);
+ int flags = DOH_REPLACE_FIRST | DOH_REPLACE_ID_BEGIN | DOH_REPLACE_NOCOMMENT;
+ if (Replace(tm, "ref ", "", flags) || Replace(tm, "ref\t", "", flags)) {
+ Printf(proxy_method_types, "typeof(%s).MakeByRefType()", tm);
+ } else if (Replace(tm, "out ", "", flags) || Replace(tm, "out\t", "", flags)) {
+ Printf(proxy_method_types, "typeof(%s).MakeByRefType()", tm);
+ } else {
+ Printf(proxy_method_types, "typeof(%s)", tm);
+ }
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number, "No csdirectorin typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ p = Getattr(p, "tmap:directorin:next");
+
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number,
+ "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ p = nextSibling(p);
+ output_director = false;
+ }
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ p = nextSibling(p);
+ }
+
+ Delete(ln);
+ Delete(arg);
+ Delete(c_decl);
+ }
+
+ /* header declaration, start wrapper definition */
+ String *target;
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Add any exception specifications to the methods in the director class
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ ParmList *throw_parm_list = NULL;
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list)
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+ Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0));
+ Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0));
+ }
+ }
+
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+
+ /* Finish off the inherited upcall's definition */
+
+ Printf(callback_def, "%s)", delegate_parms);
+ Printf(callback_def, " {\n");
+
+ /* Emit the intermediate class's upcall to the actual class */
+
+ String *upcall = NewStringf("%s(%s)", symname, imcall_args);
+
+ if ((tm = Swig_typemap_lookup("csdirectorout", n, "", 0))) {
+ substituteClassname(returntype, tm);
+ Replaceall(tm, "$cscall", upcall);
+ if (!is_void)
+ Insert(tm, 0, "return ");
+ Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
+
+ // pre and post attribute support
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ bool is_terminator_code = Len(terminator_code) > 0;
+ if (is_pre_code && is_post_code)
+ Printf(callback_code, "%s\n try {\n %s;\n } finally {\n%s\n }\n", pre_code, tm, post_code);
+ else if (is_pre_code)
+ Printf(callback_code, "%s\n %s;\n", pre_code, tm);
+ else if (is_post_code)
+ Printf(callback_code, " try {\n %s;\n } finally {\n%s\n }\n", tm, post_code);
+ else
+ Printf(callback_code, " %s;\n", tm);
+ if (is_terminator_code)
+ Printv(callback_code, "\n", terminator_code, NIL);
+ }
+
+ Printf(callback_code, " }\n");
+ Delete(upcall);
+
+ if (!ignored_method) {
+ if (!is_void)
+ Printf(w->code, "jresult = (%s) ", c_ret_type);
+
+ Printf(w->code, "swig_callback%s(%s);\n", overloaded_name, jupcall_args);
+
+ if (!is_void) {
+ String *jresult_str = NewString("jresult");
+ String *result_str = NewString("c_result");
+
+ /* Copy jresult into c_result... */
+ if ((tm = Swig_typemap_lookup("directorout", n, result_str, w))) {
+ Replaceall(tm, "$input", jresult_str);
+ Replaceall(tm, "$result", result_str);
+ Printf(w->code, "%s\n", tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s used in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Delete(jresult_str);
+ Delete(result_str);
+ }
+
+ /* Marshal outputs */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout"))) {
+ canThrow(n, "directorargout", p);
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Terminate wrapper code */
+ Printf(w->code, "}\n");
+ if (!is_void)
+ Printf(w->code, "return %s;", qualified_return);
+ }
+
+ Printf(w->code, "}");
+
+ // We expose virtual protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewString("");
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+
+ /* emit the director method */
+ if (status == SWIG_OK && output_director) {
+ if (!is_void) {
+ Replaceall(w->code, "$null", qualified_return);
+ } else {
+ Replaceall(w->code, "$null", "");
+ }
+ if (!ignored_method)
+ Printv(director_delegate_callback, "\n", callback_def, callback_code, NIL);
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+
+ if (!ignored_method) {
+ /* Emit the actual upcall through */
+ UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, decl, overloaded_name);
+ String *methid = Getattr(udata, "class_methodidx");
+ Setattr(n, "upcalldata", udata);
+ /*
+ Printf(stdout, "setting upcalldata, nodeType: %s %s::%s %p\n", nodeType(n), classname, Getattr(n, "name"), n);
+ */
+
+ Printf(director_callback_typedefs, " typedef %s (SWIGSTDCALL* SWIG_Callback%s_t)(", c_ret_type, methid);
+ Printf(director_callback_typedefs, "%s);\n", callback_typedef_parms);
+ Printf(director_callbacks, " SWIG_Callback%s_t swig_callback%s;\n", methid, overloaded_name);
+
+ Printf(director_delegate_definitions, " SwigDelegate%s_%s(%s);\n", classname, methid, delegate_parms);
+ Printf(director_delegate_instances, " private SwigDelegate%s_%s swigDelegate%s;\n", classname, methid, methid);
+ Printf(director_method_types, " private static global::System.Type[] swigMethodTypes%s = new global::System.Type[] { %s };\n", methid, proxy_method_types);
+ Printf(director_connect_parms, "SwigDirector%s%s delegate%s", classname, methid, methid);
+ }
+
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(terminator_code);
+ Delete(qualified_return);
+ Delete(declaration);
+ Delete(callback_typedef_parms);
+ Delete(delegate_parms);
+ Delete(proxy_method_types);
+ Delete(callback_def);
+ Delete(callback_code);
+ Delete(dirclassname);
+ DelWrapper(w);
+
+ return status;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorConstructor(Node *n) {
+ Node *parent = parentNode(n);
+ String *decl = Getattr(n, "decl");
+ String *supername = Swig_class_name(parent);
+ String *dirclassname = directorClassName(parent);
+ String *sub = NewString("");
+ Parm *p;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms;
+ int argidx = 0;
+
+ /* Assign arguments to superclass's parameters, if not already done */
+ for (p = superparms; p; p = nextSibling(p)) {
+ String *pname = Getattr(p, "name");
+
+ if (!pname) {
+ pname = NewStringf("arg%d", argidx++);
+ Setattr(p, "name", pname);
+ }
+ }
+
+ // TODO: Is this copy needed?
+ parms = CopyParmList(superparms);
+
+ if (!Getattr(n, "defaultargs")) {
+ /* constructor */
+ {
+ String *basetype = Getattr(parent, "classtype");
+ String *target = Swig_method_decl(0, decl, dirclassname, parms, 0);
+ String *call = Swig_csuperclass_call(0, basetype, superparms);
+
+ Printf(f_directors, "%s::%s : %s, %s {\n", dirclassname, target, call, Getattr(parent, "director:ctor"));
+ Printf(f_directors, " swig_init_callbacks();\n");
+ Printf(f_directors, "}\n\n");
+
+ Delete(target);
+ Delete(call);
+ }
+
+ /* constructor header */
+ {
+ String *target = Swig_method_decl(0, decl, dirclassname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Delete(sub);
+ Delete(supername);
+ Delete(parms);
+ Delete(dirclassname);
+ return Language::classDirectorConstructor(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDefaultConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorDefaultConstructor(Node *n) {
+ String *dirclassname = directorClassName(n);
+ String *classtype = SwigType_namestr(Getattr(n, "name"));
+ Wrapper *w = NewWrapper();
+
+ Printf(w->def, "%s::%s() : %s {", dirclassname, dirclassname, Getattr(n, "director:ctor"));
+ Printf(w->code, "}\n");
+ Wrapper_print(w, f_directors);
+
+ Printf(f_directors_h, " %s();\n", dirclassname);
+ DelWrapper(w);
+ Delete(classtype);
+ Delete(dirclassname);
+ return Language::classDirectorDefaultConstructor(n);
+ }
+
+
+ /* ------------------------------------------------------------
+ * classDirectorInit()
+ * ------------------------------------------------------------ */
+
+ int classDirectorInit(Node *n) {
+ Delete(none_comparison);
+ none_comparison = NewString(""); // not used
+
+ Delete(director_ctor_code);
+ director_ctor_code = NewString("$director_new");
+
+ directorDeclaration(n);
+
+ Printf(f_directors_h, "%s {\n", Getattr(n, "director:decl"));
+ Printf(f_directors_h, "\npublic:\n");
+
+ /* Keep track of the director methods for this class */
+ first_class_dmethod = curr_class_dmethod = n_dmethods;
+
+ director_callback_typedefs = NewString("");
+ director_callbacks = NewString("");
+ director_delegate_callback = NewString("");
+ director_delegate_definitions = NewString("");
+ director_delegate_instances = NewString("");
+ director_method_types = NewString("");
+ director_connect_parms = NewString("");
+
+ return Language::classDirectorInit(n);
+ }
+
+ int classDeclaration(Node *n) {
+ String *old_director_callback_typedefs = director_callback_typedefs;
+ String *old_director_callbacks = director_callbacks;
+ String *old_director_delegate_callback = director_delegate_callback;
+ String *old_director_delegate_definitions = director_delegate_definitions;
+ String *old_director_delegate_instances = director_delegate_instances;
+ String *old_director_method_types = director_method_types;
+ String *old_director_connect_parms = director_connect_parms;
+
+ int ret = Language::classDeclaration(n);
+
+ // these variables are deleted in emitProxyClassDefAndCPPCasts, hence no Delete here
+ director_callback_typedefs = old_director_callback_typedefs;
+ director_callbacks = old_director_callbacks;
+ director_delegate_callback = old_director_delegate_callback;
+ director_delegate_definitions = old_director_delegate_definitions;
+ director_delegate_instances = old_director_delegate_instances;
+ director_method_types = old_director_method_types;
+ director_connect_parms = old_director_connect_parms;
+
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * classDirectorDestructor()
+ * ---------------------------------------------------------------------- */
+
+ int classDirectorDestructor(Node *n) {
+ Node *current_class = getCurrentClass();
+ String *dirclassname = directorClassName(current_class);
+ Wrapper *w = NewWrapper();
+
+ if (Getattr(n, "noexcept")) {
+ Printf(f_directors_h, " virtual ~%s() noexcept;\n", dirclassname);
+ Printf(w->def, "%s::~%s() noexcept {\n", dirclassname, dirclassname);
+ } else if (Getattr(n, "throw")) {
+ Printf(f_directors_h, " virtual ~%s() throw();\n", dirclassname);
+ Printf(w->def, "%s::~%s() throw() {\n", dirclassname, dirclassname);
+ } else {
+ Printf(f_directors_h, " virtual ~%s();\n", dirclassname);
+ Printf(w->def, "%s::~%s() {\n", dirclassname, dirclassname);
+ }
+
+ Printv(w->code, "}\n", NIL);
+
+ Wrapper_print(w, f_directors);
+
+ DelWrapper(w);
+ Delete(dirclassname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorEnd()
+ * ------------------------------------------------------------ */
+
+ int classDirectorEnd(Node *n) {
+ int i;
+ String *dirclassname = directorClassName(n);
+
+ Wrapper *w = NewWrapper();
+
+ if (Len(director_callback_typedefs) > 0) {
+ Printf(f_directors_h, "\n%s", director_callback_typedefs);
+ }
+
+ Printf(f_directors_h, " void swig_connect_director(");
+
+ Printf(w->def, "void %s::swig_connect_director(", dirclassname);
+
+ for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *methid = Getattr(udata, "class_methodidx");
+ String *overname = Getattr(udata, "overname");
+
+ Printf(f_directors_h, "SWIG_Callback%s_t callback%s", methid, overname);
+ Printf(w->def, "SWIG_Callback%s_t callback%s", methid, overname);
+ Printf(w->code, "swig_callback%s = callback%s;\n", overname, overname);
+ if (i != curr_class_dmethod - 1) {
+ Printf(f_directors_h, ", ");
+ Printf(w->def, ", ");
+ }
+ }
+
+ Printf(f_directors_h, ");\n");
+ Printf(w->def, ") {");
+
+
+ if (Len(director_callbacks) > 0) {
+ Printf(f_directors_h, "\nprivate:\n%s", director_callbacks);
+ }
+ Printf(f_directors_h, " void swig_init_callbacks();\n");
+ Printf(f_directors_h, "};\n\n");
+ Printf(w->code, "}\n\n");
+
+ Printf(w->code, "void %s::swig_init_callbacks() {\n", dirclassname);
+ for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *overname = Getattr(udata, "overname");
+ Printf(w->code, "swig_callback%s = 0;\n", overname);
+ }
+ Printf(w->code, "}");
+
+ Wrapper_print(w, f_directors);
+
+ DelWrapper(w);
+ Delete(dirclassname);
+
+ return Language::classDirectorEnd(n);
+ }
+
+ /* --------------------------------------------------------------------
+ * classDirectorDisown()
+ * ------------------------------------------------------------------*/
+ virtual int classDirectorDisown(Node *n) {
+ (void) n;
+ return SWIG_OK;
+ }
+
+ /*----------------------------------------------------------------------
+ * extraDirectorProtectedCPPMethodsRequired()
+ *--------------------------------------------------------------------*/
+
+ bool extraDirectorProtectedCPPMethodsRequired() const {
+ return false;
+ }
+
+ /*----------------------------------------------------------------------
+ * directorDeclaration()
+ *
+ * Generate the director class's declaration
+ * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
+ *--------------------------------------------------------------------*/
+
+ void directorDeclaration(Node *n) {
+
+ String *base = Getattr(n, "classtype");
+ String *class_ctor = NewString("Swig::Director()");
+
+ String *dirclassname = directorClassName(n);
+ String *declaration = Swig_class_declaration(n, dirclassname);
+
+ Printf(declaration, " : public %s, public Swig::Director", base);
+
+ // Stash stuff for later.
+ Setattr(n, "director:decl", declaration);
+ Setattr(n, "director:ctor", class_ctor);
+
+ Delete(dirclassname);
+ }
+
+ /*----------------------------------------------------------------------
+ * nestedClassesSupport()
+ *--------------------------------------------------------------------*/
+
+ NestedClassSupport nestedClassesSupport() const {
+ return NCS_Full;
+ }
+}; /* class CSHARP */
+
+/* -----------------------------------------------------------------------------
+ * swig_csharp() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_csharp() {
+ return new CSHARP();
+}
+extern "C" Language *swig_csharp(void) {
+ return new_swig_csharp();
+}
+
+/* -----------------------------------------------------------------------------
+ * Static member variables
+ * ----------------------------------------------------------------------------- */
+
+const char *CSHARP::usage = "\
+C# Options (available with -csharp)\n\
+ -dllimport <dl> - Override DllImport attribute name to <dl>\n\
+ -namespace <nm> - Generate wrappers into C# namespace <nm>\n\
+ -noproxy - Generate the low-level functional interface instead\n\
+ of proxy classes\n\
+ -oldvarnames - Old intermediary method names for variable wrappers\n\
+ -outfile <file> - Write all C# into a single <file> located in the output directory\n\
+\n";
diff --git a/contrib/tools/swig/Source/Modules/d.cxx b/contrib/tools/swig/Source/Modules/d.cxx
new file mode 100644
index 00000000000..b7283eac221
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/d.cxx
@@ -0,0 +1,4647 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * d.cxx
+ *
+ * D language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+#include <ctype.h>
+
+// Hash type used for storing information about director callbacks for a class.
+typedef DOH UpcallData;
+
+class D : public Language {
+ static const char *usage;
+ const String *empty_string;
+ const String *public_string;
+ const String *protected_string;
+
+ /*
+ * Files and file sections containing C/C++ code.
+ */
+ File *f_begin;
+ File *f_runtime;
+ File *f_runtime_h;
+ File *f_header;
+ File *f_wrappers;
+ File *f_init;
+ File *f_directors;
+ File *f_directors_h;
+ List *filenames_list;
+
+ /*
+ * Command line-set modes of operation.
+ */
+ // Whether a single proxy D module is generated or classes and enums are
+ // written to their own files.
+ bool split_proxy_dmodule;
+
+ // The major D version targeted (currently 1 or 2).
+ unsigned short d_version;
+
+ /*
+ * State variables which indicate what is being wrapped at the moment.
+ * This is probably not the most elegant way of handling state, but it has
+ * proven to work in the C# and Java modules.
+ */
+ // Indicates if wrapping a native function.
+ bool native_function_flag;
+
+ // Indicates if wrapping a static functions or member variables
+ bool static_flag;
+
+ // Indicates if wrapping a nonstatic member variable
+ bool variable_wrapper_flag;
+
+ // Indicates if wrapping a member variable/enum/const.
+ bool wrapping_member_flag;
+
+ // Indicates if wrapping a global variable.
+ bool global_variable_flag;
+
+ // Name of a variable being wrapped.
+ String *variable_name;
+
+ /*
+ * Variables temporarily holding the generated C++ code.
+ */
+ // C++ code for the generated wrapper functions for casts up the C++
+ // for inheritance hierarchies.
+ String *upcasts_code;
+
+ // Function pointer typedefs for handling director callbacks on the C++ side.
+ String *director_callback_typedefs;
+
+ // Variables for storing the function pointers to the director callbacks on
+ // the C++ side.
+ String *director_callback_pointers;
+
+ /*
+ * Names of generated D entities.
+ */
+ // The name of the D module containing the interface to the C wrapper.
+ String *im_dmodule_name;
+
+ // The fully qualified name of the wrap D module (package name included).
+ String *im_dmodule_fq_name;
+
+ // The name of the proxy module which exposes the (SWIG) module contents as a
+ // D module.
+ String *proxy_dmodule_name;
+
+ // The fully qualified name of the proxy D module.
+ String *proxy_dmodule_fq_name;
+
+ // Optional: Package the D modules are placed in (set via the -package
+ // command line option).
+ String *package;
+
+ // The directory the generated D module files are written to. Is constructed
+ // from the package path if a target package is set, points to the general
+ // output directory otherwise.
+ String *dmodule_directory;
+
+ // The name of the library which contains the C wrapper (used when generating
+ // the dynamic library loader). Can be overridden via the -wrapperlibrary
+ // command line flag.
+ String *wrap_library_name;
+
+ /*
+ * Variables temporarily holding the generated D code.
+ */
+ // Import statements written to the intermediary D module header set via
+ // %pragma(d) imdmoduleimports.
+ String *im_dmodule_imports;
+
+ // The code for the intermediary D module body.
+ String *im_dmodule_code;
+
+ // Import statements for all proxy modules (the main proxy module and, if in
+ // split proxy module mode, the proxy class modules) from
+ // %pragma(d) globalproxyimports.
+ String *global_proxy_imports;
+
+ // The D code for the main proxy modules. nspace_proxy_dmodules is a hash from
+ // the namespace name as key to an {"imports", "code"}. If the nspace feature
+ // is not active, only proxy_dmodule_imports and proxy_dmodule_code are used,
+ // which contain the code for the root proxy module.
+ //
+ // These variables should not be accessed directly but rather via the
+ // proxy{Imports, Code}Buffer)() helper functions which return the right
+ // buffer for a given namespace. If not in split proxy mode, they contain the
+ // whole proxy code.
+ String *proxy_dmodule_imports;
+ String *proxy_dmodule_code;
+ Hash *nspace_proxy_dmodules;
+
+ // The D code generated for the currently processed enum.
+ String *proxy_enum_code;
+
+ /*
+ * D data for the current proxy class.
+ *
+ * These strings are mainly used to temporarily accumulate code from the
+ * various member handling functions while a single class is processed and are
+ * no longer relevant once that class has been finished, i.e. after
+ * classHandler() has returned.
+ */
+ // The unqualified name of the current proxy class.
+ String *proxy_class_name;
+
+ // The name of the current proxy class, qualified with the name of the
+ // namespace it is in, if any.
+ String *proxy_class_qname;
+
+ // The import directives for the current proxy class. They are written to the
+ // same D module the proxy class is written to.
+ String *proxy_class_imports;
+
+ // Code for enumerations nested in the current proxy class. Is emitted earlier
+ // than the rest of the body to work around forward referencing-issues.
+ String *proxy_class_enums_code;
+
+ // The generated D code making up the body of the current proxy class.
+ String *proxy_class_body_code;
+
+ // D code which is emitted right after the proxy class.
+ String *proxy_class_epilogue_code;
+
+ // The full code for the current proxy class, including the epilogue.
+ String* proxy_class_code;
+
+ // Contains a D call to the function wrapping C++ the destructor of the
+ // current class (if there is a public C++ destructor).
+ String *destructor_call;
+
+ // D code for the director callbacks generated for the current class.
+ String *director_dcallbacks_code;
+
+ /*
+ * Code for dynamically loading the wrapper library on the D side.
+ */
+ // D code which is inserted into the im D module if dynamic linking is used.
+ String *wrapper_loader_code;
+
+ // The D code to bind a function pointer to a library symbol.
+ String *wrapper_loader_bind_command;
+
+ // The cumulated binding commands binding all the functions declared in the
+ // intermediary D module to the C/C++ library symbols.
+ String *wrapper_loader_bind_code;
+
+ /*
+ * Director data.
+ */
+ List *dmethods_seq;
+ Hash *dmethods_table;
+ int n_dmethods;
+ int first_class_dmethod;
+ int curr_class_dmethod;
+
+ /*
+ * SWIG types data.
+ */
+ // Collects information about encountered types SWIG does not know about (e.g.
+ // incomplete types). This is used later to generate type wrapper proxy
+ // classes for the unknown types.
+ Hash *unknown_types;
+
+
+public:
+ /* ---------------------------------------------------------------------------
+ * D::D()
+ * --------------------------------------------------------------------------- */
+ D():empty_string(NewString("")),
+ public_string(NewString("public")),
+ protected_string(NewString("protected")),
+ f_begin(NULL),
+ f_runtime(NULL),
+ f_runtime_h(NULL),
+ f_header(NULL),
+ f_wrappers(NULL),
+ f_init(NULL),
+ f_directors(NULL),
+ f_directors_h(NULL),
+ filenames_list(NULL),
+ split_proxy_dmodule(false),
+ d_version(1),
+ native_function_flag(false),
+ static_flag(false),
+ variable_wrapper_flag(false),
+ wrapping_member_flag(false),
+ global_variable_flag(false),
+ variable_name(NULL),
+ upcasts_code(NULL),
+ director_callback_typedefs(NULL),
+ director_callback_pointers(NULL),
+ im_dmodule_name(NULL),
+ im_dmodule_fq_name(NULL),
+ proxy_dmodule_name(NULL),
+ proxy_dmodule_fq_name(NULL),
+ package(NULL),
+ dmodule_directory(NULL),
+ wrap_library_name(NULL),
+ im_dmodule_imports(NULL),
+ im_dmodule_code(NULL),
+ global_proxy_imports(NULL),
+ proxy_dmodule_imports(NULL),
+ proxy_dmodule_code(NULL),
+ nspace_proxy_dmodules(NULL),
+ proxy_enum_code(NULL),
+ proxy_class_name(NULL),
+ proxy_class_qname(NULL),
+ proxy_class_imports(NULL),
+ proxy_class_enums_code(NULL),
+ proxy_class_body_code(NULL),
+ proxy_class_epilogue_code(NULL),
+ proxy_class_code(NULL),
+ destructor_call(NULL),
+ director_dcallbacks_code(NULL),
+ wrapper_loader_code(NULL),
+ wrapper_loader_bind_command(NULL),
+ wrapper_loader_bind_code(NULL),
+ dmethods_seq(NULL),
+ dmethods_table(NULL),
+ n_dmethods(0),
+ first_class_dmethod(0),
+ curr_class_dmethod(0),
+ unknown_types(NULL) {
+
+ // For now, multiple inheritance with directors is not possible. It should be
+ // easy to implement though.
+ director_multiple_inheritance = 0;
+ director_language = 1;
+
+ // Not used:
+ Delete(none_comparison);
+ none_comparison = NewString("");
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::main()
+ * --------------------------------------------------------------------------- */
+ virtual void main(int argc, char *argv[]) {
+ SWIG_library_directory("d");
+
+ // Look for certain command line options
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if ((strcmp(argv[i], "-d2") == 0)) {
+ Swig_mark_arg(i);
+ d_version = 2;
+ } else if (strcmp(argv[i], "-wrapperlibrary") == 0) {
+ if (argv[i + 1]) {
+ wrap_library_name = NewString("");
+ Printf(wrap_library_name, argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-package") == 0) {
+ if (argv[i + 1]) {
+ package = NewString("");
+ Printf(package, argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if ((strcmp(argv[i], "-splitproxy") == 0)) {
+ Swig_mark_arg(i);
+ split_proxy_dmodule = true;
+ } else if (strcmp(argv[i], "-help") == 0) {
+ Printf(stdout, "%s\n", usage);
+ }
+ }
+ }
+
+ // Add a symbol to the parser for conditional compilation
+ Preprocessor_define("SWIGD 1", 0);
+
+ // Also make the target D version available as preprocessor symbol for
+ // use in our library files.
+ String *version_define = NewStringf("SWIG_D_VERSION %u", d_version);
+ Preprocessor_define(version_define, 0);
+ Delete(version_define);
+
+ // Add typemap definitions
+ SWIG_typemap_lang("d");
+ SWIG_config_file("d.swg");
+
+ allow_overloading();
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::top()
+ * --------------------------------------------------------------------------- */
+ virtual int top(Node *n) {
+ // Get any options set in the module directive
+ Node *optionsnode = Getattr(Getattr(n, "module"), "options");
+
+ if (optionsnode) {
+ if (Getattr(optionsnode, "imdmodulename")) {
+ im_dmodule_name = Copy(Getattr(optionsnode, "imdmodulename"));
+ }
+
+ if (Getattr(optionsnode, "directors")) {
+ // Check if directors are enabled for this module. Note: This is a
+ // "master switch", if it is not set, not director code will be emitted
+ // at all. %feature("director") statements are also required to enable
+ // directors for individual classes or methods.
+ //
+ // Use the »directors« attributte of the %module directive to enable
+ // director generation (e.g. »%module(directors="1") modulename«).
+ allow_directors();
+ }
+
+ if (Getattr(optionsnode, "dirprot")) {
+ allow_dirprot();
+ }
+
+ allow_allprotected(GetFlag(optionsnode, "allprotected"));
+ }
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+ String *outfile_h = Getattr(n, "outfile_h");
+
+ if (!outfile) {
+ Printf(stderr, "Unable to determine outfile\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ if (directorsEnabled()) {
+ if (!outfile_h) {
+ Printf(stderr, "Unable to determine outfile_h\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+ f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
+ if (!f_runtime_h) {
+ FileErrorDisplay(outfile_h);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+ f_directors_h = NewString("");
+ f_directors = NewString("");
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+
+ unknown_types = NewHash();
+ filenames_list = NewList();
+
+ // Make the package name and the resulting module output path.
+ if (package) {
+ // Append a dot so we can prepend the package variable directly to the
+ // module names in the rest of the code.
+ Printv(package, ".", NIL);
+ } else {
+ // Write the generated D modules to the »root« package by default.
+ package = NewString("");
+ }
+
+ dmodule_directory = Copy(SWIG_output_directory());
+ if (Len(package) > 0) {
+ String *package_directory = Copy(package);
+ Replaceall(package_directory, ".", SWIG_FILE_DELIMITER);
+ Printv(dmodule_directory, package_directory, NIL);
+ Delete(package_directory);
+ }
+
+ // Make the wrap and proxy D module names.
+ // The wrap module name can be set in the module directive.
+ if (!im_dmodule_name) {
+ im_dmodule_name = NewStringf("%s_im", Getattr(n, "name"));
+ }
+ im_dmodule_fq_name = NewStringf("%s%s", package, im_dmodule_name);
+ proxy_dmodule_name = Copy(Getattr(n, "name"));
+ proxy_dmodule_fq_name = NewStringf("%s%s", package, proxy_dmodule_name);
+
+ im_dmodule_code = NewString("");
+ proxy_class_imports = NewString("");
+ proxy_class_enums_code = NewString("");
+ proxy_class_body_code = NewString("");
+ proxy_class_epilogue_code = NewString("");
+ proxy_class_code = NewString("");
+ destructor_call = NewString("");
+ proxy_dmodule_code = NewString("");
+ proxy_dmodule_imports = NewString("");
+ nspace_proxy_dmodules = NewHash();
+ im_dmodule_imports = NewString("");
+ upcasts_code = NewString("");
+ global_proxy_imports = NewString("");
+ wrapper_loader_code = NewString("");
+ wrapper_loader_bind_command = NewString("");
+ wrapper_loader_bind_code = NewString("");
+ dmethods_seq = NewList();
+ dmethods_table = NewHash();
+ n_dmethods = 0;
+
+ // By default, expect the dynamically loaded wrapper library to be named
+ // [lib]<module>_wrap[.so/.dll].
+ if (!wrap_library_name)
+ wrap_library_name = NewStringf("%s_wrap", Getattr(n, "name"));
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n\n#ifndef SWIGD\n#define SWIGD\n#endif\n\n");
+
+ if (directorsEnabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+
+ /* Emit initial director header and director code: */
+ Swig_banner(f_directors_h);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", proxy_dmodule_name);
+ Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", proxy_dmodule_name);
+
+ Printf(f_directors, "\n\n");
+ Printf(f_directors, "/* ---------------------------------------------------\n");
+ Printf(f_directors, " * C++ director class methods\n");
+ Printf(f_directors, " * --------------------------------------------------- */\n\n");
+ if (outfile_h) {
+ String *filename = Swig_file_filename(outfile_h);
+ Printf(f_directors, "#include \"%s\"\n\n", filename);
+ Delete(filename);
+ }
+ }
+
+ Printf(f_runtime, "\n");
+
+ Swig_name_register("wrapper", "D_%f");
+
+ Printf(f_wrappers, "\n#ifdef __cplusplus\n");
+ Printf(f_wrappers, "extern \"C\" {\n");
+ Printf(f_wrappers, "#endif\n\n");
+
+ // Emit all the wrapper code.
+ Language::top(n);
+
+ if (directorsEnabled()) {
+ // Insert director runtime into the f_runtime file (before %header section).
+ Swig_insert_file("director_common.swg", f_runtime);
+ Swig_insert_file("director.swg", f_runtime);
+ }
+
+ // Generate the wrap D module.
+ // TODO: Add support for »static« linking.
+ {
+ String *filen = NewStringf("%s%s.d", dmodule_directory, im_dmodule_name);
+ File *im_d_file = NewFile(filen, "w", SWIG_output_files());
+ if (!im_d_file) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ // Start writing out the intermediary class file.
+ emitBanner(im_d_file);
+
+ Printf(im_d_file, "module %s;\n", im_dmodule_fq_name);
+
+ Printv(im_d_file, im_dmodule_imports, "\n", NIL);
+
+ Replaceall(wrapper_loader_code, "$wraplibrary", wrap_library_name);
+ Replaceall(wrapper_loader_code, "$wrapperloaderbindcode", wrapper_loader_bind_code);
+ Replaceall(wrapper_loader_code, "$module", proxy_dmodule_name);
+ Printf(im_d_file, "%s\n", wrapper_loader_code);
+
+ // Add the wrapper function declarations.
+ replaceModuleVariables(im_dmodule_code);
+ Printv(im_d_file, im_dmodule_code, NIL);
+
+ Delete(im_d_file);
+ }
+
+ // Generate the main D proxy module.
+ {
+ String *filen = NewStringf("%s%s.d", dmodule_directory, proxy_dmodule_name);
+ File *proxy_d_file = NewFile(filen, "w", SWIG_output_files());
+ if (!proxy_d_file) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ emitBanner(proxy_d_file);
+
+ Printf(proxy_d_file, "module %s;\n", proxy_dmodule_fq_name);
+ Printf(proxy_d_file, "\nstatic import %s;\n", im_dmodule_fq_name);
+ Printv(proxy_d_file, global_proxy_imports, NIL);
+ Printv(proxy_d_file, proxy_dmodule_imports, NIL);
+ Printv(proxy_d_file, "\n", NIL);
+
+ // Write a D type wrapper class for each SWIG type to the proxy module code.
+ for (Iterator swig_type = First(unknown_types); swig_type.key; swig_type = Next(swig_type)) {
+ writeTypeWrapperClass(swig_type.key, swig_type.item);
+ }
+
+ // Add the proxy functions (and classes, if they are not written to a separate file).
+ replaceModuleVariables(proxy_dmodule_code);
+ Printv(proxy_d_file, proxy_dmodule_code, NIL);
+
+ Delete(proxy_d_file);
+ }
+
+ // Generate the additional proxy modules for nspace support.
+ for (Iterator it = First(nspace_proxy_dmodules); it.key; it = Next(it)) {
+ String *module_name = createLastNamespaceName(it.key);
+
+ String *filename = NewStringf("%s%s.d", outputDirectory(it.key), module_name);
+ File *file = NewFile(filename, "w", SWIG_output_files());
+ if (!file) {
+ FileErrorDisplay(filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(filename);
+
+ emitBanner(file);
+
+ Printf(file, "module %s%s.%s;\n", package, it.key, module_name);
+ Printf(file, "\nstatic import %s;\n", im_dmodule_fq_name);
+ Printv(file, global_proxy_imports, NIL);
+ Printv(file, Getattr(it.item, "imports"), NIL);
+ Printv(file, "\n", NIL);
+
+ String *code = Getattr(it.item, "code");
+ replaceModuleVariables(code);
+ Printv(file, code, NIL);
+
+ Delete(file);
+ Delete(module_name);
+ }
+
+ if (upcasts_code)
+ Printv(f_wrappers, upcasts_code, NIL);
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n");
+ Printf(f_wrappers, "}\n");
+ Printf(f_wrappers, "#endif\n");
+
+ // Check for overwriting file problems on filesystems that are case insensitive
+ Iterator it1;
+ Iterator it2;
+ for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) {
+ String *item1_lower = Swig_string_lower(it1.item);
+ for (it2 = Next(it1); it2.item; it2 = Next(it2)) {
+ String *item2_lower = Swig_string_lower(it2.item);
+ if (it1.item && it2.item) {
+ if (Strcmp(item1_lower, item2_lower) == 0) {
+ Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number,
+ "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as "
+ "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item);
+ }
+ }
+ Delete(item2_lower);
+ }
+ Delete(item1_lower);
+ }
+
+ Delete(unknown_types);
+ unknown_types = NULL;
+ Delete(filenames_list);
+ filenames_list = NULL;
+ Delete(im_dmodule_name);
+ im_dmodule_name = NULL;
+ Delete(im_dmodule_fq_name);
+ im_dmodule_fq_name = NULL;
+ Delete(im_dmodule_code);
+ im_dmodule_code = NULL;
+ Delete(proxy_class_imports);
+ proxy_class_imports = NULL;
+ Delete(proxy_class_enums_code);
+ proxy_class_enums_code = NULL;
+ Delete(proxy_class_body_code);
+ proxy_class_body_code = NULL;
+ Delete(proxy_class_epilogue_code);
+ proxy_class_epilogue_code = NULL;
+ Delete(proxy_class_code);
+ proxy_class_code = NULL;
+ Delete(destructor_call);
+ destructor_call = NULL;
+ Delete(proxy_dmodule_name);
+ proxy_dmodule_name = NULL;
+ Delete(proxy_dmodule_fq_name);
+ proxy_dmodule_fq_name = NULL;
+ Delete(proxy_dmodule_code);
+ proxy_dmodule_code = NULL;
+ Delete(proxy_dmodule_imports);
+ proxy_dmodule_imports = NULL;
+ Delete(nspace_proxy_dmodules);
+ nspace_proxy_dmodules = NULL;
+ Delete(im_dmodule_imports);
+ im_dmodule_imports = NULL;
+ Delete(upcasts_code);
+ upcasts_code = NULL;
+ Delete(global_proxy_imports);
+ global_proxy_imports = NULL;
+ Delete(wrapper_loader_code);
+ wrapper_loader_code = NULL;
+ Delete(wrapper_loader_bind_code);
+ wrapper_loader_bind_code = NULL;
+ Delete(wrapper_loader_bind_command);
+ wrapper_loader_bind_command = NULL;
+ Delete(dmethods_seq);
+ dmethods_seq = NULL;
+ Delete(dmethods_table);
+ dmethods_table = NULL;
+ Delete(package);
+ package = NULL;
+ Delete(dmodule_directory);
+ dmodule_directory = NULL;
+ n_dmethods = 0;
+
+ // Merge all the generated C/C++ code and close the output files.
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+
+ if (directorsEnabled()) {
+ Dump(f_directors, f_begin);
+ Dump(f_directors_h, f_runtime_h);
+
+ Printf(f_runtime_h, "\n");
+ Printf(f_runtime_h, "#endif\n");
+
+ Delete(f_runtime_h);
+ f_runtime_h = NULL;
+ Delete(f_directors);
+ f_directors = NULL;
+ Delete(f_directors_h);
+ f_directors_h = NULL;
+ }
+
+ Dump(f_wrappers, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_runtime);
+ Delete(f_begin);
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::insertDirective()
+ * --------------------------------------------------------------------------- */
+ virtual int insertDirective(Node *n) {
+ int ret = SWIG_OK;
+ String *code = Getattr(n, "code");
+ String *section = Getattr(n, "section");
+ replaceModuleVariables(code);
+
+ if (!ImportMode && (Cmp(section, "proxycode") == 0)) {
+ if (proxy_class_body_code) {
+ Swig_typemap_replace_embedded_typemap(code, n);
+ Printv(proxy_class_body_code, code, NIL);
+ }
+ } else {
+ ret = Language::insertDirective(n);
+ }
+ return ret;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::pragmaDirective()
+ *
+ * Valid Pragmas:
+ * imdmodulecode - text (D code) is copied verbatim to the wrap module
+ * imdmoduleimports - import statements for the im D module
+ *
+ * proxydmodulecode - text (D code) is copied verbatim to the proxy module
+ * (the main proxy module if in split proxy mode).
+ * globalproxyimports - import statements inserted into _all_ proxy modules.
+ *
+ * wrapperloadercode - D code for loading the wrapper library (is copied to
+ * the im D module).
+ * wrapperloaderbindcommand - D code for binding a symbol from the wrapper
+ * library to the declaration in the im D module.
+ * --------------------------------------------------------------------------- */
+ virtual int pragmaDirective(Node *n) {
+ if (!ImportMode) {
+ String *lang = Getattr(n, "lang");
+ String *code = Getattr(n, "name");
+ String *value = Getattr(n, "value");
+
+ if (Strcmp(lang, "d") == 0) {
+ String *strvalue = NewString(value);
+ Replaceall(strvalue, "\\\"", "\"");
+
+ if (Strcmp(code, "imdmodulecode") == 0) {
+ Printf(im_dmodule_code, "%s\n", strvalue);
+ } else if (Strcmp(code, "imdmoduleimports") == 0) {
+ replaceImportTypeMacros(strvalue);
+ Chop(strvalue);
+ Printf(im_dmodule_imports, "%s\n", strvalue);
+ } else if (Strcmp(code, "proxydmodulecode") == 0) {
+ Printf(proxyCodeBuffer(0), "%s\n", strvalue);
+ } else if (Strcmp(code, "globalproxyimports") == 0) {
+ replaceImportTypeMacros(strvalue);
+ Chop(strvalue);
+ Printf(global_proxy_imports, "%s\n", strvalue);
+ } else if (Strcmp(code, "wrapperloadercode") == 0) {
+ Delete(wrapper_loader_code);
+ wrapper_loader_code = Copy(strvalue);
+ } else if (Strcmp(code, "wrapperloaderbindcommand") == 0) {
+ Delete(wrapper_loader_bind_command);
+ wrapper_loader_bind_command = Copy(strvalue);
+ } else {
+ Swig_error(input_file, line_number, "Unrecognized pragma.\n");
+ }
+ Delete(strvalue);
+ }
+ }
+ return Language::pragmaDirective(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::enumDeclaration()
+ *
+ * Wraps C/C++ enums as D enums.
+ * --------------------------------------------------------------------------- */
+ virtual int enumDeclaration(Node *n) {
+ if (ImportMode)
+ return SWIG_OK;
+
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ proxy_enum_code = NewString("");
+ String *symname = Getattr(n, "sym:name");
+ String *typemap_lookup_type = Getattr(n, "name");
+
+ // Emit the enum declaration.
+ if (typemap_lookup_type) {
+ const String *enummodifiers = lookupCodeTypemap(n, "dclassmodifiers", typemap_lookup_type, WARN_D_TYPEMAP_CLASSMOD_UNDEF);
+ Printv(proxy_enum_code, "\n", enummodifiers, " ", symname, " {\n", NIL);
+ } else {
+ // Handle anonymous enums.
+ Printv(proxy_enum_code, "\nenum {\n", NIL);
+ }
+
+ // Emit each enum item.
+ Language::enumDeclaration(n);
+
+ if (GetFlag(n, "nonempty")) {
+ // Finish the enum.
+ if (typemap_lookup_type) {
+ Printv(proxy_enum_code,
+ lookupCodeTypemap(n, "dcode", typemap_lookup_type, WARN_NONE), // Extra D code
+ "\n}\n", NIL);
+ } else {
+ // Handle anonymous enums.
+ Printv(proxy_enum_code, "\n}\n", NIL);
+ }
+ Replaceall(proxy_enum_code, "$dclassname", symname);
+ } else {
+ // D enum declarations must have at least one member to be legal, so emit
+ // an alias to int instead (their ctype/imtype is always int).
+ Delete(proxy_enum_code);
+ proxy_enum_code = NewStringf("\nalias int %s;\n", symname);
+ }
+
+ const String* imports =
+ lookupCodeTypemap(n, "dimports", typemap_lookup_type, WARN_NONE);
+ String* imports_trimmed;
+ if (Len(imports) > 0) {
+ imports_trimmed = Copy(imports);
+ Chop(imports_trimmed);
+ replaceImportTypeMacros(imports_trimmed);
+ Printv(imports_trimmed, "\n", NIL);
+ } else {
+ imports_trimmed = NewString("");
+ }
+
+ if (is_wrapping_class()) {
+ // Enums defined within the C++ class are written into the proxy
+ // class.
+ Printv(proxy_class_imports, imports_trimmed, NIL);
+ Printv(proxy_class_enums_code, proxy_enum_code, NIL);
+ } else {
+ // Write non-anonymous enums to their own file if in split proxy module
+ // mode.
+ if (split_proxy_dmodule && typemap_lookup_type) {
+ assertClassNameValidity(proxy_class_name);
+
+ String *nspace = Getattr(n, "sym:nspace");
+ String *output_directory = outputDirectory(nspace);
+ String *filename = NewStringf("%s%s.d", output_directory, symname);
+ Delete(output_directory);
+
+ File *class_file = NewFile(filename, "w", SWIG_output_files());
+ if (!class_file) {
+ FileErrorDisplay(filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filename));
+ Delete(filename);
+
+ emitBanner(class_file);
+ if (nspace) {
+ Printf(class_file, "module %s%s.%s;\n", package, nspace, symname);
+ } else {
+ Printf(class_file, "module %s%s;\n", package, symname);
+ }
+ Printv(class_file, imports_trimmed, NIL);
+
+ Printv(class_file, proxy_enum_code, NIL);
+
+ Delete(class_file);
+ } else {
+ String *nspace = Getattr(n, "sym:nspace");
+ Printv(proxyImportsBuffer(nspace), imports, NIL);
+ Printv(proxyCodeBuffer(nspace), proxy_enum_code, NIL);
+ }
+ }
+
+ Delete(imports_trimmed);
+
+ Delete(proxy_enum_code);
+ proxy_enum_code = NULL;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::enumvalueDeclaration()
+ * --------------------------------------------------------------------------- */
+ virtual int enumvalueDeclaration(Node *n) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
+ String *value = Getattr(n, "value");
+ String *name = Getattr(n, "name");
+ Node *parent = parentNode(n);
+ String *tmpValue;
+
+ // Strange hack from parent method.
+ // RESEARCH: What is this doing?
+ if (value)
+ tmpValue = NewString(value);
+ else
+ tmpValue = NewString(name);
+ // Note that this is used in enumValue() amongst other places
+ Setattr(n, "value", tmpValue);
+
+ // Deal with enum values that are not int
+ int swigtype = SwigType_type(Getattr(n, "type"));
+ if (swigtype == T_BOOL) {
+ const char *val = Equal(Getattr(n, "enumvalue"), "true") ? "1" : "0";
+ Setattr(n, "enumvalue", val);
+ } else if (swigtype == T_CHAR) {
+ String *val = NewStringf("'%(escape)s'", Getattr(n, "enumvalue"));
+ Setattr(n, "enumvalue", val);
+ Delete(val);
+ }
+
+ // Emit the enum item.
+ {
+ if (!GetFlag(n, "firstenumitem"))
+ Printf(proxy_enum_code, ",\n");
+
+ Printf(proxy_enum_code, " %s", Getattr(n, "sym:name"));
+
+ // Check for the %dconstvalue feature
+ String *value = Getattr(n, "feature:d:constvalue");
+
+ // Note that in D, enum values must be compile-time constants. Thus,
+ // %dmanifestconst(0) (getting the enum values at runtime) is not supported.
+ value = value ? value : Getattr(n, "enumvalue");
+ if (value) {
+ Printf(proxy_enum_code, " = %s", value);
+ }
+
+ // Keep track that the currently processed enum has at least one value.
+ SetFlag(parent, "nonempty");
+ }
+
+ Delete(tmpValue);
+ Swig_restore(n);
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::memberfunctionHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int memberfunctionHandler(Node *n) {
+ Language::memberfunctionHandler(n);
+
+ String *overloaded_name = getOverloadedName(n);
+ String *intermediary_function_name =
+ Swig_name_member(getNSpace(), proxy_class_name, overloaded_name);
+ Setattr(n, "imfuncname", intermediary_function_name);
+
+ String *proxy_func_name = Getattr(n, "sym:name");
+ Setattr(n, "proxyfuncname", proxy_func_name);
+ if (split_proxy_dmodule &&
+ Len(Getattr(n, "parms")) == 0 &&
+ Strncmp(proxy_func_name, package, Len(proxy_func_name)) == 0) {
+ // If we are in split proxy mode and the function is named like the
+ // target package, the D compiler is unable to resolve the ambiguity
+ // between the package name and an argument-less function call.
+ // TODO: This might occur with nspace as well, augment the check.
+ Swig_warning(WARN_D_NAME_COLLISION, input_file, line_number,
+ "%s::%s might collide with the package name, consider using %%rename to resolve the ambiguity.\n",
+ proxy_class_name, proxy_func_name);
+ }
+
+ writeProxyClassFunction(n);
+
+ Delete(overloaded_name);
+
+ // For each function, look if we have to alias in the parent class function
+ // for the overload resolution process to work as expected from C++
+ // (http://www.digitalmars.com/d/2.0/function.html#function-inheritance).
+ // For multiple overloads, only emit the alias directive once (for the
+ // last method, »sym:nextSibling« is null then).
+ // Smart pointer classes do not mirror the inheritance hierarchy of the
+ // underlying types, so aliasing the base class methods in is not required
+ // for them.
+ // DMD BUG: We have to emit the alias after the last function because
+ // taking a delegate in the overload checking code fails otherwise
+ // (http://d.puremagic.com/issues/show_bug.cgi?id=4860).
+ if (!Getattr(n, "sym:nextSibling") && !is_smart_pointer() &&
+ !areAllOverloadsOverridden(n)) {
+ String *name = Getattr(n, "sym:name");
+ Printf(proxy_class_body_code, "\nalias $dbaseclass.%s %s;\n", name, name);
+ }
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::staticmemberfunctionHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int staticmemberfunctionHandler(Node *n) {
+ static_flag = true;
+
+ Language::staticmemberfunctionHandler(n);
+
+ String *overloaded_name = getOverloadedName(n);
+ String *intermediary_function_name =
+ Swig_name_member(getNSpace(), proxy_class_name, overloaded_name);
+ Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
+ Setattr(n, "imfuncname", intermediary_function_name);
+ writeProxyClassFunction(n);
+ Delete(overloaded_name);
+
+ static_flag = false;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::globalvariableHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int globalvariableHandler(Node *n) {
+ variable_name = Getattr(n, "sym:name");
+ global_variable_flag = true;
+ int ret = Language::globalvariableHandler(n);
+ global_variable_flag = false;
+
+ return ret;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::membervariableHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int membervariableHandler(Node *n) {
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ variable_wrapper_flag = true;
+ Language::membervariableHandler(n);
+ wrapping_member_flag = false;
+ variable_wrapper_flag = false;
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::staticmembervariableHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int staticmembervariableHandler(Node *n) {
+ if (GetFlag(n, "feature:d:manifestconst") != 1) {
+ Delattr(n, "value");
+ }
+
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ static_flag = true;
+ Language::staticmembervariableHandler(n);
+ wrapping_member_flag = false;
+ static_flag = false;
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::memberconstantHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int memberconstantHandler(Node *n) {
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ Language::memberconstantHandler(n);
+ wrapping_member_flag = false;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::constructorHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int constructorHandler(Node *n) {
+ Language::constructorHandler(n);
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloadedprocess in D.
+ if (Getattr(n, "overload:ignore")) {
+ return SWIG_OK;
+ }
+
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ String *proxy_constructor_code = NewString("");
+ int i;
+
+ // Holds code for the constructor helper method generated only when the din
+ // typemap has code in the pre or post attributes.
+ String *helper_code = NewString("");
+ String *helper_args = NewString("");
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *terminator_code = NewString("");
+ NewString("");
+
+ String *overloaded_name = getOverloadedName(n);
+ String *mangled_overname = Swig_name_construct(getNSpace(), overloaded_name);
+ String *imcall = NewString("");
+
+ const String *methodmods = Getattr(n, "feature:d:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ // Typemaps were attached earlier to the node, get the return type of the
+ // call to the C++ constructor wrapper.
+ const String *wrapper_return_type = lookupDTypemap(n, "imtype", true);
+
+ String *imtypeout = Getattr(n, "tmap:imtype:out");
+ if (imtypeout) {
+ // The type in the imtype typemap's out attribute overrides the type in
+ // the typemap itself.
+ wrapper_return_type = imtypeout;
+ }
+
+ Printf(proxy_constructor_code, "\n%s this(", methodmods);
+ Printf(helper_code, "static private %s SwigConstruct%s(",
+ wrapper_return_type, proxy_class_name);
+
+ Printv(imcall, im_dmodule_fq_name, ".", mangled_overname, "(", NIL);
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("in", l, NULL);
+ Swig_typemap_attach_parms("dtype", l, NULL);
+ Swig_typemap_attach_parms("din", l, NULL);
+
+ emit_mark_varargs(l);
+
+ int gencomma = 0;
+
+ /* Output each parameter */
+ Parm *p = l;
+ for (i = 0; p; i++) {
+ if (checkAttribute(p, "varargs:ignore", "1")) {
+ // Skip ignored varargs.
+ p = nextSibling(p);
+ continue;
+ }
+
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ // Skip ignored parameters.
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+
+ // Get the D parameter type.
+ if ((tm = lookupDTypemap(p, "dtype", true))) {
+ const String *inattributes = Getattr(p, "tmap:dtype:inattributes");
+ Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ String *arg = makeParameterName(n, p, i, false);
+ String *parmtype = 0;
+
+ // Get the D code to convert the parameter value to the type used in the
+ // intermediary D module.
+ if ((tm = lookupDTypemap(p, "din"))) {
+ Replaceall(tm, "$dinput", arg);
+ String *pre = Getattr(p, "tmap:din:pre");
+ if (pre) {
+ replaceClassname(pre, pt);
+ Replaceall(pre, "$dinput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:din:post");
+ if (post) {
+ replaceClassname(post, pt);
+ Replaceall(post, "$dinput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ String *terminator = Getattr(p, "tmap:din:terminator");
+ if (terminator) {
+ replaceClassname(terminator, pt);
+ Replaceall(terminator, "$dinput", arg);
+ if (Len(terminator_code) > 0)
+ Insert(terminator_code, 0, "\n");
+ Insert(terminator_code, 0, terminator);
+ }
+ parmtype = Getattr(p, "tmap:din:parmtype");
+ if (parmtype)
+ Replaceall(parmtype, "$dinput", arg);
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DIN_UNDEF, input_file, line_number,
+ "No din typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to proxy function */
+ if (gencomma) {
+ Printf(proxy_constructor_code, ", ");
+ Printf(helper_code, ", ");
+ Printf(helper_args, ", ");
+ }
+ Printf(proxy_constructor_code, "%s %s", param_type, arg);
+ Printf(helper_code, "%s %s", param_type, arg);
+ Printf(helper_args, "%s", parmtype ? parmtype : arg);
+ ++gencomma;
+
+ Delete(parmtype);
+ Delete(arg);
+ Delete(param_type);
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Printf(imcall, ")");
+
+ Printf(proxy_constructor_code, ")");
+ Printf(helper_code, ")");
+
+ // Insert the dconstructor typemap (replacing $directorconnect as needed).
+ Hash *attributes = NewHash();
+ String *typemap_lookup_type = Getattr(getCurrentClass(), "classtypeobj");
+ String *construct_tm = Copy(lookupCodeTypemap(n, "dconstructor",
+ typemap_lookup_type, WARN_D_TYPEMAP_DCONSTRUCTOR_UNDEF, attributes));
+ if (construct_tm) {
+ const bool use_director = (parentNode(n) && Swig_directorclass(n));
+ if (!use_director) {
+ Replaceall(construct_tm, "$directorconnect", "");
+ } else {
+ String *connect_attr = Getattr(attributes, "tmap:dconstructor:directorconnect");
+
+ if (connect_attr) {
+ Replaceall(construct_tm, "$directorconnect", connect_attr);
+ } else {
+ Swig_warning(WARN_D_NO_DIRECTORCONNECT_ATTR, input_file, line_number,
+ "\"directorconnect\" attribute missing in %s \"dconstructor\" typemap.\n",
+ Getattr(n, "name"));
+ Replaceall(construct_tm, "$directorconnect", "");
+ }
+ }
+
+ Printv(proxy_constructor_code, " ", construct_tm, NIL);
+ }
+
+ replaceExcode(n, proxy_constructor_code, "dconstructor", attributes);
+
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ bool is_terminator_code = Len(terminator_code) > 0;
+ if (is_pre_code || is_post_code || is_terminator_code) {
+ Printf(helper_code, " {\n");
+ if (is_pre_code) {
+ Printv(helper_code, pre_code, "\n", NIL);
+ }
+ if (is_post_code) {
+ Printf(helper_code, " try {\n");
+ Printv(helper_code, " return ", imcall, ";\n", NIL);
+ Printv(helper_code, " } finally {\n", post_code, "\n }", NIL);
+ } else {
+ Printv(helper_code, " return ", imcall, ";", NIL);
+ }
+ if (is_terminator_code) {
+ Printv(helper_code, "\n", terminator_code, NIL);
+ }
+ Printf(helper_code, "\n}\n");
+ String *helper_name = NewStringf("%s.SwigConstruct%s(%s)",
+ proxy_class_name, proxy_class_name, helper_args);
+ Replaceall(proxy_constructor_code, "$imcall", helper_name);
+ Delete(helper_name);
+ } else {
+ Replaceall(proxy_constructor_code, "$imcall", imcall);
+ }
+
+ Printv(proxy_class_body_code, proxy_constructor_code, "\n", NIL);
+
+ Delete(helper_args);
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(terminator_code);
+ Delete(construct_tm);
+ Delete(attributes);
+ Delete(overloaded_name);
+ Delete(imcall);
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::destructorHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int destructorHandler(Node *n) {
+ Language::destructorHandler(n);
+ String *symname = Getattr(n, "sym:name");
+
+ Printv(destructor_call, im_dmodule_fq_name, ".", Swig_name_destroy(getNSpace(),symname), "(cast(void*)swigCPtr)", NIL);
+ const String *methodmods = Getattr(n, "feature:d:methodmodifiers");
+ if (methodmods)
+ Setattr(getCurrentClass(), "destructmethodmodifiers", methodmods);
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int classHandler(Node *n) {
+ String *nspace = getNSpace();
+ File *class_file = NULL;
+
+ proxy_class_name = Copy(Getattr(n, "sym:name"));
+ if (nspace) {
+ proxy_class_qname = NewStringf("%s.%s", nspace, proxy_class_name);
+ } else {
+ proxy_class_qname = Copy(proxy_class_name);
+ }
+
+ if (!addSymbol(proxy_class_name, n, nspace)) {
+ return SWIG_ERROR;
+ }
+
+ assertClassNameValidity(proxy_class_name);
+
+ if (split_proxy_dmodule) {
+ String *output_directory = outputDirectory(nspace);
+ String *filename = NewStringf("%s%s.d", output_directory, proxy_class_name);
+ class_file = NewFile(filename, "w", SWIG_output_files());
+ Delete(output_directory);
+ if (!class_file) {
+ FileErrorDisplay(filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filename));
+ Delete(filename);
+
+ emitBanner(class_file);
+ if (nspace) {
+ Printf(class_file, "module %s%s.%s;\n", package, nspace, proxy_class_name);
+ } else {
+ Printf(class_file, "module %s%s;\n", package, proxy_class_name);
+ }
+ Printf(class_file, "\nstatic import %s;\n", im_dmodule_fq_name);
+ }
+
+ Clear(proxy_class_imports);
+ Clear(proxy_class_enums_code);
+ Clear(proxy_class_body_code);
+ Clear(proxy_class_epilogue_code);
+ Clear(proxy_class_code);
+ Clear(destructor_call);
+
+
+ // Traverse the tree for this class, using the *Handler()s to generate code
+ // to the proxy_class_* variables.
+ Language::classHandler(n);
+
+
+ writeProxyClassAndUpcasts(n);
+ writeDirectorConnectWrapper(n);
+
+ Replaceall(proxy_class_code, "$dclassname", proxy_class_name);
+
+ String *dclazzname = Swig_name_member(getNSpace(), proxy_class_name, "");
+ Replaceall(proxy_class_code, "$dclazzname", dclazzname);
+ Delete(dclazzname);
+
+ if (split_proxy_dmodule) {
+ Printv(class_file, global_proxy_imports, NIL);
+ Printv(class_file, proxy_class_imports, NIL);
+
+ replaceModuleVariables(proxy_class_code);
+ Printv(class_file, proxy_class_code, NIL);
+
+ Delete(class_file);
+ } else {
+ Printv(proxyImportsBuffer(getNSpace()), proxy_class_imports, NIL);
+ Printv(proxyCodeBuffer(getNSpace()), proxy_class_code, NIL);
+ }
+
+ Delete(proxy_class_qname);
+ proxy_class_qname = NULL;
+ Delete(proxy_class_name);
+ proxy_class_name = NULL;
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::constantWrapper()
+ *
+ * Used for wrapping constants declared by #define or %constant and also for
+ * (primitive) static member constants initialised inline.
+ *
+ * If the %dmanifestconst feature is used, the C/C++ constant value is used to
+ * initialize a D »const«. If not, a »getter« method is generated which
+ * retrieves the value via a call to the C wrapper. However, if there is a
+ * %dconstvalue specified, it overrides all other settings.
+ * --------------------------------------------------------------------------- */
+ virtual int constantWrapper(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ if (!addSymbol(symname, n))
+ return SWIG_ERROR;
+
+ // The %dmanifestconst feature determines if a D manifest constant
+ // (const/enum) or a getter function is created.
+ if (GetFlag(n, "feature:d:manifestconst") != 1) {
+ // Default constant handling will work with any type of C constant. It
+ // generates a getter function (which is the same as a read only property
+ // in D) which retrieves the value via by calling the C wrapper.
+ // Note that this is only called for global constants, static member
+ // constants are already handled in staticmemberfunctionHandler().
+
+ Swig_save("constantWrapper", n, "value", NIL);
+ Swig_save("constantWrapper", n, "tmap:ctype:out", "tmap:imtype:out", "tmap:dtype:out", "tmap:out:null", "tmap:imtype:outattributes", "tmap:dtype:outattributes", NIL);
+
+ // Add the stripped quotes back in.
+ String *old_value = Getattr(n, "value");
+ SwigType *t = Getattr(n, "type");
+ if (SwigType_type(t) == T_STRING) {
+ Setattr(n, "value", NewStringf("\"%s\"", old_value));
+ Delete(old_value);
+ } else if (SwigType_type(t) == T_CHAR) {
+ Setattr(n, "value", NewStringf("\'%s\'", old_value));
+ Delete(old_value);
+ }
+
+ SetFlag(n, "feature:immutable");
+ int result = globalvariableHandler(n);
+
+ Swig_restore(n);
+ return result;
+ }
+
+ String *constants_code = NewString("");
+ SwigType *t = Getattr(n, "type");
+ SwigType *valuetype = Getattr(n, "valuetype");
+ ParmList *l = Getattr(n, "parms");
+
+ // Attach the non-standard typemaps to the parameter list.
+ Swig_typemap_attach_parms("dtype", l, NULL);
+
+ // Get D return type.
+ String *return_type = NewString("");
+ String *tm;
+ if ((tm = lookupDTypemap(n, "dtype"))) {
+ String *dtypeout = Getattr(n, "tmap:dtype:out");
+ if (dtypeout) {
+ // The type in the out attribute of the typemap overrides the type
+ // in the dtype typemap.
+ tm = dtypeout;
+ replaceClassname(tm, t);
+ }
+ Printf(return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ const String *itemname = wrapping_member_flag ? variable_name : symname;
+
+ String *attributes = Getattr(n, "feature:d:methodmodifiers");
+ if (attributes) {
+ attributes = Copy(attributes);
+ } else {
+ attributes = Copy(is_public(n) ? public_string : protected_string);
+ }
+
+ if (d_version == 1) {
+ if (static_flag) {
+ Printv(attributes, " static", NIL);
+ }
+ Printf(constants_code, "\n%s const %s %s = ", attributes, return_type, itemname);
+ } else {
+ Printf(constants_code, "\n%s enum %s %s = ", attributes, return_type, itemname);
+ }
+ Delete(attributes);
+
+ // Retrieve the override value set via %dconstvalue, if any.
+ String *override_value = Getattr(n, "feature:d:constvalue");
+ if (override_value) {
+ Printf(constants_code, "%s;\n", override_value);
+ } else {
+ // Just take the value from the C definition and hope it compiles in D.
+ if (Getattr(n, "wrappedasconstant")) {
+ if (SwigType_type(valuetype) == T_CHAR)
+ Printf(constants_code, "\'%(escape)s\';\n", Getattr(n, "staticmembervariableHandler:value"));
+ else
+ Printf(constants_code, "%s;\n", Getattr(n, "staticmembervariableHandler:value"));
+ } else {
+ // Add the stripped quotes back in.
+ String* value = Getattr(n, "value");
+ if (SwigType_type(t) == T_STRING) {
+ Printf(constants_code, "\"%s\";\n", value);
+ } else if (SwigType_type(t) == T_CHAR) {
+ Printf(constants_code, "\'%s\';\n", value);
+ } else {
+ Printf(constants_code, "%s;\n", value);
+ }
+ }
+ }
+
+ // Emit the generated code to appropriate place.
+ if (wrapping_member_flag) {
+ Printv(proxy_class_body_code, constants_code, NIL);
+ } else {
+ Printv(proxyCodeBuffer(getNSpace()), constants_code, NIL);
+ }
+
+ // Cleanup.
+ Delete(return_type);
+ Delete(constants_code);
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::functionWrapper()
+ *
+ * Generates the C wrapper code for a function and the corresponding
+ * declaration in the wrap D module.
+ * --------------------------------------------------------------------------- */
+ virtual int functionWrapper(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ int i;
+ String *c_return_type = NewString("");
+ String *im_return_type = NewString("");
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ String *body = NewString("");
+ int num_arguments = 0;
+ bool is_void_return;
+ String *overloaded_name = getOverloadedName(n);
+
+ if (!Getattr(n, "sym:overloaded")) {
+ if (!addSymbol(Getattr(n, "sym:name"), n))
+ return SWIG_ERROR;
+ }
+
+ // A new wrapper function object
+ Wrapper *f = NewWrapper();
+
+ // Make a wrapper name for this function
+ String *wname = Swig_name_wrapper(overloaded_name);
+
+ /* Attach the non-standard typemaps to the parameter list. */
+ Swig_typemap_attach_parms("ctype", l, f);
+ Swig_typemap_attach_parms("imtype", l, f);
+
+ /* Get return types */
+ if ((tm = lookupDTypemap(n, "ctype"))) {
+ String *ctypeout = Getattr(n, "tmap:ctype:out");
+ if (ctypeout) {
+ // The type in the ctype typemap's out attribute overrides the type in
+ // the typemap itself.
+ tm = ctypeout;
+ }
+ Printf(c_return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_CTYPE_UNDEF, input_file, line_number,
+ "No ctype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ if ((tm = lookupDTypemap(n, "imtype"))) {
+ String *imtypeout = Getattr(n, "tmap:imtype:out");
+ if (imtypeout) {
+ // The type in the imtype typemap's out attribute overrides the type in
+ // the typemap itself.
+ tm = imtypeout;
+ }
+ Printf(im_return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_IMTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ is_void_return = (Cmp(c_return_type, "void") == 0);
+ if (!is_void_return)
+ Wrapper_add_localv(f, "jresult", c_return_type, "jresult", NIL);
+
+ Printv(f->def, " SWIGEXPORT ", c_return_type, " ", wname, "(", NIL);
+
+ // Emit all of the local variables for holding arguments.
+ emit_parameter_variables(l, f);
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+
+ // Parameter overloading
+ Setattr(n, "wrap:parms", l);
+ Setattr(n, "wrap:name", wname);
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloaded in D
+ if (Getattr(n, "sym:overloaded")) {
+ // Emit warnings for the few cases that can't be overloaded in D and give up on generating wrapper
+ Swig_overload_check(n);
+ if (Getattr(n, "overload:ignore")) {
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+ }
+
+ // Collect the parameter list for the intermediary D module declaration of
+ // the generated wrapper function.
+ String *im_dmodule_parameters = NewString("(");
+
+ /* Get number of required and total arguments */
+ num_arguments = emit_num_arguments(l);
+ int gencomma = 0;
+
+ // Now walk the function parameter list and generate code to get arguments
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+ String *im_param_type = NewString("");
+ String *c_param_type = NewString("");
+ String *arg = NewString("");
+
+ Printf(arg, "j%s", ln);
+
+ /* Get the ctype types of the parameter */
+ if ((tm = lookupDTypemap(p, "ctype", true))) {
+ Printv(c_param_type, tm, NIL);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Get the intermediary class parameter types of the parameter */
+ if ((tm = lookupDTypemap(p, "imtype", true))) {
+ const String *inattributes = Getattr(p, "tmap:imtype:inattributes");
+ Printf(im_param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_IMTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to intermediary class method */
+ if (gencomma)
+ Printf(im_dmodule_parameters, ", ");
+ Printf(im_dmodule_parameters, "%s %s", im_param_type, arg);
+
+ // Add parameter to C function
+ Printv(f->def, gencomma ? ", " : "", c_param_type, " ", arg, NIL);
+
+ gencomma = 1;
+
+ // Get typemap for this argument
+ if ((tm = Getattr(p, "tmap:in"))) {
+ canThrow(n, "in", p);
+ Replaceall(tm, "$input", arg);
+ Setattr(p, "emit:input", arg);
+ Printf(f->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(pt, 0));
+ p = nextSibling(p);
+ }
+ Delete(im_param_type);
+ Delete(c_param_type);
+ Delete(arg);
+ }
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ canThrow(n, "check", p);
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ canThrow(n, "freearg", p);
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert argument output code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ canThrow(n, "argout", p);
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Look for usage of throws typemap and the canthrow flag
+ ParmList *throw_parm_list = NULL;
+ if ((throw_parm_list = Getattr(n, "catchlist"))) {
+ Swig_typemap_attach_parms("throws", throw_parm_list, f);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ canThrow(n, "throws", p);
+ }
+ }
+ }
+
+ String *null_attribute = 0;
+ // Now write code to make the function call
+ if (!native_function_flag) {
+
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ /* Return value if necessary */
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ canThrow(n, "out", n);
+ Replaceall(tm, "$result", "jresult");
+
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "1");
+ else
+ Replaceall(tm, "$owner", "0");
+
+ Printf(f->code, "%s", tm);
+ null_attribute = Getattr(n, "tmap:out:null");
+ if (Len(tm))
+ Printf(f->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(t, 0), Getattr(n, "name"));
+ }
+ emit_return_variable(n, t, f);
+ }
+
+ /* Output argument output code */
+ Printv(f->code, outarg, NIL);
+
+ /* Output cleanup code */
+ Printv(f->code, cleanup, NIL);
+
+ /* Look to see if there is any newfree cleanup code */
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ canThrow(n, "newfree", n);
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if (!native_function_flag) {
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ canThrow(n, "ret", n);
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ // Complete D im parameter list and emit the declaration/binding code.
+ Printv(im_dmodule_parameters, ")", NIL);
+ writeImDModuleFunction(overloaded_name, im_return_type,
+ im_dmodule_parameters, wname);
+ Delete(im_dmodule_parameters);
+
+ // Finish C function header.
+ Printf(f->def, ") {");
+
+ if (!is_void_return)
+ Printv(f->code, " return jresult;\n", NIL);
+ Printf(f->code, "}\n");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", symname);
+
+ /* Contract macro modification */
+ if (Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ") > 0) {
+ Setattr(n, "d:canthrow", "1");
+ }
+
+ if (!null_attribute)
+ Replaceall(f->code, "$null", "0");
+ else
+ Replaceall(f->code, "$null", null_attribute);
+
+ /* Dump the function out */
+ if (!native_function_flag) {
+ Wrapper_print(f, f_wrappers);
+
+ // Handle %exception which sets the canthrow attribute.
+ if (Getattr(n, "feature:except:canthrow")) {
+ Setattr(n, "d:canthrow", "1");
+ }
+
+ // A very simple check (it is not foolproof) to assist typemap writers
+ // with setting the correct features when the want to throw D exceptions
+ // from C++ code. It checks for the common methods which set
+ // a pending D exception and issues a warning if one of them has been found
+ // in the typemap, but the »canthrow« attribute/feature is not set.
+ if (!Getattr(n, "d:canthrow")) {
+ if (Strstr(f->code, "SWIG_exception")) {
+ Swig_warning(WARN_D_CANTHROW_MISSING, input_file, line_number,
+ "C code contains a call to SWIG_exception and D code does not handle pending exceptions via the canthrow attribute.\n");
+ } else if (Strstr(f->code, "SWIG_DSetPendingException")) {
+ Swig_warning(WARN_D_CANTHROW_MISSING, input_file, line_number,
+ "C code contains a call to a SWIG_DSetPendingException method and D code does not handle pending exceptions via the canthrow attribute.\n");
+ }
+ }
+ }
+
+ // If we are not processing an enum or constant, and we were not generating
+ // a wrapper function which will be accessed via a proxy class, write a
+ // function to the proxy D module.
+ if (!is_wrapping_class()) {
+ writeProxyDModuleFunction(n);
+ }
+
+ // If we are processing a public member variable, write the property-style
+ // member function to the proxy class.
+ if (wrapping_member_flag) {
+ Setattr(n, "proxyfuncname", variable_name);
+ Setattr(n, "imfuncname", symname);
+
+ writeProxyClassFunction(n);
+ }
+
+ Delete(c_return_type);
+ Delete(im_return_type);
+ Delete(cleanup);
+ Delete(outarg);
+ Delete(body);
+ Delete(overloaded_name);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::nativeWrapper()
+ * --------------------------------------------------------------------------- */
+ virtual int nativeWrapper(Node *n) {
+ String *wrapname = Getattr(n, "wrap:name");
+
+ if (!addSymbol(wrapname, n))
+ return SWIG_ERROR;
+
+ if (Getattr(n, "type")) {
+ Swig_save("nativeWrapper", n, "name", NIL);
+ Setattr(n, "name", wrapname);
+ native_function_flag = true;
+ functionWrapper(n);
+ Swig_restore(n);
+ native_function_flag = false;
+ } else {
+ Swig_error(input_file, line_number, "No return type for %%native method %s.\n", Getattr(n, "wrap:name"));
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirector()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirector(Node *n) {
+ String *nspace = Getattr(n, "sym:nspace");
+ proxy_class_name = NewString(Getattr(n, "sym:name"));
+ if (nspace) {
+ proxy_class_qname = NewStringf("%s.%s", nspace, proxy_class_name);
+ } else {
+ proxy_class_qname = Copy(proxy_class_name);
+ }
+
+ int success = Language::classDirector(n);
+
+ Delete(proxy_class_qname);
+ proxy_class_qname = NULL;
+ Delete(proxy_class_name);
+ proxy_class_name = NULL;
+
+ return success;
+ }
+
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorInit()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorInit(Node *n) {
+ Delete(director_ctor_code);
+ director_ctor_code = NewString("$director_new");
+
+ // Write C++ director class declaration, for example:
+ // class SwigDirector_myclass : public myclass, public Swig::Director {
+ String *classname = Swig_class_name(n);
+ String *directorname = directorClassName(n);
+ String *declaration = Swig_class_declaration(n, directorname);
+ const String *base = Getattr(n, "classtype");
+
+ Printf(f_directors_h,
+ "%s : public %s, public Swig::Director {\n", declaration, base);
+ Printf(f_directors_h, "\npublic:\n");
+
+ Delete(declaration);
+ Delete(directorname);
+ Delete(classname);
+
+ // Stash for later.
+ Setattr(n, "director:ctor", NewString("Swig::Director()"));
+
+ // Keep track of the director methods for this class.
+ first_class_dmethod = curr_class_dmethod = n_dmethods;
+
+ director_callback_typedefs = NewString("");
+ director_callback_pointers = NewString("");
+ director_dcallbacks_code = NewString("");
+
+ return Language::classDirectorInit(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorMethod()
+ *
+ * Emit a virtual director method to pass a method call on to the
+ * underlying D object.
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorMethod(Node *n, Node *parent, String *super) {
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ String *overloaded_name = getOverloadedName(n);
+ String *storage = Getattr(n, "storage");
+ String *value = Getattr(n, "value");
+ String *decl = Getattr(n, "decl");
+ String *declaration = NewString("");
+ String *tm;
+ Parm *p;
+ int i;
+ Wrapper *w = NewWrapper();
+ ParmList *l = Getattr(n, "parms");
+ bool is_void = !(Cmp(returntype, "void"));
+ String *qualified_return = 0;
+ bool pure_virtual = (!(Cmp(storage, "virtual")) && !(Cmp(value, "0")));
+ int status = SWIG_OK;
+ bool output_director = true;
+ String *dirclassname = directorClassName(parent);
+ String *qualified_name = NewStringf("%s::%s", dirclassname, name);
+ SwigType *c_ret_type = NULL;
+ String *dcallback_call_args = NewString("");
+ String *imclass_dmethod;
+ String *callback_typedef_parms = NewString("");
+ String *delegate_parms = NewString("");
+ String *proxy_method_param_list = NewString("");
+ String *proxy_callback_return_type = NewString("");
+ String *callback_def = NewString("");
+ String *callback_code = NewString("");
+ String *imcall_args = NewString("");
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+
+ // Kludge Alert: functionWrapper sets sym:overload properly, but it
+ // isn't at this point, so we have to manufacture it ourselves. At least
+ // we're consistent with the sym:overload name in functionWrapper. (?? when
+ // does the overloaded method name get set?)
+
+ imclass_dmethod = NewStringf("SwigDirector_%s", Swig_name_member(getNSpace(), classname, overloaded_name));
+
+ qualified_return = SwigType_rcaststr(returntype, "c_result");
+
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ String *base_typename = SwigType_base(returntype);
+ String *resolved_typename = SwigType_typedef_resolve_all(base_typename);
+ Symtab *symtab = Getattr(n, "sym:symtab");
+ Node *typenode = Swig_symbol_clookup(resolved_typename, symtab);
+
+ if (SwigType_ispointer(returntype) || (typenode && Getattr(typenode, "abstracts"))) {
+ /* initialize pointers to something sane. Same for abstract
+ classes when a reference is returned. */
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ } else {
+ /* If returning a reference, initialize the pointer to a sane
+ default - if a D exception occurs, then the pointer returns
+ something other than a NULL-initialized reference. */
+ SwigType *noref_type = SwigType_del_reference(Copy(returntype));
+ String *noref_ltype = SwigType_lstr(noref_type, 0);
+ String *return_ltype = SwigType_lstr(returntype, 0);
+
+ Wrapper_add_localv(w, "result_default", "static", noref_ltype, "result_default", NIL);
+ Wrapper_add_localv(w, "c_result", return_ltype, "c_result", NIL);
+ Printf(w->code, "result_default = SwigValueInit< %s >();\n", noref_ltype);
+ Printf(w->code, "c_result = &result_default;\n");
+ Delete(return_ltype);
+ Delete(noref_ltype);
+ Delete(noref_type);
+ }
+
+ Delete(base_typename);
+ Delete(resolved_typename);
+ }
+ } else {
+ SwigType *vt;
+
+ vt = cplus_value_type(returntype);
+ if (!vt) {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(vt, "c_result"), NIL);
+ Delete(vt);
+ }
+ }
+ }
+
+ /* Create the intermediate class wrapper */
+ tm = lookupDTypemap(n, "imtype");
+ if (tm) {
+ String *imtypeout = Getattr(n, "tmap:imtype:out");
+ if (imtypeout) {
+ // The type in the imtype typemap's out attribute overrides the type
+ // in the typemap.
+ tm = imtypeout;
+ }
+ Printf(callback_def, "\nprivate extern(C) %s swigDirectorCallback_%s_%s(void* dObject", tm, classname, overloaded_name);
+ Printv(proxy_callback_return_type, tm, NIL);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_IMTYPE_UNDEF, input_file, line_number,
+ "No imtype typemap defined for %s\n", SwigType_str(returntype, 0));
+ }
+
+ if ((c_ret_type = Swig_typemap_lookup("ctype", n, "", 0))) {
+ if (!is_void && !ignored_method) {
+ String *jretval_decl = NewStringf("%s jresult", c_ret_type);
+ Wrapper_add_localv(w, "jresult", jretval_decl, "= 0", NIL);
+ Delete(jretval_decl);
+ }
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_CTYPE_UNDEF, input_file, line_number,
+ "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Swig_director_parms_fixup(l);
+
+ // Attach the standard typemaps.
+ Swig_typemap_attach_parms("out", l, 0);
+ Swig_typemap_attach_parms("ctype", l, 0);
+ Swig_typemap_attach_parms("imtype", l, 0);
+ Swig_typemap_attach_parms("dtype", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("ddirectorin", l, 0);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ // Preamble code.
+ if (!ignored_method)
+ Printf(w->code, "if (!swig_callback_%s) {\n", overloaded_name);
+
+ if (!pure_virtual) {
+ String *super_call = Swig_method_call(super, l);
+ if (is_void) {
+ Printf(w->code, "%s;\n", super_call);
+ if (!ignored_method)
+ Printf(w->code, "return;\n");
+ } else {
+ Printf(w->code, "return %s;\n", super_call);
+ }
+ Delete(super_call);
+ } else {
+ Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
+ if (!is_void)
+ Printf(w->code, "return %s;", qualified_return);
+ else if (!ignored_method)
+ Printf(w->code, "return;\n");
+ }
+
+ if (!ignored_method)
+ Printf(w->code, "} else {\n");
+
+ // Go through argument list.
+ for (i = 0, p = l; p; ++i) {
+ /* Is this superfluous? */
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = makeParameterName(n, p, i, false);
+ String *c_param_type = NULL;
+ String *c_decl = NewString("");
+ String *arg = NewString("");
+
+ Printf(arg, "j%s", ln);
+
+ // Add each parameter to the D callback invocation arguments.
+ Printf(dcallback_call_args, ", %s", arg);
+
+ /* Get parameter's intermediary C type */
+ if ((c_param_type = lookupDTypemap(p, "ctype", true))) {
+ String *ctypeout = Getattr(p, "tmap:ctype:out");
+ if (ctypeout) {
+ // The type in the ctype typemap's out attribute overrides the type
+ // in the typemap itself.
+ c_param_type = ctypeout;
+ }
+
+ /* Add to local variables */
+ Printf(c_decl, "%s %s", c_param_type, arg);
+ if (!ignored_method)
+ Wrapper_add_localv(w, arg, c_decl, (!(SwigType_ispointer(pt) || SwigType_isreference(pt)) ? "" : "= 0"), NIL);
+
+ /* Add input marshalling code */
+ if ((tm = Getattr(p, "tmap:directorin"))) {
+
+ Setattr(p, "emit:directorinput", arg);
+ Replaceall(tm, "$input", arg);
+ Replaceall(tm, "$owner", "0");
+
+ if (Len(tm))
+ if (!ignored_method)
+ Printf(w->code, "%s\n", tm);
+
+ // Add parameter type to the C typedef for the D callback function.
+ Printf(callback_typedef_parms, ", %s", c_param_type);
+
+ /* Add parameter to the intermediate class code if generating the
+ * intermediate's upcall code */
+ if ((tm = lookupDTypemap(p, "imtype", true))) {
+ String *imtypeout = Getattr(p, "tmap:imtype:out");
+ if (imtypeout) {
+ // The type in the imtype typemap's out attribute overrides the
+ // type in the typemap itself.
+ tm = imtypeout;
+ }
+ const String *im_directorinattributes = Getattr(p, "tmap:imtype:directorinattributes");
+
+ // TODO: Is this copy really needed?
+ String *din = Copy(lookupDTypemap(p, "ddirectorin", true));
+
+ if (din) {
+ Replaceall(din, "$winput", ln);
+
+ Printf(delegate_parms, ", ");
+ if (i > 0) {
+ Printf(proxy_method_param_list, ", ");
+ Printf(imcall_args, ", ");
+ }
+ Printf(delegate_parms, "%s%s %s", im_directorinattributes ? im_directorinattributes : empty_string, tm, ln);
+
+ if (Cmp(din, ln)) {
+ Printv(imcall_args, din, NIL);
+ } else {
+ Printv(imcall_args, ln, NIL);
+ }
+
+ Delete(din);
+
+ // Get the parameter type in the proxy D class (used later when
+ // generating the overload checking code for the directorConnect
+ // function).
+ if ((tm = lookupDTypemap(p, "dtype", true))) {
+ Printf(proxy_method_param_list, "%s", tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DDIRECTORIN_UNDEF, input_file, line_number,
+ "No ddirectorin typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_IMTYPE_UNDEF, input_file, line_number,
+ "No imtype typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ p = Getattr(p, "tmap:directorin:next");
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DDIRECTORIN_UNDEF, input_file, line_number,
+ "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ p = nextSibling(p);
+ output_director = false;
+ }
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_CTYPE_UNDEF, input_file, line_number,
+ "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ p = nextSibling(p);
+ }
+
+ Delete(arg);
+ Delete(c_decl);
+ Delete(c_param_type);
+ Delete(ln);
+ }
+
+ /* header declaration, start wrapper definition */
+ String *target;
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Add any exception specifications to the methods in the director class
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ ParmList *throw_parm_list = NULL;
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list)
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+ Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0));
+ Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0));
+ }
+ }
+
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+
+ // Finish the callback function declaraction.
+ Printf(callback_def, "%s)", delegate_parms);
+ Printf(callback_def, " {\n");
+
+ /* Emit the intermediate class's upcall to the actual class */
+
+ String *upcall = NewStringf("(cast(%s)dObject).%s(%s)", classname, symname, imcall_args);
+
+ if (!is_void) {
+ if ((tm = lookupDTypemap(n, "ddirectorout"))) {
+ Replaceall(tm, "$dcall", upcall);
+ Printf(callback_code, " return %s;\n", tm);
+ }
+ } else {
+ Printf(callback_code, " %s;\n", upcall);
+ }
+
+ Printf(callback_code, "}\n");
+ Delete(upcall);
+
+ if (!ignored_method) {
+ if (!is_void)
+ Printf(w->code, "jresult = (%s) ", c_ret_type);
+
+ Printf(w->code, "swig_callback_%s(d_object%s);\n", overloaded_name, dcallback_call_args);
+
+ if (!is_void) {
+ String *jresult_str = NewString("jresult");
+ String *result_str = NewString("c_result");
+
+ /* Copy jresult into c_result... */
+ if ((tm = Swig_typemap_lookup("directorout", n, result_str, w))) {
+ Replaceall(tm, "$input", jresult_str);
+ Replaceall(tm, "$result", result_str);
+ Printf(w->code, "%s\n", tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s used in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Delete(jresult_str);
+ Delete(result_str);
+ }
+
+ /* Marshal outputs */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout"))) {
+ canThrow(n, "directorargout", p);
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Terminate wrapper code */
+ Printf(w->code, "}\n");
+ if (!is_void)
+ Printf(w->code, "return %s;", qualified_return);
+ }
+
+ Printf(w->code, "}");
+
+ // We expose virtual protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewString("");
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+
+ /* emit the director method */
+ if (status == SWIG_OK && output_director) {
+ if (!is_void) {
+ Replaceall(w->code, "$null", qualified_return);
+ } else {
+ Replaceall(w->code, "$null", "");
+ }
+ if (!ignored_method)
+ Printv(director_dcallbacks_code, callback_def, callback_code, NIL);
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+
+ if (!ignored_method) {
+ // Register the upcall method so that the callback registering code can
+ // be written later.
+
+ // We cannot directly use n here because its »type« attribute does not
+ // the full return type any longer after Language::functionHandler has
+ // returned.
+ String *dp_return_type = lookupDTypemap(n, "dtype");
+ if (dp_return_type) {
+ String *dtypeout = Getattr(n, "tmap:dtype:out");
+ if (dtypeout) {
+ // The type in the dtype typemap's out attribute overrides the type
+ // in the typemap itself.
+ dp_return_type = dtypeout;
+ replaceClassname(dp_return_type, returntype);
+ }
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(returntype, 0));
+ dp_return_type = NewString("");
+ }
+
+ UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, decl, overloaded_name, dp_return_type, proxy_method_param_list);
+ Delete(dp_return_type);
+
+ // Write the global callback function pointer on the C code.
+ String *methid = Getattr(udata, "class_methodidx");
+
+ Printf(director_callback_typedefs, " typedef %s (* SWIG_Callback%s_t)", c_ret_type, methid);
+ Printf(director_callback_typedefs, "(void *dobj%s);\n", callback_typedef_parms);
+ Printf(director_callback_pointers, " SWIG_Callback%s_t swig_callback_%s;\n", methid, overloaded_name);
+
+ // Write the type alias for the callback to the intermediary D module.
+ String *proxy_callback_type = NewString("");
+ String *dirClassName = directorClassName(parent);
+ Printf(proxy_callback_type, "%s_Callback%s", dirClassName, methid);
+ Printf(im_dmodule_code, "alias extern(C) %s function(void*%s) %s;\n", proxy_callback_return_type, delegate_parms, proxy_callback_type);
+ Delete(proxy_callback_type);
+ Delete(dirClassName);
+ }
+
+ Delete(qualified_return);
+ Delete(c_ret_type);
+ Delete(declaration);
+ Delete(callback_typedef_parms);
+ Delete(delegate_parms);
+ Delete(proxy_method_param_list);
+ Delete(callback_def);
+ Delete(callback_code);
+ DelWrapper(w);
+
+ return status;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorConstructor()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorConstructor(Node *n) {
+ Node *parent = parentNode(n);
+ String *decl = Getattr(n, "decl");;
+ String *supername = Swig_class_name(parent);
+ String *dirclassname = directorClassName(parent);
+ String *sub = NewString("");
+ Parm *p;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms;
+ int argidx = 0;
+
+ /* Assign arguments to superclass's parameters, if not already done */
+ for (p = superparms; p; p = nextSibling(p)) {
+ String *pname = Getattr(p, "name");
+
+ if (!pname) {
+ pname = NewStringf("arg%d", argidx++);
+ Setattr(p, "name", pname);
+ }
+ }
+
+ // TODO: Is this copy needed?
+ parms = CopyParmList(superparms);
+
+ if (!Getattr(n, "defaultargs")) {
+ /* constructor */
+ {
+ String *basetype = Getattr(parent, "classtype");
+ String *target = Swig_method_decl(0, decl, dirclassname, parms, 0);
+ String *call = Swig_csuperclass_call(0, basetype, superparms);
+ String *classtype = SwigType_namestr(Getattr(n, "name"));
+
+ Printf(f_directors, "%s::%s : %s, %s {\n", dirclassname, target, call, Getattr(parent, "director:ctor"));
+ Printf(f_directors, " swig_init_callbacks();\n");
+ Printf(f_directors, "}\n\n");
+
+ Delete(classtype);
+ Delete(target);
+ Delete(call);
+ }
+
+ /* constructor header */
+ {
+ String *target = Swig_method_decl(0, decl, dirclassname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Delete(sub);
+ Delete(supername);
+ Delete(parms);
+ Delete(dirclassname);
+ return Language::classDirectorConstructor(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorDefaultConstructor()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorDefaultConstructor(Node *n) {
+ String *dirclassname = directorClassName(n);
+ String *classtype = SwigType_namestr(Getattr(n, "name"));
+ Wrapper *w = NewWrapper();
+
+ Printf(w->def, "%s::%s() : %s {", dirclassname, dirclassname, Getattr(n, "director:ctor"));
+ Printf(w->code, "}\n");
+ Wrapper_print(w, f_directors);
+
+ Printf(f_directors_h, " %s();\n", dirclassname);
+ DelWrapper(w);
+ Delete(classtype);
+ Delete(dirclassname);
+ return Language::classDirectorDefaultConstructor(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorDestructor()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorDestructor(Node *n) {
+ Node *current_class = getCurrentClass();
+ String *dirclassname = directorClassName(current_class);
+ Wrapper *w = NewWrapper();
+
+ if (Getattr(n, "noexcept")) {
+ Printf(f_directors_h, " virtual ~%s() noexcept;\n", dirclassname);
+ Printf(w->def, "%s::~%s() noexcept {\n", dirclassname, dirclassname);
+ } else if (Getattr(n, "throw")) {
+ Printf(f_directors_h, " virtual ~%s() throw();\n", dirclassname);
+ Printf(w->def, "%s::~%s() throw() {\n", dirclassname, dirclassname);
+ } else {
+ Printf(f_directors_h, " virtual ~%s();\n", dirclassname);
+ Printf(w->def, "%s::~%s() {\n", dirclassname, dirclassname);
+ }
+
+ Printv(w->code, "}\n", NIL);
+
+ Wrapper_print(w, f_directors);
+
+ DelWrapper(w);
+ Delete(dirclassname);
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorEnd()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorEnd(Node *n) {
+ int i;
+ String *director_classname = directorClassName(n);
+
+ Wrapper *w = NewWrapper();
+
+ if (Len(director_callback_typedefs) > 0) {
+ Printf(f_directors_h, "\n%s", director_callback_typedefs);
+ }
+
+ Printf(f_directors_h, " void swig_connect_director(void* dobj");
+
+ Printf(w->def, "void %s::swig_connect_director(void* dobj", director_classname);
+ Printf(w->code, "d_object = dobj;");
+
+ for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *methid = Getattr(udata, "class_methodidx");
+ String *overname = Getattr(udata, "overname");
+
+ Printf(f_directors_h, ", SWIG_Callback%s_t callback%s", methid, overname);
+ Printf(w->def, ", SWIG_Callback%s_t callback_%s", methid, overname);
+ Printf(w->code, "swig_callback_%s = callback_%s;\n", overname, overname);
+ }
+
+ Printf(f_directors_h, ");\n");
+ Printf(w->def, ") {");
+
+ Printf(f_directors_h, "\nprivate:\n");
+ Printf(f_directors_h, " void swig_init_callbacks();\n");
+ Printf(f_directors_h, " void *d_object;\n");
+ if (Len(director_callback_pointers) > 0) {
+ Printf(f_directors_h, "%s", director_callback_pointers);
+ }
+ Printf(f_directors_h, "};\n\n");
+ Printf(w->code, "}\n\n");
+
+ Printf(w->code, "void %s::swig_init_callbacks() {\n", director_classname);
+ for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *overname = Getattr(udata, "overname");
+ Printf(w->code, "swig_callback_%s = 0;\n", overname);
+ }
+ Printf(w->code, "}");
+
+ Wrapper_print(w, f_directors);
+
+ DelWrapper(w);
+
+ return Language::classDirectorEnd(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorDisown()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorDisown(Node *n) {
+ (void) n;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceSpecialVariables()
+ * --------------------------------------------------------------------------- */
+ virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
+ (void)method;
+ SwigType *type = Getattr(parm, "type");
+
+ // Just assume that this goes to the proxy class, we cannot know.
+ replaceClassname(tm, type);
+ }
+
+protected:
+ /* ---------------------------------------------------------------------------
+ * D::extraDirectorProtectedCPPMethodsRequired()
+ * --------------------------------------------------------------------------- */
+ virtual bool extraDirectorProtectedCPPMethodsRequired() const {
+ return false;
+ }
+
+private:
+ /* ---------------------------------------------------------------------------
+ * D::writeImDModuleFunction()
+ *
+ * Writes a function declaration for the given (C) wrapper function to the
+ * intermediary D module.
+ *
+ * d_name - The name the function in the intermediary D module will get.
+ * return type - The return type of the function in the C wrapper.
+ * parameters - The parameter list of the C wrapper function.
+ * wrapper_function_name - The name of the exported function in the C wrapper
+ * (usually d_name prefixed by »D_«).
+ * --------------------------------------------------------------------------- */
+ void writeImDModuleFunction(const_String_or_char_ptr d_name,
+ const_String_or_char_ptr return_type, const_String_or_char_ptr parameters,
+ const_String_or_char_ptr wrapper_function_name) {
+
+ // TODO: Add support for static linking here.
+ Printf(im_dmodule_code, "SwigExternC!(%s function%s) %s;\n", return_type,
+ parameters, d_name);
+ Printv(wrapper_loader_bind_code, wrapper_loader_bind_command, NIL);
+ Replaceall(wrapper_loader_bind_code, "$function", d_name);
+ Replaceall(wrapper_loader_bind_code, "$symbol", wrapper_function_name);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeProxyClassFunction()
+ *
+ * Creates a D proxy function for a C++ function in the wrapped class. Used
+ * for both static and non-static C++ class functions.
+ *
+ * The Node must contain two extra attributes.
+ * - "proxyfuncname": The name of the D proxy function.
+ * - "imfuncname": The corresponding function in the intermediary D module.
+ * --------------------------------------------------------------------------- */
+ void writeProxyClassFunction(Node *n) {
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *intermediary_function_name = Getattr(n, "imfuncname");
+ String *proxy_function_name = Getattr(n, "proxyfuncname");
+ String *tm;
+ Parm *p;
+ int i;
+ String *imcall = NewString("");
+ String *return_type = NewString("");
+ String *function_code = NewString("");
+ bool setter_flag = false;
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *terminator_code = NewString("");
+
+ // Wrappers not wanted for some methods where the parameters cannot be
+ // overloaded in D.
+ if (Getattr(n, "overload:ignore"))
+ return;
+
+ // Don't generate proxy method for additional explicitcall method used in
+ // directors.
+ if (GetFlag(n, "explicitcall"))
+ return;
+
+ // RESEARCH: What is this good for?
+ if (l) {
+ if (SwigType_type(Getattr(l, "type")) == T_VOID) {
+ l = nextSibling(l);
+ }
+ }
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("in", l, NULL);
+ Swig_typemap_attach_parms("dtype", l, NULL);
+ Swig_typemap_attach_parms("din", l, NULL);
+
+ // Get return types.
+ if ((tm = lookupDTypemap(n, "dtype"))) {
+ String *dtypeout = Getattr(n, "tmap:dtype:out");
+ if (dtypeout) {
+ // The type in the dtype typemap's out attribute overrides the type in
+ // the typemap.
+ tm = dtypeout;
+ replaceClassname(tm, t);
+ }
+ Printf(return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ if (wrapping_member_flag) {
+ // Check if this is a setter method for a public member.
+ const String *setter_name = Swig_name_set(getNSpace(),
+ Swig_name_member(0, proxy_class_name, variable_name));
+
+ if (Cmp(Getattr(n, "sym:name"), setter_name) == 0) {
+ setter_flag = true;
+ }
+ }
+
+ // Write function modifiers.
+ {
+ String *modifiers;
+
+ const String *mods_override = Getattr(n, "feature:d:methodmodifiers");
+ if (mods_override) {
+ modifiers = Copy(mods_override);
+ } else {
+ modifiers = Copy(is_public(n) ? public_string : protected_string);
+
+ if (Getattr(n, "override")) {
+ Printf(modifiers, " override");
+ }
+ }
+
+ if (is_smart_pointer()) {
+ // Smart pointer classes do not mirror the inheritance hierarchy of the
+ // underlying pointer type, so no override required.
+ Replaceall(modifiers, "override", "");
+ }
+
+ Chop(modifiers);
+
+ if (static_flag) {
+ Printf(modifiers, " static");
+ }
+
+ Printf(function_code, "%s ", modifiers);
+ Delete(modifiers);
+ }
+
+ // Complete the function declaration up to the parameter list.
+ Printf(function_code, "%s %s(", return_type, proxy_function_name);
+
+ // Write the wrapper function call up to the parameter list.
+ Printv(imcall, im_dmodule_fq_name, ".$imfuncname(", NIL);
+ if (!static_flag) {
+ Printf(imcall, "cast(void*)swigCPtr");
+ }
+
+ String *proxy_param_types = NewString("");
+
+ // Write the parameter list for the proxy function declaration and the
+ // wrapper function call.
+ emit_mark_varargs(l);
+ int gencomma = !static_flag;
+ for (i = 0, p = l; p; i++) {
+ // Ignored varargs.
+ if (checkAttribute(p, "varargs:ignore", "1")) {
+ p = nextSibling(p);
+ continue;
+ }
+
+ // Ignored parameters.
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ // Ignore the 'this' argument for variable wrappers.
+ if (!(variable_wrapper_flag && i == 0)) {
+ String *param_name = makeParameterName(n, p, i, setter_flag);
+ SwigType *pt = Getattr(p, "type");
+
+ // Write the wrapper function call argument.
+ {
+ if (gencomma) {
+ Printf(imcall, ", ");
+ }
+
+ if ((tm = lookupDTypemap(p, "din", true))) {
+ Replaceall(tm, "$dinput", param_name);
+ String *pre = Getattr(p, "tmap:din:pre");
+ if (pre) {
+ replaceClassname(pre, pt);
+ Replaceall(pre, "$dinput", param_name);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:din:post");
+ if (post) {
+ replaceClassname(post, pt);
+ Replaceall(post, "$dinput", param_name);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ String *terminator = Getattr(p, "tmap:din:terminator");
+ if (terminator) {
+ replaceClassname(terminator, pt);
+ Replaceall(terminator, "$dinput", param_name);
+ if (Len(terminator_code) > 0)
+ Insert(terminator_code, 0, "\n");
+ Insert(terminator_code, 0, terminator);
+ }
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DIN_UNDEF, input_file, line_number,
+ "No din typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+ }
+
+ // Write the D proxy function parameter.
+ {
+ String *proxy_type = NewString("");
+
+ if ((tm = lookupDTypemap(p, "dtype"))) {
+ const String *inattributes = Getattr(p, "tmap:dtype:inattributes");
+ Printf(proxy_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma >= 2) {
+ Printf(function_code, ", ");
+ Printf(proxy_param_types, ", ");
+ }
+ gencomma = 2;
+ Printf(function_code, "%s %s", proxy_type, param_name);
+ Append(proxy_param_types, proxy_type);
+
+ Delete(proxy_type);
+ }
+
+ Delete(param_name);
+ }
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Printf(imcall, ")");
+ Printf(function_code, ") ");
+
+ if (d_version > 1 && wrapping_member_flag) {
+ Printf(function_code, "@property ");
+ }
+
+ if (wrapMemberFunctionAsDConst(n)) {
+ Printf(function_code, "const ");
+ }
+
+ // Lookup the code used to convert the wrapper return value to the proxy
+ // function return type.
+ if ((tm = lookupDTypemap(n, "dout"))) {
+ replaceExcode(n, tm, "dout", n);
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ bool is_terminator_code = Len(terminator_code) > 0;
+ if (is_pre_code || is_post_code || is_terminator_code) {
+ if (is_post_code) {
+ Insert(tm, 0, "\n try ");
+ Printv(tm, " finally {\n", post_code, "\n }", NIL);
+ } else {
+ Insert(tm, 0, "\n ");
+ }
+ if (is_pre_code) {
+ Insert(tm, 0, pre_code);
+ Insert(tm, 0, "\n");
+ }
+ if (is_terminator_code) {
+ Printv(tm, "\n", terminator_code, NIL);
+ }
+ Insert(tm, 0, "{");
+ Printv(tm, "}", NIL);
+ }
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ replaceClassname(tm, t);
+
+ // For director methods: generate code to selectively make a normal
+ // polymorphic call or an explicit method call. Needed to prevent infinite
+ // recursion when calling director methods.
+ Node *explicit_n = Getattr(n, "explicitcallnode");
+ if (explicit_n && Swig_directorclass(getCurrentClass())) {
+ String *ex_overloaded_name = getOverloadedName(explicit_n);
+ String *ex_intermediary_function_name = Swig_name_member(getNSpace(), proxy_class_name, ex_overloaded_name);
+
+ String *ex_imcall = Copy(imcall);
+ Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
+ Replaceall(imcall, "$imfuncname", intermediary_function_name);
+
+ String *excode = NewString("");
+ if (!Cmp(return_type, "void"))
+ Printf(excode, "if (swigIsMethodOverridden!(%s delegate(%s), %s function(%s), %s)()) %s; else %s",
+ return_type, proxy_param_types, return_type, proxy_param_types, proxy_function_name, ex_imcall, imcall);
+ else
+ Printf(excode, "((swigIsMethodOverridden!(%s delegate(%s), %s function(%s), %s)()) ? %s : %s)",
+ return_type, proxy_param_types, return_type, proxy_param_types, proxy_function_name, ex_imcall, imcall);
+
+ Clear(imcall);
+ Printv(imcall, excode, NIL);
+ Delete(ex_overloaded_name);
+ Delete(excode);
+ } else {
+ Replaceall(imcall, "$imfuncname", intermediary_function_name);
+ }
+ Replaceall(tm, "$imcall", imcall);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DOUT_UNDEF, input_file, line_number,
+ "No dout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ Delete(proxy_param_types);
+
+ // The whole function body is now in stored tm (if there was a matching type
+ // map, of course), so simply append it to the code buffer. The braces are
+ // included in the typemap.
+ Printv(function_code, tm, NIL);
+
+ // Write function code buffer to the class code.
+ Printv(proxy_class_body_code, "\n", function_code, "\n", NIL);
+
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(terminator_code);
+ Delete(function_code);
+ Delete(return_type);
+ Delete(imcall);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeProxyDModuleFunction()
+ * --------------------------------------------------------------------------- */
+ void writeProxyDModuleFunction(Node *n) {
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ int i;
+ String *imcall = NewString("");
+ String *return_type = NewString("");
+ String *function_code = NewString("");
+ int num_arguments = 0;
+ String *overloaded_name = getOverloadedName(n);
+ String *func_name = NULL;
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *terminator_code = NewString("");
+
+ // RESEARCH: What is this good for?
+ if (l) {
+ if (SwigType_type(Getattr(l, "type")) == T_VOID) {
+ l = nextSibling(l);
+ }
+ }
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("dtype", l, NULL);
+ Swig_typemap_attach_parms("din", l, NULL);
+
+ /* Get return types */
+ if ((tm = lookupDTypemap(n, "dtype"))) {
+ String *dtypeout = Getattr(n, "tmap:dtype:out");
+ if (dtypeout) {
+ // The type in the dtype typemap's out attribute overrides the type in
+ // the typemap.
+ tm = dtypeout;
+ replaceClassname(tm, t);
+ }
+ Printf(return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ /* Change function name for global variables */
+ if (global_variable_flag) {
+ // RESEARCH: Is the Copy() needed here?
+ func_name = Copy(variable_name);
+ } else {
+ func_name = Copy(Getattr(n, "sym:name"));
+ }
+
+ /* Start generating the function */
+ const String *outattributes = Getattr(n, "tmap:dtype:outattributes");
+ if (outattributes)
+ Printf(function_code, " %s\n", outattributes);
+
+ const String *methodmods = Getattr(n, "feature:d:methodmodifiers");
+ // TODO: Check if is_public(n) could possibly make any sense here
+ // (private global functions would be useless anyway?).
+ methodmods = methodmods ? methodmods : empty_string;
+
+ Printf(function_code, "\n%s%s %s(", methodmods, return_type, func_name);
+ Printv(imcall, im_dmodule_fq_name, ".", overloaded_name, "(", NIL);
+
+ /* Get number of required and total arguments */
+ num_arguments = emit_num_arguments(l);
+
+ int gencomma = 0;
+
+ /* Output each parameter */
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ /* Ignored parameters */
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+
+ // Get the D parameter type.
+ if ((tm = lookupDTypemap(p, "dtype", true))) {
+ const String *inattributes = Getattr(p, "tmap:dtype:inattributes");
+ Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ const bool generating_setter = global_variable_flag || wrapping_member_flag;
+ String *arg = makeParameterName(n, p, i, generating_setter);
+
+ // Get the D code to convert the parameter value to the type used in the
+ // wrapper D module.
+ if ((tm = lookupDTypemap(p, "din", true))) {
+ Replaceall(tm, "$dinput", arg);
+ String *pre = Getattr(p, "tmap:din:pre");
+ if (pre) {
+ replaceClassname(pre, pt);
+ Replaceall(pre, "$dinput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:din:post");
+ if (post) {
+ replaceClassname(post, pt);
+ Replaceall(post, "$dinput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ String *terminator = Getattr(p, "tmap:din:terminator");
+ if (terminator) {
+ replaceClassname(terminator, pt);
+ Replaceall(terminator, "$dinput", arg);
+ if (Len(terminator_code) > 0)
+ Insert(terminator_code, 0, "\n");
+ Insert(terminator_code, 0, terminator);
+ }
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DIN_UNDEF, input_file, line_number,
+ "No din typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to module class function */
+ if (gencomma >= 2)
+ Printf(function_code, ", ");
+ gencomma = 2;
+ Printf(function_code, "%s %s", param_type, arg);
+
+ p = Getattr(p, "tmap:in:next");
+ Delete(arg);
+ Delete(param_type);
+ }
+
+ Printf(imcall, ")");
+ Printf(function_code, ") ");
+
+ if (global_variable_flag && (d_version > 1)) {
+ Printf(function_code, "@property ");
+ }
+
+ // Lookup the code used to convert the wrapper return value to the proxy
+ // function return type.
+ if ((tm = lookupDTypemap(n, "dout"))) {
+ replaceExcode(n, tm, "dout", n);
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ bool is_terminator_code = Len(terminator_code) > 0;
+ if (is_pre_code || is_post_code || is_terminator_code) {
+ if (is_post_code) {
+ Insert(tm, 0, "\n try ");
+ Printv(tm, " finally {\n", post_code, "\n }", NIL);
+ } else {
+ Insert(tm, 0, "\n ");
+ }
+ if (is_pre_code) {
+ Insert(tm, 0, pre_code);
+ Insert(tm, 0, "\n");
+ }
+ if (is_terminator_code) {
+ Printv(tm, "\n", terminator_code, NIL);
+ }
+ Insert(tm, 0, " {");
+ Printf(tm, "\n}");
+ }
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ replaceClassname(tm, t);
+ Replaceall(tm, "$imcall", imcall);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DOUT_UNDEF, input_file, line_number,
+ "No dout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ // The whole function code is now stored in tm (if there was a matching
+ // type map, of course), so simply append it to the code buffer.
+ Printf(function_code, "%s\n", tm ? (const String *) tm : empty_string);
+ Printv(proxyCodeBuffer(getNSpace()), function_code, NIL);
+
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(terminator_code);
+ Delete(function_code);
+ Delete(return_type);
+ Delete(imcall);
+ Delete(func_name);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeProxyClassAndUpcasts()
+ *
+ * Collects all the code fragments generated by the handler function while
+ * traversing the tree from the proxy_class_* variables and writes the
+ * class definition (including any epilogue code) to proxy_class_code.
+ *
+ * Also writes the upcast function to the wrapper layer when processing a
+ * derived class.
+ *
+ * Inputs:
+ * n – The class node currently processed.
+ * --------------------------------------------------------------------------- */
+ void writeProxyClassAndUpcasts(Node *n) {
+ SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
+
+ /*
+ * Handle inheriting from D and C++ classes.
+ */
+
+ String *c_classname = Getattr(n, "name");
+ String *c_baseclassname = NULL;
+ Node *basenode = NULL;
+ String *baseclass = NULL;
+
+ // Inheritance from pure D classes.
+ Node *attributes = NewHash();
+ const String *pure_baseclass =
+ lookupCodeTypemap(n, "dbase", typemap_lookup_type, WARN_NONE, attributes);
+ bool purebase_replace = GetFlag(attributes, "tmap:dbase:replace") ? true : false;
+ bool purebase_notderived = GetFlag(attributes, "tmap:dbase:notderived") ? true : false;
+ Delete(attributes);
+
+ // C++ inheritance.
+ if (!purebase_replace) {
+ List *baselist = Getattr(n, "bases");
+ if (baselist) {
+ Iterator base = First(baselist);
+ while (base.item) {
+ if (!GetFlag(base.item, "feature:ignore")) {
+ SwigType *baseclassname = Getattr(base.item, "name");
+ if (!c_baseclassname) {
+ basenode = base.item;
+ String *name = createProxyName(baseclassname);
+ if (name) {
+ c_baseclassname = baseclassname;
+ baseclass = name;
+ }
+ } else {
+ /* Warn about multiple inheritance for additional base class(es) */
+ String *proxyclassname = Getattr(n, "classtypeobj");
+ Swig_warning(WARN_D_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Base %s of class %s ignored: multiple inheritance is not supported in D.\n", SwigType_namestr(baseclassname), SwigType_namestr(proxyclassname));
+ }
+ }
+ base = Next(base);
+ }
+ }
+ }
+
+ bool derived = baseclass != NULL;
+
+ if (derived && purebase_notderived) {
+ pure_baseclass = empty_string;
+ }
+ const String *wanted_base = baseclass ? baseclass : pure_baseclass;
+
+ if (purebase_replace) {
+ wanted_base = pure_baseclass;
+ derived = false;
+ basenode = NULL;
+ baseclass = NULL;
+ if (purebase_notderived) {
+ Swig_error(Getfile(n), Getline(n),
+ "The dbase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n",
+ typemap_lookup_type);
+ }
+ } else if (baseclass && Len(pure_baseclass) > 0) {
+ Swig_warning(WARN_D_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Warning for %s, base class %s ignored. Multiple inheritance is not supported in D. "
+ "Perhaps you need one of the 'replace' or 'notderived' attributes in the dbase typemap?\n", typemap_lookup_type, pure_baseclass);
+ }
+
+ // Add code to do C++ casting to base class (only for classes in an inheritance hierarchy)
+ if (derived) {
+ writeClassUpcast(n, proxy_class_name, c_classname, c_baseclassname);
+ }
+
+ /*
+ * Write needed imports.
+ */
+ // If this class is derived from a C++ class, we need to have the D class
+ // generated for it in scope.
+ if (derived) {
+ requireDType(Getattr(basenode, "sym:nspace"), Getattr(basenode, "sym:name"));
+ }
+
+ // Write any custom import statements to the proxy module header.
+ const String *imports = lookupCodeTypemap(n, "dimports", typemap_lookup_type, WARN_NONE);
+ if (Len(imports) > 0) {
+ String* imports_trimmed = Copy(imports);
+ Chop(imports_trimmed);
+ replaceImportTypeMacros(imports_trimmed);
+ Printv(proxy_class_imports, imports_trimmed, "\n", NIL);
+ Delete(imports_trimmed);
+ }
+
+ /*
+ * Write the proxy class header.
+ */
+ // Class modifiers.
+ const String *modifiers =
+ lookupCodeTypemap(n, "dclassmodifiers", typemap_lookup_type, WARN_D_TYPEMAP_CLASSMOD_UNDEF);
+
+ // User-defined interfaces.
+ const String *interfaces =
+ lookupCodeTypemap(n, derived ? "dinterfaces_derived" : "dinterfaces", typemap_lookup_type, WARN_NONE);
+
+ Printv(proxy_class_code,
+ "\n",
+ modifiers,
+ " $dclassname",
+ (*Char(wanted_base) || *Char(interfaces)) ? " : " : "", wanted_base,
+ (*Char(wanted_base) && *Char(interfaces)) ? ", " : "", interfaces, " {",
+ NIL);
+
+ /*
+ * Write the proxy class body.
+ */
+ String* body = NewString("");
+
+ // Default class body.
+ const String *dbody;
+ if (derived) {
+ dbody = lookupCodeTypemap(n, "dbody_derived", typemap_lookup_type, WARN_D_TYPEMAP_DBODY_UNDEF);
+ } else {
+ dbody = lookupCodeTypemap(n, "dbody", typemap_lookup_type, WARN_D_TYPEMAP_DBODY_UNDEF);
+ }
+
+ Printv(body, dbody, NIL);
+
+ // Destructor and dispose().
+ // If the C++ destructor is accessible (public), it is wrapped by the
+ // dispose() method which is also called by the emitted D constructor. If it
+ // is not accessible, no D destructor is written and the generated dispose()
+ // method throws an exception.
+ // This enables C++ classes with protected or private destructors to be used
+ // in D as it would be used in C++ (GC finalization is a no-op then because
+ // of the empty D destructor) while preventing usage in »scope« variables.
+ // The method name for the dispose() method is specified in a typemap
+ // attribute called »methodname«.
+ const String *tm = NULL;
+
+ const String *dispose_methodname;
+ const String *dispose_methodmodifiers;
+ const String *dispose_parameters;
+ attributes = NewHash();
+ if (derived) {
+ tm = lookupCodeTypemap(n, "ddispose_derived", typemap_lookup_type, WARN_NONE, attributes);
+ dispose_methodname = Getattr(attributes, "tmap:ddispose_derived:methodname");
+ dispose_methodmodifiers = Getattr(attributes, "tmap:ddispose_derived:methodmodifiers");
+ dispose_parameters = Getattr(attributes, "tmap:ddispose_derived:parameters");
+ } else {
+ tm = lookupCodeTypemap(n, "ddispose", typemap_lookup_type, WARN_NONE, attributes);
+ dispose_methodname = Getattr(attributes, "tmap:ddispose:methodname");
+ dispose_methodmodifiers = Getattr(attributes, "tmap:ddispose:methodmodifiers");
+ dispose_parameters = Getattr(attributes, "tmap:ddispose:parameters");
+ }
+
+ if (tm && *Char(tm)) {
+ if (!dispose_methodname) {
+ Swig_error(Getfile(n), Getline(n),
+ "No methodname attribute defined in the ddispose%s typemap for %s\n",
+ (derived ? "_derived" : ""), proxy_class_name);
+ }
+ if (!dispose_methodmodifiers) {
+ Swig_error(Getfile(n), Getline(n),
+ "No methodmodifiers attribute defined in ddispose%s typemap for %s.\n",
+ (derived ? "_derived" : ""), proxy_class_name);
+ }
+ if (!dispose_parameters)
+ dispose_parameters = empty_string;
+ }
+
+ if (tm) {
+ // Write the destructor if the C++ one is accessible.
+ if (*Char(destructor_call)) {
+ Printv(body,
+ lookupCodeTypemap(n, "ddestructor", typemap_lookup_type, WARN_NONE), NIL);
+ }
+
+ // Write the dispose() method.
+ String *dispose_code = NewString("");
+ Printv(dispose_code, tm, NIL);
+
+ if (*Char(destructor_call)) {
+ Replaceall(dispose_code, "$imcall", destructor_call);
+ } else {
+ Replaceall(dispose_code, "$imcall", "throw new object.Exception(\"C++ destructor does not have public access\")");
+ }
+
+ if (*Char(dispose_code)) {
+ Printv(body, "\n", NIL);
+ const String *methodmods = Getattr(n, "destructmethodmodifiers");
+ if (methodmods)
+ Printv(body, methodmods, NIL);
+ else
+ Printv(body, dispose_methodmodifiers, (derived ? " override" : ""), NIL);
+ Printv(body, " void ", dispose_methodname, "(", dispose_parameters, ") ", dispose_code, "\n", NIL);
+ }
+ }
+
+ if (Swig_directorclass(n)) {
+ // If directors are enabled for the current class, generate the
+ // director connect helper function which is called from the constructor
+ // and write it to the class body.
+ writeDirectorConnectProxy(n);
+ }
+
+ // Write all constants and enumerations first to prevent forward reference
+ // errors.
+ Printv(body, proxy_class_enums_code, NIL);
+
+ // Write the code generated in other methods to the class body.
+ Printv(body, proxy_class_body_code, NIL);
+
+ // Append extra user D code to the class body.
+ Printv(body,
+ lookupCodeTypemap(n, "dcode", typemap_lookup_type, WARN_NONE), "\n", NIL);
+
+ // Write the class body and the curly bracket closing the class definition
+ // to the proxy module.
+ indentCode(body);
+ Replaceall(body, "$dbaseclass", baseclass);
+
+ Printv(proxy_class_code, body, "\n}\n", NIL);
+ Delete(body);
+
+ // Write the epilogue code if there is any.
+ Printv(proxy_class_code, proxy_class_epilogue_code, NIL);
+ }
+
+
+ /* ---------------------------------------------------------------------------
+ * D::writeClassUpcast()
+ * --------------------------------------------------------------------------- */
+ void writeClassUpcast(Node *n, const String* d_class_name, SwigType* c_classname, SwigType* c_baseclassname) {
+
+ SwigType *smart = Swig_cparse_smartptr(n);
+ String *upcast_name = Swig_name_member(getNSpace(), d_class_name, (smart != 0 ? "SmartPtrUpcast" : "Upcast"));
+ String *upcast_wrapper_name = Swig_name_wrapper(upcast_name);
+
+ writeImDModuleFunction(upcast_name, "void*", "(void* objectRef)",
+ upcast_wrapper_name);
+
+ String *classname = SwigType_namestr(c_classname);
+ String *baseclassname = SwigType_namestr(c_baseclassname);
+ if (smart) {
+ String *smartnamestr = SwigType_namestr(smart);
+ String *bsmartnamestr = SwigType_namestr(smart);
+
+ // TODO: SwigType_typedef_resolve_all on a String instead of SwigType is incorrect for templates
+ SwigType *rclassname = SwigType_typedef_resolve_all(classname);
+ SwigType *rbaseclassname = SwigType_typedef_resolve_all(baseclassname);
+ Replaceall(bsmartnamestr, rclassname, rbaseclassname);
+
+ Printv(upcasts_code,
+ "SWIGEXPORT ", bsmartnamestr, " * ", upcast_wrapper_name,
+ "(", smartnamestr, " *objectRef) {\n",
+ " return objectRef ? new ", bsmartnamestr, "(*objectRef) : 0;\n"
+ "}\n",
+ "\n", NIL);
+
+ Delete(rbaseclassname);
+ Delete(rclassname);
+ Delete(bsmartnamestr);
+ Delete(smartnamestr);
+ } else {
+ Printv(upcasts_code,
+ "SWIGEXPORT ", baseclassname, " * ", upcast_wrapper_name,
+ "(", baseclassname, " *objectRef) {\n",
+ " return (", baseclassname, " *)objectRef;\n"
+ "}\n",
+ "\n", NIL);
+ }
+
+ Replaceall(upcasts_code, "$cclass", classname);
+ Replaceall(upcasts_code, "$cbaseclass", baseclassname);
+
+ Delete(baseclassname);
+ Delete(classname);
+ Delete(upcast_name);
+ Delete(upcast_wrapper_name);
+ Delete(smart);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeTypeWrapperClass()
+ * --------------------------------------------------------------------------- */
+ void writeTypeWrapperClass(String *classname, SwigType *type) {
+ Node *n = NewHash();
+ Setfile(n, input_file);
+ Setline(n, line_number);
+
+ assertClassNameValidity(classname);
+
+ String* imports_target;
+ String* code_target;
+ File *class_file = NULL;
+ if (split_proxy_dmodule) {
+ String *filename = NewStringf("%s%s.d", dmodule_directory, classname);
+ class_file = NewFile(filename, "w", SWIG_output_files());
+ if (!class_file) {
+ FileErrorDisplay(filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filename));
+ Delete(filename);
+
+ emitBanner(class_file);
+ Printf(class_file, "module %s%s;\n", package, classname);
+ Printf(class_file, "\nstatic import %s;\n", im_dmodule_fq_name);
+
+ imports_target = NewString("");
+ code_target = NewString("");
+ } else {
+ imports_target = proxyImportsBuffer(0);
+ code_target = proxyCodeBuffer(0);
+ }
+
+ // Import statements.
+ const String *imports = lookupCodeTypemap(n, "dimports", type, WARN_NONE);
+ if (Len(imports) > 0) {
+ String *imports_trimmed = Copy(imports);
+ Chop(imports_trimmed);
+ replaceImportTypeMacros(imports_trimmed);
+ Printv(imports_target, imports_trimmed, "\n", NIL);
+ Delete(imports_trimmed);
+ }
+
+ // Pure D baseclass and interfaces (no C++ inheritance possible.
+ const String *pure_baseclass = lookupCodeTypemap(n, "dbase", type, WARN_NONE);
+ const String *pure_interfaces = lookupCodeTypemap(n, "dinterfaces", type, WARN_NONE);
+
+ // Emit the class.
+ Printv(code_target,
+ "\n",
+ lookupCodeTypemap(n, "dclassmodifiers", type, WARN_D_TYPEMAP_CLASSMOD_UNDEF),
+ " $dclassname",
+ (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass,
+ ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ? ", " : "", pure_interfaces,
+ " {", NIL);
+
+ String* body = NewString("");
+ Printv(body, lookupCodeTypemap(n, "dbody", type, WARN_D_TYPEMAP_DBODY_UNDEF),
+ lookupCodeTypemap(n, "dcode", type, WARN_NONE), NIL);
+ indentCode(body);
+ Printv(code_target, body, "\n}\n", NIL);
+ Delete(body);
+
+ Replaceall(code_target, "$dclassname", classname);
+
+ if (split_proxy_dmodule) {
+ Printv(class_file, imports_target, NIL);
+ Delete(imports_target);
+
+ replaceModuleVariables(code_target);
+ Printv(class_file, code_target, NIL);
+ Delete(code_target);
+
+ Delete(class_file);
+ }
+
+ Delete(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeDirectorConnectProxy(Node *classNode)
+ *
+ * Writes the helper method which registers the director callbacks by calling
+ * the director connect function from the D side to the proxy class.
+ * --------------------------------------------------------------------------- */
+ void writeDirectorConnectProxy(Node* classNode) {
+ String *dirClassName = directorClassName(classNode);
+ String *connect_name = Swig_name_member(getNSpace(),
+ proxy_class_name, "director_connect");
+ Printf(proxy_class_body_code, "\nprivate void swigDirectorConnect() {\n");
+
+ int i;
+ for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *method = Getattr(udata, "method");
+ String *overloaded_name = Getattr(udata, "overname");
+ String *return_type = Getattr(udata, "return_type");
+ String *param_list = Getattr(udata, "param_list");
+ String *methid = Getattr(udata, "class_methodidx");
+ Printf(proxy_class_body_code, " %s.%s_Callback%s callback%s;\n", im_dmodule_fq_name, dirClassName, methid, methid);
+ Printf(proxy_class_body_code, " if (swigIsMethodOverridden!(%s delegate(%s), %s function(%s), %s)()) {\n", return_type, param_list, return_type, param_list, method);
+ Printf(proxy_class_body_code, " callback%s = &swigDirectorCallback_%s_%s;\n", methid, proxy_class_name, overloaded_name);
+ Printf(proxy_class_body_code, " }\n\n");
+ }
+ Printf(proxy_class_body_code, " %s.%s(cast(void*)swigCPtr, cast(void*)this", im_dmodule_fq_name, connect_name);
+ for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *methid = Getattr(udata, "class_methodidx");
+ Printf(proxy_class_body_code, ", callback%s", methid);
+ }
+ Printf(proxy_class_body_code, ");\n");
+ Printf(proxy_class_body_code, "}\n");
+
+ // Helper function to determine if a method has been overridden in a
+ // subclass of the wrapped class. If not, we just pass null to the
+ // director_connect_function since the method from the C++ class should
+ // be called as usual (see above).
+ // Only emit it if the proxy class has at least one method.
+ if (first_class_dmethod < curr_class_dmethod) {
+ Printf(proxy_class_body_code, "\n");
+ Printf(proxy_class_body_code, "private bool swigIsMethodOverridden(DelegateType, FunctionType, alias fn)() %s{\n", (d_version > 1) ? "const " : "");
+ Printf(proxy_class_body_code, " DelegateType dg = &fn;\n");
+ Printf(proxy_class_body_code, " return dg.funcptr != SwigNonVirtualAddressOf!(FunctionType, fn);\n");
+ Printf(proxy_class_body_code, "}\n");
+ Printf(proxy_class_body_code, "\n");
+ Printf(proxy_class_body_code, "private static Function SwigNonVirtualAddressOf(Function, alias fn)() {\n");
+ Printf(proxy_class_body_code, " return cast(Function) &fn;\n");
+ Printf(proxy_class_body_code, "}\n");
+ }
+
+ if (Len(director_dcallbacks_code) > 0) {
+ Printv(proxy_class_epilogue_code, director_dcallbacks_code, NIL);
+ }
+
+ Delete(director_callback_typedefs);
+ director_callback_typedefs = NULL;
+ Delete(director_callback_pointers);
+ director_callback_pointers = NULL;
+ Delete(director_dcallbacks_code);
+ director_dcallbacks_code = NULL;
+ Delete(dirClassName);
+ Delete(connect_name);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeDirectorConnectWrapper()
+ *
+ * Writes the director connect function and the corresponding declaration to
+ * the C++ wrapper respectively the D wrapper.
+ * --------------------------------------------------------------------------- */
+ void writeDirectorConnectWrapper(Node *n) {
+ if (!Swig_directorclass(n))
+ return;
+
+ // Output the director connect method.
+ String *norm_name = SwigType_namestr(Getattr(n, "name"));
+ String *connect_name = Swig_name_member(getNSpace(),
+ proxy_class_name, "director_connect");
+ String *dirClassName = directorClassName(n);
+ Wrapper *code_wrap;
+
+ Printv(wrapper_loader_bind_code, wrapper_loader_bind_command, NIL);
+ Replaceall(wrapper_loader_bind_code, "$function", connect_name);
+ Replaceall(wrapper_loader_bind_code, "$symbol", Swig_name_wrapper(connect_name));
+
+ Printf(im_dmodule_code, "extern(C) void function(void* cObject, void* dObject");
+
+ code_wrap = NewWrapper();
+ Printf(code_wrap->def, "SWIGEXPORT void D_%s(void *objarg, void *dobj", connect_name);
+
+ Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", norm_name, norm_name);
+ Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName);
+
+ Printf(code_wrap->code, " director->swig_connect_director(dobj");
+
+ for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *methid = Getattr(udata, "class_methodidx");
+
+ Printf(code_wrap->def, ", %s::SWIG_Callback%s_t callback%s", dirClassName, methid, methid);
+ Printf(code_wrap->code, ", callback%s", methid);
+ Printf(im_dmodule_code, ", %s_Callback%s callback%s", dirClassName, methid, methid);
+ }
+
+ Printf(code_wrap->def, ") {\n");
+ Printf(code_wrap->code, ");\n");
+ Printf(im_dmodule_code, ") %s;\n", connect_name);
+ Printf(code_wrap->code, "}\n");
+
+ Wrapper_print(code_wrap, f_wrappers);
+ DelWrapper(code_wrap);
+
+ Delete(connect_name);
+ Delete(dirClassName);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::requireDType()
+ *
+ * If the given type is not already in scope in the current module, adds an
+ * import statement for it. The name is considered relative to the global root
+ * package if one is set.
+ *
+ * This is only used for dependencies created in generated code, user-
+ * (i.e. typemap-) specified import statements are handled separately.
+ * --------------------------------------------------------------------------- */
+ void requireDType(const String *nspace, const String *symname) {
+ String *dmodule = createModuleName(nspace, symname);
+
+ if (!inProxyModule(dmodule)) {
+ String *import = createImportStatement(dmodule);
+ Append(import, "\n");
+ if (is_wrapping_class()) {
+ addImportStatement(proxy_class_imports, import);
+ } else {
+ addImportStatement(proxyImportsBuffer(getNSpace()), import);
+ }
+ Delete(import);
+ }
+ Delete(dmodule);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::addImportStatement()
+ *
+ * Adds the given import statement to the given list of import statements if
+ * there is no statement importing that module present yet.
+ * --------------------------------------------------------------------------- */
+ void addImportStatement(String *target, const String *import) const {
+ char *position = Strstr(target, import);
+ if (position) {
+ // If the import statement has been found in the target string, we have to
+ // check if the previous import was static, which would lead to problems
+ // if this import is not.
+ // Thus, we check if the seven characters in front of the occurrence are
+ // »static «. If the import string passed is also static, the checks fail
+ // even if the found statement is also static because the last seven
+ // characters would be part of the previous import statement then.
+
+ if (position - Char(target) < 7) {
+ return;
+ }
+ if (strncmp(position - 7, "static ", 7)) {
+ return;
+ }
+ }
+
+ Printv(target, import, NIL);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::createImportStatement()
+ *
+ * Creates a string containing an import statement for the given module.
+ * --------------------------------------------------------------------------- */
+ String *createImportStatement(const String *dmodule_name,
+ bool static_import = true) const {
+
+ if (static_import) {
+ return NewStringf("static import %s%s;", package, dmodule_name);
+ } else {
+ return NewStringf("import %s%s;", package, dmodule_name);
+ }
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::inProxyModule()
+ *
+ * Determines if the specified proxy type is declared in the currently
+ * processed proxy D module.
+ *
+ * This function is used to determine if fully qualified type names have to
+ * be used (package, module and type name). If the split proxy mode is not
+ * used, this solely depends on whether the type is in the current namespace.
+ * --------------------------------------------------------------------------- */
+ bool inProxyModule(const String *type_name) const {
+ if (!split_proxy_dmodule) {
+ String *nspace = createOuterNamespaceNames(type_name);
+
+ // Check if strings are either both null (no namespace) or are both
+ // non-null and have the same contents. Cannot use Strcmp for this
+ // directly because of its strange way of handling the case where only
+ // one argument is 0 ("<").
+ bool result = !nspace && !getNSpace();
+ if (nspace && getNSpace())
+ result = (Strcmp(nspace, getNSpace()) == 0);
+
+ Delete(nspace);
+ return result;
+ }
+
+ if (!is_wrapping_class()) {
+ return false;
+ }
+
+ return (Strcmp(proxy_class_qname, type_name) == 0);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::addUpcallMethod()
+ *
+ * Adds new director upcall signature.
+ * --------------------------------------------------------------------------- */
+ UpcallData *addUpcallMethod(String *imclass_method, String *class_method,
+ String *decl, String *overloaded_name, String *return_type, String *param_list) {
+
+ String *key = NewStringf("%s|%s", imclass_method, decl);
+
+ ++curr_class_dmethod;
+
+ String *class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
+ n_dmethods++;
+
+ Hash *new_udata = NewHash();
+ Append(dmethods_seq, new_udata);
+ Setattr(dmethods_table, key, new_udata);
+
+ Setattr(new_udata, "method", Copy(class_method));
+ Setattr(new_udata, "class_methodidx", class_methodidx);
+ Setattr(new_udata, "decl", Copy(decl));
+ Setattr(new_udata, "overname", Copy(overloaded_name));
+ Setattr(new_udata, "return_type", Copy(return_type));
+ Setattr(new_udata, "param_list", Copy(param_list));
+
+ Delete(key);
+ return new_udata;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::assertClassNameValidity()
+ * --------------------------------------------------------------------------- */
+ void assertClassNameValidity(const String* class_name) const {
+ // TODO: With nspace support, there could arise problems also when not in
+ // split proxy mode, warnings for these should be added.
+ if (split_proxy_dmodule) {
+ if (Cmp(class_name, im_dmodule_name) == 0) {
+ Swig_error(input_file, line_number,
+ "Class name cannot be equal to intermediary D module name: %s\n",
+ class_name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ String *nspace = getNSpace();
+ if (nspace) {
+ // Check the root package/outermost namespace (a class A in module
+ // A.B leads to problems if another module A.C is also imported)
+ if (Len(package) > 0) {
+ String *dotless_package = NewStringWithSize(package, Len(package) - 1);
+ if (Cmp(class_name, dotless_package) == 0) {
+ Swig_error(input_file, line_number,
+ "Class name cannot be the same as the root package it is in: %s\n",
+ class_name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(dotless_package);
+ } else {
+ String *outer = createFirstNamespaceName(nspace);
+ if (Cmp(class_name, outer) == 0) {
+ Swig_error(input_file, line_number,
+ "Class name cannot be the same as the outermost namespace it is in: %s\n",
+ class_name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(outer);
+ }
+
+ // … and the innermost one (because of the conflict with the main proxy
+ // module named like the namespace).
+ String *inner = createLastNamespaceName(nspace);
+ if (Cmp(class_name, inner) == 0) {
+ Swig_error(input_file, line_number,
+ "Class name cannot be the same as the innermost namespace it is in: %s\n",
+ class_name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(inner);
+ } else {
+ if (Cmp(class_name, proxy_dmodule_name) == 0) {
+ Swig_error(input_file, line_number,
+ "Class name cannot be equal to proxy D module name: %s\n",
+ class_name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+ }
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::getPrimitiveDptype()
+ *
+ * Returns the D proxy type for the passed type if it is a primitive type in
+ * both C and D.
+ * --------------------------------------------------------------------------- */
+ String *getPrimitiveDptype(Node *node, SwigType *type) {
+ SwigType *stripped_type = SwigType_typedef_resolve_all(type);
+
+ // A reference can only be the »outermost element« of a type.
+ bool mutable_ref = false;
+ if (SwigType_isreference(stripped_type)) {
+ SwigType_del_reference(stripped_type);
+
+ if (SwigType_isconst(stripped_type)) {
+ SwigType_del_qualifier(stripped_type);
+ } else {
+ mutable_ref = true;
+ }
+ }
+
+ // Strip all the pointers from the type.
+ int indirection_count = 0;
+ while (SwigType_ispointer(stripped_type)) {
+ ++indirection_count;
+ SwigType_del_pointer(stripped_type);
+ }
+
+ // Now that we got rid of the pointers, see if we are dealing with a
+ // primitive type.
+ String *dtype = 0;
+ if (SwigType_isfunction(stripped_type) && indirection_count > 0) {
+ // type was a function pointer, split it up.
+ SwigType_add_pointer(stripped_type);
+ --indirection_count;
+
+ SwigType *return_type = Copy(stripped_type);
+ SwigType *params_type = SwigType_functionpointer_decompose(return_type);
+ String *return_dtype = getPrimitiveDptype(node, return_type);
+ Delete(return_type);
+ if (!return_dtype) {
+ return 0;
+ }
+
+ List *parms = SwigType_parmlist(params_type);
+ List *param_dtypes = NewList();
+ for (Iterator it = First(parms); it.item; it = Next(it)) {
+ String *current_dtype = getPrimitiveDptype(node, it.item);
+ if (Cmp(current_dtype, "void") == 0) {
+ // void somefunc(void) is legal syntax in C, but not in D, so simply
+ // skip the void parameter.
+ Delete(current_dtype);
+ continue;
+ }
+ if (!current_dtype) {
+ Delete(return_dtype);
+ Delete(param_dtypes);
+ return 0;
+ }
+ Append(param_dtypes, current_dtype);
+ }
+
+ String *param_list = NewString("");
+ {
+ bool gen_comma = false;
+ for (Iterator it = First(param_dtypes); it.item; it = Next(it)) {
+ if (gen_comma) {
+ Append(param_list, ", ");
+ }
+ Append(param_list, it.item);
+ Delete(it.item);
+ gen_comma = true;
+ }
+ }
+
+ dtype = NewStringf("%s.SwigExternC!(%s function(%s))", im_dmodule_fq_name,
+ return_dtype, param_list);
+ Delete(param_list);
+ Delete(param_dtypes);
+ Delete(return_dtype);
+ } else {
+ Hash *attributes = NewHash();
+ const String *tm =
+ lookupCodeTypemap(node, "dtype", stripped_type, WARN_NONE, attributes);
+ if(!GetFlag(attributes, "tmap:dtype:cprimitive")) {
+ dtype = 0;
+ } else {
+ dtype = Copy(tm);
+
+ // We need to call replaceClassname here with the stripped type to avoid
+ // $dclassname in the enum typemaps being replaced later with the full
+ // type.
+ replaceClassname(dtype, stripped_type);
+ }
+ Delete(attributes);
+ }
+ Delete(stripped_type);
+
+ if (!dtype) {
+ // The type passed is no primitive type.
+ return 0;
+ }
+
+ // The type is ultimately a primitive type, now append the right number of
+ // indirection levels (pointers).
+ for (int i = 0; i < indirection_count; ++i) {
+ Append(dtype, "*");
+ }
+
+ // Add a level of indirection for a mutable reference since it is wrapped
+ // as a pointer.
+ if (mutable_ref) {
+ Append(dtype, "*");
+ }
+
+ return dtype;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::lookupCodeTypemap()
+ *
+ * Looks up a D code fragment for generating the wrapper class for the given
+ * type.
+ *
+ * n - for input only and must contain info for Getfile(n) and Getline(n) to work
+ * tmap_method - typemap method name
+ * type - typemap type to lookup
+ * warning - warning number to issue if no typemaps found
+ * typemap_attributes - the typemap attributes are attached to this node and will
+ * also be used for temporary storage if non null
+ * return is never NULL, unlike Swig_typemap_lookup()
+ * --------------------------------------------------------------------------- */
+ const String *lookupCodeTypemap(Node *n, const_String_or_char_ptr tmap_method,
+ SwigType *type, int warning, Node *typemap_attributes = 0) const {
+
+ Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
+ Setattr(node, "type", type);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
+ if (!tm) {
+ tm = empty_string;
+ if (warning != WARN_NONE) {
+ Swig_warning(warning, Getfile(n), Getline(n),
+ "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
+ }
+ }
+ if (!typemap_attributes) {
+ Delete(node);
+ }
+
+ return tm;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::lookupDTypemap()
+ *
+ * Looks up a D typemap for the given node, replacing D-specific special
+ * variables as needed.
+ *
+ * The method parameter specifies the typemap method to use. If attached is
+ * true, the value is just fetched from the tmap:<method> node attribute,
+ * Swig_typemap_lookup is used otherwise.
+ * --------------------------------------------------------------------------- */
+ String *lookupDTypemap(Node *n, const_String_or_char_ptr method, bool attached = false) {
+ String *result = 0;
+
+ if (attached) {
+ String *attr_name = NewStringf("tmap:%s", method);
+ result = Copy(Getattr(n, attr_name));
+ Delete(attr_name);
+ } else {
+ // FIXME: As a workaround for a bug so far only surfacing in the
+ // smart_pointer_const_overload test case, remove the nativepointer
+ // typemap attribute since it seems to be already there from a dout
+ // typemap of a different type in that test.
+ String *np_key = NewStringf("tmap:%s:nativepointer", method);
+ Delattr(n, np_key);
+ Delete(np_key);
+
+ result = Swig_typemap_lookup(method, n, "", 0);
+ }
+
+ if (!result) {
+ return 0;
+ }
+
+ // Check if the passed node actually has type information attached. This
+ // is not the case e.g. in constructorWrapper.
+ SwigType *type = Getattr(n, "type");
+ if (type) {
+ String *np_key = NewStringf("tmap:%s:nativepointer", method);
+ String *np_value = Getattr(n, np_key);
+ Delete(np_key);
+ String *dtype;
+ if (np_value && (dtype = getPrimitiveDptype(n, type))) {
+ // If the typemap in question has a »nativepointer« attribute and we
+ // are dealing with a primitive type, use it instead.
+ result = Copy(np_value);
+ Replaceall(result, "$dtype", dtype);
+ }
+
+ replaceClassname(result, type);
+ }
+
+ return result;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceClassname()
+ *
+ * Replaces the special variable $dclassname with the proxy class name for
+ * classes/structs/unions SWIG knows about. Also substitutes the enumeration
+ * name for non-anonymous enums. Otherwise, $classname is replaced with a
+ * $descriptor(type)-like name.
+ *
+ * $*dclassname and $&classname work like with descriptors (see manual section
+ * 10.4.3), they remove a prointer from respectively add a pointer to the type.
+ *
+ * Inputs:
+ * tm - String to perform the substitution at (will usually come from a
+ * typemap.
+ * pt - The type to substitute for the variables.
+ * Outputs:
+ * tm - String with the variables substituted.
+ * Return:
+ * substitution_performed - flag indicating if a substitution was performed
+ * --------------------------------------------------------------------------- */
+ bool replaceClassname(String *tm, SwigType *pt) {
+ bool substitution_performed = false;
+ SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
+ SwigType *strippedtype = SwigType_strip_qualifiers(type);
+
+ if (Strstr(tm, "$dclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ replaceClassnameVariable(tm, "$dclassname", classnametype);
+ substitution_performed = true;
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$*dclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ Delete(SwigType_pop(classnametype));
+ replaceClassnameVariable(tm, "$*dclassname", classnametype);
+ substitution_performed = true;
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$&dclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ SwigType_add_pointer(classnametype);
+ replaceClassnameVariable(tm, "$&dclassname", classnametype);
+ substitution_performed = true;
+ Delete(classnametype);
+ }
+
+ Delete(strippedtype);
+ Delete(type);
+
+ return substitution_performed;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceClassnameVariable()
+ *
+ * See D::replaceClassname().
+ * --------------------------------------------------------------------------- */
+ void replaceClassnameVariable(String *target, const char *variable, SwigType *type) {
+ // TODO: Fix const-correctness of methods called in here and make type const.
+
+ // We make use of the fact that this function is called at least once for
+ // every type encountered which is written to a separate file, which allows
+ // us to handle imports here.
+ // When working in split proxy module mode, each generated proxy class/enum
+ // is written to a separate module. This requires us to add a corresponding
+ // import when a type is used in another generated module. If we are not
+ // working in split proxy module mode, this is not relevant and the
+ // generated module name is discarded.
+ String *type_name;
+
+ if (SwigType_isenum(type)) {
+ // RESEARCH: Make sure that we really cannot get here for anonymous enums.
+ Node *n = enumLookup(type);
+ if (n) {
+ String *enum_name = Getattr(n, "sym:name");
+
+ Node *p = parentNode(n);
+ if (p && !Strcmp(nodeType(p), "class")) {
+ // This is a nested enum.
+ String *parent_name = Getattr(p, "sym:name");
+ String *nspace = Getattr(p, "sym:nspace");
+
+ // An enum nested in a class is not written to a separate module (this
+ // would not even be possible in D), so just import the parent.
+ requireDType(nspace, parent_name);
+
+ String *module = createModuleName(nspace, parent_name);
+ if (inProxyModule(module)) {
+ type_name = NewStringf("%s.%s", parent_name, enum_name);
+ } else {
+ type_name = NewStringf("%s%s.%s.%s", package, module, parent_name, enum_name);
+ }
+ } else {
+ // A non-nested enum is written to a separate module, import it.
+ String *nspace = Getattr(n, "sym:nspace");
+ requireDType(nspace, enum_name);
+
+ String *module = createModuleName(nspace, enum_name);
+ if (inProxyModule(module)) {
+ type_name = Copy(enum_name);
+ } else {
+ type_name = NewStringf("%s%s.%s", package, module, enum_name);
+ }
+ }
+ } else {
+ type_name = NewStringf("int");
+ }
+ } else {
+ Node *n = classLookup(type);
+ if (n) {
+ String *class_name = Getattr(n, "sym:name");
+ String *nspace = Getattr(n, "sym:nspace");
+ requireDType(nspace, class_name);
+
+ String *module = createModuleName(nspace, class_name);
+ if (inProxyModule(module)) {
+ type_name = Copy(class_name);
+ } else {
+ type_name = NewStringf("%s%s.%s", package, module, class_name);
+ }
+ Delete(module);
+ } else {
+ // SWIG does not know anything about the type (after resolving typedefs).
+ // Just mangle the type name string like $descriptor(type) would do.
+ String *descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(type));
+ requireDType(NULL, descriptor);
+
+ String *module = createModuleName(NULL, descriptor);
+ if (inProxyModule(module)) {
+ type_name = Copy(descriptor);
+ } else {
+ type_name = NewStringf("%s%s.%s", package, module, descriptor);
+ }
+ Delete(module);
+
+ // Add to hash table so that a type wrapper class can be created later.
+ Setattr(unknown_types, descriptor, type);
+
+ Delete(descriptor);
+ }
+ }
+
+ Replaceall(target, variable, type_name);
+ Delete(type_name);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::createModuleName()
+ *
+ * Returns a string holding the name of the module to import to bring the
+ * given type in scope.
+ * --------------------------------------------------------------------------- */
+ String *createModuleName(const String *nspace, const String *type_name) const {
+ String *module;
+ if (nspace) {
+ module = NewStringf("%s.", nspace);
+ if (split_proxy_dmodule) {
+ Printv(module, type_name, NIL);
+ } else {
+ String *inner = createLastNamespaceName(nspace);
+ Printv(module, inner, NIL);
+ Delete(inner);
+ }
+ } else {
+ if (split_proxy_dmodule) {
+ module = Copy(type_name);
+ } else {
+ module = Copy(proxy_dmodule_name);
+ }
+ }
+ return module;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceModuleVariables()
+ *
+ * Replaces the $imdmodule and $module variables with their values in the
+ * target string.
+ * --------------------------------------------------------------------------- */
+ void replaceModuleVariables(String *target) const {
+ Replaceall(target, "$imdmodule", im_dmodule_fq_name);
+ Replaceall(target, "$module", proxy_dmodule_name);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceExcode()
+ *
+ * If a C++ method can throw a exception, additional code is added to the
+ * proxy method to check if an exception is pending so that it can be
+ * rethrown on the D side.
+ *
+ * This method replaces the $excode variable with the exception handling code
+ * in the excode typemap attribute if it »canthrow« an exception.
+ * --------------------------------------------------------------------------- */
+ void replaceExcode(Node *n, String *code, const String *typemap, Node *parameter) const {
+ String *excode_attribute = NewStringf("tmap:%s:excode", typemap);
+ String *excode = Getattr(parameter, excode_attribute);
+ if (Getattr(n, "d:canthrow")) {
+ int count = Replaceall(code, "$excode", excode);
+ if (count < 1 || !excode) {
+ Swig_warning(WARN_D_EXCODE_MISSING, input_file, line_number,
+ "D exception may not be thrown – no $excode or excode attribute in '%s' typemap.\n",
+ typemap);
+ }
+ } else {
+ Replaceall(code, "$excode", "");
+ }
+ Delete(excode_attribute);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceImportTypeMacros()
+ *
+ * Replaces the $importtype(SomeDClass) macro with an import statement if it
+ * is required to get SomeDClass in scope for the currently generated proxy
+ * D module.
+ * --------------------------------------------------------------------------- */
+ void replaceImportTypeMacros(String *target) const {
+ // Code from replace_embedded_typemap.
+ char *start = 0;
+ while ((start = Strstr(target, "$importtype("))) {
+ char *end = 0;
+ char *param_start = 0;
+ char *param_end = 0;
+ int level = 0;
+ char *c = start;
+ while (*c) {
+ if (*c == '(') {
+ if (level == 0) {
+ param_start = c + 1;
+ }
+ level++;
+ }
+ if (*c == ')') {
+ level--;
+ if (level == 0) {
+ param_end = c;
+ end = c + 1;
+ break;
+ }
+ }
+ c++;
+ }
+
+ if (end) {
+ String *current_macro = NewStringWithSize(start, (int)(end - start));
+ String *current_param = NewStringWithSize(param_start, (int)(param_end - param_start));
+
+
+ if (inProxyModule(current_param)) {
+ Replace(target, current_macro, "", DOH_REPLACE_ANY);
+ } else {
+ String *import = createImportStatement(current_param, false);
+ Replace(target, current_macro, import, DOH_REPLACE_ANY);
+ Delete(import);
+ }
+
+ Delete(current_param);
+ Delete(current_macro);
+ } else {
+ String *current_macro = NewStringWithSize(start, (int)(c - start));
+ Swig_error(Getfile(target), Getline(target), "Syntax error in: %s\n", current_macro);
+ Replace(target, current_macro, "<error in $importtype macro>", DOH_REPLACE_ANY);
+ Delete(current_macro);
+ }
+ }
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::getOverloadedName()
+ * --------------------------------------------------------------------------- */
+ String *getOverloadedName(Node *n) const {
+ // A void* parameter is used for all wrapped classes in the wrapper code.
+ // Thus, the wrapper function names for overloaded functions are postfixed
+ // with a counter string to make them unique.
+ String *overloaded_name = Copy(Getattr(n, "sym:name"));
+
+ if (Getattr(n, "sym:overloaded")) {
+ Append(overloaded_name, Getattr(n, "sym:overname"));
+ }
+
+ return overloaded_name;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::createProxyName()
+ *
+ * Returns the D class name if a type corresponds to something wrapped with a
+ * proxy class, NULL otherwise.
+ * --------------------------------------------------------------------------- */
+ String *createProxyName(SwigType *t) {
+ String *proxyname = NULL;
+ Node *n = classLookup(t);
+ if (n) {
+ String *nspace = Getattr(n, "sym:nspace");
+ String *symname = Getattr(n, "sym:name");
+
+ String *module = createModuleName(nspace, symname);
+ if (inProxyModule(module)) {
+ proxyname = Copy(symname);
+ } else {
+ proxyname = NewStringf("%s%s.%s", package, module, symname);
+ }
+ }
+ return proxyname;
+ }
+
+ String *makeParameterName(Node *n, Parm *p, int arg_num, bool setter) const {
+ String *arg = Language::makeParameterName(n, p, arg_num, setter);
+
+ if (split_proxy_dmodule && Strncmp(arg, package, Len(arg)) == 0) {
+ // If we are in split proxy mode and the argument is named like the target
+ // package, we append an underscore to its name to avoid clashes.
+ Append(arg, "_");
+ }
+
+ return arg;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::canThrow()
+ *
+ * Determines whether the code in the typemap can throw a D exception.
+ * If so, note it for later when excodeSubstitute() is called.
+ * --------------------------------------------------------------------------- */
+ void canThrow(Node *n, const String *typemap, Node *parameter) const {
+ String *canthrow_attribute = NewStringf("tmap:%s:canthrow", typemap);
+ String *canthrow = Getattr(parameter, canthrow_attribute);
+ if (canthrow)
+ Setattr(n, "d:canthrow", "1");
+ Delete(canthrow_attribute);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::wrapMemberFunctionAsDConst()
+ *
+ * Determines whether the member function represented by the passed node is
+ * wrapped as D »const« or not.
+ * --------------------------------------------------------------------------- */
+ bool wrapMemberFunctionAsDConst(Node *n) const {
+ if (d_version == 1) return false;
+ if (static_flag) return false; // Never emit »const« for static member functions.
+ return GetFlag(n, "memberget") || SwigType_isconst(Getattr(n, "decl"));
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::areAllOverloadsOverridden()
+ *
+ * Determines whether the class the passed function node belongs to overrides
+ * all the overlaods for the passed function node defined somewhere up the
+ * inheritance hierarchy.
+ * --------------------------------------------------------------------------- */
+ bool areAllOverloadsOverridden(Node *n) const {
+ List *base_list = Getattr(parentNode(n), "bases");
+ if (!base_list) {
+ // If the class which contains n is not derived from any other class,
+ // there cannot be any not-overridden overloads.
+ return true;
+ }
+
+ // In case of multiple base classes, skip to the one which has not been
+ // ignored.
+ // RESEARCH: Also emit a warning in case of multiple inheritance here?
+ Iterator it = First(base_list);
+ while (it.item && GetFlag(it.item, "feature:ignore")) {
+ it = Next(it);
+ }
+ Node *base_class = it.item;
+
+ if (!base_class) {
+ // If all base classes have been ignored, there cannot be one either.
+ return true;
+ }
+
+ // We try to find at least a single overload which exists in the base class
+ // so we can progress up the inheritance hierarchy even if there have been
+ // new overloads introduced after the topmost class.
+ Node *base_function = NULL;
+ String *symname = Getattr(n, "sym:name");
+ if (symname) {
+ for (Node *tmp = firstChild(base_class); tmp; tmp = nextSibling(tmp)) {
+ String *child_symname = Getattr(tmp, "sym:name");
+ if (child_symname && (Strcmp(child_symname, symname) == 0)) {
+ base_function = tmp;
+ break;
+ }
+ }
+ }
+
+ if (!base_function) {
+ // If there is no overload which also exists in the super class, there
+ // cannot be any base class overloads not overridden.
+ return true;
+ }
+
+ size_t base_overload_count = 0;
+ for (Node *tmp = firstSibling(base_function); tmp; tmp = Getattr(tmp, "sym:nextSibling")) {
+ if (is_protected(base_function) &&
+ !(Swig_director_mode() && Swig_director_protected_mode() && Swig_all_protected_mode())) {
+ // If the base class function is »protected« and were are not in
+ // director mode, it is not emitted to the base class and thus we do
+ // not count it. Otherwise, we would run into issues if the visibility
+ // of some functions was changed from protected to public in a child
+ // class with the using directive.
+ continue;
+ }
+ ++base_overload_count;
+ }
+
+ return ((base_overload_count <= overridingOverloadCount(n)) &&
+ areAllOverloadsOverridden(base_function));
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::overridingOverloadCount()
+ *
+ * Given a member function node, this function counts how many of the
+ * overloads of the function (including itself) override a function in the
+ * base class.
+ * --------------------------------------------------------------------------- */
+ size_t overridingOverloadCount(Node *n) const {
+ size_t result = 0;
+
+ Node *tmp = firstSibling(n);
+ do {
+ // KLUDGE: We also have to count the function if the access attribute is
+ // not present, since this means that it has been promoted into another
+ // protection level in the base class with the C++ »using« directive, and
+ // is thus taken into account when counting the base class overloads, even
+ // if it is not marked as »override« by the SWIG parser.
+ if (Getattr(n, "override") || !Getattr(n, "access")) {
+ ++result;
+ }
+ } while((tmp = Getattr(tmp, "sym:nextSibling")));
+
+ return result;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::firstSibling()
+ *
+ * Returns the first sibling of the passed node.
+ * --------------------------------------------------------------------------- */
+ Node *firstSibling(Node *n) const {
+ Node *result = n;
+ while (Node *tmp = Getattr(result, "sym:previousSibling")) {
+ result = tmp;
+ }
+ return result;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::indentCode()
+ *
+ * Helper function to indent a code (string) by one level.
+ * --------------------------------------------------------------------------- */
+ void indentCode(String* code) const {
+ Replaceall(code, "\n", "\n ");
+ Replaceall(code, " \n", "\n");
+ Chop(code);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::emitBanner()
+ * --------------------------------------------------------------------------- */
+ void emitBanner(File *f) const {
+ Printf(f, "/* ----------------------------------------------------------------------------\n");
+ Swig_banner_target_lang(f, " *");
+ Printf(f, " * ----------------------------------------------------------------------------- */\n\n");
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::outputDirectory()
+ *
+ * Returns the directory to write the D modules for the given namespace to and
+ * and creates the subdirectory if it doesn't exist.
+ * --------------------------------------------------------------------------- */
+ String *outputDirectory(String *nspace) {
+ String *output_directory = Copy(dmodule_directory);
+ if (nspace) {
+ String *nspace_subdirectory = Copy(nspace);
+ Replaceall(nspace_subdirectory, ".", SWIG_FILE_DELIMITER);
+ String *newdir_error = Swig_new_subdirectory(output_directory, nspace_subdirectory);
+ if (newdir_error) {
+ Printf(stderr, "%s\n", newdir_error);
+ Delete(newdir_error);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Printv(output_directory, nspace_subdirectory, SWIG_FILE_DELIMITER, 0);
+ Delete(nspace_subdirectory);
+ }
+ return output_directory;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::proxyCodeBuffer()
+ *
+ * Returns the buffer to write proxy code for the given namespace to.
+ * --------------------------------------------------------------------------- */
+ String *proxyCodeBuffer(String *nspace) {
+ if (!nspace) {
+ return proxy_dmodule_code;
+ }
+
+ Hash *hash = Getattr(nspace_proxy_dmodules, nspace);
+ if (!hash) {
+ hash = NewHash();
+ Setattr(hash, "code", NewString(""));
+ Setattr(hash, "imports", NewString(""));
+ Setattr(nspace_proxy_dmodules, nspace, hash);
+ }
+ return Getattr(hash, "code");
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::proxyCodeBuffer()
+ *
+ * Returns the buffer to write imports for the proxy code for the given
+ * namespace to.
+ * --------------------------------------------------------------------------- */
+ String *proxyImportsBuffer(String *nspace) {
+ if (!nspace) {
+ return proxy_dmodule_imports;
+ }
+
+ Hash *hash = Getattr(nspace_proxy_dmodules, nspace);
+ if (!hash) {
+ hash = NewHash();
+ Setattr(hash, "code", NewString(""));
+ Setattr(hash, "imports", NewString(""));
+ Setattr(nspace_proxy_dmodules, nspace, hash);
+ }
+ return Getattr(hash, "imports");
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::createFirstNamespaceName()
+ *
+ * Returns a new string containing the name of the outermost namespace, e.g.
+ * »A« for the argument »A.B.C«.
+ * --------------------------------------------------------------------------- */
+ String *createFirstNamespaceName(const String *nspace) const {
+ char *tmp = Char(nspace);
+ char *c = tmp;
+ char *co = 0;
+ if (!strstr(c, "."))
+ return 0;
+
+ co = c + Len(nspace);
+
+ while (*c && (c != co)) {
+ if (*c == '.') {
+ break;
+ }
+ c++;
+ }
+ if (!*c || (c == tmp)) {
+ return NULL;
+ }
+ return NewStringWithSize(tmp, (int)(c - tmp));
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::createLastNamespaceName()
+ *
+ * Returns a new string containing the name of the innermost namespace, e.g.
+ * »C« for the argument »A.B.C«.
+ * --------------------------------------------------------------------------- */
+ String *createLastNamespaceName(const String *nspace) const {
+ if (!nspace) return NULL;
+ char *c = Char(nspace);
+ char *cc = c;
+ if (!strstr(c, "."))
+ return NewString(nspace);
+
+ while (*c) {
+ if (*c == '.') {
+ cc = c;
+ }
+ ++c;
+ }
+ return NewString(cc + 1);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::createOuterNamespaceNames()
+ *
+ * Returns a new string containing the name of the outer namespace, e.g.
+ * »A.B« for the argument »A.B.C«.
+ * --------------------------------------------------------------------------- */
+ String *createOuterNamespaceNames(const String *nspace) const {
+ if (!nspace) return NULL;
+ char *tmp = Char(nspace);
+ char *c = tmp;
+ char *cc = c;
+ if (!strstr(c, "."))
+ return NULL;
+
+ while (*c) {
+ if (*c == '.') {
+ cc = c;
+ }
+ ++c;
+ }
+ if (cc == tmp) {
+ return NULL;
+ }
+ return NewStringWithSize(tmp, (int)(cc - tmp));
+ }
+};
+
+static Language *new_swig_d() {
+ return new D();
+}
+
+/* -----------------------------------------------------------------------------
+ * swig_d() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+extern "C" Language *swig_d(void) {
+ return new_swig_d();
+}
+
+/* -----------------------------------------------------------------------------
+ * Usage information displayed at the command line.
+ * ----------------------------------------------------------------------------- */
+const char *D::usage = "\
+D Options (available with -d)\n\
+ -d2 - Generate code for D2/Phobos (default: D1/Tango)\n\
+ -package <pkg> - Write generated D modules into package <pkg>\n\
+ -splitproxy - Write each D type to a dedicated file instead of\n\
+ generating a single proxy D module.\n\
+ -wrapperlibrary <wl> - Set the name of the wrapper library to <wl>\n\
+\n";
diff --git a/contrib/tools/swig/Source/Modules/directors.cxx b/contrib/tools/swig/Source/Modules/directors.cxx
new file mode 100644
index 00000000000..a91d5fd9a32
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/directors.cxx
@@ -0,0 +1,241 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * directors.cxx
+ *
+ * Director support functions.
+ * Not all of these may be necessary, and some may duplicate existing functionality
+ * in SWIG. --MR
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+
+/* -----------------------------------------------------------------------------
+ * Swig_csuperclass_call()
+ *
+ * Generates a fully qualified method call, including the full parameter list.
+ * e.g. "base::method(i, j)"
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_csuperclass_call(String *base, String *method, ParmList *l) {
+ String *call = NewString("");
+ int arg_idx = 0;
+ Parm *p;
+ if (base) {
+ Printf(call, "%s::", base);
+ }
+ Printf(call, "%s(", method);
+ for (p = l; p; p = nextSibling(p)) {
+ String *pname = Getattr(p, "name");
+ if (!pname && Cmp(Getattr(p, "type"), "void")) {
+ pname = NewString("");
+ Printf(pname, "arg%d", arg_idx++);
+ }
+ if (p != l)
+ Printf(call, ", ");
+ Printv(call, pname, NIL);
+ }
+ Printf(call, ")");
+ return call;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_class_declaration()
+ *
+ * Generate the start of a class/struct declaration.
+ * e.g. "class myclass"
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_class_declaration(Node *n, String *name) {
+ if (!name) {
+ name = Getattr(n, "sym:name");
+ }
+ String *result = NewString("");
+ String *kind = Getattr(n, "kind");
+ Printf(result, "%s %s", kind, name);
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_class_name()
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_class_name(Node *n) {
+ String *name;
+ name = Copy(Getattr(n, "sym:name"));
+ return name;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_director_declaration()
+ *
+ * Generate the full director class declaration, complete with base classes.
+ * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_director_declaration(Node *n) {
+ String *classname = Swig_class_name(n);
+ String *directorname = Language::instance()->directorClassName(n);
+ String *base = Getattr(n, "classtype");
+ String *declaration = Swig_class_declaration(n, directorname);
+
+ Printf(declaration, " : public %s, public Swig::Director {\n", base);
+ Delete(classname);
+ Delete(directorname);
+ return declaration;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_method_call()
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_method_call(const_String_or_char_ptr name, ParmList *parms) {
+ String *func;
+ int i = 0;
+ int comma = 0;
+ Parm *p = parms;
+ SwigType *pt;
+ String *nname;
+
+ func = NewString("");
+ nname = SwigType_namestr(name);
+ Printf(func, "%s(", nname);
+ while (p) {
+ String *pname;
+ pt = Getattr(p, "type");
+ if ((SwigType_type(pt) != T_VOID)) {
+ if (comma)
+ Printf(func, ",");
+ pname = Getattr(p, "name");
+ Printf(func, "%s", pname);
+ comma = 1;
+ i++;
+ }
+ p = nextSibling(p);
+ }
+ Printf(func, ")");
+ return func;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_method_decl()
+ *
+ * Return a stringified version of a C/C++ declaration.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_method_decl(SwigType *return_base_type, SwigType *decl, const_String_or_char_ptr id, List *args, int default_args) {
+ String *result = NewString("");
+ bool conversion_operator = Strstr(id, "operator ") != 0 && !return_base_type;
+
+ Parm *parm = args;
+ int arg_idx = 0;
+ while (parm) {
+ String *type = Getattr(parm, "type");
+ String *name = Getattr(parm, "name");
+ if (!name && Cmp(type, "void")) {
+ name = NewString("");
+ Printf(name, "arg%d", arg_idx++);
+ Setattr(parm, "name", name);
+ }
+ parm = nextSibling(parm);
+ }
+
+ String *rettype = Copy(decl);
+ String *quals = SwigType_pop_function_qualifiers(rettype);
+ String *qualifiers = 0;
+ if (quals)
+ qualifiers = SwigType_str(quals, 0);
+
+ String *popped_decl = SwigType_pop_function(rettype);
+ if (return_base_type)
+ Append(rettype, return_base_type);
+
+ if (!conversion_operator) {
+ SwigType *rettype_stripped = SwigType_strip_qualifiers(rettype);
+ String *rtype = SwigType_str(rettype, 0);
+ Append(result, rtype);
+ if (SwigType_issimple(rettype_stripped) && return_base_type)
+ Append(result, " ");
+ Delete(rtype);
+ Delete(rettype_stripped);
+ }
+
+ if (id)
+ Append(result, id);
+
+ String *args_string = default_args ? ParmList_str_defaultargs(args) : ParmList_str(args);
+ Printv(result, "(", args_string, ")", NIL);
+
+ if (qualifiers)
+ Printv(result, " ", qualifiers, NIL);
+
+ // Reformat result to how it has been historically
+ Replaceall(result, ",", ", ");
+ Replaceall(result, "=", " = ");
+
+ Delete(args_string);
+ Delete(popped_decl);
+ Delete(qualifiers);
+ Delete(quals);
+ Delete(rettype);
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_director_emit_dynamic_cast()
+ *
+ * In order to call protected virtual director methods from the target language, we need
+ * to add an extra dynamic_cast to call the public C++ wrapper in the director class.
+ * Also for non-static protected members when the allprotected option is on.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f) {
+ // TODO: why is the storage element removed in staticmemberfunctionHandler ??
+ if ((!is_public(n) && (is_member_director(n) || GetFlag(n, "explicitcall"))) ||
+ (is_non_virtual_protected_access(n) && !(Swig_storage_isstatic_custom(n, "staticmemberfunctionHandler:storage") ||
+ Swig_storage_isstatic(n))
+ && !Equal(nodeType(n), "constructor"))) {
+ Node *parent = Getattr(n, "parentNode");
+ String *dirname;
+ String *dirdecl;
+ dirname = Language::instance()->directorClassName(parent);
+ dirdecl = NewStringf("%s *darg = 0", dirname);
+ Wrapper_add_local(f, "darg", dirdecl);
+ Printf(f->code, "darg = dynamic_cast<%s *>(arg1);\n", dirname);
+ Delete(dirname);
+ Delete(dirdecl);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_director_parms_fixup()
+ *
+ * For each parameter in the C++ member function, copy the parameter name
+ * to its "lname"; this ensures that Swig_typemap_attach_parms() will do
+ * the right thing when it sees strings like "$1" in "directorin" typemaps.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_director_parms_fixup(ParmList *parms) {
+ Parm *p;
+ int i;
+ for (i = 0, p = parms; p; p = nextSibling(p), ++i) {
+ String *arg = Getattr(p, "name");
+ String *lname = 0;
+
+ if (!arg && !Equal(Getattr(p, "type"), "void")) {
+ lname = NewStringf("arg%d", i);
+ Setattr(p, "name", lname);
+ } else
+ lname = Copy(arg);
+
+ Setattr(p, "lname", lname);
+ Delete(lname);
+ }
+}
+
diff --git a/contrib/tools/swig/Source/Modules/emit.cxx b/contrib/tools/swig/Source/Modules/emit.cxx
new file mode 100644
index 00000000000..7a4c2dcfb12
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/emit.cxx
@@ -0,0 +1,559 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * emit.cxx
+ *
+ * Useful functions for emitting various pieces of code.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+
+/* -----------------------------------------------------------------------------
+ * emit_return_variable()
+ *
+ * Emits a variable declaration for a function return value.
+ * The variable name is always called result.
+ * n => Node of the method being wrapped
+ * rt => the return type
+ * f => the wrapper to generate code into
+ * ----------------------------------------------------------------------------- */
+
+void emit_return_variable(Node *n, SwigType *rt, Wrapper *f) {
+
+ if (!GetFlag(n, "tmap:out:optimal")) {
+ if (rt && (SwigType_type(rt) != T_VOID)) {
+ SwigType *vt = cplus_value_type(rt);
+ SwigType *tt = vt ? vt : rt;
+ SwigType *lt = SwigType_ltype(tt);
+ String *lstr = SwigType_str(lt, Swig_cresult_name());
+ if (SwigType_ispointer(lt)) {
+ Wrapper_add_localv(f, Swig_cresult_name(), lstr, "= 0", NULL);
+ } else {
+ Wrapper_add_local(f, Swig_cresult_name(), lstr);
+ }
+ if (vt) {
+ Delete(vt);
+ }
+ Delete(lt);
+ Delete(lstr);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * emit_parameter_variables()
+ *
+ * Emits a list of variable declarations for function parameters.
+ * The variable names are always called arg1, arg2, etc...
+ * l => the parameter list
+ * f => the wrapper to generate code into
+ * ----------------------------------------------------------------------------- */
+
+void emit_parameter_variables(ParmList *l, Wrapper *f) {
+
+ Parm *p;
+ String *tm;
+
+ /* Emit function arguments */
+ Swig_cargs(f, l);
+
+ /* Attach typemaps to parameters */
+ /* Swig_typemap_attach_parms("ignore",l,f); */
+
+ Swig_typemap_attach_parms("default", l, f);
+ Swig_typemap_attach_parms("arginit", l, f);
+
+ /* Apply the arginit and default */
+ p = l;
+ while (p) {
+ tm = Getattr(p, "tmap:arginit");
+ if (tm) {
+ Replace(tm, "$target", Getattr(p, "lname"), DOH_REPLACE_ANY);
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:arginit:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Apply the default typemap */
+ p = l;
+ while (p) {
+ tm = Getattr(p, "tmap:default");
+ if (tm) {
+ Replace(tm, "$target", Getattr(p, "lname"), DOH_REPLACE_ANY);
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:default:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * emit_attach_parmmaps()
+ *
+ * Attach the standard parameter related typemaps.
+ * ----------------------------------------------------------------------------- */
+
+void emit_attach_parmmaps(ParmList *l, Wrapper *f) {
+ Swig_typemap_attach_parms("in", l, f);
+ Swig_typemap_attach_parms("typecheck", l, 0);
+ Swig_typemap_attach_parms("argout", l, f);
+ Swig_typemap_attach_parms("check", l, f);
+ Swig_typemap_attach_parms("freearg", l, f);
+
+ {
+ /* This is compatibility code to deal with the deprecated "ignore" typemap */
+ Parm *p = l;
+ Parm *np;
+ while (p) {
+ String *tm = Getattr(p, "tmap:in");
+ if (tm && checkAttribute(p, "tmap:in:numinputs", "0")) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Printv(f->code, tm, "\n", NIL);
+ np = Getattr(p, "tmap:in:next");
+ while (p && (p != np)) {
+ /* Setattr(p,"ignore","1"); Deprecate */
+ p = nextSibling(p);
+ }
+ } else if (tm) {
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ /* Perform a sanity check on "in" and "freearg" typemaps. These
+ must exactly match to avoid chaos. If a mismatch occurs, we
+ nuke the freearg typemap */
+ {
+ Parm *p = l;
+ Parm *npin, *npfreearg;
+ while (p) {
+ npin = Getattr(p, "tmap:in:next");
+
+ /*
+ if (Getattr(p,"tmap:ignore")) {
+ npin = Getattr(p,"tmap:ignore:next");
+ } else if (Getattr(p,"tmap:in")) {
+ npin = Getattr(p,"tmap:in:next");
+ }
+ */
+
+ if (Getattr(p, "tmap:freearg")) {
+ npfreearg = Getattr(p, "tmap:freearg:next");
+ if (npin != npfreearg) {
+ while (p != npin) {
+ Delattr(p, "tmap:freearg");
+ Delattr(p, "tmap:freearg:next");
+ p = nextSibling(p);
+ }
+ }
+ }
+ p = npin;
+ }
+ }
+
+ /* Check for variable length arguments with no input typemap.
+ If no input is defined, we set this to ignore and print a
+ message.
+ */
+ {
+ Parm *p = l;
+ Parm *lp = 0;
+ while (p) {
+ if (!checkAttribute(p, "tmap:in:numinputs", "0")) {
+ lp = p;
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+ if (SwigType_isvarargs(Getattr(p, "type"))) {
+ Swig_warning(WARN_LANG_VARARGS, input_file, line_number, "Variable length arguments discarded.\n");
+ Setattr(p, "tmap:in", "");
+ }
+ lp = 0;
+ p = nextSibling(p);
+ }
+
+ /* Check if last input argument is variable length argument */
+ if (lp) {
+ p = lp;
+ while (p) {
+ if (SwigType_isvarargs(Getattr(p, "type"))) {
+ // Mark the head of the ParmList that it has varargs
+ Setattr(l, "emit:varargs", lp);
+//Printf(stdout, "setting emit:varargs %s ... %s +++ %s\n", Getattr(l, "emit:varargs"), Getattr(l, "type"), Getattr(p, "type"));
+ break;
+ }
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ /*
+ * An equivalent type can be used in the typecheck typemap for SWIG to detect the overloading of equivalent
+ * target language types. This is primarily for the smartptr feature, where a pointer and a smart pointer
+ * are seen as equivalent types in the target language.
+ */
+ {
+ Parm *p = l;
+ while (p) {
+ String *tm = Getattr(p, "tmap:typecheck");
+ if (tm) {
+ String *equivalent = Getattr(p, "tmap:typecheck:equivalent");
+ if (equivalent) {
+ String *precedence = Getattr(p, "tmap:typecheck:precedence");
+ if (precedence && Strcmp(precedence, "0") != 0)
+ Swig_error(Getfile(tm), Getline(tm), "The 'typecheck' typemap for %s contains an 'equivalent' attribute for a 'precedence' that is not set to SWIG_TYPECHECK_POINTER or 0.\n", SwigType_str(Getattr(p, "type"), 0));
+ SwigType *cpt = Swig_cparse_type(equivalent);
+ if (cpt) {
+ Setattr(p, "equivtype", cpt);
+ Delete(cpt);
+ } else {
+ Swig_error(Getfile(tm), Getline(tm), "Invalid type (%s) in 'equivalent' attribute in 'typecheck' typemap for type %s.\n", equivalent, SwigType_str(Getattr(p, "type"), 0));
+ }
+ }
+ p = Getattr(p, "tmap:typecheck:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * emit_num_arguments()
+ *
+ * Calculate the total number of arguments. This function is safe for use
+ * with multi-argument typemaps which may change the number of arguments in
+ * strange ways.
+ * ----------------------------------------------------------------------------- */
+
+int emit_num_arguments(ParmList *parms) {
+ Parm *p = parms;
+ int nargs = 0;
+
+ while (p) {
+ if (Getattr(p, "tmap:in")) {
+ nargs += GetInt(p, "tmap:in:numinputs");
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* DB 04/02/2003: Not sure this is necessary with tmap:in:numinputs */
+ /*
+ if (parms && (p = Getattr(parms,"emit:varargs"))) {
+ if (!nextSibling(p)) {
+ nargs--;
+ }
+ }
+ */
+ return nargs;
+}
+
+/* -----------------------------------------------------------------------------
+ * emit_num_required()
+ *
+ * Computes the number of required arguments. This function is safe for
+ * use with multi-argument typemaps and knows how to skip over everything
+ * properly. Note that parameters with default values are counted unless
+ * the compact default args option is on.
+ * ----------------------------------------------------------------------------- */
+
+int emit_num_required(ParmList *parms) {
+ Parm *p = parms;
+ int nargs = 0;
+ Parm *first_default_arg = 0;
+ int compactdefargs = ParmList_is_compactdefargs(p);
+
+ while (p) {
+ if (Getattr(p, "tmap:in") && checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ if (Getattr(p, "tmap:default"))
+ break;
+ if (Getattr(p, "value")) {
+ if (!first_default_arg)
+ first_default_arg = p;
+ if (compactdefargs)
+ break;
+ }
+ nargs += GetInt(p, "tmap:in:numinputs");
+ if (Getattr(p, "tmap:in")) {
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ /* Print error message for non-default arguments following default arguments */
+ /* The error message is printed more than once with most language modules, this ought to be fixed */
+ if (first_default_arg) {
+ p = first_default_arg;
+ while (p) {
+ if (Getattr(p, "tmap:in") && checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ if (!Getattr(p, "value") && (!Getattr(p, "tmap:default"))) {
+ Swig_error(Getfile(p), Getline(p), "Non-optional argument '%s' follows an optional argument.\n", Getattr(p, "name"));
+ }
+ if (Getattr(p, "tmap:in")) {
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+ }
+
+ /* DB 04/02/2003: Not sure this is necessary with tmap:in:numinputs */
+ /*
+ if (parms && (p = Getattr(parms,"emit:varargs"))) {
+ if (!nextSibling(p)) {
+ nargs--;
+ }
+ }
+ */
+ return nargs;
+}
+
+/* -----------------------------------------------------------------------------
+ * emit_isvarargs()
+ *
+ * Checks if a ParmList is a parameter list containing varargs.
+ * This function requires emit_attach_parmmaps to have been called beforehand.
+ * ----------------------------------------------------------------------------- */
+
+int emit_isvarargs(ParmList *p) {
+ if (!p)
+ return 0;
+ if (Getattr(p, "emit:varargs"))
+ return 1;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * emit_isvarargs_function()
+ *
+ * Checks for varargs in a function/constructor (can be overloaded)
+ * ----------------------------------------------------------------------------- */
+
+bool emit_isvarargs_function(Node *n) {
+ bool has_varargs = false;
+ Node *over = Getattr(n, "sym:overloaded");
+ if (over) {
+ for (Node *sibling = over; sibling; sibling = Getattr(sibling, "sym:nextSibling")) {
+ if (ParmList_has_varargs(Getattr(sibling, "parms"))) {
+ has_varargs = true;
+ break;
+ }
+ }
+ } else {
+ has_varargs = ParmList_has_varargs(Getattr(n, "parms")) ? true : false;
+ }
+ return has_varargs;
+}
+
+/* -----------------------------------------------------------------------------
+ * void emit_mark_vararg_parms()
+ *
+ * Marks the vararg parameters which are to be ignored.
+ * Vararg parameters are marked as ignored if there is no 'in' varargs (...)
+ * typemap.
+ * ----------------------------------------------------------------------------- */
+
+void emit_mark_varargs(ParmList *l) {
+ Parm *p = l;
+ while (p) {
+ if (SwigType_isvarargs(Getattr(p, "type")))
+ if (!Getattr(p, "tmap:in"))
+ Setattr(p, "varargs:ignore", "1");
+ p = nextSibling(p);
+ }
+}
+
+#if 0
+/* replace_contract_args. This function replaces argument names in contract
+ specifications. Used in conjunction with the %contract directive. */
+
+static void replace_contract_args(Parm *cp, Parm *rp, String *s) {
+ while (cp && rp) {
+ String *n = Getattr(cp, "name");
+ if (n) {
+ Replace(s, n, Getattr(rp, "lname"), DOH_REPLACE_ID);
+ }
+ cp = nextSibling(cp);
+ rp = nextSibling(rp);
+ }
+}
+#endif
+
+/* -----------------------------------------------------------------------------
+ * int emit_action_code()
+ *
+ * Emits action code for a wrapper. Adds in exception handling code (%exception).
+ * eaction -> the action code to emit
+ * wrappercode -> the emitted code (output)
+ * ----------------------------------------------------------------------------- */
+int emit_action_code(Node *n, String *wrappercode, String *eaction) {
+ assert(Getattr(n, "wrap:name"));
+
+ /* Look for except feature (%exception) */
+ String *tm = GetFlagAttr(n, "feature:except");
+ if (tm)
+ tm = Copy(tm);
+ if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
+ if (Strstr(tm, "$")) {
+ Swig_replace_special_variables(n, parentNode(n), tm);
+ Replaceall(tm, "$function", eaction); // deprecated
+ Replaceall(tm, "$action", eaction);
+ }
+ Printv(wrappercode, tm, "\n", NIL);
+ Delete(tm);
+ return 1;
+ } else {
+ Printv(wrappercode, eaction, "\n", NIL);
+ return 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * int emit_action()
+ *
+ * Emits the call to the wrapped function.
+ * Adds in exception specification exception handling and %exception code.
+ * ----------------------------------------------------------------------------- */
+String *emit_action(Node *n) {
+ String *actioncode = NewStringEmpty();
+ String *tm;
+ String *action;
+ String *wrap;
+ ParmList *catchlist = Getattr(n, "catchlist");
+
+ /* Look for fragments */
+ {
+ String *fragment = Getattr(n, "feature:fragment");
+ if (fragment) {
+ char *c, *tok;
+ String *t = Copy(fragment);
+ c = Char(t);
+ tok = strtok(c, ",");
+ while (tok) {
+ String *fname = NewString(tok);
+ Setfile(fname, Getfile(n));
+ Setline(fname, Getline(n));
+ Swig_fragment_emit(fname);
+ Delete(fname);
+ tok = strtok(NULL, ",");
+ }
+ Delete(t);
+ }
+ }
+
+ /* Emit wrapper code (if any) */
+ wrap = Getattr(n, "wrap:code");
+ if (wrap && Swig_filebyname("header") != Getattr(n, "wrap:code:done")) {
+ File *f_code = Swig_filebyname("header");
+ if (f_code) {
+ Printv(f_code, wrap, NIL);
+ }
+ Setattr(n, "wrap:code:done", f_code);
+ }
+
+ action = Getattr(n, "feature:action");
+ if (!action)
+ action = Getattr(n, "wrap:action");
+ assert(action != 0);
+
+ /* Emit contract code (if any) */
+ if (Swig_contract_mode_get()) {
+ /* Preassertion */
+ tm = Getattr(n, "contract:preassert");
+ if (Len(tm)) {
+ Printv(actioncode, tm, "\n", NIL);
+ }
+ }
+ /* Exception handling code */
+
+ /* saves action -> eaction for postcatching exception */
+ String *eaction = NewString("");
+
+ /* If we are in C++ mode and there is an exception specification. We're going to
+ enclose the block in a try block */
+ if (catchlist) {
+ Printf(eaction, "try {\n");
+ }
+
+ String *preaction = Getattr(n, "wrap:preaction");
+ if (preaction)
+ Printv(eaction, preaction, NIL);
+
+ Printv(eaction, action, NIL);
+
+ String *postaction = Getattr(n, "wrap:postaction");
+ if (postaction)
+ Printv(eaction, postaction, NIL);
+
+ if (catchlist) {
+ int unknown_catch = 0;
+ int has_varargs = 0;
+ Printf(eaction, "}");
+ for (Parm *ep = catchlist; ep; ep = nextSibling(ep)) {
+ String *em = Swig_typemap_lookup("throws", ep, "_e", 0);
+ if (em) {
+ SwigType *et = Getattr(ep, "type");
+ SwigType *etr = SwigType_typedef_resolve_all(et);
+ if (SwigType_isreference(etr) || SwigType_ispointer(etr) || SwigType_isarray(etr)) {
+ Printf(eaction, " catch(%s) {", SwigType_str(et, "_e"));
+ } else if (SwigType_isvarargs(etr)) {
+ Printf(eaction, " catch(...) {");
+ has_varargs = 1;
+ } else {
+ Printf(eaction, " catch(%s) {", SwigType_str(et, "&_e"));
+ }
+ Printv(eaction, em, "\n", NIL);
+ Printf(eaction, "}");
+ } else {
+ Swig_warning(WARN_TYPEMAP_THROW, Getfile(n), Getline(n), "No 'throws' typemap defined for exception type '%s'\n", SwigType_str(Getattr(ep, "type"), 0));
+ unknown_catch = 1;
+ }
+ }
+ if (unknown_catch && !has_varargs) {
+ Printf(eaction, " catch(...) {\nthrow;\n}");
+ }
+ }
+
+ /* Look for except typemap (Deprecated) */
+ tm = Swig_typemap_lookup("except", n, Swig_cresult_name(), 0);
+ if (tm) {
+ Setattr(n, "feature:except", tm);
+ tm = 0;
+ }
+
+ /* emit the except feature code */
+ emit_action_code(n, actioncode, eaction);
+
+ Delete(eaction);
+
+ /* Emit contract code (if any) */
+ if (Swig_contract_mode_get()) {
+ /* Postassertion */
+ tm = Getattr(n, "contract:postassert");
+ if (Len(tm)) {
+ Printv(actioncode, tm, "\n", NIL);
+ }
+ }
+
+ return actioncode;
+}
diff --git a/contrib/tools/swig/Source/Modules/go.cxx b/contrib/tools/swig/Source/Modules/go.cxx
new file mode 100644
index 00000000000..0163f71df0a
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/go.cxx
@@ -0,0 +1,7010 @@
+/* -----------------------------------------------------------------------------
+ * See the LICENSE file for information on copyright, usage and redistribution
+ * of SWIG, and the README file for authors - http://www.swig.org/release.html.
+ *
+ * go.cxx
+ *
+ * Go language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+#include <ctype.h>
+
+/* ----------------------------------------------------------------------
+ * siphash()
+ *
+ * 64-bit SipHash-2-4 to generate unique id for each module
+ * ---------------------------------------------------------------------- */
+
+// An unsigned 64-bit integer that works on a 32-bit host.
+typedef struct {
+ // Assume unsigned long is at least 32 bits.
+ unsigned long hi;
+ unsigned long lo;
+} swig_uint64;
+
+// Rotate v left by bits, which must be <= 32.
+static inline void _rotl(swig_uint64 *v, int bits) {
+ assert(bits <= 32);
+ unsigned long tmp = v->hi;
+ if (bits == 32) {
+ v->hi = v->lo;
+ v->lo = tmp;
+ } else {
+ v->hi = (tmp << bits) | ((0xfffffffful & v->lo) >> (32 - bits));
+ v->lo = (v->lo << bits) | ((0xfffffffful & tmp) >> (32 - bits));
+ }
+}
+
+// dst ^= src
+static inline void _xor(swig_uint64 *dst, swig_uint64 *src) {
+ dst->lo ^= src->lo;
+ dst->hi ^= src->hi;
+}
+
+// dst += src
+static inline void _add(swig_uint64 *dst, swig_uint64 *src) {
+ dst->lo += src->lo;
+ dst->hi += src->hi + ((dst->lo & 0xfffffffful) < (src->lo&0xfffffffful) ? 1 : 0);
+}
+#define SIPROUND \
+ do { \
+ _add(&v0, &v1); _rotl(&v1, 13); _xor(&v1, &v0); _rotl(&v0, 32); \
+ _add(&v2, &v3); _rotl(&v3, 16); _xor(&v3, &v2); \
+ _add(&v0, &v3); _rotl(&v3, 21); _xor(&v3, &v0); \
+ _add(&v2, &v1); _rotl(&v1, 17); _xor(&v1, &v2); _rotl(&v2, 32); \
+ } while(0)
+
+// Set out to the hash of inc/inlen.
+static void siphash(swig_uint64 *out, const char *inc, unsigned long inlen) {
+ /* "somepseudorandomlygeneratedbytes" */
+ swig_uint64 v0 = {0x736f6d65UL, 0x70736575UL};
+ swig_uint64 v1 = {0x646f7261UL, 0x6e646f6dUL};
+ swig_uint64 v2 = {0x6c796765UL, 0x6e657261UL};
+ swig_uint64 v3 = {0x74656462UL, 0x79746573UL};
+ swig_uint64 b;
+ /* hard-coded k. */
+ swig_uint64 k0 = {0x07060504UL, 0x03020100UL};
+ swig_uint64 k1 = {0x0F0E0D0CUL, 0x0B0A0908UL};
+ int i;
+ const int cROUNDS = 2, dROUNDS = 4;
+ const unsigned char *in = (const unsigned char *)inc;
+ const unsigned char *end = in + inlen - (inlen % 8);
+ int left = inlen & 7;
+ _xor(&v3, &k1); _xor(&v2, &k0); _xor(&v1, &k1); _xor(&v0, &k0);
+ for (; in != end; in += 8) {
+ b.hi = 0; b.lo = 0;
+ for (i = 0; i < 4; i++) {
+ b.lo |= ((unsigned long)in[i]) << (8*i);
+ }
+ for (i = 0; i < 4; i++) {
+ b.hi |= ((unsigned long)in[i+4]) << (8*i);
+ }
+ _xor(&v3, &b);
+ for (i = 0; i < cROUNDS; i++) {
+ SIPROUND;
+ }
+ _xor(&v0, &b);
+ }
+ b.hi = (inlen & 0xff)<<24; b.lo = 0;
+ for (; left; left--) {
+ if (left > 4) {
+ b.hi |= ((unsigned long)in[left-1]) << (8*left-8-32);
+ } else {
+ b.lo |= ((unsigned long)in[left-1]) << (8*left-8);
+ }
+ }
+ _xor(&v3, &b);
+ for(i=0; i<cROUNDS; i++) {
+ SIPROUND;
+ }
+ _xor(&v0, &b); v2.lo ^= 0xff;
+ for(i=0; i<dROUNDS; i++) {
+ SIPROUND;
+ }
+ out->lo = 0; out->hi = 0;
+ _xor(out, &v0); _xor(out, &v1); _xor(out, &v2); _xor(out, &v3);
+}
+#undef SIPROUND
+
+class GO:public Language {
+ static const char *const usage;
+
+ // Go package name.
+ String *package;
+ // SWIG module name.
+ String *module;
+ // Flag for generating cgo input files.
+ bool cgo_flag;
+ // Flag for generating gccgo output.
+ bool gccgo_flag;
+ // Prefix to use with gccgo.
+ String *go_prefix;
+ // -fgo-prefix option.
+ String *prefix_option;
+ // -fgo-pkgpath option.
+ String *pkgpath_option;
+ // Prefix for translating %import directive to import statements.
+ String *import_prefix;
+ // Whether to use a shared library.
+ bool use_shlib;
+ // Name of shared library to import.
+ String *soname;
+ // Size in bits of the Go type "int". 0 if not specified.
+ int intgo_type_size;
+
+ /* Output files */
+ File *f_c_begin;
+ File *f_go_begin;
+ File *f_gc_begin;
+
+ /* Output fragments */
+ File *f_c_runtime;
+ File *f_c_header;
+ File *f_c_wrappers;
+ File *f_c_init;
+ File *f_c_directors;
+ File *f_c_directors_h;
+ File *f_go_imports;
+ File *f_go_runtime;
+ File *f_go_header;
+ File *f_go_wrappers;
+ File *f_go_directors;
+ File *f_gc_runtime;
+ File *f_gc_header;
+ File *f_gc_wrappers;
+ File *f_cgo_comment;
+ File *f_cgo_comment_typedefs;
+
+ // True if we imported a module.
+ bool saw_import;
+ // If not NULL, name of import package being processed.
+ String *imported_package;
+ // Build interface methods while handling a class. This is only
+ // non-NULL when we are handling methods.
+ String *interfaces;
+ // The class node while handling a class. This is only non-NULL
+ // when we are handling methods.
+ Node *class_node;
+ // The class name while handling a class. This is only non-NULL
+ // when we are handling methods. This is the name of the class as
+ // SWIG sees it.
+ String *class_name;
+ // The receiver name while handling a class. This is only non-NULL
+ // when we are handling methods. This is the name of the class
+ // as run through goCPointerType.
+ String *class_receiver;
+ // A hash table of method names that we have seen when processing a
+ // class. This lets us detect base class methods that we don't want
+ // to use.
+ Hash *class_methods;
+ // True when we are generating the wrapper functions for a variable.
+ bool making_variable_wrappers;
+ // True when working with a static member function.
+ bool is_static_member_function;
+ // A hash table of enum types that we have seen but which may not have
+ // been defined. The index is a SwigType.
+ Hash *undefined_enum_types;
+ // A hash table of types that we have seen but which may not have
+ // been defined. The index is a SwigType.
+ Hash *undefined_types;
+ // A hash table of classes which were defined. The index is a Go
+ // type name.
+ Hash *defined_types;
+ // A hash table of all the go_imports already imported. The index is a full
+ // import name e.g. '"runtime"' or '_ "runtime/cgo"' or 'sc "syscall"'.
+ Hash *go_imports;
+ // A unique ID used to make public symbols unique.
+ String *unique_id;
+
+public:
+ GO():package(NULL),
+ module(NULL),
+ cgo_flag(true),
+ gccgo_flag(false),
+ go_prefix(NULL),
+ prefix_option(NULL),
+ pkgpath_option(NULL),
+ import_prefix(NULL),
+ use_shlib(false),
+ soname(NULL),
+ intgo_type_size(0),
+ f_c_begin(NULL),
+ f_go_begin(NULL),
+ f_gc_begin(NULL),
+ f_c_runtime(NULL),
+ f_c_header(NULL),
+ f_c_wrappers(NULL),
+ f_c_init(NULL),
+ f_c_directors(NULL),
+ f_c_directors_h(NULL),
+ f_go_imports(NULL),
+ f_go_runtime(NULL),
+ f_go_header(NULL),
+ f_go_wrappers(NULL),
+ f_go_directors(NULL),
+ f_gc_runtime(NULL),
+ f_gc_header(NULL),
+ f_gc_wrappers(NULL),
+ f_cgo_comment(NULL),
+ f_cgo_comment_typedefs(NULL),
+ saw_import(false),
+ imported_package(NULL),
+ interfaces(NULL),
+ class_node(NULL),
+ class_name(NULL),
+ class_receiver(NULL),
+ class_methods(NULL),
+ making_variable_wrappers(false),
+ is_static_member_function(false),
+ undefined_enum_types(NULL),
+ undefined_types(NULL),
+ defined_types(NULL),
+ go_imports(NULL),
+ unique_id(NULL) {
+ director_multiple_inheritance = 1;
+ director_language = 1;
+ director_prot_ctor_code = NewString("_swig_gopanic(\"accessing abstract class or protected constructor\");");
+ }
+
+private:
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+ virtual void main(int argc, char *argv[]) {
+
+ SWIG_library_directory("go");
+ bool display_help = false;
+
+ // Process command line options.
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-package") == 0) {
+ if (argv[i + 1]) {
+ package = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-cgo") == 0) {
+ Swig_mark_arg(i);
+ cgo_flag = true;
+ } else if (strcmp(argv[i], "-no-cgo") == 0) {
+ Swig_mark_arg(i);
+ cgo_flag = false;
+ } else if (strcmp(argv[i], "-gccgo") == 0) {
+ Swig_mark_arg(i);
+ gccgo_flag = true;
+ } else if (strcmp(argv[i], "-go-prefix") == 0) {
+ if (argv[i + 1]) {
+ prefix_option = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-go-pkgpath") == 0) {
+ if (argv[i + 1]) {
+ pkgpath_option = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-import-prefix") == 0) {
+ if (argv[i + 1]) {
+ import_prefix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-use-shlib") == 0) {
+ Swig_mark_arg(i);
+ use_shlib = true;
+ } else if (strcmp(argv[i], "-soname") == 0) {
+ if (argv[i + 1]) {
+ soname = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-longsize") == 0) {
+ // Ignore for backward compatibility.
+ if (argv[i + 1]) {
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ ++i;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-intgosize") == 0) {
+ if (argv[i + 1]) {
+ intgo_type_size = atoi(argv[i + 1]);
+ if (intgo_type_size != 32 && intgo_type_size != 64) {
+ Printf(stderr, "-intgosize not 32 or 64\n");
+ Swig_arg_error();
+ }
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ ++i;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-help") == 0) {
+ display_help = true;
+ Printf(stdout, "%s\n", usage);
+ }
+ }
+ }
+
+ if (gccgo_flag && !pkgpath_option && !prefix_option) {
+ prefix_option = NewString("go");
+ }
+
+ // Add preprocessor symbol to parser.
+ Preprocessor_define("SWIGGO 1", 0);
+
+ if (cgo_flag) {
+ Preprocessor_define("SWIGGO_CGO 1", 0);
+ }
+
+ if (gccgo_flag) {
+ Preprocessor_define("SWIGGO_GCCGO 1", 0);
+ }
+
+ // This test may be removed in the future, when we can assume that
+ // everybody has upgraded to Go 1.1. The code below is prepared
+ // for this test to simply be taken out.
+ if (intgo_type_size == 0 && !display_help) {
+ Printf(stderr, "SWIG -go: -intgosize option required but not specified\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ if (intgo_type_size == 32) {
+ Preprocessor_define("SWIGGO_INTGO_SIZE 32", 0);
+ } else if (intgo_type_size == 64) {
+ Preprocessor_define("SWIGGO_INTGO_SIZE 64", 0);
+ } else {
+ Preprocessor_define("SWIGGO_INTGO_SIZE 0", 0);
+ }
+
+ // Add typemap definitions.
+ SWIG_typemap_lang("go");
+ SWIG_config_file("go.swg");
+
+ allow_overloading();
+ }
+
+ /* ---------------------------------------------------------------------
+ * top()
+ *
+ * For 6g/8g, we are going to create the following files:
+ *
+ * 1) A .c or .cxx file compiled with gcc. This file will contain
+ * function wrappers. Each wrapper will take a pointer to a
+ * struct holding the arguments, unpack them, and call the real
+ * function.
+ *
+ * 2) A .go file which defines the Go form of all types, and which
+ * defines Go function wrappers. Each wrapper will call the C
+ * function wrapper in the second file.
+ *
+ * 3) A .c file compiled with 6c/8c. This file will define
+ * Go-callable C function wrappers. Each wrapper will use
+ * cgocall to call the function wrappers in the first file.
+ *
+ * When generating code for gccgo, we don't need the third file, and
+ * the function wrappers in the first file have a different form.
+ *
+ * --------------------------------------------------------------------- */
+
+ virtual int top(Node *n) {
+ Node *optionsnode = Getattr(Getattr(n, "module"), "options");
+ if (optionsnode) {
+ if (Getattr(optionsnode, "directors")) {
+ allow_directors();
+ }
+ if (Getattr(optionsnode, "dirprot")) {
+ allow_dirprot();
+ }
+ allow_allprotected(GetFlag(optionsnode, "allprotected"));
+ }
+
+ module = Getattr(n, "name");
+ if (!package) {
+ package = Copy(module);
+ }
+ if (!soname && use_shlib) {
+ soname = Copy(package);
+ Append(soname, ".so");
+ }
+
+ if (gccgo_flag) {
+ String *pref;
+ if (pkgpath_option) {
+ pref = pkgpath_option;
+ } else {
+ pref = prefix_option;
+ }
+ go_prefix = NewString("");
+ for (char *p = Char(pref); *p != '\0'; p++) {
+ if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9') || *p == '.' || *p == '$') {
+ Putc(*p, go_prefix);
+ } else {
+ Putc('_', go_prefix);
+ }
+ }
+ if (!pkgpath_option) {
+ Append(go_prefix, ".");
+ Append(go_prefix, getModuleName(package));
+ }
+ }
+
+ // Get filenames.
+
+ String *swig_filename = Getattr(n, "infile");
+ String *c_filename = Getattr(n, "outfile");
+ String *c_filename_h = Getattr(n, "outfile_h");
+
+ String *go_filename = NewString("");
+ Printf(go_filename, "%s%s.go", SWIG_output_directory(), module);
+
+ String *gc_filename = NULL;
+ if (!gccgo_flag) {
+ gc_filename = NewString("");
+ Printf(gc_filename, "%s%s_gc.c", SWIG_output_directory(), module);
+ }
+
+ // Generate a unique ID based on a hash of the SWIG input.
+ swig_uint64 hash = {0, 0};
+ FILE *swig_input = Swig_open(swig_filename);
+ if (swig_input == NULL) {
+ FileErrorDisplay(swig_filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ String *swig_input_content = Swig_read_file(swig_input);
+ siphash(&hash, Char(swig_input_content), Len(swig_input_content));
+ Delete(swig_input_content);
+ fclose(swig_input);
+ unique_id = NewString("");
+ Printf(unique_id, "_%s_%08x%08x", getModuleName(package), hash.hi, hash.lo);
+
+ // 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 && !cgo_flag) {
+ f_gc_begin = NewFile(gc_filename, "w", SWIG_output_files());
+ if (!f_gc_begin) {
+ FileErrorDisplay(gc_filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+
+ f_c_runtime = NewString("");
+ f_c_header = NewString("");
+ f_c_wrappers = NewString("");
+ f_c_init = NewString("");
+ f_c_directors = NewString("");
+ f_go_imports = NewString("");
+ f_go_runtime = NewString("");
+ f_go_header = NewString("");
+ f_go_wrappers = NewString("");
+ f_go_directors = NewString("");
+ if (!gccgo_flag && !cgo_flag) {
+ f_gc_runtime = NewString("");
+ f_gc_header = NewString("");
+ f_gc_wrappers = NewString("");
+ }
+ if (cgo_flag) {
+ f_cgo_comment = NewString("");
+ f_cgo_comment_typedefs = NewString("");
+ }
+
+ Swig_register_filebyname("begin", f_c_begin);
+ Swig_register_filebyname("runtime", f_c_runtime);
+ Swig_register_filebyname("header", f_c_header);
+ Swig_register_filebyname("wrapper", f_c_wrappers);
+ Swig_register_filebyname("init", f_c_init);
+ Swig_register_filebyname("director", f_c_directors);
+ Swig_register_filebyname("director_h", f_c_directors_h);
+ Swig_register_filebyname("go_begin", f_go_begin);
+ Swig_register_filebyname("go_imports", f_go_imports);
+ Swig_register_filebyname("go_runtime", f_go_runtime);
+ Swig_register_filebyname("go_header", f_go_header);
+ Swig_register_filebyname("go_wrapper", f_go_wrappers);
+ Swig_register_filebyname("go_director", f_go_directors);
+ if (!gccgo_flag && !cgo_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);
+ }
+ if (cgo_flag) {
+ Swig_register_filebyname("cgo_comment", f_cgo_comment);
+ Swig_register_filebyname("cgo_comment_typedefs", f_cgo_comment_typedefs);
+ }
+
+ Swig_banner(f_c_begin);
+ if (CPlusPlus) {
+ Printf(f_c_begin, "\n// source: %s\n\n", swig_filename);
+ } else {
+ Printf(f_c_begin, "\n/* source: %s */\n\n", swig_filename);
+ }
+
+ Printf(f_c_runtime, "#define SWIGMODULE %s\n", module);
+ if (gccgo_flag) {
+ Printf(f_c_runtime, "#define SWIGGO_PREFIX %s\n", go_prefix);
+ }
+
+ if (directorsEnabled()) {
+ Printf(f_c_runtime, "#define SWIG_DIRECTORS\n");
+
+ Swig_banner(f_c_directors_h);
+ Printf(f_c_directors_h, "\n// source: %s\n\n", swig_filename);
+
+ Printf(f_c_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module);
+ Printf(f_c_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module);
+ Printf(f_c_directors_h, "class Swig_memory;\n\n");
+
+ Printf(f_c_directors, "\n// C++ director class methods.\n");
+ String *filename = Swig_file_filename(c_filename_h);
+ Printf(f_c_directors, "#include \"%s\"\n\n", filename);
+ Delete(filename);
+ }
+
+ Swig_banner(f_go_begin);
+ Printf(f_go_begin, "\n// source: %s\n", swig_filename);
+
+ if (!gccgo_flag && !cgo_flag && soname) {
+ Swig_banner(f_gc_begin);
+ Printf(f_gc_begin, "\n/* source: %s */\n\n", swig_filename);
+ Printf(f_gc_begin, "\n/* This file should be compiled with 6c/8c. */\n");
+ Printf(f_gc_begin, "#pragma dynimport _ _ \"%s\"\n", soname);
+ }
+
+ if (cgo_flag) {
+ Printv(f_cgo_comment_typedefs, "/*\n", NULL);
+
+ // The cgo program defines the intgo type after our function
+ // definitions, but we want those definitions to be able to use
+ // intgo also.
+ Printv(f_cgo_comment_typedefs, "#define intgo swig_intgo\n", NULL);
+ Printv(f_cgo_comment_typedefs, "typedef void *swig_voidp;\n", NULL);
+ }
+
+ // Output module initialization code.
+
+ Printf(f_go_begin, "\npackage %s\n\n", getModuleName(package));
+
+ if (gccgo_flag && !cgo_flag) {
+ Printf(f_go_runtime, "func SwigCgocall()\n");
+ Printf(f_go_runtime, "func SwigCgocallDone()\n");
+ Printf(f_go_runtime, "func SwigCgocallBack()\n");
+ Printf(f_go_runtime, "func SwigCgocallBackDone()\n\n");
+ }
+
+ // All the C++ wrappers should be extern "C".
+
+ Printv(f_c_wrappers, "#ifdef __cplusplus\n", "extern \"C\" {\n", "#endif\n\n", NULL);
+
+ // Set up the hash table for types not defined by SWIG.
+
+ undefined_enum_types = NewHash();
+ undefined_types = NewHash();
+ defined_types = NewHash();
+ go_imports = NewHash();
+
+ // Emit code.
+
+ Language::top(n);
+
+ if (directorsEnabled()) {
+ // Insert director runtime into the f_runtime file (make it occur before %header section)
+ Swig_insert_file("director_common.swg", f_c_runtime);
+ Swig_insert_file("director.swg", f_c_runtime);
+ }
+
+ Delete(go_imports);
+
+ // Write out definitions for the types not defined by SWIG.
+
+ if (Len(undefined_enum_types) > 0)
+ Printv(f_go_wrappers, "\n", NULL);
+ for (Iterator p = First(undefined_enum_types); p.key; p = Next(p)) {
+ String *name = p.item;
+ Printv(f_go_wrappers, "type ", name, " int\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "\n", NULL);
+ for (Iterator p = First(undefined_types); p.key; p = Next(p)) {
+ String *ty = goType(NULL, p.key);
+ if (!Getattr(defined_types, ty)) {
+ String *cp = goCPointerType(p.key, false);
+ if (!Getattr(defined_types, cp)) {
+ Printv(f_go_wrappers, "type ", cp, " uintptr\n", NULL);
+ Printv(f_go_wrappers, "type ", ty, " interface {\n", NULL);
+ Printv(f_go_wrappers, "\tSwigcptr() uintptr;\n", NULL);
+ Printv(f_go_wrappers, "}\n", NULL);
+ Printv(f_go_wrappers, "func (p ", cp, ") Swigcptr() uintptr {\n", NULL);
+ Printv(f_go_wrappers, "\treturn uintptr(p)\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+ }
+ Delete(cp);
+ }
+ Delete(ty);
+ }
+ Delete(undefined_enum_types);
+ Delete(undefined_types);
+ Delete(defined_types);
+
+ /* Write and cleanup */
+
+ Dump(f_c_header, f_c_runtime);
+
+ if (directorsEnabled()) {
+ Printf(f_c_directors_h, "#endif\n");
+ Delete(f_c_directors_h);
+ f_c_directors_h = NULL;
+
+ Dump(f_c_directors, f_c_runtime);
+ Delete(f_c_directors);
+ f_c_directors = NULL;
+ }
+
+ // End the extern "C".
+ Printv(f_c_wrappers, "#ifdef __cplusplus\n", "}\n", "#endif\n\n", NULL);
+
+ if (cgo_flag) {
+ // End the cgo comment.
+ Printv(f_cgo_comment, "#undef intgo\n", NULL);
+ Printv(f_cgo_comment, "*/\n", NULL);
+ Printv(f_cgo_comment, "import \"C\"\n", NULL);
+ Printv(f_cgo_comment, "\n", NULL);
+ }
+
+ Dump(f_c_runtime, f_c_begin);
+ Dump(f_c_wrappers, f_c_begin);
+ Dump(f_c_init, f_c_begin);
+ if (cgo_flag) {
+ Dump(f_cgo_comment_typedefs, f_go_begin);
+ Dump(f_cgo_comment, f_go_begin);
+ }
+ Dump(f_go_imports, f_go_begin);
+ Dump(f_go_header, f_go_begin);
+ Dump(f_go_runtime, f_go_begin);
+ Dump(f_go_wrappers, f_go_begin);
+ if (directorsEnabled()) {
+ Dump(f_go_directors, f_go_begin);
+ }
+ if (!gccgo_flag && !cgo_flag) {
+ Dump(f_gc_header, f_gc_begin);
+ Dump(f_gc_runtime, f_gc_begin);
+ Dump(f_gc_wrappers, f_gc_begin);
+ }
+
+ Delete(f_c_runtime);
+ Delete(f_c_header);
+ Delete(f_c_wrappers);
+ Delete(f_c_init);
+ Delete(f_go_imports);
+ Delete(f_go_runtime);
+ Delete(f_go_header);
+ Delete(f_go_wrappers);
+ Delete(f_go_directors);
+ if (!gccgo_flag && !cgo_flag) {
+ Delete(f_gc_runtime);
+ Delete(f_gc_header);
+ Delete(f_gc_wrappers);
+ }
+ if (cgo_flag) {
+ Delete(f_cgo_comment);
+ Delete(f_cgo_comment_typedefs);
+ }
+
+ Delete(f_c_begin);
+ Delete(f_go_begin);
+ if (!gccgo_flag && !cgo_flag) {
+ Delete(f_gc_begin);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * importDirective()
+ *
+ * Handle a SWIG import statement by generating a Go import
+ * statement.
+ * ------------------------------------------------------------ */
+
+ virtual int importDirective(Node *n) {
+ String *hold_import = imported_package;
+ String *modname = Getattr(n, "module");
+ if (modname) {
+ if (!Getattr(go_imports, modname)) {
+ Setattr(go_imports, modname, modname);
+ Printv(f_go_imports, "import \"", NULL);
+ if (import_prefix) {
+ Printv(f_go_imports, import_prefix, "/", NULL);
+ }
+ Printv(f_go_imports, modname, "\"\n", NULL);
+ }
+ imported_package = modname;
+ saw_import = true;
+ }
+ int r = Language::importDirective(n);
+ imported_package = hold_import;
+ return r;
+ }
+
+ /* ----------------------------------------------------------------------
+ * Language::insertDirective()
+ *
+ * If the section is go_imports, store them for later.
+ * ---------------------------------------------------------------------- */
+ virtual int insertDirective(Node *n) {
+ char *section = Char(Getattr(n, "section"));
+ if ((ImportMode && !Getattr(n, "generated")) ||
+ !section || (strcmp(section, "go_imports") != 0)) {
+ return Language::insertDirective(n);
+ }
+
+ char *code = Char(Getattr(n, "code"));
+ char *pch = strtok(code, ",");
+ while (pch != NULL) {
+ // Do not import same thing more than once.
+ if (!Getattr(go_imports, pch)) {
+ Setattr(go_imports, pch, pch);
+ Printv(f_go_imports, "import ", pch, "\n", NULL);
+ }
+ pch = strtok(NULL, ",");
+ }
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * functionWrapper()
+ *
+ * Implement a function.
+ * ---------------------------------------------------------------------- */
+
+ virtual int functionWrapper(Node *n) {
+ if (GetFlag(n, "feature:ignore")) {
+ return SWIG_OK;
+ }
+
+ // We don't need explicit calls.
+ if (GetFlag(n, "explicitcall")) {
+ return SWIG_OK;
+ }
+
+ // Don't emit constructors for abstract director classes. They
+ // will never succeed anyhow.
+ if (Swig_methodclass(n) && Swig_directorclass(n)
+ && Strcmp(Char(Getattr(n, "wrap:action")), director_prot_ctor_code) == 0) {
+ 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)) {
+ // 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);
+ }
+ Append(wname, unique_id);
+ 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 a virtual method not defined in the current class.
+ * parms: The parameters.
+ * result: The result type.
+ * is_static: Whether this is a static method or member.
+ * ---------------------------------------------------------------------- */
+
+ int makeWrappers(Node *n, String *name, String *go_name, String *overname, String *wname, List *base, ParmList *parms, SwigType *result, bool is_static) {
+
+ assert(result);
+
+ int ret = SWIG_OK;
+
+ if (cgo_flag) {
+ int r = makeCgoWrappers(n, go_name, overname, wname, base, parms, result, is_static);
+ if (r != SWIG_OK) {
+ ret = r;
+ }
+ } else {
+ int r = goFunctionWrapper(n, name, go_name, overname, wname, base, parms, result, is_static);
+ if (r != SWIG_OK) {
+ ret = r;
+ }
+
+ if (!gccgo_flag) {
+ r = gcFunctionWrapper(wname);
+ if (r != SWIG_OK) {
+ ret = r;
+ }
+ r = gccFunctionWrapper(n, base, wname, parms, result);
+ if (r != SWIG_OK) {
+ ret = r;
+ }
+ } else {
+ r = gccgoFunctionWrapper(n, base, wname, parms, result);
+ if (r != SWIG_OK) {
+ ret = r;
+ }
+ }
+ }
+
+ if (class_methods) {
+ Setattr(class_methods, Getattr(n, "name"), NewString(""));
+ }
+
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * struct cgoWrapperInfo
+ *
+ * Information needed by the CGO wrapper functions.
+ * ---------------------------------------------------------------------- */
+
+ struct cgoWrapperInfo {
+ // The function we are generating code for.
+ Node *n;
+ // The name of the Go function.
+ String *go_name;
+ // The overload string for an overloaded function.
+ String *overname;
+ // The name of the C wrapper function.
+ String *wname;
+ // The base classes.
+ List *base;
+ // The parameters.
+ ParmList *parms;
+ // The result type.
+ SwigType *result;
+ // Whether this is a static function, not a class method.
+ bool is_static;
+ // The Go receiver type.
+ String *receiver;
+ // Whether this is a class constructor.
+ bool is_constructor;
+ // Whether this is a class destructor.
+ bool is_destructor;
+ };
+
+ /* ----------------------------------------------------------------------
+ * makeCgoWrappers()
+ *
+ * Write out the wrappers for a function when producing cgo input
+ * files.
+ * ---------------------------------------------------------------------- */
+
+ int makeCgoWrappers(Node *n, String *go_name, String *overname, String *wname, List *base, ParmList *parms, SwigType *result, bool is_static) {
+ Swig_save("makeCgoWrappers", n, "emit:cgotype", "emit:cgotypestruct", NULL);
+
+ cgoWrapperInfo info;
+
+ info.n = n;
+ info.go_name = go_name;
+ info.overname = overname;
+ info.wname = wname;
+ info.base = base;
+ info.parms = parms;
+ info.result = result;
+ info.is_static = is_static;
+
+ info.receiver = class_receiver;
+ if (is_static) {
+ info.receiver = NULL;
+ }
+
+ String *nodetype = Getattr(n, "nodeType");
+ info.is_constructor = Cmp(nodetype, "constructor") == 0;
+ info.is_destructor = Cmp(nodetype, "destructor") == 0;
+ if (info.is_constructor || info.is_destructor) {
+ assert(class_receiver);
+ assert(!base);
+ info.receiver = NULL;
+ }
+
+ int ret = SWIG_OK;
+
+ int r = cgoGoWrapper(&info);
+ if (r != SWIG_OK) {
+ ret = r;
+ }
+
+ r = cgoCommentWrapper(&info);
+ if (r != SWIG_OK) {
+ ret = r;
+ }
+
+ r = cgoGccWrapper(&info);
+ if (r != SWIG_OK) {
+ ret = r;
+ }
+
+ Swig_restore(n);
+
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * cgoGoWrapper()
+ *
+ * Write out Go code to call a cgo function. This code will go into
+ * the generated Go output file.
+ * ---------------------------------------------------------------------- */
+ int cgoGoWrapper(const cgoWrapperInfo *info) {
+
+ Wrapper *dummy = initGoTypemaps(info->parms);
+
+ bool add_to_interface = interfaces && !info->is_constructor && !info->is_destructor && !info->is_static && !info->overname && checkFunctionVisibility(info->n, NULL);
+
+ Printv(f_go_wrappers, "func ", NULL);
+
+ Parm *p = info->parms;
+ int pi = 0;
+
+ // Add the receiver first if this is a method.
+ if (info->receiver) {
+ Printv(f_go_wrappers, "(", NULL);
+ if (info->base && info->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, " ", info->receiver, ") ", NULL);
+ }
+
+ Printv(f_go_wrappers, info->go_name, NULL);
+ if (info->overname) {
+ Printv(f_go_wrappers, info->overname, NULL);
+ }
+ Printv(f_go_wrappers, "(", NULL);
+
+ // If we are doing methods, add this method to the interface.
+ if (add_to_interface) {
+ Printv(interfaces, "\t", info->go_name, "(", NULL);
+ }
+
+ // Write out the parameters to both the function definition and
+ // the interface.
+
+ String *parm_print = NewString("");
+
+ int parm_count = emit_num_arguments(info->parms);
+ int required_count = emit_num_required(info->parms);
+ int args = 0;
+
+ for (; pi < parm_count; ++pi) {
+ p = getParm(p);
+ if (pi == 0 && info->is_destructor) {
+ String *cl = exportedName(class_name);
+ Printv(parm_print, Getattr(p, "lname"), " ", cl, NULL);
+ Delete(cl);
+ ++args;
+ } else {
+ if (args > 0) {
+ Printv(parm_print, ", ", NULL);
+ }
+ ++args;
+ if (pi >= required_count) {
+ Printv(parm_print, "_swig_args ...interface{}", NULL);
+ break;
+ }
+ 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 (info->is_constructor) {
+ String *cl = exportedName(class_name);
+ Printv(parm_print, " (_swig_ret ", cl, ")", NULL);
+ Delete(cl);
+ } else {
+ if (SwigType_type(info->result) != T_VOID) {
+ String *tm = goType(info->n, info->result);
+ Printv(parm_print, " (_swig_ret ", tm, ")", NULL);
+ Delete(tm);
+ }
+ }
+
+ Printv(f_go_wrappers, parm_print, NULL);
+ if (add_to_interface) {
+ Printv(interfaces, parm_print, "\n", NULL);
+ }
+
+ // Write out the function body.
+
+ Printv(f_go_wrappers, " {\n", NULL);
+
+ if (parm_count > required_count) {
+ Parm *p = info->parms;
+ int i;
+ for (i = 0; i < required_count; ++i) {
+ p = getParm(p);
+ p = nextParm(p);
+ }
+ for (; i < parm_count; ++i) {
+ p = getParm(p);
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(f_go_wrappers, "\tvar ", Getattr(p, "lname"), " ", tm, "\n", NULL);
+ Printf(f_go_wrappers, "\tif len(_swig_args) > %d {\n", i - required_count);
+ Printf(f_go_wrappers, "\t\t%s = _swig_args[%d].(%s)\n", Getattr(p, "lname"), i - required_count, tm);
+ Printv(f_go_wrappers, "\t}\n", NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+ }
+
+ String *call = NewString("\t");
+
+ String *ret_type = NULL;
+ bool memcpy_ret = false;
+ String *wt = NULL;
+ if (SwigType_type(info->result) != T_VOID) {
+ if (info->is_constructor) {
+ ret_type = exportedName(class_name);
+ } else {
+ ret_type = goImType(info->n, info->result);
+ }
+ Printv(f_go_wrappers, "\tvar swig_r ", ret_type, "\n", NULL);
+
+ bool c_struct_type;
+ Delete(cgoTypeForGoValue(info->n, info->result, &c_struct_type));
+ if (c_struct_type) {
+ memcpy_ret = true;
+ }
+
+ if (memcpy_ret) {
+ Printv(call, "swig_r_p := ", NULL);
+ } else {
+ Printv(call, "swig_r = (", ret_type, ")(", NULL);
+ }
+
+ if (info->is_constructor || goTypeIsInterface(info->n, info->result)) {
+ if (info->is_constructor) {
+ wt = Copy(class_receiver);
+ } else {
+ wt = goWrapperType(info->n, info->result, true);
+ }
+ Printv(call, wt, "(", NULL);
+ }
+ }
+
+ Printv(call, "C.", info->wname, "(", NULL);
+
+ args = 0;
+
+ if (parm_count > required_count) {
+ Printv(call, "C.swig_intgo(len(_swig_args))", NULL);
+ ++args;
+ }
+
+ if (info->base && info->receiver) {
+ if (args > 0) {
+ Printv(call, ", ", NULL);
+ }
+ ++args;
+ Printv(call, "C.uintptr_t(_swig_base)", NULL);
+ }
+
+ p = info->parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (args > 0) {
+ Printv(call, ", ", NULL);
+ }
+ ++args;
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+
+ String *ivar = NewStringf("_swig_i_%d", i);
+
+ String *goin = goGetattr(p, "tmap:goin");
+ if (goin == NULL) {
+ Printv(f_go_wrappers, "\t", ivar, " := ", ln, NULL);
+ if ((i == 0 && info->is_destructor) || ((i > 0 || !info->receiver || info->base || info->is_constructor) && goTypeIsInterface(p, pt))) {
+ Printv(f_go_wrappers, ".Swigcptr()", NULL);
+ }
+ Printv(f_go_wrappers, "\n", NULL);
+ Setattr(p, "emit:goinput", ln);
+ } else {
+ String *itm = goImType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(f_go_wrappers, goin, "\n", NULL);
+ Delete(goin);
+ Setattr(p, "emit:goinput", ivar);
+ }
+
+ bool c_struct_type;
+ String *ct = cgoTypeForGoValue(p, pt, &c_struct_type);
+ if (c_struct_type) {
+ Printv(call, "*(*C.", ct, ")(unsafe.Pointer(&", ivar, "))", NULL);
+ } else {
+ Printv(call, "C.", ct, "(", ivar, ")", NULL);
+ }
+ Delete(ct);
+
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, call, ")", NULL);
+ Delete(call);
+
+ if (wt) {
+ // Close the type conversion to the wrapper type.
+ Printv(f_go_wrappers, ")", NULL);
+ }
+ if (SwigType_type(info->result) != T_VOID && !memcpy_ret) {
+ // Close the type conversion of the return value.
+ Printv(f_go_wrappers, ")", NULL);
+ }
+
+ Printv(f_go_wrappers, "\n", NULL);
+
+ if (memcpy_ret) {
+ Printv(f_go_wrappers, "\tswig_r = *(*", ret_type, ")(unsafe.Pointer(&swig_r_p))\n", NULL);
+ }
+ if (ret_type) {
+ Delete(ret_type);
+ }
+
+ goargout(info->parms);
+
+ if (SwigType_type(info->result) != T_VOID) {
+
+ Swig_save("cgoGoWrapper", info->n, "type", "tmap:goout", NULL);
+ Setattr(info->n, "type", info->result);
+
+ String *goout = goTypemapLookup("goout", info->n, "swig_r");
+ if (goout == NULL) {
+ Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ } else {
+ String *tm = goType(info->n, info->result);
+ Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+ goout = Copy(goout);
+ Replaceall(goout, "$input", "swig_r");
+ Replaceall(goout, "$result", "swig_r_1");
+ Printv(f_go_wrappers, goout, "\n", NULL);
+ Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+ }
+
+ Swig_restore(info->n);
+ }
+
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ DelWrapper(dummy);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * cgoCommentWrapper()
+ *
+ * Write out a cgo function to call a C/C++ function. This code
+ * will go into the cgo comment in the generated Go output file.
+ * ---------------------------------------------------------------------- */
+ int cgoCommentWrapper(const cgoWrapperInfo *info) {
+ String *ret_type;
+ if (SwigType_type(info->result) == T_VOID) {
+ ret_type = NewString("void");
+ } else {
+ bool c_struct_type;
+ ret_type = cgoTypeForGoValue(info->n, info->result, &c_struct_type);
+ }
+
+ Printv(f_cgo_comment, "extern ", ret_type, " ", info->wname, "(", NULL);
+
+ Delete(ret_type);
+
+ int parm_count = emit_num_arguments(info->parms);
+ int required_count = emit_num_required(info->parms);
+ int args = 0;
+
+ if (parm_count > required_count) {
+ Printv(f_cgo_comment, "intgo _swig_args", NULL);
+ ++args;
+ }
+
+ if (info->base && info->receiver) {
+ if (args > 0) {
+ Printv(f_cgo_comment, ", ", NULL);
+ }
+ ++args;
+ Printv(f_cgo_comment, "uintptr_t _swig_base", NULL);
+ }
+
+ Parm *p = info->parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (args > 0) {
+ Printv(f_cgo_comment, ", ", NULL);
+ }
+ ++args;
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+
+ bool c_struct_type;
+ String *ct = cgoTypeForGoValue(p, pt, &c_struct_type);
+ Printv(f_cgo_comment, ct, " ", ln, NULL);
+ Delete(ct);
+
+ p = nextParm(p);
+ }
+
+ if (args == 0) {
+ Printv(f_cgo_comment, "void", NULL);
+ }
+
+ Printv(f_cgo_comment, ");\n", NULL);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * cgoGccWrapper()
+ *
+ * Write out code to the C/C++ wrapper file. This code will be
+ * called by the code generated by cgoCommentWrapper.
+ * ---------------------------------------------------------------------- */
+ int cgoGccWrapper(const cgoWrapperInfo *info) {
+ Wrapper *f = NewWrapper();
+
+ Swig_save("cgoGccWrapper", info->n, "parms", NULL);
+
+ ParmList *parms = info->parms;
+
+ Parm *base_parm = NULL;
+ if (info->base && !isStatic(info->n)) {
+ SwigType *base_type = Copy(getClassType());
+ SwigType_add_pointer(base_type);
+ base_parm = NewParm(base_type, NewString("arg1"), info->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(info->n, info->result, f);
+
+ // Start the function definition.
+
+ String *fnname = NewString("");
+ Printv(fnname, info->wname, "(", NULL);
+
+ int args = 0;
+
+ if (parm_count > required_count) {
+ Printv(fnname, "intgo _swig_optargc", NULL);
+ ++args;
+ }
+
+ Parm *p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ if (args > 0) {
+ Printv(fnname, ", ", NULL);
+ }
+ ++args;
+
+ p = getParm(p);
+
+ SwigType *pt = Copy(Getattr(p, "type"));
+ if (SwigType_isarray(pt)) {
+ SwigType_del_array(pt);
+ SwigType_add_pointer(pt);
+ }
+ String *pn = NewStringf("_swig_go_%d", i);
+ String *ct = gcCTypeForGoValue(p, pt, pn);
+ Printv(fnname, ct, NULL);
+ Delete(ct);
+ Delete(pn);
+ Delete(pt);
+
+ p = nextParm(p);
+ }
+
+ Printv(fnname, ")", NULL);
+
+ if (SwigType_type(info->result) == T_VOID) {
+ Printv(f->def, "void ", fnname, NULL);
+ } else {
+ String *ct = gcCTypeForGoValue(info->n, info->result, fnname);
+ Printv(f->def, ct, NULL);
+ Delete(ct);
+
+ String *ln = NewString("_swig_go_result");
+ ct = gcCTypeForGoValue(info->n, info->result, ln);
+ Wrapper_add_local(f, "_swig_go_result", ct);
+ Delete(ct);
+ Delete(ln);
+ }
+
+ Delete(fnname);
+
+ Printv(f->def, " {\n", NULL);
+
+ // Apply the in typemaps.
+
+ 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 {
+ tm = Copy(tm);
+ String *pn = NewStringf("_swig_go_%d", i);
+ Replaceall(tm, "$input", pn);
+ if (i < required_count) {
+ Printv(f->code, "\t", tm, "\n", NULL);
+ } else {
+ Printf(f->code, "\tif (_swig_optargc > %d) {\n", i - required_count);
+ Printv(f->code, "\t\t", tm, "\n", NULL);
+ Printv(f->code, "\t}\n", NULL);
+ }
+ Delete(tm);
+ Setattr(p, "emit:input", pn);
+ }
+ p = nextParm(p);
+ }
+
+ Printv(f->code, "\n", NULL);
+
+ // Do the real work of the function.
+
+ checkConstraints(parms, f);
+
+ emitGoAction(info->n, info->base, parms, info->result, f);
+
+ argout(parms, f);
+
+ cleanupFunction(info->n, f, parms);
+
+ if (SwigType_type(info->result) != T_VOID) {
+ Printv(f->code, "\treturn _swig_go_result;\n", NULL);
+ }
+
+ Printv(f->code, "}\n", NULL);
+
+ Wrapper_print(f, f_c_wrappers);
+
+ Swig_restore(info->n);
+
+ DelWrapper(f);
+ if (base_parm) {
+ Delete(base_parm);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * goFunctionWrapper()
+ *
+ * Write out a function wrapper in Go. When not implementing a
+ * method, the actual code is all in C; here we just declare the C
+ * function. When implementing a method, we have to call the C
+ * function, because it will have a different name. If base is not
+ * NULL, then we are being called to forward a virtual method to a
+ * base class.
+ * ---------------------------------------------------------------------- */
+
+ int goFunctionWrapper(Node *n, String *name, String *go_name, String *overname, String *wname, List *base, ParmList *parms, SwigType *result, bool is_static) {
+ Wrapper *dummy = initGoTypemaps(parms);
+
+ 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;
+ }
+
+ Swig_save("cgoGoWrapper", n, "type", "tmap:goout", NULL);
+ Setattr(n, "type", result);
+
+ String *goout = goTypemapLookup("goout", n, "swig_r");
+
+ Swig_restore(n);
+
+ bool add_to_interface = (interfaces && !is_constructor && !is_destructor && !is_static && !overname && checkFunctionVisibility(n, NULL));
+
+ bool needs_wrapper = (gccgo_flag || receiver || is_constructor || is_destructor || parm_count > required_count);
+
+ bool has_goout = false;
+ if (goout) {
+ has_goout = true;
+ }
+
+ // See whether any of the function parameters are represented by
+ // interface values. When calling the C++ code, we need to convert
+ // back to a uintptr.
+ Parm *p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *ty = Getattr(p, "type");
+ if (goGetattr(p, "tmap:goargout")) {
+ has_goout = true;
+ needs_wrapper = true;
+ } else if (goTypeIsInterface(p, ty) || goGetattr(p, "tmap:goin")) {
+ needs_wrapper = true;
+ }
+
+ if (paramNeedsEscape(p)) {
+ needs_wrapper = true;
+ }
+
+ p = nextParm(p);
+ }
+ if (goTypeIsInterface(n, result) || goout != NULL) {
+ needs_wrapper = true;
+ }
+
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, "var ", wname, " unsafe.Pointer\n\n", NULL);
+ }
+
+ // If this is a method, first declare the C function we will call.
+ // If we do not need a wrapper, then we will only be writing a
+ // declaration.
+ String *wrapper_name = NULL;
+ if (needs_wrapper) {
+ wrapper_name = buildGoWrapperName(name, overname);
+
+ if (gccgo_flag) {
+ Printv(f_go_wrappers, "//extern ", go_prefix, "_", wname, "\n", NULL);
+ }
+
+ bool arg = false;
+ Printv(f_go_wrappers, "func ", wrapper_name, "(", NULL);
+ if (parm_count > required_count) {
+ Printv(f_go_wrappers, argName(&arg), " int", NULL);
+ }
+ Parm *p = getParm(parms);
+ int i = 0;
+ if (is_destructor) {
+ if (parm_count > required_count) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ Printv(f_go_wrappers, argName(&arg), " uintptr", NULL);
+ ++i;
+ p = nextParm(p);
+ } else if (receiver && (base || !is_constructor)) {
+ if (parm_count > required_count) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ Printv(f_go_wrappers, argName(&arg), " ", receiver, NULL);
+ if (!base) {
+ ++i;
+ p = nextParm(p);
+ }
+ }
+ for (; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0 || (base && receiver) || parm_count > required_count) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ String *tm = goWrapperType(p, Getattr(p, "type"), false);
+ Printv(f_go_wrappers, argName(&arg), " ", tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+ Printv(f_go_wrappers, ")", NULL);
+ if (is_constructor) {
+ Printv(f_go_wrappers, " (", argName(&arg), " ", class_receiver, ")", NULL);
+ } else {
+ if (SwigType_type(result) != T_VOID) {
+ String *tm = goWrapperType(n, result, true);
+ Printv(f_go_wrappers, " (", argName(&arg), " ", tm, ")", NULL);
+ Delete(tm);
+ }
+ }
+
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, " {\n", NULL);
+ if (arg) {
+ Printv(f_go_wrappers, "\t_swig_p := uintptr(unsafe.Pointer(&base))\n", NULL);
+ } else {
+ Printv(f_go_wrappers, "\tvar _swig_p uintptr\n", NULL);
+ }
+ Printv(f_go_wrappers, "\t_cgo_runtime_cgocall(", wname, ", _swig_p)\n", NULL);
+ Printv(f_go_wrappers, "\treturn\n", NULL);
+ Printv(f_go_wrappers, "}", NULL);
+ }
+
+ Printv(f_go_wrappers, "\n\n", NULL);
+ }
+
+ // Start defining the Go function.
+
+ if (!needs_wrapper && gccgo_flag) {
+ Printv(f_go_wrappers, "//extern ", go_prefix, "_", wname, "\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "func ", NULL);
+
+ p = parms;
+ int pi = 0;
+
+ // Add the receiver if this is a method.
+ String *first = NULL;
+ if (receiver) {
+ Printv(f_go_wrappers, "(", NULL);
+ if (base && receiver) {
+ Printv(f_go_wrappers, "_swig_base", NULL);
+ if (first == NULL) {
+ first = NewString("_swig_base");
+ }
+ } else {
+ Printv(f_go_wrappers, Getattr(p, "lname"), NULL);
+ if (first == NULL) {
+ first = Copy(Getattr(p, "lname"));
+ }
+ p = nextParm(p);
+ ++pi;
+ }
+ Printv(f_go_wrappers, " ", receiver, ") ", NULL);
+ }
+
+ Printv(f_go_wrappers, go_name, NULL);
+ if (overname) {
+ Printv(f_go_wrappers, overname, NULL);
+ }
+ Printv(f_go_wrappers, "(", NULL);
+
+ // If we are doing methods, add this function to the interface.
+ if (add_to_interface) {
+ Printv(interfaces, "\t", go_name, "(", NULL);
+ }
+
+ // Write out the parameters to both the function definition and
+ // the interface.
+
+ String *parm_print = NewString("");
+
+ for (; pi < parm_count; ++pi) {
+ p = getParm(p);
+ if (pi == 0 && is_destructor) {
+ String *cl = exportedName(class_name);
+ Printv(parm_print, Getattr(p, "lname"), " ", cl, NULL);
+ if (first == NULL) {
+ first = Copy(Getattr(p, "lname"));
+ }
+ Delete(cl);
+ } else {
+ if (pi > (receiver && !base ? 1 : 0)) {
+ Printv(parm_print, ", ", NULL);
+ }
+ if (pi >= required_count) {
+ Printv(parm_print, "_swig_args ...interface{}", NULL);
+ if (first == NULL) {
+ first = NewString("_swig_args");
+ }
+ break;
+ }
+ Printv(parm_print, Getattr(p, "lname"), " ", NULL);
+ if (first == NULL) {
+ first = Copy(Getattr(p, "lname"));
+ }
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(parm_print, tm, NULL);
+ Delete(tm);
+ }
+ p = nextParm(p);
+ }
+
+ Printv(parm_print, ")", NULL);
+
+ // Write out the result type.
+ if (is_constructor) {
+ String *cl = exportedName(class_name);
+ Printv(parm_print, " (_swig_ret ", cl, ")", NULL);
+ if (first == NULL) {
+ first = NewString("_swig_ret");
+ }
+ Delete(cl);
+ } else {
+ if (SwigType_type(result) != T_VOID) {
+ String *tm = goType(n, result);
+ Printv(parm_print, " (_swig_ret ", tm, ")", NULL);
+ if (first == NULL) {
+ first = NewString("_swig_ret");
+ }
+ Delete(tm);
+ }
+ }
+
+ Printv(f_go_wrappers, parm_print, NULL);
+ if (add_to_interface) {
+ Printv(interfaces, parm_print, "\n", NULL);
+ }
+
+ // If this is a wrapper, we need to actually call the C function.
+ if (needs_wrapper) {
+ Printv(f_go_wrappers, " {\n", NULL);
+
+ if (parm_count > required_count) {
+ Parm *p = parms;
+ int i;
+ for (i = 0; i < required_count; ++i) {
+ p = getParm(p);
+ p = nextParm(p);
+ }
+ for (; i < parm_count; ++i) {
+ p = getParm(p);
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(f_go_wrappers, "\tvar ", Getattr(p, "lname"), " ", tm, "\n", NULL);
+ Printf(f_go_wrappers, "\tif len(_swig_args) > %d {\n", i - required_count);
+ Printf(f_go_wrappers, "\t\t%s = _swig_args[%d].(%s)\n", Getattr(p, "lname"), i - required_count, tm);
+ Printv(f_go_wrappers, "\t}\n", NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+ }
+
+ String *call = NewString("");
+
+ bool need_return_var = SwigType_type(result) != T_VOID && ((gccgo_flag && is_constructor) || has_goout);
+ if (need_return_var) {
+ Printv(f_go_wrappers, "\tvar swig_r ", NULL);
+ if (is_constructor) {
+ String *cl = exportedName(class_name);
+ Printv(f_go_wrappers, cl, NULL);
+ Delete(cl);
+ } else {
+ Printv(f_go_wrappers, goImType(n, result), NULL);
+ }
+ Printv(f_go_wrappers, "\n", NULL);
+ }
+
+ if (gccgo_flag) {
+ if (has_goout || is_constructor) {
+ Printv(call, "\tfunc() {\n", NULL);
+ }
+ Printv(call, "\tdefer SwigCgocallDone()\n", NULL);
+ Printv(call, "\tSwigCgocall()\n", NULL);
+ }
+
+ Printv(call, "\t", NULL);
+ if (SwigType_type(result) != T_VOID) {
+ if (need_return_var) {
+ Printv(call, "swig_r = ", NULL);
+ } else {
+ Printv(call, "return ", NULL);
+ }
+ }
+
+ Printv(call, wrapper_name, "(", NULL);
+
+ if (parm_count > required_count) {
+ Printv(call, "len(_swig_args)", NULL);
+ }
+
+ if (base && receiver) {
+ if (parm_count > required_count) {
+ Printv(call, ", ", NULL);
+ }
+ Printv(call, "_swig_base", NULL);
+ }
+
+ Parm *p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0 || (base && receiver)
+ || parm_count > required_count) {
+ Printv(call, ", ", NULL);
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+
+ String *goin = goGetattr(p, "tmap:goin");
+ if (goin == NULL) {
+ Printv(call, ln, NULL);
+ if ((i == 0 && is_destructor) || ((i > 0 || !receiver || base || is_constructor) && goTypeIsInterface(p, pt))) {
+ Printv(call, ".Swigcptr()", NULL);
+ }
+ Setattr(p, "emit:goinput", ln);
+ } else {
+ String *ivar = NewString("");
+ Printf(ivar, "_swig_i_%d", i);
+ String *itm = goImType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(f_go_wrappers, goin, "\n", NULL);
+ Delete(goin);
+ Printv(call, ivar, NULL);
+ Setattr(p, "emit:goinput", ivar);
+ }
+
+ // If the parameter has an argout or freearg typemap, make
+ // sure that it escapes.
+ if (paramNeedsEscape(p)) {
+ Printv(f_go_wrappers, "\tif Swig_escape_always_false {\n", NULL);
+ Printv(f_go_wrappers, "\t\tSwig_escape_val = ", Getattr(p, "emit:goinput"), "\n", NULL);
+ Printv(f_go_wrappers, "\t}\n", NULL);
+ }
+
+ p = nextParm(p);
+ }
+ Printv(call, ")\n", NULL);
+
+ if (gccgo_flag && (has_goout || is_constructor)) {
+ Printv(call, "\t}()\n", NULL);
+ }
+
+ Printv(f_go_wrappers, call, NULL);
+ Delete(call);
+
+ goargout(parms);
+
+ if (need_return_var) {
+ if (goout == NULL) {
+ Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ } else {
+ String *tm = goType(n, result);
+ Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+ Replaceall(goout, "$input", "swig_r");
+ Replaceall(goout, "$result", "swig_r_1");
+ Printv(f_go_wrappers, goout, "\n", NULL);
+ Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+ }
+ }
+
+ Printv(f_go_wrappers, "}\n", NULL);
+ } else if (!gccgo_flag) {
+ // We don't need a wrapper. If we're using gccgo, the function
+ // declaration is all we need--it has a //extern comment to
+ // GCC-compiled wrapper. If we're not using gccgo, we need to
+ // call the GCC-compiled wrapper here.
+ Printv(f_go_wrappers, " {\n", NULL);
+ if (first == NULL) {
+ Printv(f_go_wrappers, "\tvar _swig_p uintptr\n", NULL);
+ } else {
+ Printv(f_go_wrappers, "\t_swig_p := uintptr(unsafe.Pointer(&", first, "))\n", NULL);
+ }
+ Printv(f_go_wrappers, "\t_cgo_runtime_cgocall(", wname, ", _swig_p)\n", NULL);
+ Printv(f_go_wrappers, "\treturn\n", NULL);
+ Printv(f_go_wrappers, "}", NULL);
+ }
+
+ Printv(f_go_wrappers, "\n", NULL);
+
+ Delete(wrapper_name);
+ DelWrapper(dummy);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * initGoTypemaps()
+ *
+ * Initialize the typenames for a Go wrapper, returning a dummy
+ * Wrapper*. Also set consistent names for the parameters.
+ * ---------------------------------------------------------------------- */
+
+ Wrapper* initGoTypemaps(ParmList *parms) {
+ Wrapper *dummy = NewWrapper();
+ emit_attach_parmmaps(parms, dummy);
+
+ Parm *p = parms;
+ int parm_count = emit_num_arguments(parms);
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ Swig_cparm_name(p, i);
+ p = nextParm(p);
+ }
+
+ Swig_typemap_attach_parms("default", parms, dummy);
+ Swig_typemap_attach_parms("gotype", parms, dummy);
+ Swig_typemap_attach_parms("goin", parms, dummy);
+ Swig_typemap_attach_parms("goargout", parms, dummy);
+ Swig_typemap_attach_parms("imtype", parms, dummy);
+
+ return dummy;
+ }
+
+ /* ----------------------------------------------------------------------
+ * argName()
+ *
+ * A helper for goFunctionWrapper to output the first argument name
+ * as "base" and all others as "_".
+ * ---------------------------------------------------------------------- */
+
+ const char *argName(bool *arg) {
+ if (*arg) {
+ return "_";
+ }
+ *arg = true;
+ return "base";
+ }
+
+ /* ----------------------------------------------------------------------
+ * paramNeedsEscape()
+ *
+ * A helper for goFunctionWrapper that returns whether a parameter
+ * needs to explicitly escape. This is true if the parameter has a
+ * non-empty argout or freearg typemap, because in those cases the
+ * Go argument might be or contain a pointer. We need to ensure
+ * that that pointer does not point into the stack, which means that
+ * it needs to escape.
+ * ---------------------------------------------------------------------- */
+ bool paramNeedsEscape(Parm *p) {
+ String *argout = Getattr(p, "tmap:argout");
+ String *freearg = Getattr(p, "tmap:freearg");
+ if ((!argout || Len(argout) == 0) && (!freearg || Len(freearg) == 0)) {
+ return false;
+ }
+ // If a C++ type is represented as an interface type in Go, then
+ // we don't care whether it escapes, because we know that the
+ // pointer is a C++ pointer.
+ if (goTypeIsInterface(p, Getattr(p, "type"))) {
+ return false;
+ }
+ return true;
+ }
+
+ /* ----------------------------------------------------------------------
+ * gcFunctionWrapper()
+ *
+ * This is used for 6g/8g, not for gccgo. Write out the function
+ * redirector that will be compiled with 6c/8c. This used to write
+ * out a real function wrapper, but that has moved into Go code.
+ * ---------------------------------------------------------------------- */
+
+ int gcFunctionWrapper(String *wname) {
+ Wrapper *f = NewWrapper();
+
+ Printv(f->def, "#pragma dynimport ", wname, " ", wname, " \"\"\n", NULL);
+ Printv(f->def, "#pragma cgo_import_static ", wname, "\n", NULL);
+ Printv(f->def, "extern void ", wname, "(void*);\n", NULL);
+ // Declare this as a uintptr, since it is not a pointer into the
+ // Go heap.
+ // \xc2\xb7 is UTF-8 for U+00B7 which is Unicode 'Middle Dot'
+ Printv(f->def, "uintptr \xc2\xb7", wname, " = (uintptr)", wname, ";\n", NULL);
+
+ Wrapper_print(f, f_gc_wrappers);
+
+ DelWrapper(f);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * gccFunctionWrapper()
+ *
+ * This is used for 6g/8g, not for gccgo. Write out the function
+ * wrapper which will be compiled with gcc. If the base parameter
+ * is not NULL, this is calls the base class method rather than
+ * executing the SWIG wrapper code.
+ * ---------------------------------------------------------------------- */
+
+ int gccFunctionWrapper(Node *n, List *base, String *wname, ParmList *parms, SwigType *result) {
+ Wrapper *f = NewWrapper();
+
+ Swig_save("gccFunctionWrapper", n, "parms", NULL);
+
+ Parm *base_parm = NULL;
+ if (base && !isStatic(n)) {
+ SwigType *base_type = Copy(getClassType());
+ SwigType_add_pointer(base_type);
+ base_parm = NewParm(base_type, NewString("arg1"), n);
+ set_nextSibling(base_parm, parms);
+ parms = base_parm;
+ }
+
+ emit_parameter_variables(parms, f);
+ emit_attach_parmmaps(parms, f);
+ int parm_count = emit_num_arguments(parms);
+ int required_count = emit_num_required(parms);
+ bool needs_swigargs = false;
+
+ 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.
+
+ String *swigargs = NewString("\tstruct swigargs {\n");
+
+ if (parm_count > required_count) {
+ needs_swigargs = true;
+ Printv(swigargs, "\t\tintgo _swig_optargc;\n", NULL);
+ }
+
+ Parm *p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+
+ String *ln = Getattr(p, "lname");
+ SwigType *pt = Getattr(p, "type");
+ String *ct = gcCTypeForGoValue(p, pt, ln);
+ Printv(swigargs, "\t\t\t", ct, ";\n", NULL);
+ needs_swigargs = true;
+ Delete(ct);
+
+ String *gn = NewStringf("_swig_go_%d", i);
+ ct = gcCTypeForGoValue(p, pt, gn);
+ Setattr(p, "emit:input", gn);
+ Wrapper_add_local(f, gn, ct);
+ Delete(ct);
+
+ p = nextParm(p);
+ }
+ if (SwigType_type(result) != T_VOID) {
+ Printv(swigargs, "\t\tlong : 0;\n", NULL);
+ String *ln = NewString(Swig_cresult_name());
+ String *ct = gcCTypeForGoValue(n, result, ln);
+ Delete(ln);
+ Printv(swigargs, "\t\t", ct, ";\n", NULL);
+ needs_swigargs = true;
+ Delete(ct);
+
+ ln = NewString("_swig_go_result");
+ ct = gcCTypeForGoValue(n, result, ln);
+ Wrapper_add_local(f, "_swig_go_result", ct);
+ Delete(ct);
+ Delete(ln);
+ }
+ Printv(swigargs, "\t} SWIGSTRUCTPACKED *swig_a = (struct swigargs *) swig_v;\n", NULL);
+
+ // Copy the input arguments out of the structure into the Go local
+ // variables.
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *ln = Getattr(p, "lname");
+ String *gn = Getattr(p, "emit:input");
+ Printv(f->code, "\t", gn, " = swig_a->", ln, ";\n", NULL);
+ p = nextParm(p);
+ }
+
+ // Apply the in typemaps.
+ 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 {
+ tm = Copy(tm);
+ String *gn = Getattr(p, "emit:input");
+ Replaceall(tm, "$input", gn);
+ if (i < required_count) {
+ Printv(f->code, "\t", tm, "\n", NULL);
+ } else {
+ Printf(f->code, "\tif (swig_a->_swig_optargc > %d) {\n", i - required_count);
+ Printv(f->code, "\t\t", tm, "\n", NULL);
+ Printv(f->code, "\t}\n", NULL);
+ }
+ Delete(tm);
+ }
+ p = nextParm(p);
+ }
+
+ Printv(f->code, "\n", NULL);
+
+ // Do the real work of the function.
+
+ checkConstraints(parms, f);
+
+ emitGoAction(n, base, parms, result, f);
+
+ argout(parms, f);
+
+ cleanupFunction(n, f, parms);
+
+ if (needs_swigargs)
+ {
+ Printv(f->locals, swigargs, NULL);
+ }
+
+ Printv(f->code, "}\n", NULL);
+
+ Wrapper_print(f, f_c_wrappers);
+
+ Swig_restore(n);
+
+ Delete(swigargs);
+ DelWrapper(f);
+ Delete(base_parm);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * gccgoFunctionWrapper()
+ *
+ * This is used for gccgo, not 6g/8g. Write out the function
+ * wrapper which will be compiled with gcc. If the base parameter
+ * is not NULL, this is calls the base class method rather than
+ * executing the SWIG wrapper code.
+ * ---------------------------------------------------------------------- */
+
+ int gccgoFunctionWrapper(Node *n, List *base, String *wname, ParmList *parms, SwigType *result) {
+ Wrapper *f = NewWrapper();
+
+ Swig_save("gccgoFunctionWrapper", n, "parms", NULL);
+
+ Parm *base_parm = NULL;
+ if (base && !isStatic(n)) {
+ SwigType *base_type = Copy(getClassType());
+ SwigType_add_pointer(base_type);
+ base_parm = NewParm(base_type, NewString("arg1"), n);
+ set_nextSibling(base_parm, parms);
+ parms = base_parm;
+ }
+
+ emit_parameter_variables(parms, f);
+ emit_attach_parmmaps(parms, f);
+ int parm_count = emit_num_arguments(parms);
+ int required_count = emit_num_required(parms);
+
+ emit_return_variable(n, result, f);
+
+ // Start the function definition.
+
+ String *fnname = NewString("");
+ Printv(fnname, "go_", wname, "(", NULL);
+
+ if (parm_count > required_count) {
+ Printv(fnname, "intgo _swig_optargc", NULL);
+ }
+
+ Parm *p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ SwigType *pt = Copy(Getattr(p, "type"));
+ if (SwigType_isarray(pt)) {
+ SwigType_del_array(pt);
+ SwigType_add_pointer(pt);
+ }
+ String *pn = NewString("g");
+ Append(pn, Getattr(p, "lname"));
+ String *ct = gccgoCTypeForGoValue(p, pt, pn);
+ if (i > 0 || parm_count > required_count) {
+ Printv(fnname, ", ", NULL);
+ }
+ Printv(fnname, ct, NULL);
+ Delete(ct);
+ Delete(pn);
+ Delete(pt);
+ p = nextParm(p);
+ }
+
+ Printv(fnname, ")", NULL);
+
+ String *fndef = NewString("");
+ if (SwigType_type(result) == T_VOID) {
+ Printv(fndef, "void ", fnname, NULL);
+ } else {
+ String *ct = gccgoCTypeForGoValue(n, result, fnname);
+ Printv(fndef, ct, NULL);
+ Delete(ct);
+ }
+
+ Printv(f->def, fndef, " __asm__(\"", go_prefix, "_", wname, "\");\n", NULL);
+
+ Printv(f->def, fndef, " {\n", NULL);
+
+ Delete(fnname);
+ Delete(fndef);
+
+ if (SwigType_type(result) != T_VOID) {
+ String *ln = NewString("_swig_go_result");
+ String *ct = gccgoCTypeForGoValue(n, result, ln);
+ Wrapper_add_local(f, "_swig_go_result", ct);
+ Delete(ct);
+ Delete(ln);
+ }
+
+ // Copy the parameters into the variables which hold their values,
+ // applying appropriate transformations.
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+
+ String *tm = Getattr(p, "tmap:in");
+ if (!tm) {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number,
+ "Unable to use type %s as a function argument\n", SwigType_str(Getattr(p, "type"), 0));
+ } else {
+ String *ln = Getattr(p, "lname");
+ String *pn = NewString("g");
+ Append(pn, ln);
+ tm = Copy(tm);
+ Replaceall(tm, "$input", pn);
+ Setattr(p, "emit:input", pn);
+ if (i < required_count) {
+ Printv(f->code, " ", tm, "\n", NULL);
+ } else {
+ Printf(f->code, " if (_swig_optargc > %d) {\n", i - required_count);
+ Printv(f->code, " ", tm, "\n", NULL);
+ Printv(f->code, " }\n", NULL);
+ }
+ Delete(tm);
+ }
+
+ p = nextParm(p);
+ }
+
+ Printv(f->code, "\n", NULL);
+
+ // Do the real work of the function.
+
+ checkConstraints(parms, f);
+
+ emitGoAction(n, base, parms, result, f);
+
+ argout(parms, f);
+
+ cleanupFunction(n, f, parms);
+
+ if (SwigType_type(result) != T_VOID) {
+ Printv(f->code, " return _swig_go_result;\n", NULL);
+ }
+
+ Printv(f->code, "}\n", NULL);
+
+ Wrapper_print(f, f_c_wrappers);
+
+ Swig_restore(n);
+
+ DelWrapper(f);
+ Delete(base_parm);
+
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * checkConstraints()
+ *
+ * Check parameter constraints if any. This is used for the C/C++
+ * function. This assumes that each parameter has an "emit:input"
+ * property with the name to use to refer to that parameter.
+ * ----------------------------------------------------------------------- */
+
+ void checkConstraints(ParmList *parms, Wrapper *f) {
+ Parm *p = parms;
+ while (p) {
+ String *tm = Getattr(p, "tmap:check");
+ if (!tm) {
+ p = nextSibling(p);
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(f->code, tm, "\n\n", NULL);
+ Delete(tm);
+ p = Getattr(p, "tmap:check:next");
+ }
+ }
+ }
+
+ /* -----------------------------------------------------------------------
+ * emitGoAction()
+ *
+ * Emit the action of the function. This is used for the C/C++ function.
+ * ----------------------------------------------------------------------- */
+
+ void emitGoAction(Node *n, List *base, ParmList *parms, SwigType *result, Wrapper *f) {
+ if (!gccgo_flag && !cgo_flag && SwigType_type(result) != T_VOID) {
+ Wrapper_add_local(f, "swig_stktop", "char *swig_stktop");
+ Printv(f->code, "\tswig_stktop = _swig_topofstack();\n", NULL);
+ }
+ String *actioncode;
+ if (!base || isStatic(n)) {
+ Swig_director_emit_dynamic_cast(n, f);
+ actioncode = emit_action(n);
+ } else {
+ // Call the base class method.
+ actioncode = NewString("");
+
+ String *current = NewString("");
+ if (!gccgo_flag && !cgo_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"));
+ Replace(code, Getattr(parms, "lname"), current, DOH_REPLACE_ANY | DOH_REPLACE_ID);
+ Delete(current);
+ Printv(actioncode, code, "\n", NULL);
+ }
+
+ Swig_save("emitGoAction", n, "type", "tmap:out", NULL);
+
+ Setattr(n, "type", result);
+
+ String *tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode);
+ if (!tm) {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s\n", SwigType_str(result, 0));
+ } else {
+ Replaceall(tm, "$result", "_swig_go_result");
+ if (GetFlag(n, "feature:new")) {
+ Replaceall(tm, "$owner", "1");
+ } else {
+ Replaceall(tm, "$owner", "0");
+ }
+ Printv(f->code, tm, "\n", NULL);
+ Delete(tm);
+ }
+
+ if (!gccgo_flag && !cgo_flag && SwigType_type(result) != T_VOID) {
+ // If the function called back into the Go code, the stack might
+ // have been copied. We need to adjust swig_a accordingly here.
+ // This is what cgo does.
+ Printv(f->code, "\tswig_a = (struct swigargs*)((char*)swig_a + (_swig_topofstack() - swig_stktop));\n", NULL);
+ Printv(f->code, "\tswig_a->", Swig_cresult_name(), " = ", "_swig_go_result;\n", NULL);
+ }
+
+ Swig_restore(n);
+ }
+
+ /* -----------------------------------------------------------------------
+ * argout()
+ *
+ * Handle argument output code if any. This is used for the C/C++
+ * function. This assumes that each parameter has an "emit:input"
+ * property with the name to use to refer to that parameter.
+ * ----------------------------------------------------------------------- */
+
+ void argout(ParmList *parms, Wrapper *f) {
+ Parm *p = parms;
+ while (p) {
+ String *tm = Getattr(p, "tmap:argout");
+ if (!tm) {
+ p = nextSibling(p);
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$result", Swig_cresult_name());
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(f->code, tm, "\n", NULL);
+ Delete(tm);
+ p = Getattr(p, "tmap:argout:next");
+ }
+ }
+ }
+
+ /* -----------------------------------------------------------------------
+ * goargout()
+ *
+ * Handle Go argument output code if any. This is used for the Go
+ * function. This assumes that each parameter has an "emit:goinput"
+ * property with the name to use to refer to that parameter.
+ * ----------------------------------------------------------------------- */
+
+ void goargout(ParmList *parms) {
+ Parm *p = parms;
+ while (p) {
+ String *tm = Getattr(p, "tmap:goargout");
+ if (!tm) {
+ p = nextSibling(p);
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$result", "swig_r");
+ Replaceall(tm, "$input", Getattr(p, "emit:goinput"));
+ Printv(f_go_wrappers, tm, "\n", NULL);
+ Delete(tm);
+ p = Getattr(p, "tmap:goargout:next");
+ }
+ }
+
+ // When using cgo, if we need to memcpy a parameter to pass it to
+ // the C code, the compiler may think that the parameter is not
+ // live during the function call. If the garbage collector runs
+ // while the C/C++ function is running, the parameter may be
+ // freed. Force the compiler to see the parameter as live across
+ // the C/C++ function.
+ if (cgo_flag) {
+ int parm_count = emit_num_arguments(parms);
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ bool c_struct_type;
+ Delete(cgoTypeForGoValue(p, Getattr(p, "type"), &c_struct_type));
+ if (c_struct_type) {
+ Printv(f_go_wrappers, "\tif Swig_escape_always_false {\n", NULL);
+ Printv(f_go_wrappers, "\t\tSwig_escape_val = ", Getattr(p, "emit:goinput"), "\n", NULL);
+ Printv(f_go_wrappers, "\t}\n", NULL);
+ }
+ p = nextParm(p);
+ }
+ }
+ }
+
+ /* -----------------------------------------------------------------------
+ * freearg()
+ *
+ * Handle argument cleanup code if any. This is used for the C/C++
+ * function. This assumes that each parameter has an "emit:input"
+ * property with the name to use to refer to that parameter.
+ * ----------------------------------------------------------------------- */
+
+ String *freearg(ParmList *parms) {
+ String *ret = NewString("");
+ Parm *p = parms;
+ while (p) {
+ String *tm = Getattr(p, "tmap:freearg");
+ if (!tm) {
+ p = nextSibling(p);
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(ret, tm, "\n", NULL);
+ Delete(tm);
+ p = Getattr(p, "tmap:freearg:next");
+ }
+ }
+ return ret;
+ }
+
+ /* -----------------------------------------------------------------------
+ * cleanupFunction()
+ *
+ * Final function cleanup code.
+ * ----------------------------------------------------------------------- */
+
+ void cleanupFunction(Node *n, Wrapper *f, ParmList *parms) {
+ String *cleanup = freearg(parms);
+ Printv(f->code, cleanup, NULL);
+
+ if (GetFlag(n, "feature:new")) {
+ String *tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0);
+ if (tm) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printv(f->code, tm, "\n", NULL);
+ Delete(tm);
+ }
+ }
+
+ Replaceall(f->code, "$cleanup", cleanup);
+ Delete(cleanup);
+
+ /* See if there is any return cleanup code */
+ String *tm;
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+
+ Replaceall(f->code, "$symname", Getattr(n, "sym:name"));
+ }
+
+ /* -----------------------------------------------------------------------
+ * variableHandler()
+ *
+ * This exists just to set the making_variable_wrappers flag.
+ * ----------------------------------------------------------------------- */
+
+ virtual int variableHandler(Node *n) {
+ assert(!making_variable_wrappers);
+ making_variable_wrappers = true;
+ int r = Language::variableHandler(n);
+ making_variable_wrappers = false;
+ return r;
+ }
+
+ /* -----------------------------------------------------------------------
+ * constantWrapper()
+ *
+ * Product a const declaration.
+ * ------------------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ SwigType *type = Getattr(n, "type");
+
+ if (!SwigType_issimple(type) && SwigType_type(type) != T_STRING) {
+ return goComplexConstant(n, type);
+ }
+
+ if (Swig_storage_isstatic(n)) {
+ return goComplexConstant(n, type);
+ }
+
+ String *go_name = buildGoName(Getattr(n, "sym:name"), false, false);
+
+ String *tm = goType(n, type);
+ String *value = Getattr(n, "value");
+
+ String *copy = NULL;
+ if (SwigType_type(type) == T_BOOL) {
+ if (Cmp(value, "true") != 0 && Cmp(value, "false") != 0) {
+ return goComplexConstant(n, type);
+ }
+ } else if (SwigType_type(type) == T_STRING || SwigType_type(type) == T_CHAR) {
+ // Backslash sequences are somewhat different in Go and C/C++.
+ if (Strchr(value, '\\') != 0) {
+ return goComplexConstant(n, type);
+ }
+ } else {
+ // Accept a 0x prefix, and strip combinations of u and l
+ // suffixes. Otherwise accept digits, decimal point, and
+ // exponentiation. Treat anything else as too complicated to
+ // handle as a Go constant.
+ char *p = Char(value);
+ int len = (int)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) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ 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, getModuleName(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;
+ }
+
+ Swig_require("enumvalueDeclaration", n, "*sym:name", NIL);
+ Node *parent = parentNode(n);
+
+ if (Getattr(parent, "unnamed")) {
+ Setattr(n, "type", NewString("int"));
+ } else {
+ Setattr(n, "type", Getattr(parent, "enumtype"));
+ }
+
+ if (GetFlag(parent, "scopedenum")) {
+ String *symname = Getattr(n, "sym:name");
+ symname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
+ Setattr(n, "sym:name", symname);
+ Delete(symname);
+ }
+
+ int ret = goComplexConstant(n, Getattr(n, "type"));
+ Swig_restore(n);
+ return ret;
+ }
+
+ /* -----------------------------------------------------------------------
+ * 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 *rawval = Getattr(n, "rawval");
+ if (rawval && Len(rawval)) {
+ // Based on Swig_VargetToFunction
+ String *nname = NewStringf("(%s)", rawval);
+ String *call;
+ if (SwigType_isclass(type)) {
+ call = NewStringf("%s", nname);
+ } else {
+ call = SwigType_lcaststr(type, nname);
+ }
+ String *cres = Swig_cresult(type, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ Delete(nname);
+ Delete(call);
+ Delete(cres);
+ } else {
+ 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) {
+ Printv(get, "(char *)", NULL);
+ 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);
+ Delete(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);
+ Append(wname, unique_id);
+ Setattr(n, "wrap:name", wname);
+
+ int r = makeWrappers(n, sname, go_name, NULL, wname, NULL, NULL, type, true);
+
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ String *t = goType(n, type);
+ Printv(f_go_wrappers, "var ", varname, " ", t, " = ", go_name, "()\n", NULL);
+
+ Delete(varname);
+ Delete(t);
+ Delete(go_name);
+ Delete(sname);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ *
+ * For a C++ class, in Go we generate both a struct and an
+ * interface. The interface will declare all the class public
+ * methods. We will define all the methods on the struct, so that
+ * the struct meets the interface. We then expect users of the
+ * class to use the interface.
+ * ------------------------------------------------------------ */
+
+ virtual int classHandler(Node *n) {
+ class_node = n;
+
+ List *baselist = Getattr(n, "bases");
+ bool has_base_classes = baselist && Len(baselist) > 0;
+
+ String *name = Getattr(n, "sym:name");
+
+ String *go_name = exportedName(name);
+
+ if (!checkNameConflict(go_name, n, NULL)) {
+ Delete(go_name);
+ SetFlag(n, "go:conflict");
+ return SWIG_NOWRAP;
+ }
+
+ String *go_type_name = goCPointerType(Getattr(n, "classtypeobj"), true);
+
+ class_name = name;
+ class_receiver = go_type_name;
+ class_methods = NewHash();
+
+ int isdir = GetFlag(n, "feature:director");
+ int isnodir = GetFlag(n, "feature:nodirector");
+ bool is_director = isdir && !isnodir;
+
+ Printv(f_go_wrappers, "type ", go_type_name, " uintptr\n\n", NULL);
+
+ // A method to return the pointer to the C++ class. This is used
+ // by generated code to convert between the interface and the C++
+ // value.
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") Swigcptr() uintptr {\n", NULL);
+ Printv(f_go_wrappers, "\treturn (uintptr)(p)\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ // A method used as a marker for the class, to avoid invalid
+ // interface conversions when using multiple inheritance.
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") SwigIs", go_name, "() {\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ if (is_director) {
+ // Return the interface passed to the NewDirector function.
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") DirectorInterface() interface{} {\n", NULL);
+ Printv(f_go_wrappers, "\treturn nil\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+ }
+
+ // We have seen a definition for this type.
+ Setattr(defined_types, go_name, go_name);
+ Setattr(defined_types, go_type_name, go_type_name);
+
+ interfaces = NewString("");
+
+ int r = Language::classHandler(n);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ if (has_base_classes) {
+ // For each method defined in a base class but not defined in
+ // this class, we need to define the method in this class. We
+ // can't use anonymous field inheritance because it works
+ // differently in Go and in C++.
+
+ Hash *local = NewHash();
+ for (Node *ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
+
+ if (!is_public(ni)) {
+ continue;
+ }
+
+ String *type = Getattr(ni, "nodeType");
+ if (Cmp(type, "constructor") == 0 || Cmp(type, "destructor") == 0) {
+ continue;
+ }
+
+ String *cname = Getattr(ni, "sym:name");
+ if (!cname) {
+ cname = Getattr(ni, "name");
+ }
+ if (cname) {
+ Setattr(local, cname, NewString(""));
+ }
+ }
+
+ for (Iterator b = First(baselist); b.item; b = Next(b)) {
+ List *bases = NewList();
+ Append(bases, Getattr(b.item, "classtype"));
+ int r = addBase(n, b.item, bases, local);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ Delete(bases);
+ }
+
+ Delete(local);
+
+ Hash *parents = NewHash();
+ addFirstBaseInterface(n, parents, baselist);
+ int r = addExtraBaseInterfaces(n, parents, baselist);
+ Delete(parents);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ Printv(f_go_wrappers, "type ", go_name, " interface {\n", NULL);
+ Printv(f_go_wrappers, "\tSwigcptr() uintptr\n", NULL);
+ Printv(f_go_wrappers, "\tSwigIs", go_name, "()\n", NULL);
+
+ if (is_director) {
+ Printv(f_go_wrappers, "\tDirectorInterface() interface{}\n", NULL);
+ }
+
+ Append(f_go_wrappers, interfaces);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+ Delete(interfaces);
+
+ interfaces = NULL;
+ class_name = NULL;
+ class_receiver = NULL;
+ class_node = NULL;
+ Delete(class_methods);
+ class_methods = NULL;
+
+ Delete(go_type_name);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * addBase()
+ *
+ * Implement methods and members defined in a parent class for a
+ * child class.
+ * ------------------------------------------------------------ */
+
+ int addBase(Node *n, Node *base, List *bases, Hash *local) {
+ if (GetFlag(base, "feature:ignore")) {
+ return SWIG_OK;
+ }
+
+ for (Node *ni = Getattr(base, "firstChild"); ni; ni = nextSibling(ni)) {
+
+ if (GetFlag(ni, "feature:ignore")) {
+ continue;
+ }
+
+ if (!is_public(ni)) {
+ continue;
+ }
+
+ String *type = Getattr(ni, "nodeType");
+ if (Strcmp(type, "constructor") == 0 || Strcmp(type, "destructor") == 0 || Strcmp(type, "enum") == 0 || Strcmp(type, "using") == 0 || Strcmp(type, "classforward") == 0 || Strcmp(type, "template") == 0) {
+ continue;
+ }
+ String *storage = Getattr(ni, "storage");
+ if (storage && (Strcmp(storage, "typedef") == 0 || Strcmp(storage, "friend") == 0)) {
+ continue;
+ }
+
+ String *mname = Getattr(ni, "sym:name");
+ if (!mname) {
+ continue;
+ }
+
+ String *lname = Getattr(ni, "name");
+ if (Getattr(class_methods, lname)) {
+ continue;
+ }
+ if (Getattr(local, lname)) {
+ continue;
+ }
+ Setattr(local, lname, NewString(""));
+
+ String *ty = NewString(Getattr(ni, "type"));
+ SwigType_push(ty, Getattr(ni, "decl"));
+ String *fullty = SwigType_typedef_resolve_all(ty);
+ bool is_function = SwigType_isfunction(fullty) ? true : false;
+ Delete(ty);
+ Delete(fullty);
+
+ if (is_function) {
+ int r = goBaseMethod(n, bases, ni);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ if (Getattr(ni, "sym:overloaded")) {
+ for (Node *on = Getattr(ni, "sym:nextSibling"); on; on = Getattr(on, "sym:nextSibling")) {
+ r = goBaseMethod(n, bases, on);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ String *receiver = class_receiver;
+ bool is_static = isStatic(ni);
+ if (is_static) {
+ receiver = NULL;
+ }
+ String *go_name = buildGoName(Getattr(ni, "sym:name"), is_static, false);
+ r = makeDispatchFunction(ni, go_name, receiver, is_static, NULL, false);
+ Delete(go_name);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+ } else {
+ int r = goBaseVariable(n, bases, ni);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+ }
+
+ List *baselist = Getattr(base, "bases");
+ if (baselist && Len(baselist) > 0) {
+ for (Iterator b = First(baselist); b.item; b = Next(b)) {
+ List *nb = Copy(bases);
+ Append(nb, Getattr(b.item, "classtype"));
+ int r = addBase(n, b.item, nb, local);
+ Delete(nb);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * goBaseMethod()
+ *
+ * Implement a method defined in a parent class for a child class.
+ * ------------------------------------------------------------ */
+
+ int goBaseMethod(Node *method_class, List *bases, Node *method) {
+ String *symname = Getattr(method, "sym:name");
+ if (!validIdentifier(symname)) {
+ return SWIG_OK;
+ }
+
+ String *name = NewString("");
+ Printv(name, Getattr(method_class, "sym:name"), "_", symname, NULL);
+
+ bool is_static = isStatic(method);
+
+ String *go_name = buildGoName(name, is_static, false);
+
+ String *overname = NULL;
+ if (Getattr(method, "sym:overloaded")) {
+ overname = Getattr(method, "sym:overname");
+ }
+ String *wname = Swig_name_wrapper(name);
+ if (overname) {
+ Append(wname, overname);
+ }
+ Append(wname, unique_id);
+
+ 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);
+
+ int flags = Extend | SmartPointer | use_naturalvar_mode(var);
+ if (isNonVirtualProtectedAccess(var)) {
+ flags |= CWRAP_ALL_PROTECTED_ACCESS;
+ }
+
+ // Copied from Swig_wrapped_member_var_type.
+ if (SwigType_isclass(vt)) {
+ if (flags & CWRAP_NATURAL_VAR) {
+ if (CPlusPlus) {
+ if (!SwigType_isconst(vt)) {
+ SwigType_add_qualifier(vt, "const");
+ }
+ SwigType_add_reference(vt);
+ }
+ } else {
+ SwigType_add_pointer(vt);
+ }
+ }
+
+ 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);
+ Append(wname, unique_id);
+ 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);
+ Append(wname, unique_id);
+
+ int r = makeWrappers(var, mname_get, go_name, NULL, wname, bases, NULL, vt, false);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ Delete(wname);
+ Delete(mname_get);
+ Delete(go_name);
+ Delete(mname);
+ Delete(var_name);
+ Delete(var_type);
+ Delete(vt);
+
+ Swig_restore(var);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * addFirstBaseInterface()
+ *
+ * When a C++ class uses multiple inheritance, we can use the C++
+ * pointer for the first base class but not for any subsequent base
+ * classes. However, the Go interface will match the interface for
+ * all the base classes. To avoid accidentally treating a class as
+ * a pointer to a base class other than the first one, we use an
+ * isClassname method. This function adds those methods as
+ * required.
+ *
+ * For convenience when using multiple inheritance, we also add
+ * functions to retrieve the base class pointers.
+ * ------------------------------------------------------------ */
+
+ void addFirstBaseInterface(Node *n, Hash *parents, List *bases) {
+ if (!bases || Len(bases) == 0) {
+ return;
+ }
+ Iterator b = First(bases);
+ if (!GetFlag(b.item, "feature:ignore")) {
+ String *go_name = buildGoName(Getattr(n, "sym:name"), false, false);
+ String *go_type_name = goCPointerType(Getattr(n, "classtypeobj"), true);
+ String *go_base_name = exportedName(Getattr(b.item, "sym:name"));
+ String *go_base_type = goType(n, Getattr(b.item, "classtypeobj"));
+ String *go_base_type_name = goCPointerType(Getattr(b.item, "classtypeobj"), true);
+
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") SwigIs", go_base_name, "() {\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(interfaces, "\tSwigIs", go_base_name, "()\n", NULL);
+
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") SwigGet", go_base_name, "() ", go_base_type, " {\n", NULL);
+ Printv(f_go_wrappers, "\treturn ", go_base_type_name, "(p.Swigcptr())\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(interfaces, "\tSwigGet", go_base_name, "() ", go_base_type, "\n", NULL);
+
+ Setattr(parents, go_base_name, NewString(""));
+
+ Delete(go_name);
+ Delete(go_type_name);
+ Delete(go_base_type);
+ Delete(go_base_type_name);
+ }
+
+ addFirstBaseInterface(n, parents, Getattr(b.item, "bases"));
+ }
+
+ /* ------------------------------------------------------------
+ * addExtraBaseInterfaces()
+ *
+ * Add functions to retrieve the base class pointers for all base
+ * classes other than the first.
+ * ------------------------------------------------------------ */
+
+ int addExtraBaseInterfaces(Node *n, Hash *parents, List *bases) {
+ Iterator b = First(bases);
+
+ Node *fb = b.item;
+
+ for (b = Next(b); b.item; b = Next(b)) {
+ if (GetFlag(b.item, "feature:ignore")) {
+ continue;
+ }
+
+ String *go_base_name = exportedName(Getattr(b.item, "sym:name"));
+
+ Swig_save("addExtraBaseInterface", n, "wrap:action", "wrap:name", "wrap:parms", NULL);
+
+ SwigType *type = Copy(Getattr(n, "classtypeobj"));
+ SwigType_add_pointer(type);
+ Parm *parm = NewParm(type, "self", n);
+ Setattr(n, "wrap:parms", parm);
+
+ String *pn = Swig_cparm_name(parm, 0);
+ String *action = NewString("");
+ Printv(action, Swig_cresult_name(), " = (", Getattr(b.item, "classtype"), "*)", pn, ";", NULL);
+ Delete(pn);
+
+ Setattr(n, "wrap:action", action);
+
+ String *name = Copy(class_name);
+ Append(name, "_SwigGet");
+ Append(name, go_base_name);
+
+ String *go_name = NewString("SwigGet");
+ String *c1 = exportedName(go_base_name);
+ Append(go_name, c1);
+ Delete(c1);
+
+ String *wname = Swig_name_wrapper(name);
+ Append(wname, unique_id);
+ Setattr(n, "wrap:name", wname);
+
+ SwigType *result = Copy(Getattr(b.item, "classtypeobj"));
+ SwigType_add_pointer(result);
+
+ int r = makeWrappers(n, name, go_name, NULL, wname, NULL, parm, result,
+ false);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ Swig_restore(n);
+
+ Setattr(parents, go_base_name, NewString(""));
+
+ Delete(go_name);
+ Delete(type);
+ Delete(parm);
+ Delete(action);
+ Delete(result);
+
+ String *ns = NewString("");
+ addParentExtraBaseInterfaces(n, parents, b.item, false, ns);
+ Delete(ns);
+ }
+
+ if (!GetFlag(fb, "feature:ignore")) {
+ String *ns = NewString("");
+ addParentExtraBaseInterfaces(n, parents, fb, true, ns);
+ Delete(ns);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * addParentExtraBaseInterfaces()
+ *
+ * Add functions to retrieve the base class pointers for all base
+ * classes of parents other than the first base class at each level.
+ * ------------------------------------------------------------ */
+
+ void addParentExtraBaseInterfaces(Node *n, Hash *parents, Node *base, bool is_base_first, String *sofar) {
+ List *baselist = Getattr(base, "bases");
+ if (!baselist || Len(baselist) == 0) {
+ return;
+ }
+
+ String *go_this_base_name = exportedName(Getattr(base, "sym:name"));
+
+ String *sf = NewString("");
+ Printv(sf, sofar, ".SwigGet", go_this_base_name, "()", NULL);
+
+ Iterator b = First(baselist);
+
+ if (is_base_first) {
+ if (!b.item) {
+ return;
+ }
+ if (!GetFlag(b.item, "feature:ignore")) {
+ addParentExtraBaseInterfaces(n, parents, b.item, true, sf);
+ }
+
+ b = Next(b);
+ }
+
+ String *go_name = buildGoName(Getattr(n, "sym:name"), false, false);
+ String *go_type_name = goCPointerType(Getattr(n, "classtypeobj"), true);
+
+ for (; b.item; b = Next(b)) {
+ if (GetFlag(b.item, "feature:ignore")) {
+ continue;
+ }
+
+ String *go_base_name = exportedName(Getattr(b.item, "sym:name"));
+
+ if (!Getattr(parents, go_base_name)) {
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") SwigGet", go_base_name, "() ", go_base_name, " {\n", NULL);
+ Printv(f_go_wrappers, "\treturn p", sf, ".SwigGet", go_base_name, "()\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(interfaces, "\tSwigGet", go_base_name, "() ", go_base_name, "\n", NULL);
+
+ addParentExtraBaseInterfaces(n, parents, b.item, false, sf);
+
+ Setattr(parents, go_base_name, NewString(""));
+ }
+ }
+
+ Delete(go_name);
+ Delete(go_type_name);
+ Delete(go_this_base_name);
+ Delete(sf);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorInit
+ *
+ * Add support for a director class.
+ *
+ * Virtual inheritance is different in Go and C++. We implement
+ * director classes by defining a new function in Go,
+ * NewDirectorClassname, which takes a empty interface value and
+ * creates an instance of a new child class. The new child class
+ * refers all methods back to Go. The Go code checks whether the
+ * value passed to NewDirectorClassname implements that method; if
+ * it does, it calls it, otherwise it calls back into C++.
+ * ------------------------------------------------------------ */
+
+ int classDirectorInit(Node *n) {
+ // Because we use a different function to handle inheritance in
+ // Go, ordinary creations of the object should not create a
+ // director object.
+ Delete(director_ctor_code);
+ director_ctor_code = NewString("$nondirector_new");
+
+ class_node = n;
+
+ String *name = Getattr(n, "sym:name");
+
+ assert(!class_name);
+ class_name = name;
+
+ String *go_name = exportedName(name);
+
+ String *go_type_name = goCPointerType(Getattr(n, "classtypeobj"), true);
+
+ assert(!class_receiver);
+ class_receiver = go_type_name;
+
+ String *director_struct_name = NewString("_swig_Director");
+ Append(director_struct_name, go_name);
+
+ String *cxx_director_name = NewString("SwigDirector_");
+ Append(cxx_director_name, name);
+
+ // The Go type of the director class.
+ Printv(f_go_wrappers, "type ", director_struct_name, " struct {\n", NULL);
+ Printv(f_go_wrappers, "\t", go_type_name, "\n", NULL);
+ Printv(f_go_wrappers, "\tv interface{}\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(f_go_wrappers, "func (p *", director_struct_name, ") Swigcptr() uintptr {\n", NULL);
+ Printv(f_go_wrappers, "\treturn p.", go_type_name, ".Swigcptr()\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(f_go_wrappers, "func (p *", director_struct_name, ") SwigIs", go_name, "() {\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(f_go_wrappers, "func (p *", director_struct_name, ") DirectorInterface() interface{} {\n", NULL);
+ Printv(f_go_wrappers, "\treturn p.v\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ // Start defining the director class.
+ Printv(f_c_directors_h, "class ", cxx_director_name, " : public ", Getattr(n, "classtype"), "\n", NULL);
+ Printv(f_c_directors_h, "{\n", NULL);
+ Printv(f_c_directors_h, " public:\n", NULL);
+
+ Delete(director_struct_name);
+ Delete(cxx_director_name);
+
+ class_methods = NewHash();
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorConstructor
+ *
+ * Emit a constructor for a director class.
+ * ------------------------------------------------------------ */
+
+ int classDirectorConstructor(Node *n) {
+ bool is_ignored = GetFlag(n, "feature:ignore") ? true : false;
+
+ String *name = Getattr(n, "sym:name");
+ if (!name) {
+ assert(is_ignored);
+ name = Getattr(n, "name");
+ }
+
+ String *overname = NULL;
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ }
+
+ String *go_name = exportedName(name);
+
+ ParmList *parms = Getattr(n, "parms");
+ Setattr(n, "wrap:parms", parms);
+
+ String *cn = exportedName(Getattr(parentNode(n), "sym:name"));
+
+ String *go_type_name = goCPointerType(Getattr(parentNode(n), "classtypeobj"), true);
+
+ String *director_struct_name = NewString("_swig_Director");
+ Append(director_struct_name, cn);
+
+ String *fn_name = NewString("_swig_NewDirector");
+ Append(fn_name, cn);
+ Append(fn_name, go_name);
+
+ if (!overname && !is_ignored) {
+ if (!checkNameConflict(fn_name, n, NULL)) {
+ return SWIG_NOWRAP;
+ }
+ }
+
+ String *fn_with_over_name = Copy(fn_name);
+ if (overname) {
+ Append(fn_with_over_name, overname);
+ }
+
+ String *wname = Swig_name_wrapper(fn_name);
+
+ if (overname) {
+ Append(wname, overname);
+ }
+ Append(wname, unique_id);
+ Setattr(n, "wrap:name", wname);
+
+ bool is_static = isStatic(n);
+
+ Wrapper *dummy = NewWrapper();
+ emit_attach_parmmaps(parms, dummy);
+ DelWrapper(dummy);
+
+ Swig_typemap_attach_parms("gotype", parms, NULL);
+ Swig_typemap_attach_parms("goin", parms, NULL);
+ Swig_typemap_attach_parms("goargout", parms, NULL);
+ Swig_typemap_attach_parms("imtype", parms, NULL);
+ int parm_count = emit_num_arguments(parms);
+
+ String *func_name = NewString("NewDirector");
+ Append(func_name, go_name);
+
+ String *func_with_over_name = Copy(func_name);
+ if (overname) {
+ Append(func_with_over_name, overname);
+ }
+
+ SwigType *first_type = NewString("int");
+ Parm *first_parm = NewParm(first_type, "swig_p", n);
+ set_nextSibling(first_parm, parms);
+ Setattr(first_parm, "lname", "p");
+
+ Parm *p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ Swig_cparm_name(p, i);
+ p = nextParm(p);
+ }
+
+ if (!is_ignored) {
+ if (cgo_flag) {
+ Printv(f_cgo_comment, "extern uintptr_t ", wname, "(int", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ bool c_struct_type;
+ String *ct = cgoTypeForGoValue(p, Getattr(p, "type"), &c_struct_type);
+ Printv(f_cgo_comment, ", ", ct, " ", Getattr(p, "lname"), NULL);
+ p = nextParm(p);
+ }
+ Printv(f_cgo_comment, ");\n", NULL);
+ } else {
+ // Declare the C++ wrapper.
+
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, "var ", wname, " unsafe.Pointer\n\n", NULL);
+ } else {
+ Printv(f_go_wrappers, "//extern ", go_prefix, "_", wname, "\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "func ", fn_with_over_name, "(_swig_director int", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *tm = goWrapperType(p, Getattr(p, "type"), false);
+ Printv(f_go_wrappers, ", _ ", tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ") (_swig_ret ", go_type_name, ")", NULL);
+
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, " {\n", NULL);
+ Printv(f_go_wrappers, "\t_swig_p := uintptr(unsafe.Pointer(&_swig_director))\n", NULL);
+ Printv(f_go_wrappers, "\t_cgo_runtime_cgocall(", wname, ", _swig_p)\n", NULL);
+ Printv(f_go_wrappers, "\treturn\n", NULL);
+ Printv(f_go_wrappers, "}", NULL);
+ }
+
+ Printv(f_go_wrappers, "\n\n", NULL);
+ }
+
+ // Write out the Go function that calls the wrapper.
+
+ Printv(f_go_wrappers, "func ", func_with_over_name, "(v interface{}", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", NULL);
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(f_go_wrappers, tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ") ", cn, " {\n", NULL);
+
+ Printv(f_go_wrappers, "\tp := &", director_struct_name, "{0, v}\n", NULL);
+
+ if (gccgo_flag && !cgo_flag) {
+ Printv(f_go_wrappers, "\tdefer SwigCgocallDone()\n", NULL);
+ Printv(f_go_wrappers, "\tSwigCgocall()\n", NULL);
+ }
+
+ String *call = NewString("");
+
+ Printv(call, "\tp.", class_receiver, " = ", NULL);
+ if (cgo_flag) {
+ Printv(call, go_type_name, "(C.", wname, "(C.int(swigDirectorAdd(p))", NULL);
+ } else {
+ Printv(call, fn_with_over_name, "(swigDirectorAdd(p)", NULL);
+ }
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ Printv(call, ", ", NULL);
+
+ p = getParm(p);
+ String *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+
+ String *ivar = NewStringf("_swig_i_%d", i);
+
+ String *goin = goGetattr(p, "tmap:goin");
+ if (goin == NULL) {
+ Printv(f_go_wrappers, "\t", ivar, " := ", ln, NULL);
+ if (goTypeIsInterface(p, pt)) {
+ Printv(f_go_wrappers, ".Swigcptr()", NULL);
+ }
+ Printv(f_go_wrappers, "\n", NULL);
+ } else {
+ String *itm = goImType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(f_go_wrappers, goin, "\n", NULL);
+ Delete(goin);
+ }
+
+ Setattr(p, "emit:goinput", ivar);
+
+ if (cgo_flag) {
+ bool c_struct_type;
+ String *ct = cgoTypeForGoValue(p, pt, &c_struct_type);
+ if (c_struct_type) {
+ Printv(call, "*(*C.", ct, ")(unsafe.Pointer(&", ivar, "))", NULL);
+ } else {
+ Printv(call, "C.", ct, "(", ivar, ")", NULL);
+ }
+ Delete(ct);
+ } else {
+ Printv(call, ivar, NULL);
+ }
+ p = nextParm(p);
+ }
+
+ Printv(call, ")", NULL);
+ if (cgo_flag) {
+ Printv(call, ")", NULL);
+ }
+
+ Printv(f_go_wrappers, call, "\n", NULL);
+
+ goargout(parms);
+
+ Printv(f_go_wrappers, "\treturn p\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ SwigType *result = Copy(Getattr(parentNode(n), "classtypeobj"));
+ SwigType_add_pointer(result);
+
+ Swig_save("classDirectorConstructor", n, "wrap:name", "wrap:action", NULL);
+
+ String *dwname = Swig_name_wrapper(name);
+ Append(dwname, unique_id);
+ Setattr(n, "wrap:name", dwname);
+
+ String *action = NewString("");
+ Printv(action, Swig_cresult_name(), " = new SwigDirector_", class_name, "(", NULL);
+ String *pname = Swig_cparm_name(NULL, 0);
+ Printv(action, pname, NULL);
+ Delete(pname);
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *pname = Swig_cparm_name(NULL, i + 1);
+ Printv(action, ", ", NULL);
+ if (SwigType_isreference(Getattr(p, "type"))) {
+ Printv(action, "*", NULL);
+ }
+ Printv(action, pname, NULL);
+ Delete(pname);
+ p = nextParm(p);
+ }
+ Printv(action, ");", NULL);
+ Setattr(n, "wrap:action", action);
+
+ if (cgo_flag) {
+ cgoWrapperInfo info;
+
+ info.n = n;
+ info.go_name = func_name;
+ info.overname = overname;
+ info.wname = wname;
+ info.base = NULL;
+ info.parms = first_parm;
+ info.result = result;
+ info.is_static = false;
+ info.receiver = NULL;
+ info.is_constructor = true;
+ info.is_destructor = false;
+
+ int r = cgoGccWrapper(&info);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ } else if (!gccgo_flag) {
+ int r = gcFunctionWrapper(wname);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ r = gccFunctionWrapper(n, NULL, wname, first_parm, result);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ } else {
+ int r = gccgoFunctionWrapper(n, NULL, wname, first_parm, result);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ Swig_restore(n);
+
+ Delete(result);
+ }
+
+ String *cxx_director_name = NewString("SwigDirector_");
+ Append(cxx_director_name, class_name);
+
+ String *decl = Swig_method_decl(NULL, Getattr(n, "decl"), cxx_director_name, first_parm, 0);
+ Printv(f_c_directors_h, " ", decl, ";\n", NULL);
+ Delete(decl);
+
+ decl = Swig_method_decl(NULL, Getattr(n, "decl"), cxx_director_name, first_parm, 0);
+ Printv(f_c_directors, cxx_director_name, "::", decl, "\n", NULL);
+ Delete(decl);
+
+ Printv(f_c_directors, " : ", Getattr(parentNode(n), "classtype"), "(", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0) {
+ Printv(f_c_directors, ", ", NULL);
+ }
+ String *pn = Getattr(p, "name");
+ assert(pn);
+ Printv(f_c_directors, pn, NULL);
+ p = nextParm(p);
+ }
+ Printv(f_c_directors, "),\n", NULL);
+ Printv(f_c_directors, " go_val(swig_p), swig_mem(0)\n", NULL);
+ Printv(f_c_directors, "{ }\n\n", NULL);
+
+ if (Getattr(n, "sym:overloaded") && !Getattr(n, "sym:nextSibling")) {
+ int r = makeDispatchFunction(n, func_name, cn, is_static, Getattr(parentNode(n), "classtypeobj"), false);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ Delete(cxx_director_name);
+ Delete(go_name);
+ Delete(cn);
+ Delete(go_type_name);
+ Delete(director_struct_name);
+ Delete(fn_name);
+ Delete(fn_with_over_name);
+ Delete(func_name);
+ Delete(func_with_over_name);
+ Delete(wname);
+ Delete(first_type);
+ Delete(first_parm);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDestructor
+ *
+ * Emit a destructor for a director class.
+ * ------------------------------------------------------------ */
+
+ int classDirectorDestructor(Node *n) {
+ if (!is_public(n)) {
+ return SWIG_OK;
+ }
+
+ bool is_ignored = GetFlag(n, "feature:ignore") ? true : false;
+
+ if (!is_ignored) {
+ String *fnname = NewString("DeleteDirector");
+ String *c1 = exportedName(class_name);
+ Append(fnname, c1);
+ Delete(c1);
+
+ String *wname = Swig_name_wrapper(fnname);
+ Append(wname, unique_id);
+
+ Setattr(n, "wrap:name", fnname);
+
+ Swig_DestructorToFunction(n, getNSpace(), getClassType(), CPlusPlus, Extend);
+
+ ParmList *parms = Getattr(n, "parms");
+ Setattr(n, "wrap:parms", parms);
+
+ String *result = NewString("void");
+ int r = makeWrappers(n, fnname, fnname, NULL, wname, NULL, parms, result, isStatic(n));
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ Delete(result);
+ Delete(fnname);
+ Delete(wname);
+ }
+
+ // Generate the destructor for the C++ director class. Since the
+ // Go code is keeping a pointer to the C++ object, we need to call
+ // back to the Go code to let it know that the C++ object is gone.
+
+ String *go_name = NewString("Swiggo_DeleteDirector_");
+ Append(go_name, class_name);
+
+ String *cn = exportedName(class_name);
+
+ String *director_struct_name = NewString("_swig_Director");
+ Append(director_struct_name, cn);
+
+ Printv(f_c_directors_h, " virtual ~SwigDirector_", class_name, "()", NULL);
+
+ String *throws = buildThrow(n);
+ if (throws) {
+ Printv(f_c_directors_h, " ", throws, NULL);
+ }
+
+ Printv(f_c_directors_h, ";\n", NULL);
+
+ String *director_sig = NewString("");
+
+ Printv(director_sig, "SwigDirector_", class_name, "::~SwigDirector_", class_name, "()", NULL);
+
+ if (throws) {
+ Printv(director_sig, " ", throws, NULL);
+ Delete(throws);
+ }
+
+ Printv(director_sig, "\n", NULL);
+ Printv(director_sig, "{\n", NULL);
+
+ if (is_ignored) {
+ Printv(f_c_directors, director_sig, NULL);
+ } else {
+ makeDirectorDestructorWrapper(go_name, director_struct_name, director_sig);
+ }
+
+ Printv(f_c_directors, " delete swig_mem;\n", NULL);
+
+ Printv(f_c_directors, "}\n\n", NULL);
+
+ Delete(director_sig);
+ Delete(go_name);
+ Delete(cn);
+ Delete(director_struct_name);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * makeDirectorDestructorWrapper
+ *
+ * Emit the function wrapper for the destructor of a director class.
+ * This writes director_sig to f_c_directors and leaves the function
+ * unfinished.
+ * ------------------------------------------------------------ */
+
+ void makeDirectorDestructorWrapper(String *go_name, String *director_struct_name, String *director_sig) {
+ if (cgo_flag) {
+ makeCgoDirectorDestructorWrapper(go_name, director_struct_name, director_sig);
+ return;
+ }
+
+ Printv(f_go_wrappers, "func ", go_name, "(c int) {\n", NULL);
+ if (gccgo_flag) {
+ Printv(f_go_wrappers, "\tSwigCgocallBack()\n", NULL);
+ Printv(f_go_wrappers, "\tdefer SwigCgocallBackDone()\n", NULL);
+ }
+ Printv(f_go_wrappers, "\tswigDirectorLookup(c).(*", director_struct_name, ").", class_receiver, " = 0\n", NULL);
+ Printv(f_go_wrappers, "\tswigDirectorDelete(c)\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ String *wname = NewString("_swiggo_wrap_DeleteDirector_");
+ Append(wname, class_name);
+
+ if (!gccgo_flag) {
+ Printv(f_c_directors, "extern \"C\" void ", wname, "(void*, int);\n", NULL);
+ } else {
+ Printv(f_c_directors, "extern \"C\" void ", wname, "(intgo) __asm__(\"", go_prefix, ".", go_name, "\");\n", NULL);
+ }
+
+ Printv(f_c_directors, director_sig, NULL);
+
+ if (!gccgo_flag) {
+ Printv(f_c_directors, " struct { intgo p; } SWIGSTRUCTPACKED a;\n", NULL);
+ Printv(f_c_directors, " a.p = go_val;\n", NULL);
+ Printv(f_c_directors, " crosscall2(", wname, ", &a, (int) sizeof a);\n", NULL);
+
+ Printv(f_gc_wrappers, "#pragma dynexport ", wname, " ", wname, "\n", NULL);
+ Printv(f_gc_wrappers, "#pragma cgo_export_static ", wname, " ", wname, "\n", NULL);
+ Printv(f_gc_wrappers, "#pragma textflag 7\n", NULL);
+ Printv(f_gc_wrappers, "extern void \xc2\xb7", go_name, "();\n", NULL);
+ Printv(f_gc_wrappers, "void\n", NULL);
+ Printv(f_gc_wrappers, wname, "(void *a, int32 n)\n", NULL);
+ Printv(f_gc_wrappers, "{\n", NULL);
+ Printv(f_gc_wrappers, "\truntime\xc2\xb7" "cgocallback(\xc2\xb7", go_name, ", a, n);\n", NULL);
+ Printv(f_gc_wrappers, "}\n\n", NULL);
+ } else {
+ Printv(f_c_directors, " ", wname, "(go_val);\n", NULL);
+ }
+
+ Delete(wname);
+ }
+
+ /* ------------------------------------------------------------
+ * makeCgoDirectorDestructorWrapper
+ *
+ * When using cgo, emit the function wrapper for the destructor of a
+ * director class.
+ * ------------------------------------------------------------ */
+
+ void makeCgoDirectorDestructorWrapper(String *go_name, String *director_struct_name, String *director_sig) {
+ String *wname = Copy(go_name);
+ Append(wname, unique_id);
+
+ Printv(f_go_wrappers, "//export ", wname, "\n", NULL);
+ Printv(f_go_wrappers, "func ", wname, "(c int) {\n", NULL);
+ Printv(f_go_wrappers, "\tswigDirectorLookup(c).(*", director_struct_name, ").", class_receiver, " = 0\n", NULL);
+ Printv(f_go_wrappers, "\tswigDirectorDelete(c)\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(f_c_directors, "extern \"C\" void ", wname, "(intgo);\n", NULL);
+ Printv(f_c_directors, director_sig, NULL);
+ Printv(f_c_directors, " ", wname, "(go_val);\n", NULL);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorMethod
+ *
+ * Emit a method for a director class, plus its overloads.
+ * ------------------------------------------------------------ */
+
+ int classDirectorMethod(Node *n, Node *parent, String *super) {
+ bool is_ignored = GetFlag(n, "feature:ignore") ? true : false;
+
+ // We don't need explicit calls.
+ if (GetFlag(n, "explicitcall")) {
+ return SWIG_OK;
+ }
+
+ String *name = Getattr(n, "sym:name");
+ if (!name) {
+ assert(is_ignored);
+ name = Getattr(n, "name");
+ }
+
+ bool overloaded = Getattr(n, "sym:overloaded") && !Getattr(n, "explicitcallnode");
+ if (!overloaded) {
+ int r = oneClassDirectorMethod(n, parent, super);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ } else {
+ // Handle overloaded methods here, because otherwise we will
+ // reject them in the class_methods hash table. We need to use
+ // class_methods so that we correctly handle cases where a
+ // function in one class hides a function of the same name in a
+ // parent class.
+ if (!Getattr(class_methods, name)) {
+ for (Node *on = Getattr(n, "sym:overloaded"); on; on = Getattr(on, "sym:nextSibling")) {
+ // Swig_overload_rank expects wrap:name and wrap:parms to be
+ // set.
+ String *wn = Swig_name_wrapper(Getattr(on, "sym:name"));
+ Append(wn, Getattr(on, "sym:overname"));
+ Append(wn, unique_id);
+ Setattr(on, "wrap:name", wn);
+ Delete(wn);
+ Setattr(on, "wrap:parms", Getattr(on, "parms"));
+ }
+ }
+
+ int r = oneClassDirectorMethod(n, parent, super);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ if (!Getattr(n, "sym:nextSibling"))
+ {
+ // Last overloaded function
+ Node *on = Getattr(n, "sym:overloaded");
+ bool is_static = isStatic(on);
+
+ String *cn = exportedName(Getattr(parent, "sym:name"));
+ String *go_name = buildGoName(name, is_static, false);
+
+ String *director_struct_name = NewString("_swig_Director");
+ Append(director_struct_name, cn);
+
+ int r = makeDispatchFunction(on, go_name, director_struct_name, is_static, director_struct_name, false);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ if (!GetFlag(n, "abstract")) {
+ String *go_upcall = NewString("Director");
+ Append(go_upcall, cn);
+ Append(go_upcall, go_name);
+ r = makeDispatchFunction(on, go_upcall, director_struct_name, is_static, director_struct_name, true);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ Delete(go_upcall);
+ }
+
+ Delete(director_struct_name);
+ Delete(go_name);
+ Delete(cn);
+ }
+ }
+ Setattr(class_methods, name, NewString(""));
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * oneClassDirectorMethod
+ *
+ * Emit a method for a director class.
+ * ------------------------------------------------------------ */
+
+ int oneClassDirectorMethod(Node *n, Node *parent, String *super) {
+ String *symname = Getattr(n, "sym:name");
+ if (!checkFunctionVisibility(n, parent)) {
+ return SWIG_OK;
+ }
+
+ bool is_ignored = GetFlag(n, "feature:ignore") ? true : false;
+ bool is_pure_virtual = (Cmp(Getattr(n, "storage"), "virtual") == 0 && Cmp(Getattr(n, "value"), "0") == 0);
+
+ String *name = Getattr(n, "sym:name");
+ if (!name) {
+ assert(is_ignored);
+ name = Getattr(n, "name");
+ }
+
+ String *overname = NULL;
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ }
+
+ String *cn = exportedName(Getattr(parent, "sym:name"));
+
+ String *go_type_name = goCPointerType(Getattr(parent, "classtypeobj"), true);
+
+ String *director_struct_name = NewString("_swig_Director");
+ Append(director_struct_name, cn);
+
+ bool is_static = isStatic(n);
+
+ String *go_name = buildGoName(name, is_static, false);
+
+ ParmList *parms = Getattr(n, "parms");
+ Setattr(n, "wrap:parms", parms);
+
+ Wrapper *dummy = NewWrapper();
+ emit_attach_parmmaps(parms, dummy);
+
+ Swig_typemap_attach_parms("gotype", parms, NULL);
+ Swig_typemap_attach_parms("imtype", parms, NULL);
+ int parm_count = emit_num_arguments(parms);
+
+ SwigType *result = Getattr(n, "type");
+
+ // Save the type for overload processing.
+ Setattr(n, "go:type", result);
+
+ String *interface_name = NewString("_swig_DirectorInterface");
+ Append(interface_name, cn);
+ Append(interface_name, go_name);
+ if (overname) {
+ Append(interface_name, overname);
+ }
+
+ String *callback_name = Copy(director_struct_name);
+ Append(callback_name, "_callback_");
+ Append(callback_name, name);
+ Replace(callback_name, "_swig", "Swig", DOH_REPLACE_FIRST);
+ if (overname) {
+ Append(callback_name, overname);
+ }
+ if (cgo_flag) {
+ Append(callback_name, unique_id);
+ }
+
+ String *upcall_name = Copy(director_struct_name);
+ Append(upcall_name, "_upcall_");
+ Append(upcall_name, go_name);
+
+ String *upcall_wname = Swig_name_wrapper(upcall_name);
+ if (overname) {
+ Append(upcall_wname, overname);
+ }
+ Append(upcall_wname, unique_id);
+
+ String *upcall_gc_name = buildGoWrapperName(upcall_name, overname);
+
+ String *go_with_over_name = Copy(go_name);
+ if (overname) {
+ Append(go_with_over_name, overname);
+ }
+
+ Parm *p = 0;
+ Wrapper *w = NewWrapper();
+
+ Swig_director_parms_fixup(parms);
+
+ Swig_typemap_attach_parms("directorin", parms, w);
+ Swig_typemap_attach_parms("directorargout", parms, w);
+ Swig_typemap_attach_parms("godirectorin", parms, w);
+ Swig_typemap_attach_parms("goin", parms, dummy);
+ Swig_typemap_attach_parms("goargout", parms, dummy);
+
+ DelWrapper(dummy);
+
+ if (!is_ignored) {
+ // We use an interface to see if this method is defined in Go.
+ Printv(f_go_wrappers, "type ", interface_name, " interface {\n", NULL);
+ Printv(f_go_wrappers, "\t", go_with_over_name, "(", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(f_go_wrappers, tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ")", NULL);
+
+ if (SwigType_type(result) != T_VOID) {
+ String *tm = goType(n, result);
+ Printv(f_go_wrappers, " ", tm, NULL);
+ Delete(tm);
+ }
+
+ Printv(f_go_wrappers, "\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ if (!GetFlag(n, "abstract")) {
+ if (cgo_flag) {
+ Printv(f_cgo_comment, "extern ", NULL);
+
+ if (SwigType_type(result) == T_VOID) {
+ Printv(f_cgo_comment, "void", NULL);
+ } else {
+ bool c_struct_type;
+ String *ret_type = cgoTypeForGoValue(n, result, &c_struct_type);
+ Printv(f_cgo_comment, ret_type, NULL);
+ Delete(ret_type);
+ }
+
+ Printv(f_cgo_comment, " ", upcall_wname, "(uintptr_t", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ bool c_struct_type;
+ String *ct = cgoTypeForGoValue(p, Getattr(p, "type"), &c_struct_type);
+ Printv(f_cgo_comment, ", ", ct, " ", Getattr(p, "lname"), NULL);
+ p = nextParm(p);
+ }
+ Printv(f_cgo_comment, ");\n", NULL);
+ } else {
+ // Declare the upcall function, which calls the method on
+ // the parent class.
+
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, "var ", upcall_wname, " unsafe.Pointer\n\n", NULL);
+ } else {
+ Printv(f_go_wrappers, "//extern ", go_prefix, "_", upcall_wname, "\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "func ", upcall_gc_name, "(_swig_ptr ", go_type_name, NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *tm = goWrapperType(p, Getattr(p, "type"), false);
+ Printv(f_go_wrappers, ", _ ", tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ")", NULL);
+
+ if (SwigType_type(result) != T_VOID) {
+ String *tm = goWrapperType(n, result, true);
+ Printv(f_go_wrappers, " (_swig_ret ", tm, ")", NULL);
+ Delete(tm);
+ }
+
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, " {\n", NULL);
+ Printv(f_go_wrappers, "\t_swig_p := uintptr(unsafe.Pointer(&_swig_ptr))\n", NULL);
+ Printv(f_go_wrappers, "\t_cgo_runtime_cgocall(", upcall_wname, ", _swig_p)\n", NULL);
+ Printv(f_go_wrappers, "\treturn\n", NULL);
+ Printv(f_go_wrappers, "}", NULL);
+ }
+
+ Printv(f_go_wrappers, "\n\n", NULL);
+ }
+ }
+
+ // Define the method on the director class in Go.
+
+ Printv(f_go_wrappers, "func (swig_p *", director_struct_name, ") ", go_with_over_name, "(", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ Printv(f_go_wrappers, Getattr(p, "lname"), " ", NULL);
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(f_go_wrappers, tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ")", NULL);
+
+ if (SwigType_type(result) != T_VOID) {
+ String *tm = goType(n, result);
+ Printv(f_go_wrappers, " ", tm, NULL);
+ Delete(tm);
+ }
+
+ Printv(f_go_wrappers, " {\n", NULL);
+
+ Printv(f_go_wrappers, "\tif swig_g, swig_ok := swig_p.v.(", interface_name, "); swig_ok {\n", NULL);
+ Printv(f_go_wrappers, "\t\t", NULL);
+ if (SwigType_type(result) != T_VOID) {
+ Printv(f_go_wrappers, "return ", NULL);
+ }
+ Printv(f_go_wrappers, "swig_g.", go_with_over_name, "(", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ Printv(f_go_wrappers, Getattr(p, "lname"), NULL);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ")\n", NULL);
+ if (SwigType_type(result) == T_VOID) {
+ Printv(f_go_wrappers, "\t\treturn\n", NULL);
+ }
+ Printv(f_go_wrappers, "\t}\n", NULL);
+
+ if (GetFlag(n, "abstract")) {
+ Printv(f_go_wrappers, "\tpanic(\"call to pure virtual method\")\n", NULL);
+ } else {
+ String *ret_type = NULL;
+ bool memcpy_ret = false;
+ String *wt = NULL;
+ bool has_goout = false;
+ String *goout = NULL;
+ if (SwigType_type(result) != T_VOID) {
+ ret_type = goImType(n, result);
+ Printv(f_go_wrappers, "\tvar swig_r ", ret_type, "\n", NULL);
+ goout = goTypemapLookup("goout", n, "swig_r");
+ if (goout) {
+ has_goout = true;
+ }
+
+ if (cgo_flag) {
+ bool c_struct_type;
+ Delete(cgoTypeForGoValue(n, result, &c_struct_type));
+ if (c_struct_type) {
+ memcpy_ret = true;
+ }
+ }
+ }
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (goGetattr(p, "tmap:goargout")) {
+ has_goout = true;
+ }
+ p = nextParm(p);
+ }
+
+ String *call = NewString("");
+
+ if (gccgo_flag && !cgo_flag) {
+ if (has_goout) {
+ Printv(call, "\tfunc() {\n", NULL);
+ }
+ Printv(call, "\tdefer SwigCgocallDone()\n", NULL);
+ Printv(call, "\tSwigCgocall()\n", NULL);
+ }
+
+ Printv(call, "\t", NULL);
+ if (SwigType_type(result) != T_VOID) {
+ if (memcpy_ret) {
+ Printv(call, "swig_r_p := ", NULL);
+ } else {
+ Printv(call, "swig_r = ", NULL);
+ if (cgo_flag) {
+ Printv(call, "(", ret_type, ")(", NULL);
+ }
+ }
+ if (cgo_flag && goTypeIsInterface(n, result)) {
+ wt = goWrapperType(n, result, true);
+ Printv(call, "(", wt, ")(", NULL);
+ }
+ }
+
+ if (cgo_flag) {
+ Printv(call, "C.", upcall_wname, NULL);
+ } else {
+ Printv(call, upcall_gc_name, NULL);
+ }
+ Printv(call, "(", NULL);
+ if (cgo_flag) {
+ Printv(call, "C.uintptr_t(", NULL);
+ }
+ Printv(call, "swig_p.", go_type_name, NULL);
+ if (cgo_flag) {
+ Printv(call, ")", NULL);
+ }
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ Printv(call, ", ", NULL);
+ p = getParm(p);
+ SwigType *pt = Getattr(p, "type");
+
+ String *ln = Getattr(p, "lname");
+
+ String *ivar = NewStringf("_swig_i_%d", i);
+
+ // This is an ordinary call from Go to C++, so adjust using
+ // the goin typemap.
+ String *goin = goGetattr(p, "tmap:goin");
+ if (goin == NULL) {
+ Printv(f_go_wrappers, "\t", ivar, " := ", ln, NULL);
+ if (goTypeIsInterface(p, pt)) {
+ Printv(f_go_wrappers, ".Swigcptr()", NULL);
+ }
+ Printv(f_go_wrappers, "\n", NULL);
+ } else {
+ String *itm = goImType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(f_go_wrappers, goin, NULL);
+ Delete(goin);
+ }
+
+ Setattr(p, "emit:goinput", ivar);
+
+ if (cgo_flag) {
+ bool c_struct_type;
+ String *ct = cgoTypeForGoValue(p, pt, &c_struct_type);
+ if (c_struct_type) {
+ Printv(call, "*(*C.", ct, ")(unsafe.Pointer(&", ivar, "))", NULL);
+ } else {
+ Printv(call, "C.", ct, "(", ivar, ")", NULL);
+ }
+ } else {
+ Printv(call, ivar, NULL);
+ }
+
+ p = nextParm(p);
+ }
+
+ Printv(call, ")", NULL);
+
+ if (gccgo_flag && !cgo_flag && has_goout) {
+ Printv(call, "\n\t}()", NULL);
+ }
+
+ if (cgo_flag) {
+ if (wt) {
+ // Close the type conversion to the wrapper type.
+ Printv(call, ")", NULL);
+ }
+ if (SwigType_type(result) != T_VOID && !memcpy_ret) {
+ // Close the type conversion of the return value.
+ Printv(call, ")", NULL);
+ }
+ }
+
+ Printv(call, "\n", NULL);
+
+ Printv(f_go_wrappers, call, NULL);
+ Delete(call);
+
+ if (memcpy_ret) {
+ Printv(f_go_wrappers, "\tswig_r = *(*", ret_type, ")(unsafe.Pointer(&swig_r_p))\n", NULL);
+ }
+
+ goargout(parms);
+
+ if (SwigType_type(result) != T_VOID) {
+ if (goout == NULL) {
+ Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ } else {
+ String *tm = goType(n, result);
+ Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+ Replaceall(goout, "$input", "swig_r");
+ Replaceall(goout, "$result", "swig_r_1");
+ Printv(f_go_wrappers, goout, "\n", NULL);
+ Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+ }
+ }
+
+ if (ret_type) {
+ Delete(ret_type);
+ }
+ if (wt) {
+ Delete(wt);
+ }
+ }
+
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ // Define a method in the C++ director class that the C++ upcall
+ // function can call. This permits an upcall to a protected
+ // method.
+
+ if (!GetFlag(n, "abstract")) {
+ String *upcall_method_name = NewString("_swig_upcall_");
+ Append(upcall_method_name, name);
+ if (overname) {
+ Append(upcall_method_name, overname);
+ }
+ SwigType *rtype = Getattr(n, "classDirectorMethods:type");
+ String *upcall_decl = Swig_method_decl(rtype, Getattr(n, "decl"), upcall_method_name, parms, 0);
+ Printv(f_c_directors_h, " ", upcall_decl, " {\n", NULL);
+ Delete(upcall_decl);
+
+ Printv(f_c_directors_h, " ", NULL);
+ if (SwigType_type(result) != T_VOID) {
+ Printv(f_c_directors_h, "return ", NULL);
+ }
+
+ String *super_call = Swig_method_call(super, parms);
+ Printv(f_c_directors_h, super_call, ";\n", NULL);
+ Delete(super_call);
+
+ Printv(f_c_directors_h, " }\n", NULL);
+
+ // Define the C++ function that the Go function calls.
+
+ SwigType *first_type = NULL;
+ Parm *first_parm = parms;
+ if (!is_static) {
+ first_type = NewString("SwigDirector_");
+ Append(first_type, class_name);
+ SwigType_add_pointer(first_type);
+ first_parm = NewParm(first_type, "p", n);
+ set_nextSibling(first_parm, parms);
+ }
+
+ Swig_save("classDirectorMethod", n, "wrap:name", "wrap:action", NULL);
+
+ Setattr(n, "wrap:name", upcall_wname);
+
+ String *action = NewString("");
+ if (SwigType_type(result) != T_VOID) {
+ Printv(action, Swig_cresult_name(), " = (", SwigType_lstr(result, 0), ")", NULL);
+ if (SwigType_isreference(result)) {
+ Printv(action, "&", NULL);
+ }
+ }
+ Printv(action, Swig_cparm_name(NULL, 0), "->", upcall_method_name, "(", NULL);
+
+ p = parms;
+ int i = 0;
+ while (p != NULL) {
+ if (SwigType_type(Getattr(p, "type")) != T_VOID) {
+ String *pname = Swig_cparm_name(NULL, i + 1);
+ if (i > 0) {
+ Printv(action, ", ", NULL);
+ }
+
+ // A parameter whose type is a reference is converted into a
+ // pointer type by gcCTypeForGoValue. We are calling a
+ // function which expects a reference so we need to convert
+ // back.
+ if (SwigType_isreference(Getattr(p, "type"))) {
+ Printv(action, "*", NULL);
+ }
+
+ Printv(action, pname, NULL);
+ Delete(pname);
+ i++;
+ }
+ p = nextSibling(p);
+ }
+ Printv(action, ");", NULL);
+ Setattr(n, "wrap:action", action);
+
+ if (cgo_flag) {
+ cgoWrapperInfo info;
+
+ info.n = n;
+ info.go_name = go_name;
+ info.overname = overname;
+ info.wname = upcall_wname;
+ info.base = NULL;
+ info.parms = first_parm;
+ info.result = result;
+ info.is_static = is_static;
+ info.receiver = NULL;
+ info.is_constructor = false;
+ info.is_destructor = false;
+
+ int r = cgoGccWrapper(&info);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ } else if (!gccgo_flag) {
+ // Write the upcall wrapper function. This is compiled by gc
+ // and calls the C++ function.
+ int r = gcFunctionWrapper(upcall_wname);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ r = gccFunctionWrapper(n, NULL, upcall_wname, first_parm, result);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ } else {
+ int r = gccgoFunctionWrapper(n, NULL, upcall_wname, first_parm, result);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ Delete(first_type);
+ if (first_parm != parms) {
+ Delete(first_parm);
+ }
+
+ Swig_restore(n);
+ Delete(upcall_method_name);
+
+ // Define a function that uses the Go director type that other
+ // methods in the Go type can call to get parent methods.
+
+ Printv(f_go_wrappers, "func Director", cn, go_with_over_name, "(p ", cn, NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", NULL);
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(f_go_wrappers, tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ")", NULL);
+
+ if (SwigType_type(result) != T_VOID) {
+ String *tm = goType(n, result);
+ Printv(f_go_wrappers, " ", tm, NULL);
+ Delete(tm);
+ }
+
+ Printv(f_go_wrappers, " {\n", NULL);
+
+ String *ret_type = NULL;
+ bool memcpy_ret = false;
+ String *wt = NULL;
+ String *goout = NULL;
+ if (SwigType_type(result) != T_VOID) {
+ ret_type = goImType(n, result);
+ Printv(f_go_wrappers, "\tvar swig_r ", ret_type, "\n", NULL);
+ goout = goTypemapLookup("goout", n, "swig_r");
+
+ if (cgo_flag) {
+ bool c_struct_type;
+ Delete(cgoTypeForGoValue(n, result, &c_struct_type));
+ if (c_struct_type) {
+ memcpy_ret = true;
+ }
+ }
+ }
+
+ String *call = NewString("");
+
+ if (gccgo_flag && !cgo_flag) {
+ if (goout != NULL) {
+ Printv(call, "\tfunc() {\n", NULL);
+ }
+ Printv(call, "\tdefer SwigCgocallDone()\n", NULL);
+ Printv(call, "\tSwigCgocall()\n", NULL);
+ }
+
+ Printv(call, "\t", NULL);
+ if (SwigType_type(result) != T_VOID) {
+ if (memcpy_ret) {
+ Printv(call, "swig_r_p := ", NULL);
+ } else {
+ Printv(call, "swig_r = ", NULL);
+ if (cgo_flag) {
+ Printv(call, "(", ret_type, ")(", NULL);
+ }
+ }
+ if (cgo_flag && goTypeIsInterface(n, result)) {
+ wt = goWrapperType(n, result, true);
+ Printv(call, "(", wt, ")(", NULL);
+ }
+ }
+
+ if (cgo_flag) {
+ Printv(call, "C.", upcall_wname, NULL);
+ } else {
+ Printv(call, upcall_gc_name, NULL);
+ }
+ Printv(call, "(", NULL);
+ if (cgo_flag) {
+ Printv(call, "C.uintptr_t(", NULL);
+ }
+ Printv(call, "p.(*", director_struct_name, ").", go_type_name, NULL);
+ if (cgo_flag) {
+ Printv(call, ")", NULL);
+ }
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ Printv(call, ", ", NULL);
+ p = getParm(p);
+ SwigType *pt = Getattr(p, "type");
+
+ String *ivar = NewStringf("_swig_i_%d", i);
+
+ String *ln = Copy(Getattr(p, "lname"));
+
+ String *goin = goGetattr(p, "tmap:goin");
+ if (goin == NULL) {
+ Printv(f_go_wrappers, "\t", ivar, " := ", ln, NULL);
+ if (goTypeIsInterface(p, pt)) {
+ Printv(f_go_wrappers, ".Swigcptr()", NULL);
+ }
+ Printv(f_go_wrappers, "\n", NULL);
+ } else {
+ String *itm = goImType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(f_go_wrappers, goin, NULL);
+ Delete(goin);
+ }
+
+ Setattr(p, "emit:goinput", ivar);
+
+ if (cgo_flag) {
+ bool c_struct_type;
+ String *ct = cgoTypeForGoValue(p, pt, &c_struct_type);
+ if (c_struct_type) {
+ Printv(call, "*(*C.", ct, ")(unsafe.Pointer(&", ivar, "))", NULL);
+ } else {
+ Printv(call, "C.", ct, "(", ivar, ")", NULL);
+ }
+ } else {
+ Printv(call, ivar, NULL);
+ }
+
+ Delete(ln);
+
+ p = nextParm(p);
+ }
+
+ Printv(call, ")", NULL);
+
+ if (gccgo_flag && !cgo_flag && goout != NULL) {
+ Printv(call, "\n\t}()", NULL);
+ }
+
+ if (cgo_flag) {
+ if (wt) {
+ // Close the type conversion to the wrapper type.
+ Printv(call, ")", NULL);
+ }
+ if (SwigType_type(result) != T_VOID && !memcpy_ret) {
+ // Close the type conversion of the return value.
+ Printv(call, ")", NULL);
+ }
+ }
+
+ Printv(call, "\n", NULL);
+
+ Printv(f_go_wrappers, call, NULL);
+ Delete(call);
+
+ if (memcpy_ret) {
+ Printv(f_go_wrappers, "\tswig_r = *(*", ret_type, ")(unsafe.Pointer(&swig_r_p))\n", NULL);
+ }
+
+ goargout(parms);
+
+ if (SwigType_type(result) != T_VOID) {
+ if (goout == NULL) {
+ Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ } else {
+ String *tm = goType(n, result);
+ Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+ Replaceall(goout, "$input", "swig_r");
+ Replaceall(goout, "$result", "swig_r_1");
+ Printv(f_go_wrappers, goout, "\n", NULL);
+ Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+ }
+ }
+
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ if (ret_type) {
+ Delete(ret_type);
+ }
+ if (wt) {
+ Delete(wt);
+ }
+ }
+
+ // The Go function which invokes the method. This is called by
+ // the C++ method on the director class.
+
+ if (cgo_flag) {
+ Printv(f_go_wrappers, "//export ", callback_name, "\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "func ", callback_name, "(swig_c int", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *tm = goWrapperType(p, Getattr(p, "type"), false);
+ Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ") ", NULL);
+ String *result_wrapper = NULL;
+ if (SwigType_type(result) != T_VOID) {
+ result_wrapper = goWrapperType(n, result, true);
+ Printv(f_go_wrappers, "(swig_result ", result_wrapper, ") ", NULL);
+ }
+ Printv(f_go_wrappers, "{\n", NULL);
+
+ if (is_ignored) {
+ Printv(f_go_wrappers, "\treturn\n", NULL);
+ } else {
+ bool result_is_interface = false;
+ String *goout = NULL;
+ if (SwigType_type(result) != T_VOID) {
+ result_is_interface = goTypeIsInterface(NULL, result);
+ Printv(f_go_wrappers, "\tvar swig_r ", NULL);
+ if (!result_is_interface) {
+ Printv(f_go_wrappers, goType(n, result), NULL);
+ } else {
+ Printv(f_go_wrappers, result_wrapper, NULL);
+ }
+ Printv(f_go_wrappers, "\n", NULL);
+ goout = goTypemapLookup("godirectorout", n, "swig_r");
+ }
+
+ String *call = NewString("");
+ Printv(call, "\t", NULL);
+
+ if (SwigType_type(result) != T_VOID) {
+ Printv(call, "swig_r = ", NULL);
+ if (result_is_interface) {
+ Printv(call, result_wrapper, "(", NULL);
+ }
+ }
+ Printv(call, "swig_p.", go_with_over_name, "(", NULL);
+
+ String *goincode = NewString("");
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0) {
+ Printv(call, ", ", NULL);
+ }
+ SwigType *pt = Getattr(p, "type");
+
+ String *ln = NewString("");
+
+ // If the Go representation is an interface type class, then
+ // we are receiving a uintptr, and must convert to the
+ // interface.
+ bool is_interface = goTypeIsInterface(p, pt);
+ if (is_interface) {
+ // Passing is_result as true to goWrapperType gives us the
+ // name of the Go type we need to convert to an interface.
+ String *wt = goWrapperType(p, pt, true);
+ Printv(ln, wt, "(", NULL);
+ Delete(wt);
+ }
+
+ Printv(ln, Getattr(p, "lname"), NULL);
+
+ if (is_interface) {
+ Printv(ln, ")", NULL);
+ }
+
+ String *goin = goGetattr(p, "tmap:godirectorin");
+ if (goin == NULL) {
+ Printv(call, ln, NULL);
+ } else {
+ String *ivar = NewString("");
+ Printf(ivar, "_swig_i_%d", i);
+ String *itm = goType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(goincode, goin, "\n", NULL);
+ Delete(goin);
+ Printv(call, ivar, NULL);
+ Delete(ivar);
+ }
+
+ Delete(ln);
+
+ p = nextParm(p);
+ }
+
+ Printv(call, ")", NULL);
+
+ if (result_is_interface) {
+ Printv(call, ".Swigcptr())", NULL);
+ }
+ Printv(call, "\n", NULL);
+
+ if (gccgo_flag && !cgo_flag) {
+ if (goout != NULL) {
+ Printv(f_go_wrappers, "\tfunc() {\n", NULL);
+ }
+ Printv(f_go_wrappers, "\tSwigCgocallBack()\n", NULL);
+ Printv(f_go_wrappers, "\tdefer SwigCgocallBackDone()\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "\tswig_p := swigDirectorLookup(swig_c).(*", director_struct_name, ")\n", NULL);
+ Printv(f_go_wrappers, goincode, NULL);
+ Printv(f_go_wrappers, call, NULL);
+ Delete(call);
+
+ if (gccgo_flag && !cgo_flag && goout != NULL) {
+ Printv(f_go_wrappers, "\t}()\n", NULL);
+ }
+
+ if (SwigType_type(result) != T_VOID) {
+ if (goout == NULL) {
+ Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ } else {
+ String *tm = goImType(n, result);
+ Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+ Replaceall(goout, "$input", "swig_r");
+ Replaceall(goout, "$result", "swig_r_1");
+ Printv(f_go_wrappers, goout, "\n", NULL);
+ Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+ }
+ }
+ }
+
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Delete(result_wrapper);
+
+ Delete(upcall_wname);
+ Delete(upcall_gc_name);
+ Delete(go_with_over_name);
+ }
+
+ if (!is_ignored || is_pure_virtual) {
+ // Declare the method for the director class.
+
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ String *decl = Swig_method_decl(rtype, Getattr(n, "decl"), Getattr(n, "name"), parms, 0);
+ Printv(f_c_directors_h, " virtual ", decl, NULL);
+ Delete(decl);
+
+ String *qname = NewString("");
+ Printv(qname, "SwigDirector_", class_name, "::", Getattr(n, "name"), NULL);
+ decl = Swig_method_decl(rtype, Getattr(n, "decl"), qname, parms, 0);
+ Printv(w->def, decl, NULL);
+ Delete(decl);
+ Delete(qname);
+
+ String *throws = buildThrow(n);
+ if (throws) {
+ Printv(f_c_directors_h, " ", throws, NULL);
+ Printv(w->def, " ", throws, NULL);
+ Delete(throws);
+ }
+
+ Printv(f_c_directors_h, ";\n", NULL);
+
+ Printv(w->def, " {\n", NULL);
+
+ if (SwigType_type(result) != T_VOID) {
+ if (!SwigType_isclass(result)) {
+ if (!(SwigType_ispointer(result) || SwigType_isreference(result))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(result, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(result, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(result, "c_result"), "= 0", NIL);
+ }
+ } else {
+ String *cres = SwigType_lstr(result, "c_result");
+ Printf(w->code, "%s;\n", cres);
+ Delete(cres);
+ }
+ }
+
+ if (!is_ignored) {
+ makeDirectorMethodWrapper(n, w, callback_name);
+ } else {
+ assert(is_pure_virtual);
+ Printv(w->code, " _swig_gopanic(\"call to pure virtual function ", Getattr(parent, "sym:name"), name, "\");\n", NULL);
+ if (SwigType_type(result) != T_VOID) {
+ String *retstr = SwigType_rcaststr(result, "c_result");
+ Printv(w->code, " return ", retstr, ";\n", NULL);
+ Delete(retstr);
+ }
+ }
+
+ Printv(w->code, "}", NULL);
+
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_c_directors);
+ }
+
+ Delete(cn);
+ Delete(go_type_name);
+ Delete(director_struct_name);
+ Delete(interface_name);
+ Delete(callback_name);
+ Delete(upcall_name);
+ Delete(go_name);
+ DelWrapper(w);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * makeDirectorMethodWrapper
+ *
+ * Emit the function wrapper for a director method.
+ * ------------------------------------------------------------ */
+ void makeDirectorMethodWrapper(Node *n, Wrapper *w, String *callback_name) {
+ if (cgo_flag) {
+ makeCgoDirectorMethodWrapper(n, w, callback_name);
+ return;
+ }
+
+ ParmList *parms = Getattr(n, "wrap:parms");
+ SwigType *result = Getattr(n, "type");
+
+ String *callback_wname = Swig_name_wrapper(callback_name);
+ Append(callback_wname, unique_id);
+
+ if (!gccgo_flag) {
+ Printv(f_c_directors, "extern \"C\" void ", callback_wname, "(void*, int);\n", NULL);
+ } else {
+ Printv(f_c_directors, "extern \"C\" ", NULL);
+
+ String *fnname = NewString("");
+ Printv(fnname, callback_wname, "(int", NULL);
+
+ Parm *p = parms;
+ while (p) {
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+ String *cg = gccgoCTypeForGoValue(p, Getattr(p, "type"),
+ Getattr(p, "lname"));
+ Printv(fnname, ", ", cg, NULL);
+ Delete(cg);
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ Printv(fnname, ")", NULL);
+
+ if (SwigType_type(result) == T_VOID) {
+ Printv(f_c_directors, "void ", fnname, NULL);
+ } else {
+ String *tm = gccgoCTypeForGoValue(n, result, fnname);
+ Printv(f_c_directors, tm, NULL);
+ Delete(tm);
+ }
+
+ Delete(fnname);
+
+ Printv(f_c_directors, " __asm__(\"", go_prefix, ".", callback_name, "\");\n", NULL);
+ }
+
+ if (!gccgo_flag) {
+ Printv(w->code, " struct {\n", NULL);
+ Printv(w->code, " intgo go_val;\n", NULL);
+
+ Parm *p = parms;
+ while (p) {
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+ String *ln = Getattr(p, "lname");
+ String *cg = gcCTypeForGoValue(p, Getattr(p, "type"), ln);
+ Printv(w->code, " ", cg, ";\n", NULL);
+ Delete(cg);
+ p = Getattr(p, "tmap:directorin:next");
+ }
+ if (SwigType_type(result) != T_VOID) {
+ Printv(w->code, " long : 0;\n", NULL);
+ String *rname = NewString(Swig_cresult_name());
+ String *cg = gcCTypeForGoValue(n, result, rname);
+ Printv(w->code, " ", cg, ";\n", NULL);
+ Delete(cg);
+ Delete(rname);
+ }
+
+ Printv(w->code, " } SWIGSTRUCTPACKED swig_a;\n", NULL);
+ Printv(w->code, " swig_a.go_val = go_val;\n", NULL);
+
+ p = parms;
+ while (p) {
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+ String *tm = Getattr(p, "tmap:directorin");
+ if (!tm) {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file,
+ line_number, "Unable to use type %s as director method argument\n", SwigType_str(Getattr(p, "type"), 0));
+ } else {
+ tm = Copy(tm);
+ String *ln = Getattr(p, "lname");
+ String *input = NewString("");
+ Printv(input, "swig_a.", ln, NULL);
+ Setattr(p, "emit:directorinput", input);
+ Replaceall(tm, "$input", input);
+ Replaceall(tm, "$owner", "0");
+ Delete(input);
+ Printv(w->code, "\t", tm, "\n", NULL);
+ Delete(tm);
+ }
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ Printv(w->code, " crosscall2(", callback_wname, ", &swig_a, (int) sizeof swig_a);\n", NULL);
+
+ /* Marshal outputs */
+ for (p = parms; p;) {
+ String *tm;
+ if ((tm = Getattr(p, "tmap:directorargout"))) {
+ tm = Copy(tm);
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ Delete(tm);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ if (SwigType_type(result) != T_VOID) {
+ String *result_str = NewString("c_result");
+ String *tm = Swig_typemap_lookup("directorout", n, result_str, NULL);
+ if (!tm) {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use type %s as director method result\n", SwigType_str(result, 0));
+ } else {
+ static const String *swig_a_result = NewStringf("swig_a.%s", Swig_cresult_name());
+ Replaceall(tm, "$input", swig_a_result);
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, " ", tm, "\n", NULL);
+ String *retstr = SwigType_rcaststr(result, "c_result");
+ Printv(w->code, " return ", retstr, ";\n", NULL);
+ Delete(retstr);
+ Delete(tm);
+ }
+ Delete(result_str);
+ }
+
+ // The C wrapper code which calls the Go function.
+ Printv(f_gc_wrappers, "#pragma dynexport ", callback_wname, " ", callback_wname, "\n", NULL);
+ Printv(f_gc_wrappers, "#pragma cgo_export_static ", callback_wname, " ", callback_wname, "\n", NULL);
+ Printv(f_gc_wrappers, "#pragma textflag 7\n", NULL);
+ Printv(f_gc_wrappers, "extern void \xc2\xb7", callback_name, "();\n", NULL);
+ Printv(f_gc_wrappers, "void\n", NULL);
+ Printv(f_gc_wrappers, callback_wname, "(void *a, int32 n)\n", NULL);
+ Printv(f_gc_wrappers, "{\n", NULL);
+ Printv(f_gc_wrappers, "\truntime\xc2\xb7" "cgocallback(\xc2\xb7", callback_name, ", a, n);\n", NULL);
+ Printv(f_gc_wrappers, "}\n\n", NULL);
+ } else {
+ if (SwigType_type(result) != T_VOID) {
+ String *r = NewString(Swig_cresult_name());
+ String *tm = gccgoCTypeForGoValue(n, result, r);
+ Wrapper_add_local(w, r, tm);
+ Delete(tm);
+ Delete(r);
+ }
+
+ String *args = NewString("");
+
+ Parm *p = parms;
+ while (p) {
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ String *pn = NewString("g");
+ Append(pn, Getattr(p, "lname"));
+ Setattr(p, "emit:directorinput", pn);
+
+ String *tm = gccgoCTypeForGoValue(n, Getattr(p, "type"), pn);
+ Wrapper_add_local(w, pn, tm);
+ Delete(tm);
+
+ tm = Getattr(p, "tmap:directorin");
+ if (!tm) {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file,
+ line_number, "Unable to use type %s as director method argument\n", SwigType_str(Getattr(p, "type"), 0));
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$input", pn);
+ Replaceall(tm, "$owner", 0);
+ Printv(w->code, " ", tm, "\n", NULL);
+ Delete(tm);
+
+ Printv(args, ", ", pn, NULL);
+ }
+
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ Printv(w->code, " ", NULL);
+ if (SwigType_type(result) != T_VOID) {
+ Printv(w->code, Swig_cresult_name(), " = ", NULL);
+ }
+ Printv(w->code, callback_wname, "(go_val", args, ");\n", NULL);
+
+ /* Marshal outputs */
+ for (p = parms; p;) {
+ String *tm;
+ if ((tm = Getattr(p, "tmap:directorargout"))) {
+ tm = Copy(tm);
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ Delete(tm);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ if (SwigType_type(result) != T_VOID) {
+ String *result_str = NewString("c_result");
+ String *tm = Swig_typemap_lookup("directorout", n, result_str, NULL);
+ if (!tm) {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use type %s as director method result\n", SwigType_str(result, 0));
+ } else {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, " ", tm, "\n", NULL);
+ String *retstr = SwigType_rcaststr(result, "c_result");
+ Printv(w->code, " return ", retstr, ";\n", NULL);
+ Delete(retstr);
+ Delete(tm);
+ }
+ Delete(result_str);
+ }
+ }
+
+ Delete(callback_wname);
+ }
+
+ /* ------------------------------------------------------------
+ * makeDirectorMethodWrapper
+ *
+ * Emit the function wrapper for a director method for cgo.
+ * ------------------------------------------------------------ */
+
+ void makeCgoDirectorMethodWrapper(Node *n, Wrapper *w, String *callback_name) {
+ ParmList *parms = Getattr(n, "wrap:parms");
+ SwigType *result = Getattr(n, "type");
+
+ Printv(f_c_directors, "extern \"C\" ", NULL);
+
+ String *fnname = Copy(callback_name);
+ Append(fnname, "(int");
+
+ Parm *p = parms;
+ while (p) {
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+ String *cg = gcCTypeForGoValue(p, Getattr(p, "type"), Getattr(p, "lname"));
+ Printv(fnname, ", ", cg, NULL);
+ Delete(cg);
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ Printv(fnname, ")", NULL);
+
+ if (SwigType_type(result) == T_VOID) {
+ Printv(f_c_directors, "void ", fnname, NULL);
+ } else {
+ String *tm = gcCTypeForGoValue(n, result, fnname);
+ Printv(f_c_directors, tm, NULL);
+ Delete(tm);
+ }
+
+ Delete(fnname);
+
+ Printv(f_c_directors, ";\n", NULL);
+
+ if (SwigType_type(result) != T_VOID) {
+ String *r = NewString(Swig_cresult_name());
+ String *tm = gcCTypeForGoValue(n, result, r);
+ Wrapper_add_local(w, r, tm);
+ Delete(tm);
+ Delete(r);
+ }
+
+ String *args = NewString("");
+
+ p = parms;
+ while (p) {
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ String *pn = NewString("swig_");
+ Append(pn, Getattr(p, "lname"));
+ Setattr(p, "emit:directorinput", pn);
+
+ String *tm = gcCTypeForGoValue(p, Getattr(p, "type"), pn);
+ Wrapper_add_local(w, pn, tm);
+ Delete(tm);
+
+ tm = Getattr(p, "tmap:directorin");
+ if (!tm) {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file,
+ line_number, "Unable to use type %s as director method argument\n", SwigType_str(Getattr(p, "type"), 0));
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$input", pn);
+ Replaceall(tm, "$owner", 0);
+ Printv(w->code, " ", tm, "\n", NULL);
+ Delete(tm);
+
+ Printv(args, ", ", pn, NULL);
+ }
+
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ Printv(w->code, " ", NULL);
+ if (SwigType_type(result) != T_VOID) {
+ Printv(w->code, Swig_cresult_name(), " = ", NULL);
+ }
+ Printv(w->code, callback_name, "(go_val", args, ");\n", NULL);
+
+ /* Marshal outputs */
+ for (p = parms; p; ) {
+ String *tm;
+ if ((tm = Getattr(p, "tmap:directorargout"))) {
+ tm = Copy(tm);
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NULL);
+ Delete(tm);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ if (SwigType_type(result) != T_VOID) {
+ String *result_str = NewString("c_result");
+ String *tm = Swig_typemap_lookup("directorout", n, result_str, NULL);
+ if (!tm) {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use type %s as director method result\n", SwigType_str(result, 0));
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$input", Swig_cresult_name());
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, " ", tm, "\n", NULL);
+ String *retstr = SwigType_rcaststr(result, "c_result");
+ Printv(w->code, " return ", retstr, ";\n", NULL);
+ Delete(retstr);
+ Delete(tm);
+ }
+ Delete(result_str);
+ }
+ }
+
+
+ /* ------------------------------------------------------------
+ * classDirectorEnd
+ *
+ * Complete support for a director class.
+ * ------------------------------------------------------------ */
+
+ int classDirectorEnd(Node *n) {
+ (void) n;
+
+ Printv(f_c_directors_h, " private:\n", NULL);
+ Printv(f_c_directors_h, " intgo go_val;\n", NULL);
+ Printv(f_c_directors_h, " Swig_memory *swig_mem;\n", NULL);
+ Printv(f_c_directors_h, "};\n\n", NULL);
+
+ class_name = NULL;
+ class_node = NULL;
+
+ Delete(class_receiver);
+ class_receiver = NULL;
+
+ Delete(class_methods);
+ class_methods = NULL;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDisown
+ *
+ * I think Go does not require a disown method.
+ * ------------------------------------------------------------ */
+
+ int classDirectorDisown(Node *n) {
+ (void) n;
+ return SWIG_OK;
+ }
+
+ /*----------------------------------------------------------------------
+ * buildThrow()
+ *
+ * Build and return a throw clause if needed.
+ *--------------------------------------------------------------------*/
+
+ String *buildThrow(Node *n) {
+ if (Getattr(n, "noexcept"))
+ return NewString("noexcept");
+ ParmList *throw_parm_list = Getattr(n, "throws");
+ if (!throw_parm_list && !Getattr(n, "throw"))
+ return NULL;
+ String *ret = NewString("throw(");
+ if (throw_parm_list) {
+ Swig_typemap_attach_parms("throws", throw_parm_list, NULL);
+ }
+ bool first = true;
+ for (Parm *p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (first) {
+ first = false;
+ } else {
+ Printv(ret, ", ", NULL);
+ }
+ String *s = SwigType_str(Getattr(p, "type"), 0);
+ Printv(ret, s, NULL);
+ Delete(s);
+ }
+ }
+ Printv(ret, ")", NULL);
+ return ret;
+ }
+
+ /*----------------------------------------------------------------------
+ * extraDirectorProtectedCPPMethodsRequired()
+ *
+ * We don't need to check upcall when calling methods.
+ *--------------------------------------------------------------------*/
+
+ bool extraDirectorProtectedCPPMethodsRequired() const {
+ return false;
+ }
+
+ /*----------------------------------------------------------------------
+ * makeDispatchFunction
+ *
+ * Make a dispatch function for an overloaded C++ function. The
+ * receiver parameter is the receiver for a method, unless is_upcall
+ * is true. If is_upcall is true, then the receiver parameter is
+ * the type of the first argument to the function.
+ *--------------------------------------------------------------------*/
+
+ int makeDispatchFunction(Node *n, String *go_name, String *receiver, bool is_static, SwigType *director_struct, bool is_upcall) {
+ bool is_director = director_struct ? true : false;
+
+ String *nodetype = Getattr(n, "nodeType");
+ bool is_constructor = Cmp(nodetype, "constructor") == 0;
+ bool is_destructor = Cmp(nodetype, "destructor") == 0;
+
+ bool can_use_receiver = (!is_constructor && !is_destructor && !is_upcall);
+
+ bool use_receiver = (!is_static && can_use_receiver);
+
+ bool add_to_interface = (interfaces && !is_constructor && !is_destructor && !is_static && !is_upcall);
+
+ List *dispatch = Swig_overload_rank(n, false);
+ int nfunc = Len(dispatch);
+
+ SwigType *all_result;
+ bool mismatch;
+ if (is_constructor) {
+ assert(!is_upcall);
+ if (!is_director) {
+ all_result = Copy(Getattr(class_node, "classtypeobj"));
+ } else {
+ all_result = Copy(director_struct);
+ }
+ mismatch = false;
+ } else {
+ all_result = NULL;
+ mismatch = false;
+ bool any_void = false;
+ for (int i = 0; i < nfunc; ++i) {
+ Node *nn = Getitem(dispatch, i);
+ Node *ni = Getattr(nn, "directorNode") ? Getattr(nn, "directorNode") : nn;
+ SwigType *result = Getattr(ni, "go:type");
+ assert(result);
+
+ if (SwigType_type(result) == T_VOID) {
+ if (all_result) {
+ mismatch = true;
+ }
+ any_void = true;
+ } else {
+ if (any_void) {
+ mismatch = true;
+ } else if (!all_result) {
+ all_result = Copy(result);
+ } else if (Cmp(result, all_result) != 0) {
+ mismatch = true;
+ }
+ }
+ }
+ if (mismatch) {
+ Delete(all_result);
+ all_result = NULL;
+ } else if (all_result) {
+ ;
+ } else {
+ all_result = NewString("void");
+ }
+ }
+
+ Printv(f_go_wrappers, "func ", NULL);
+
+ if (receiver && use_receiver) {
+ Printv(f_go_wrappers, "(p ", receiver, ") ", NULL);
+ }
+
+ Printv(f_go_wrappers, go_name, "(", NULL);
+ if (is_director && is_constructor) {
+ Printv(f_go_wrappers, "abi interface{}, ", NULL);
+ assert(!add_to_interface);
+ }
+ if (is_upcall) {
+ Printv(f_go_wrappers, "p *", receiver, ", ", NULL);
+ assert(!add_to_interface);
+ }
+ Printv(f_go_wrappers, "a ...interface{})", NULL);
+
+ if (add_to_interface) {
+ Printv(interfaces, "\t", go_name, "(a ...interface{})", NULL);
+ }
+
+ if (mismatch) {
+ Printv(f_go_wrappers, " interface{}", NULL);
+ if (add_to_interface) {
+ Printv(interfaces, " interface{}", NULL);
+ }
+ } else if (all_result && SwigType_type(all_result) != T_VOID) {
+ if (is_director && is_constructor) {
+ Printv(f_go_wrappers, " ", receiver, NULL);
+ if (add_to_interface) {
+ Printv(interfaces, " ", receiver, NULL);
+ }
+ } else {
+ String *tm = goType(n, all_result);
+ Printv(f_go_wrappers, " ", tm, NULL);
+ if (add_to_interface) {
+ Printv(interfaces, " ", tm, NULL);
+ }
+ Delete(tm);
+ }
+ }
+ Printv(f_go_wrappers, " {\n", NULL);
+ if (add_to_interface) {
+ Printv(interfaces, "\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "\targc := len(a)\n", NULL);
+
+ for (int i = 0; i < nfunc; ++i) {
+ int fn = 0;
+ Node *nn = Getitem(dispatch, i);
+ Node *ni = Getattr(nn, "directorNode") ? Getattr(nn, "directorNode") : nn;
+ Parm *pi = Getattr(ni, "wrap:parms");
+
+ // If we are using a receiver, we want to ignore a leading self
+ // parameter. Because of the way this is called, there may or
+ // may not be a self parameter at this point.
+ if (use_receiver && pi && Getattr(pi, "self")) {
+ pi = getParm(pi);
+ if (pi) {
+ pi = nextParm(pi);
+ }
+ }
+
+ int num_required = emit_num_required(pi);
+ int num_arguments = emit_num_arguments(pi);
+ bool varargs = emit_isvarargs(pi) ? true : false;
+
+ if (varargs) {
+ Printf(f_go_wrappers, "\tif argc >= %d {\n", num_required);
+ } else {
+ if (num_required == num_arguments) {
+ Printf(f_go_wrappers, "\tif argc == %d {\n", num_required);
+ } else {
+ Printf(f_go_wrappers, "\tif argc >= %d && argc <= %d {\n", num_required, num_arguments);
+ }
+ }
+
+ // Build list of collisions with the same number of arguments.
+ List *coll = NewList();
+ for (int k = i + 1; k < nfunc; ++k) {
+ Node *nnk = Getitem(dispatch, k);
+ Node *nk = Getattr(nnk, "directorNode") ? Getattr(nnk, "directorNode") : nnk;
+ Parm *pk = Getattr(nk, "wrap:parms");
+ if (use_receiver && pk && Getattr(pk, "self")) {
+ pk = getParm(pk);
+ if (pk) {
+ pk = nextParm(pk);
+ }
+ }
+ int nrk = emit_num_required(pk);
+ int nak = emit_num_arguments(pk);
+ if ((nrk >= num_required && nrk <= num_arguments)
+ || (nak >= num_required && nak <= num_arguments)
+ || (nrk <= num_required && nak >= num_arguments)
+ || (varargs && nrk >= num_required)) {
+ Append(coll, nk);
+ }
+ }
+
+ int num_braces = 0;
+ if (Len(coll) > 0 && num_arguments > 0) {
+ int j = 0;
+ Parm *pj = pi;
+ while (pj) {
+ pj = getParm(pj);
+ if (!pj) {
+ break;
+ }
+
+ // If all the overloads have the same type in this position,
+ // we can omit the check.
+ SwigType *tm = goOverloadType(pj, Getattr(pj, "type"));
+ bool emitcheck = false;
+ for (int k = 0; k < Len(coll) && !emitcheck; ++k) {
+ Node *nk = Getitem(coll, k);
+ Parm *pk = Getattr(nk, "wrap:parms");
+ if (use_receiver && pk && Getattr(pk, "self")) {
+ pk = getParm(pk);
+ if (pk) {
+ pk = nextParm(pk);
+ }
+ }
+ int nak = emit_num_arguments(pk);
+ if (nak <= j)
+ continue;
+ int l = 0;
+ Parm *pl = pk;
+ while (pl && l <= j) {
+ pl = getParm(pl);
+ if (!pl) {
+ break;
+ }
+ if (l == j) {
+ SwigType *tml = goOverloadType(pl, Getattr(pl, "type"));
+ if (Cmp(tm, tml) != 0) {
+ emitcheck = true;
+ }
+ Delete(tml);
+ }
+ pl = nextParm(pl);
+ ++l;
+ }
+ }
+
+ if (emitcheck) {
+ if (j >= num_required) {
+ Printf(f_go_wrappers, "\t\tif argc > %d {\n", j);
+ ++num_braces;
+ }
+
+ fn = i + 1;
+ Printf(f_go_wrappers, "\t\tif _, ok := a[%d].(%s); !ok {\n", j, tm);
+ Printf(f_go_wrappers, "\t\t\tgoto check_%d\n", fn);
+ Printv(f_go_wrappers, "\t\t}\n", NULL);
+ }
+
+ Delete(tm);
+
+ pj = nextParm(pj);
+
+ ++j;
+ }
+ }
+
+ for (; num_braces > 0; --num_braces) {
+ Printv(f_go_wrappers, "\t\t}\n", NULL);
+ }
+
+ // We may need to generate multiple calls if there are variable
+ // argument lists involved. Build the start of the call.
+
+ String *start = NewString("");
+
+ SwigType *result = Getattr(ni, "go:type");
+
+ if (is_constructor) {
+ result = all_result;
+ } else if (is_destructor) {
+ result = NULL;
+ }
+
+ if (result && SwigType_type(result) != T_VOID && (!all_result || SwigType_type(all_result) != T_VOID)) {
+ Printv(start, "return ", NULL);
+ }
+
+ bool advance_parm = false;
+
+ if (receiver && use_receiver) {
+ Printv(start, "p.", go_name, NULL);
+ } else if (can_use_receiver && !isStatic(ni) && pi && Getattr(pi, "self")) {
+ // This is an overload of a static function and a non-static
+ // function.
+ assert(num_required > 0);
+ SwigType *tm = goWrapperType(pi, Getattr(pi, "type"), true);
+ String *nm = buildGoName(Getattr(ni, "sym:name"), false, isFriend(ni));
+ Printv(start, "a[0].(", tm, ").", nm, NULL);
+ Delete(nm);
+ Delete(tm);
+ advance_parm = true;
+ } else {
+ Printv(start, go_name, NULL);
+ }
+
+ Printv(start, Getattr(ni, "sym:overname"), "(", NULL);
+
+ bool need_comma = false;
+
+ if (is_director && is_constructor) {
+ Printv(start, "abi", NULL);
+ need_comma = true;
+ }
+ if (is_upcall) {
+ Printv(start, "p", NULL);
+ need_comma = true;
+ }
+ Parm *p = pi;
+ int pn = 0;
+ if (advance_parm) {
+ p = getParm(p);
+ if (p) {
+ p = nextParm(p);
+ }
+ ++pn;
+ }
+ while (pn < num_required) {
+ p = getParm(p);
+
+ if (need_comma) {
+ Printv(start, ", ", NULL);
+ }
+
+ SwigType *tm = goType(p, Getattr(p, "type"));
+ Printf(start, "a[%d].(%s)", pn, tm);
+ Delete(tm);
+
+ need_comma = true;
+ ++pn;
+ p = nextParm(p);
+ }
+
+ String *end = NULL;
+ if (!result || SwigType_type(result) == T_VOID || (all_result && SwigType_type(all_result) == T_VOID)) {
+ end = NewString("");
+ Printv(end, "return", NULL);
+ if (!all_result || SwigType_type(all_result) != T_VOID) {
+ Printv(end, " 0", NULL);
+ }
+ }
+
+ if (num_required == num_arguments) {
+ Printv(f_go_wrappers, "\t\t", start, ")\n", NULL);
+ if (end) {
+ Printv(f_go_wrappers, "\t\t", end, "\n", NULL);
+ }
+ } else {
+ Printv(f_go_wrappers, "\t\tswitch argc {\n", NULL);
+ for (int j = num_required; j <= num_arguments; ++j) {
+ Printf(f_go_wrappers, "\t\tcase %d:\n", j);
+ Printv(f_go_wrappers, "\t\t\t", start, NULL);
+ bool nc = need_comma;
+ for (int k = num_required; k < j; ++k) {
+ if (nc) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ Printf(f_go_wrappers, "a[%d]", k);
+ nc = true;
+ }
+ Printv(f_go_wrappers, ")\n", NULL);
+ if (end) {
+ Printv(f_go_wrappers, "\t\t\t", end, "\n", NULL);
+ }
+ }
+ Printv(f_go_wrappers, "\t\t}\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "\t}\n", NULL);
+
+ if (fn != 0) {
+ Printf(f_go_wrappers, "check_%d:\n", fn);
+ }
+
+ Delete(coll);
+ }
+
+ Printv(f_go_wrappers, "\tpanic(\"No match for overloaded function call\")\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Delete(all_result);
+ Delete(dispatch);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * checkFunctionVisibility()
+ *
+ * Return true if we should write out a function based on its
+ * visibility, false otherwise.
+ * ---------------------------------------------------------------------- */
+
+ bool checkFunctionVisibility(Node *n, Node *parent) {
+ // Write out a public function.
+ if (is_public(n))
+ return true;
+ // Don't write out a private function.
+ if (is_private(n))
+ return false;
+ // Write a protected function for a director class in
+ // dirprot_mode.
+ if (parent == NULL) {
+ return false;
+ }
+ if (dirprot_mode() && Swig_directorclass(parent))
+ return true;
+ // Otherwise don't write out a protected function.
+ return false;
+ }
+
+
+ /* ----------------------------------------------------------------------
+ * exportedName()
+ *
+ * Given a C/C++ name, return a name in Go which will be exported.
+ * If the first character is an upper case letter, this returns a
+ * copy of its argument. If the first character is a lower case
+ * letter, this forces it to upper case. Otherwise, this prepends
+ * 'X'.
+ * ---------------------------------------------------------------------- */
+
+ String *exportedName(String *name) {
+ String *copy = Copy(name);
+ char c = *Char(copy);
+ if (islower(c)) {
+ char l[2];
+ char u[2];
+ l[0] = c;
+ l[1] = '\0';
+ u[0] = toupper(c);
+ u[1] = '\0';
+ Replace(copy, l, u, DOH_REPLACE_FIRST);
+ } else if (!isalpha(c)) {
+ char l[2];
+ char u[3];
+ l[0] = c;
+ l[1] = '\0';
+ u[0] = 'X';
+ u[1] = c;
+ u[2] = '\0';
+ Replace(copy, l, u, DOH_REPLACE_FIRST);
+ }
+ String *ret = Swig_name_mangle(copy);
+ Delete(copy);
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * removeClassname()
+ *
+ * If the name starts with the current class name, followed by an
+ * underscore, remove it. If there is no current class name, this
+ * simply returns a copy of the name. This undoes Swig's way of
+ * recording the class name in a member name.
+ * ---------------------------------------------------------------------- */
+
+ String *removeClassname(String *name) {
+ String *copy = Copy(name);
+ if (class_name) {
+ char *p = Char(name);
+ if (Strncmp(name, class_name, Len(class_name)) == 0 && p[Len(class_name)] == '_') {
+ Replace(copy, class_name, "", DOH_REPLACE_FIRST);
+ Replace(copy, "_", "", DOH_REPLACE_FIRST);
+ }
+ }
+ return copy;
+ }
+
+ /* ----------------------------------------------------------------------
+ * buildGoName()
+ *
+ * Build the name to use for an ordinary function, variable, or
+ * whatever in Go. The name argument is something like the sym:name
+ * attribute of the node. If is_static is false, this could be a
+ * method, and the returned name will be the name of the
+ * method--i.e., it will not include the class name.
+ * ---------------------------------------------------------------------- */
+
+ String *buildGoName(String *name, bool is_static, bool is_friend) {
+ String *nw = NewString("");
+ if (is_static && !is_friend && class_name) {
+ String *c1 = exportedName(class_name);
+ Append(nw, c1);
+ Delete(c1);
+ }
+ String *c2 = removeClassname(name);
+ String *c3 = exportedName(c2);
+ Append(nw, c3);
+ Delete(c2);
+ Delete(c3);
+ String *ret = Swig_name_mangle(nw);
+ Delete(nw);
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * buildGoWrapperName()
+ *
+ * Build the name to use for a Go wrapper function. This is a
+ * function called by the real Go function in order to convert C++
+ * classes from interfaces to pointers, and other such conversions
+ * between the Go type and the C++ type.
+ * ---------------------------------------------------------------------- */
+
+ String *buildGoWrapperName(String *name, String *overname) {
+ String *s1 = NewString("_swig_wrap_");
+ Append(s1, name);
+ String *s2 = Swig_name_mangle(s1);
+ Delete(s1);
+ if (overname) {
+ Append(s2, overname);
+ }
+ return s2;
+ }
+
+ /* ----------------------------------------------------------------------
+ * checkNameConflict()
+ *
+ * Check for a name conflict on the name we are going to use in Go.
+ * These conflicts are likely because of the enforced
+ * capitalization. When we find one, issue a warning and return
+ * false. If the name is OK, return true.
+ * ---------------------------------------------------------------------- */
+
+ bool checkNameConflict(String* name, Node* n, const_String_or_char_ptr scope) {
+ Node *lk = symbolLookup(name, scope);
+ if (lk) {
+ String *n1 = Getattr(n, "sym:name");
+ if (!n1) {
+ n1 = Getattr(n, "name");
+ }
+ String *n2 = Getattr(lk, "sym:name");
+ if (!n2) {
+ n2 = Getattr(lk, "name");
+ }
+ Swig_warning(WARN_GO_NAME_CONFLICT, input_file, line_number,
+ "Ignoring '%s' due to Go name ('%s') conflict with '%s'\n",
+ n1, name, n2);
+ return false;
+ }
+ bool r = addSymbol(name, n, scope) ? true : false;
+ assert(r);
+ return true;
+ }
+
+ /* ----------------------------------------------------------------------
+ * checkIgnoredParameters()
+ *
+ * If any of the parameters of this function, or the return type,
+ * are ignored due to a name conflict, give a warning and return
+ * false.
+ * ---------------------------------------------------------------------- */
+
+ bool checkIgnoredParameters(Node *n, String *go_name) {
+ ParmList *parms = Getattr(n, "parms");
+ if (parms) {
+ Wrapper *dummy = NewWrapper();
+ emit_attach_parmmaps(parms, dummy);
+ int parm_count = emit_num_arguments(parms);
+ Parm *p = parms;
+
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (!checkIgnoredType(n, go_name, Getattr(p, "type"))) {
+ DelWrapper(dummy);
+ return false;
+ }
+ p = nextParm(p);
+ }
+
+ DelWrapper(dummy);
+ }
+
+ if (!checkIgnoredType(n, go_name, Getattr(n, "type"))) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /* ----------------------------------------------------------------------
+ * checkIgnoredType()
+ *
+ * If this type is being ignored due to a name conflict, give a
+ * warning and return false.
+ * ---------------------------------------------------------------------- */
+
+ bool checkIgnoredType(Node *n, String *go_name, SwigType *type) {
+ if (hasGoTypemap(n, type)) {
+ return true;
+ }
+
+ SwigType *t = SwigType_typedef_resolve_all(type);
+
+ bool ret = true;
+ bool is_conflict = false;
+ Node *e = Language::enumLookup(t);
+ if (e) {
+ if (GetFlag(e, "go:conflict")) {
+ is_conflict = true;
+ }
+ } else if (SwigType_issimple(t)) {
+ Node *cn = classLookup(t);
+ if (cn) {
+ if (GetFlag(cn, "go:conflict")) {
+ is_conflict = true;
+ }
+ }
+ } else if (SwigType_ispointer(t) || SwigType_isarray(t) || SwigType_isqualifier(t) || SwigType_isreference(t)) {
+ SwigType *r = Copy(t);
+ if (SwigType_ispointer(r)) {
+ SwigType_del_pointer(r);
+ } else if (SwigType_isarray(r)) {
+ SwigType_del_array(r);
+ } else if (SwigType_isqualifier(r)) {
+ SwigType_del_qualifier(r);
+ } else {
+ SwigType_del_reference(r);
+ }
+
+ if (!checkIgnoredType(n, go_name, r)) {
+ ret = false;
+ }
+
+ Delete(r);
+ }
+
+ if (is_conflict) {
+ String *s = SwigType_str(t, NULL);
+ Swig_warning(WARN_GO_NAME_CONFLICT, input_file, line_number,
+ "Ignoring '%s' (Go name '%s') due to Go name conflict for parameter or result type '%s'\n",
+ Getattr(n, "name"), go_name, s);
+ Delete(s);
+ ret = false;
+ }
+
+ Delete(t);
+
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * goType()
+ *
+ * Given a SWIG type, return a string for the type in Go.
+ * ---------------------------------------------------------------------- */
+
+ String *goType(Node *n, SwigType *type) {
+ return goTypeWithInfo(n, type, false, NULL);
+ }
+
+ /* ----------------------------------------------------------------------
+ * goImType()
+ *
+ * Given a SWIG type, return a string for the intermediate Go type
+ * to pass to C/C++. This is like goType except that it looks for
+ * an imtype typemap entry first.
+ * ---------------------------------------------------------------------- */
+
+ String *goImType(Node *n, SwigType *type) {
+ return goTypeWithInfo(n, type, true, NULL);
+ }
+
+ /* ----------------------------------------------------------------------
+ * goTypeWithInfo()
+ *
+ * Like goType, but return some more information.
+ *
+ * If use_imtype is true, this look for a imtype typemap entry.
+ *
+ * If the p_is_interface parameter is not NULL, this sets
+ * *p_is_interface to indicate whether this type is going to be
+ * represented by a Go interface type. These are cases where the Go
+ * code needs to make some adjustments when passing values back and
+ * forth with C/C++.
+ * ---------------------------------------------------------------------- */
+
+ String *goTypeWithInfo(Node *n, SwigType *type, bool use_imtype, bool *p_is_interface) {
+ if (p_is_interface) {
+ *p_is_interface = false;
+ }
+
+ String *ret = NULL;
+ if (use_imtype) {
+ if (n && Cmp(type, Getattr(n, "type")) == 0) {
+ if (Strcmp(Getattr(n, "nodeType"), "parm") == 0) {
+ ret = Getattr(n, "tmap:imtype");
+ }
+ if (!ret) {
+ ret = Swig_typemap_lookup("imtype", n, "", NULL);
+ }
+ } else {
+ Parm *p = NewParm(type, "goImType", n);
+ ret = Swig_typemap_lookup("imtype", p, "", NULL);
+ Delete(p);
+ }
+ }
+ if (!ret) {
+ if (n && Cmp(type, Getattr(n, "type")) == 0) {
+ if (Strcmp(Getattr(n, "nodeType"), "parm") == 0) {
+ ret = Getattr(n, "tmap:gotype");
+ }
+ if (!ret) {
+ ret = Swig_typemap_lookup("gotype", n, "", NULL);
+ }
+ } else {
+ Parm *p = NewParm(type, "goType", n);
+ ret = Swig_typemap_lookup("gotype", p, "", NULL);
+ Delete(p);
+ }
+ }
+
+ if (ret && Strstr(ret, "$gotypename") != 0) {
+ ret = NULL;
+ }
+
+ if (ret) {
+ return Copy(ret);
+ }
+
+ SwigType *t = SwigType_typedef_resolve_all(type);
+
+ if (SwigType_isenum(t)) {
+ Node *e = Language::enumLookup(t);
+ if (e) {
+ ret = goEnumName(e);
+ } else if (Strcmp(t, "enum ") == 0) {
+ ret = NewString("int");
+ } else {
+ // An unknown enum - one that has not been parsed (neither a C enum forward reference nor a definition) or an ignored enum
+ String *tt = Copy(t);
+ Replace(tt, "enum ", "", DOH_REPLACE_ANY);
+ ret = exportedName(tt);
+ Setattr(undefined_enum_types, t, ret);
+ Delete(tt);
+ }
+ } else if (SwigType_isfunctionpointer(t) || SwigType_isfunction(t)) {
+ ret = NewString("_swig_fnptr");
+ } else if (SwigType_ismemberpointer(t)) {
+ ret = NewString("_swig_memberptr");
+ } else if (SwigType_issimple(t)) {
+ Node *cn = classLookup(t);
+ if (cn) {
+ ret = Getattr(cn, "sym:name");
+ if (!ret) {
+ ret = Getattr(cn, "name");
+ }
+ ret = exportedName(ret);
+
+ Node *cnmod = Getattr(cn, "module");
+ if (!cnmod || Strcmp(Getattr(cnmod, "name"), module) == 0) {
+ Setattr(undefined_types, t, t);
+ } else {
+ String *nw = NewString("");
+ Printv(nw, getModuleName(Getattr(cnmod, "name")), ".", ret, NULL);
+ Delete(ret);
+ ret = nw;
+ }
+ } else {
+ // SWIG does not know about this type.
+ ret = exportedName(t);
+ Setattr(undefined_types, t, t);
+ }
+ if (p_is_interface) {
+ *p_is_interface = true;
+ }
+ } else if (SwigType_ispointer(t) || SwigType_isarray(t)) {
+ SwigType *r = Copy(t);
+ if (SwigType_ispointer(r)) {
+ SwigType_del_pointer(r);
+ } else {
+ SwigType_del_array(r);
+ }
+
+ if (SwigType_type(r) == T_VOID) {
+ ret = NewString("uintptr");
+ } else {
+ bool is_interface;
+ String *base = goTypeWithInfo(n, r, false, &is_interface);
+
+ // At the Go level, an unknown or class type is handled as an
+ // interface wrapping a pointer. This means that if a
+ // function returns the C type X, we will be wrapping the C
+ // type X*. In Go we will call that type X. That means that
+ // if a C function expects X*, we can pass the Go type X. And
+ // that means that when we see the C type X*, we should use
+ // the Go type X.
+
+ // The is_interface variable tells us this. However, it will
+ // be true both for the case of X and for the case of X*. If
+ // r is a pointer here, then we are looking at X**. There is
+ // really no good way for us to handle that.
+ bool is_pointer_to_pointer = false;
+ if (is_interface) {
+ SwigType *c = Copy(r);
+ if (SwigType_isqualifier(c)) {
+ SwigType_del_qualifier(c);
+ if (SwigType_ispointer(c) || SwigType_isarray(c)) {
+ is_pointer_to_pointer = true;
+ }
+ }
+ Delete(c);
+ }
+
+ if (is_interface) {
+ if (!is_pointer_to_pointer) {
+ ret = base;
+ if (p_is_interface) {
+ *p_is_interface = true;
+ }
+ } else {
+ ret = NewString("uintptr");
+ }
+ } else {
+ ret = NewString("*");
+ Append(ret, base);
+ Delete(base);
+ }
+ }
+
+ Delete(r);
+ } else if (SwigType_isreference(t)) {
+ SwigType *r = Copy(t);
+ SwigType_del_reference(r);
+
+ // If this is a const reference, and we are looking at a pointer
+ // to it, then we just use the pointer we already have.
+ bool add_pointer = true;
+ if (SwigType_isqualifier(r)) {
+ String *q = SwigType_parm(r);
+ if (Strcmp(q, "const") == 0) {
+ SwigType *c = Copy(r);
+ SwigType_del_qualifier(c);
+ if (SwigType_ispointer(c)) {
+ add_pointer = false;
+ }
+ Delete(c);
+ }
+ }
+ if (add_pointer) {
+ SwigType_add_pointer(r);
+ }
+ ret = goTypeWithInfo(n, r, false, p_is_interface);
+ Delete(r);
+ } else if (SwigType_isqualifier(t)) {
+ SwigType *r = Copy(t);
+ SwigType_del_qualifier(r);
+ ret = goTypeWithInfo(n, r, false, p_is_interface);
+ Delete(r);
+ } else if (SwigType_isvarargs(t)) {
+ ret = NewString("[]interface{}");
+ }
+
+ Delete(t);
+
+ if (!ret) {
+ Swig_warning(WARN_LANG_NATIVE_UNIMPL, input_file, line_number, "No Go typemap defined for %s\n", SwigType_str(type, 0));
+ ret = NewString("uintptr");
+ }
+
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * cgoTypeForGoValue()
+ *
+ * Given a SWIG type, return a string for the C type to use for the
+ * cgo wrapper code. This always returns a simple identifier, since
+ * it is used in Go code as C.name.
+ *
+ * This sets *c_struct_type if the C type uses a struct where the Go
+ * type uses a simple type. This is true for strings and slices.
+ * When this is true the Go code has to jump through unsafe hoops to
+ * pass the type checker.
+ * ---------------------------------------------------------------------- */
+
+ String *cgoTypeForGoValue(Node *n, SwigType *type, bool *c_struct_type) {
+ *c_struct_type = false;
+
+ bool is_interface;
+ String *go_type = goTypeWithInfo(n, type, true, &is_interface);
+ if (is_interface) {
+ Delete(go_type);
+ return NewString("uintptr_t");
+ }
+ if (Strcmp(go_type, "uintptr") == 0) {
+ Delete(go_type);
+ return NewString("uintptr_t");
+ }
+ if (((char*)Char(go_type))[0] == '*') {
+ // Treat all pointers as void*. There is no meaningful type
+ // checking going on here anyhow, and that lets us avoid
+ // worrying about defining the base type of the pointer.
+ Delete(go_type);
+ return NewString("swig_voidp");
+ }
+
+ // Check for some Go types that are really pointers under the covers.
+ bool is_hidden_pointer = Strncmp(go_type, "func(", 5) == 0 || Strncmp(go_type, "map[", 4) == 0 || Strncmp(go_type, "chan ", 5) == 0;
+
+ Delete(go_type);
+
+ String *ct = Getattr(n, "emit:cgotype");
+ if (ct) {
+ *c_struct_type = Getattr(n, "emit:cgotypestruct") ? true : false;
+ return Copy(ct);
+ }
+
+ String *t = Copy(type);
+ if (SwigType_isarray(t)) {
+ SwigType_del_array(t);
+ SwigType_add_pointer(t);
+ }
+
+ bool add_typedef = true;
+
+ static int count;
+ ++count;
+ ct = NewStringf("swig_type_%d", count);
+
+ String *gct = gcCTypeForGoValue(n, t, ct);
+ Delete(t);
+
+ if (Strncmp(gct, "_gostring_", 10) == 0 || Strncmp(gct, "_goslice_", 9) == 0) {
+ *c_struct_type = true;
+ Setattr(n, "emit:cgotypestruct", type);
+ } else {
+ char *p = Strstr(gct, ct);
+ if (p != NULL && p > (char*)Char(gct) && p[-1] == '*' && p[Len(ct)] == '\0') {
+ // Treat all pointers as void*. See above.
+ Delete(ct);
+ --count;
+ ct = NewString("swig_voidp");
+ add_typedef = false;
+ if (is_hidden_pointer) {
+ // A Go type that is really a pointer, like func, map, chan,
+ // is being represented in C by a pointer. This is fine,
+ // but we have to memcpy the type rather than simply
+ // converting it.
+ *c_struct_type = true;
+ Setattr(n, "emit:cgotypestruct", type);
+ }
+ }
+
+ if (Strncmp(gct, "bool ", 5) == 0) {
+ // Change the C++ type bool to the C type _Bool.
+ Replace(gct, "bool", "_Bool", DOH_REPLACE_FIRST);
+ }
+ if (Strncmp(gct, "intgo ", 6) == 0) {
+ // We #define intgo to swig_intgo for the cgo comment.
+ Replace(gct, "intgo", "swig_intgo", DOH_REPLACE_FIRST);
+ }
+ p = Strstr(gct, ct);
+ if (p != NULL && p > (char*)Char(gct) && p[-1] == ' ' && p[Len(ct)] == '\0') {
+ String *q = NewStringWithSize(gct, Len(gct) - Len(ct) - 1);
+ if (validIdentifier(q)) {
+ // This is a simple type name, and we can use it directly.
+ Delete(ct);
+ --count;
+ ct = q;
+ add_typedef = false;
+ }
+ }
+ }
+ if (add_typedef) {
+ Printv(f_cgo_comment_typedefs, "typedef ", gct, ";\n", NULL);
+ }
+
+ Setattr(n, "emit:cgotype", ct);
+
+ Delete(gct);
+
+ return Copy(ct);
+ }
+
+ /* ----------------------------------------------------------------------
+ * goWrapperType()
+ *
+ * Given a type, return a string for the type to use for the wrapped
+ * Go function. This function exists because for a C++ class we
+ * need to convert interface and reference types.
+ * ---------------------------------------------------------------------- */
+
+ String *goWrapperType(Node *n, SwigType *type, bool is_result) {
+ bool is_interface;
+ String *ret = goTypeWithInfo(n, type, true, &is_interface);
+
+ // If this is an interface, we want to pass the real type.
+ if (is_interface) {
+ Delete(ret);
+ if (!is_result) {
+ ret = NewString("uintptr");
+ } else {
+ SwigType *ty = SwigType_typedef_resolve_all(type);
+ while (true) {
+ if (SwigType_ispointer(ty)) {
+ SwigType_del_pointer(ty);
+ } else if (SwigType_isarray(ty)) {
+ SwigType_del_array(ty);
+ } else if (SwigType_isreference(ty)) {
+ SwigType_del_reference(ty);
+ } else if (SwigType_isqualifier(ty)) {
+ SwigType_del_qualifier(ty);
+ } else {
+ break;
+ }
+ }
+ assert(SwigType_issimple(ty));
+ String *p = goCPointerType(ty, true);
+ Delete(ty);
+ ret = p;
+ }
+ }
+
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * goOverloadType()
+ *
+ * Given a type, return the Go type to use when dispatching of
+ * overloaded functions. This is normally just the usual Go type.
+ * However, for a C++ class, the usual Go type is an interface type.
+ * And if that interface type represents a C++ type that SWIG does
+ * not know about, then the interface type generated for any C++
+ * class will match that interface. So for that case, we match on
+ * the underlying integer type.
+ *
+ * It has to work this way so that we can handle a derived type of a
+ * %ignore'd type. It's unlikely that anybody will have a value of
+ * an undefined type, but we support it because it worked in the
+ * past.
+ * ---------------------------------------------------------------------- */
+
+ String *goOverloadType(Node *n, SwigType *type) {
+ SwigType *ty = SwigType_typedef_resolve_all(type);
+ while (true) {
+ if (SwigType_ispointer(ty)) {
+ SwigType_del_pointer(ty);
+ } else if (SwigType_isarray(ty)) {
+ SwigType_del_array(ty);
+ } else if (SwigType_isreference(ty)) {
+ SwigType_del_reference(ty);
+ } else if (SwigType_isqualifier(ty)) {
+ SwigType_del_qualifier(ty);
+ } else {
+ break;
+ }
+ }
+
+ if (Getattr(undefined_types, ty) && !Getattr(defined_types, ty)) {
+ return goWrapperType(n, type, true);
+ }
+
+ return goType(n, type);
+ }
+
+ /* ----------------------------------------------------------------------
+ * goCPointerType()
+ *
+ * Return the name of the Go type to use for the C pointer value.
+ * The regular C type is the name of an interface type which wraps a
+ * pointer whose name is returned by this function.
+ * ---------------------------------------------------------------------- */
+
+ String *goCPointerType(SwigType *type, bool add_to_hash) {
+ SwigType *ty = SwigType_typedef_resolve_all(type);
+ Node *cn = classLookup(ty);
+ String *ex;
+ String *ret;
+ if (!cn) {
+ if (add_to_hash) {
+ Setattr(undefined_types, ty, ty);
+ }
+ ret = NewString("Swigcptr");
+ ex = exportedName(ty);
+ Append(ret, ex);
+ } else {
+ String *cname = Getattr(cn, "sym:name");
+ if (!cname) {
+ cname = Getattr(cn, "name");
+ }
+ ex = exportedName(cname);
+ Node *cnmod = Getattr(cn, "module");
+ if (!cnmod || Strcmp(Getattr(cnmod, "name"), module) == 0) {
+ if (add_to_hash) {
+ Setattr(undefined_types, ty, ty);
+ }
+ ret = NewString("Swigcptr");
+ Append(ret, ex);
+ } else {
+ ret = NewString("");
+ Printv(ret, getModuleName(Getattr(cnmod, "name")), ".Swigcptr", ex, NULL);
+ }
+ }
+ Delete(ty);
+ Delete(ex);
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * gcCTypeForGoValue()
+ *
+ * Given a type, return the C/C++ type which will be used to catch
+ * the value in Go. This is the 6g/8g version.
+ * ---------------------------------------------------------------------- */
+
+ String *gcCTypeForGoValue(Node *n, SwigType *type, String *name) {
+ bool is_interface;
+ String *gt = goTypeWithInfo(n, type, true, &is_interface);
+
+ String *tail = NewString("");
+ SwigType *t = SwigType_typedef_resolve_all(type);
+ if (!SwigType_isreference(t)) {
+ while (Strncmp(gt, "*", 1) == 0) {
+ Replace(gt, "*", "", DOH_REPLACE_FIRST);
+ Printv(tail, "*", NULL);
+ }
+ }
+ Delete(t);
+
+ bool is_string = Strcmp(gt, "string") == 0;
+ bool is_slice = Strncmp(gt, "[]", 2) == 0;
+ bool is_function = Strcmp(gt, "_swig_fnptr") == 0;
+ bool is_member = Strcmp(gt, "_swig_memberptr") == 0;
+ bool is_complex64 = Strcmp(gt, "complex64") == 0;
+ bool is_complex128 = Strcmp(gt, "complex128") == 0;
+ bool is_bool = false;
+ bool is_int8 = false;
+ bool is_int16 = false;
+ bool is_int = Strcmp(gt, "int") == 0 || Strcmp(gt, "uint") == 0;
+ bool is_int32 = false;
+ bool is_int64 = false;
+ bool is_float32 = false;
+ bool is_float64 = false;
+
+ bool has_typemap = (n != NULL && Getattr(n, "tmap:gotype") != NULL) || hasGoTypemap(n, type);
+ if (has_typemap) {
+ is_bool = Strcmp(gt, "bool") == 0;
+ is_int8 = Strcmp(gt, "int8") == 0 || Strcmp(gt, "uint8") == 0 || Strcmp(gt, "byte") == 0;
+ is_int16 = Strcmp(gt, "int16") == 0 || Strcmp(gt, "uint16") == 0;
+ is_int32 = Strcmp(gt, "int32") == 0 || Strcmp(gt, "uint32") == 0;
+ is_int64 = Strcmp(gt, "int64") == 0 || Strcmp(gt, "uint64") == 0;
+ is_float32 = Strcmp(gt, "float32") == 0;
+ is_float64 = Strcmp(gt, "float64") == 0;
+ }
+ Delete(gt);
+
+ String *ret;
+ if (is_string) {
+ // Note that we don't turn a reference to a string into a
+ // pointer to a string. Strings are immutable anyhow.
+ ret = NewString("");
+ Printv(ret, "_gostring_", tail, " ", name, NULL);
+ Delete(tail);
+ return ret;
+ } else if (is_slice) {
+ // Slices are always passed as a _goslice_, whether or not references
+ // are involved.
+ ret = NewString("");
+ Printv(ret, "_goslice_", tail, " ", name, NULL);
+ Delete(tail);
+ return ret;
+ } else if (is_function || is_member) {
+ ret = NewString("");
+ Printv(ret, "void*", tail, " ", name, NULL);
+ Delete(tail);
+ return ret;
+ } else if (is_complex64) {
+ ret = NewString("_Complex float ");
+ } else if (is_complex128) {
+ ret = NewString("_Complex double ");
+ } else if (is_interface) {
+ SwigType *t = SwigType_typedef_resolve_all(type);
+ if (SwigType_ispointer(t)) {
+ SwigType_del_pointer(t);
+ }
+ if (SwigType_isreference(t)) {
+ SwigType_del_reference(t);
+ }
+ SwigType_add_pointer(t);
+ ret = SwigType_lstr(t, name);
+ Delete(t);
+ Delete(tail);
+ return ret;
+ } else {
+ SwigType *t = SwigType_typedef_resolve_all(type);
+ if (!has_typemap && SwigType_isreference(t)) {
+ // A const reference to a known type, or to a pointer, is not
+ // mapped to a pointer.
+ SwigType_del_reference(t);
+ if (SwigType_isqualifier(t)) {
+ String *q = SwigType_parm(t);
+ if (Strcmp(q, "const") == 0) {
+ SwigType_del_qualifier(t);
+ if (hasGoTypemap(n, t) || SwigType_ispointer(t)) {
+ if (is_int) {
+ ret = NewString("intgo ");
+ Append(ret, name);
+ } else if (is_int64) {
+ ret = NewString("long long ");
+ Append(ret, name);
+ } else {
+ ret = SwigType_lstr(t, name);
+ }
+ Delete(q);
+ Delete(t);
+ Delete(tail);
+ return ret;
+ }
+ }
+ Delete(q);
+ }
+ }
+
+ if (Language::enumLookup(t) != NULL) {
+ is_int = true;
+ } else {
+ SwigType *tstripped = SwigType_strip_qualifiers(t);
+ if (SwigType_isenum(tstripped))
+ is_int = true;
+ Delete(tstripped);
+ }
+
+ Delete(t);
+ if (is_bool) {
+ ret = NewString("bool ");
+ } else if (is_int8) {
+ ret = NewString("char ");
+ } else if (is_int16) {
+ ret = NewString("short ");
+ } else if (is_int) {
+ ret = NewString("intgo ");
+ } else if (is_int32) {
+ ret = NewString("int ");
+ } else if (is_int64) {
+ ret = NewString("long long ");
+ } else if (is_float32) {
+ ret = NewString("float ");
+ } else if (is_float64) {
+ ret = NewString("double ");
+ } else {
+ Delete(tail);
+ return SwigType_lstr(type, name);
+ }
+ }
+
+ Append(ret, tail);
+ if (!has_typemap && SwigType_isreference(type)) {
+ Append(ret, "* ");
+ }
+ Append(ret, name);
+ Delete(tail);
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * gccgoCTypeForGoValue()
+ *
+ * Given a type, return the C/C++ type which will be used to catch
+ * the value in Go. This is the gccgo version.
+ * ---------------------------------------------------------------------- */
+
+ String *gccgoCTypeForGoValue(Node *n, SwigType *type, String *name) {
+ return gcCTypeForGoValue(n, type, name);
+ }
+
+ /* ----------------------------------------------------------------------
+ * goTypeIsInterface
+ *
+ * Return whether this C++ type is represented as an interface type
+ * in Go. These types require adjustments in the Go code when
+ * passing them back and forth between Go and C++.
+ * ---------------------------------------------------------------------- */
+
+ bool goTypeIsInterface(Node *n, SwigType *type) {
+ bool is_interface;
+ Delete(goTypeWithInfo(n, type, false, &is_interface));
+ return is_interface;
+ }
+
+ /* ----------------------------------------------------------------------
+ * hasGoTypemap
+ *
+ * Return whether a type has a "gotype" typemap entry.
+ * ---------------------------------------------------------------------- */
+
+ bool hasGoTypemap(Node *n, SwigType *type) {
+ Parm *p = NewParm(type, "test", n);
+ SwigType *tm = Swig_typemap_lookup("gotype", p, "", NULL);
+ Delete(p);
+ if (tm && Strstr(tm, "$gotypename") == 0) {
+ Delete(tm);
+ return true;
+ }
+ Delete(tm);
+ return false;
+ }
+
+ /* ----------------------------------------------------------------------
+ * goEnumName()
+ *
+ * Given an enum node, return a string to use for the enum type in Go.
+ * ---------------------------------------------------------------------- */
+
+ String *goEnumName(Node *n) {
+ String *ret = Getattr(n, "go:enumname");
+ if (ret) {
+ return Copy(ret);
+ }
+
+ if (Equal(Getattr(n, "type"), "enum ")) {
+ return NewString("int");
+ }
+
+ String *type = Getattr(n, "enumtype");
+ assert(type);
+ char *p = Char(type);
+ int len = Len(type);
+ String *s = NewString("");
+ bool capitalize = true;
+ for (int i = 0; i < len; ++i, ++p) {
+ if (*p == ':') {
+ ++i;
+ ++p;
+ assert(*p == ':');
+ capitalize = true;
+ } else if (capitalize) {
+ Putc(toupper(*p), s);
+ capitalize = false;
+ } else {
+ Putc(*p, s);
+ }
+ }
+
+ ret = Swig_name_mangle(s);
+ Delete(s);
+ return ret;
+ }
+
+
+ /* ----------------------------------------------------------------------
+ * getParm()
+ *
+ * Get the real parameter to use.
+ * ---------------------------------------------------------------------- */
+
+ Parm *getParm(Parm *p) {
+ while (p && checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+ return p;
+ }
+
+ /* ----------------------------------------------------------------------
+ * nextParm()
+ *
+ * Return the next parameter.
+ * ---------------------------------------------------------------------- */
+
+ Parm *nextParm(Parm *p) {
+ if (!p) {
+ return NULL;
+ } else if (Getattr(p, "tmap:in")) {
+ return Getattr(p, "tmap:in:next");
+ } else {
+ return nextSibling(p);
+ }
+ }
+
+ /* ----------------------------------------------------------------------
+ * isStatic
+ *
+ * Return whether a node should be considered as static rather than
+ * as a member.
+ * ---------------------------------------------------------------------- */
+
+ bool isStatic(Node *n) {
+ String *storage = Getattr(n, "storage");
+ return (storage && (Swig_storage_isstatic(n) || Strcmp(storage, "friend") == 0) && (!SmartPointer || !Getattr(n, "allocate:smartpointeraccess")));
+ }
+
+ /* ----------------------------------------------------------------------
+ * isFriend
+ *
+ * Return whether a node is a friend.
+ * ---------------------------------------------------------------------- */
+
+ bool isFriend(Node *n) {
+ String *storage = Getattr(n, "storage");
+ return storage && Strcmp(storage, "friend") == 0;
+ }
+
+ /* ----------------------------------------------------------------------
+ * goGetattr
+ *
+ * Fetch an attribute from a node but return NULL if it is the empty string.
+ * ---------------------------------------------------------------------- */
+ Node *goGetattr(Node *n, const char *name) {
+ Node *ret = Getattr(n, name);
+ if (ret != NULL && Len(ret) == 0) {
+ ret = NULL;
+ }
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * goTypemapLookup
+ *
+ * Look up a typemap but return NULL if it is the empty string.
+ * ---------------------------------------------------------------------- */
+ String *goTypemapLookup(const char *name, Node *node, const char *lname) {
+ String *ret = Swig_typemap_lookup(name, node, lname, NULL);
+ if (ret != NULL && Len(ret) == 0) {
+ ret = NULL;
+ }
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * getModuleName
+ *
+ * Return the name of a module. This is different from module path:
+ * "some/path/to/module" -> "module".
+ * ---------------------------------------------------------------------- */
+
+ String *getModuleName(String *module_path) {
+ char *suffix = strrchr(Char(module_path), '/');
+ if (suffix == NULL) {
+ return module_path;
+ }
+ return Str(suffix + 1);
+ }
+
+}; /* class GO */
+
+/* -----------------------------------------------------------------------------
+ * swig_go() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_go() {
+ return new GO();
+}
+extern "C" Language *swig_go(void) {
+ return new_swig_go();
+}
+
+/* -----------------------------------------------------------------------------
+ * Static member variables
+ * ----------------------------------------------------------------------------- */
+
+// Usage message.
+const char * const GO::usage = "\
+Go Options (available with -go)\n\
+ -cgo - Generate cgo input files\n\
+ -no-cgo - Do not generate cgo input files\n\
+ -gccgo - Generate code for gccgo rather than gc\n\
+ -go-pkgpath <p> - Like gccgo -fgo-pkgpath option\n\
+ -go-prefix <p> - Like gccgo -fgo-prefix option\n\
+ -import-prefix <p> - Prefix to add to %import directives\n\
+ -intgosize <s> - Set size of Go int type--32 or 64 bits\n\
+ -package <name> - Set name of the Go package to <name>\n\
+ -use-shlib - Force use of a shared library\n\
+ -soname <name> - Set shared library holding C/C++ code to <name>\n\
+\n";
diff --git a/contrib/tools/swig/Source/Modules/guile.cxx b/contrib/tools/swig/Source/Modules/guile.cxx
new file mode 100644
index 00000000000..461c69e5034
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/guile.cxx
@@ -0,0 +1,1683 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * guile.cxx
+ *
+ * Guile language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+
+#include <ctype.h>
+
+// Note string broken in half for compilers that can't handle long strings
+static const char *usage = "\
+Guile Options (available with -guile)\n\
+ -emitsetters - Emit procedures-with-setters for variables\n\
+ and structure slots.\n\
+ -emitslotaccessors - Emit accessor methods for all GOOPS slots\n" "\
+ -exportprimitive - Add the (export ...) code from scmstub into the\n\
+ GOOPS file.\n\
+ -goopsprefix <prefix> - Prepend <prefix> to all goops identifiers\n\
+ -Linkage <lstyle> - Use linkage protocol <lstyle> (default `simple')\n\
+ Use `module' for native Guile module linking\n\
+ (requires Guile >= 1.5.0). Use `passive' for\n\
+ passive linking (no C-level module-handling code),\n\
+ `ltdlmod' for Guile's old dynamic module\n\
+ convention (Guile <= 1.4), or `hobbit' for hobbit\n\
+ modules.\n\
+ -onlysetters - Don't emit traditional getter and setter\n\
+ procedures for structure slots,\n\
+ only emit procedures-with-setters.\n\
+ -package <name> - Set the path of the module to <name>\n\
+ (default NULL)\n\
+ -prefix <name> - Use <name> as prefix [default \"gswig_\"]\n\
+ -procdoc <file> - Output procedure documentation to <file>\n\
+ -procdocformat <format> - Output procedure documentation in <format>;\n\
+ one of `guile-1.4', `plain', `texinfo'\n\
+ -proxy - Export GOOPS class definitions\n\
+ -primsuffix <suffix> - Name appended to primitive module when exporting\n\
+ GOOPS classes. (default = \"primitive\")\n\
+ -scmstub - Output Scheme file with module declaration and\n\
+ exports; only with `passive' and `simple' linkage\n\
+ -useclassprefix - Prepend the class name to all goops identifiers\n\
+\n";
+
+static File *f_begin = 0;
+static File *f_runtime = 0;
+static File *f_header = 0;
+static File *f_wrappers = 0;
+static File *f_init = 0;
+
+
+static String *prefix = NewString("gswig_");
+static char *module = 0;
+static String *package = 0;
+static enum {
+ GUILE_LSTYLE_SIMPLE, // call `SWIG_init()'
+ GUILE_LSTYLE_PASSIVE, // passive linking (no module code)
+ GUILE_LSTYLE_MODULE, // native guile module linking (Guile >= 1.4.1)
+ GUILE_LSTYLE_LTDLMOD_1_4, // old (Guile <= 1.4) dynamic module convention
+ GUILE_LSTYLE_HOBBIT // use (hobbit4d link)
+} linkage = GUILE_LSTYLE_SIMPLE;
+
+static File *procdoc = 0;
+static bool scmstub = false;
+static String *scmtext;
+static bool goops = false;
+static String *goopstext;
+static String *goopscode;
+static String *goopsexport;
+
+static enum {
+ GUILE_1_4,
+ PLAIN,
+ TEXINFO
+} docformat = GUILE_1_4;
+
+static int emit_setters = 0;
+static int only_setters = 0;
+static int emit_slot_accessors = 0;
+static int struct_member = 0;
+
+static String *beforereturn = 0;
+static String *return_nothing_doc = 0;
+static String *return_one_doc = 0;
+static String *return_multi_doc = 0;
+
+static String *exported_symbols = 0;
+
+static int exporting_destructor = 0;
+static String *swigtype_ptr = 0;
+
+/* GOOPS stuff */
+static String *primsuffix = 0;
+static String *class_name = 0;
+static String *short_class_name = 0;
+static String *goops_class_methods;
+static int in_class = 0;
+static int have_constructor = 0;
+static int useclassprefix = 0; // -useclassprefix argument
+static String *goopsprefix = 0; // -goopsprefix argument
+static int primRenamer = 0; // if (use-modules ((...) :renamer ...) is exported to GOOPS file
+static int exportprimitive = 0; // -exportprimitive argument
+static String *memberfunction_name = 0;
+
+extern "C" {
+ static int has_classname(Node *class_node) {
+ return Getattr(class_node, "guile:goopsclassname") ? 1 : 0;
+ }
+}
+
+class GUILE:public Language {
+public:
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+ int i;
+
+ SWIG_library_directory("guile");
+ SWIG_typemap_lang("guile");
+
+ // Look for certain command line options
+ for (i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ SWIG_exit(EXIT_SUCCESS);
+ } else if (strcmp(argv[i], "-prefix") == 0) {
+ if (argv[i + 1]) {
+ prefix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else 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], "-Linkage") == 0 || strcmp(argv[i], "-linkage") == 0) {
+ if (argv[i + 1]) {
+ if (0 == strcmp(argv[i + 1], "ltdlmod"))
+ linkage = GUILE_LSTYLE_LTDLMOD_1_4;
+ else if (0 == strcmp(argv[i + 1], "hobbit"))
+ linkage = GUILE_LSTYLE_HOBBIT;
+ else if (0 == strcmp(argv[i + 1], "simple"))
+ linkage = GUILE_LSTYLE_SIMPLE;
+ else if (0 == strcmp(argv[i + 1], "passive"))
+ linkage = GUILE_LSTYLE_PASSIVE;
+ else if (0 == strcmp(argv[i + 1], "module"))
+ linkage = GUILE_LSTYLE_MODULE;
+ else
+ Swig_arg_error();
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-procdoc") == 0) {
+ if (argv[i + 1]) {
+ procdoc = NewFile(argv[i + 1], "w", SWIG_output_files());
+ if (!procdoc) {
+ FileErrorDisplay(argv[i + 1]);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-procdocformat") == 0) {
+ if (strcmp(argv[i + 1], "guile-1.4") == 0)
+ docformat = GUILE_1_4;
+ else if (strcmp(argv[i + 1], "plain") == 0)
+ docformat = PLAIN;
+ else if (strcmp(argv[i + 1], "texinfo") == 0)
+ docformat = TEXINFO;
+ else
+ Swig_arg_error();
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else if (strcmp(argv[i], "-emit-setters") == 0 || strcmp(argv[i], "-emitsetters") == 0) {
+ emit_setters = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-only-setters") == 0 || strcmp(argv[i], "-onlysetters") == 0) {
+ emit_setters = 1;
+ only_setters = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-emit-slot-accessors") == 0 || strcmp(argv[i], "-emitslotaccessors") == 0) {
+ emit_slot_accessors = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-scmstub") == 0) {
+ scmstub = true;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-shadow") == 0) || ((strcmp(argv[i], "-proxy") == 0))) {
+ goops = true;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-gh") == 0) {
+ Printf(stderr, "Deprecated command line option: -gh. Wrappers are always generated for the SCM interface. See documentation for more information regarding the deprecated GH interface.\n");
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-scm") == 0) {
+ Printf(stderr, "Deprecated command line option: -scm. Wrappers are always generated for the SCM interface. See documentation for more information regarding the deprecated GH interface.\n");
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-primsuffix") == 0) {
+ if (argv[i + 1]) {
+ primsuffix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-goopsprefix") == 0) {
+ if (argv[i + 1]) {
+ goopsprefix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-useclassprefix") == 0) {
+ useclassprefix = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-exportprimitive") == 0) {
+ exportprimitive = 1;
+ // should use Swig_warning() here?
+ Swig_mark_arg(i);
+ }
+ }
+ }
+
+ // set default value for primsuffix
+ if (!primsuffix)
+ primsuffix = NewString("primitive");
+
+ //goops support can only be enabled if passive or module linkage is used
+ if (goops) {
+ if (linkage != GUILE_LSTYLE_PASSIVE && linkage != GUILE_LSTYLE_MODULE) {
+ Printf(stderr, "guile: GOOPS support requires passive or module linkage\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+
+ if (goops) {
+ // -proxy implies -emit-setters
+ emit_setters = 1;
+ }
+
+ if ((linkage == GUILE_LSTYLE_PASSIVE && scmstub) || linkage == GUILE_LSTYLE_MODULE)
+ primRenamer = 1;
+
+ if (exportprimitive && primRenamer) {
+ // should use Swig_warning() ?
+ Printf(stderr, "guile: Warning: -exportprimitive only makes sense with passive linkage without a scmstub.\n");
+ }
+
+ // Make sure `prefix' ends in an underscore
+ if (prefix) {
+ const char *px = Char(prefix);
+ if (px[Len(prefix) - 1] != '_')
+ Printf(prefix, "_");
+ }
+
+ /* Add a symbol for this module */
+ Preprocessor_define("SWIGGUILE 1", 0);
+ /* Read in default typemaps */
+ SWIG_config_file("guile_scm.swg");
+ allow_overloading();
+
+ }
+
+ /* ------------------------------------------------------------
+ * top()
+ * ------------------------------------------------------------ */
+
+ virtual int top(Node *n) {
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+
+ scmtext = NewString("");
+ Swig_register_filebyname("scheme", scmtext);
+ exported_symbols = NewString("");
+ goopstext = NewString("");
+ Swig_register_filebyname("goops", goopstext);
+ goopscode = NewString("");
+ goopsexport = NewString("");
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n\n#ifndef SWIGGUILE\n#define SWIGGUILE\n#endif\n\n");
+
+ /* Write out directives and declarations */
+
+ module = Swig_copy_string(Char(Getattr(n, "name")));
+
+ switch (linkage) {
+ case GUILE_LSTYLE_SIMPLE:
+ /* Simple linkage; we have to export the SWIG_init function. The user can
+ rename the function by a #define. */
+ Printf(f_runtime, "#define SWIG_GUILE_INIT_STATIC extern\n");
+ break;
+ default:
+ /* Other linkage; we make the SWIG_init function static */
+ Printf(f_runtime, "#define SWIG_GUILE_INIT_STATIC static\n");
+ break;
+ }
+
+ if (CPlusPlus) {
+ Printf(f_runtime, "extern \"C\" {\n\n");
+ }
+ Printf(f_runtime, "SWIG_GUILE_INIT_STATIC void\nSWIG_init (void);\n");
+ if (CPlusPlus) {
+ Printf(f_runtime, "\n}\n");
+ }
+
+ Printf(f_runtime, "\n");
+
+ Language::top(n);
+
+ /* Close module */
+
+ Printf(f_wrappers, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
+
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+
+ Printf(f_init, "}\n\n");
+ Printf(f_init, "#ifdef __cplusplus\n}\n#endif\n");
+
+ String *module_name = NewString("");
+
+ if (!module)
+ Printv(module_name, "swig", NIL);
+ else {
+ if (package)
+ Printf(module_name, "%s/%s", package, module);
+ else
+ Printv(module_name, module, NIL);
+ }
+ emit_linkage(module_name);
+
+ Delete(module_name);
+
+ if (procdoc) {
+ Delete(procdoc);
+ procdoc = NULL;
+ }
+ Delete(goopscode);
+ Delete(goopsexport);
+ Delete(goopstext);
+
+ /* Close all of the files */
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+ Dump(f_wrappers, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_runtime);
+ Delete(f_begin);
+ return SWIG_OK;
+ }
+
+ void emit_linkage(String *module_name) {
+ String *module_func = NewString("");
+
+ if (CPlusPlus) {
+ Printf(f_init, "extern \"C\" {\n\n");
+ }
+
+ Printv(module_func, module_name, NIL);
+ Replaceall(module_func, "-", "_");
+
+ switch (linkage) {
+ case GUILE_LSTYLE_SIMPLE:
+ Printf(f_init, "\n/* Linkage: simple */\n");
+ break;
+ case GUILE_LSTYLE_PASSIVE:
+ Printf(f_init, "\n/* Linkage: passive */\n");
+ Replaceall(module_func, "/", "_");
+ Insert(module_func, 0, "scm_init_");
+ Append(module_func, "_module");
+
+ Printf(f_init, "SCM\n%s (void)\n{\n", module_func);
+ Printf(f_init, " SWIG_init();\n");
+ Printf(f_init, " return SCM_UNSPECIFIED;\n");
+ Printf(f_init, "}\n");
+ break;
+ case GUILE_LSTYLE_LTDLMOD_1_4:
+ Printf(f_init, "\n/* Linkage: ltdlmod */\n");
+ Replaceall(module_func, "/", "_");
+ Insert(module_func, 0, "scm_init_");
+ Append(module_func, "_module");
+ Printf(f_init, "SCM\n%s (void)\n{\n", module_func);
+ {
+ String *mod = NewString(module_name);
+ Replaceall(mod, "/", " ");
+ Printf(f_init, " scm_register_module_xxx (\"%s\", (void *) SWIG_init);\n", mod);
+ Printf(f_init, " return SCM_UNSPECIFIED;\n");
+ Delete(mod);
+ }
+ Printf(f_init, "}\n");
+ break;
+ case GUILE_LSTYLE_MODULE:
+ Printf(f_init, "\n/* Linkage: module */\n");
+ Replaceall(module_func, "/", "_");
+ Insert(module_func, 0, "scm_init_");
+ Append(module_func, "_module");
+
+ Printf(f_init, "static void SWIG_init_helper(void *data)\n");
+ Printf(f_init, "{\n SWIG_init();\n");
+ if (Len(exported_symbols) > 0)
+ Printf(f_init, " scm_c_export(%sNULL);", exported_symbols);
+ Printf(f_init, "\n}\n\n");
+
+ Printf(f_init, "SCM\n%s (void)\n{\n", module_func);
+ {
+ String *mod = NewString(module_name);
+ if (goops)
+ Printv(mod, "-", primsuffix, NIL);
+ Replaceall(mod, "/", " ");
+ Printf(f_init, " scm_c_define_module(\"%s\",\n", mod);
+ Printf(f_init, " SWIG_init_helper, NULL);\n");
+ Printf(f_init, " return SCM_UNSPECIFIED;\n");
+ Delete(mod);
+ }
+ Printf(f_init, "}\n");
+ break;
+ case GUILE_LSTYLE_HOBBIT:
+ Printf(f_init, "\n/* Linkage: hobbit */\n");
+ Replaceall(module_func, "/", "_slash_");
+ Insert(module_func, 0, "scm_init_");
+ Printf(f_init, "SCM\n%s (void)\n{\n", module_func);
+ {
+ String *mod = NewString(module_name);
+ Replaceall(mod, "/", " ");
+ Printf(f_init, " scm_register_module_xxx (\"%s\", (void *) SWIG_init);\n", mod);
+ Printf(f_init, " return SCM_UNSPECIFIED;\n");
+ Delete(mod);
+ }
+ Printf(f_init, "}\n");
+ break;
+ default:
+ abort(); // for now
+ }
+
+ if (scmstub) {
+ /* Emit Scheme stub if requested */
+ String *primitive_name = NewString(module_name);
+ if (goops)
+ Printv(primitive_name, "-", primsuffix, NIL);
+
+ String *mod = NewString(primitive_name);
+ Replaceall(mod, "/", " ");
+
+ String *fname = NewStringf("%s%s.scm",
+ SWIG_output_directory(),
+ primitive_name);
+ Delete(primitive_name);
+ File *scmstubfile = NewFile(fname, "w", SWIG_output_files());
+ if (!scmstubfile) {
+ FileErrorDisplay(fname);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(fname);
+
+ Swig_banner_target_lang(scmstubfile, ";;;");
+ Printf(scmstubfile, "\n");
+ if (linkage == GUILE_LSTYLE_SIMPLE || linkage == GUILE_LSTYLE_PASSIVE)
+ Printf(scmstubfile, "(define-module (%s))\n\n", mod);
+ Delete(mod);
+ Printf(scmstubfile, "%s", scmtext);
+ if ((linkage == GUILE_LSTYLE_SIMPLE || linkage == GUILE_LSTYLE_PASSIVE)
+ && Len(exported_symbols) > 0) {
+ String *ex = NewString(exported_symbols);
+ Replaceall(ex, ", ", "\n ");
+ Replaceall(ex, "\"", "");
+ Chop(ex);
+ Printf(scmstubfile, "\n(export %s)\n", ex);
+ Delete(ex);
+ }
+ Delete(scmstubfile);
+ }
+
+ if (goops) {
+ String *mod = NewString(module_name);
+ Replaceall(mod, "/", " ");
+
+ String *fname = NewStringf("%s%s.scm", SWIG_output_directory(),
+ module_name);
+ File *goopsfile = NewFile(fname, "w", SWIG_output_files());
+ if (!goopsfile) {
+ FileErrorDisplay(fname);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(fname);
+ Swig_banner_target_lang(goopsfile, ";;;");
+ Printf(goopsfile, "\n");
+ Printf(goopsfile, "(define-module (%s))\n", mod);
+ Printf(goopsfile, "%s\n", goopstext);
+ Printf(goopsfile, "(use-modules (oop goops) (Swig common))\n");
+ if (primRenamer) {
+ Printf(goopsfile, "(use-modules ((%s-%s) :renamer (symbol-prefix-proc 'primitive:)))\n", mod, primsuffix);
+ }
+ Printf(goopsfile, "%s\n(export %s)", goopscode, goopsexport);
+ if (exportprimitive) {
+ String *ex = NewString(exported_symbols);
+ Replaceall(ex, ", ", "\n ");
+ Replaceall(ex, "\"", "");
+ Chop(ex);
+ Printf(goopsfile, "\n(export %s)", ex);
+ Delete(ex);
+ }
+ Delete(mod);
+ Delete(goopsfile);
+ }
+
+ Delete(module_func);
+ if (CPlusPlus) {
+ Printf(f_init, "\n}\n");
+ }
+ }
+
+ /* Return true iff T is a pointer type */
+
+ int is_a_pointer(SwigType *t) {
+ return SwigType_ispointer(SwigType_typedef_resolve_all(t));
+ }
+
+ /* Report an error handling the given type. */
+
+ void throw_unhandled_guile_type_error(SwigType *d) {
+ Swig_warning(WARN_TYPEMAP_UNDEF, input_file, line_number, "Unable to handle type %s.\n", SwigType_str(d, 0));
+ }
+
+ /* Write out procedure documentation */
+
+ void write_doc(const String *proc_name, const String *signature, const String *doc, const String *signature2 = NULL) {
+ switch (docformat) {
+ case GUILE_1_4:
+ Printv(procdoc, "\f\n", NIL);
+ Printv(procdoc, "(", signature, ")\n", NIL);
+ if (signature2)
+ Printv(procdoc, "(", signature2, ")\n", NIL);
+ Printv(procdoc, doc, "\n", NIL);
+ break;
+ case PLAIN:
+ Printv(procdoc, "\f", proc_name, "\n\n", NIL);
+ Printv(procdoc, "(", signature, ")\n", NIL);
+ if (signature2)
+ Printv(procdoc, "(", signature2, ")\n", NIL);
+ Printv(procdoc, doc, "\n\n", NIL);
+ break;
+ case TEXINFO:
+ Printv(procdoc, "\f", proc_name, "\n", NIL);
+ Printv(procdoc, "@deffn primitive ", signature, "\n", NIL);
+ if (signature2)
+ Printv(procdoc, "@deffnx primitive ", signature2, "\n", NIL);
+ Printv(procdoc, doc, "\n", NIL);
+ Printv(procdoc, "@end deffn\n\n", NIL);
+ break;
+ }
+ }
+
+ /* returns false if the typemap is an empty string */
+ bool handle_documentation_typemap(String *output,
+ const String *maybe_delimiter, Parm *p, const String *typemap, const String *default_doc, const String *name = NULL) {
+ String *tmp = NewString("");
+ String *tm;
+ if (!(tm = Getattr(p, typemap))) {
+ Printf(tmp, "%s", default_doc);
+ tm = tmp;
+ }
+ bool result = (Len(tm) > 0);
+ if (maybe_delimiter && Len(output) > 0 && Len(tm) > 0) {
+ Printv(output, maybe_delimiter, NIL);
+ }
+ const String *pn = !name ? (const String *) Getattr(p, "name") : name;
+ String *pt = Getattr(p, "type");
+ Replaceall(tm, "$name", pn); // legacy for $parmname
+ Replaceall(tm, "$type", SwigType_str(pt, 0));
+ /* $NAME is like $name, but marked-up as a variable. */
+ String *ARGNAME = NewString("");
+ if (docformat == TEXINFO)
+ Printf(ARGNAME, "@var{%s}", pn);
+ else
+ Printf(ARGNAME, "%(upper)s", pn);
+ Replaceall(tm, "$NAME", ARGNAME);
+ Replaceall(tm, "$PARMNAME", ARGNAME);
+ Printv(output, tm, NIL);
+ Delete(tmp);
+ return result;
+ }
+
+ /* ------------------------------------------------------------
+ * functionWrapper()
+ * Create a function declaration and register it with the interpreter.
+ * ------------------------------------------------------------ */
+
+ virtual int functionWrapper(Node *n) {
+ String *iname = Getattr(n, "sym:name");
+ SwigType *d = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ Parm *p;
+ String *proc_name = 0;
+ char source[256];
+ Wrapper *f = NewWrapper();
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ String *signature = NewString("");
+ String *doc_body = NewString("");
+ String *returns = NewString("");
+ String *method_signature = NewString("");
+ String *primitive_args = NewString("");
+ Hash *scheme_arg_names = NewHash();
+ int num_results = 1;
+ String *tmp = NewString("");
+ String *tm;
+ int i;
+ int numargs = 0;
+ int numreq = 0;
+ String *overname = 0;
+ int args_passed_as_array = 0;
+ int scheme_argnum = 0;
+ bool any_specialized_arg = false;
+
+ // Make a wrapper name for this
+ String *wname = Swig_name_wrapper(iname);
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ args_passed_as_array = 1;
+ } else {
+ if (!addSymbol(iname, n)) {
+ DelWrapper(f);
+ return SWIG_ERROR;
+ }
+ }
+ if (overname) {
+ Append(wname, overname);
+ }
+ Setattr(n, "wrap:name", wname);
+
+ // Build the name for scheme.
+ proc_name = NewString(iname);
+ Replaceall(proc_name, "_", "-");
+
+ /* Emit locals etc. into f->code; figure out which args to ignore */
+ emit_parameter_variables(l, f);
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+ Setattr(n, "wrap:parms", l);
+
+ /* Get number of required and total arguments */
+ numargs = emit_num_arguments(l);
+ numreq = emit_num_required(l);
+
+ /* Declare return variable */
+
+ Wrapper_add_local(f, "gswig_result", "SCM gswig_result");
+ Wrapper_add_local(f, "gswig_list_p", "SWIGUNUSED int gswig_list_p = 0");
+
+ /* Open prototype and signature */
+
+ Printv(f->def, "static SCM\n", wname, " (", NIL);
+ if (args_passed_as_array) {
+ Printv(f->def, "int argc, SCM *argv", NIL);
+ }
+ Printv(signature, proc_name, NIL);
+
+ /* Now write code to extract the parameters */
+
+ for (i = 0, p = l; i < numargs; i++) {
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ int opt_p = (i >= numreq);
+
+ // Produce names of source and target
+ if (args_passed_as_array)
+ sprintf(source, "argv[%d]", i);
+ else
+ sprintf(source, "s_%d", i);
+ String *target = Getattr(p, "lname");
+
+ if (!args_passed_as_array) {
+ if (i != 0)
+ Printf(f->def, ", ");
+ Printf(f->def, "SCM s_%d", i);
+ }
+ if (opt_p) {
+ Printf(f->code, " if (%s != SCM_UNDEFINED) {\n", source);
+ }
+ if ((tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$source", source);
+ Replaceall(tm, "$target", target);
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source);
+ Printv(f->code, tm, "\n", NIL);
+
+ SwigType *pb = SwigType_typedef_resolve_all(SwigType_base(pt));
+ SwigType *pn = Getattr(p, "name");
+ String *argname;
+ scheme_argnum++;
+ if (pn && !Getattr(scheme_arg_names, pn))
+ argname = pn;
+ else {
+ /* Anonymous arg or re-used argument name -- choose a name that cannot clash */
+ argname = NewStringf("%%arg%d", scheme_argnum);
+ }
+
+ if (procdoc) {
+ if (i == numreq) {
+ /* First optional argument */
+ Printf(signature, " #:optional");
+ }
+ /* Add to signature (arglist) */
+ handle_documentation_typemap(signature, " ", p, "tmap:in:arglist", "$name", argname);
+ /* Document the type of the arg in the documentation body */
+ handle_documentation_typemap(doc_body, ", ", p, "tmap:in:doc", "$NAME is of type <$type>", argname);
+ }
+
+ if (goops) {
+ if (i < numreq) {
+ if (strcmp("void", Char(pt)) != 0) {
+ Node *class_node = Swig_symbol_clookup_check(pb, Getattr(n, "sym:symtab"),
+ has_classname);
+ String *goopsclassname = !class_node ? NULL : Getattr(class_node, "guile:goopsclassname");
+ /* do input conversion */
+ if (goopsclassname) {
+ Printv(method_signature, " (", argname, " ", goopsclassname, ")", NIL);
+ any_specialized_arg = true;
+ } else {
+ Printv(method_signature, " ", argname, NIL);
+ }
+ Printv(primitive_args, " ", argname, NIL);
+ Setattr(scheme_arg_names, argname, p);
+ }
+ }
+ }
+
+ if (!pn) {
+ Delete(argname);
+ }
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ throw_unhandled_guile_type_error(pt);
+ p = nextSibling(p);
+ }
+ if (opt_p)
+ Printf(f->code, " }\n");
+ }
+ if (Len(doc_body) > 0)
+ Printf(doc_body, ".\n");
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ /* Pass output arguments back to the caller. */
+
+ /* Insert argument output code */
+ String *returns_argout = NewString("");
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ if (procdoc) {
+ if (handle_documentation_typemap(returns_argout, ", ", p, "tmap:argout:doc", "$NAME (of type $type)")) {
+ /* A documentation typemap that is not the empty string
+ indicates that a value is returned to Scheme. */
+ num_results++;
+ }
+ }
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ if (exporting_destructor) {
+ /* Mark the destructor's argument as destroyed. */
+ String *tm = NewString("SWIG_Guile_MarkPointerDestroyed($input);");
+ Replaceall(tm, "$input", Getattr(l, "emit:input"));
+ Printv(cleanup, tm, "\n", NIL);
+ Delete(tm);
+ }
+
+ /* Close prototype */
+
+ Printf(f->def, ")\n{\n");
+
+ /* Define the scheme name in C. This define is used by several Guile
+ macros. */
+ Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL);
+
+ // Now write code to make the function call
+ String *actioncode = emit_action(n);
+
+ // Now have return value, figure out what to do with it.
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ Replaceall(tm, "$result", "gswig_result");
+ Replaceall(tm, "$target", "gswig_result");
+ Replaceall(tm, "$source", Swig_cresult_name());
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "1");
+ else
+ Replaceall(tm, "$owner", "0");
+ Printv(f->code, tm, "\n", NIL);
+ } else {
+ throw_unhandled_guile_type_error(d);
+ }
+ emit_return_variable(n, d, f);
+
+ // Documentation
+ if ((tm = Getattr(n, "tmap:out:doc"))) {
+ Printv(returns, tm, NIL);
+ if (Len(tm) > 0)
+ num_results = 1;
+ else
+ num_results = 0;
+ } else {
+ String *s = SwigType_str(d, 0);
+ Chop(s);
+ Printf(returns, "<%s>", s);
+ Delete(s);
+ num_results = 1;
+ }
+ Append(returns, returns_argout);
+
+
+ // Dump the argument output code
+ Printv(f->code, outarg, NIL);
+
+ // Dump the argument cleanup code
+ Printv(f->code, cleanup, NIL);
+
+ // Look for any remaining cleanup
+
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printv(f->code, tm, "\n", NIL);
+ }
+ }
+ // Free any memory allocated by the function being wrapped..
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printv(f->code, tm, "\n", NIL);
+ }
+ // Wrap things up (in a manner of speaking)
+
+ if (beforereturn)
+ Printv(f->code, beforereturn, "\n", NIL);
+ Printv(f->code, "return gswig_result;\n", NIL);
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", iname);
+ // Undefine the scheme name
+
+ Printf(f->code, "#undef FUNC_NAME\n");
+ Printf(f->code, "}\n");
+
+ Wrapper_print(f, f_wrappers);
+
+ if (!Getattr(n, "sym:overloaded")) {
+ if (numargs > 10) {
+ int i;
+ /* gh_new_procedure would complain: too many args */
+ /* Build a wrapper wrapper */
+ Printv(f_wrappers, "static SCM\n", wname, "_rest (SCM rest)\n", NIL);
+ Printv(f_wrappers, "{\n", NIL);
+ Printf(f_wrappers, "SCM arg[%d];\n", numargs);
+ Printf(f_wrappers, "SWIG_Guile_GetArgs (arg, rest, %d, %d, \"%s\");\n", numreq, numargs - numreq, proc_name);
+ Printv(f_wrappers, "return ", wname, "(", NIL);
+ Printv(f_wrappers, "arg[0]", NIL);
+ for (i = 1; i < numargs; i++)
+ Printf(f_wrappers, ", arg[%d]", i);
+ Printv(f_wrappers, ");\n", NIL);
+ Printv(f_wrappers, "}\n", NIL);
+ /* Register it */
+ Printf(f_init, "scm_c_define_gsubr(\"%s\", 0, 0, 1, (swig_guile_proc) %s_rest);\n", proc_name, wname);
+ } else if (emit_setters && struct_member && strlen(Char(proc_name)) > 3) {
+ int len = Len(proc_name);
+ const char *pc = Char(proc_name);
+ /* MEMBER-set and MEMBER-get functions. */
+ int is_setter = (pc[len - 3] == 's');
+ if (is_setter) {
+ Printf(f_init, "SCM setter = ");
+ struct_member = 2; /* have a setter */
+ } else
+ Printf(f_init, "SCM getter = ");
+ /* GOOPS support uses the MEMBER-set and MEMBER-get functions,
+ so ignore only_setters in this case. */
+ if (only_setters && !goops)
+ Printf(f_init, "scm_c_make_gsubr(\"%s\", %d, %d, 0, (swig_guile_proc) %s);\n", proc_name, numreq, numargs - numreq, wname);
+ else
+ Printf(f_init, "scm_c_define_gsubr(\"%s\", %d, %d, 0, (swig_guile_proc) %s);\n", proc_name, numreq, numargs - numreq, wname);
+
+ if (!is_setter) {
+ /* Strip off "-get" */
+ char *pws_name = (char *) malloc(sizeof(char) * (len - 3));
+ strncpy(pws_name, pc, len - 3);
+ pws_name[len - 4] = 0;
+ if (struct_member == 2) {
+ /* There was a setter, so create a procedure with setter */
+ Printf(f_init, "scm_c_define");
+ Printf(f_init, "(\"%s\", " "scm_make_procedure_with_setter(getter, setter));\n", pws_name);
+ } else {
+ /* There was no setter, so make an alias to the getter */
+ Printf(f_init, "scm_c_define");
+ Printf(f_init, "(\"%s\", getter);\n", pws_name);
+ }
+ Printf(exported_symbols, "\"%s\", ", pws_name);
+ free(pws_name);
+ }
+ } else {
+ /* Register the function */
+ if (exporting_destructor) {
+ Printf(f_init, "((swig_guile_clientdata *)(SWIGTYPE%s->clientdata))->destroy = (guile_destructor) %s;\n", swigtype_ptr, wname);
+ //Printf(f_init, "SWIG_TypeClientData(SWIGTYPE%s, (void *) %s);\n", swigtype_ptr, wname);
+ }
+ Printf(f_init, "scm_c_define_gsubr(\"%s\", %d, %d, 0, (swig_guile_proc) %s);\n", proc_name, numreq, numargs - numreq, wname);
+ }
+ } else { /* overloaded function; don't export the single methods */
+ if (!Getattr(n, "sym:nextSibling")) {
+ /* Emit overloading dispatch function */
+
+ int maxargs;
+ String *dispatch = Swig_overload_dispatch(n, "return %s(argc,argv);", &maxargs);
+
+ /* Generate a dispatch wrapper for all overloaded functions */
+
+ Wrapper *df = NewWrapper();
+ String *dname = Swig_name_wrapper(iname);
+
+ Printv(df->def, "static SCM\n", dname, "(SCM rest)\n{\n", NIL);
+ Printf(df->code, "#define FUNC_NAME \"%s\"\n", proc_name);
+ Printf(df->code, "SCM argv[%d];\n", maxargs);
+ Printf(df->code, "int argc = SWIG_Guile_GetArgs (argv, rest, %d, %d, \"%s\");\n", 0, maxargs, proc_name);
+ Printv(df->code, dispatch, "\n", NIL);
+ Printf(df->code, "scm_misc_error(\"%s\", \"No matching method for generic function `%s'\", SCM_EOL);\n", proc_name, iname);
+ Printf(df->code, "#undef FUNC_NAME\n");
+ Printv(df->code, "}\n", NIL);
+ Wrapper_print(df, f_wrappers);
+ Printf(f_init, "scm_c_define_gsubr(\"%s\", 0, 0, 1, (swig_guile_proc) %s);\n", proc_name, dname);
+ DelWrapper(df);
+ Delete(dispatch);
+ Delete(dname);
+ }
+ }
+ Printf(exported_symbols, "\"%s\", ", proc_name);
+
+ if (!in_class || memberfunction_name) {
+ // export wrapper into goops file
+ String *method_def = NewString("");
+ String *goops_name;
+ if (in_class)
+ goops_name = NewString(memberfunction_name);
+ else
+ goops_name = goopsNameMapping(proc_name, "");
+ String *primitive_name = NewString("");
+ if (primRenamer)
+ Printv(primitive_name, "primitive:", proc_name, NIL);
+ else
+ Printv(primitive_name, proc_name, NIL);
+ Replaceall(method_signature, "_", "-");
+ Replaceall(primitive_args, "_", "-");
+ if (!any_specialized_arg) {
+ /* If there would not be any specialized argument in
+ the method declaration, we simply re-export the
+ function. This is a performance optimization. */
+ Printv(method_def, "(define ", goops_name, " ", primitive_name, ")\n", NIL);
+ } else if (numreq == numargs) {
+ Printv(method_def, "(define-method (", goops_name, method_signature, ")\n", NIL);
+ Printv(method_def, " (", primitive_name, primitive_args, "))\n", NIL);
+ } else {
+ /* Handle optional args. For the rest argument, use a name
+ that cannot clash. */
+ Printv(method_def, "(define-method (", goops_name, method_signature, " . %args)\n", NIL);
+ Printv(method_def, " (apply ", primitive_name, primitive_args, " %args))\n", NIL);
+ }
+ if (in_class) {
+ /* Defer method definition till end of class definition. */
+ Printv(goops_class_methods, method_def, NIL);
+ } else {
+ Printv(goopscode, method_def, NIL);
+ }
+ Printf(goopsexport, "%s ", goops_name);
+ Delete(primitive_name);
+ Delete(goops_name);
+ Delete(method_def);
+ }
+
+ if (procdoc) {
+ String *returns_text = NewString("");
+ if (num_results == 0)
+ Printv(returns_text, return_nothing_doc, NIL);
+ else if (num_results == 1)
+ Printv(returns_text, return_one_doc, NIL);
+ else
+ Printv(returns_text, return_multi_doc, NIL);
+ /* Substitute documentation variables */
+ static const char *numbers[] = { "zero", "one", "two", "three",
+ "four", "five", "six", "seven",
+ "eight", "nine", "ten", "eleven",
+ "twelve"
+ };
+ if (num_results <= 12)
+ Replaceall(returns_text, "$num_values", numbers[num_results]);
+ else {
+ String *num_results_str = NewStringf("%d", num_results);
+ Replaceall(returns_text, "$num_values", num_results_str);
+ Delete(num_results_str);
+ }
+ Replaceall(returns_text, "$values", returns);
+ Printf(doc_body, "\n%s", returns_text);
+ write_doc(proc_name, signature, doc_body);
+ Delete(returns_text);
+ }
+
+ Delete(proc_name);
+ Delete(outarg);
+ Delete(cleanup);
+ Delete(signature);
+ Delete(method_signature);
+ Delete(primitive_args);
+ Delete(doc_body);
+ Delete(returns_argout);
+ Delete(returns);
+ Delete(tmp);
+ Delete(scheme_arg_names);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * variableWrapper()
+ *
+ * Create a link to a C variable.
+ * This creates a single function PREFIX_var_VARNAME().
+ * This function takes a single optional argument. If supplied, it means
+ * we are setting this variable to some value. If omitted, it means we are
+ * simply evaluating this variable. Either way, we return the variables
+ * value.
+ * ------------------------------------------------------------ */
+
+ virtual int variableWrapper(Node *n) {
+
+ char *name = GetChar(n, "name");
+ char *iname = GetChar(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+
+ String *proc_name;
+ Wrapper *f;
+ String *tm;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ f = NewWrapper();
+ // evaluation function names
+
+ String *var_name = Swig_name_wrapper(iname);
+
+ // Build the name for scheme.
+ proc_name = NewString(iname);
+ Replaceall(proc_name, "_", "-");
+ Setattr(n, "wrap:name", proc_name);
+
+ if (1 || (SwigType_type(t) != T_USER) || (is_a_pointer(t))) {
+
+ Printf(f->def, "static SCM\n%s(SCM s_0)\n{\n", var_name);
+
+ /* Define the scheme name in C. This define is used by several Guile
+ macros. */
+ Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL);
+
+ Wrapper_add_local(f, "gswig_result", "SCM gswig_result");
+
+ if (!GetFlag(n, "feature:immutable")) {
+ /* Check for a setting of the variable value */
+ Printf(f->code, "if (s_0 != SCM_UNDEFINED) {\n");
+ if ((tm = Swig_typemap_lookup("varin", n, name, 0))) {
+ Replaceall(tm, "$source", "s_0");
+ Replaceall(tm, "$input", "s_0");
+ Replaceall(tm, "$target", name);
+ /* Printv(f->code,tm,"\n",NIL); */
+ emit_action_code(n, f->code, tm);
+ } else {
+ throw_unhandled_guile_type_error(t);
+ }
+ Printf(f->code, "}\n");
+ }
+ // Now return the value of the variable (regardless
+ // of evaluating or setting)
+
+ if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
+ Replaceall(tm, "$source", name);
+ Replaceall(tm, "$target", "gswig_result");
+ Replaceall(tm, "$result", "gswig_result");
+ /* Printv(f->code,tm,"\n",NIL); */
+ emit_action_code(n, f->code, tm);
+ } else {
+ throw_unhandled_guile_type_error(t);
+ }
+ Printf(f->code, "\nreturn gswig_result;\n");
+ Printf(f->code, "#undef FUNC_NAME\n");
+ Printf(f->code, "}\n");
+
+ Wrapper_print(f, f_wrappers);
+
+ // Now add symbol to the Guile interpreter
+
+ if (!emit_setters || GetFlag(n, "feature:immutable")) {
+ /* Read-only variables become a simple procedure returning the
+ value; read-write variables become a simple procedure with
+ an optional argument. */
+
+ if (!goops && GetFlag(n, "feature:constasvar")) {
+ /* need to export this function as a variable instead of a procedure */
+ if (scmstub) {
+ /* export the function in the wrapper, and (set!) it in scmstub */
+ Printf(f_init, "scm_c_define_gsubr(\"%s\", 0, %d, 0, (swig_guile_proc) %s);\n", proc_name, !GetFlag(n, "feature:immutable"), var_name);
+ Printf(scmtext, "(set! %s (%s))\n", proc_name, proc_name);
+ } else {
+ /* export the variable directly */
+ Printf(f_init, "scm_c_define(\"%s\", %s(SCM_UNDEFINED));\n", proc_name, var_name);
+ }
+
+ } else {
+ /* Export the function as normal */
+ Printf(f_init, "scm_c_define_gsubr(\"%s\", 0, %d, 0, (swig_guile_proc) %s);\n", proc_name, !GetFlag(n, "feature:immutable"), var_name);
+ }
+
+ } else {
+ /* Read/write variables become a procedure with setter. */
+ Printf(f_init, "{ SCM p = scm_c_define_gsubr(\"%s\", 0, 1, 0, (swig_guile_proc) %s);\n", proc_name, var_name);
+ Printf(f_init, "scm_c_define");
+ Printf(f_init, "(\"%s\", " "scm_make_procedure_with_setter(p, p)); }\n", proc_name);
+ }
+ Printf(exported_symbols, "\"%s\", ", proc_name);
+
+ // export wrapper into goops file
+ if (!in_class) { // only if the variable is not part of a class
+ String *class_name = SwigType_typedef_resolve_all(SwigType_base(t));
+ String *goops_name = goopsNameMapping(proc_name, "");
+ String *primitive_name = NewString("");
+ if (primRenamer)
+ Printv(primitive_name, "primitive:", NIL);
+ Printv(primitive_name, proc_name, NIL);
+ /* Simply re-export the procedure */
+ if ((!emit_setters || GetFlag(n, "feature:immutable"))
+ && GetFlag(n, "feature:constasvar")) {
+ Printv(goopscode, "(define ", goops_name, " (", primitive_name, "))\n", NIL);
+ } else {
+ Printv(goopscode, "(define ", goops_name, " ", primitive_name, ")\n", NIL);
+ }
+ Printf(goopsexport, "%s ", goops_name);
+ Delete(primitive_name);
+ Delete(class_name);
+ Delete(goops_name);
+ }
+
+ if (procdoc) {
+ /* Compute documentation */
+ String *signature = NewString("");
+ String *signature2 = NULL;
+ String *doc = NewString("");
+
+ if (GetFlag(n, "feature:immutable")) {
+ Printv(signature, proc_name, NIL);
+ if (GetFlag(n, "feature:constasvar")) {
+ Printv(doc, "Is constant ", NIL);
+ } else {
+ Printv(doc, "Returns constant ", NIL);
+ }
+ if ((tm = Getattr(n, "tmap:varout:doc"))) {
+ Printv(doc, tm, NIL);
+ } else {
+ String *s = SwigType_str(t, 0);
+ Chop(s);
+ Printf(doc, "<%s>", s);
+ Delete(s);
+ }
+ } else if (emit_setters) {
+ Printv(signature, proc_name, NIL);
+ signature2 = NewString("");
+ Printv(signature2, "set! (", proc_name, ") ", NIL);
+ handle_documentation_typemap(signature2, NIL, n, "tmap:varin:arglist", "new-value");
+ Printv(doc, "Get or set the value of the C variable, \n", NIL);
+ Printv(doc, "which is of type ", NIL);
+ handle_documentation_typemap(doc, NIL, n, "tmap:varout:doc", "$1_type");
+ Printv(doc, ".");
+ } else {
+ Printv(signature, proc_name, " #:optional ", NIL);
+ if ((tm = Getattr(n, "tmap:varin:doc"))) {
+ Printv(signature, tm, NIL);
+ } else {
+ String *s = SwigType_str(t, 0);
+ Chop(s);
+ Printf(signature, "new-value <%s>", s);
+ Delete(s);
+ }
+
+ Printv(doc, "If NEW-VALUE is provided, " "set C variable to this value.\n", NIL);
+ Printv(doc, "Returns variable value ", NIL);
+ if ((tm = Getattr(n, "tmap:varout:doc"))) {
+ Printv(doc, tm, NIL);
+ } else {
+ String *s = SwigType_str(t, 0);
+ Chop(s);
+ Printf(doc, "<%s>", s);
+ Delete(s);
+ }
+ }
+ write_doc(proc_name, signature, doc, signature2);
+ Delete(signature);
+ if (signature2)
+ Delete(signature2);
+ Delete(doc);
+ }
+
+ } else {
+ Swig_warning(WARN_TYPEMAP_VAR_UNDEF, input_file, line_number, "Unsupported variable type %s (ignored).\n", SwigType_str(t, 0));
+ }
+ Delete(var_name);
+ Delete(proc_name);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ *
+ * We create a read-only variable.
+ * ------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ char *name = GetChar(n, "name");
+ char *iname = GetChar(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *rawval = Getattr(n, "rawval");
+ String *value = rawval ? rawval : Getattr(n, "value");
+ int constasvar = GetFlag(n, "feature:constasvar");
+
+
+ String *proc_name;
+ String *var_name;
+ Wrapper *f;
+ SwigType *nctype;
+ String *tm;
+
+ f = NewWrapper();
+
+ // Make a static variable;
+ var_name = NewStringf("%sconst_%s", prefix, iname);
+
+ // Strip const qualifier from type if present
+
+ nctype = NewString(type);
+ if (SwigType_isconst(nctype)) {
+ Delete(SwigType_pop(nctype));
+ }
+ // Build the name for scheme.
+ proc_name = NewString(iname);
+ Replaceall(proc_name, "_", "-");
+
+ if ((SwigType_type(nctype) == T_USER) && (!is_a_pointer(nctype))) {
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
+ Delete(var_name);
+ DelWrapper(f);
+ return SWIG_NOWRAP;
+ }
+ // See if there's a typemap
+
+ if ((tm = Swig_typemap_lookup("constant", n, name, 0))) {
+ Replaceall(tm, "$source", value);
+ Replaceall(tm, "$value", value);
+ Replaceall(tm, "$target", name);
+ Printv(f_header, tm, "\n", NIL);
+ } else {
+ // Create variable and assign it a value
+ Printf(f_header, "static %s = (%s)(%s);\n", SwigType_str(type, var_name), SwigType_str(type, 0), value);
+ }
+ {
+ /* Hack alert: will cleanup later -- Dave */
+ Node *nn = NewHash();
+ Setfile(nn, Getfile(n));
+ Setline(nn, Getline(n));
+ Setattr(nn, "name", var_name);
+ Setattr(nn, "sym:name", iname);
+ Setattr(nn, "type", nctype);
+ SetFlag(nn, "feature:immutable");
+ if (constasvar) {
+ SetFlag(nn, "feature:constasvar");
+ }
+ variableWrapper(nn);
+ Delete(nn);
+ }
+ Delete(var_name);
+ Delete(nctype);
+ Delete(proc_name);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDeclaration()
+ * ------------------------------------------------------------ */
+ virtual int classDeclaration(Node *n) {
+ String *class_name = NewStringf("<%s>", Getattr(n, "sym:name"));
+ Setattr(n, "guile:goopsclassname", class_name);
+ return Language::classDeclaration(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ * ------------------------------------------------------------ */
+ virtual int classHandler(Node *n) {
+ /* Create new strings for building up a wrapper function */
+ have_constructor = 0;
+
+ class_name = NewString("");
+ short_class_name = NewString("");
+ Printv(class_name, "<", Getattr(n, "sym:name"), ">", NIL);
+ Printv(short_class_name, Getattr(n, "sym:name"), NIL);
+ Replaceall(class_name, "_", "-");
+ Replaceall(short_class_name, "_", "-");
+
+ if (!addSymbol(class_name, n))
+ return SWIG_ERROR;
+
+ /* Handle inheritance */
+ String *base_class = NewString("<");
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator i = First(baselist);
+ while (i.item) {
+ Printv(base_class, Getattr(i.item, "sym:name"), NIL);
+ i = Next(i);
+ if (i.item) {
+ Printf(base_class, "> <");
+ }
+ }
+ }
+ Printf(base_class, ">");
+ Replaceall(base_class, "_", "-");
+
+ Printv(goopscode, "(define-class ", class_name, " ", NIL);
+ Printf(goopsexport, "%s ", class_name);
+
+ if (Len(base_class) > 2) {
+ Printv(goopscode, "(", base_class, ")\n", NIL);
+ } else {
+ Printv(goopscode, "(<swig>)\n", NIL);
+ }
+ SwigType *ct = NewStringf("p.%s", Getattr(n, "name"));
+ swigtype_ptr = SwigType_manglestr(ct);
+
+ String *mangled_classname = Swig_name_mangle(Getattr(n, "sym:name"));
+ /* Export clientdata structure */
+ Printf(f_runtime, "static swig_guile_clientdata _swig_guile_clientdata%s = { NULL, SCM_EOL };\n", mangled_classname);
+
+ Printv(f_init, "SWIG_TypeClientData(SWIGTYPE", swigtype_ptr, ", (void *) &_swig_guile_clientdata", mangled_classname, ");\n", NIL);
+ SwigType_remember(ct);
+ Delete(ct);
+
+ /* Emit all of the members */
+ goops_class_methods = NewString("");
+
+ in_class = 1;
+ Language::classHandler(n);
+ in_class = 0;
+
+ Printv(goopscode, " #:metaclass <swig-metaclass>\n", NIL);
+
+ if (have_constructor)
+ Printv(goopscode, " #:new-function ", primRenamer ? "primitive:" : "", "new-", short_class_name, "\n", NIL);
+
+ Printf(goopscode, ")\n%s\n", goops_class_methods);
+ Delete(goops_class_methods);
+ goops_class_methods = 0;
+
+
+ /* export class initialization function */
+ if (goops) {
+ /* export the wrapper function */
+ String *funcName = NewString(mangled_classname);
+ Printf(funcName, "_swig_guile_setgoopsclass");
+ String *guileFuncName = NewString(funcName);
+ Replaceall(guileFuncName, "_", "-");
+
+ Printv(f_wrappers, "static SCM ", funcName, "(SCM cl) \n", NIL);
+ Printf(f_wrappers, "#define FUNC_NAME %s\n{\n", guileFuncName);
+ Printv(f_wrappers, " ((swig_guile_clientdata *)(SWIGTYPE", swigtype_ptr, "->clientdata))->goops_class = cl;\n", NIL);
+ Printf(f_wrappers, " return SCM_UNSPECIFIED;\n");
+ Printf(f_wrappers, "}\n#undef FUNC_NAME\n\n");
+
+ Printf(f_init, "scm_c_define_gsubr(\"%s\", 1, 0, 0, (swig_guile_proc) %s);\n", guileFuncName, funcName);
+ Printf(exported_symbols, "\"%s\", ", guileFuncName);
+
+ /* export the call to the wrapper function */
+ Printf(goopscode, "(%s%s %s)\n\n", primRenamer ? "primitive:" : "", guileFuncName, class_name);
+
+ Delete(guileFuncName);
+ Delete(funcName);
+ }
+
+ Delete(mangled_classname);
+
+ Delete(swigtype_ptr);
+ swigtype_ptr = 0;
+
+ Delete(class_name);
+ Delete(short_class_name);
+ class_name = 0;
+ short_class_name = 0;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * memberfunctionHandler()
+ * ------------------------------------------------------------ */
+ int memberfunctionHandler(Node *n) {
+ String *iname = Getattr(n, "sym:name");
+ String *proc = NewString(iname);
+ Replaceall(proc, "_", "-");
+
+ memberfunction_name = goopsNameMapping(proc, short_class_name);
+ Language::memberfunctionHandler(n);
+ Delete(memberfunction_name);
+ memberfunction_name = NULL;
+ Delete(proc);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * membervariableHandler()
+ * ------------------------------------------------------------ */
+ int membervariableHandler(Node *n) {
+ String *iname = Getattr(n, "sym:name");
+
+ if (emit_setters) {
+ struct_member = 1;
+ Printf(f_init, "{\n");
+ }
+
+ Language::membervariableHandler(n);
+
+ if (emit_setters) {
+ Printf(f_init, "}\n");
+ struct_member = 0;
+ }
+
+ String *proc = NewString(iname);
+ Replaceall(proc, "_", "-");
+ String *goops_name = goopsNameMapping(proc, short_class_name);
+
+ /* The slot name is never qualified with the class,
+ even if useclassprefix is true. */
+ Printv(goopscode, " (", proc, " #:allocation #:virtual", NIL);
+ /* GOOPS (at least in Guile 1.6.3) only accepts closures, not
+ primitive procedures for slot-ref and slot-set. */
+ Printv(goopscode, "\n #:slot-ref (lambda (obj) (", primRenamer ? "primitive:" : "", short_class_name, "-", proc, "-get", " obj))", NIL);
+ if (!GetFlag(n, "feature:immutable")) {
+ Printv(goopscode, "\n #:slot-set! (lambda (obj value) (", primRenamer ? "primitive:" : "", short_class_name, "-", proc, "-set", " obj value))", NIL);
+ } else {
+ Printf(goopscode, "\n #:slot-set! (lambda (obj value) (error \"Immutable slot\"))");
+ }
+ if (emit_slot_accessors) {
+ if (GetFlag(n, "feature:immutable")) {
+ Printv(goopscode, "\n #:getter ", goops_name, NIL);
+ } else {
+ Printv(goopscode, "\n #:accessor ", goops_name, NIL);
+ }
+ Printf(goopsexport, "%s ", goops_name);
+ }
+ Printv(goopscode, ")\n", NIL);
+ Delete(proc);
+ Delete(goops_name);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constructorHandler()
+ * ------------------------------------------------------------ */
+ int constructorHandler(Node *n) {
+ Language::constructorHandler(n);
+ have_constructor = 1;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * destructorHandler()
+ * ------------------------------------------------------------ */
+ virtual int destructorHandler(Node *n) {
+ exporting_destructor = true;
+ Language::destructorHandler(n);
+ exporting_destructor = false;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * pragmaDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int pragmaDirective(Node *n) {
+ if (!ImportMode) {
+ String *lang = Getattr(n, "lang");
+ String *cmd = Getattr(n, "name");
+ String *value = Getattr(n, "value");
+
+# define store_pragma(PRAGMANAME) \
+ if (Strcmp(cmd, #PRAGMANAME) == 0) { \
+ if (PRAGMANAME) Delete(PRAGMANAME); \
+ PRAGMANAME = value ? NewString(value) : NULL; \
+ }
+
+ if (Strcmp(lang, "guile") == 0) {
+ store_pragma(beforereturn)
+ store_pragma(return_nothing_doc)
+ store_pragma(return_one_doc)
+ store_pragma(return_multi_doc);
+# undef store_pragma
+ }
+ }
+ return Language::pragmaDirective(n);
+ }
+
+
+ /* ------------------------------------------------------------
+ * goopsNameMapping()
+ * Maps the identifier from C++ to the GOOPS based * on command
+ * line parameters and such.
+ * If class_name = "" that means the mapping is for a function or
+ * variable not attached to any class.
+ * ------------------------------------------------------------ */
+ String *goopsNameMapping(String *name, const_String_or_char_ptr class_name) {
+ String *n = NewString("");
+
+ if (Strcmp(class_name, "") == 0) {
+ // not part of a class, so no class name to prefix
+ if (goopsprefix) {
+ Printf(n, "%s%s", goopsprefix, name);
+ } else {
+ Printf(n, "%s", name);
+ }
+ } else {
+ if (useclassprefix) {
+ Printf(n, "%s-%s", class_name, name);
+ } else {
+ if (goopsprefix) {
+ Printf(n, "%s%s", goopsprefix, name);
+ } else {
+ Printf(n, "%s", name);
+ }
+ }
+ }
+ return n;
+ }
+
+
+ /* ------------------------------------------------------------
+ * validIdentifier()
+ * ------------------------------------------------------------ */
+
+ virtual int validIdentifier(String *s) {
+ char *c = Char(s);
+ /* Check whether we have an R5RS identifier. Guile supports a
+ superset of R5RS identifiers, but it's probably a bad idea to use
+ those. */
+ /* <identifier> --> <initial> <subsequent>* | <peculiar identifier> */
+ /* <initial> --> <letter> | <special initial> */
+ if (!(isalpha(*c) || (*c == '!') || (*c == '$') || (*c == '%')
+ || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':')
+ || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?')
+ || (*c == '^') || (*c == '_') || (*c == '~'))) {
+ /* <peculiar identifier> --> + | - | ... */
+ if ((strcmp(c, "+") == 0)
+ || strcmp(c, "-") == 0 || strcmp(c, "...") == 0)
+ return 1;
+ else
+ return 0;
+ }
+ /* <subsequent> --> <initial> | <digit> | <special subsequent> */
+ while (*c) {
+ if (!(isalnum(*c) || (*c == '!') || (*c == '$') || (*c == '%')
+ || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':')
+ || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?')
+ || (*c == '^') || (*c == '_') || (*c == '~') || (*c == '+')
+ || (*c == '-') || (*c == '.') || (*c == '@')))
+ return 0;
+ c++;
+ }
+ return 1;
+ }
+
+ String *runtimeCode() {
+ String *s;
+ s = Swig_include_sys("guile_scm_run.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'guile_scm_run.swg");
+ s = NewString("");
+ }
+ return s;
+ }
+
+ String *defaultExternalRuntimeFilename() {
+ return NewString("swigguilerun.h");
+ }
+};
+
+/* -----------------------------------------------------------------------------
+ * swig_guile() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_guile() {
+ return new GUILE();
+}
+extern "C" Language *swig_guile(void) {
+ return new_swig_guile();
+}
diff --git a/contrib/tools/swig/Source/Modules/interface.cxx b/contrib/tools/swig/Source/Modules/interface.cxx
new file mode 100644
index 00000000000..fee6cd7dab2
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/interface.cxx
@@ -0,0 +1,185 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * interface.cxx
+ *
+ * This module contains support for the interface feature.
+ * This feature is used in language modules where the target language does not
+ * naturally support C++ style multiple inheritance, but does support inheritance
+ * from multiple interfaces.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+
+static bool interface_feature_enabled = false;
+
+/* -----------------------------------------------------------------------------
+ * collect_interface_methods()
+ *
+ * Create a list of all the methods from the base classes of class n that are
+ * marked as an interface. The resulting list is thus the list of methods that
+ * need to be implemented in order for n to be non-abstract.
+ * ----------------------------------------------------------------------------- */
+
+static List *collect_interface_methods(Node *n) {
+ List *methods = NewList();
+ if (Hash *bases = Getattr(n, "interface:bases")) {
+ List *keys = Keys(bases);
+ for (Iterator base = First(keys); base.item; base = Next(base)) {
+ Node *cls = Getattr(bases, base.item);
+ if (cls == n)
+ continue;
+ for (Node *child = firstChild(cls); child; child = nextSibling(child)) {
+ if (Cmp(nodeType(child), "cdecl") == 0) {
+ if (GetFlag(child, "feature:ignore") || Getattr(child, "interface:owner"))
+ continue; // skip methods propagated to bases
+ Node *m = Copy(child);
+ set_nextSibling(m, NIL);
+ set_previousSibling(m, NIL);
+ Setattr(m, "interface:owner", cls);
+ Append(methods, m);
+ }
+ }
+ }
+ Delete(keys);
+ }
+ return methods;
+}
+
+/* -----------------------------------------------------------------------------
+ * collect_interface_bases
+ * ----------------------------------------------------------------------------- */
+
+static void collect_interface_bases(Hash *bases, Node *n) {
+ if (Getattr(n, "feature:interface")) {
+ String *name = Getattr(n, "interface:name");
+ if (!Getattr(bases, name))
+ Setattr(bases, name, n);
+ }
+
+ if (List *baselist = Getattr(n, "bases")) {
+ for (Iterator base = First(baselist); base.item; base = Next(base)) {
+ if (!GetFlag(base.item, "feature:ignore")) {
+ if (Getattr(base.item, "feature:interface"))
+ collect_interface_bases(bases, base.item);
+ }
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * collect_interface_base_classes()
+ *
+ * Create a hash containing all the classes up the inheritance hierarchy
+ * marked with feature:interface (including this class n).
+ * Stops going up the inheritance chain as soon as a class is found without
+ * feature:interface.
+ * The idea is to find all the base interfaces that a class must implement.
+ * ----------------------------------------------------------------------------- */
+
+static void collect_interface_base_classes(Node *n) {
+ if (Getattr(n, "feature:interface")) {
+ // check all bases are also interfaces
+ if (List *baselist = Getattr(n, "bases")) {
+ for (Iterator base = First(baselist); base.item; base = Next(base)) {
+ if (!GetFlag(base.item, "feature:ignore")) {
+ if (!Getattr(base.item, "feature:interface")) {
+ Swig_error(Getfile(n), Getline(n), "Base class '%s' of '%s' is not similarly marked as an interface.\n", SwigType_namestr(Getattr(base.item, "name")), SwigType_namestr(Getattr(n, "name")));
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+ }
+ }
+ }
+
+ Hash *interface_bases = NewHash();
+ collect_interface_bases(interface_bases, n);
+ if (Len(interface_bases) == 0)
+ Delete(interface_bases);
+ else
+ Setattr(n, "interface:bases", interface_bases);
+}
+
+/* -----------------------------------------------------------------------------
+ * process_interface_name()
+ * ----------------------------------------------------------------------------- */
+
+static void process_interface_name(Node *n) {
+ if (Getattr(n, "feature:interface")) {
+ String *interface_name = Getattr(n, "feature:interface:name");
+ if (!Len(interface_name)) {
+ Swig_error(Getfile(n), Getline(n), "The interface feature for '%s' is missing the name attribute.\n", SwigType_namestr(Getattr(n, "name")));
+ SWIG_exit(EXIT_FAILURE);
+ }
+ if (Strchr(interface_name, '%')) {
+ String *name = NewStringf(interface_name, Getattr(n, "sym:name"));
+ Setattr(n, "interface:name", name);
+ } else {
+ Setattr(n, "interface:name", interface_name);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_interface_propagate_methods()
+ *
+ * Find all the base classes marked as an interface (with feature:interface) for
+ * class node n. For each of these, add all of its methods as methods of n so that
+ * n is not abstract. If class n is also marked as an interface, it will remain
+ * abstract and not have any methods added.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_interface_propagate_methods(Node *n) {
+ if (interface_feature_enabled) {
+ process_interface_name(n);
+ collect_interface_base_classes(n);
+ List *methods = collect_interface_methods(n);
+ bool is_interface = Getattr(n, "feature:interface") != 0;
+ for (Iterator mi = First(methods); mi.item; mi = Next(mi)) {
+ if (!is_interface && GetFlag(mi.item, "abstract"))
+ continue;
+ String *this_decl = Getattr(mi.item, "decl");
+ String *this_decl_resolved = SwigType_typedef_resolve_all(this_decl);
+ bool identically_overloaded_method = false; // true when a base class' method is implemented in n
+ if (SwigType_isfunction(this_decl_resolved)) {
+ String *name = Getattr(mi.item, "name");
+ for (Node *child = firstChild(n); child; child = nextSibling(child)) {
+ if (Getattr(child, "interface:owner"))
+ break; // at the end of the list are newly appended methods
+ if (Cmp(nodeType(child), "cdecl") == 0) {
+ if (checkAttribute(child, "name", name)) {
+ String *decl = SwigType_typedef_resolve_all(Getattr(child, "decl"));
+ identically_overloaded_method = Strcmp(decl, this_decl_resolved) == 0;
+ Delete(decl);
+ if (identically_overloaded_method)
+ break;
+ }
+ }
+ }
+ }
+ Delete(this_decl_resolved);
+ if (!identically_overloaded_method) {
+ // TODO: Fix if the method is overloaded with different arguments / has default args
+ appendChild(n, mi.item);
+ } else {
+ Delete(mi.item);
+ }
+ }
+ Delete(methods);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_interface_feature_enable()
+ *
+ * Turn on interface feature support
+ * ----------------------------------------------------------------------------- */
+
+void Swig_interface_feature_enable() {
+ interface_feature_enabled = true;
+}
diff --git a/contrib/tools/swig/Source/Modules/java.cxx b/contrib/tools/swig/Source/Modules/java.cxx
new file mode 100644
index 00000000000..7734c64714d
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/java.cxx
@@ -0,0 +1,5002 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * java.cxx
+ *
+ * Java language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include <limits.h> // for INT_MAX
+#include "cparse.h"
+#include <ctype.h>
+#include "javadoc.h"
+
+/* Hash type used for upcalls from C/C++ */
+typedef DOH UpcallData;
+
+class JAVA:public Language {
+ static const char *usage;
+ const String *empty_string;
+ const String *public_string;
+ const String *protected_string;
+
+ Hash *swig_types_hash;
+ File *f_begin;
+ File *f_runtime;
+ File *f_runtime_h;
+ File *f_header;
+ File *f_wrappers;
+ File *f_init;
+ File *f_directors;
+ File *f_directors_h;
+ List *filenames_list;
+
+ bool proxy_flag; // Flag for generating proxy classes
+ bool nopgcpp_flag; // Flag for suppressing the premature garbage collection prevention parameter
+ bool native_function_flag; // Flag for when wrapping a native function
+ bool enum_constant_flag; // Flag for when wrapping an enum or constant
+ bool static_flag; // Flag for when wrapping a static functions or member variables
+ bool variable_wrapper_flag; // Flag for when wrapping a nonstatic member variable
+ bool wrapping_member_flag; // Flag for when wrapping a member variable/enum/const
+ bool global_variable_flag; // Flag for when wrapping a global variable
+ bool old_variable_names; // Flag for old style variable names in the intermediary class
+ bool member_func_flag; // flag set when wrapping a member function
+ bool doxygen; //flag for converting found doxygen to javadoc
+ bool comment_creation_chatter; //flag for getting information about where comments were created in java.cxx
+
+ String *imclass_name; // intermediary class name
+ String *module_class_name; // module class name
+ String *constants_interface_name; // constants interface name
+ String *imclass_class_code; // intermediary class code
+ String *proxy_class_def;
+ String *proxy_class_code;
+ String *interface_class_code; // if %feature("interface") was declared for a class, here goes the interface declaration
+ String *module_class_code;
+ String *proxy_class_name; // proxy class name
+ String *full_proxy_class_name;// fully qualified proxy class name when using nspace feature, otherwise same as proxy_class_name
+ String *full_imclass_name; // fully qualified intermediary class name when using nspace feature, otherwise same as imclass_name
+ String *variable_name; //Name of a variable being wrapped
+ String *proxy_class_constants_code;
+ String *module_class_constants_code;
+ String *enum_code;
+ String *package; // Optional package name
+ String *jnipackage; // Package name used in the JNI code
+ String *package_path; // Package name used internally by JNI (slashes)
+ String *imclass_imports; //intermediary class imports from %pragma
+ String *module_imports; //module imports from %pragma
+ String *imclass_baseclass; //inheritance for intermediary class class from %pragma
+ String *imclass_package; //package in which to generate the intermediary class
+ String *module_baseclass; //inheritance for module class from %pragma
+ String *imclass_interfaces; //interfaces for intermediary class class from %pragma
+ String *module_interfaces; //interfaces for module class from %pragma
+ String *imclass_class_modifiers; //class modifiers for intermediary class overridden by %pragma
+ String *module_class_modifiers; //class modifiers for module class overridden by %pragma
+ String *upcasts_code; //C++ casts for inheritance hierarchies C++ code
+ String *imclass_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code
+ String *imclass_directors; // Intermediate class director code
+ String *destructor_call; //C++ destructor call if any
+ String *destructor_throws_clause; //C++ destructor throws clause if any
+
+ // Director method stuff:
+ List *dmethods_seq;
+ Hash *dmethods_table;
+ int n_dmethods;
+ int n_directors;
+ int first_class_dmethod;
+ int curr_class_dmethod;
+ int nesting_depth;
+
+ enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
+
+public:
+
+ /* -----------------------------------------------------------------------------
+ * JAVA()
+ * ----------------------------------------------------------------------------- */
+
+ JAVA():empty_string(NewString("")),
+ public_string(NewString("public")),
+ protected_string(NewString("protected")),
+ swig_types_hash(NULL),
+ f_begin(NULL),
+ f_runtime(NULL),
+ f_runtime_h(NULL),
+ f_header(NULL),
+ f_wrappers(NULL),
+ f_init(NULL),
+ f_directors(NULL),
+ f_directors_h(NULL),
+ filenames_list(NULL),
+ proxy_flag(true),
+ nopgcpp_flag(false),
+ native_function_flag(false),
+ enum_constant_flag(false),
+ static_flag(false),
+ variable_wrapper_flag(false),
+ wrapping_member_flag(false),
+ global_variable_flag(false),
+ old_variable_names(false),
+ member_func_flag(false),
+ doxygen(false),
+ comment_creation_chatter(false),
+ imclass_name(NULL),
+ module_class_name(NULL),
+ constants_interface_name(NULL),
+ imclass_class_code(NULL),
+ proxy_class_def(NULL),
+ proxy_class_code(NULL),
+ interface_class_code(NULL),
+ module_class_code(NULL),
+ proxy_class_name(NULL),
+ full_proxy_class_name(NULL),
+ full_imclass_name(NULL),
+ variable_name(NULL),
+ proxy_class_constants_code(NULL),
+ module_class_constants_code(NULL),
+ enum_code(NULL),
+ package(NULL),
+ jnipackage(NULL),
+ package_path(NULL),
+ imclass_imports(NULL),
+ module_imports(NULL),
+ imclass_baseclass(NULL),
+ imclass_package(NULL),
+ module_baseclass(NULL),
+ imclass_interfaces(NULL),
+ module_interfaces(NULL),
+ imclass_class_modifiers(NULL),
+ module_class_modifiers(NULL),
+ upcasts_code(NULL),
+ imclass_cppcasts_code(NULL),
+ imclass_directors(NULL),
+ destructor_call(NULL),
+ destructor_throws_clause(NULL),
+ dmethods_seq(NULL),
+ dmethods_table(NULL),
+ n_dmethods(0),
+ n_directors(0),
+ first_class_dmethod(0),
+ curr_class_dmethod(0),
+ nesting_depth(0){
+ /* for now, multiple inheritance in directors is disabled, this
+ should be easy to implement though */
+ director_multiple_inheritance = 0;
+ director_language = 1;
+ }
+
+ ~JAVA() {
+ delete doxygenTranslator;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * constructIntermediateClassName()
+ *
+ * Construct the fully qualified name of the intermediate class and set
+ * the full_imclass_name attribute accordingly.
+ * ----------------------------------------------------------------------------- */
+ void constructIntermediateClassName(Node *n) {
+ String *nspace = Getattr(n, "sym:nspace");
+
+ if (imclass_package && package)
+ full_imclass_name = NewStringf("%s.%s.%s", package, imclass_package, imclass_name);
+ else if (package && nspace)
+ full_imclass_name = NewStringf("%s.%s", package, imclass_name);
+ else if (imclass_package)
+ full_imclass_name = NewStringf("%s.%s", imclass_package, imclass_name);
+ else
+ full_imclass_name = NewStringf("%s", imclass_name);
+
+ if (nspace && !package) {
+ String *name = Getattr(n, "name") ? Getattr(n, "name") : NewString("<unnamed>");
+ Swig_warning(WARN_JAVA_NSPACE_WITHOUT_PACKAGE, Getfile(n), Getline(n),
+ "The nspace feature is used on '%s' without -package. "
+ "The generated code may not compile as Java does not support types declared in a named package accessing types declared in an unnamed package.\n", name);
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getProxyName()
+ *
+ * Test to see if a type corresponds to something wrapped with a proxy class.
+ * Return NULL if not otherwise the proxy class name, fully qualified with
+ * package name if the nspace feature is used, unless jnidescriptor is true as
+ * the package name is handled differently (unfortunately for legacy reasons).
+ * ----------------------------------------------------------------------------- */
+
+ String *getProxyName(SwigType *t, bool jnidescriptor = false) {
+ String *proxyname = NULL;
+ if (proxy_flag) {
+ Node *n = classLookup(t);
+ if (n) {
+ proxyname = Getattr(n, "proxyname");
+ if (!proxyname || jnidescriptor) {
+ String *nspace = Getattr(n, "sym:nspace");
+ String *symname = Copy(Getattr(n, "sym:name"));
+ if (symname && !GetFlag(n, "feature:flatnested")) {
+ for (Node *outer_class = Getattr(n, "nested:outer"); outer_class; outer_class = Getattr(outer_class, "nested:outer")) {
+ if (String* name = Getattr(outer_class, "sym:name")) {
+ Push(symname, jnidescriptor ? "$" : ".");
+ Push(symname, name);
+ }
+ else
+ return NULL;
+ }
+ }
+ if (nspace) {
+ if (package && !jnidescriptor)
+ proxyname = NewStringf("%s.%s.%s", package, nspace, symname);
+ else
+ proxyname = NewStringf("%s.%s", nspace, symname);
+ } else {
+ proxyname = Copy(symname);
+ }
+ if (!jnidescriptor) {
+ Setattr(n, "proxyname", proxyname); // Cache it
+ Delete(proxyname);
+ }
+ Delete(symname);
+ }
+ }
+ }
+ return proxyname;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * makeValidJniName()
+ * ----------------------------------------------------------------------------- */
+
+ String *makeValidJniName(const String *name) {
+ String *valid_jni_name = NewString(name);
+ Replaceall(valid_jni_name, "_", "_1");
+ return valid_jni_name;
+ }
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+
+ SWIG_library_directory("java");
+
+ int doxygen_translator_flags = 0;
+
+ // Look for certain 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("");
+ Printf(package, argv[i + 1]);
+ if (Len(package) == 0) {
+ Delete(package);
+ package = 0;
+ }
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if ((strcmp(argv[i], "-shadow") == 0) || ((strcmp(argv[i], "-proxy") == 0))) {
+ Printf(stderr, "Deprecated command line option: %s. Proxy classes are now generated by default.\n", argv[i]);
+ Swig_mark_arg(i);
+ proxy_flag = true;
+ } else if ((strcmp(argv[i], "-doxygen") == 0)) {
+ Swig_mark_arg(i);
+ doxygen = true;
+ scan_doxygen_comments = true;
+ } else if ((strcmp(argv[i], "-debug-doxygen-translator") == 0)) {
+ Swig_mark_arg(i);
+ doxygen_translator_flags |= DoxygenTranslator::debug_translator;
+ } else if ((strcmp(argv[i], "-debug-doxygen-parser") == 0)) {
+ Swig_mark_arg(i);
+ doxygen_translator_flags |= DoxygenTranslator::debug_parser;
+ } else if ((strcmp(argv[i], "-noproxy") == 0)) {
+ Swig_mark_arg(i);
+ proxy_flag = false;
+ } else if (strcmp(argv[i], "-nopgcpp") == 0) {
+ Swig_mark_arg(i);
+ nopgcpp_flag = true;
+ } else if (strcmp(argv[i], "-oldvarnames") == 0) {
+ Swig_mark_arg(i);
+ old_variable_names = true;
+ } else if (strcmp(argv[i], "-jnic") == 0) {
+ Swig_mark_arg(i);
+ Printf(stderr, "Deprecated command line option: -jnic. C JNI calling convention now used when -c++ not specified.\n");
+ } else if (strcmp(argv[i], "-nofinalize") == 0) {
+ Swig_mark_arg(i);
+ Printf(stderr, "Deprecated command line option: -nofinalize. Use the new javafinalize typemap instead.\n");
+ } else if (strcmp(argv[i], "-jnicpp") == 0) {
+ Swig_mark_arg(i);
+ Printf(stderr, "Deprecated command line option: -jnicpp. C++ JNI calling convention now used when -c++ specified.\n");
+ } else if (strcmp(argv[i], "-help") == 0) {
+ Printf(stdout, "%s\n", usage);
+ }
+ }
+ }
+
+ if (doxygen)
+ doxygenTranslator = new JavaDocConverter(doxygen_translator_flags);
+
+ // Add a symbol to the parser for conditional compilation
+ Preprocessor_define("SWIGJAVA 1", 0);
+
+ // Add typemap definitions
+ SWIG_typemap_lang("java");
+ SWIG_config_file("java.swg");
+
+ allow_overloading();
+ Swig_interface_feature_enable();
+ }
+
+ /* ---------------------------------------------------------------------
+ * top()
+ * --------------------------------------------------------------------- */
+
+ virtual int top(Node *n) {
+
+ // Get any options set in the module directive
+ Node *optionsnode = Getattr(Getattr(n, "module"), "options");
+
+ if (optionsnode) {
+ if (Getattr(optionsnode, "jniclassname"))
+ imclass_name = Copy(Getattr(optionsnode, "jniclassname"));
+ /* check if directors are enabled for this module. note: this
+ * is a "master" switch, without which no director code will be
+ * emitted. %feature("director") statements are also required
+ * to enable directors for individual classes or methods.
+ *
+ * use %module(directors="1") modulename at the start of the
+ * interface file to enable director generation.
+ */
+ if (Getattr(optionsnode, "directors")) {
+ allow_directors();
+ }
+ if (Getattr(optionsnode, "dirprot")) {
+ allow_dirprot();
+ }
+ allow_allprotected(GetFlag(optionsnode, "allprotected"));
+ }
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+ String *outfile_h = Getattr(n, "outfile_h");
+
+ if (!outfile) {
+ Printf(stderr, "Unable to determine outfile\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ if (directorsEnabled()) {
+ if (!outfile_h) {
+ Printf(stderr, "Unable to determine outfile_h\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+ f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
+ if (!f_runtime_h) {
+ FileErrorDisplay(outfile_h);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+ f_directors_h = NewString("");
+ f_directors = NewString("");
+
+ /* Register file targets with the SWIG file handler */
+ 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);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+
+ swig_types_hash = NewHash();
+ filenames_list = NewList();
+
+ // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
+ if (!imclass_name) {
+ imclass_name = NewStringf("%sJNI", Getattr(n, "name"));
+ module_class_name = Copy(Getattr(n, "name"));
+ } else {
+ // Rename the module name if it is the same as intermediary class name - a backwards compatibility solution
+ if (Cmp(imclass_name, Getattr(n, "name")) == 0)
+ module_class_name = NewStringf("%sModule", Getattr(n, "name"));
+ else
+ module_class_name = Copy(Getattr(n, "name"));
+ }
+ constants_interface_name = NewStringf("%sConstants", module_class_name);
+
+ // module class and intermediary classes are always created
+ if (!addSymbol(imclass_name, n))
+ return SWIG_ERROR;
+ if (!addSymbol(module_class_name, n))
+ return SWIG_ERROR;
+
+ imclass_class_code = NewString("");
+ proxy_class_def = NewString("");
+ proxy_class_code = NewString("");
+ module_class_constants_code = NewString("");
+ imclass_baseclass = NewString("");
+ imclass_package = NULL;
+ imclass_interfaces = NewString("");
+ imclass_class_modifiers = NewString("");
+ module_class_code = NewString("");
+ module_baseclass = NewString("");
+ module_interfaces = NewString("");
+ module_imports = NewString("");
+ module_class_modifiers = NewString("");
+ imclass_imports = NewString("");
+ imclass_cppcasts_code = NewString("");
+ imclass_directors = NewString("");
+ upcasts_code = NewString("");
+ dmethods_seq = NewList();
+ dmethods_table = NewHash();
+ n_dmethods = 0;
+ n_directors = 0;
+ jnipackage = NewString("");
+ package_path = NewString("");
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n\n#ifndef SWIGJAVA\n#define SWIGJAVA\n#endif\n\n");
+
+ if (directorsEnabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+
+ /* Emit initial director header and director code: */
+ Swig_banner(f_directors_h);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_class_name);
+ Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_class_name);
+
+ Printf(f_directors, "\n\n");
+ Printf(f_directors, "/* ---------------------------------------------------\n");
+ Printf(f_directors, " * C++ director class methods\n");
+ Printf(f_directors, " * --------------------------------------------------- */\n\n");
+ if (outfile_h) {
+ String *filename = Swig_file_filename(outfile_h);
+ Printf(f_directors, "#include \"%s\"\n\n", filename);
+ Delete(filename);
+ }
+ }
+
+ Printf(f_runtime, "\n");
+
+ String *wrapper_name = NewString("");
+
+ if (package) {
+ String *jniname = makeValidJniName(package);
+ Printv(jnipackage, jniname, NIL);
+ Delete(jniname);
+ Replaceall(jnipackage, ".", "_");
+ Append(jnipackage, "_");
+ Printv(package_path, package, NIL);
+ Replaceall(package_path, ".", "/");
+ }
+ String *jniname = makeValidJniName(imclass_name);
+ Printf(wrapper_name, "Java_%s%s_%%f", jnipackage, jniname);
+ Delete(jniname);
+
+ Swig_name_register("wrapper", Char(wrapper_name));
+ if (old_variable_names) {
+ Swig_name_register("set", "set_%n%v");
+ Swig_name_register("get", "get_%n%v");
+ }
+
+ Delete(wrapper_name);
+
+ Printf(f_wrappers, "\n#ifdef __cplusplus\n");
+ Printf(f_wrappers, "extern \"C\" {\n");
+ Printf(f_wrappers, "#endif\n\n");
+
+ /* Emit code */
+ Language::top(n);
+
+ if (directorsEnabled()) {
+ // Insert director runtime into the f_runtime file (make it occur before %header section)
+ Swig_insert_file("director_common.swg", f_runtime);
+ Swig_insert_file("director.swg", f_runtime);
+ }
+ // Generate the intermediary class
+ {
+ String *filen = NewStringf("%s%s.java", outputDirectory(imclass_package), imclass_name);
+ File *f_im = NewFile(filen, "w", SWIG_output_files());
+ if (!f_im) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ // Start writing out the intermediary class file
+ emitBanner(f_im);
+
+ if (imclass_package && package)
+ Printf(f_im, "package %s.%s;", package, imclass_package);
+ else if (imclass_package)
+ Printf(f_im, "package %s;", imclass_package);
+ else if (package)
+ Printf(f_im, "package %s;\n", package);
+
+ if (imclass_imports)
+ Printf(f_im, "%s\n", imclass_imports);
+
+ if (Len(imclass_class_modifiers) > 0)
+ Printf(f_im, "%s ", imclass_class_modifiers);
+ Printf(f_im, "%s ", imclass_name);
+
+ if (imclass_baseclass && *Char(imclass_baseclass))
+ Printf(f_im, "extends %s ", imclass_baseclass);
+ if (Len(imclass_interfaces) > 0)
+ Printv(f_im, "implements ", imclass_interfaces, " ", NIL);
+ Printf(f_im, "{\n");
+
+ // Add the intermediary class methods
+ Replaceall(imclass_class_code, "$module", module_class_name);
+ Replaceall(imclass_class_code, "$imclassname", imclass_name);
+ Printv(f_im, imclass_class_code, NIL);
+ Printv(f_im, imclass_cppcasts_code, NIL);
+ if (Len(imclass_directors) > 0)
+ Printv(f_im, "\n", imclass_directors, NIL);
+
+ if (n_dmethods > 0) {
+ Putc('\n', f_im);
+ Printf(f_im, " private final static native void swig_module_init();\n");
+ Printf(f_im, " static {\n");
+ Printf(f_im, " swig_module_init();\n");
+ Printf(f_im, " }\n");
+ }
+ // Finish off the class
+ Printf(f_im, "}\n");
+ Delete(f_im);
+ }
+
+ // Generate the Java module class
+ {
+ String *filen = NewStringf("%s%s.java", SWIG_output_directory(), module_class_name);
+ File *f_module = NewFile(filen, "w", SWIG_output_files());
+ if (!f_module) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ // Start writing out the module class file
+ emitBanner(f_module);
+
+ if (package)
+ Printf(f_module, "package %s;\n", package);
+
+ if (module_imports)
+ Printf(f_module, "%s\n", module_imports);
+
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0);
+ if (comment_creation_chatter)
+ Printf(f_module, "/* This was generated from top() */\n");
+ Printv(f_module, Char(doxygen_comments), NIL);
+ Delete(doxygen_comments);
+ }
+ if (Len(module_class_modifiers) > 0)
+ Printf(f_module, "%s ", module_class_modifiers);
+ Printf(f_module, "%s ", module_class_name);
+
+ if (module_baseclass && *Char(module_baseclass))
+ Printf(f_module, "extends %s ", module_baseclass);
+ if (Len(module_interfaces) > 0) {
+ if (Len(module_class_constants_code) != 0)
+ Printv(f_module, "implements ", constants_interface_name, ", ", module_interfaces, " ", NIL);
+ else
+ Printv(f_module, "implements ", module_interfaces, " ", NIL);
+ } else {
+ if (Len(module_class_constants_code) != 0)
+ Printv(f_module, "implements ", constants_interface_name, " ", NIL);
+ }
+ Printf(f_module, "{\n");
+
+ Replaceall(module_class_code, "$module", module_class_name);
+ Replaceall(module_class_constants_code, "$module", module_class_name);
+
+ Replaceall(module_class_code, "$imclassname", imclass_name);
+ Replaceall(module_class_constants_code, "$imclassname", imclass_name);
+
+ // Add the wrapper methods
+ Printv(f_module, module_class_code, NIL);
+
+ // Finish off the class
+ Printf(f_module, "}\n");
+ Delete(f_module);
+ }
+
+ // Generate the Java constants interface
+ if (Len(module_class_constants_code) != 0) {
+ String *filen = NewStringf("%s%s.java", SWIG_output_directory(), constants_interface_name);
+ File *f_module = NewFile(filen, "w", SWIG_output_files());
+ if (!f_module) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ // Start writing out the Java constants interface file
+ emitBanner(f_module);
+
+ if (package)
+ Printf(f_module, "package %s;\n", package);
+
+ if (module_imports)
+ Printf(f_module, "%s\n", module_imports);
+
+ Printf(f_module, "public interface %s {\n", constants_interface_name);
+
+ // Write out all the global constants
+ Printv(f_module, module_class_constants_code, NIL);
+
+ // Finish off the Java interface
+ Printf(f_module, "}\n");
+ Delete(f_module);
+ }
+
+ if (upcasts_code)
+ Printv(f_wrappers, upcasts_code, NIL);
+
+ emitDirectorUpcalls();
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n");
+ Printf(f_wrappers, "}\n");
+ Printf(f_wrappers, "#endif\n");
+
+ // Output a Java type wrapper class for each SWIG type
+ for (Iterator swig_type = First(swig_types_hash); swig_type.key; swig_type = Next(swig_type)) {
+ emitTypeWrapperClass(swig_type.key, swig_type.item);
+ }
+
+ // Check for overwriting file problems on filesystems that are case insensitive
+ Iterator it1;
+ Iterator it2;
+ for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) {
+ String *item1_lower = Swig_string_lower(it1.item);
+ for (it2 = Next(it1); it2.item; it2 = Next(it2)) {
+ String *item2_lower = Swig_string_lower(it2.item);
+ if (it1.item && it2.item) {
+ if (Strcmp(item1_lower, item2_lower) == 0) {
+ Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number,
+ "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as "
+ "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item);
+ }
+ }
+ Delete(item2_lower);
+ }
+ Delete(item1_lower);
+ }
+
+ Delete(swig_types_hash);
+ swig_types_hash = NULL;
+ Delete(filenames_list);
+ filenames_list = NULL;
+ Delete(imclass_name);
+ imclass_name = NULL;
+ Delete(imclass_class_code);
+ imclass_class_code = NULL;
+ Delete(proxy_class_def);
+ proxy_class_def = NULL;
+ Delete(proxy_class_code);
+ proxy_class_code = NULL;
+ Delete(module_class_constants_code);
+ module_class_constants_code = NULL;
+ Delete(imclass_baseclass);
+ imclass_baseclass = NULL;
+ Delete(imclass_package);
+ imclass_package = NULL;
+ Delete(imclass_interfaces);
+ imclass_interfaces = NULL;
+ Delete(imclass_class_modifiers);
+ imclass_class_modifiers = NULL;
+ Delete(module_class_name);
+ module_class_name = NULL;
+ Delete(constants_interface_name);
+ constants_interface_name = NULL;
+ Delete(module_class_code);
+ module_class_code = NULL;
+ Delete(module_baseclass);
+ module_baseclass = NULL;
+ Delete(module_interfaces);
+ module_interfaces = NULL;
+ Delete(module_imports);
+ module_imports = NULL;
+ Delete(module_class_modifiers);
+ module_class_modifiers = NULL;
+ Delete(imclass_imports);
+ imclass_imports = NULL;
+ Delete(imclass_cppcasts_code);
+ imclass_cppcasts_code = NULL;
+ Delete(imclass_directors);
+ imclass_directors = NULL;
+ Delete(upcasts_code);
+ upcasts_code = NULL;
+ Delete(package);
+ package = NULL;
+ Delete(jnipackage);
+ jnipackage = NULL;
+ Delete(package_path);
+ package_path = NULL;
+ Delete(dmethods_seq);
+ dmethods_seq = NULL;
+ Delete(dmethods_table);
+ dmethods_table = NULL;
+ n_dmethods = 0;
+
+ /* Close all of the files */
+ Dump(f_header, f_runtime);
+
+ if (directorsEnabled()) {
+ Dump(f_directors, f_runtime);
+ Dump(f_directors_h, f_runtime_h);
+
+ Printf(f_runtime_h, "\n");
+ Printf(f_runtime_h, "#endif\n");
+
+ Delete(f_runtime_h);
+ f_runtime_h = NULL;
+ Delete(f_directors);
+ f_directors = NULL;
+ Delete(f_directors_h);
+ f_directors_h = NULL;
+ }
+
+ Dump(f_wrappers, f_runtime);
+ Wrapper_pretty_print(f_init, f_runtime);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Dump(f_runtime, f_begin);
+ Delete(f_runtime);
+ Delete(f_begin);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * emitBanner()
+ * ----------------------------------------------------------------------------- */
+
+ void emitBanner(File *f) {
+ Printf(f, "/* ----------------------------------------------------------------------------\n");
+ Swig_banner_target_lang(f, " *");
+ Printf(f, " * ----------------------------------------------------------------------------- */\n\n");
+ }
+
+ /*-----------------------------------------------------------------------
+ * Add new director upcall signature
+ *----------------------------------------------------------------------*/
+
+ UpcallData *addUpcallMethod(String *imclass_method, String *class_method, String *imclass_desc, String *class_desc, String *decl) {
+ String *key = NewStringf("%s|%s", imclass_method, decl);
+
+ ++curr_class_dmethod;
+
+ String *imclass_methodidx = NewStringf("%d", n_dmethods);
+ String *class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
+ n_dmethods++;
+
+ Hash *new_udata = NewHash();
+ Append(dmethods_seq, new_udata);
+ Setattr(dmethods_table, key, new_udata);
+
+ Setattr(new_udata, "method", Copy(class_method));
+ Setattr(new_udata, "fdesc", Copy(class_desc));
+ Setattr(new_udata, "imclass_method", Copy(imclass_method));
+ Setattr(new_udata, "imclass_fdesc", Copy(imclass_desc));
+ Setattr(new_udata, "imclass_methodidx", imclass_methodidx);
+ Setattr(new_udata, "class_methodidx", class_methodidx);
+ Setattr(new_udata, "decl", Copy(decl));
+
+ Delete(key);
+ return new_udata;
+ }
+
+ /*-----------------------------------------------------------------------
+ * Get director upcall signature
+ *----------------------------------------------------------------------*/
+
+ UpcallData *getUpcallMethodData(String *director_class, String *decl) {
+ String *key = NewStringf("%s|%s", director_class, decl);
+ UpcallData *udata = Getattr(dmethods_table, key);
+
+ Delete(key);
+ return udata;
+ }
+
+ /* ----------------------------------------------------------------------
+ * nativeWrapper()
+ * ---------------------------------------------------------------------- */
+
+ virtual int nativeWrapper(Node *n) {
+ String *wrapname = Getattr(n, "wrap:name");
+
+ if (!addSymbol(wrapname, n, imclass_name))
+ return SWIG_ERROR;
+
+ if (Getattr(n, "type")) {
+ Swig_save("nativeWrapper", n, "name", NIL);
+ Setattr(n, "name", wrapname);
+ native_function_flag = true;
+ functionWrapper(n);
+ Swig_restore(n);
+ native_function_flag = false;
+ } else {
+ Swig_error(input_file, line_number, "No return type for %%native method %s.\n", Getattr(n, "wrap:name"));
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * functionWrapper()
+ * ---------------------------------------------------------------------- */
+
+ virtual int functionWrapper(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ int i;
+ String *c_return_type = NewString("");
+ String *im_return_type = NewString("");
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ String *body = NewString("");
+ int num_arguments = 0;
+ int gencomma = 0;
+ bool is_void_return;
+ String *overloaded_name = getOverloadedName(n);
+ String *nondir_args = NewString("");
+ bool is_destructor = (Cmp(Getattr(n, "nodeType"), "destructor") == 0);
+
+ if (!Getattr(n, "sym:overloaded")) {
+ if (!addSymbol(symname, n, imclass_name))
+ return SWIG_ERROR;
+ }
+
+ /*
+ The rest of this function deals with generating the intermediary class wrapper function (that wraps
+ a c/c++ function) and generating the JNI c code. Each Java wrapper function has a
+ matching JNI c function call.
+ */
+
+ // A new wrapper function object
+ Wrapper *f = NewWrapper();
+
+ // Make a wrapper name for this function
+ String *jniname = makeValidJniName(overloaded_name);
+ String *wname = Swig_name_wrapper(jniname);
+
+ Delete(jniname);
+
+ /* Attach the non-standard typemaps to the parameter list. */
+ Swig_typemap_attach_parms("jni", l, f);
+ Swig_typemap_attach_parms("jtype", l, f);
+ Swig_typemap_attach_parms("jstype", l, f);
+
+ /* Get return types */
+ if ((tm = Swig_typemap_lookup("jni", n, "", 0))) {
+ Printf(c_return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ if ((tm = Swig_typemap_lookup("jtype", n, "", 0))) {
+ Printf(im_return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ is_void_return = (Cmp(c_return_type, "void") == 0);
+ if (!is_void_return)
+ Wrapper_add_localv(f, "jresult", c_return_type, "jresult = 0", NIL);
+
+ Printv(f->def, "SWIGEXPORT ", c_return_type, " JNICALL ", wname, "(JNIEnv *jenv, jclass jcls", NIL);
+
+ // Usually these function parameters are unused - The code below ensures
+ // that compilers do not issue such a warning if configured to do so.
+
+ Printv(f->code, " (void)jenv;\n", NIL);
+ Printv(f->code, " (void)jcls;\n", NIL);
+
+ // Emit all of the local variables for holding arguments.
+ emit_parameter_variables(l, f);
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+
+ // Parameter overloading
+ Setattr(n, "wrap:parms", l);
+ Setattr(n, "wrap:name", wname);
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
+ if (Getattr(n, "sym:overloaded")) {
+ // Emit warnings for the few cases that can't be overloaded in Java and give up on generating wrapper
+ Swig_overload_check(n);
+ if (Getattr(n, "overload:ignore")) {
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+ }
+
+ Printf(imclass_class_code, " public final static native %s %s(", im_return_type, overloaded_name);
+
+ num_arguments = emit_num_arguments(l);
+
+ // Now walk the function parameter list and generate code to get arguments
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+ String *im_param_type = NewString("");
+ String *c_param_type = NewString("");
+ String *arg = NewString("");
+
+ Printf(arg, "j%s", ln);
+
+ /* Get the JNI C types of the parameter */
+ if ((tm = Getattr(p, "tmap:jni"))) {
+ Printv(c_param_type, tm, NIL);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Get the intermediary class parameter types of the parameter */
+ if ((tm = Getattr(p, "tmap:jtype"))) {
+ Printv(im_param_type, tm, NIL);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to intermediary class method */
+ if (gencomma)
+ Printf(imclass_class_code, ", ");
+ Printf(imclass_class_code, "%s %s", im_param_type, arg);
+
+ // Add parameter to C function
+ Printv(f->def, ", ", c_param_type, " ", arg, NIL);
+
+ ++gencomma;
+
+ // Premature garbage collection prevention parameter
+ if (!is_destructor) {
+ String *pgc_parameter = prematureGarbageCollectionPreventionParameter(pt, p);
+ if (pgc_parameter) {
+ Printf(imclass_class_code, ", %s %s_", pgc_parameter, arg);
+ Printf(f->def, ", jobject %s_", arg);
+ Printf(f->code, " (void)%s_;\n", arg);
+ }
+ }
+ // Get typemap for this argument
+ if ((tm = Getattr(p, "tmap:in"))) {
+ addThrows(n, "tmap:in", p);
+ Replaceall(tm, "$source", arg); /* deprecated */
+ Replaceall(tm, "$target", ln); /* deprecated */
+ Replaceall(tm, "$arg", arg); /* deprecated? */
+ Replaceall(tm, "$input", arg);
+ Setattr(p, "emit:input", arg);
+
+ Printf(nondir_args, "%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(pt, 0));
+ p = nextSibling(p);
+ }
+
+ Delete(im_param_type);
+ Delete(c_param_type);
+ Delete(arg);
+ }
+
+ Printv(f->code, nondir_args, NIL);
+ Delete(nondir_args);
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ addThrows(n, "tmap:check", p);
+ Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */
+ Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ addThrows(n, "tmap:freearg", p);
+ Replaceall(tm, "$source", Getattr(p, "emit:input")); /* deprecated */
+ Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert argument output code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ addThrows(n, "tmap:argout", p);
+ Replaceall(tm, "$source", Getattr(p, "emit:input")); /* deprecated */
+ Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */
+ Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Get any Java exception classes in the throws typemap
+ ParmList *throw_parm_list = NULL;
+ if ((throw_parm_list = Getattr(n, "catchlist"))) {
+ Swig_typemap_attach_parms("throws", throw_parm_list, f);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ addThrows(n, "tmap:throws", p);
+ }
+ }
+ }
+
+ // Now write code to make the function call
+ if (!native_function_flag) {
+
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ // Handle exception classes specified in the "except" feature's "throws" attribute
+ addThrows(n, "feature:except", n);
+
+ /* Return value if necessary */
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ addThrows(n, "tmap:out", n);
+ Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */
+ Replaceall(tm, "$target", "jresult"); /* deprecated */
+ Replaceall(tm, "$result", "jresult");
+
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "1");
+ else
+ Replaceall(tm, "$owner", "0");
+
+ Printf(f->code, "%s", tm);
+ if (Len(tm))
+ Printf(f->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(t, 0), Getattr(n, "name"));
+ }
+ emit_return_variable(n, t, f);
+ }
+
+ /* Output argument output code */
+ Printv(f->code, outarg, NIL);
+
+ /* Output cleanup code */
+ Printv(f->code, cleanup, NIL);
+
+ /* Look to see if there is any newfree cleanup code */
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ addThrows(n, "tmap:newfree", n);
+ Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if (!native_function_flag) {
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ addThrows(n, "tmap:ret", n);
+ Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* Finish C function and intermediary class function definitions */
+ Printf(imclass_class_code, ")");
+ generateThrowsClause(n, imclass_class_code);
+ Printf(imclass_class_code, ";\n");
+
+ Printf(f->def, ") {");
+
+ if (!is_void_return)
+ Printv(f->code, " return jresult;\n", NIL);
+ Printf(f->code, "}\n");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", symname);
+
+ /* Contract macro modification */
+ Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ");
+
+ if (!is_void_return)
+ Replaceall(f->code, "$null", "0");
+ else
+ Replaceall(f->code, "$null", "");
+
+ /* Dump the function out */
+ if (!native_function_flag)
+ Wrapper_print(f, f_wrappers);
+
+ if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
+ moduleClassFunctionHandler(n);
+ }
+
+ /*
+ * Generate the proxy class getters/setters for public member variables.
+ * Not for enums and constants.
+ */
+ if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
+ // Capitalize the first letter in the variable to create a JavaBean type getter/setter function name
+ bool getter_flag = Cmp(symname, Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) != 0;
+
+ String *getter_setter_name = NewString("");
+ if (!getter_flag)
+ Printf(getter_setter_name, "set");
+ else
+ Printf(getter_setter_name, "get");
+ Putc(toupper((int) *Char(variable_name)), getter_setter_name);
+ Printf(getter_setter_name, "%s", Char(variable_name) + 1);
+
+ Setattr(n, "proxyfuncname", getter_setter_name);
+ Setattr(n, "imfuncname", symname);
+
+ proxyClassFunctionHandler(n);
+ Delete(getter_setter_name);
+ }
+
+ Delete(c_return_type);
+ Delete(im_return_type);
+ Delete(cleanup);
+ Delete(outarg);
+ Delete(body);
+ Delete(overloaded_name);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * variableWrapper()
+ * ----------------------------------------------------------------------- */
+
+ virtual int variableWrapper(Node *n) {
+ variable_wrapper_flag = true;
+ Language::variableWrapper(n); /* Default to functions */
+ variable_wrapper_flag = false;
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * globalvariableHandler()
+ * ------------------------------------------------------------------------ */
+
+ virtual int globalvariableHandler(Node *n) {
+
+ variable_name = Getattr(n, "sym:name");
+ global_variable_flag = true;
+ int ret = Language::globalvariableHandler(n);
+ global_variable_flag = false;
+ return ret;
+ }
+
+ String *getCurrentScopeName(String *nspace) {
+ String *scope = 0;
+ if (nspace || getCurrentClass()) {
+ scope = NewString("");
+ if (nspace)
+ Printf(scope, "%s", nspace);
+ if (Node* cls = getCurrentClass()) {
+ if (Node *outer = Getattr(cls, "nested:outer")) {
+ String *outerClassesPrefix = Copy(Getattr(outer, "sym:name"));
+ for (outer = Getattr(outer, "nested:outer"); outer != 0; outer = Getattr(outer, "nested:outer")) {
+ Push(outerClassesPrefix, ".");
+ Push(outerClassesPrefix, Getattr(outer, "sym:name"));
+ }
+ Printv(scope, nspace ? "." : "", outerClassesPrefix, ".", proxy_class_name, NIL);
+ Delete(outerClassesPrefix);
+ } else
+ Printv(scope, nspace ? "." : "", proxy_class_name, NIL);
+ }
+ }
+ return scope;
+ }
+
+ /* ----------------------------------------------------------------------
+ * enumDeclaration()
+ *
+ * C/C++ enums can be mapped in one of 4 ways, depending on the java:enum feature specified:
+ * 1) Simple enums - simple constant within the proxy class or module class
+ * 2) Typeunsafe enums - simple constant in a Java class (class named after the c++ enum name)
+ * 3) Typesafe enum - typesafe enum pattern (class named after the c++ enum name)
+ * 4) Proper enums - proper Java enum
+ * Anonymous enums always default to 1)
+ * ---------------------------------------------------------------------- */
+
+ virtual int enumDeclaration(Node *n) {
+
+ if (!ImportMode) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ String *nspace = Getattr(n, "sym:nspace"); // NSpace/getNSpace() only works during Language::enumDeclaration call
+ if (proxy_flag && !is_wrapping_class()) {
+ // Global enums / enums in a namespace
+ assert(!full_imclass_name);
+ constructIntermediateClassName(n);
+ }
+
+ enum_code = NewString("");
+ String *symname = Getattr(n, "sym:name");
+ String *constants_code = (proxy_flag && is_wrapping_class())? proxy_class_constants_code : module_class_constants_code;
+ EnumFeature enum_feature = decodeEnumFeature(n);
+ String *typemap_lookup_type = Getattr(n, "name");
+
+ if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
+ // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum
+
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0);
+ if (comment_creation_chatter)
+ Printf(enum_code, "/* This was generated from enumDeclaration() */\n");
+ Printv(enum_code, Char(doxygen_comments), NIL);
+ Delete(doxygen_comments);
+ }
+
+ String *scope = getCurrentScopeName(nspace);
+ if (!addSymbol(symname, n, scope))
+ return SWIG_ERROR;
+
+ // Pure Java baseclass and interfaces
+ const String *pure_baseclass = typemapLookup(n, "javabase", typemap_lookup_type, WARN_NONE);
+ const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE);
+
+ // Emit the enum
+ Printv(enum_code, typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers (enum modifiers really)
+ " ", symname, *Char(pure_baseclass) ? // Bases
+ " extends " : "", pure_baseclass, *Char(pure_interfaces) ? // Interfaces
+ " implements " : "", pure_interfaces, " {\n", NIL);
+ if (proxy_flag && is_wrapping_class())
+ Replaceall(enum_code, "$static ", "static ");
+ else
+ Replaceall(enum_code, "$static ", "");
+ Delete(scope);
+ } else {
+ if (symname && !Getattr(n, "unnamedinstance"))
+ Printf(constants_code, " // %s \n", symname);
+ // Translate and write javadoc comment for the enum itself if flagged
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
+ if (comment_creation_chatter)
+ Printf(constants_code, "/* This was generated from enumDeclaration() */\n");
+ Printf(constants_code, Char(doxygen_comments));
+ Printf(constants_code, "\n");
+ Delete(doxygen_comments);
+ }
+ }
+
+ // Emit each enum item
+ Language::enumDeclaration(n);
+
+ if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
+ // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum
+ // Finish the enum declaration
+ // Typemaps are used to generate the enum definition in a similar manner to proxy classes.
+ Printv(enum_code, (enum_feature == ProperEnum) ? ";\n" : "", typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class
+ typemapLookup(n, "javacode", typemap_lookup_type, WARN_NONE), // extra Java code
+ "}", NIL);
+
+ Replaceall(enum_code, "$javaclassname", symname);
+
+ // Substitute $enumvalues - intended usage is for typesafe enums
+ if (Getattr(n, "enumvalues"))
+ Replaceall(enum_code, "$enumvalues", Getattr(n, "enumvalues"));
+ else
+ Replaceall(enum_code, "$enumvalues", "");
+
+ if (proxy_flag && is_wrapping_class()) {
+ // Enums defined within the C++ class are defined within the proxy class
+
+ // Add extra indentation
+ Replaceall(enum_code, "\n", "\n ");
+ Replaceall(enum_code, " \n", "\n");
+ if (GetFlag(getCurrentClass(), "feature:interface"))
+ Printv(interface_class_code, " ", enum_code, "\n\n", NIL);
+ else
+ Printv(proxy_class_constants_code, " ", enum_code, "\n\n", NIL);
+ } else {
+ // Global enums are defined in their own file
+ String *output_directory = outputDirectory(nspace);
+ String *filen = NewStringf("%s%s.java", output_directory, symname);
+ File *f_enum = NewFile(filen, "w", SWIG_output_files());
+ if (!f_enum) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ // Start writing out the enum file
+ emitBanner(f_enum);
+
+ if (package || nspace) {
+ Printf(f_enum, "package ");
+ if (package)
+ Printv(f_enum, package, nspace ? "." : "", NIL);
+ if (nspace)
+ Printv(f_enum, nspace, NIL);
+ Printf(f_enum, ";\n");
+ }
+
+ Printv(f_enum, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE), // Import statements
+ "\n", enum_code, "\n", NIL);
+
+ Printf(f_enum, "\n");
+ Delete(f_enum);
+ Delete(output_directory);
+ }
+ } else {
+ // Wrap C++ enum with simple constant
+ Printf(enum_code, "\n");
+ if (proxy_flag && is_wrapping_class())
+ Printv(proxy_class_constants_code, enum_code, NIL);
+ else
+ Printv(module_class_constants_code, enum_code, NIL);
+ }
+
+ Delete(enum_code);
+ enum_code = NULL;
+
+ if (proxy_flag && !is_wrapping_class()) {
+ Delete(full_imclass_name);
+ full_imclass_name = 0;
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * enumvalueDeclaration()
+ * ---------------------------------------------------------------------- */
+
+ virtual int enumvalueDeclaration(Node *n) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
+ String *symname = Getattr(n, "sym:name");
+ String *value = Getattr(n, "value");
+ String *name = Getattr(n, "name");
+ Node *parent = parentNode(n);
+ int unnamedinstance = GetFlag(parent, "unnamedinstance");
+ String *parent_name = Getattr(parent, "name");
+ String *nspace = getNSpace();
+ String *newsymname = 0;
+ String *tmpValue;
+
+ // Strange hack from parent method
+ if (value)
+ tmpValue = NewString(value);
+ else
+ tmpValue = NewString(name);
+ // Note that this is used in enumValue() amongst other places
+ Setattr(n, "value", tmpValue);
+
+ // Deal with enum values that are not int
+ int swigtype = SwigType_type(Getattr(n, "type"));
+ if (swigtype == T_BOOL) {
+ const char *val = Equal(Getattr(n, "enumvalue"), "true") ? "1" : "0";
+ Setattr(n, "enumvalue", val);
+ } else if (swigtype == T_CHAR) {
+ String *val = NewStringf("'%(escape)s'", Getattr(n, "enumvalue"));
+ Setattr(n, "enumvalue", val);
+ Delete(val);
+ }
+
+ {
+ EnumFeature enum_feature = decodeEnumFeature(parent);
+
+ if ((enum_feature == SimpleEnum) && GetFlag(parent, "scopedenum")) {
+ newsymname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
+ symname = newsymname;
+ }
+
+ // Add to language symbol table
+ String *scope = 0;
+ if (unnamedinstance || !parent_name || enum_feature == SimpleEnum) {
+ String *enumClassPrefix = getEnumClassPrefix();
+ if (enumClassPrefix) {
+ scope = NewString("");
+ if (nspace)
+ Printf(scope, "%s.", nspace);
+ Printf(scope, "%s", enumClassPrefix);
+ } else {
+ scope = Copy(constants_interface_name);
+ }
+ } else {
+ scope = getCurrentScopeName(nspace);
+ if (!scope)
+ scope = Copy(Getattr(parent, "sym:name"));
+ else
+ Printf(scope, ".%s", Getattr(parent, "sym:name"));
+ }
+ if (!addSymbol(symname, n, scope))
+ return SWIG_ERROR;
+
+ if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) {
+ if (!GetFlag(n, "firstenumitem"))
+ Printf(enum_code, ",\n");
+ }
+
+ // Translate and write javadoc comment if flagged
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
+ if (comment_creation_chatter)
+ Printf(enum_code, "/* This was generated from enumvalueDeclaration() */\n");
+ Printv(enum_code, Char(doxygen_comments), NIL);
+ Delete(doxygen_comments);
+ }
+
+ if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) {
+ // Wrap (non-anonymous) C/C++ enum with a proper Java enum
+ // Emit the enum item.
+ Printf(enum_code, " %s", symname);
+ if (Getattr(n, "enumvalue")) {
+ String *value = enumValue(n);
+ Printf(enum_code, "(%s)", value);
+ Delete(value);
+ }
+ } else {
+ // Wrap C/C++ enums with constant integers or use the typesafe enum pattern
+ SwigType *typemap_lookup_type = parent_name ? parent_name : NewString("enum ");
+ Setattr(n, "type", typemap_lookup_type);
+ const String *tm = typemapLookup(n, "jstype", typemap_lookup_type, WARN_JAVA_TYPEMAP_JSTYPE_UNDEF);
+
+ String *return_type = Copy(tm);
+ substituteClassname(typemap_lookup_type, return_type);
+ const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ if ((enum_feature == TypesafeEnum) && parent_name && !unnamedinstance) {
+ // Wrap (non-anonymous) enum using the typesafe enum pattern
+ if (Getattr(n, "enumvalue")) {
+ String *value = enumValue(n);
+ Printf(enum_code, " %s final static %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value);
+ Delete(value);
+ } else {
+ Printf(enum_code, " %s final static %s %s = new %s(\"%s\");\n", methodmods, return_type, symname, return_type, symname);
+ }
+ } else {
+ // Simple integer constants
+ // Note these are always generated for anonymous enums, no matter what enum_feature is specified
+ // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later
+ String *value = enumValue(n);
+ Printf(enum_code, " %s final static %s %s = %s;\n", methodmods, return_type, symname, value);
+ Delete(value);
+ }
+ Delete(return_type);
+ }
+
+ // Add the enum value to the comma separated list being constructed in the enum declaration.
+ String *enumvalues = Getattr(parent, "enumvalues");
+ if (!enumvalues)
+ Setattr(parent, "enumvalues", Copy(symname));
+ else
+ Printv(enumvalues, ", ", symname, NIL);
+ Delete(scope);
+ }
+
+ Delete(newsymname);
+ Delete(tmpValue);
+ Swig_restore(n);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * constantWrapper()
+ * Used for wrapping constants - #define or %constant.
+ * Also for inline initialised const static primitive type member variables (short, int, double, enums etc).
+ * Java static final variables are generated for these.
+ * If the %javaconst(1) feature is used then the C constant value is used to initialise the Java final variable.
+ * If not, a JNI method is generated to get the C constant value for initialisation of the Java final variable.
+ * However, if the %javaconstvalue feature is used, it overrides all other ways to generate the initialisation.
+ * Also note that this method might be called for wrapping enum items (when the enum is using %javaconst(0)).
+ * ------------------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+ SwigType *valuetype = Getattr(n, "valuetype");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ String *return_type = NewString("");
+ String *constants_code = NewString("");
+ Swig_save("constantWrapper", n, "value", NIL);
+
+ // Translate and write javadoc comment if flagged
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
+ if (comment_creation_chatter)
+ Printf(constants_code, "/* This was generated from constantWrapper() */\n");
+ Printv(constants_code, Char(doxygen_comments), NIL);
+ Delete(doxygen_comments);
+ }
+
+ bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
+
+ const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname;
+ if (!is_enum_item) {
+ String *scope = 0;
+ if (proxy_class_name) {
+ String *nspace = getNSpace();
+ scope = NewString("");
+ if (nspace)
+ Printf(scope, "%s.", nspace);
+ Printf(scope, "%s", proxy_class_name);
+ } else {
+ scope = Copy(constants_interface_name);
+ }
+ if (!addSymbol(itemname, n, scope))
+ return SWIG_ERROR;
+ Delete(scope);
+ }
+
+ // The %javaconst feature determines how the constant value is obtained
+ int const_feature_flag = GetFlag(n, "feature:java:const");
+
+ /* Adjust the enum type for the Swig_typemap_lookup.
+ * We want the same jstype typemap for all the enum items so we use the enum type (parent node). */
+ if (is_enum_item) {
+ t = Getattr(parentNode(n), "enumtype");
+ Setattr(n, "type", t);
+ }
+
+ /* Attach the non-standard typemaps to the parameter list. */
+ Swig_typemap_attach_parms("jstype", l, NULL);
+
+ /* Get Java return types */
+ bool classname_substituted_flag = false;
+
+ if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
+ classname_substituted_flag = substituteClassname(t, tm);
+ Printf(return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ // Add the stripped quotes back in
+ String *new_value = NewString("");
+ if (SwigType_type(t) == T_STRING) {
+ Printf(new_value, "\"%s\"", Copy(Getattr(n, "value")));
+ Setattr(n, "value", new_value);
+ } else if (SwigType_type(t) == T_CHAR) {
+ Printf(new_value, "\'%s\'", Copy(Getattr(n, "value")));
+ Setattr(n, "value", new_value);
+ }
+
+ const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ Printf(constants_code, " %s final static %s %s = ", methodmods, return_type, itemname);
+
+ // Check for the %javaconstvalue feature
+ String *value = Getattr(n, "feature:java:constvalue");
+
+ if (value) {
+ Printf(constants_code, "%s;\n", value);
+ } else if (!const_feature_flag) {
+ // Default enum and constant handling will work with any type of C constant and initialises the Java variable from C through a JNI call.
+
+ if (classname_substituted_flag) {
+ if (SwigType_isenum(t)) {
+ // This handles wrapping of inline initialised const enum static member variables (not when wrapping enum items - ignored later on)
+ Printf(constants_code, "%s.swigToEnum(%s.%s());\n", return_type, full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
+ } else {
+ // This handles function pointers using the %constant directive
+ Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
+ }
+ } else {
+ Printf(constants_code, "%s.%s();\n", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
+ }
+
+ // Each constant and enum value is wrapped with a separate JNI function call
+ SetFlag(n, "feature:immutable");
+ enum_constant_flag = true;
+ variableWrapper(n);
+ enum_constant_flag = false;
+ } else {
+ // Alternative constant handling will use the C syntax to make a true Java constant and hope that it compiles as Java code
+ if (Getattr(n, "wrappedasconstant")) {
+ if (SwigType_type(valuetype) == T_CHAR)
+ Printf(constants_code, "\'%(escape)s\';\n", Getattr(n, "staticmembervariableHandler:value"));
+ else
+ Printf(constants_code, "%s;\n", Getattr(n, "staticmembervariableHandler:value"));
+ } else {
+ Printf(constants_code, "%s;\n", Getattr(n, "value"));
+ }
+ }
+
+ // Emit the generated code to appropriate place
+ // Enums only emit the intermediate and JNI methods, so no proxy or module class wrapper methods needed
+ if (!is_enum_item) {
+ if (proxy_flag && wrapping_member_flag)
+ Printv(proxy_class_constants_code, constants_code, NIL);
+ else
+ Printv(module_class_constants_code, constants_code, NIL);
+ }
+ // Cleanup
+ Swig_restore(n);
+ Delete(new_value);
+ Delete(return_type);
+ Delete(constants_code);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * insertDirective()
+ * ----------------------------------------------------------------------------- */
+
+ virtual int insertDirective(Node *n) {
+ int ret = SWIG_OK;
+ String *code = Getattr(n, "code");
+ String *section = Getattr(n, "section");
+ Replaceall(code, "$module", module_class_name);
+ Replaceall(code, "$imclassname", imclass_name);
+
+ if (!ImportMode && (Cmp(section, "proxycode") == 0)) {
+ if (proxy_class_code) {
+ Swig_typemap_replace_embedded_typemap(code, n);
+ int offset = Len(code) > 0 && *Char(code) == '\n' ? 1 : 0;
+ Printv(proxy_class_code, Char(code) + offset, "\n", NIL);
+ }
+ } else {
+ ret = Language::insertDirective(n);
+ }
+ return ret;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * pragmaDirective()
+ *
+ * Valid Pragmas:
+ * jniclassbase - base (extends) for the intermediary class
+ * jniclasspackage - package in which to generate the intermediary class
+ * jniclassclassmodifiers - class modifiers for the intermediary class
+ * jniclasscode - text (java code) is copied verbatim to the intermediary class
+ * jniclassimports - import statements for the intermediary class
+ * jniclassinterfaces - interface (implements) for the intermediary class
+ *
+ * modulebase - base (extends) for the module class
+ * moduleclassmodifiers - class modifiers for the module class
+ * modulecode - text (java code) is copied verbatim to the module class
+ * moduleimports - import statements for the module class
+ * moduleinterfaces - interface (implements) for the module class
+ *
+ * ----------------------------------------------------------------------------- */
+
+ virtual int pragmaDirective(Node *n) {
+ if (!ImportMode) {
+ String *lang = Getattr(n, "lang");
+ String *code = Getattr(n, "name");
+ String *value = Getattr(n, "value");
+
+ if (Strcmp(lang, "java") == 0) {
+
+ String *strvalue = NewString(value);
+ Replaceall(strvalue, "\\\"", "\"");
+
+ if (Strcmp(code, "jniclassbase") == 0) {
+ Delete(imclass_baseclass);
+ imclass_baseclass = Copy(strvalue);
+ } else if (Strcmp(code, "jniclasspackage") == 0) {
+ Delete(imclass_package);
+ imclass_package = Copy(strvalue);
+ String *imclass_class_package_jniname = makeValidJniName(imclass_package);
+ Printv(jnipackage, imclass_class_package_jniname, NIL);
+ Delete(imclass_class_package_jniname);
+ Replaceall(jnipackage, NSPACE_SEPARATOR, "_");
+ Append(jnipackage, "_");
+
+ String *wrapper_name = NewString("");
+ String *imclass_class_jniname = makeValidJniName(imclass_name);
+ Printf(wrapper_name, "Java_%s%s_%%f", jnipackage, imclass_class_jniname);
+ Delete(imclass_class_jniname);
+
+ Swig_name_unregister("wrapper");
+ Swig_name_register("wrapper", Char(wrapper_name));
+
+ Delete(wrapper_name);
+ } else if (Strcmp(code, "jniclassclassmodifiers") == 0) {
+ Delete(imclass_class_modifiers);
+ imclass_class_modifiers = Copy(strvalue);
+ } else if (Strcmp(code, "jniclasscode") == 0) {
+ Printf(imclass_class_code, "%s\n", strvalue);
+ } else if (Strcmp(code, "jniclassimports") == 0) {
+ Delete(imclass_imports);
+ imclass_imports = Copy(strvalue);
+ } else if (Strcmp(code, "jniclassinterfaces") == 0) {
+ Delete(imclass_interfaces);
+ imclass_interfaces = Copy(strvalue);
+ } else if (Strcmp(code, "modulebase") == 0) {
+ Delete(module_baseclass);
+ module_baseclass = Copy(strvalue);
+ } else if (Strcmp(code, "moduleclassmodifiers") == 0) {
+ Delete(module_class_modifiers);
+ module_class_modifiers = Copy(strvalue);
+ } else if (Strcmp(code, "modulecode") == 0) {
+ Printf(module_class_code, "%s\n", strvalue);
+ } else if (Strcmp(code, "moduleimports") == 0) {
+ Delete(module_imports);
+ module_imports = Copy(strvalue);
+ } else if (Strcmp(code, "moduleinterfaces") == 0) {
+ Delete(module_interfaces);
+ module_interfaces = Copy(strvalue);
+ } else if (Strcmp(code, "moduleimport") == 0) {
+ Swig_error(input_file, line_number, "Deprecated pragma. Please use the moduleimports pragma.\n");
+ } else if (Strcmp(code, "moduleinterface") == 0) {
+ Swig_error(input_file, line_number, "Deprecated pragma. Please use the moduleinterfaces pragma.\n");
+ } else if (Strcmp(code, "modulemethodmodifiers") == 0) {
+ Swig_error(input_file, line_number, "Deprecated pragma. Please use %%javamethodmodifiers.\n");
+ } else if (Strcmp(code, "allshadowimport") == 0) {
+ Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javaimports).\n");
+ } else if (Strcmp(code, "allshadowcode") == 0) {
+ Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javacode).\n");
+ } else if (Strcmp(code, "allshadowbase") == 0) {
+ Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javabase).\n");
+ } else if (Strcmp(code, "allshadowinterface") == 0) {
+ Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javainterfaces).\n");
+ } else if (Strcmp(code, "allshadowclassmodifiers") == 0) {
+ Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javaclassmodifiers).\n");
+ } else if (proxy_flag) {
+ if (Strcmp(code, "shadowcode") == 0) {
+ Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javacode).\n");
+ } else if (Strcmp(code, "shadowimport") == 0) {
+ Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javaimports).\n");
+ } else if (Strcmp(code, "shadowbase") == 0) {
+ Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javabase).\n");
+ } else if (Strcmp(code, "shadowinterface") == 0) {
+ Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javainterfaces).\n");
+ } else if (Strcmp(code, "shadowclassmodifiers") == 0) {
+ Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javaclassmodifiers).\n");
+ } else {
+ Swig_error(input_file, line_number, "Unrecognized pragma.\n");
+ }
+ } else {
+ Swig_error(input_file, line_number, "Unrecognized pragma.\n");
+ }
+ Delete(strvalue);
+ }
+ }
+ return Language::pragmaDirective(n);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getQualifiedInterfaceName()
+ * ----------------------------------------------------------------------------- */
+
+ String *getQualifiedInterfaceName(Node *n) {
+ String *ret = Getattr(n, "interface:qname");
+ if (!ret) {
+ String *nspace = Getattr(n, "sym:nspace");
+ String *symname = Getattr(n, "interface:name");
+ if (nspace) {
+ if (package)
+ ret = NewStringf("%s.%s.%s", package, nspace, symname);
+ else
+ ret = NewStringf("%s.%s", nspace, symname);
+ } else {
+ ret = Copy(symname);
+ }
+ Setattr(n, "interface:qname", ret);
+ }
+ return ret;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getInterfaceName()
+ * ----------------------------------------------------------------------------- */
+
+ String *getInterfaceName(SwigType *t, bool qualified) {
+ String *interface_name = NULL;
+ if (proxy_flag) {
+ Node *n = classLookup(t);
+ if (n && Getattr(n, "interface:name"))
+ interface_name = qualified ? getQualifiedInterfaceName(n) : Getattr(n, "interface:name");
+ }
+ return interface_name;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addInterfaceNameAndUpcasts()
+ * ----------------------------------------------------------------------------- */
+
+ void addInterfaceNameAndUpcasts(SwigType *smart, String *interface_list, String *interface_upcasts, Hash *base_list, SwigType *c_classname) {
+ List *keys = Keys(base_list);
+ for (Iterator it = First(keys); it.item; it = Next(it)) {
+ Node *base = Getattr(base_list, it.item);
+ SwigType *c_baseclassname = Getattr(base, "name");
+ String *interface_name = Getattr(base, "interface:name");
+ if (Len(interface_list))
+ Append(interface_list, ", ");
+ Append(interface_list, interface_name);
+
+ Node *attributes = NewHash();
+ String *interface_code = Copy(typemapLookup(base, "javainterfacecode", Getattr(base, "classtypeobj"), WARN_JAVA_TYPEMAP_INTERFACECODE_UNDEF, attributes));
+ String *cptr_method_name = 0;
+ if (interface_code) {
+ Replaceall(interface_code, "$interfacename", interface_name);
+ Printv(interface_upcasts, interface_code, NIL);
+ cptr_method_name = Copy(Getattr(attributes, "tmap:javainterfacecode:cptrmethod"));
+ }
+ if (!cptr_method_name)
+ cptr_method_name = NewStringf("%s_GetInterfaceCPtr", interface_name);
+ Replaceall(cptr_method_name, ".", "_");
+ Replaceall(cptr_method_name, "$interfacename", interface_name);
+
+ String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), cptr_method_name);
+ upcastsCode(smart, upcast_method_name, c_classname, c_baseclassname);
+
+ Delete(upcast_method_name);
+ Delete(cptr_method_name);
+ Delete(interface_code);
+ }
+ Delete(keys);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * upcastsCode()
+ *
+ * Add code for C++ casting to base class
+ * ----------------------------------------------------------------------------- */
+
+ void upcastsCode(SwigType *smart, String *upcast_method_name, SwigType *c_classname, SwigType *c_baseclassname) {
+ String *jniname = makeValidJniName(upcast_method_name);
+ String *wname = Swig_name_wrapper(jniname);
+
+ Printf(imclass_cppcasts_code, " public final static native long %s(long jarg1);\n", upcast_method_name);
+
+ String *classname = SwigType_namestr(c_classname);
+ String *baseclassname = SwigType_namestr(c_baseclassname);
+ if (smart) {
+ String *smartnamestr = SwigType_namestr(smart);
+ String *bsmartnamestr = SwigType_namestr(smart);
+
+ // TODO: SwigType_typedef_resolve_all on a String instead of SwigType is incorrect for templates
+ SwigType *rclassname = SwigType_typedef_resolve_all(classname);
+ SwigType *rbaseclassname = SwigType_typedef_resolve_all(baseclassname);
+ Replaceall(bsmartnamestr, rclassname, rbaseclassname);
+
+ Printv(upcasts_code,
+ "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n",
+ " jlong baseptr = 0;\n"
+ " ", smartnamestr, " *argp1;\n"
+ " (void)jenv;\n"
+ " (void)jcls;\n"
+ " argp1 = *(", smartnamestr, " **)&jarg1;\n"
+ " *(", bsmartnamestr, " **)&baseptr = argp1 ? new ", bsmartnamestr, "(*argp1) : 0;\n"
+ " return baseptr;\n"
+ "}\n", "\n", NIL);
+
+ Delete(rbaseclassname);
+ Delete(rclassname);
+ Delete(bsmartnamestr);
+ Delete(smartnamestr);
+ } else {
+ Printv(upcasts_code,
+ "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n",
+ " jlong baseptr = 0;\n"
+ " (void)jenv;\n"
+ " (void)jcls;\n"
+ " *(", baseclassname, " **)&baseptr = *(", classname, " **)&jarg1;\n"
+ " return baseptr;\n"
+ "}\n", "\n", NIL);
+ }
+
+ Delete(baseclassname);
+ Delete(classname);
+ Delete(wname);
+ Delete(jniname);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * emitProxyClassDefAndCPPCasts()
+ * ----------------------------------------------------------------------------- */
+
+ void emitProxyClassDefAndCPPCasts(Node *n) {
+ SwigType *c_classname = Getattr(n, "name");
+ SwigType *c_baseclassname = NULL;
+ String *baseclass = NULL;
+ String *interface_list = NewStringEmpty();
+ String *interface_upcasts = NewStringEmpty();
+ SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
+ bool feature_director = Swig_directorclass(n) ? true : false;
+ bool has_outerclass = Getattr(n, "nested:outer") != 0 && !GetFlag(n, "feature:flatnested");
+ SwigType *smart = Swig_cparse_smartptr(n);
+
+ // Inheritance from pure Java classes
+ Node *attributes = NewHash();
+ const String *pure_baseclass = typemapLookup(n, "javabase", typemap_lookup_type, WARN_NONE, attributes);
+ bool purebase_replace = GetFlag(attributes, "tmap:javabase:replace") ? true : false;
+ bool purebase_notderived = GetFlag(attributes, "tmap:javabase:notderived") ? true : false;
+ Delete(attributes);
+
+ // C++ inheritance
+ if (!purebase_replace) {
+ List *baselist = Getattr(n, "bases");
+ if (baselist) {
+ Iterator base = First(baselist);
+ while (base.item) {
+ if (!(GetFlag(base.item, "feature:ignore") || Getattr(base.item, "feature:interface"))) {
+ SwigType *baseclassname = Getattr(base.item, "name");
+ if (!c_baseclassname) {
+ String *name = getProxyName(baseclassname);
+ if (name) {
+ c_baseclassname = baseclassname;
+ baseclass = name;
+ }
+ } else {
+ /* Warn about multiple inheritance for additional base class(es) */
+ String *proxyclassname = Getattr(n, "classtypeobj");
+ Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Warning for %s, base %s ignored. Multiple inheritance is not supported in Java.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname));
+ }
+ }
+ base = Next(base);
+ }
+ }
+ }
+
+ Hash *interface_bases = Getattr(n, "interface:bases");
+ if (interface_bases)
+ addInterfaceNameAndUpcasts(smart, interface_list, interface_upcasts, interface_bases, c_classname);
+
+ bool derived = baseclass != 0;
+ if (derived && purebase_notderived)
+ pure_baseclass = empty_string;
+ const String *wanted_base = baseclass ? baseclass : pure_baseclass;
+
+ if (purebase_replace) {
+ wanted_base = pure_baseclass;
+ derived = false;
+ baseclass = NULL;
+ if (purebase_notderived)
+ Swig_error(Getfile(n), Getline(n), "The javabase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type);
+ } else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
+ Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Warning for %s, base %s ignored. Multiple inheritance is not supported in Java. "
+ "Perhaps you need one of the 'replace' or 'notderived' attributes in the javabase typemap?\n", typemap_lookup_type, pure_baseclass);
+ }
+
+ // Pure Java interfaces
+ const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE);
+
+ if (*Char(interface_list) && *Char(pure_interfaces))
+ Append(interface_list, ", ");
+ Append(interface_list, pure_interfaces);
+ // Start writing the proxy class
+ if (!has_outerclass) // Import statements
+ Printv(proxy_class_def, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE),"\n", NIL);
+
+ // Translate and write javadoc comment if flagged
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0);
+ if (comment_creation_chatter)
+ Printf(proxy_class_def, "/* This was generated from emitProxyClassDefAndCPPCasts() */\n");
+ Printv(proxy_class_def, Char(doxygen_comments), NIL);
+ Delete(doxygen_comments);
+ }
+
+ if (has_outerclass)
+ Printv(proxy_class_def, "static ", NIL); // C++ nested classes correspond to static java classes
+ Printv(proxy_class_def, typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
+ " $javaclassname", // Class name and bases
+ (*Char(wanted_base)) ? " extends " : "", wanted_base, *Char(interface_list) ? // Pure Java interfaces
+ " implements " : "", interface_list, " {", derived ? typemapLookup(n, "javabody_derived", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF) : // main body of class
+ typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class
+ NIL);
+
+ // C++ destructor is wrapped by the delete method
+ // Note that the method name is specified in a typemap attribute called methodname
+ String *destruct = NewString("");
+ const String *tm = NULL;
+ attributes = NewHash();
+ const String *destruct_methodname = NULL;
+ const String *destruct_methodmodifiers = NULL;
+ const String *destruct_parameters = NULL;
+ if (derived) {
+ tm = typemapLookup(n, "javadestruct_derived", typemap_lookup_type, WARN_NONE, attributes);
+ destruct_methodname = Getattr(attributes, "tmap:javadestruct_derived:methodname");
+ destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct_derived:methodmodifiers");
+ destruct_parameters = Getattr(attributes, "tmap:javadestruct_derived:parameters");
+ } else {
+ tm = typemapLookup(n, "javadestruct", typemap_lookup_type, WARN_NONE, attributes);
+ destruct_methodname = Getattr(attributes, "tmap:javadestruct:methodname");
+ destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct:methodmodifiers");
+ destruct_parameters = Getattr(attributes, "tmap:javadestruct:parameters");
+ }
+ if (tm && *Char(tm)) {
+ if (!destruct_methodname) {
+ Swig_error(Getfile(n), Getline(n), "No methodname attribute defined in javadestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
+ }
+ if (!destruct_methodmodifiers) {
+ Swig_error(Getfile(n), Getline(n), "No methodmodifiers attribute defined in javadestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name);
+ }
+ if (!destruct_parameters)
+ destruct_parameters = empty_string;
+ }
+ // Emit the finalize and delete methods
+ if (tm) {
+ // Finalize method
+ if (*Char(destructor_call)) {
+ Printv(proxy_class_def, typemapLookup(n, "javafinalize", typemap_lookup_type, WARN_NONE), NIL);
+ }
+ // delete method
+ Printv(destruct, tm, NIL);
+ if (*Char(destructor_call))
+ Replaceall(destruct, "$jnicall", destructor_call);
+ else
+ Replaceall(destruct, "$jnicall", "throw new UnsupportedOperationException(\"C++ destructor does not have public access\")");
+ if (*Char(destruct)) {
+ Printv(proxy_class_def, "\n ", NIL);
+ const String *methodmods = Getattr(n, "destructmethodmodifiers");
+ if (methodmods)
+ Printv(proxy_class_def, methodmods, NIL);
+ else
+ Printv(proxy_class_def, destruct_methodmodifiers, NIL);
+ Printv(proxy_class_def, " void ", destruct_methodname, "(", destruct_parameters, ")", destructor_throws_clause, " ", destruct, "\n", NIL);
+ }
+ }
+ if (*Char(interface_upcasts))
+ Printv(proxy_class_def, interface_upcasts, NIL);
+
+ /* Insert directordisconnect typemap, if this class has directors enabled */
+ /* Also insert the swigTakeOwnership and swigReleaseOwnership methods */
+ if (feature_director) {
+ String *destruct_jnicall, *release_jnicall, *take_jnicall;
+ String *changeown_method_name = Swig_name_member(getNSpace(), getClassPrefix(), "change_ownership");
+
+ destruct_jnicall = NewStringf("%s()", destruct_methodname);
+ release_jnicall = NewStringf("%s.%s(this, swigCPtr, false)", full_imclass_name, changeown_method_name);
+ take_jnicall = NewStringf("%s.%s(this, swigCPtr, true)", full_imclass_name, changeown_method_name);
+
+ emitCodeTypemap(n, false, typemap_lookup_type, "directordisconnect", "methodname", destruct_jnicall);
+ emitCodeTypemap(n, false, typemap_lookup_type, "directorowner_release", "methodname", release_jnicall);
+ emitCodeTypemap(n, false, typemap_lookup_type, "directorowner_take", "methodname", take_jnicall);
+
+ Delete(destruct_jnicall);
+ Delete(changeown_method_name);
+ Delete(release_jnicall);
+ Delete(take_jnicall);
+ }
+
+ Delete(interface_upcasts);
+ Delete(interface_list);
+ Delete(attributes);
+ Delete(destruct);
+
+ // Emit extra user code
+ Printv(proxy_class_def, typemapLookup(n, "javacode", typemap_lookup_type, WARN_NONE), // extra Java code
+ "\n", NIL);
+
+ if (derived) {
+ String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), smart != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast");
+ upcastsCode(smart, upcast_method_name, c_classname, c_baseclassname);
+ Delete(upcast_method_name);
+ }
+
+ Delete(smart);
+ }
+
+ /* ----------------------------------------------------------------------
+ * emitInterfaceDeclaration()
+ * ---------------------------------------------------------------------- */
+
+ void emitInterfaceDeclaration(Node *n, String *interface_name, File *f_interface, String *nspace) {
+ if (package || nspace) {
+ Printf(f_interface, "package ");
+ if (package)
+ Printv(f_interface, package, nspace ? "." : "", NIL);
+ if (nspace)
+ Printv(f_interface, nspace, NIL);
+ Printf(f_interface, ";\n");
+ }
+
+ Printv(f_interface, typemapLookup(n, "javaimports", Getattr(n, "classtypeobj"), WARN_NONE), "\n", NIL);
+ Printf(f_interface, "public interface %s", interface_name);
+ if (List *baselist = Getattr(n, "bases")) {
+ String *bases = 0;
+ for (Iterator base = First(baselist); base.item; base = Next(base)) {
+ if (GetFlag(base.item, "feature:ignore") || !Getattr(base.item, "feature:interface"))
+ continue; // TODO: warn about skipped non-interface bases
+ String *base_iname = Getattr(base.item, "interface:name");
+ if (!bases)
+ bases = Copy(base_iname);
+ else {
+ Append(bases, ", ");
+ Append(bases, base_iname);
+ }
+ }
+ if (bases) {
+ Printv(f_interface, " extends ", bases, NIL);
+ Delete(bases);
+ }
+ }
+ Printf(f_interface, " {\n");
+
+ Node *attributes = NewHash();
+ String *interface_code = Copy(typemapLookup(n, "javainterfacecode", Getattr(n, "classtypeobj"), WARN_JAVA_TYPEMAP_INTERFACECODE_UNDEF, attributes));
+ if (interface_code) {
+ String *interface_declaration = Copy(Getattr(attributes, "tmap:javainterfacecode:declaration"));
+ if (interface_declaration) {
+ Replaceall(interface_declaration, "$interfacename", interface_name);
+ Printv(f_interface, interface_declaration, NIL);
+ Delete(interface_declaration);
+ }
+ Delete(interface_code);
+ }
+ }
+
+ /* ----------------------------------------------------------------------
+ * classDeclaration()
+ * ---------------------------------------------------------------------- */
+
+ int classDeclaration(Node *n) {
+ return Language::classDeclaration(n);
+ }
+
+ /* ----------------------------------------------------------------------
+ * classHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int classHandler(Node *n) {
+ File *f_proxy = NULL;
+ File *f_interface = NULL;
+ String *old_proxy_class_name = proxy_class_name;
+ String *old_full_proxy_class_name = full_proxy_class_name;
+ String *old_full_imclass_name = full_imclass_name;
+ String *old_destructor_call = destructor_call;
+ String *old_destructor_throws_clause = destructor_throws_clause;
+ String *old_proxy_class_constants_code = proxy_class_constants_code;
+ String *old_proxy_class_def = proxy_class_def;
+ String *old_proxy_class_code = proxy_class_code;
+ bool has_outerclass = Getattr(n, "nested:outer") && !GetFlag(n, "feature:flatnested");
+ String *old_interface_class_code = interface_class_code;
+ interface_class_code = 0;
+
+ if (proxy_flag) {
+ proxy_class_name = NewString(Getattr(n, "sym:name"));
+ String *nspace = getNSpace();
+ constructIntermediateClassName(n);
+
+ String *outerClassesPrefix = 0;
+ if (Node *outer = Getattr(n, "nested:outer")) {
+ outerClassesPrefix = Copy(Getattr(outer, "sym:name"));
+ for (outer = Getattr(outer, "nested:outer"); outer != 0; outer = Getattr(outer, "nested:outer")) {
+ Push(outerClassesPrefix, ".");
+ Push(outerClassesPrefix, Getattr(outer, "sym:name"));
+ }
+ }
+ if (!nspace) {
+ full_proxy_class_name = outerClassesPrefix ? NewStringf("%s.%s", outerClassesPrefix, proxy_class_name) : NewStringf("%s", proxy_class_name);
+
+ if (Cmp(proxy_class_name, imclass_name) == 0) {
+ Printf(stderr, "Class name cannot be equal to intermediary class name: %s\n", proxy_class_name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ if (Cmp(proxy_class_name, module_class_name) == 0) {
+ Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ } else {
+ if (outerClassesPrefix) {
+ if (package)
+ full_proxy_class_name = NewStringf("%s.%s.%s.%s", package, nspace, outerClassesPrefix, proxy_class_name);
+ else
+ full_proxy_class_name = NewStringf("%s.%s.%s", nspace, outerClassesPrefix, proxy_class_name);
+ } else {
+ if (package)
+ full_proxy_class_name = NewStringf("%s.%s.%s", package, nspace, proxy_class_name);
+ else
+ full_proxy_class_name = NewStringf("%s.%s", nspace, proxy_class_name);
+ }
+ }
+
+ String *interface_name = Getattr(n, "feature:interface") ? Getattr(n, "interface:name") : 0;
+ if (outerClassesPrefix) {
+ String *fnspace = nspace ? NewStringf("%s.%s", nspace, outerClassesPrefix) : outerClassesPrefix;
+ if (!addSymbol(proxy_class_name, n, fnspace))
+ return SWIG_ERROR;
+ if (interface_name && !addInterfaceSymbol(interface_name, n, fnspace))
+ return SWIG_ERROR;
+ if (nspace)
+ Delete(fnspace);
+ Delete(outerClassesPrefix);
+ } else {
+ if (!addSymbol(proxy_class_name, n, nspace))
+ return SWIG_ERROR;
+ if (interface_name && !addInterfaceSymbol(interface_name, n, nspace))
+ return SWIG_ERROR;
+ }
+
+ // Each outer proxy class goes into a separate file
+ if (!has_outerclass) {
+ String *output_directory = outputDirectory(nspace);
+ String *filen = NewStringf("%s%s.java", output_directory, proxy_class_name);
+ f_proxy = NewFile(filen, "w", SWIG_output_files());
+ if (!f_proxy) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ Delete(output_directory);
+
+ // Start writing out the proxy class file
+ emitBanner(f_proxy);
+
+ if (package || nspace) {
+ Printf(f_proxy, "package ");
+ if (package)
+ Printv(f_proxy, package, nspace ? "." : "", NIL);
+ if (nspace)
+ Printv(f_proxy, nspace, NIL);
+ Printf(f_proxy, ";\n");
+ }
+ }
+ else
+ ++nesting_depth;
+
+ proxy_class_def = NewString("");
+ proxy_class_code = NewString("");
+ destructor_call = NewString("");
+ destructor_throws_clause = NewString("");
+ proxy_class_constants_code = NewString("");
+
+ if (Getattr(n, "feature:interface")) {
+ interface_class_code = NewString("");
+ String *output_directory = outputDirectory(nspace);
+ String *filen = NewStringf("%s%s.java", output_directory, interface_name);
+ f_interface = NewFile(filen, "w", SWIG_output_files());
+ if (!f_interface) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, filen); // file name ownership goes to the list
+ emitBanner(f_interface);
+ emitInterfaceDeclaration(n, interface_name, interface_class_code, nspace);
+ Delete(filen);
+ Delete(output_directory);
+ }
+ }
+
+ Language::classHandler(n);
+
+ if (proxy_flag) {
+ emitProxyClassDefAndCPPCasts(n);
+
+ String *javaclazzname = Swig_name_member(getNSpace(), getClassPrefix(), ""); // mangled full proxy class name
+
+ Replaceall(proxy_class_def, "$javaclassname", proxy_class_name);
+ Replaceall(proxy_class_code, "$javaclassname", proxy_class_name);
+ Replaceall(proxy_class_constants_code, "$javaclassname", proxy_class_name);
+ Replaceall(interface_class_code, "$javaclassname", proxy_class_name);
+
+ Replaceall(proxy_class_def, "$javaclazzname", javaclazzname);
+ Replaceall(proxy_class_code, "$javaclazzname", javaclazzname);
+ Replaceall(proxy_class_constants_code, "$javaclazzname", javaclazzname);
+ Replaceall(interface_class_code, "$javaclazzname", javaclazzname);
+
+ Replaceall(proxy_class_def, "$module", module_class_name);
+ Replaceall(proxy_class_code, "$module", module_class_name);
+ Replaceall(proxy_class_constants_code, "$module", module_class_name);
+ Replaceall(interface_class_code, "$module", module_class_name);
+
+ Replaceall(proxy_class_def, "$imclassname", full_imclass_name);
+ Replaceall(proxy_class_code, "$imclassname", full_imclass_name);
+ Replaceall(proxy_class_constants_code, "$imclassname", full_imclass_name);
+ Replaceall(interface_class_code, "$imclassname", full_imclass_name);
+
+ if (!has_outerclass)
+ Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
+ else {
+ Swig_offset_string(proxy_class_def, nesting_depth);
+ Append(old_proxy_class_code, proxy_class_def);
+ Swig_offset_string(proxy_class_code, nesting_depth);
+ Append(old_proxy_class_code, proxy_class_code);
+ }
+
+ // Write out all the constants
+ if (Len(proxy_class_constants_code) != 0) {
+ if (!has_outerclass)
+ Printv(f_proxy, proxy_class_constants_code, NIL);
+ else {
+ Swig_offset_string(proxy_class_constants_code, nesting_depth);
+ Append(old_proxy_class_code, proxy_class_constants_code);
+ }
+ }
+
+ if (!has_outerclass) {
+ Printf(f_proxy, "}\n");
+ Delete(f_proxy);
+ f_proxy = NULL;
+ } else {
+ for (int i = 0; i < nesting_depth; ++i)
+ Append(old_proxy_class_code, " ");
+ Append(old_proxy_class_code, "}\n\n");
+ --nesting_depth;
+ }
+
+ if (f_interface) {
+ Printv(f_interface, interface_class_code, "}\n", NIL);
+ Delete(f_interface);
+ f_interface = 0;
+ }
+
+ emitDirectorExtraMethods(n);
+
+ Delete(interface_class_code);
+ interface_class_code = old_interface_class_code;
+ Delete(javaclazzname);
+ Delete(proxy_class_name);
+ proxy_class_name = old_proxy_class_name;
+ Delete(full_proxy_class_name);
+ full_proxy_class_name = old_full_proxy_class_name;
+ Delete(full_imclass_name);
+ full_imclass_name = old_full_imclass_name;
+ Delete(destructor_call);
+ destructor_call = old_destructor_call;
+ Delete(destructor_throws_clause);
+ destructor_throws_clause = old_destructor_throws_clause;
+ Delete(proxy_class_constants_code);
+ proxy_class_constants_code = old_proxy_class_constants_code;
+ Delete(proxy_class_def);
+ proxy_class_def = old_proxy_class_def;
+ Delete(proxy_class_code);
+ proxy_class_code = old_proxy_class_code;
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * memberfunctionHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int memberfunctionHandler(Node *n) {
+ member_func_flag = true;
+ Language::memberfunctionHandler(n);
+
+ if (proxy_flag) {
+ String *overloaded_name = getOverloadedName(n);
+ String *intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name);
+ Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
+ Setattr(n, "imfuncname", intermediary_function_name);
+ proxyClassFunctionHandler(n);
+ Delete(overloaded_name);
+ }
+ member_func_flag = false;
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+
+ static_flag = true;
+ member_func_flag = true;
+ Language::staticmemberfunctionHandler(n);
+
+ if (proxy_flag) {
+ String *overloaded_name = getOverloadedName(n);
+ String *intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name);
+ Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
+ Setattr(n, "imfuncname", intermediary_function_name);
+ proxyClassFunctionHandler(n);
+ Delete(overloaded_name);
+ }
+ static_flag = false;
+ member_func_flag = false;
+
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * proxyClassFunctionHandler()
+ *
+ * Function called for creating a Java wrapper function around a c++ function in the
+ * proxy class. Used for both static and non-static C++ class functions.
+ * C++ class static functions map to Java static functions.
+ * Two extra attributes in the Node must be available. These are "proxyfuncname" -
+ * the name of the Java class proxy function, which in turn will call "imfuncname" -
+ * the intermediary (JNI) function name in the intermediary class.
+ * ----------------------------------------------------------------------------- */
+
+ void proxyClassFunctionHandler(Node *n) {
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *intermediary_function_name = Getattr(n, "imfuncname");
+ String *proxy_function_name = Getattr(n, "proxyfuncname");
+ String *tm;
+ Parm *p;
+ int i;
+ String *imcall = NewString("");
+ String *return_type = NewString("");
+ String *function_code = NewString("");
+ bool setter_flag = false;
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ bool is_interface = Getattr(parentNode(n), "feature:interface") != 0
+ && !static_flag && Getattr(n, "interface:owner") == 0;
+
+ if (!proxy_flag)
+ return;
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
+ if (Getattr(n, "overload:ignore"))
+ return;
+
+ // Don't generate proxy method for additional explicitcall method used in directors
+ if (GetFlag(n, "explicitcall"))
+ return;
+
+ if (l) {
+ if (SwigType_type(Getattr(l, "type")) == T_VOID) {
+ l = nextSibling(l);
+ }
+ }
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("in", l, NULL);
+ Swig_typemap_attach_parms("jtype", l, NULL);
+ Swig_typemap_attach_parms("jstype", l, NULL);
+ Swig_typemap_attach_parms("javain", l, NULL);
+
+ /* Get return types */
+ if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
+ // Note that in the case of polymorphic (covariant) return types, the method's return type is changed to be the base of the C++ return type
+ SwigType *covariant = Getattr(n, "covariant");
+ substituteClassname(covariant ? covariant : t, tm);
+ Printf(return_type, "%s", tm);
+ if (covariant)
+ Swig_warning(WARN_JAVA_COVARIANT_RET, input_file, line_number,
+ "Covariant return types not supported in Java. Proxy method will return %s.\n", SwigType_str(covariant, 0));
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ if (wrapping_member_flag && !enum_constant_flag) {
+ // For wrapping member variables (Javabean setter)
+ setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) == 0);
+ }
+
+ // Translate and write javadoc comment if flagged
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
+ if (comment_creation_chatter)
+ Printf(function_code, "/* This was generated from proxyclassfunctionhandler() */\n");
+ Printv(function_code, Char(doxygen_comments), NIL);
+ Delete(doxygen_comments);
+ }
+
+ /* Start generating the proxy function */
+ const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+ Printf(function_code, " %s ", methodmods);
+ if (static_flag)
+ Printf(function_code, "static ");
+ Printf(function_code, "%s %s(", return_type, proxy_function_name);
+
+ if (is_interface)
+ Printf(interface_class_code, " %s %s(", return_type, proxy_function_name);
+
+ Printv(imcall, full_imclass_name, ".$imfuncname(", NIL);
+ if (!static_flag) {
+ Printf(imcall, "swigCPtr");
+
+ String *this_type = Copy(getClassType());
+ String *name = NewString("jself");
+ String *qualifier = Getattr(n, "qualifier");
+ if (qualifier)
+ SwigType_push(this_type, qualifier);
+ SwigType_add_pointer(this_type);
+ Parm *this_parm = NewParm(this_type, name, n);
+ Swig_typemap_attach_parms("jtype", this_parm, NULL);
+ Swig_typemap_attach_parms("jstype", this_parm, NULL);
+
+ if (prematureGarbageCollectionPreventionParameter(this_type, this_parm))
+ Printf(imcall, ", this");
+
+ Delete(this_parm);
+ Delete(name);
+ Delete(this_type);
+ }
+
+ emit_mark_varargs(l);
+
+ int gencomma = !static_flag;
+
+ /* Output each parameter */
+ for (i = 0, p = l; p; i++) {
+
+ /* Ignored varargs */
+ if (checkAttribute(p, "varargs:ignore", "1")) {
+ p = nextSibling(p);
+ continue;
+ }
+
+ /* Ignored parameters */
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ /* Ignore the 'this' argument for variable wrappers */
+ if (!(variable_wrapper_flag && i == 0) || static_flag) {
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+
+ /* Get the Java parameter type */
+ if ((tm = Getattr(p, "tmap:jstype"))) {
+ substituteClassname(pt, tm);
+ Printf(param_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ String *arg = makeParameterName(n, p, i, setter_flag);
+
+ // Use typemaps to transform type used in Java proxy wrapper (in proxy class) to type used in JNI function (in intermediary class)
+ if ((tm = Getattr(p, "tmap:javain"))) {
+ addThrows(n, "tmap:javain", p);
+ substituteClassname(pt, tm);
+ Replaceall(tm, "$javainput", arg);
+ String *pre = Getattr(p, "tmap:javain:pre");
+ if (pre) {
+ substituteClassname(pt, pre);
+ Replaceall(pre, "$javainput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:javain:post");
+ if (post) {
+ substituteClassname(pt, post);
+ Replaceall(post, "$javainput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to proxy function */
+ if (gencomma >= 2) {
+ Printf(function_code, ", ");
+ if (is_interface)
+ Printf(interface_class_code, ", ");
+ }
+ gencomma = 2;
+ Printf(function_code, "%s %s", param_type, arg);
+ if (is_interface)
+ Printf(interface_class_code, "%s %s", param_type, arg);
+
+ if (prematureGarbageCollectionPreventionParameter(pt, p)) {
+ String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
+ if (pgcppname) {
+ String *argname = Copy(pgcppname);
+ Replaceall(argname, "$javainput", arg);
+ Printf(imcall, ", %s", argname);
+ Delete(argname);
+ } else {
+ Printf(imcall, ", %s", arg);
+ }
+ }
+
+ Delete(arg);
+ Delete(param_type);
+ }
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Printf(imcall, ")");
+ Printf(function_code, ")");
+
+ // Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in proxy class)
+ if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) {
+ addThrows(n, "tmap:javaout", n);
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ if (is_pre_code || is_post_code) {
+ Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
+ if (is_post_code) {
+ Insert(tm, 0, "\n try ");
+ Printv(tm, " finally {\n", post_code, "\n }", NIL);
+ } else {
+ Insert(tm, 0, "\n ");
+ }
+ if (is_pre_code) {
+ Insert(tm, 0, pre_code);
+ Insert(tm, 0, "\n");
+ }
+ Insert(tm, 0, "{");
+ Printf(tm, "\n }");
+ }
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ substituteClassname(t, tm);
+
+ // For director methods: generate code to selectively make a normal polymorphic call or
+ // an explicit method call - needed to prevent infinite recursion calls in director methods.
+ Node *explicit_n = Getattr(n, "explicitcallnode");
+ if (explicit_n) {
+ String *ex_overloaded_name = getOverloadedName(explicit_n);
+ String *ex_intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), ex_overloaded_name);
+
+ String *ex_imcall = Copy(imcall);
+ Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
+ Replaceall(imcall, "$imfuncname", intermediary_function_name);
+
+ String *excode = NewString("");
+ if (!Cmp(return_type, "void"))
+ Printf(excode, "if (getClass() == %s.class) %s; else %s", proxy_class_name, imcall, ex_imcall);
+ else
+ Printf(excode, "(getClass() == %s.class) ? %s : %s", proxy_class_name, imcall, ex_imcall);
+
+ Clear(imcall);
+ Printv(imcall, excode, NIL);
+ Delete(ex_overloaded_name);
+ Delete(excode);
+ } else {
+ Replaceall(imcall, "$imfuncname", intermediary_function_name);
+ }
+
+ Replaceall(tm, "$jnicall", imcall);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ if (is_interface) {
+ Printf(interface_class_code, ")");
+ generateThrowsClause(n, interface_class_code);
+ Printf(interface_class_code, ";\n");
+ }
+ generateThrowsClause(n, function_code);
+ Printf(function_code, " %s\n\n", tm ? tm : empty_string);
+ Printv(proxy_class_code, function_code, NIL);
+
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(function_code);
+ Delete(return_type);
+ Delete(imcall);
+ }
+
+ /* ----------------------------------------------------------------------
+ * constructorHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int constructorHandler(Node *n) {
+
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ int i;
+ String *function_code = NewString("");
+ String *helper_code = NewString(""); // Holds code for the constructor helper method generated only when the javain typemap has code in the pre or post attributes
+ String *helper_args = NewString("");
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *im_return_type = NewString("");
+ bool feature_director = (parentNode(n) && Swig_directorclass(n));
+
+ Language::constructorHandler(n);
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
+ if (Getattr(n, "overload:ignore"))
+ return SWIG_OK;
+
+ if (proxy_flag) {
+ String *overloaded_name = getOverloadedName(n);
+ String *mangled_overname = Swig_name_construct(getNSpace(), overloaded_name);
+ String *imcall = NewString("");
+
+ const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ tm = Getattr(n, "tmap:jtype"); // typemaps were attached earlier to the node
+ Printf(im_return_type, "%s", tm);
+
+ // Translate and write javadoc comment if flagged
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
+ if (comment_creation_chatter)
+ Printf(function_code, "/* This was generated from constructionhandler() */\n");
+ Printv(function_code, Char(doxygen_comments), NIL);
+ Delete(doxygen_comments);
+ }
+
+ Printf(function_code, " %s %s(", methodmods, proxy_class_name);
+ Printf(helper_code, " static private %s SwigConstruct%s(", im_return_type, proxy_class_name);
+
+ Printv(imcall, full_imclass_name, ".", mangled_overname, "(", NIL);
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("in", l, NULL);
+ Swig_typemap_attach_parms("jtype", l, NULL);
+ Swig_typemap_attach_parms("jstype", l, NULL);
+ Swig_typemap_attach_parms("javain", l, NULL);
+
+ emit_mark_varargs(l);
+
+ int gencomma = 0;
+
+ /* Output each parameter */
+ for (i = 0, p = l; p; i++) {
+
+ /* Ignored varargs */
+ if (checkAttribute(p, "varargs:ignore", "1")) {
+ p = nextSibling(p);
+ continue;
+ }
+
+ /* Ignored parameters */
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+
+ /* Get the Java parameter type */
+ if ((tm = Getattr(p, "tmap:jstype"))) {
+ substituteClassname(pt, tm);
+ Printf(param_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ String *arg = makeParameterName(n, p, i, false);
+
+ // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in JNI function (in intermediary class)
+ if ((tm = Getattr(p, "tmap:javain"))) {
+ addThrows(n, "tmap:javain", p);
+ substituteClassname(pt, tm);
+ Replaceall(tm, "$javainput", arg);
+ String *pre = Getattr(p, "tmap:javain:pre");
+ if (pre) {
+ substituteClassname(pt, pre);
+ Replaceall(pre, "$javainput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:javain:post");
+ if (post) {
+ substituteClassname(pt, post);
+ Replaceall(post, "$javainput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to proxy function */
+ if (gencomma) {
+ Printf(function_code, ", ");
+ Printf(helper_code, ", ");
+ Printf(helper_args, ", ");
+ }
+ Printf(function_code, "%s %s", param_type, arg);
+ Printf(helper_code, "%s %s", param_type, arg);
+ Printf(helper_args, "%s", arg);
+ ++gencomma;
+
+ if (prematureGarbageCollectionPreventionParameter(pt, p)) {
+ String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
+ if (pgcppname) {
+ String *argname = Copy(pgcppname);
+ Replaceall(argname, "$javainput", arg);
+ Printf(imcall, ", %s", argname);
+ Delete(argname);
+ } else {
+ Printf(imcall, ", %s", arg);
+ }
+ }
+
+ Delete(arg);
+ Delete(param_type);
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Printf(imcall, ")");
+
+ Printf(function_code, ")");
+ Printf(helper_code, ")");
+ generateThrowsClause(n, function_code);
+
+ /* Insert the javaconstruct typemap, doing the replacement for $directorconnect, as needed */
+ Hash *attributes = NewHash();
+ String *typemap_lookup_type = Getattr(getCurrentClass(), "classtypeobj");
+ String *construct_tm = Copy(typemapLookup(n, "javaconstruct", typemap_lookup_type,
+ WARN_JAVA_TYPEMAP_JAVACONSTRUCT_UNDEF, attributes));
+ if (construct_tm) {
+ if (!feature_director) {
+ Replaceall(construct_tm, "$directorconnect", "");
+ } else {
+ String *connect_attr = Getattr(attributes, "tmap:javaconstruct:directorconnect");
+
+ if (connect_attr) {
+ Replaceall(construct_tm, "$directorconnect", connect_attr);
+ } else {
+ Swig_warning(WARN_JAVA_NO_DIRECTORCONNECT_ATTR, input_file, line_number, "\"directorconnect\" attribute missing in %s \"javaconstruct\" typemap.\n",
+ Getattr(n, "name"));
+ Replaceall(construct_tm, "$directorconnect", "");
+ }
+ }
+
+ Printv(function_code, " ", construct_tm, "\n", NIL);
+ }
+
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ if (is_pre_code || is_post_code) {
+ generateThrowsClause(n, helper_code);
+ Printf(helper_code, " {\n");
+ if (is_pre_code) {
+ Printv(helper_code, pre_code, "\n", NIL);
+ }
+ if (is_post_code) {
+ Printf(helper_code, " try {\n");
+ Printv(helper_code, " return ", imcall, ";\n", NIL);
+ Printv(helper_code, " } finally {\n", post_code, "\n }", NIL);
+ } else {
+ Printv(helper_code, " return ", imcall, ";", NIL);
+ }
+ Printf(helper_code, "\n }\n");
+ String *helper_name = NewStringf("%s.SwigConstruct%s(%s)", proxy_class_name, proxy_class_name, helper_args);
+ Printv(proxy_class_code, helper_code, "\n", NIL);
+ Replaceall(function_code, "$imcall", helper_name);
+ Delete(helper_name);
+ } else {
+ Replaceall(function_code, "$imcall", imcall);
+ }
+
+ Printv(proxy_class_code, function_code, "\n", NIL);
+
+ Delete(helper_args);
+ Delete(im_return_type);
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(construct_tm);
+ Delete(attributes);
+ Delete(overloaded_name);
+ Delete(imcall);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * destructorHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int destructorHandler(Node *n) {
+ Language::destructorHandler(n);
+ String *symname = Getattr(n, "sym:name");
+
+ if (proxy_flag) {
+ Printv(destructor_call, full_imclass_name, ".", Swig_name_destroy(getNSpace(), symname), "(swigCPtr)", NIL);
+ generateThrowsClause(n, destructor_throws_clause);
+ const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
+ if (methodmods)
+ Setattr(getCurrentClass(), "destructmethodmodifiers", methodmods);
+ }
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * membervariableHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int membervariableHandler(Node *n) {
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ variable_wrapper_flag = true;
+ Language::membervariableHandler(n);
+ wrapping_member_flag = false;
+ variable_wrapper_flag = false;
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * staticmembervariableHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int staticmembervariableHandler(Node *n) {
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ static_flag = true;
+ Language::staticmembervariableHandler(n);
+ wrapping_member_flag = false;
+ static_flag = false;
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * memberconstantHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int memberconstantHandler(Node *n) {
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ Language::memberconstantHandler(n);
+ wrapping_member_flag = false;
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getOverloadedName()
+ * ----------------------------------------------------------------------------- */
+
+ String *getOverloadedName(Node *n) {
+
+ /* Although JNI functions are designed to handle overloaded Java functions,
+ * a Java long is used for all classes in the SWIG intermediary class.
+ * The intermediary class methods are thus mangled when overloaded to give
+ * a unique name. */
+ String *overloaded_name = NewStringf("%s", Getattr(n, "sym:name"));
+
+ if (Getattr(n, "sym:overloaded")) {
+ Printv(overloaded_name, Getattr(n, "sym:overname"), NIL);
+ }
+
+ return overloaded_name;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * moduleClassFunctionHandler()
+ * ----------------------------------------------------------------------------- */
+
+ void moduleClassFunctionHandler(Node *n) {
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ int i;
+ String *imcall = NewString("");
+ String *return_type = NewString("");
+ String *function_code = NewString("");
+ int num_arguments = 0;
+ String *overloaded_name = getOverloadedName(n);
+ String *func_name = NULL;
+ bool setter_flag = false;
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+
+ // Translate and write javadoc comment if flagged
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
+ if (comment_creation_chatter)
+ Printf(function_code, "/* This was generated from moduleClassFunctionHandler() */\n");
+ Printv(function_code, doxygen_comments, NIL);
+ Delete(doxygen_comments);
+ }
+
+ if (l) {
+ if (SwigType_type(Getattr(l, "type")) == T_VOID) {
+ l = nextSibling(l);
+ }
+ }
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("jstype", l, NULL);
+ Swig_typemap_attach_parms("javain", l, NULL);
+
+ /* Get return types */
+ if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
+ substituteClassname(t, tm);
+ Printf(return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ /* Change function name for global variables */
+ if (proxy_flag && global_variable_flag) {
+ // Capitalize the first letter in the variable to create a JavaBean type getter/setter function name
+ func_name = NewString("");
+ setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), variable_name)) == 0);
+ if (setter_flag)
+ Printf(func_name, "set");
+ else
+ Printf(func_name, "get");
+ Putc(toupper((int) *Char(variable_name)), func_name);
+ Printf(func_name, "%s", Char(variable_name) + 1);
+ } else {
+ func_name = Copy(Getattr(n, "sym:name"));
+ }
+
+ /* Start generating the function */
+ const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+ Printf(function_code, " %s static %s %s(", methodmods, return_type, func_name);
+ Printv(imcall, imclass_name, ".", overloaded_name, "(", NIL);
+
+ /* Get number of required and total arguments */
+ num_arguments = emit_num_arguments(l);
+
+ bool global_or_member_variable = global_variable_flag || (wrapping_member_flag && !enum_constant_flag);
+ int gencomma = 0;
+
+ /* Output each parameter */
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ /* Ignored parameters */
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+
+ /* Get the Java parameter type */
+ if ((tm = Getattr(p, "tmap:jstype"))) {
+ substituteClassname(pt, tm);
+ Printf(param_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ String *arg = makeParameterName(n, p, i, global_or_member_variable);
+
+ // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in JNI function (in intermediary class)
+ if ((tm = Getattr(p, "tmap:javain"))) {
+ addThrows(n, "tmap:javain", p);
+ substituteClassname(pt, tm);
+ Replaceall(tm, "$javainput", arg);
+ String *pre = Getattr(p, "tmap:javain:pre");
+ if (pre) {
+ substituteClassname(pt, pre);
+ Replaceall(pre, "$javainput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:javain:post");
+ if (post) {
+ substituteClassname(pt, post);
+ Replaceall(post, "$javainput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to module class function */
+ if (gencomma >= 2)
+ Printf(function_code, ", ");
+ gencomma = 2;
+ Printf(function_code, "%s %s", param_type, arg);
+
+ if (prematureGarbageCollectionPreventionParameter(pt, p)) {
+ String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
+ if (pgcppname) {
+ String *argname = Copy(pgcppname);
+ Replaceall(argname, "$javainput", arg);
+ Printf(imcall, ", %s", argname);
+ Delete(argname);
+ } else {
+ Printf(imcall, ", %s", arg);
+ }
+ }
+
+ p = Getattr(p, "tmap:in:next");
+ Delete(arg);
+ Delete(param_type);
+ }
+
+ Printf(imcall, ")");
+ Printf(function_code, ")");
+
+ // Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in module class)
+ if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) {
+ addThrows(n, "tmap:javaout", n);
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ if (is_pre_code || is_post_code) {
+ Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
+ if (is_post_code) {
+ Insert(tm, 0, "\n try ");
+ Printv(tm, " finally {\n", post_code, "\n }", NIL);
+ } else {
+ Insert(tm, 0, "\n ");
+ }
+ if (is_pre_code) {
+ Insert(tm, 0, pre_code);
+ Insert(tm, 0, "\n");
+ }
+ Insert(tm, 0, "{");
+ Printf(tm, "\n }");
+ }
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ substituteClassname(t, tm);
+ Replaceall(tm, "$jnicall", imcall);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ generateThrowsClause(n, function_code);
+ Printf(function_code, " %s\n\n", tm ? tm : empty_string);
+ Printv(module_class_code, function_code, NIL);
+
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(function_code);
+ Delete(return_type);
+ Delete(imcall);
+ Delete(func_name);
+ }
+
+ /*----------------------------------------------------------------------
+ * replaceSpecialVariables()
+ *--------------------------------------------------------------------*/
+
+ virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
+ (void)method;
+ SwigType *type = Getattr(parm, "type");
+ substituteClassname(type, tm);
+ }
+
+ /*----------------------------------------------------------------------
+ * decodeEnumFeature()
+ * Decode the possible enum features, which are one of:
+ * %javaenum(simple)
+ * %javaenum(typeunsafe) - default
+ * %javaenum(typesafe)
+ * %javaenum(proper)
+ *--------------------------------------------------------------------*/
+
+ EnumFeature decodeEnumFeature(Node *n) {
+ EnumFeature enum_feature = TypeunsafeEnum;
+ String *feature = Getattr(n, "feature:java:enum");
+ if (feature) {
+ if (Cmp(feature, "simple") == 0)
+ enum_feature = SimpleEnum;
+ else if (Cmp(feature, "typesafe") == 0)
+ enum_feature = TypesafeEnum;
+ else if (Cmp(feature, "proper") == 0)
+ enum_feature = ProperEnum;
+ }
+ return enum_feature;
+ }
+
+ /* -----------------------------------------------------------------------
+ * enumValue()
+ * This method will return a string with an enum value to use in Java generated
+ * code. If the %javaconst feature is not used, the string will contain the intermediary
+ * class call to obtain the enum value. The intermediary class and JNI methods to obtain
+ * the enum value will be generated. Otherwise the C/C++ enum value will be used if there
+ * is one and hopefully it will compile as Java code - e.g. 20 as in: enum E{e=20};
+ * The %javaconstvalue feature overrides all other ways to generate the constant value.
+ * The caller must delete memory allocated for the returned string.
+ * ------------------------------------------------------------------------ */
+
+ String *enumValue(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+
+ // Check for the %javaconstvalue feature
+ String *value = Getattr(n, "feature:java:constvalue");
+
+ if (!value) {
+ // The %javaconst feature determines how the constant value is obtained
+ int const_feature_flag = GetFlag(n, "feature:java:const");
+
+ if (const_feature_flag) {
+ // Use the C syntax to make a true Java constant and hope that it compiles as Java code
+ value = Getattr(n, "enumvalue") ? Copy(Getattr(n, "enumvalue")) : Copy(Getattr(n, "enumvalueex"));
+ } else {
+ String *newsymname = 0;
+ if (!getCurrentClass() || !proxy_flag) {
+ String *enumClassPrefix = getEnumClassPrefix();
+ if (enumClassPrefix) {
+ // A global scoped enum
+ newsymname = Swig_name_member(0, enumClassPrefix, symname);
+ symname = newsymname;
+ }
+ }
+
+ // Get the enumvalue from a JNI call
+ if (!getCurrentClass() || !cparse_cplusplus || !proxy_flag) {
+ // Strange hack to change the name
+ Setattr(n, "name", Getattr(n, "value")); /* for wrapping of enums in a namespace when emit_action is used */
+ constantWrapper(n);
+ value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
+ } else {
+ memberconstantHandler(n);
+ value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), Swig_name_member(0, getEnumClassPrefix(), symname)));
+ }
+ Delete(newsymname);
+ }
+ }
+ return value;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getEnumName()
+ *
+ * If jnidescriptor is set, inner class names are separated with '$' otherwise a '.'
+ * and the package is also not added to the name.
+ * ----------------------------------------------------------------------------- */
+
+ String *getEnumName(SwigType *t, bool jnidescriptor) {
+ Node *enumname = NULL;
+ Node *n = enumLookup(t);
+ if (n) {
+ enumname = Getattr(n, "enumname");
+ if (!enumname || jnidescriptor) {
+ String *symname = Getattr(n, "sym:name");
+ if (symname) {
+ // Add in class scope when referencing enum if not a global enum
+ String *scopename_prefix = Swig_scopename_prefix(Getattr(n, "name"));
+ String *proxyname = 0;
+ if (scopename_prefix) {
+ proxyname = getProxyName(scopename_prefix, jnidescriptor);
+ }
+ if (proxyname) {
+ const char *class_separator = jnidescriptor ? "$" : ".";
+ enumname = NewStringf("%s%s%s", proxyname, class_separator, symname);
+ } else {
+ // global enum or enum in a namespace
+ String *nspace = Getattr(n, "sym:nspace");
+ if (nspace) {
+ if (package && !jnidescriptor)
+ enumname = NewStringf("%s.%s.%s", package, nspace, symname);
+ else
+ enumname = NewStringf("%s.%s", nspace, symname);
+ } else {
+ enumname = Copy(symname);
+ }
+ }
+ if (!jnidescriptor) {
+ Setattr(n, "enumname", enumname); // Cache it
+ Delete(enumname);
+ }
+ Delete(scopename_prefix);
+ }
+ }
+ }
+
+ return enumname;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substituteClassname()
+ *
+ * Substitute the special variable $javaclassname 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 Java class name. Note that the $&javaclassname substitution
+ * is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
+ * Note that the path separator is a '.' unless jnidescriptor is set.
+ * Inputs:
+ * pt - parameter type
+ * tm - typemap contents that might contain the special variable to be replaced
+ * jnidescriptor - if set, inner class names are separated with '$' otherwise a '/' is used for the path separator
+ * Outputs:
+ * tm - typemap contents complete with the special variable substitution
+ * Return:
+ * substitution_performed - flag indicating if a substitution was performed
+ * ----------------------------------------------------------------------------- */
+
+ bool substituteClassname(SwigType *pt, String *tm, bool jnidescriptor = false) {
+ bool substitution_performed = false;
+ SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
+ SwigType *strippedtype = SwigType_strip_qualifiers(type);
+
+ if (Strstr(tm, "$javaclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ substituteClassnameSpecialVariable(classnametype, tm, "$javaclassname", jnidescriptor);
+ substitution_performed = true;
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$*javaclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ Delete(SwigType_pop(classnametype));
+ if (Len(classnametype) > 0) {
+ substituteClassnameSpecialVariable(classnametype, tm, "$*javaclassname", jnidescriptor);
+ substitution_performed = true;
+ }
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$&javaclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ SwigType_add_pointer(classnametype);
+ substituteClassnameSpecialVariable(classnametype, tm, "$&javaclassname", jnidescriptor);
+ substitution_performed = true;
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$javainterfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$javainterfacename", jnidescriptor, true);
+ substitution_performed = true;
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$*javainterfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ Delete(SwigType_pop(interfacenametype));
+ if (Len(interfacenametype) > 0) {
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*javainterfacename", jnidescriptor, true);
+ substitution_performed = true;
+ }
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$&javainterfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ SwigType_add_pointer(interfacenametype);
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&javainterfacename", jnidescriptor, true);
+ substitution_performed = true;
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$interfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$interfacename", jnidescriptor, false);
+ substitution_performed = true;
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$*interfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ Delete(SwigType_pop(interfacenametype));
+ if (Len(interfacenametype) > 0) {
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*interfacename", jnidescriptor, false);
+ substitution_performed = true;
+ }
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$&interfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ SwigType_add_pointer(interfacenametype);
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&interfacename", jnidescriptor, false);
+ substitution_performed = true;
+ Delete(interfacenametype);
+ }
+
+ Delete(strippedtype);
+ Delete(type);
+
+ return substitution_performed;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substituteClassnameSpecialVariable()
+ * ----------------------------------------------------------------------------- */
+
+ void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable, bool jnidescriptor) {
+ String *replacementname;
+
+ if (SwigType_isenum(classnametype)) {
+ String *enumname = getEnumName(classnametype, jnidescriptor);
+ if (enumname) {
+ replacementname = Copy(enumname);
+ } else {
+ bool anonymous_enum = (Cmp(classnametype, "enum ") == 0);
+ if (anonymous_enum) {
+ replacementname = NewString("int");
+ } else {
+ // An unknown enum - one that has not been parsed (neither a C enum forward reference nor a definition) or an ignored enum
+ replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
+ Replace(replacementname, "enum ", "", DOH_REPLACE_ANY);
+ Setattr(swig_types_hash, replacementname, classnametype);
+ }
+ }
+ } else {
+ String *classname = getProxyName(classnametype, jnidescriptor); // getProxyName() works for pointers to classes too
+ if (classname) {
+ replacementname = Copy(classname);
+ } else {
+ // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
+ replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
+
+ // Add to hash table so that the type wrapper classes can be created later
+ Setattr(swig_types_hash, replacementname, classnametype);
+ }
+ }
+ if (jnidescriptor)
+ Replaceall(replacementname,".","/");
+ Replaceall(tm, classnamespecialvariable, replacementname);
+
+ Delete(replacementname);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substituteInterfacenameSpecialVariable()
+ * ----------------------------------------------------------------------------- */
+
+ void substituteInterfacenameSpecialVariable(SwigType *interfacenametype, String *tm, const char *interfacenamespecialvariable, bool jnidescriptor, bool qualified) {
+
+ String *interfacename = getInterfaceName(interfacenametype/*, jnidescriptor*/, qualified);
+ if (interfacename) {
+ String *replacementname = Copy(interfacename);
+
+ if (jnidescriptor)
+ Replaceall(replacementname,".","/");
+ Replaceall(tm, interfacenamespecialvariable, replacementname);
+
+ Delete(replacementname);
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * emitTypeWrapperClass()
+ * ----------------------------------------------------------------------------- */
+
+ void emitTypeWrapperClass(String *classname, SwigType *type) {
+ Node *n = NewHash();
+ Setfile(n, input_file);
+ Setline(n, line_number);
+
+ String *swigtype = NewString("");
+ String *filen = NewStringf("%s%s.java", SWIG_output_directory(), classname);
+ File *f_swigtype = NewFile(filen, "w", SWIG_output_files());
+ if (!f_swigtype) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ // Start writing out the type wrapper class file
+ emitBanner(f_swigtype);
+
+ if (package)
+ Printf(f_swigtype, "package %s;\n", package);
+
+ // Pure Java baseclass and interfaces
+ const String *pure_baseclass = typemapLookup(n, "javabase", type, WARN_NONE);
+ const String *pure_interfaces = typemapLookup(n, "javainterfaces", type, WARN_NONE);
+
+ // Emit the class
+ Printv(swigtype, typemapLookup(n, "javaimports", type, WARN_NONE), // Import statements
+ "\n", typemapLookup(n, "javaclassmodifiers", type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
+ " $javaclassname", // Class name and bases
+ *Char(pure_baseclass) ? " extends " : "", pure_baseclass, *Char(pure_interfaces) ? // Interfaces
+ " implements " : "", pure_interfaces, " {", typemapLookup(n, "javabody", type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class
+ typemapLookup(n, "javacode", type, WARN_NONE), // extra Java code
+ "}\n", "\n", NIL);
+
+ Replaceall(swigtype, "$javaclassname", classname);
+ Replaceall(swigtype, "$module", module_class_name);
+ Replaceall(swigtype, "$imclassname", imclass_name);
+
+ // For unknown enums
+ Replaceall(swigtype, "$static ", "");
+ Replaceall(swigtype, "$enumvalues", "");
+
+ Printv(f_swigtype, swigtype, NIL);
+
+ Delete(f_swigtype);
+ Delete(swigtype);
+ Delete(n);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * typemapLookup()
+ * n - for input only and must contain info for Getfile(n) and Getline(n) to work
+ * tmap_method - typemap method name
+ * type - typemap type to lookup
+ * warning - warning number to issue if no typemaps found
+ * typemap_attributes - the typemap attributes are attached to this node and will
+ * also be used for temporary storage if non null
+ * return is never NULL, unlike Swig_typemap_lookup()
+ * ----------------------------------------------------------------------------- */
+
+ const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) {
+ Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
+ Setattr(node, "type", type);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
+ if (!tm) {
+ tm = empty_string;
+ if (warning != WARN_NONE)
+ Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
+ }
+ if (!typemap_attributes)
+ Delete(node);
+ return tm;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addThrows()
+ *
+ * Adds exception classes to a throws list. The throws list is the list of classes
+ * that will form the Java throws clause. Mainly for checked exceptions.
+ * ----------------------------------------------------------------------------- */
+
+ void addThrows(Node *n, const String *attribute, Node *parameter) {
+ // Get the comma separated exception classes for the throws clause - held in typemap/feature's "throws" attribute
+ String *throws_attribute = NewStringf("%s:throws", attribute);
+ String *throws = Getattr(parameter, throws_attribute);
+
+ if (throws && Len(throws) > 0) {
+ String *throws_list = Getattr(n, "java:throwslist");
+ if (!throws_list) {
+ throws_list = NewList();
+ Setattr(n, "java:throwslist", throws_list);
+ }
+ // Put the exception classes in the throws clause into a temporary List
+ List *temp_classes_list = Split(throws, ',', INT_MAX);
+
+ // Add the exception classes to the node throws list, but don't duplicate if already in list
+ if (temp_classes_list && Len(temp_classes_list) > 0) {
+ for (Iterator cls = First(temp_classes_list); cls.item; cls = Next(cls)) {
+ String *exception_class = NewString(cls.item);
+ Replaceall(exception_class, " ", ""); // remove spaces
+ Replaceall(exception_class, "\t", ""); // remove tabs
+ if (Len(exception_class) > 0) {
+ // $javaclassname substitution
+ SwigType *pt = Getattr(parameter, "type");
+ substituteClassname(pt, exception_class);
+
+ // Don't duplicate the Java exception class in the throws clause
+ bool found_flag = false;
+ for (Iterator item = First(throws_list); item.item; item = Next(item)) {
+ if (Strcmp(item.item, exception_class) == 0)
+ found_flag = true;
+ }
+ if (!found_flag)
+ Append(throws_list, exception_class);
+ }
+ Delete(exception_class);
+ }
+ }
+ Delete(temp_classes_list);
+ }
+ Delete(throws_attribute);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * generateThrowsClause()
+ *
+ * Generates throws clause for checked exception
+ * ----------------------------------------------------------------------------- */
+
+ void generateThrowsClause(Node *n, String *code) {
+ // Add the throws clause into code
+ List *throws_list = Getattr(n, "java:throwslist");
+ if (throws_list) {
+ Iterator cls = First(throws_list);
+ Printf(code, " throws %s", cls.item);
+ while ((cls = Next(cls)).item)
+ Printf(code, ", %s", cls.item);
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * prematureGarbageCollectionPreventionParameter()
+ *
+ * Get the proxy class name for use in an additional generated parameter. The
+ * additional parameter is added to a native method call purely to prevent
+ * premature garbage collection of proxy classes which pass their C++ class pointer
+ * in a Java long to the JNI layer.
+ * ----------------------------------------------------------------------------- */
+
+ String *prematureGarbageCollectionPreventionParameter(SwigType *t, Parm *p) {
+ String *pgcpp_java_type = 0;
+ String *jtype = NewString(Getattr(p, "tmap:jtype"));
+
+ // Strip C comments
+ String *stripped_jtype = Swig_strip_c_comments(jtype);
+ if (stripped_jtype) {
+ Delete(jtype);
+ jtype = stripped_jtype;
+ }
+
+ // Remove whitespace
+ Replaceall(jtype, " ", "");
+ Replaceall(jtype, "\t", "");
+
+ if (Cmp(jtype, "long") == 0) {
+ if (proxy_flag) {
+ if (!GetFlag(p, "tmap:jtype:nopgcpp") && !nopgcpp_flag) {
+ String *interface_name = getInterfaceName(t, true);
+ pgcpp_java_type = interface_name ? interface_name : getProxyName(t);
+ if (!pgcpp_java_type) {
+ // Look for proxy class parameters passed to C++ layer using non-default typemaps, ie not one of above types
+ String *jstype = NewString(Getattr(p, "tmap:jstype"));
+ if (jstype) {
+ Hash *classes = getClassHash();
+ if (classes) {
+ // Strip C comments
+ String *stripped_jstype = Swig_strip_c_comments(jstype);
+ if (stripped_jstype) {
+ Delete(jstype);
+ jstype = stripped_jstype;
+ }
+ // Remove whitespace
+ Replaceall(jstype, " ", "");
+ Replaceall(jstype, "\t", "");
+
+ Iterator ki;
+ for (ki = First(classes); ki.key; ki = Next(ki)) {
+ Node *cls = ki.item;
+ if (cls && !Getattr(cls, "feature:ignore")) {
+ String *symname = Getattr(cls, "sym:name");
+ if (symname && Strcmp(symname, jstype) == 0) {
+ pgcpp_java_type = symname;
+ }
+ }
+ }
+ }
+ }
+ Delete(jstype);
+ }
+ }
+ }
+ }
+ Delete(jtype);
+ return pgcpp_java_type;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * outputDirectory()
+ *
+ * Return the directory to use for generating Java classes/enums and create the
+ * subdirectory (does not create if language specific outdir does not exist).
+ * ----------------------------------------------------------------------------- */
+
+ String *outputDirectory(String *nspace) {
+ String *output_directory = Copy(SWIG_output_directory());
+ if (nspace) {
+ String *nspace_subdirectory = Copy(nspace);
+ Replaceall(nspace_subdirectory, ".", SWIG_FILE_DELIMITER);
+ String *newdir_error = Swig_new_subdirectory(output_directory, nspace_subdirectory);
+ if (newdir_error) {
+ Printf(stderr, "%s\n", newdir_error);
+ Delete(newdir_error);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Printv(output_directory, nspace_subdirectory, SWIG_FILE_DELIMITER, 0);
+ Delete(nspace_subdirectory);
+ }
+ return output_directory;
+ }
+
+ /*----------------------------------------------------------------------
+ * Start of director methods
+ *--------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------
+ * getUpcallJNIMethod()
+ *--------------------------------------------------------------------*/
+
+ String *getUpcallJNIMethod(String *descrip) {
+ static struct {
+ char code;
+ const char *method;
+ } upcall_methods[] = {
+ {
+ 'B', "CallStaticByteMethod"}, {
+ 'C', "CallStaticCharMethod"}, {
+ 'D', "CallStaticDoubleMethod"}, {
+ 'F', "CallStaticFloatMethod"}, {
+ 'I', "CallStaticIntMethod"}, {
+ 'J', "CallStaticLongMethod"}, {
+ 'L', "CallStaticObjectMethod"}, {
+ 'S', "CallStaticShortMethod"}, {
+ 'V', "CallStaticVoidMethod"}, {
+ 'Z', "CallStaticBooleanMethod"}, {
+ '[', "CallStaticObjectMethod"}
+ };
+
+ char code;
+ int i;
+
+ code = *Char(descrip);
+ for (i = 0; i < (int) (sizeof(upcall_methods) / sizeof(upcall_methods[0])); ++i)
+ if (code == upcall_methods[i].code)
+ return NewString(upcall_methods[i].method);
+ return NULL;
+ }
+
+ /*----------------------------------------------------------------------
+ * emitDirectorUpcalls()
+ *--------------------------------------------------------------------*/
+
+ void emitDirectorUpcalls() {
+ if (n_dmethods) {
+ Wrapper *w = NewWrapper();
+ String *jni_imclass_name = makeValidJniName(imclass_name);
+ String *swig_module_init = NewString("swig_module_init");
+ String *swig_module_init_jni = makeValidJniName(swig_module_init);
+ String *dmethod_data = NewString("");
+ int n_methods = 0;
+ Iterator udata_iter;
+
+ udata_iter = First(dmethods_seq);
+ while (udata_iter.item) {
+ UpcallData *udata = udata_iter.item;
+ Printf(dmethod_data, " { \"%s\", \"%s\" }", Getattr(udata, "imclass_method"), Getattr(udata, "imclass_fdesc"));
+ ++n_methods;
+
+ udata_iter = Next(udata_iter);
+
+ if (udata_iter.item)
+ Putc(',', dmethod_data);
+ Putc('\n', dmethod_data);
+ }
+
+ Printf(f_runtime, "namespace Swig {\n");
+ Printf(f_runtime, " namespace {\n");
+ Printf(f_runtime, " jclass jclass_%s = NULL;\n", imclass_name);
+ Printf(f_runtime, " jmethodID director_method_ids[%d];\n", n_methods);
+ Printf(f_runtime, " }\n");
+ Printf(f_runtime, "}\n");
+
+ Printf(w->def, "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls) {", jnipackage, jni_imclass_name, swig_module_init_jni);
+ Printf(w->code, "static struct {\n");
+ Printf(w->code, " const char *method;\n");
+ Printf(w->code, " const char *signature;\n");
+ Printf(w->code, "} methods[%d] = {\n", n_methods);
+ Printv(w->code, dmethod_data, NIL);
+ Printf(w->code, "};\n");
+
+ Wrapper_add_local(w, "i", "int i");
+
+ Printf(w->code, "Swig::jclass_%s = (jclass) jenv->NewGlobalRef(jcls);\n", imclass_name);
+ Printf(w->code, "if (!Swig::jclass_%s) return;\n", imclass_name);
+ Printf(w->code, "for (i = 0; i < (int) (sizeof(methods)/sizeof(methods[0])); ++i) {\n");
+ Printf(w->code, " Swig::director_method_ids[i] = jenv->GetStaticMethodID(jcls, methods[i].method, methods[i].signature);\n");
+ Printf(w->code, " if (!Swig::director_method_ids[i]) return;\n");
+ Printf(w->code, "}\n");
+
+ Printf(w->code, "}\n");
+
+ Wrapper_print(w, f_wrappers);
+ Delete(dmethod_data);
+ Delete(swig_module_init_jni);
+ Delete(swig_module_init);
+ Delete(jni_imclass_name);
+ DelWrapper(w);
+ }
+ }
+
+ /*----------------------------------------------------------------------
+ * emitDirectorExtraMethods()
+ *
+ * This is where the director connect method is generated.
+ *--------------------------------------------------------------------*/
+ void emitDirectorExtraMethods(Node *n) {
+ if (!Swig_directorclass(n))
+ return;
+
+ // Output the director connect method:
+ String *jni_imclass_name = makeValidJniName(imclass_name);
+ String *norm_name = SwigType_namestr(Getattr(n, "name"));
+ String *swig_director_connect = Swig_name_member(getNSpace(), getClassPrefix(), "director_connect");
+ String *swig_director_connect_jni = makeValidJniName(swig_director_connect);
+ String *smartptr = Getattr(n, "feature:smartptr");
+ String *dirClassName = directorClassName(n);
+ Wrapper *code_wrap;
+
+ Printf(imclass_class_code, " public final static native void %s(%s obj, long cptr, boolean mem_own, boolean weak_global);\n",
+ swig_director_connect, full_proxy_class_name);
+
+ code_wrap = NewWrapper();
+ Printf(code_wrap->def,
+ "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jswig_mem_own, "
+ "jboolean jweak_global) {\n", jnipackage, jni_imclass_name, swig_director_connect_jni);
+
+ if (smartptr) {
+ Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", smartptr, smartptr);
+ Printf(code_wrap->code, " (void)jcls;\n");
+ Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n");
+ Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n");
+ Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
+ }
+ else {
+ Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
+ Printf(code_wrap->code, " (void)jcls;\n");
+ Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName);
+ }
+
+ Printf(code_wrap->code, " director->swig_connect_director(jenv, jself, jenv->GetObjectClass(jself), "
+ "(jswig_mem_own == JNI_TRUE), (jweak_global == JNI_TRUE));\n");
+ Printf(code_wrap->code, "}\n");
+
+ Wrapper_print(code_wrap, f_wrappers);
+ DelWrapper(code_wrap);
+
+ Delete(swig_director_connect_jni);
+ Delete(swig_director_connect);
+
+ // Output the swigReleaseOwnership, swigTakeOwnership methods:
+ String *changeown_method_name = Swig_name_member(getNSpace(), getClassPrefix(), "change_ownership");
+ String *changeown_jnimethod_name = makeValidJniName(changeown_method_name);
+
+ Printf(imclass_class_code, " public final static native void %s(%s obj, long cptr, boolean take_or_release);\n", changeown_method_name, full_proxy_class_name);
+
+ code_wrap = NewWrapper();
+ Printf(code_wrap->def,
+ "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jtake_or_release) {\n",
+ jnipackage, jni_imclass_name, changeown_jnimethod_name);
+
+ if (Len(smartptr)) {
+ Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", smartptr, smartptr);
+ Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n");
+ Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n");
+ Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
+ } else {
+ Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
+ Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName);
+ }
+
+ Printf(code_wrap->code, " (void)jcls;\n");
+ Printf(code_wrap->code, " if (director) {\n");
+ Printf(code_wrap->code, " director->swig_java_change_ownership(jenv, jself, jtake_or_release ? true : false);\n");
+ Printf(code_wrap->code, " }\n");
+ Printf(code_wrap->code, "}\n");
+
+ Wrapper_print(code_wrap, f_wrappers);
+ DelWrapper(code_wrap);
+
+ Delete(changeown_method_name);
+ Delete(changeown_jnimethod_name);
+ Delete(norm_name);
+ Delete(dirClassName);
+ Delete(jni_imclass_name);
+ }
+
+ /*----------------------------------------------------------------------
+ * emitCodeTypemap()
+ *
+ * Output a code typemap that uses $methodname and $jnicall, as used
+ * in the directordisconnect, director_release and director_take
+ * typemaps.
+ *--------------------------------------------------------------------*/
+
+ void emitCodeTypemap(Node *n, bool derived, SwigType *lookup_type, const String *typemap, const String *methodname, const String *jnicall) {
+ const String *tm = NULL;
+ Node *tmattrs = NewHash();
+ String *lookup_tmname = NewString(typemap);
+ String *method_attr_name;
+ String *method_attr;
+
+ if (derived) {
+ Append(lookup_tmname, "_derived");
+ }
+
+ tm = typemapLookup(n, lookup_tmname, lookup_type, WARN_NONE, tmattrs);
+ method_attr_name = NewStringf("tmap:%s:%s", lookup_tmname, methodname);
+ method_attr = Getattr(tmattrs, method_attr_name);
+
+ if (*Char(tm)) {
+ if (method_attr) {
+ String *codebody = Copy(tm);
+ Replaceall(codebody, "$methodname", method_attr);
+ Replaceall(codebody, "$jnicall", jnicall);
+ Append(proxy_class_def, codebody);
+ Delete(codebody);
+ } else {
+ Swig_error(input_file, line_number, "No %s method name attribute for %s\n", lookup_tmname, proxy_class_name);
+ }
+ } else {
+ Swig_error(input_file, line_number, "No %s typemap for %s\n", lookup_tmname, proxy_class_name);
+ }
+
+ Delete(tmattrs);
+ Delete(lookup_tmname);
+ // Delete(method_attr);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substitutePackagePath()
+ *
+ * Replace $packagepath using the javapackage typemap associated with passed
+ * parm or global package if p is 0. "$packagepath/" is replaced with "" if
+ * no package is set. Note that the path separator is a '/'.
+ * ----------------------------------------------------------------------------- */
+
+ void substitutePackagePath(String *text, Parm *p) {
+ String *pkg_path= 0;
+
+ if (p)
+ pkg_path = Swig_typemap_lookup("javapackage", p, "", 0);
+ if (!pkg_path || Len(pkg_path) == 0)
+ pkg_path = Copy(package_path);
+
+ if (Len(pkg_path) > 0) {
+ Replaceall(pkg_path, ".", "/");
+ Replaceall(text, "$packagepath", pkg_path);
+ } else {
+ Replaceall(text, "$packagepath/", empty_string);
+ Replaceall(text, "$packagepath", empty_string);
+ }
+ Delete(pkg_path);
+ }
+
+ /* ---------------------------------------------------------------
+ * Canonicalize the JNI field descriptor
+ *
+ * Replace the $packagepath and $javaclassname family of special
+ * variables with the desired package and Java proxy name as
+ * required in the JNI field descriptors.
+ *
+ * !!SFM!! If $packagepath occurs in the field descriptor, but
+ * package_path isn't set (length == 0), then strip it and the
+ * optional trailing '/' from the resulting name.
+ *
+ * --------------------------------------------------------------- */
+
+ String *canonicalizeJNIDescriptor(String *descriptor_in, Parm *p) {
+ SwigType *type = Getattr(p, "type");
+ String *descriptor_out = Copy(descriptor_in);
+
+ substituteClassname(type, descriptor_out, true);
+ substitutePackagePath(descriptor_out, p);
+
+ return descriptor_out;
+ }
+
+ /* ---------------------------------------------------------------
+ * classDirectorMethod()
+ *
+ * Emit a virtual director method to pass a method call on to the
+ * underlying Java object.
+ *
+ * --------------------------------------------------------------- */
+
+ int classDirectorMethod(Node *n, Node *parent, String *super) {
+ String *c_classname = Getattr(parent, "name");
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ String *overloaded_name = getOverloadedName(n);
+ String *storage = Getattr(n, "storage");
+ String *value = Getattr(n, "value");
+ String *decl = Getattr(n, "decl");
+ String *declaration = NewString("");
+ String *tm;
+ Parm *p;
+ int i;
+ Wrapper *w = NewWrapper();
+ ParmList *l = Getattr(n, "parms");
+ bool is_void = !(Cmp(returntype, "void"));
+ String *qualified_return = 0;
+ bool pure_virtual = (!(Cmp(storage, "virtual")) && !(Cmp(value, "0")));
+ int status = SWIG_OK;
+ bool output_director = true;
+ String *dirclassname = directorClassName(parent);
+ String *qualified_name = NewStringf("%s::%s", dirclassname, name);
+ String *jnidesc = NewString("");
+ String *classdesc = NewString("");
+ String *jniret_desc = NewString("");
+ String *classret_desc = NewString("");
+ SwigType *c_ret_type = NULL;
+ String *jupcall_args = NewString("swigjobj");
+ String *imclass_dmethod;
+ String *callback_def = NewString("");
+ String *callback_code = NewString("");
+ String *imcall_args = NewString("");
+ int classmeth_off = curr_class_dmethod - first_class_dmethod;
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+ String *qualified_classname = getProxyName(getClassName());
+
+ // Kludge Alert: functionWrapper sets sym:overload properly, but it
+ // isn't at this point, so we have to manufacture it ourselves. At least
+ // we're consistent with the sym:overload name in functionWrapper. (?? when
+ // does the overloaded method name get set?)
+
+ imclass_dmethod = NewStringf("%s", Swig_name_member(getNSpace(), dirclassname, overloaded_name));
+
+ qualified_return = SwigType_rcaststr(returntype, "c_result");
+
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ String *base_typename = SwigType_base(returntype);
+ String *resolved_typename = SwigType_typedef_resolve_all(base_typename);
+ Symtab *symtab = Getattr(n, "sym:symtab");
+ Node *typenode = Swig_symbol_clookup(resolved_typename, symtab);
+
+ if (SwigType_ispointer(returntype) || (typenode && Getattr(typenode, "abstracts"))) {
+ /* initialize pointers to something sane. Same for abstract
+ classes when a reference is returned. */
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ } else {
+ /* If returning a reference, initialize the pointer to a sane
+ default - if a Java exception occurs, then the pointer returns
+ something other than a NULL-initialized reference. */
+ SwigType *noref_type = SwigType_del_reference(Copy(returntype));
+ String *noref_ltype = SwigType_lstr(noref_type, 0);
+ String *return_ltype = SwigType_lstr(returntype, 0);
+
+ Wrapper_add_localv(w, "result_default", "static", noref_ltype, "result_default", NIL);
+ Wrapper_add_localv(w, "c_result", return_ltype, "c_result", NIL);
+ Printf(w->code, "result_default = SwigValueInit< %s >();\n", noref_ltype);
+ Printf(w->code, "c_result = &result_default;\n");
+ Delete(return_ltype);
+ Delete(noref_ltype);
+ Delete(noref_type);
+ }
+
+ Delete(base_typename);
+ Delete(resolved_typename);
+ }
+ } else {
+ SwigType *vt;
+
+ vt = cplus_value_type(returntype);
+ if (!vt) {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(vt, "c_result"), NIL);
+ Delete(vt);
+ }
+ }
+ }
+
+ /* Create the intermediate class wrapper */
+ tm = Swig_typemap_lookup("jtype", n, "", 0);
+ if (tm) {
+ Printf(callback_def, " public static %s %s(%s jself", tm, imclass_dmethod, qualified_classname);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(returntype, 0));
+ }
+
+ String *cdesc = NULL;
+ SwigType *covariant = Getattr(n, "covariant");
+ SwigType *adjustedreturntype = covariant ? covariant : returntype;
+ Parm *adjustedreturntypeparm = NewParmNode(adjustedreturntype, n);
+
+ if (Swig_typemap_lookup("directorin", adjustedreturntypeparm, "", 0)
+ && (cdesc = Getattr(adjustedreturntypeparm, "tmap:directorin:descriptor"))) {
+
+ // Note that in the case of polymorphic (covariant) return types, the
+ // method's return type is changed to be the base of the C++ return
+ // type
+ String *jnidesc_canon = canonicalizeJNIDescriptor(cdesc, adjustedreturntypeparm);
+ Append(classret_desc, jnidesc_canon);
+ Delete(jnidesc_canon);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number, "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ /* Get the JNI field descriptor for this return type, add the JNI field descriptor
+ to jniret_desc */
+ if ((c_ret_type = Swig_typemap_lookup("jni", n, "", 0))) {
+ Parm *tp = NewParmNode(c_ret_type, n);
+
+ if (!is_void && !ignored_method) {
+ String *jretval_decl = NewStringf("%s jresult", c_ret_type);
+ Wrapper_add_localv(w, "jresult", jretval_decl, "= 0", NIL);
+ Delete(jretval_decl);
+ }
+
+ String *jdesc = NULL;
+ if (Swig_typemap_lookup("directorin", tp, "", 0)
+ && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))) {
+
+ // Objects marshalled passing a Java class across JNI boundary use jobject - the nouse flag indicates this
+ // We need the specific Java class name instead of the generic 'Ljava/lang/Object;'
+ if (GetFlag(tp, "tmap:directorin:nouse"))
+ jdesc = cdesc;
+ String *jnidesc_canon = canonicalizeJNIDescriptor(jdesc, tp);
+ Append(jniret_desc, jnidesc_canon);
+ Delete(jnidesc_canon);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
+ "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(c_ret_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Delete(tp);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Delete(adjustedreturntypeparm);
+
+ Swig_director_parms_fixup(l);
+
+ /* Attach the standard typemaps */
+ Swig_typemap_attach_parms("out", l, 0);
+ Swig_typemap_attach_parms("jni", l, 0);
+ Swig_typemap_attach_parms("jtype", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("javadirectorin", l, 0);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ if (!ignored_method) {
+ /* Add Java environment pointer to wrapper */
+ String *jenvstr = NewString("jenv");
+ String *jobjstr = NewString("swigjobj");
+
+ Wrapper_add_localv(w, "swigjnienv", "JNIEnvWrapper", "swigjnienv(this)", NIL, NIL);
+ Wrapper_add_localv(w, jenvstr, "JNIEnv *", jenvstr, "= swigjnienv.getJNIEnv()", NIL);
+ Wrapper_add_localv(w, jobjstr, "jobject", jobjstr, "= (jobject) NULL", NIL);
+ Delete(jenvstr);
+ Delete(jobjstr);
+
+ /* Preamble code */
+ Printf(w->code, "if (!swig_override[%d]) {\n", classmeth_off);
+ }
+
+ if (!pure_virtual) {
+ String *super_call = Swig_method_call(super, l);
+ if (is_void) {
+ Printf(w->code, "%s;\n", super_call);
+ if (!ignored_method)
+ Printf(w->code, "return;\n");
+ } else {
+ Printf(w->code, "return %s;\n", super_call);
+ }
+ Delete(super_call);
+ } else {
+ Printf(w->code, "SWIG_JavaThrowException(JNIEnvWrapper(this).getJNIEnv(), SWIG_JavaDirectorPureVirtual, ");
+ Printf(w->code, "\"Attempted to invoke pure virtual method %s::%s.\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
+
+ /* Make sure that we return something in the case of a pure
+ * virtual method call for syntactical reasons. */
+ if (!is_void)
+ Printf(w->code, "return %s;", qualified_return);
+ else if (!ignored_method)
+ Printf(w->code, "return;\n");
+ }
+
+ if (!ignored_method) {
+ Printf(w->code, "}\n");
+ Printf(w->code, "swigjobj = swig_get_self(jenv);\n");
+ Printf(w->code, "if (swigjobj && jenv->IsSameObject(swigjobj, NULL) == JNI_FALSE) {\n");
+ }
+
+ /* Start the Java field descriptor for the intermediate class's upcall (insert jself object) */
+ Parm *tp = NewParmNode(c_classname, n);
+ String *jdesc;
+
+ if ((tm = Swig_typemap_lookup("directorin", tp, "", 0))
+ && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))) {
+ String *jni_canon = canonicalizeJNIDescriptor(jdesc, tp);
+ Append(jnidesc, jni_canon);
+ Delete(jni_canon);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
+ "No or improper directorin typemap for type %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Delete(tp);
+
+ /* Go through argument list, convert from native to Java */
+ for (i = 0, p = l; p; ++i) {
+ /* Is this superfluous? */
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = makeParameterName(n, p, i, false);
+ String *c_param_type = NULL;
+ String *c_decl = NewString("");
+ String *arg = NewString("");
+
+ Printf(arg, "j%s", ln);
+
+ /* Add various typemap's 'throws' clauses */
+ addThrows(n, "tmap:directorin", p);
+ addThrows(n, "tmap:out", p);
+
+ /* And add to the upcall args */
+ Printf(jupcall_args, ", %s", arg);
+
+ /* Get parameter's intermediary C type */
+ if ((c_param_type = Getattr(p, "tmap:jni"))) {
+ Parm *tp = NewParm(c_param_type, Getattr(p, "name"), n);
+ String *desc_tm = NULL, *jdesc = NULL, *cdesc = NULL;
+
+ /* Add to local variables */
+ Printf(c_decl, "%s %s", c_param_type, arg);
+ if (!ignored_method)
+ Wrapper_add_localv(w, arg, c_decl, (!(SwigType_ispointer(pt) || SwigType_isreference(pt)) ? "" : "= 0"), NIL);
+
+ /* Add input marshalling code and update JNI field descriptor */
+ if ((desc_tm = Swig_typemap_lookup("directorin", tp, "", 0))
+ && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))
+ && (tm = Getattr(p, "tmap:directorin"))
+ && (cdesc = Getattr(p, "tmap:directorin:descriptor"))) {
+
+ // Objects marshalled by passing a Java class across the JNI boundary use jobject as the JNI type -
+ // the nouse flag indicates this. We need the specific Java class name instead of the generic 'Ljava/lang/Object;'
+ if (GetFlag(tp, "tmap:directorin:nouse"))
+ jdesc = cdesc;
+ String *jni_canon = canonicalizeJNIDescriptor(jdesc, tp);
+ Append(jnidesc, jni_canon);
+ Delete(jni_canon);
+
+ Setattr(p, "emit:directorinput", arg);
+ Replaceall(tm, "$input", arg);
+ Replaceall(tm, "$owner", "0");
+
+ if (Len(tm))
+ if (!ignored_method)
+ Printf(w->code, "%s\n", tm);
+
+ /* Add parameter to the intermediate class code if generating the
+ * intermediate's upcall code */
+ if ((tm = Getattr(p, "tmap:jtype"))) {
+ String *din = Copy(Getattr(p, "tmap:javadirectorin"));
+ addThrows(n, "tmap:javadirectorin", p);
+
+ if (din) {
+ Replaceall(din, "$module", module_class_name);
+ Replaceall(din, "$imclassname", imclass_name);
+ substituteClassname(pt, din);
+ Replaceall(din, "$jniinput", ln);
+
+ if (i > 0)
+ Printf(imcall_args, ", ");
+ Printf(callback_def, ", %s %s", tm, ln);
+
+ if (Cmp(din, ln)) {
+ Printv(imcall_args, din, NIL);
+ } else
+ Printv(imcall_args, ln, NIL);
+
+ jni_canon = canonicalizeJNIDescriptor(cdesc, p);
+ Append(classdesc, jni_canon);
+ Delete(jni_canon);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number, "No javadirectorin typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ p = Getattr(p, "tmap:directorin:next");
+
+ Delete(desc_tm);
+ } else {
+ if (!desc_tm) {
+ Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number,
+ "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ p = nextSibling(p);
+ } else if (!jdesc) {
+ Swig_warning(WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC, input_file, line_number,
+ "Missing JNI descriptor in directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ p = Getattr(p, "tmap:directorin:next");
+ } else if (!tm) {
+ Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number,
+ "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ p = nextSibling(p);
+ } else if (!cdesc) {
+ Swig_warning(WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC, input_file, line_number,
+ "Missing JNI descriptor in directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ output_director = false;
+ }
+
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ p = nextSibling(p);
+ }
+
+ Delete(arg);
+ Delete(c_decl);
+ Delete(ln);
+ }
+
+ /* header declaration, start wrapper definition */
+ String *target;
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Add any exception specifications to the methods in the director class
+ // Get any Java exception classes in the throws typemap
+ ParmList *throw_parm_list = NULL;
+
+ // May need to add Java throws clause to director methods if %catches defined
+ // Get any Java exception classes in the throws typemap
+ ParmList *catches_list = Getattr(n, "catchlist");
+ if (catches_list) {
+ Swig_typemap_attach_parms("throws", catches_list, 0);
+ Swig_typemap_attach_parms("directorthrows", catches_list, 0);
+ for (p = catches_list; p; p = nextSibling(p)) {
+ addThrows(n, "tmap:throws", p);
+ }
+ }
+
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list) {
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ Swig_typemap_attach_parms("directorthrows", throw_parm_list, 0);
+ }
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ // %catches replaces the specified exception specification
+ if (!catches_list) {
+ addThrows(n, "tmap:throws", p);
+ }
+
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+
+ Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0));
+ Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0));
+ }
+ }
+
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+
+ /* Emit the intermediate class's upcall to the actual class */
+
+ String *upcall = NewStringf("jself.%s(%s)", symname, imcall_args);
+
+ // Handle exception classes specified in the "except" feature's "throws" attribute
+ addThrows(n, "feature:except", n);
+
+ if (!is_void) {
+ if ((tm = Swig_typemap_lookup("javadirectorout", n, "", 0))) {
+ addThrows(n, "tmap:javadirectorout", n);
+ substituteClassname(returntype, tm);
+ Replaceall(tm, "$javacall", upcall);
+
+ Printf(callback_code, " return %s;\n", tm);
+ }
+
+ if ((tm = Swig_typemap_lookup("out", n, "", 0)))
+ addThrows(n, "tmap:out", n);
+
+ Delete(tm);
+ } else
+ Printf(callback_code, " %s;\n", upcall);
+
+ Printf(callback_code, " }\n");
+ Delete(upcall);
+
+ /* Finish off the inherited upcall's definition */
+ Putc(')', callback_def);
+ generateThrowsClause(n, callback_def);
+ Printf(callback_def, " {\n");
+
+ if (!ignored_method) {
+ /* Emit the actual upcall through */
+ String *imclass_desc = NewStringf("(%s)%s", jnidesc, jniret_desc);
+ String *class_desc = NewStringf("(%s)%s", classdesc, classret_desc);
+ UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, imclass_desc, class_desc, decl);
+ String *methid = Getattr(udata, "imclass_methodidx");
+ String *methop = getUpcallJNIMethod(jniret_desc);
+
+ if (!is_void)
+ Printf(w->code, "jresult = (%s) ", c_ret_type);
+
+ Printf(w->code, "jenv->%s(Swig::jclass_%s, Swig::director_method_ids[%s], %s);\n", methop, imclass_name, methid, jupcall_args);
+
+ // Generate code to handle any Java exception thrown by director delegation
+ directorExceptHandler(n, catches_list ? catches_list : throw_parm_list, w);
+
+ if (!is_void) {
+ String *jresult_str = NewString("jresult");
+ String *result_str = NewString("c_result");
+
+ /* Copy jresult into c_result... */
+ if ((tm = Swig_typemap_lookup("directorout", n, result_str, w))) {
+ addThrows(n, "tmap:directorout", n);
+ Replaceall(tm, "$input", jresult_str);
+ Replaceall(tm, "$result", result_str);
+ Printf(w->code, "%s\n", tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s used in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Delete(jresult_str);
+ Delete(result_str);
+ }
+
+ /* Marshal outputs */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout"))) {
+ addThrows(n, "tmap:directorargout", p);
+ Replaceall(tm, "$result", makeParameterName(n, p, i, false));
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ Delete(imclass_desc);
+ Delete(class_desc);
+
+ /* Terminate wrapper code */
+ Printf(w->code, "} else {\n");
+ Printf(w->code, "SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, \"null upcall object in %s::%s \");\n",
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ Printf(w->code, "}\n");
+
+ Printf(w->code, "if (swigjobj) jenv->DeleteLocalRef(swigjobj);\n");
+
+ if (!is_void)
+ Printf(w->code, "return %s;", qualified_return);
+ }
+
+ Printf(w->code, "}");
+
+ // We expose virtual protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewString("");
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+
+ /* emit the director method */
+ if (status == SWIG_OK && output_director) {
+ if (!is_void) {
+ Replaceall(w->code, "$null", qualified_return);
+ } else {
+ Replaceall(w->code, "$null", "");
+ }
+ if (!GetFlag(n, "feature:ignore"))
+ Printv(imclass_directors, callback_def, callback_code, NIL);
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+
+ Delete(inline_extra_method);
+ Delete(qualified_return);
+ Delete(jnidesc);
+ Delete(c_ret_type);
+ Delete(jniret_desc);
+ Delete(declaration);
+ Delete(callback_def);
+ Delete(callback_code);
+ DelWrapper(w);
+
+ return status;
+ }
+
+ /* ------------------------------------------------------------
+ * directorExceptHandler()
+ *
+ * Emit code to map Java exceptions back to C++ exceptions when
+ * feature("director:except") is applied to a method node.
+ * This is generated after the Java method upcall.
+ * ------------------------------------------------------------ */
+
+ void directorExceptHandler(Node *n, ParmList *throw_parm_list, Wrapper *w) {
+
+ String *directorexcept = Getattr(n, "feature:director:except");
+ if (!directorexcept) {
+ directorexcept = NewString("");
+ Printf(directorexcept, "jthrowable $error = jenv->ExceptionOccurred();\n");
+ Printf(directorexcept, "if ($error) {");
+ Printf(directorexcept, "$directorthrowshandlers\n");
+ Printf(directorexcept, " Swig::DirectorException::raise(jenv, $error);\n");
+ Printf(directorexcept, "}\n");
+ } else {
+ directorexcept = Copy(directorexcept);
+ }
+
+ // Can explicitly disable director:except by setting to "" or "0"
+ if (Len(directorexcept) > 0 && Cmp(directorexcept, "0") != 0) {
+
+ // Replace $packagepath
+ substitutePackagePath(directorexcept, 0);
+
+ // Replace $directorthrowshandlers with any defined typemap handlers (or nothing)
+ if (Strstr(directorexcept, "$directorthrowshandlers")) {
+ String *directorthrowshandlers_code = NewString("");
+
+ for (Parm *p = throw_parm_list; p; p = nextSibling(p)) {
+ String *tm = Getattr(p, "tmap:directorthrows");
+
+ if (tm) {
+ // replace $packagepath/$javaclassname
+ String *directorthrows = canonicalizeJNIDescriptor(tm, p);
+ Printv(directorthrowshandlers_code, directorthrows, NIL);
+ Delete(directorthrows);
+ } else {
+ String *t = Getattr(p,"type");
+ Swig_warning(WARN_TYPEMAP_DIRECTORTHROWS_UNDEF, Getfile(n), Getline(n), "No directorthrows typemap defined for %s\n", SwigType_str(t, 0));
+ }
+ }
+ Replaceall(directorexcept, "$directorthrowshandlers", directorthrowshandlers_code);
+ Delete(directorthrowshandlers_code);
+ }
+
+ Replaceall(directorexcept, "$error", "swigerror");
+ Printf(w->code, " %s\n", directorexcept);
+ }
+ Delete(directorexcept);
+ }
+
+ /* ------------------------------------------------------------
+ * directorPrefixArgs()
+ * ------------------------------------------------------------ */
+
+ void directorPrefixArgs(Node *n) {
+ Parm *p;
+
+ /* Need to prepend 'jenv' to the director constructor's argument list */
+
+ String *jenv_type = NewString("JNIEnv");
+
+ SwigType_add_pointer(jenv_type);
+
+ p = NewParm(jenv_type, NewString("jenv"), n);
+ Setattr(p, "arg:byname", "1");
+ set_nextSibling(p, NULL);
+
+ Setattr(n, "director:prefix_args", p);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorConstructor(Node *n) {
+ Node *parent = parentNode(n);
+ String *decl = Getattr(n, "decl");
+ String *supername = Swig_class_name(parent);
+ String *dirclassname = directorClassName(parent);
+ String *sub = NewString("");
+ Parm *p;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms;
+ int argidx = 0;
+
+ /* Assign arguments to superclass's parameters, if not already done */
+ for (p = superparms; p; p = nextSibling(p)) {
+ String *pname = Getattr(p, "name");
+
+ if (!pname) {
+ pname = NewStringf("arg%d", argidx++);
+ Setattr(p, "name", pname);
+ }
+ }
+
+ /* insert jenv prefix argument */
+ parms = CopyParmList(superparms);
+
+ String *jenv_type = NewString("JNIEnv");
+ SwigType_add_pointer(jenv_type);
+ p = NewParm(jenv_type, NewString("jenv"), n);
+ set_nextSibling(p, parms);
+ parms = p;
+
+ directorPrefixArgs(n);
+
+ if (!Getattr(n, "defaultargs")) {
+ /* constructor */
+ {
+ String *basetype = Getattr(parent, "classtype");
+ String *target = Swig_method_decl(0, decl, dirclassname, parms, 0);
+ String *call = Swig_csuperclass_call(0, basetype, superparms);
+ String *classtype = SwigType_namestr(Getattr(n, "name"));
+
+ Printf(f_directors, "%s::%s : %s, %s {\n", dirclassname, target, call, Getattr(parent, "director:ctor"));
+ Printf(f_directors, "}\n\n");
+
+ Delete(classtype);
+ Delete(target);
+ Delete(call);
+ }
+
+ /* constructor header */
+ {
+ String *target = Swig_method_decl(0, decl, dirclassname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Delete(sub);
+ Delete(supername);
+ Delete(jenv_type);
+ Delete(parms);
+ Delete(dirclassname);
+ return Language::classDirectorConstructor(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDefaultConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorDefaultConstructor(Node *n) {
+ String *classname = Swig_class_name(n);
+ String *classtype = SwigType_namestr(Getattr(n, "name"));
+ String *dirClassName = directorClassName(n);
+ Wrapper *w = NewWrapper();
+
+ Printf(w->def, "%s::%s(JNIEnv *jenv) : %s {", dirClassName, dirClassName, Getattr(n, "director:ctor"));
+ Printf(w->code, "}\n");
+ Wrapper_print(w, f_directors);
+
+ Printf(f_directors_h, " %s(JNIEnv *jenv);\n", dirClassName);
+ DelWrapper(w);
+ Delete(classtype);
+ Delete(classname);
+ Delete(dirClassName);
+ directorPrefixArgs(n);
+ return Language::classDirectorDefaultConstructor(n);
+ }
+
+
+ /* ------------------------------------------------------------
+ * classDirectorInit()
+ * ------------------------------------------------------------ */
+
+ int classDirectorInit(Node *n) {
+ Delete(none_comparison);
+ none_comparison = NewString(""); // not used
+
+ Delete(director_ctor_code);
+ director_ctor_code = NewString("$director_new");
+
+ directorDeclaration(n);
+
+ Printf(f_directors_h, "%s {\n", Getattr(n, "director:decl"));
+ Printf(f_directors_h, "\npublic:\n");
+ Printf(f_directors_h, " void swig_connect_director(JNIEnv *jenv, jobject jself, jclass jcls, bool swig_mem_own, bool weak_global);\n");
+
+ /* Keep track of the director methods for this class */
+ first_class_dmethod = curr_class_dmethod = n_dmethods;
+
+ return Language::classDirectorInit(n);
+ }
+
+ /* ----------------------------------------------------------------------
+ * classDirectorDestructor()
+ * ---------------------------------------------------------------------- */
+
+ int classDirectorDestructor(Node *n) {
+ Node *current_class = getCurrentClass();
+ String *full_classname = Getattr(current_class, "name");
+ String *classname = Swig_class_name(current_class);
+ String *dirClassName = directorClassName(current_class);
+ Wrapper *w = NewWrapper();
+
+ if (Getattr(n, "noexcept")) {
+ Printf(f_directors_h, " virtual ~%s() noexcept;\n", dirClassName);
+ Printf(w->def, "%s::~%s() noexcept {\n", dirClassName, dirClassName);
+ } else if (Getattr(n, "throw")) {
+ Printf(f_directors_h, " virtual ~%s() throw();\n", dirClassName);
+ Printf(w->def, "%s::~%s() throw() {\n", dirClassName, dirClassName);
+ } else {
+ Printf(f_directors_h, " virtual ~%s();\n", dirClassName);
+ Printf(w->def, "%s::~%s() {\n", dirClassName, dirClassName);
+ }
+
+ /* Ensure that correct directordisconnect typemap's method name is called
+ * here: */
+
+ Node *disconn_attr = NewHash();
+ String *disconn_methodname = NULL;
+
+ typemapLookup(n, "directordisconnect", full_classname, WARN_NONE, disconn_attr);
+ disconn_methodname = Getattr(disconn_attr, "tmap:directordisconnect:methodname");
+
+ Printv(w->code, " swig_disconnect_director_self(\"", disconn_methodname, "\");\n", "}\n", NIL);
+
+ Wrapper_print(w, f_directors);
+
+ DelWrapper(w);
+ Delete(disconn_attr);
+ Delete(classname);
+ Delete(dirClassName);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorEnd()
+ * ------------------------------------------------------------ */
+
+ int classDirectorEnd(Node *n) {
+ String *full_classname = Getattr(n, "name");
+ String *classname = getProxyName(full_classname, true);
+ String *director_classname = directorClassName(n);
+ String *internal_classname;
+
+ Wrapper *w = NewWrapper();
+
+ if (Len(package_path) > 0)
+ internal_classname = NewStringf("%s/%s", package_path, classname);
+ else
+ internal_classname = NewStringf("%s", classname);
+
+ // If the namespace is multiple levels, the result of getNSpace() will have inserted
+ // .'s to delimit namespaces, so we need to replace those with /'s
+ Replace(internal_classname, NSPACE_SEPARATOR, "/", DOH_REPLACE_ANY);
+
+ Wrapper_add_localv(w, "baseclass", "static jclass baseclass", "= 0", NIL);
+ Printf(w->def, "void %s::swig_connect_director(JNIEnv *jenv, jobject jself, jclass jcls, bool swig_mem_own, bool weak_global) {", director_classname);
+
+ if (first_class_dmethod != curr_class_dmethod) {
+ Printf(w->def, "static struct {\n");
+ Printf(w->def, "const char *mname;\n");
+ Printf(w->def, "const char *mdesc;\n");
+ Printf(w->def, "jmethodID base_methid;\n");
+ Printf(w->def, "} methods[] = {\n");
+
+ for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+
+ Printf(w->def, "{ \"%s\", \"%s\", NULL }", Getattr(udata, "method"), Getattr(udata, "fdesc"));
+ if (i != curr_class_dmethod - 1)
+ Putc(',', w->def);
+ Putc('\n', w->def);
+ }
+
+ Printf(w->def, "};\n");
+ }
+
+ Printf(w->code, "if (swig_set_self(jenv, jself, swig_mem_own, weak_global)) {\n");
+ Printf(w->code, "if (!baseclass) {\n");
+ Printf(w->code, "baseclass = jenv->FindClass(\"%s\");\n", internal_classname);
+ Printf(w->code, "if (!baseclass) return;\n");
+ Printf(w->code, "baseclass = (jclass) jenv->NewGlobalRef(baseclass);\n");
+ Printf(w->code, "}\n");
+
+ int n_methods = curr_class_dmethod - first_class_dmethod;
+
+ if (n_methods) {
+ /* Emit the swig_overrides() method and the swig_override array */
+ Printf(f_directors_h, "public:\n");
+ Printf(f_directors_h, " bool swig_overrides(int n) {\n");
+ Printf(f_directors_h, " return (n < %d ? swig_override[n] : false);\n", n_methods);
+ Printf(f_directors_h, " }\n");
+ Printf(f_directors_h, "protected:\n");
+ Printf(f_directors_h, " Swig::BoolArray<%d> swig_override;\n", n_methods);
+
+ /* Emit the code to look up the class's methods, initialize the override array */
+
+ Printf(w->code, "bool derived = (jenv->IsSameObject(baseclass, jcls) ? false : true);\n");
+ Printf(w->code, "for (int i = 0; i < %d; ++i) {\n", n_methods);
+ Printf(w->code, " if (!methods[i].base_methid) {\n");
+ Printf(w->code, " methods[i].base_methid = jenv->GetMethodID(baseclass, methods[i].mname, methods[i].mdesc);\n");
+ Printf(w->code, " if (!methods[i].base_methid) return;\n");
+ Printf(w->code, " }\n");
+ // Generally, derived classes have a mix of overridden and
+ // non-overridden methods and it is worth making a GetMethodID
+ // check during initialization to determine if each method is
+ // overridden, thus avoiding unnecessary calls into Java.
+ //
+ // On the other hand, when derived classes are
+ // expected to override all director methods then the
+ // GetMethodID calls are inefficient, and it is better to let
+ // the director unconditionally call up into Java. The resulting code
+ // will still behave correctly (though less efficiently) when Java
+ // code doesn't override a given method.
+ //
+ // The assumeoverride feature on a director controls whether or not
+ // overrides are assumed.
+ if (GetFlag(n, "feature:director:assumeoverride")) {
+ Printf(w->code, " swig_override[i] = derived;\n");
+ } else {
+ Printf(w->code, " swig_override[i] = false;\n");
+ Printf(w->code, " if (derived) {\n");
+ Printf(w->code, " jmethodID methid = jenv->GetMethodID(jcls, methods[i].mname, methods[i].mdesc);\n");
+ Printf(w->code, " swig_override[i] = (methid != methods[i].base_methid);\n");
+ Printf(w->code, " jenv->ExceptionClear();\n");
+ Printf(w->code, " }\n");
+ }
+ Printf(w->code, "}\n");
+ } else {
+ Printf(f_directors_h, "public:\n");
+ Printf(f_directors_h, " bool swig_overrides(int n) {\n");
+ Printf(f_directors_h, " return false;\n");
+ Printf(f_directors_h, " }\n");
+ }
+
+ Printf(f_directors_h, "};\n\n");
+ Printf(w->code, "}\n");
+ Printf(w->code, "}\n");
+
+ Wrapper_print(w, f_directors);
+
+ DelWrapper(w);
+ Delete(internal_classname);
+
+ return Language::classDirectorEnd(n);
+ }
+
+ /* --------------------------------------------------------------------
+ * classDirectorDisown()
+ * ------------------------------------------------------------------*/
+
+ virtual int classDirectorDisown(Node *n) {
+ (void) n;
+ return SWIG_OK;
+ }
+
+ /*----------------------------------------------------------------------
+ * extraDirectorProtectedCPPMethodsRequired()
+ *--------------------------------------------------------------------*/
+
+ bool extraDirectorProtectedCPPMethodsRequired() const {
+ return false;
+ }
+
+ /*----------------------------------------------------------------------
+ * directorDeclaration()
+ *
+ * Generate the director class's declaration
+ * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
+ *--------------------------------------------------------------------*/
+
+ void directorDeclaration(Node *n) {
+ String *base = Getattr(n, "classtype");
+ String *class_ctor = NewString("Swig::Director(jenv)");
+
+ String *directorname = directorClassName(n);
+ String *declaration = Swig_class_declaration(n, directorname);
+
+ Printf(declaration, " : public %s, public Swig::Director", base);
+
+ // Stash stuff for later.
+ Setattr(n, "director:decl", declaration);
+ Setattr(n, "director:ctor", class_ctor);
+ }
+
+ /*----------------------------------------------------------------------
+ * nestedClassesSupport()
+ *--------------------------------------------------------------------*/
+
+ NestedClassSupport nestedClassesSupport() const {
+ return NCS_Full;
+ }
+}; /* class JAVA */
+
+/* -----------------------------------------------------------------------------
+ * swig_java() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_java() {
+ return new JAVA();
+}
+extern "C" Language *swig_java(void) {
+ return new_swig_java();
+}
+
+/* -----------------------------------------------------------------------------
+ * Static member variables
+ * ----------------------------------------------------------------------------- */
+
+const char *JAVA::usage = "\
+Java Options (available with -java)\n\
+ -doxygen - Convert C++ doxygen comments to JavaDoc comments in proxy classes\n\
+ -debug-doxygen-parser - Display doxygen parser module debugging information\n\
+ -debug-doxygen-translator - Display doxygen translator module debugging information\n\
+ -nopgcpp - Suppress premature garbage collection prevention parameter\n\
+ -noproxy - Generate the low-level functional interface instead\n\
+ of proxy classes\n\
+ -oldvarnames - Old intermediary method names for variable wrappers\n\
+ -package <name> - Set name of the Java package to <name>\n\
+\n";
diff --git a/contrib/tools/swig/Source/Modules/javascript.cxx b/contrib/tools/swig/Source/Modules/javascript.cxx
new file mode 100644
index 00000000000..d2b33b1b429
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/javascript.cxx
@@ -0,0 +1,2489 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * javascript.cxx
+ *
+ * Javascript language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+
+/**
+ * Enables extra debugging information in typemaps.
+ */
+static bool js_template_enable_debug = false;
+
+#define ERR_MSG_ONLY_ONE_ENGINE_PLEASE "Only one engine can be specified at a time."
+
+// keywords used for state variables
+#define NAME "name"
+#define NAME_MANGLED "name_mangled"
+#define TYPE "type"
+#define TYPE_MANGLED "type_mangled"
+#define WRAPPER_NAME "wrapper"
+#define IS_IMMUTABLE "is_immutable"
+#define IS_STATIC "is_static"
+#define IS_ABSTRACT "is_abstract"
+#define GETTER "getter"
+#define SETTER "setter"
+#define PARENT "parent"
+#define PARENT_MANGLED "parent_mangled"
+#define CTOR "ctor"
+#define CTOR_WRAPPERS "ctor_wrappers"
+#define CTOR_DISPATCHERS "ctor_dispatchers"
+#define DTOR "dtor"
+#define ARGCOUNT "wrap:argc"
+#define HAS_TEMPLATES "has_templates"
+#define FORCE_CPP "force_cpp"
+#define RESET true
+
+// keys for global state variables
+#define CREATE_NAMESPACES "create_namespaces"
+#define REGISTER_NAMESPACES "register_namespaces"
+#define INITIALIZER "initializer"
+
+// keys for class scoped state variables
+#define MEMBER_VARIABLES "member_variables"
+#define MEMBER_FUNCTIONS "member_functions"
+#define STATIC_FUNCTIONS "static_functions"
+#define STATIC_VARIABLES "static_variables"
+
+
+/**
+ * A convenience class to manage state variables for emitters.
+ * The implementation delegates to SWIG Hash DOHs and provides
+ * named sub-hashes for class, variable, and function states.
+ */
+class JSEmitterState {
+
+public:
+ JSEmitterState();
+ ~JSEmitterState();
+ DOH *globals();
+ DOH *globals(const char *key, DOH *initial = 0);
+ DOH *clazz(bool reset = false);
+ DOH *clazz(const char *key, DOH *initial = 0);
+ DOH *function(bool reset = false);
+ DOH *function(const char *key, DOH *initial = 0);
+ DOH *variable(bool reset = false);
+ DOH *variable(const char *key, DOH *initial = 0);
+ static int IsSet(DOH *val);
+
+private:
+ DOH *getState(const char *key, bool reset = false);
+ Hash *globalHash;
+};
+
+/**
+ * A convenience class that wraps a code snippet used as template
+ * for code generation.
+ */
+class Template {
+
+public:
+ Template(const String *code);
+ Template(const String *code, const String *templateName);
+ Template(const Template & other);
+ ~Template();
+ String *str();
+ Template & replace(const String *pattern, const String *repl);
+ Template & print(DOH *doh);
+ Template & pretty_print(DOH *doh);
+ void operator=(const Template & t);
+ Template & trim();
+
+private:
+ String *code;
+ String *templateName;
+};
+
+/**
+ * JSEmitter represents an abstraction of javascript code generators
+ * for different javascript engines.
+ **/
+class JSEmitter {
+
+protected:
+
+ typedef JSEmitterState State;
+
+ enum MarshallingMode {
+ Setter,
+ Getter,
+ Ctor,
+ Function
+ };
+
+public:
+
+ enum JSEngine {
+ JavascriptCore,
+ V8,
+ NodeJS
+ };
+
+ JSEmitter(JSEngine engine);
+
+ virtual ~ JSEmitter();
+
+ /**
+ * Opens output files and temporary output DOHs.
+ */
+ virtual int initialize(Node *n);
+
+ /**
+ * Writes all collected code into the output file(s).
+ */
+ virtual int dump(Node *n) = 0;
+
+ /**
+ * Cleans up all open output DOHs.
+ */
+ virtual int close() = 0;
+
+ /**
+ * Switches the context for code generation.
+ *
+ * Classes, global variables and global functions may need to
+ * be registered in certain static tables.
+ * This method should be used to switch output DOHs correspondingly.
+ */
+ virtual int switchNamespace(Node *);
+
+ /**
+ * Invoked at the beginning of the classHandler.
+ */
+ virtual int enterClass(Node *);
+
+ /**
+ * Invoked at the end of the classHandler.
+ */
+ virtual int exitClass(Node *) {
+ return SWIG_OK;
+ };
+
+ /**
+ * Invoked at the beginning of the variableHandler.
+ */
+ virtual int enterVariable(Node *);
+
+ /**
+ * Invoked at the end of the variableHandler.
+ */
+ virtual int exitVariable(Node *) {
+ return SWIG_OK;
+ };
+
+ /**
+ * Invoked at the beginning of the functionHandler.
+ */
+ virtual int enterFunction(Node *);
+
+ /**
+ * Invoked at the end of the functionHandler.
+ */
+ virtual int exitFunction(Node *) {
+ return SWIG_OK;
+ };
+
+ /**
+ * Invoked by functionWrapper callback after call to Language::functionWrapper.
+ */
+ virtual int emitWrapperFunction(Node *n);
+
+ /**
+ * Invoked by nativeWrapper callback
+ */
+ virtual int emitNativeFunction(Node *n);
+
+ /**
+ * Invoked from constantWrapper after call to Language::constantWrapper.
+ **/
+ virtual int emitConstant(Node *n);
+
+ /**
+ * Registers a given code snippet for a given key name.
+ *
+ * This method is called by the fragmentDirective handler
+ * of the JAVASCRIPT language module.
+ **/
+ int registerTemplate(const String *name, const String *code);
+
+ /**
+ * Retrieve the code template registered for a given name.
+ */
+ Template getTemplate(const String *name);
+
+ State & getState();
+
+protected:
+
+ /**
+ * Generates code for a constructor function.
+ */
+ virtual int emitCtor(Node *n);
+
+ /**
+ * Generates code for a destructor function.
+ */
+ virtual int emitDtor(Node *n);
+
+ /**
+ * Generates code for a function.
+ */
+ virtual int emitFunction(Node *n, bool is_member, bool is_static);
+
+ virtual int emitFunctionDispatcher(Node *n, bool /*is_member */ );
+
+ /**
+ * Generates code for a getter function.
+ */
+ virtual int emitGetter(Node *n, bool is_member, bool is_static);
+
+ /**
+ * Generates code for a setter function.
+ */
+ virtual int emitSetter(Node *n, bool is_member, bool is_static);
+
+ virtual void marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static) = 0;
+
+ virtual String *emitInputTypemap(Node *n, Parm *params, Wrapper *wrapper, String *arg);
+
+ virtual void marshalOutput(Node *n, ParmList *params, Wrapper *wrapper, String *actioncode, const String *cresult = 0, bool emitReturnVariable = true);
+
+ virtual void emitCleanupCode(Node *n, Wrapper *wrapper, ParmList *params);
+
+ /**
+ * Helper function to retrieve the first parent class node.
+ */
+ Node *getBaseClass(Node *n);
+
+ Parm *skipIgnoredArgs(Parm *p);
+
+ virtual int createNamespace(String *scope);
+
+ virtual Hash *createNamespaceEntry(const char *name, const char *parent, const char *parent_mangled);
+
+ virtual int emitNamespaces() = 0;
+
+
+protected:
+
+ JSEngine engine;
+ Hash *templates;
+ State state;
+
+ // contains context specific data (DOHs)
+ // to allow generation of namespace related code
+ // which are switched on namespace change
+ Hash *namespaces;
+ Hash *current_namespace;
+ String *defaultResultName;
+ File *f_wrappers;
+};
+
+/* factory methods for concrete JSEmitters: */
+
+JSEmitter *swig_javascript_create_JSCEmitter();
+JSEmitter *swig_javascript_create_V8Emitter();
+JSEmitter *swig_javascript_create_NodeJSEmitter();
+
+/**********************************************************************
+ * JAVASCRIPT: SWIG module implementation
+ **********************************************************************/
+
+class JAVASCRIPT:public Language {
+
+public:
+
+ JAVASCRIPT():emitter(NULL) {
+ }
+ ~JAVASCRIPT() {
+ delete emitter;
+ }
+
+ virtual int functionHandler(Node *n);
+ virtual int globalfunctionHandler(Node *n);
+ virtual int variableHandler(Node *n);
+ virtual int globalvariableHandler(Node *n);
+ virtual int staticmemberfunctionHandler(Node *n);
+ virtual int classHandler(Node *n);
+ virtual int functionWrapper(Node *n);
+ virtual int constantWrapper(Node *n);
+ virtual int nativeWrapper(Node *n);
+ virtual void main(int argc, char *argv[]);
+ virtual int top(Node *n);
+
+ /**
+ * Registers all %fragments assigned to section "templates".
+ **/
+ virtual int fragmentDirective(Node *n);
+
+public:
+
+ virtual String *getNSpace() const;
+
+private:
+
+ JSEmitter *emitter;
+};
+
+/* ---------------------------------------------------------------------
+ * functionWrapper()
+ *
+ * Low level code generator for functions
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::functionWrapper(Node *n) {
+
+ // note: the default implementation only prints a message
+ // Language::functionWrapper(n);
+ emitter->emitWrapperFunction(n);
+
+ return SWIG_OK;
+}
+
+/* ---------------------------------------------------------------------
+ * functionHandler()
+ *
+ * Function handler for generating wrappers for functions
+ * --------------------------------------------------------------------- */
+int JAVASCRIPT::functionHandler(Node *n) {
+
+ if (GetFlag(n, "isextension") == 1) {
+ SetFlag(n, "ismember");
+ }
+
+ emitter->enterFunction(n);
+ Language::functionHandler(n);
+ emitter->exitFunction(n);
+
+ return SWIG_OK;
+}
+
+/* ---------------------------------------------------------------------
+ * globalfunctionHandler()
+ *
+ * Function handler for generating wrappers for functions
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::globalfunctionHandler(Node *n) {
+ emitter->switchNamespace(n);
+ Language::globalfunctionHandler(n);
+
+ return SWIG_OK;
+}
+
+/* ---------------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ *
+ * Function handler for generating wrappers for static member functions
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::staticmemberfunctionHandler(Node *n) {
+ /*
+ * Note: storage=static is removed by Language::staticmemberfunctionHandler.
+ * So, don't rely on that after here. Instead use the state variable which is
+ * set by JSEmitter::enterFunction().
+ */
+ Language::staticmemberfunctionHandler(n);
+ return SWIG_OK;
+}
+
+/* ---------------------------------------------------------------------
+ * variableHandler()
+ *
+ * Function handler for generating wrappers for variables
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::variableHandler(Node *n) {
+
+ emitter->enterVariable(n);
+ Language::variableHandler(n);
+ emitter->exitVariable(n);
+
+ return SWIG_OK;
+}
+
+/* ---------------------------------------------------------------------
+ * globalvariableHandler()
+ *
+ * Function handler for generating wrappers for global variables
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::globalvariableHandler(Node *n) {
+ emitter->switchNamespace(n);
+ Language::globalvariableHandler(n);
+
+ return SWIG_OK;
+}
+
+/* ---------------------------------------------------------------------
+ * constantHandler()
+ *
+ * Function handler for generating wrappers for constants
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::constantWrapper(Node *n) {
+ emitter->switchNamespace(n);
+
+ // Note: callbacks trigger this wrapper handler
+ // TODO: handle callback declarations
+ if (Equal(Getattr(n, "kind"), "function")) {
+ return SWIG_OK;
+ }
+ // TODO: the emitter for constants must be implemented in a cleaner way
+ // currently we treat it like a read-only variable
+ // however, there is a remaining bug with function pointer constants
+ // which could be fixed with a cleaner approach
+ emitter->emitConstant(n);
+
+ return SWIG_OK;
+}
+
+/* ---------------------------------------------------------------------
+ * nativeWrapper()
+ *
+ * Function wrapper for generating placeholders for native functions
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::nativeWrapper(Node *n) {
+ emitter->emitNativeFunction(n);
+
+ return SWIG_OK;
+}
+
+/* ---------------------------------------------------------------------
+ * classHandler()
+ *
+ * Function handler for generating wrappers for class
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::classHandler(Node *n) {
+ emitter->switchNamespace(n);
+
+ emitter->enterClass(n);
+ Language::classHandler(n);
+ emitter->exitClass(n);
+
+ return SWIG_OK;
+}
+
+int JAVASCRIPT::fragmentDirective(Node *n) {
+
+ // catch all fragment directives that have "templates" as location
+ // and register them at the emitter.
+ String *section = Getattr(n, "section");
+
+ if (Equal(section, "templates") && !ImportMode) {
+ emitter->registerTemplate(Getattr(n, "value"), Getattr(n, "code"));
+ } else {
+ return Language::fragmentDirective(n);
+ }
+
+ return SWIG_OK;
+}
+
+String *JAVASCRIPT::getNSpace() const {
+ return Language::getNSpace();
+}
+
+/* ---------------------------------------------------------------------
+ * top()
+ *
+ * Function handler for processing top node of the parse tree
+ * Wrapper code generation essentially starts from here
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::top(Node *n) {
+ emitter->initialize(n);
+
+ Language::top(n);
+
+ emitter->dump(n);
+ emitter->close();
+
+ return SWIG_OK;
+}
+
+static const char *usage = (char *) "\
+Javascript Options (available with -javascript)\n\
+ -jsc - creates a JavascriptCore extension \n\
+ -v8 - creates a v8 extension \n\
+ -node - creates a node.js extension \n\
+ -debug-codetemplates - generates information about the origin of code templates\n";
+
+
+/* ---------------------------------------------------------------------
+ * main()
+ *
+ * Entry point for the JAVASCRIPT module
+ * --------------------------------------------------------------------- */
+
+void JAVASCRIPT::main(int argc, char *argv[]) {
+ // Set javascript subdirectory in SWIG library
+ SWIG_library_directory("javascript");
+
+ int engine = -1;
+
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-v8") == 0) {
+ if (engine != -1) {
+ Printf(stderr, ERR_MSG_ONLY_ONE_ENGINE_PLEASE);
+ SWIG_exit(-1);
+ }
+ Swig_mark_arg(i);
+ engine = JSEmitter::V8;
+ } else if (strcmp(argv[i], "-jsc") == 0) {
+ if (engine != -1) {
+ Printf(stderr, ERR_MSG_ONLY_ONE_ENGINE_PLEASE);
+ SWIG_exit(-1);
+ }
+ Swig_mark_arg(i);
+ engine = JSEmitter::JavascriptCore;
+ } else if (strcmp(argv[i], "-node") == 0) {
+ if (engine != -1) {
+ Printf(stderr, ERR_MSG_ONLY_ONE_ENGINE_PLEASE);
+ SWIG_exit(-1);
+ }
+ Swig_mark_arg(i);
+ engine = JSEmitter::NodeJS;
+ } else if (strcmp(argv[i], "-debug-codetemplates") == 0) {
+ Swig_mark_arg(i);
+ js_template_enable_debug = true;
+ } else if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ return;
+ }
+ }
+ }
+
+ switch (engine) {
+ case JSEmitter::V8:
+ {
+ emitter = swig_javascript_create_V8Emitter();
+ Preprocessor_define("SWIG_JAVASCRIPT_V8 1", 0);
+ SWIG_library_directory("javascript/v8");
+ // V8 API is C++, so output must be C++ compatible even when wrapping C code
+ if (!cparse_cplusplus) {
+ Swig_cparse_cplusplusout(1);
+ }
+ break;
+ }
+ case JSEmitter::JavascriptCore:
+ {
+ emitter = swig_javascript_create_JSCEmitter();
+ Preprocessor_define("SWIG_JAVASCRIPT_JSC 1", 0);
+ SWIG_library_directory("javascript/jsc");
+ break;
+ }
+ case JSEmitter::NodeJS:
+ {
+ emitter = swig_javascript_create_V8Emitter();
+ Preprocessor_define("SWIG_JAVASCRIPT_V8 1", 0);
+ Preprocessor_define("BUILDING_NODE_EXTENSION 1", 0);
+ SWIG_library_directory("javascript/v8");
+ break;
+ }
+ default:
+ {
+ Printf(stderr, "SWIG Javascript: Unknown engine. Please specify one of '-jsc', '-v8' or '-node'.\n");
+ SWIG_exit(-1);
+ break;
+ }
+ }
+
+ // Add a symbol to the parser for conditional compilation
+ Preprocessor_define("SWIGJAVASCRIPT 1", 0);
+
+ // Add typemap definitions
+ SWIG_typemap_lang("javascript");
+
+ // Set configuration file
+ SWIG_config_file("javascript.swg");
+
+ allow_overloading();
+}
+
+/* -----------------------------------------------------------------------------
+ * swig_javascript() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_javascript() {
+ return new JAVASCRIPT();
+}
+
+extern "C" Language *swig_javascript(void) {
+ return new_swig_javascript();
+}
+
+/**********************************************************************
+ * Emitter implementations
+ **********************************************************************/
+
+/* -----------------------------------------------------------------------------
+ * JSEmitter()
+ * ----------------------------------------------------------------------------- */
+
+JSEmitter::JSEmitter(JSEmitter::JSEngine engine)
+: engine(engine), templates(NewHash()), namespaces(NULL), current_namespace(NULL), defaultResultName(NewString("result")), f_wrappers(NULL) {
+}
+
+/* -----------------------------------------------------------------------------
+ * ~JSEmitter()
+ * ----------------------------------------------------------------------------- */
+
+JSEmitter::~JSEmitter() {
+ Delete(templates);
+}
+
+/* -----------------------------------------------------------------------------
+ * JSEmitter::RegisterTemplate() : Registers a code template
+ *
+ * Note: this is used only by JAVASCRIPT::fragmentDirective().
+ * ----------------------------------------------------------------------------- */
+
+int JSEmitter::registerTemplate(const String *name, const String *code) {
+ if (!State::IsSet(state.globals(HAS_TEMPLATES))) {
+ SetFlag(state.globals(), HAS_TEMPLATES);
+ }
+ return Setattr(templates, name, code);
+}
+
+/* -----------------------------------------------------------------------------
+ * JSEmitter::getTemplate() : Provides a registered code template
+ * ----------------------------------------------------------------------------- */
+
+Template JSEmitter::getTemplate(const String *name) {
+ String *templ = Getattr(templates, name);
+
+ if (!templ) {
+ Printf(stderr, "Could not find template %s\n.", name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ Template t(templ, name);
+ return t;
+}
+
+JSEmitterState & JSEmitter::getState() {
+ return state;
+}
+
+int JSEmitter::initialize(Node * /*n */ ) {
+
+ if (namespaces != NULL) {
+ Delete(namespaces);
+ }
+ namespaces = NewHash();
+ Hash *global_namespace = createNamespaceEntry("exports", 0, 0);
+
+ Setattr(namespaces, "::", global_namespace);
+ current_namespace = global_namespace;
+
+ f_wrappers = NewString("");
+
+ return SWIG_OK;
+}
+
+/* ---------------------------------------------------------------------
+ * skipIgnoredArgs()
+ * --------------------------------------------------------------------- */
+
+Parm *JSEmitter::skipIgnoredArgs(Parm *p) {
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+ return p;
+}
+
+/* -----------------------------------------------------------------------------
+ * JSEmitter::getBaseClass() : the node of the base class or NULL
+ *
+ * Note: the first base class is provided. Multiple inheritance is not
+ * supported.
+ * ----------------------------------------------------------------------------- */
+
+Node *JSEmitter::getBaseClass(Node *n) {
+ // retrieve the first base class that is not %ignored
+ List *baselist = Getattr(n, "bases");
+ if (baselist) {
+ Iterator base = First(baselist);
+ while (base.item && GetFlag(base.item, "feature:ignore")) {
+ base = Next(base);
+ }
+ return base.item;
+ }
+ return NULL;
+}
+
+ /* -----------------------------------------------------------------------------
+ * JSEmitter::emitWrapperFunction() : dispatches emitter functions.
+ *
+ * This allows to have small sized, dedicated emitting functions.
+ * All state dependent branching is done here.
+ * ----------------------------------------------------------------------------- */
+
+int JSEmitter::emitWrapperFunction(Node *n) {
+ int ret = SWIG_OK;
+
+ String *kind = Getattr(n, "kind");
+
+ if (kind) {
+
+ if (Equal(kind, "function")
+ // HACK: sneaky.ctest revealed that typedef'd (global) functions must be
+ // detected via the 'view' attribute.
+ || (Equal(kind, "variable") && Equal(Getattr(n, "view"), "globalfunctionHandler"))
+ ) {
+ bool is_member = GetFlag(n, "ismember") != 0 || GetFlag(n, "feature:extend") != 0;
+ bool is_static = GetFlag(state.function(), IS_STATIC) != 0;
+ ret = emitFunction(n, is_member, is_static);
+ } else if (Cmp(kind, "variable") == 0) {
+ bool is_static = GetFlag(state.variable(), IS_STATIC) != 0;
+ // HACK: smartpointeraccessed static variables are not treated as statics
+ if (GetFlag(n, "allocate:smartpointeraccess")) {
+ is_static = false;
+ }
+
+ bool is_member = GetFlag(n, "ismember") != 0;
+ bool is_setter = GetFlag(n, "memberset") != 0 || GetFlag(n, "varset") != 0;
+ bool is_getter = GetFlag(n, "memberget") != 0 || GetFlag(n, "varget") != 0;
+ if (is_setter) {
+ ret = emitSetter(n, is_member, is_static);
+ } else if (is_getter) {
+ ret = emitGetter(n, is_member, is_static);
+ } else {
+ Swig_print_node(n);
+ }
+
+ } else {
+ Printf(stderr, "Warning: unsupported wrapper function type\n");
+ Swig_print_node(n);
+ ret = SWIG_ERROR;
+ }
+ } else {
+ String *view = Getattr(n, "view");
+
+ if (Cmp(view, "constructorHandler") == 0) {
+ ret = emitCtor(n);
+ } else if (Cmp(view, "destructorHandler") == 0) {
+ ret = emitDtor(n);
+ } else {
+ Printf(stderr, "Warning: unsupported wrapper function type");
+ Swig_print_node(n);
+ ret = SWIG_ERROR;
+ }
+ }
+
+ return ret;
+}
+
+int JSEmitter::emitNativeFunction(Node *n) {
+ String *wrapname = Getattr(n, "wrap:name");
+ enterFunction(n);
+ state.function(WRAPPER_NAME, wrapname);
+ exitFunction(n);
+ return SWIG_OK;
+}
+
+int JSEmitter::enterClass(Node *n) {
+ state.clazz(RESET);
+ state.clazz(NAME, Getattr(n, "sym:name"));
+ state.clazz("nspace", current_namespace);
+
+ // Creating a mangled name using the current namespace and the symbol name
+ String *mangled_name = NewString("");
+ Printf(mangled_name, "%s_%s", Getattr(current_namespace, NAME_MANGLED), Getattr(n, "sym:name"));
+ state.clazz(NAME_MANGLED, SwigType_manglestr(mangled_name));
+ Delete(mangled_name);
+
+ state.clazz(TYPE, NewString(Getattr(n, "classtype")));
+
+ String *type = SwigType_manglestr(Getattr(n, "classtypeobj"));
+ String *classtype_mangled = NewString("");
+ Printf(classtype_mangled, "p%s", type);
+ state.clazz(TYPE_MANGLED, classtype_mangled);
+ Delete(type);
+
+ String *ctor_wrapper = NewString("_wrap_new_veto_");
+ Append(ctor_wrapper, state.clazz(NAME));
+ state.clazz(CTOR, ctor_wrapper);
+ state.clazz(CTOR_DISPATCHERS, NewString(""));
+ state.clazz(DTOR, NewString("0"));
+
+ // HACK: assume that a class is abstract
+ // this is resolved by emitCtor (which is only called for non abstract classes)
+ SetFlag(state.clazz(), IS_ABSTRACT);
+
+ return SWIG_OK;
+}
+
+int JSEmitter::enterFunction(Node *n) {
+ state.function(RESET);
+ state.function(NAME, Getattr(n, "sym:name"));
+ if (Equal(Getattr(n, "storage"), "static")) {
+ SetFlag(state.function(), IS_STATIC);
+ }
+ return SWIG_OK;
+}
+
+int JSEmitter::enterVariable(Node *n) {
+ // reset the state information for variables.
+ state.variable(RESET);
+
+ // Retrieve a pure symbol name. Using 'sym:name' as a basis, as it considers %renamings.
+ if (Equal(Getattr(n, "view"), "memberconstantHandler")) {
+ // Note: this is kind of hacky/experimental
+ // For constants/enums 'sym:name' contains e.g., 'Foo_Hello' instead of 'Hello'
+ state.variable(NAME, Getattr(n, "memberconstantHandler:sym:name"));
+ } else {
+ state.variable(NAME, Swig_scopename_last(Getattr(n, "sym:name")));
+ }
+
+ if (Equal(Getattr(n, "storage"), "static")) {
+ SetFlag(state.variable(), IS_STATIC);
+ }
+
+ if (!Language::instance()->is_assignable(n)) {
+ SetFlag(state.variable(), IS_IMMUTABLE);
+ }
+ // FIXME: test "arrays_global" does not compile with that as it is not allowed to assign to char[]
+ if (Equal(Getattr(n, "type"), "a().char")) {
+ SetFlag(state.variable(), IS_IMMUTABLE);
+ }
+
+ return SWIG_OK;
+}
+
+int JSEmitter::emitCtor(Node *n) {
+
+ Wrapper *wrapper = NewWrapper();
+
+ bool is_overloaded = GetFlag(n, "sym:overloaded") != 0;
+
+ Template t_ctor(getTemplate("js_ctor"));
+
+ String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
+ if (is_overloaded) {
+ t_ctor = getTemplate("js_overloaded_ctor");
+ Append(wrap_name, Getattr(n, "sym:overname"));
+ }
+ Setattr(n, "wrap:name", wrap_name);
+ // note: we can remove the is_abstract flag now, as this
+ // is called for non-abstract classes only.
+ Setattr(state.clazz(), IS_ABSTRACT, 0);
+
+ ParmList *params = Getattr(n, "parms");
+ emit_parameter_variables(params, wrapper);
+ emit_attach_parmmaps(params, wrapper);
+ // HACK: in test-case `ignore_parameter` emit_attach_parmmaps generated an extra line of applied typemaps.
+ // Deleting wrapper->code here, to reset, and as it seemed to have no side effect elsewhere
+ Delete(wrapper->code);
+ wrapper->code = NewString("");
+
+ Printf(wrapper->locals, "%sresult;", SwigType_str(Getattr(n, "type"), 0));
+
+ marshalInputArgs(n, params, wrapper, Ctor, true, false);
+ String *action = emit_action(n);
+ Printv(wrapper->code, action, "\n", 0);
+
+ emitCleanupCode(n, wrapper, params);
+
+ t_ctor.replace("$jswrapper", wrap_name)
+ .replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
+ .replace("$jslocals", wrapper->locals)
+ .replace("$jscode", wrapper->code)
+ .replace("$jsargcount", Getattr(n, ARGCOUNT))
+ .pretty_print(f_wrappers);
+
+ Template t_ctor_case(getTemplate("js_ctor_dispatch_case"));
+ t_ctor_case.replace("$jswrapper", wrap_name)
+ .replace("$jsargcount", Getattr(n, ARGCOUNT));
+ Append(state.clazz(CTOR_DISPATCHERS), t_ctor_case.str());
+
+ DelWrapper(wrapper);
+
+ // create a dispatching ctor
+ if (is_overloaded) {
+ if (!Getattr(n, "sym:nextSibling")) {
+ String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
+ Template t_mainctor(getTemplate("js_ctor_dispatcher"));
+ t_mainctor.replace("$jswrapper", wrap_name)
+ .replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsdispatchcases", state.clazz(CTOR_DISPATCHERS))
+ .pretty_print(f_wrappers);
+ state.clazz(CTOR, wrap_name);
+ }
+ } else {
+ state.clazz(CTOR, wrap_name);
+ }
+
+ return SWIG_OK;
+}
+
+int JSEmitter::emitDtor(Node *n) {
+
+ String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
+
+ SwigType *type = state.clazz(TYPE);
+ String *p_classtype = SwigType_add_pointer(state.clazz(TYPE));
+ String *ctype = SwigType_lstr(p_classtype, "");
+ String *free = NewString("");
+
+ // (Taken from JSCore implementation.)
+ /* The if (Extend) block was taken from the Ruby implementation.
+ * The problem is that in the case of an %extend to create a destructor for a struct to coordinate automatic memory cleanup with the Javascript collector,
+ * the SWIG function was not being generated. More specifically:
+ struct MyData {
+ %extend {
+ ~MyData() {
+ FreeData($self);
+ }
+ }
+ };
+ %newobject CreateData;
+ struct MyData* CreateData(void);
+ %delobject FreeData;
+ void FreeData(struct MyData* the_data);
+
+ where the use case is something like:
+ var my_data = example.CreateData();
+ my_data = null;
+
+ This function was not being generated:
+ SWIGINTERN void delete_MyData(struct MyData *self){
+ FreeData(self);
+ }
+
+ I don't understand fully why it wasn't being generated. It just seems to happen in the Lua generator.
+ There is a comment about staticmemberfunctionHandler having an inconsistency and I tracked down dome of the SWIGINTERN void delete_*
+ code to that function in the Language base class.
+ The Ruby implementation seems to have an explicit check for if(Extend) and explicitly generates the code, so that's what I'm doing here.
+ The Ruby implementation does other stuff which I omit.
+ */
+ if (Extend) {
+ String *wrap = Getattr(n, "wrap:code");
+ if (wrap) {
+ Printv(f_wrappers, wrap, NIL);
+ }
+ }
+ // HACK: this is only for the v8 emitter. maybe set an attribute wrap:action of node
+ // TODO: generate dtors more similar to other wrappers
+ // EW: I think this is wrong. delete should only be used when new was used to create. If malloc was used, free needs to be used.
+ if (SwigType_isarray(type)) {
+ Printf(free, "delete [] (%s)", ctype);
+ } else {
+ Printf(free, "delete (%s)", ctype);
+ }
+
+ String *destructor_action = Getattr(n, "wrap:action");
+ // Adapted from the JSCore implementation.
+ /* The next challenge is to generate the correct finalize function for JavaScriptCore to call.
+ Originally, it would use this fragment from javascriptcode.swg
+ %fragment ("JS_destructordefn", "templates")
+ %{
+ void _wrap_${classname_mangled}_finalize(JSObjectRef thisObject)
+ {
+ SWIG_PRV_DATA* t = (SWIG_PRV_DATA*)JSObjectGetPrivate(thisObject);
+ if(t && t->swigCMemOwn) free ((${type}*)t->swigCObject);
+ if(t) free(t);
+ }
+ %}
+
+ But for the above example case of %extend to define a destructor on a struct, we need to override the system to not call
+ free ((${type}*)t->swigCObject);
+ and substitute it with what the user has provided.
+ To solve this, I created a variation fragment called JS_destructoroverridedefn:
+ SWIG_PRV_DATA* t = (SWIG_PRV_DATA*)JSObjectGetPrivate(thisObject);
+ if(t && t->swigCMemOwn) {
+ ${type}* arg1 = (${type}*)t->swigCObject;
+ ${destructor_action}
+ }
+ if(t) free(t);
+
+ Based on what I saw in the Lua and Ruby modules, I use Getattr(n, "wrap:action")
+ to decide if the user has a preferred destructor action.
+ Based on that, I decide which fragment to use.
+ And in the case of the custom action, I substitute that action in.
+ I noticed that destructor_action has the form
+ delete_MyData(arg1);
+ The explicit arg1 is a little funny, so I structured the fragment to create a temporary variable called arg1 to make the generation easier.
+ This might suggest this solution misunderstands a more complex case.
+
+ Also, there is a problem where destructor_action is always true for me, even when not requesting %extend as above.
+ So this code doesn't actually quite work as I expect. The end result is that the code still works because
+ destructor_action calls free like the original template. The one caveat is the string in destructor_action casts to char* which is weird.
+ I think there is a deeper underlying SWIG issue because I don't think it should be char*. However, it doesn't really matter for free.
+
+ Maybe the fix for the destructor_action always true problem is that this is supposed to be embedded in the if(Extend) block above.
+ But I don't fully understand the conditions of any of these things, and since it works for the moment, I don't want to break more stuff.
+ */
+ if (destructor_action) {
+ Template t_dtor = getTemplate("js_dtoroverride");
+ state.clazz(DTOR, wrap_name);
+ t_dtor.replace("${classname_mangled}", state.clazz(NAME_MANGLED))
+ .replace("$jswrapper", wrap_name)
+ .replace("$jsfree", free)
+ .replace("$jstype", ctype);
+
+ t_dtor.replace("${destructor_action}", destructor_action);
+ Wrapper_pretty_print(t_dtor.str(), f_wrappers);
+ } else {
+ Template t_dtor = getTemplate("js_dtor");
+ state.clazz(DTOR, wrap_name);
+ t_dtor.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jswrapper", wrap_name)
+ .replace("$jsfree", free)
+ .replace("$jstype", ctype)
+ .pretty_print(f_wrappers);
+ }
+
+ Delete(p_classtype);
+ Delete(ctype);
+ Delete(free);
+
+ return SWIG_OK;
+}
+
+int JSEmitter::emitGetter(Node *n, bool is_member, bool is_static) {
+ Wrapper *wrapper = NewWrapper();
+ Template t_getter(getTemplate("js_getter"));
+
+ // prepare wrapper name
+ String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
+ Setattr(n, "wrap:name", wrap_name);
+ state.variable(GETTER, wrap_name);
+
+ // prepare local variables
+ ParmList *params = Getattr(n, "parms");
+ emit_parameter_variables(params, wrapper);
+ emit_attach_parmmaps(params, wrapper);
+
+ // prepare code part
+ String *action = emit_action(n);
+ marshalInputArgs(n, params, wrapper, Getter, is_member, is_static);
+ marshalOutput(n, params, wrapper, action);
+
+ emitCleanupCode(n, wrapper, params);
+
+ t_getter.replace("$jswrapper", wrap_name)
+ .replace("$jslocals", wrapper->locals)
+ .replace("$jscode", wrapper->code)
+ .pretty_print(f_wrappers);
+
+ DelWrapper(wrapper);
+
+ return SWIG_OK;
+}
+
+int JSEmitter::emitSetter(Node *n, bool is_member, bool is_static) {
+
+ // skip variables that are immutable
+ if (State::IsSet(state.variable(IS_IMMUTABLE))) {
+ return SWIG_OK;
+ }
+
+ Wrapper *wrapper = NewWrapper();
+
+ Template t_setter(getTemplate("js_setter"));
+
+ // prepare wrapper name
+ String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
+ Setattr(n, "wrap:name", wrap_name);
+ state.variable(SETTER, wrap_name);
+
+ // prepare local variables
+ ParmList *params = Getattr(n, "parms");
+ emit_parameter_variables(params, wrapper);
+ emit_attach_parmmaps(params, wrapper);
+
+ // prepare code part
+ String *action = emit_action(n);
+ marshalInputArgs(n, params, wrapper, Setter, is_member, is_static);
+ Append(wrapper->code, action);
+
+ emitCleanupCode(n, wrapper, params);
+
+ t_setter.replace("$jswrapper", wrap_name)
+ .replace("$jslocals", wrapper->locals)
+ .replace("$jscode", wrapper->code)
+ .pretty_print(f_wrappers);
+
+ DelWrapper(wrapper);
+
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * JSEmitter::emitConstant() : triggers code generation for constants
+ * ----------------------------------------------------------------------------- */
+
+int JSEmitter::emitConstant(Node *n) {
+ // HACK: somehow it happened under Mac OS X that before everything started
+ // a lot of SWIG internal constants were emitted
+ // This didn't happen on other platforms yet...
+ // we ignore those premature definitions
+ if (!State::IsSet(state.globals(HAS_TEMPLATES))) {
+ return SWIG_ERROR;
+ }
+
+ Wrapper *wrapper = NewWrapper();
+ SwigType *type = Getattr(n, "type");
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ String *wname = Swig_name_wrapper(name);
+ String *rawval = Getattr(n, "rawval");
+ String *value = rawval ? rawval : Getattr(n, "value");
+
+ // HACK: forcing usage of cppvalue for v8 (which turned out to fix typdef_struct.i, et. al)
+ if (State::IsSet(state.globals(FORCE_CPP)) && Getattr(n, "cppvalue") != NULL) {
+ value = Getattr(n, "cppvalue");
+ }
+
+ Template t_getter(getTemplate("js_getter"));
+
+ // call the variable methods as a constants are
+ // registered in same way
+ enterVariable(n);
+ state.variable(GETTER, wname);
+ // TODO: why do we need this?
+ Setattr(n, "wrap:name", wname);
+
+ // special treatment of member pointers
+ if (SwigType_type(type) == T_MPOINTER) {
+ // TODO: this could go into a code-template
+ String *mpointer_wname = NewString("");
+ Printf(mpointer_wname, "_wrapConstant_%s", iname);
+ Setattr(n, "memberpointer:constant:wrap:name", mpointer_wname);
+ String *str = SwigType_str(type, mpointer_wname);
+ Printf(f_wrappers, "static %s = %s;\n", str, value);
+ Delete(str);
+ value = mpointer_wname;
+ }
+
+ marshalOutput(n, 0, wrapper, NewString(""), value, false);
+
+ t_getter.replace("$jswrapper", wname)
+ .replace("$jslocals", wrapper->locals)
+ .replace("$jscode", wrapper->code)
+ .pretty_print(f_wrappers);
+
+ exitVariable(n);
+
+ DelWrapper(wrapper);
+
+ return SWIG_OK;
+}
+
+int JSEmitter::emitFunction(Node *n, bool is_member, bool is_static) {
+ Wrapper *wrapper = NewWrapper();
+ Template t_function(getTemplate("js_function"));
+
+ bool is_overloaded = GetFlag(n, "sym:overloaded") != 0;
+
+ // prepare the function wrapper name
+ String *iname = Getattr(n, "sym:name");
+ String *wrap_name = Swig_name_wrapper(iname);
+ if (is_overloaded) {
+ t_function = getTemplate("js_overloaded_function");
+ Append(wrap_name, Getattr(n, "sym:overname"));
+ }
+ Setattr(n, "wrap:name", wrap_name);
+ state.function(WRAPPER_NAME, wrap_name);
+
+ // prepare local variables
+ ParmList *params = Getattr(n, "parms");
+ emit_parameter_variables(params, wrapper);
+ emit_attach_parmmaps(params, wrapper);
+
+ // HACK: in test-case `ignore_parameter` emit_attach_parmmaps generates an extra line of applied typemap.
+ // Deleting wrapper->code here fixes the problem, and seems to have no side effect elsewhere
+ Delete(wrapper->code);
+ wrapper->code = NewString("");
+
+ marshalInputArgs(n, params, wrapper, Function, is_member, is_static);
+ String *action = emit_action(n);
+ marshalOutput(n, params, wrapper, action);
+ emitCleanupCode(n, wrapper, params);
+ Replaceall(wrapper->code, "$symname", iname);
+
+ t_function.replace("$jswrapper", wrap_name)
+ .replace("$jslocals", wrapper->locals)
+ .replace("$jscode", wrapper->code)
+ .replace("$jsargcount", Getattr(n, ARGCOUNT))
+ .pretty_print(f_wrappers);
+
+
+ DelWrapper(wrapper);
+
+ return SWIG_OK;
+}
+
+int JSEmitter::emitFunctionDispatcher(Node *n, bool /*is_member */ ) {
+ Wrapper *wrapper = NewWrapper();
+
+ // Generate call list, go to first node
+ Node *sibl = n;
+
+ while (Getattr(sibl, "sym:previousSibling"))
+ sibl = Getattr(sibl, "sym:previousSibling"); // go all the way up
+
+ do {
+ String *siblname = Getattr(sibl, "wrap:name");
+
+ if (siblname) {
+ // handle function overloading
+ Template t_dispatch_case = getTemplate("js_function_dispatch_case");
+ t_dispatch_case.replace("$jswrapper", siblname)
+ .replace("$jsargcount", Getattr(sibl, ARGCOUNT));
+
+ Append(wrapper->code, t_dispatch_case.str());
+ }
+
+ } while ((sibl = Getattr(sibl, "sym:nextSibling")));
+
+ Template t_function(getTemplate("js_function_dispatcher"));
+
+ // Note: this dispatcher function gets called after the last overloaded function has been created.
+ // At this time, n.wrap:name contains the name of the last wrapper function.
+ // To get a valid function name for the dispatcher function we take the last wrapper name and
+ // substract the extension "sym:overname",
+ String *wrap_name = NewString(Getattr(n, "wrap:name"));
+ String *overname = Getattr(n, "sym:overname");
+
+ Node *methodclass = Swig_methodclass(n);
+ String *class_name = Getattr(methodclass, "sym:name");
+
+ int l1 = Len(wrap_name);
+ int l2 = Len(overname);
+ Delslice(wrap_name, l1 - l2, l1);
+
+ String *new_string = NewStringf("%s_%s", class_name, wrap_name);
+ String *final_wrap_name = Swig_name_wrapper(new_string);
+
+ Setattr(n, "wrap:name", final_wrap_name);
+ state.function(WRAPPER_NAME, final_wrap_name);
+
+
+
+ t_function.replace("$jslocals", wrapper->locals)
+ .replace("$jscode", wrapper->code);
+
+ // call this here, to replace all variables
+ t_function.replace("$jswrapper", final_wrap_name)
+ .replace("$jsname", state.function(NAME))
+ .pretty_print(f_wrappers);
+
+ // Delete the state variable
+ DelWrapper(wrapper);
+
+ return SWIG_OK;
+}
+
+String *JSEmitter::emitInputTypemap(Node *n, Parm *p, Wrapper *wrapper, String *arg) {
+ // Get input typemap for current param
+ String *tm = Getattr(p, "tmap:in");
+ SwigType *type = Getattr(p, "type");
+
+ if (tm != NULL) {
+ Replaceall(tm, "$input", arg);
+ Setattr(p, "emit:input", arg);
+ // do replacements for built-in variables
+ if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+ Replaceall(tm, "$symname", Getattr(n, "sym:name"));
+ Printf(wrapper->code, "%s\n", tm);
+ } 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));
+ }
+
+ return tm;
+}
+
+void JSEmitter::marshalOutput(Node *n, ParmList *params, Wrapper *wrapper, String *actioncode, const String *cresult, bool emitReturnVariable) {
+ SwigType *type = Getattr(n, "type");
+ String *tm;
+ Parm *p;
+
+ // adds a declaration for the result variable
+ if (emitReturnVariable)
+ emit_return_variable(n, type, wrapper);
+ // if not given, use default result identifier ('result') for output typemap
+ if (cresult == 0)
+ cresult = defaultResultName;
+
+ tm = Swig_typemap_lookup_out("out", n, cresult, wrapper, actioncode);
+ bool should_own = GetFlag(n, "feature:new") != 0;
+
+ if (tm) {
+ Replaceall(tm, "$objecttype", Swig_scopename_last(SwigType_str(SwigType_strip_qualifiers(type), 0)));
+
+ if (should_own) {
+ Replaceall(tm, "$owner", "SWIG_POINTER_OWN");
+ } else {
+ Replaceall(tm, "$owner", "0");
+ }
+ Append(wrapper->code, tm);
+
+ if (Len(tm) > 0) {
+ 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"));
+ }
+
+ if (params) {
+ for (p = params; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(wrapper->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ Replaceall(wrapper->code, "$result", "jsresult");
+}
+
+void JSEmitter::emitCleanupCode(Node *n, Wrapper *wrapper, ParmList *params) {
+ Parm *p;
+ String *tm;
+
+ for (p = params; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ //addThrows(n, "tmap:freearg", p);
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(wrapper->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ if (GetFlag(n, "feature:new")) {
+ tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0);
+ if (tm != NIL) {
+ //addThrows(throws_hash, "newfree", n);
+ Printv(wrapper->code, tm, "\n", NIL);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Printf(wrapper->code, "%s\n", tm);
+ Delete(tm);
+ }
+}
+
+int JSEmitter::switchNamespace(Node *n) {
+ // HACK: somehow this gets called for member functions.
+ // We can safely ignore them, as members are not associated to a namespace (only their class)
+ if (GetFlag(n, "ismember")) {
+ return SWIG_OK;
+ }
+
+ // if nspace is deactivated, everything goes into the global scope
+ if (!GetFlag(n, "feature:nspace")) {
+ current_namespace = Getattr(namespaces, "::");
+ return SWIG_OK;
+ }
+
+// EXPERIMENTAL: we want to use Language::getNSpace() here
+// However, it is not working yet.
+// For namespace functions Language::getNSpace() does not give a valid result
+#if 0
+ JAVASCRIPT *lang = static_cast<JAVASCRIPT*>(Language::instance());
+ String *_nspace = lang->getNSpace();
+ if (!Equal(nspace, _nspace)) {
+ Printf(stdout, "##### Custom vs Language::getNSpace(): %s | %s\n", nspace, _nspace);
+ Swig_print_node(n);
+ }
+#endif
+
+ String *nspace = Getattr(n, "sym:nspace");
+
+ if (nspace == NULL) {
+ // It seems that only classes have 'sym:nspace' set.
+ // We try to get the namespace from the qualified name (i.e., everything before the last '::')
+ nspace = Swig_scopename_prefix(Getattr(n, "name"));
+ }
+
+ // If there is not even a scopename prefix then it must be global scope
+ if (nspace == NULL) {
+ current_namespace = Getattr(namespaces, "::");
+ return SWIG_OK;
+ }
+
+ String *scope = NewString(nspace);
+ // replace "." with "::" that we can use Swig_scopename_last
+ Replaceall(scope, ".", "::");
+
+ // if the scope is not yet registered
+ // create (parent) namespaces recursively
+ if (!Getattr(namespaces, scope)) {
+ createNamespace(scope);
+ }
+ current_namespace = Getattr(namespaces, scope);
+
+ return SWIG_OK;
+}
+
+int JSEmitter::createNamespace(String *scope) {
+
+ String *parent_scope = Swig_scopename_prefix(scope);
+ Hash *parent_namespace;
+ if (parent_scope == 0) {
+ parent_namespace = Getattr(namespaces, "::");
+ } else if (!Getattr(namespaces, parent_scope)) {
+ createNamespace(parent_scope);
+ parent_namespace = Getattr(namespaces, parent_scope);
+ } else {
+ parent_namespace = Getattr(namespaces, parent_scope);
+ }
+ assert(parent_namespace != 0);
+
+ Hash *new_namespace = createNamespaceEntry(Char(scope), Char(Getattr(parent_namespace, "name")), Char(Getattr(parent_namespace, "name_mangled")));
+ Setattr(namespaces, scope, new_namespace);
+
+ Delete(parent_scope);
+ return SWIG_OK;
+}
+
+Hash *JSEmitter::createNamespaceEntry(const char *_name, const char *parent, const char *parent_mangled) {
+ Hash *entry = NewHash();
+ String *name = NewString(_name);
+ Setattr(entry, NAME, Swig_scopename_last(name));
+ Setattr(entry, NAME_MANGLED, Swig_name_mangle(name));
+ Setattr(entry, PARENT, NewString(parent));
+ Setattr(entry, PARENT_MANGLED, NewString(parent_mangled));
+
+ Delete(name);
+ return entry;
+}
+
+/**********************************************************************
+ * JavascriptCore: JSEmitter implementation for JavascriptCore engine
+ **********************************************************************/
+
+class JSCEmitter:public JSEmitter {
+
+public:
+ JSCEmitter();
+ virtual ~ JSCEmitter();
+ virtual int initialize(Node *n);
+ virtual int dump(Node *n);
+ virtual int close();
+
+protected:
+ virtual int enterVariable(Node *n);
+ virtual int exitVariable(Node *n);
+ virtual int enterFunction(Node *n);
+ virtual int exitFunction(Node *n);
+ virtual int enterClass(Node *n);
+ virtual int exitClass(Node *n);
+ virtual void marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static);
+ virtual Hash *createNamespaceEntry(const char *name, const char *parent, const char *parent_mangled);
+ virtual int emitNamespaces();
+
+private:
+
+ String *NULL_STR;
+ String *VETO_SET;
+
+ // output file and major code parts
+ File *f_wrap_cpp;
+ File *f_runtime;
+ File *f_header;
+ File *f_init;
+
+};
+
+JSCEmitter::JSCEmitter()
+: JSEmitter(JSEmitter::JavascriptCore), NULL_STR(NewString("NULL")), VETO_SET(NewString("JS_veto_set_variable")), f_wrap_cpp(NULL), f_runtime(NULL), f_header(NULL), f_init(NULL) {
+}
+
+JSCEmitter::~JSCEmitter() {
+ Delete(NULL_STR);
+ Delete(VETO_SET);
+}
+
+
+/* ---------------------------------------------------------------------
+ * marshalInputArgs()
+ *
+ * Process all of the arguments passed into the argv array
+ * and convert them into C/C++ function arguments using the
+ * supplied typemaps.
+ * --------------------------------------------------------------------- */
+
+void JSCEmitter::marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static) {
+ Parm *p;
+ String *tm;
+
+ // determine an offset index, as members have an extra 'this' argument
+ // except: static members and ctors.
+ int startIdx = 0;
+ if (is_member && !is_static && mode != Ctor) {
+ startIdx = 1;
+ }
+ // store number of arguments for argument checks
+ int num_args = emit_num_arguments(parms) - startIdx;
+ String *argcount = NewString("");
+ Printf(argcount, "%d", num_args);
+ Setattr(n, ARGCOUNT, argcount);
+
+ // process arguments
+ int i = 0;
+ for (p = parms; p; i++) {
+ String *arg = NewString("");
+ String *type = Getattr(p, "type");
+
+ // ignore varargs
+ if (SwigType_isvarargs(type))
+ break;
+
+ switch (mode) {
+ case Getter:
+ case Function:
+ if (is_member && !is_static && i == 0) {
+ Printv(arg, "thisObject", 0);
+ } else {
+ Printf(arg, "argv[%d]", i - startIdx);
+ }
+ break;
+ case Setter:
+ if (is_member && !is_static && i == 0) {
+ Printv(arg, "thisObject", 0);
+ } else {
+ Printv(arg, "value", 0);
+ }
+ break;
+ case Ctor:
+ Printf(arg, "argv[%d]", i);
+ break;
+ default:
+ throw "Illegal state.";
+ }
+ tm = emitInputTypemap(n, p, wrapper, arg);
+ Delete(arg);
+ if (tm) {
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+}
+
+int JSCEmitter::initialize(Node *n) {
+
+ JSEmitter::initialize(n);
+
+ /* Get the output file name */
+ String *outfile = Getattr(n, "outfile");
+
+ /* Initialize I/O */
+ f_wrap_cpp = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_wrap_cpp) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ /* Initialization of members */
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+
+ state.globals(CREATE_NAMESPACES, NewString(""));
+ state.globals(REGISTER_NAMESPACES, NewString(""));
+ state.globals(INITIALIZER, NewString(""));
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("begin", f_wrap_cpp);
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+
+ Swig_banner(f_wrap_cpp);
+
+ return SWIG_OK;
+}
+
+int JSCEmitter::dump(Node *n) {
+ /* Get the module name */
+ String *module = Getattr(n, "name");
+
+ Template initializer_define(getTemplate("js_initializer_define"));
+ initializer_define.replace("$jsname", module).pretty_print(f_header);
+
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+
+ Printv(f_wrap_cpp, f_runtime, "\n", 0);
+ Printv(f_wrap_cpp, f_header, "\n", 0);
+ Printv(f_wrap_cpp, f_wrappers, "\n", 0);
+
+ emitNamespaces();
+
+ // compose the initializer function using a template
+ Template initializer(getTemplate("js_initializer"));
+ initializer.replace("$jsname", module)
+ .replace("$jsregisterclasses", state.globals(INITIALIZER))
+ .replace("$jscreatenamespaces", state.globals(CREATE_NAMESPACES))
+ .replace("$jsregisternamespaces", state.globals(REGISTER_NAMESPACES))
+ .pretty_print(f_init);
+
+ Printv(f_wrap_cpp, f_init, 0);
+
+ return SWIG_OK;
+}
+
+int JSCEmitter::close() {
+ Delete(f_runtime);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(namespaces);
+ Delete(f_wrap_cpp);
+ return SWIG_OK;
+}
+
+int JSCEmitter::enterFunction(Node *n) {
+
+ JSEmitter::enterFunction(n);
+
+ return SWIG_OK;
+}
+
+int JSCEmitter::exitFunction(Node *n) {
+ Template t_function = getTemplate("jsc_function_declaration");
+
+ bool is_member = GetFlag(n, "ismember") != 0 || GetFlag(n, "feature:extend") != 0;
+ bool is_overloaded = GetFlag(n, "sym:overloaded") != 0;
+
+ // handle overloaded functions
+ if (is_overloaded) {
+ if (!Getattr(n, "sym:nextSibling")) {
+ //state.function(WRAPPER_NAME, Swig_name_wrapper(Getattr(n, "name")));
+ // create dispatcher
+ emitFunctionDispatcher(n, is_member);
+ } else {
+ //don't register wrappers of overloaded functions in function tables
+ return SWIG_OK;
+ }
+ }
+
+ t_function.replace("$jsname", state.function(NAME))
+ .replace("$jswrapper", state.function(WRAPPER_NAME));
+
+ if (is_member) {
+ if (GetFlag(state.function(), IS_STATIC)) {
+ t_function.pretty_print(state.clazz(STATIC_FUNCTIONS));
+ } else {
+ t_function.pretty_print(state.clazz(MEMBER_FUNCTIONS));
+ }
+ } else {
+ t_function.pretty_print(Getattr(current_namespace, "functions"));
+ }
+
+ return SWIG_OK;
+}
+
+int JSCEmitter::enterVariable(Node *n) {
+ JSEmitter::enterVariable(n);
+ state.variable(GETTER, NULL_STR);
+ state.variable(SETTER, VETO_SET);
+ return SWIG_OK;
+}
+
+int JSCEmitter::exitVariable(Node *n) {
+ Template t_variable(getTemplate("jsc_variable_declaration"));
+ t_variable.replace("$jsname", state.variable(NAME))
+ .replace("$jsgetter", state.variable(GETTER))
+ .replace("$jssetter", state.variable(SETTER));
+
+ if (GetFlag(n, "ismember")) {
+ if (GetFlag(state.variable(), IS_STATIC)
+ || Equal(Getattr(n, "nodeType"), "enumitem")) {
+ t_variable.pretty_print(state.clazz(STATIC_VARIABLES));
+ } else {
+ t_variable.pretty_print(state.clazz(MEMBER_VARIABLES));
+ }
+ } else {
+ t_variable.pretty_print(Getattr(current_namespace, "values"));
+ }
+
+ return SWIG_OK;
+}
+
+int JSCEmitter::enterClass(Node *n) {
+ JSEmitter::enterClass(n);
+ state.clazz(MEMBER_VARIABLES, NewString(""));
+ state.clazz(MEMBER_FUNCTIONS, NewString(""));
+ state.clazz(STATIC_VARIABLES, NewString(""));
+ state.clazz(STATIC_FUNCTIONS, NewString(""));
+
+ Template t_class_decl = getTemplate("jsc_class_declaration");
+ t_class_decl.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .pretty_print(f_wrappers);
+
+ return SWIG_OK;
+}
+
+int JSCEmitter::exitClass(Node *n) {
+ Template t_class_tables(getTemplate("jsc_class_tables"));
+ t_class_tables.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsclassvariables", state.clazz(MEMBER_VARIABLES))
+ .replace("$jsclassfunctions", state.clazz(MEMBER_FUNCTIONS))
+ .replace("$jsstaticclassfunctions", state.clazz(STATIC_FUNCTIONS))
+ .replace("$jsstaticclassvariables", state.clazz(STATIC_VARIABLES))
+ .pretty_print(f_wrappers);
+
+ /* adds the ctor wrappers at this position */
+ // Note: this is necessary to avoid extra forward declarations.
+ //Append(f_wrappers, state.clazz(CTOR_WRAPPERS));
+
+ // for abstract classes add a vetoing ctor
+ if (GetFlag(state.clazz(), IS_ABSTRACT)) {
+ Template t_veto_ctor(getTemplate("js_veto_ctor"));
+ t_veto_ctor.replace("$jswrapper", state.clazz(CTOR))
+ .replace("$jsname", state.clazz(NAME))
+ .pretty_print(f_wrappers);
+ }
+
+ /* adds a class template statement to initializer function */
+ Template t_classtemplate(getTemplate("jsc_class_definition"));
+
+ /* prepare registration of base class */
+ String *jsclass_inheritance = NewString("");
+ Node *base_class = getBaseClass(n);
+ if (base_class != NULL) {
+ Template t_inherit(getTemplate("jsc_class_inherit"));
+ t_inherit.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsbaseclassmangled", SwigType_manglestr(Getattr(base_class, "name")))
+ .pretty_print(jsclass_inheritance);
+ } else {
+ Template t_inherit(getTemplate("jsc_class_noinherit"));
+ t_inherit.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .pretty_print(jsclass_inheritance);
+ }
+
+ t_classtemplate.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
+ .replace("$jsclass_inheritance", jsclass_inheritance)
+ .replace("$jsctor", state.clazz(CTOR))
+ .replace("$jsdtor", state.clazz(DTOR))
+ .pretty_print(state.globals(INITIALIZER));
+ Delete(jsclass_inheritance);
+
+ /* Note: this makes sure that there is a swig_type added for this class */
+ SwigType_remember_clientdata(state.clazz(TYPE_MANGLED), NewString("0"));
+
+ /* adds a class registration statement to initializer function */
+ Template t_registerclass(getTemplate("jsc_class_registration"));
+ t_registerclass.replace("$jsname", state.clazz(NAME))
+ .replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsnspace", Getattr(state.clazz("nspace"), NAME_MANGLED))
+ .pretty_print(state.globals(INITIALIZER));
+
+ return SWIG_OK;
+}
+
+Hash *JSCEmitter::createNamespaceEntry(const char *name, const char *parent, const char *parent_mangled) {
+ Hash *entry = JSEmitter::createNamespaceEntry(name, parent, parent_mangled);
+ Setattr(entry, "functions", NewString(""));
+ Setattr(entry, "values", NewString(""));
+ return entry;
+}
+
+int JSCEmitter::emitNamespaces() {
+ Iterator it;
+ for (it = First(namespaces); it.item; it = Next(it)) {
+ Hash *entry = it.item;
+ String *name = Getattr(entry, NAME);
+ String *name_mangled = Getattr(entry, NAME_MANGLED);
+ String *parent_mangled = Getattr(entry, PARENT_MANGLED);
+ String *functions = Getattr(entry, "functions");
+ String *variables = Getattr(entry, "values");
+
+ // skip the global namespace which is given by the application
+
+ Template namespace_definition(getTemplate("jsc_nspace_declaration"));
+ namespace_definition.replace("$jsglobalvariables", variables)
+ .replace("$jsglobalfunctions", functions)
+ .replace("$jsnspace", name_mangled)
+ .replace("$jsmangledname", name_mangled)
+ .pretty_print(f_wrap_cpp);
+
+ Template t_createNamespace(getTemplate("jsc_nspace_definition"));
+ t_createNamespace.replace("$jsmangledname", name_mangled);
+ Append(state.globals(CREATE_NAMESPACES), t_createNamespace.str());
+
+ // Don't register 'exports' as namespace. It is return to the application.
+ if (!Equal("exports", name)) {
+ Template t_registerNamespace(getTemplate("jsc_nspace_registration"));
+ t_registerNamespace.replace("$jsmangledname", name_mangled)
+ .replace("$jsname", name)
+ .replace("$jsparent", parent_mangled);
+ Append(state.globals(REGISTER_NAMESPACES), t_registerNamespace.str());
+ }
+ }
+
+ return SWIG_OK;
+}
+
+JSEmitter *swig_javascript_create_JSCEmitter() {
+ return new JSCEmitter();
+}
+
+/**********************************************************************
+ * V8: JSEmitter implementation for V8 engine
+ **********************************************************************/
+
+class V8Emitter:public JSEmitter {
+
+public:
+ V8Emitter();
+
+ virtual ~ V8Emitter();
+ virtual int initialize(Node *n);
+ virtual int dump(Node *n);
+ virtual int close();
+ virtual int enterClass(Node *n);
+ virtual int exitClass(Node *n);
+ virtual int enterVariable(Node *n);
+ virtual int exitVariable(Node *n);
+ virtual int exitFunction(Node *n);
+
+protected:
+ virtual void marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static);
+ virtual int emitNamespaces();
+
+protected:
+ /* built-in parts */
+ String *f_runtime;
+ String *f_header;
+ String *f_init;
+ String *f_post_init;
+
+ /* part for class templates */
+ String *f_class_templates;
+
+ /* parts for initilizer */
+ String *f_init_namespaces;
+ String *f_init_class_templates;
+ String *f_init_wrappers;
+ String *f_init_inheritance;
+ String *f_init_class_instances;
+ String *f_init_static_wrappers;
+ String *f_init_register_classes;
+ String *f_init_register_namespaces;
+
+ // the output cpp file
+ File *f_wrap_cpp;
+
+ String *NULL_STR;
+ String *VETO_SET;
+ String *moduleName;
+
+};
+
+V8Emitter::V8Emitter()
+: JSEmitter(JSEmitter::V8), NULL_STR(NewString("0")), VETO_SET(NewString("JS_veto_set_variable")) {
+}
+
+V8Emitter::~V8Emitter() {
+ Delete(NULL_STR);
+ Delete(VETO_SET);
+}
+
+int V8Emitter::initialize(Node *n) {
+ JSEmitter::initialize(n);
+
+ moduleName = Getattr(n, "name");
+
+ // Get the output file name
+ String *outfile = Getattr(n, "outfile");
+ f_wrap_cpp = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_wrap_cpp) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ f_runtime = NewString("");
+ f_header = NewString("");
+ f_class_templates = NewString("");
+ f_init = NewString("");
+ f_post_init = NewString("");
+
+ f_init_namespaces = NewString("");
+ f_init_class_templates = NewString("");
+ f_init_wrappers = NewString("");
+ f_init_inheritance = NewString("");
+ f_init_class_instances = NewString("");
+ f_init_static_wrappers = NewString("");
+ f_init_register_classes = NewString("");
+ f_init_register_namespaces = NewString("");
+
+ // note: this is necessary for built-in generation of SWIG runtime code
+ Swig_register_filebyname("begin", f_wrap_cpp);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("post-init", f_post_init);
+
+ state.globals(FORCE_CPP, NewString("1"));
+
+ Swig_banner(f_wrap_cpp);
+
+ return SWIG_OK;
+}
+
+int V8Emitter::dump(Node *n) {
+ /* Get the module name */
+ String *module = Getattr(n, "name");
+
+ Template initializer_define(getTemplate("js_initializer_define"));
+ initializer_define.replace("$jsname", module).pretty_print(f_header);
+
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+
+ Printv(f_wrap_cpp, f_runtime, "\n", 0);
+ Printv(f_wrap_cpp, f_header, "\n", 0);
+ Printv(f_wrap_cpp, f_class_templates, "\n", 0);
+ Printv(f_wrap_cpp, f_wrappers, "\n", 0);
+
+ emitNamespaces();
+
+ // compose the initializer function using a template
+ // filled with sub-parts
+ Template initializer(getTemplate("js_initializer"));
+ initializer.replace("$jsname", moduleName)
+ .replace("$jsv8nspaces", f_init_namespaces)
+ .replace("$jsv8classtemplates", f_init_class_templates)
+ .replace("$jsv8wrappers", f_init_wrappers)
+ .replace("$jsv8inheritance", f_init_inheritance)
+ .replace("$jsv8classinstances", f_init_class_instances)
+ .replace("$jsv8staticwrappers", f_init_static_wrappers)
+ .replace("$jsv8registerclasses", f_init_register_classes)
+ .replace("$jsv8registernspaces", f_init_register_namespaces);
+ Printv(f_init, initializer.str(), 0);
+
+ Printv(f_wrap_cpp, f_init, 0);
+
+ Printv(f_wrap_cpp, f_post_init, 0);
+
+ return SWIG_OK;
+}
+
+int V8Emitter::close() {
+ Delete(f_runtime);
+ Delete(f_header);
+ Delete(f_class_templates);
+ Delete(f_init_namespaces);
+ Delete(f_init_class_templates);
+ Delete(f_init_wrappers);
+ Delete(f_init_inheritance);
+ Delete(f_init_class_instances);
+ Delete(f_init_static_wrappers);
+ Delete(f_init_register_classes);
+ Delete(f_init_register_namespaces);
+ Delete(f_init);
+ Delete(f_post_init);
+ Delete(f_wrap_cpp);
+ return SWIG_OK;
+}
+
+int V8Emitter::enterClass(Node *n) {
+ JSEmitter::enterClass(n);
+
+ // emit declaration of a v8 class template
+ Template t_decl_class(getTemplate("jsv8_declare_class_template"));
+ t_decl_class.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .trim()
+ .pretty_print(f_class_templates);
+
+ return SWIG_OK;
+}
+
+int V8Emitter::exitClass(Node *n) {
+ if (GetFlag(state.clazz(), IS_ABSTRACT)) {
+ Template t_veto_ctor(getTemplate("js_veto_ctor"));
+ t_veto_ctor.replace("$jswrapper", state.clazz(CTOR))
+ .replace("$jsname", state.clazz(NAME))
+ .pretty_print(f_wrappers);
+ }
+
+ /* Note: this makes sure that there is a swig_type added for this class */
+ String *clientData = NewString("");
+ Printf(clientData, "&%s_clientData", state.clazz(NAME_MANGLED));
+
+ /* Note: this makes sure that there is a swig_type added for this class */
+ SwigType_remember_clientdata(state.clazz(TYPE_MANGLED), NewString("0"));
+
+ // emit definition of v8 class template
+ Template t_def_class = getTemplate("jsv8_define_class_template");
+ t_def_class.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.clazz(NAME))
+ .replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
+ .replace("$jsdtor", state.clazz(DTOR))
+ .trim()
+ .pretty_print(f_init_class_templates);
+
+ Template t_class_instance = getTemplate("jsv8_create_class_instance");
+ t_class_instance.replace("$jsname", state.clazz(NAME))
+ .replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsctor", state.clazz(CTOR))
+ .trim()
+ .pretty_print(f_init_class_instances);
+
+ // emit inheritance setup
+ Node *baseClass = getBaseClass(n);
+ if (baseClass) {
+ String *base_name = Getattr(baseClass, "name");
+
+ Template t_inherit = getTemplate("jsv8_inherit");
+
+ String *base_name_mangled = SwigType_manglestr(base_name);
+ t_inherit.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsbaseclass", base_name_mangled)
+ .trim()
+ .pretty_print(f_init_inheritance);
+ Delete(base_name_mangled);
+ }
+ // emit registration of class template
+ Template t_register = getTemplate("jsv8_register_class");
+ t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.clazz(NAME))
+ .replace("$jsparent", Getattr(state.clazz("nspace"), NAME_MANGLED))
+ .trim()
+ .pretty_print(f_init_register_classes);
+
+ return SWIG_OK;
+}
+
+int V8Emitter::enterVariable(Node *n) {
+ JSEmitter::enterVariable(n);
+
+ state.variable(GETTER, NULL_STR);
+ state.variable(SETTER, VETO_SET);
+
+ return SWIG_OK;
+}
+
+int V8Emitter::exitVariable(Node *n) {
+ if (GetFlag(n, "ismember")) {
+ if (GetFlag(state.variable(), IS_STATIC) || Equal(Getattr(n, "nodeType"), "enumitem")) {
+ Template t_register = getTemplate("jsv8_register_static_variable");
+ t_register.replace("$jsparent", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.variable(NAME))
+ .replace("$jsgetter", state.variable(GETTER))
+ .replace("$jssetter", state.variable(SETTER))
+ .trim()
+ .pretty_print(f_init_static_wrappers);
+ } else {
+ Template t_register = getTemplate("jsv8_register_member_variable");
+ t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.variable(NAME))
+ .replace("$jsgetter", state.variable(GETTER))
+ .replace("$jssetter", state.variable(SETTER))
+ .trim()
+ .pretty_print(f_init_wrappers);
+ }
+ } else {
+ // Note: a global variable is treated like a static variable
+ // with the parent being a nspace object (instead of class object)
+ Template t_register = getTemplate("jsv8_register_static_variable");
+ t_register.replace("$jsparent", Getattr(current_namespace, NAME_MANGLED))
+ .replace("$jsname", state.variable(NAME))
+ .replace("$jsgetter", state.variable(GETTER))
+ .replace("$jssetter", state.variable(SETTER))
+ .trim()
+ .pretty_print(f_init_wrappers);
+ }
+
+ return SWIG_OK;
+}
+
+int V8Emitter::exitFunction(Node *n) {
+ bool is_member = GetFlag(n, "ismember") != 0 || GetFlag(n, "feature:extend") != 0;
+
+ // create a dispatcher for overloaded functions
+ bool is_overloaded = GetFlag(n, "sym:overloaded") != 0;
+ if (is_overloaded) {
+ if (!Getattr(n, "sym:nextSibling")) {
+ //state.function(WRAPPER_NAME, Swig_name_wrapper(Getattr(n, "name")));
+ emitFunctionDispatcher(n, is_member);
+ } else {
+ //don't register wrappers of overloaded functions in function tables
+ return SWIG_OK;
+ }
+ }
+ // register the function at the specific context
+ if (is_member) {
+ if (GetFlag(state.function(), IS_STATIC)) {
+ Template t_register = getTemplate("jsv8_register_static_function");
+ t_register.replace("$jsparent", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.function(NAME))
+ .replace("$jswrapper", state.function(WRAPPER_NAME))
+ .trim()
+ .pretty_print(f_init_static_wrappers);
+ } else {
+ Template t_register = getTemplate("jsv8_register_member_function");
+ t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.function(NAME))
+ .replace("$jswrapper", state.function(WRAPPER_NAME))
+ .trim()
+ .pretty_print(f_init_wrappers);
+ }
+ } else {
+ // Note: a global function is treated like a static function
+ // with the parent being a nspace object instead of class object
+ Template t_register = getTemplate("jsv8_register_static_function");
+ t_register.replace("$jsparent", Getattr(current_namespace, NAME_MANGLED))
+ .replace("$jsname", state.function(NAME))
+ .replace("$jswrapper", state.function(WRAPPER_NAME))
+ .trim()
+ .pretty_print(f_init_static_wrappers);
+ }
+
+ return SWIG_OK;
+}
+
+void V8Emitter::marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static) {
+ Parm *p;
+ String *tm;
+
+ int startIdx = 0;
+ if (is_member && !is_static && mode != Ctor) {
+ startIdx = 1;
+ }
+ // store number of arguments for argument checks
+ int num_args = emit_num_arguments(parms) - startIdx;
+ String *argcount = NewString("");
+ Printf(argcount, "%d", num_args);
+ Setattr(n, ARGCOUNT, argcount);
+
+ int i = 0;
+ for (p = parms; p; i++) {
+ String *arg = NewString("");
+ String *type = Getattr(p, "type");
+
+ // ignore varargs
+ if (SwigType_isvarargs(type))
+ break;
+
+ switch (mode) {
+ case Getter:
+ if (is_member && !is_static && i == 0) {
+ Printv(arg, "info.Holder()", 0);
+ } else {
+ Printf(arg, "args[%d]", i - startIdx);
+ }
+ break;
+ case Function:
+ if (is_member && !is_static && i == 0) {
+ Printv(arg, "args.Holder()", 0);
+ } else {
+ Printf(arg, "args[%d]", i - startIdx);
+ }
+ break;
+ case Setter:
+ if (is_member && !is_static && i == 0) {
+ Printv(arg, "info.Holder()", 0);
+ } else {
+ Printv(arg, "value", 0);
+ }
+ break;
+ case Ctor:
+ Printf(arg, "args[%d]", i);
+ break;
+ default:
+ throw "Illegal state.";
+ }
+
+ tm = emitInputTypemap(n, p, wrapper, arg);
+ Delete(arg);
+
+ if (tm) {
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+}
+
+int V8Emitter::emitNamespaces() {
+ Iterator it;
+ for (it = First(namespaces); it.item; it = Next(it)) {
+ Hash *entry = it.item;
+ String *name = Getattr(entry, NAME);
+ String *name_mangled = Getattr(entry, NAME_MANGLED);
+ String *parent = Getattr(entry, PARENT);
+ String *parent_mangled = Getattr(entry, PARENT_MANGLED);
+
+ bool do_create = true;
+ bool do_register = true;
+
+ if (Equal(parent, "")) {
+ do_register = false;
+ }
+ // Note: 'exports' is by convention the name of the object where
+ // globals are stored into
+ if (Equal(name, "exports")) {
+ do_create = false;
+ }
+
+ if (do_create) {
+ // create namespace object and register it to the parent scope
+ Template t_create_ns = getTemplate("jsv8_create_namespace");
+ t_create_ns.replace("$jsmangledname", name_mangled)
+ .trim()
+ .pretty_print(f_init_namespaces);
+ }
+
+ if (do_register) {
+ Template t_register_ns = getTemplate("jsv8_register_namespace");
+ t_register_ns.replace("$jsmangledname", name_mangled)
+ .replace("$jsname", name)
+ .replace("$jsparent", parent_mangled)
+ .trim();
+
+ // prepend in order to achieve reversed order of registration statements
+ String *tmp_register_stmt = NewString("");
+ t_register_ns.pretty_print(tmp_register_stmt);
+ Insert(f_init_register_namespaces, 0, tmp_register_stmt);
+ Delete(tmp_register_stmt);
+ }
+ }
+
+ return SWIG_OK;
+}
+
+JSEmitter *swig_javascript_create_V8Emitter() {
+ return new V8Emitter();
+}
+
+/**********************************************************************
+ * Helper implementations
+ **********************************************************************/
+
+JSEmitterState::JSEmitterState()
+: globalHash(NewHash()) {
+ // initialize sub-hashes
+ Setattr(globalHash, "class", NewHash());
+ Setattr(globalHash, "function", NewHash());
+ Setattr(globalHash, "variable", NewHash());
+}
+
+JSEmitterState::~JSEmitterState() {
+ Delete(globalHash);
+}
+
+DOH *JSEmitterState::getState(const char *key, bool new_key) {
+ if (new_key) {
+ Hash *hash = NewHash();
+ Setattr(globalHash, key, hash);
+ }
+ return Getattr(globalHash, key);
+}
+
+DOH *JSEmitterState::globals() {
+ return globalHash;
+}
+
+DOH *JSEmitterState::globals(const char *key, DOH *initial) {
+ if (initial != 0) {
+ Setattr(globalHash, key, initial);
+ }
+ return Getattr(globalHash, key);
+}
+
+DOH *JSEmitterState::clazz(bool new_key) {
+ return getState("class", new_key);
+}
+
+DOH *JSEmitterState::clazz(const char *key, DOH *initial) {
+ DOH *c = clazz();
+ if (initial != 0) {
+ Setattr(c, key, initial);
+ }
+ return Getattr(c, key);
+}
+
+DOH *JSEmitterState::function(bool new_key) {
+ return getState("function", new_key);
+}
+
+DOH *JSEmitterState::function(const char *key, DOH *initial) {
+ DOH *f = function();
+ if (initial != 0) {
+ Setattr(f, key, initial);
+ }
+ return Getattr(f, key);
+}
+
+DOH *JSEmitterState::variable(bool new_key) {
+ return getState("variable", new_key);
+}
+
+DOH *JSEmitterState::variable(const char *key, DOH *initial) {
+ DOH *v = variable();
+ if (initial != 0) {
+ Setattr(v, key, initial);
+ }
+ return Getattr(v, key);
+}
+
+/*static*/
+int JSEmitterState::IsSet(DOH *val) {
+ if (!val) {
+ return 0;
+ } else {
+ const char *cval = Char(val);
+ if (!cval)
+ return 0;
+ return (strcmp(cval, "0") != 0) ? 1 : 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Template::Template() : creates a Template class for given template code
+ * ----------------------------------------------------------------------------- */
+
+Template::Template(const String *code_) {
+
+ if (!code_) {
+ Printf(stdout, "Template code was null. Illegal input for template.");
+ SWIG_exit(EXIT_FAILURE);
+ }
+ code = NewString(code_);
+ templateName = NewString("");
+}
+
+Template::Template(const String *code_, const String *templateName_) {
+
+ if (!code_) {
+ Printf(stdout, "Template code was null. Illegal input for template.");
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ code = NewString(code_);
+ templateName = NewString(templateName_);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Template::~Template() : cleans up of Template.
+ * ----------------------------------------------------------------------------- */
+
+Template::~Template() {
+ Delete(code);
+ Delete(templateName);
+}
+
+/* -----------------------------------------------------------------------------
+ * String* Template::str() : retrieves the current content of the template.
+ * ----------------------------------------------------------------------------- */
+
+String *Template::str() {
+ if (js_template_enable_debug) {
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *debug_code = NewString("");
+ Printf(pre_code, "/* begin fragment(\"%s\") */", templateName);
+ Printf(post_code, "/* end fragment(\"%s\") */", templateName);
+ Printf(debug_code, "%s\n%s\n%s\n", pre_code, code, post_code);
+
+ Delete(code);
+ Delete(pre_code);
+ Delete(post_code);
+
+ code = debug_code;
+ }
+ return code;
+}
+
+Template & Template::trim() {
+ const char *str = Char(code);
+ if (str == 0)
+ return *this;
+
+ int length = Len(code);
+ if (length == 0)
+ return *this;
+
+ int idx;
+ for (idx = 0; idx < length; ++idx) {
+ if (str[idx] != ' ' && str[idx] != '\t' && str[idx] != '\r' && str[idx] != '\n')
+ break;
+ }
+ int start_pos = idx;
+
+ for (idx = length - 1; idx >= start_pos; --idx) {
+ if (str[idx] != ' ' && str[idx] != '\t' && str[idx] != '\r' && str[idx] != '\n')
+ break;
+ }
+ int end_pos = idx;
+
+ int new_length = end_pos - start_pos + 1;
+ char *newstr = new char[new_length + 1];
+ memcpy(newstr, str + start_pos, new_length);
+ newstr[new_length] = 0;
+
+ Delete(code);
+ code = NewString(newstr);
+ delete[]newstr;
+
+ return *this;
+}
+
+/* -----------------------------------------------------------------------------
+ * Template& Template::replace(const String* pattern, const String* repl) :
+ *
+ * replaces all occurrences of a given pattern with a given replacement.
+ *
+ * - pattern: the pattern to be replaced
+ * - repl: the replacement string
+ * - returns a reference to the Template to allow chaining of methods.
+ * ----------------------------------------------------------------------------- */
+
+Template & Template::replace(const String *pattern, const String *repl) {
+ Replaceall(code, pattern, repl);
+ return *this;
+}
+
+Template & Template::print(DOH *doh) {
+ Printv(doh, str(), 0);
+ return *this;
+}
+
+Template & Template::pretty_print(DOH *doh) {
+ Wrapper_pretty_print(str(), doh);
+ return *this;
+}
+
+Template::Template(const Template & t) {
+ code = NewString(t.code);
+ templateName = NewString(t.templateName);
+}
+
+void Template::operator=(const Template & t) {
+ Delete(code);
+ Delete(templateName);
+ code = NewString(t.code);
+ templateName = NewString(t.templateName);
+}
diff --git a/contrib/tools/swig/Source/Modules/lang.cxx b/contrib/tools/swig/Source/Modules/lang.cxx
new file mode 100644
index 00000000000..f7979b611c2
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/lang.cxx
@@ -0,0 +1,3895 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * lang.cxx
+ *
+ * Language base class functions. Default C++ handling is also implemented here.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+#include <ctype.h>
+
+/* default mode settings */
+static int director_mode = 0;
+static int director_protected_mode = 1;
+static int all_protected_mode = 0;
+static int naturalvar_mode = 0;
+Language *Language::this_ = 0;
+
+/* Set director_protected_mode */
+void Wrapper_director_mode_set(int flag) {
+ director_mode = flag;
+}
+
+void Wrapper_director_protected_mode_set(int flag) {
+ director_protected_mode = flag;
+}
+
+void Wrapper_all_protected_mode_set(int flag) {
+ all_protected_mode = flag;
+}
+
+void Wrapper_naturalvar_mode_set(int flag) {
+ naturalvar_mode = flag;
+}
+
+extern "C" {
+ int Swig_director_mode() {
+ return director_mode;
+ }
+ int Swig_director_protected_mode() {
+ return director_protected_mode;
+ }
+ int Swig_all_protected_mode() {
+ return all_protected_mode;
+ }
+ void Language_replace_special_variables(String *method, String *tm, Parm *parm) {
+ Language::instance()->replaceSpecialVariables(method, tm, parm);
+ }
+}
+
+/* Some status variables used during parsing */
+static int InClass = 0; /* Parsing C++ or not */
+static String *ClassName = 0; /* This is the real name of the current class */
+static String *EnumClassName = 0; /* Enum class name */
+static String *ClassPrefix = 0; /* Class prefix */
+static String *EnumClassPrefix = 0; /* Prefix for strongly typed enums (including ClassPrefix) */
+static String *NSpace = 0; /* Namespace for the nspace feature */
+static String *ClassType = 0; /* Fully qualified type name to use */
+static String *DirectorClassName = 0; /* Director name of the current class */
+int Abstract = 0;
+int ImportMode = 0;
+int IsVirtual = 0;
+static String *AttributeFunctionGet = 0;
+static String *AttributeFunctionSet = 0;
+static Node *CurrentClass = 0;
+int line_number = 0;
+String *input_file = 0;
+int SmartPointer = 0;
+static Hash *classhash;
+
+extern int GenerateDefault;
+extern int ForceExtern;
+extern int AddExtern;
+
+/* import modes */
+
+#define IMPORT_MODE 1
+
+/* ----------------------------------------------------------------------
+ * Dispatcher::emit_one()
+ *
+ * Dispatch a single node
+ * ---------------------------------------------------------------------- */
+
+int Dispatcher::emit_one(Node *n) {
+ int ret = SWIG_OK;
+
+ char *tag = Char(nodeType(n));
+ if (!tag) {
+ /* Printf(stderr,"SWIG: Fatal internal error. Malformed parse tree
+ node!\n"); */
+ return SWIG_OK;
+ }
+
+ /* Do not proceed if marked with an error */
+
+ if (Getattr(n, "error"))
+ return SWIG_OK;
+
+ /* Look for warnings */
+ String *wrn = Getattr(n, "feature:warnfilter");
+ if (wrn)
+ Swig_warnfilter(wrn, 1);
+
+ /* ============================================================
+ * C/C++ parsing
+ * ============================================================ */
+
+ if (strcmp(tag, "extern") == 0) {
+ ret = externDeclaration(n);
+ } else if (strcmp(tag, "cdecl") == 0) {
+ ret = cDeclaration(n);
+ } else if (strcmp(tag, "enum") == 0) {
+ ret = enumDeclaration(n);
+ } else if (strcmp(tag, "enumitem") == 0) {
+ ret = enumvalueDeclaration(n);
+ } else if (strcmp(tag, "enumforward") == 0) {
+ ret = enumforwardDeclaration(n);
+ } else if (strcmp(tag, "class") == 0) {
+ ret = classDeclaration(n);
+ } else if (strcmp(tag, "classforward") == 0) {
+ ret = classforwardDeclaration(n);
+ } else if (strcmp(tag, "constructor") == 0) {
+ ret = constructorDeclaration(n);
+ } else if (strcmp(tag, "destructor") == 0) {
+ ret = destructorDeclaration(n);
+ } else if (strcmp(tag, "access") == 0) {
+ ret = accessDeclaration(n);
+ } else if (strcmp(tag, "using") == 0) {
+ ret = usingDeclaration(n);
+ } else if (strcmp(tag, "namespace") == 0) {
+ ret = namespaceDeclaration(n);
+ } else if (strcmp(tag, "template") == 0) {
+ ret = templateDeclaration(n);
+ } else if (strcmp(tag, "lambda") == 0) {
+ ret = lambdaDeclaration(n);
+ }
+
+ /* ===============================================================
+ * SWIG directives
+ * =============================================================== */
+
+ else if (strcmp(tag, "top") == 0) {
+ ret = top(n);
+ } else if (strcmp(tag, "extend") == 0) {
+ ret = extendDirective(n);
+ } else if (strcmp(tag, "apply") == 0) {
+ ret = applyDirective(n);
+ } else if (strcmp(tag, "clear") == 0) {
+ ret = clearDirective(n);
+ } else if (strcmp(tag, "constant") == 0) {
+ ret = constantDirective(n);
+ } else if (strcmp(tag, "fragment") == 0) {
+ ret = fragmentDirective(n);
+ } else if (strcmp(tag, "import") == 0) {
+ ret = importDirective(n);
+ } else if (strcmp(tag, "include") == 0) {
+ ret = includeDirective(n);
+ } else if (strcmp(tag, "insert") == 0) {
+ ret = insertDirective(n);
+ } else if (strcmp(tag, "module") == 0) {
+ ret = moduleDirective(n);
+ } else if (strcmp(tag, "native") == 0) {
+ ret = nativeDirective(n);
+ } else if (strcmp(tag, "pragma") == 0) {
+ ret = pragmaDirective(n);
+ } else if (strcmp(tag, "typemap") == 0) {
+ ret = typemapDirective(n);
+ } else if (strcmp(tag, "typemapcopy") == 0) {
+ ret = typemapcopyDirective(n);
+ } else if (strcmp(tag, "typemapitem") == 0) {
+ ret = typemapitemDirective(n);
+ } else if (strcmp(tag, "types") == 0) {
+ ret = typesDirective(n);
+ } else {
+ Swig_error(input_file, line_number, "Unrecognized parse tree node type '%s'\n", tag);
+ ret = SWIG_ERROR;
+ }
+ if (wrn)
+ Swig_warnfilter(wrn, 0);
+ return ret;
+}
+
+/* ----------------------------------------------------------------------
+ * Dispatcher::emit_children()
+ *
+ * Emit all children that match the given type. type = 0 means all types.
+ * ---------------------------------------------------------------------- */
+
+int Dispatcher::emit_children(Node *n) {
+ Node *c;
+ char *eo = Char(Getattr(n, "feature:emitonlychildren"));
+ for (c = firstChild(n); c; c = nextSibling(c)) {
+ if (eo) {
+ const char *tag = Char(nodeType(c));
+ if (strcmp(tag, "cdecl") == 0) {
+ if (checkAttribute(c, "storage", "typedef"))
+ tag = "typedef";
+ }
+ if (strstr(eo, tag) == 0) {
+ continue;
+ }
+ }
+ emit_one(c);
+ }
+ return SWIG_OK;
+}
+
+
+/* Stubs for dispatcher class. We don't do anything by default---up to derived class
+ to fill in traversal code */
+
+int Dispatcher::defaultHandler(Node *) {
+ return SWIG_OK;
+}
+int Dispatcher::extendDirective(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::applyDirective(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::clearDirective(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::constantDirective(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::fragmentDirective(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::importDirective(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::includeDirective(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::insertDirective(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::moduleDirective(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::nativeDirective(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::pragmaDirective(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::typemapDirective(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::typemapitemDirective(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::typemapcopyDirective(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::typesDirective(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::cDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::externDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::enumDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::enumvalueDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::enumforwardDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::classDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::templateDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::lambdaDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::classforwardDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::constructorDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::destructorDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::accessDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::usingDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+int Dispatcher::namespaceDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+
+/* Allocators */
+Language::Language():
+none_comparison(NewString("$arg != 0")),
+director_ctor_code(NewString("")),
+director_prot_ctor_code(0),
+symtabs(NewHash()),
+overloading(0),
+multiinput(0),
+cplus_runtime(0),
+directors(0) {
+ symbolAddScope(""); // create top level/global symbol table scope
+ argc_template_string = NewString("argc");
+ argv_template_string = NewString("argv[%d]");
+
+ /* Default director constructor code, passed to Swig_ConstructorToFunction */
+ Printv(director_ctor_code, "if ( $comparison ) { /* subclassed */\n", " $director_new \n", "} else {\n", " $nondirector_new \n", "}\n", NIL);
+
+ /*
+ Default director 'protected' constructor code, disabled by
+ default. Each language that needs it, has to define it.
+ */
+ director_prot_ctor_code = 0;
+ director_multiple_inheritance = 1;
+ director_language = 0;
+ assert(!this_);
+ this_ = this;
+
+ doxygenTranslator = NULL;
+}
+
+Language::~Language() {
+ Delete(symtabs);
+ Delete(director_ctor_code);
+ Delete(none_comparison);
+ this_ = 0;
+}
+
+ /* -----------------------------------------------------------------------------
+ * directorClassName()
+ * ----------------------------------------------------------------------------- */
+
+ String *Language::directorClassName(Node *n) {
+ String *dirclassname;
+ String *nspace = NewString(Getattr(n, "sym:nspace"));
+ const char *attrib = "director:classname";
+ String *classname = getClassPrefix();
+
+ Replace(nspace, NSPACE_SEPARATOR, "_", DOH_REPLACE_ANY);
+ if (Len(nspace) > 0)
+ dirclassname = NewStringf("SwigDirector_%s_%s", nspace, classname);
+ else
+ dirclassname = NewStringf("SwigDirector_%s", classname);
+ Setattr(n, attrib, dirclassname);
+
+ Delete(nspace);
+ return dirclassname;
+ }
+
+/* ----------------------------------------------------------------------
+ emit_one()
+ ---------------------------------------------------------------------- */
+
+int Language::emit_one(Node *n) {
+ int ret;
+ int oldext;
+ if (!n)
+ return SWIG_OK;
+
+ if (GetFlag(n, "feature:ignore")
+ && !Getattr(n, "feature:onlychildren"))
+ return SWIG_OK;
+
+ oldext = Extend;
+ if (Getattr(n, "feature:extend"))
+ Extend = 1;
+
+ line_number = Getline(n);
+ input_file = Getfile(n);
+
+ /*
+ symtab = Getattr(n,"symtab");
+ if (symtab) {
+ symtab = Swig_symbol_setscope(symtab);
+ }
+ */
+ ret = Dispatcher::emit_one(n);
+ /*
+ if (symtab) {
+ Swig_symbol_setscope(symtab);
+ }
+ */
+ Extend = oldext;
+ return ret;
+}
+
+
+static Parm *nonvoid_parms(Parm *p) {
+ if (p) {
+ SwigType *t = Getattr(p, "type");
+ if (SwigType_type(t) == T_VOID)
+ return 0;
+ }
+ return p;
+}
+
+/* -----------------------------------------------------------------------------
+ * cplus_value_type()
+ *
+ * Returns the alternative value type needed in C++ for class value
+ * types. When swig is not sure about using a plain $ltype value,
+ * since the class doesn't have a default constructor, or it can't be
+ * assigned, you will get back 'SwigValueWrapper<type >'.
+ *
+ * ----------------------------------------------------------------------------- */
+
+SwigType *cplus_value_type(SwigType *t) {
+ return SwigType_alttype(t, 0);
+}
+
+static Node *first_nontemplate(Node *n) {
+ while (n) {
+ if (Strcmp(nodeType(n), "template") != 0)
+ return n;
+ n = Getattr(n, "sym:nextSibling");
+ }
+ return n;
+}
+
+
+
+/* --------------------------------------------------------------------------
+ * swig_pragma()
+ *
+ * Handle swig pragma directives.
+ * -------------------------------------------------------------------------- */
+
+void swig_pragma(char *lang, char *name, char *value) {
+ if (strcmp(lang, "swig") == 0) {
+ if ((strcmp(name, "make_default") == 0) || ((strcmp(name, "makedefault") == 0))) {
+ GenerateDefault = 1;
+ } else if ((strcmp(name, "no_default") == 0) || ((strcmp(name, "nodefault") == 0))) {
+ Swig_warning(WARN_DEPRECATED_NODEFAULT, "SWIG", 1, "dangerous, use %%nodefaultctor, %%nodefaultdtor instead.\n");
+ GenerateDefault = 0;
+ } else if (strcmp(name, "attributefunction") == 0) {
+ String *nvalue = NewString(value);
+ char *s = strchr(Char(nvalue), ':');
+ if (!s) {
+ Swig_error(input_file, line_number, "Bad value for attributefunction. Expected \"fmtget:fmtset\".\n");
+ } else {
+ *s = 0;
+ AttributeFunctionGet = NewString(Char(nvalue));
+ AttributeFunctionSet = NewString(s + 1);
+ }
+ Delete(nvalue);
+ } else if (strcmp(name, "noattributefunction") == 0) {
+ AttributeFunctionGet = 0;
+ AttributeFunctionSet = 0;
+ }
+ }
+}
+
+/* --------------------------------------------------------------------------
+ * Language::use_naturalvar_mode()
+ *
+ * Determine whether to use const ref typemaps instead of pointer typemaps
+ * for variable access.
+ * -------------------------------------------------------------------------- */
+int Language::use_naturalvar_mode(Node *n) const {
+ if (Getattr(n, "unnamed"))
+ return 0;
+
+ // The naturalvar feature can be attached to either the variable name or the variable's type
+ // naturalvar on the variable name is more specific and overrides naturalvar on the variable's type
+ String *naturalvar = Getattr(n, "feature:naturalvar");
+ bool explicitly_off = naturalvar && Strcmp(naturalvar, "0") == 0;
+ int nvar = GetFlag(n, "feature:naturalvar");
+
+ if (!explicitly_off && !nvar) {
+ /* look for feature in the class */
+ SwigType *ty = Getattr(n, "type");
+ SwigType *fullty = SwigType_typedef_resolve_all(ty);
+ if (SwigType_isclass(fullty)) {
+ SwigType *tys = SwigType_strip_qualifiers(fullty);
+ if (!CPlusPlus) {
+ Replaceall(tys, "struct ", "");
+ Replaceall(tys, "union ", "");
+ Replaceall(tys, "class ", "");
+ }
+ Node *typenode = Swig_symbol_clookup(tys, 0);
+ if (typenode) {
+ naturalvar = Getattr(typenode, "feature:naturalvar");
+ explicitly_off = naturalvar && Strcmp(naturalvar, "0") == 0;
+ nvar = nvar || GetFlag(typenode, "feature:naturalvar");
+ }
+ Delete(tys);
+ }
+ Delete(fullty);
+ }
+ nvar = nvar || naturalvar_mode;
+ return explicitly_off ? 0 : nvar ? CWRAP_NATURAL_VAR : 0;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::top() - Top of parsing tree
+ * ---------------------------------------------------------------------- */
+
+int Language::top(Node *n) {
+ Node *mod = Getattr(n, "module");
+ if (mod) {
+ Node *options = Getattr(mod, "options");
+ if (options) {
+ if (Getattr(options, "naturalvar")) {
+ naturalvar_mode = 1;
+ }
+ }
+ }
+ classhash = Getattr(n, "classes");
+ return emit_children(n);
+}
+
+/* ----------------------------------------------------------------------
+ * Language::extendDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::extendDirective(Node *n) {
+ save_value<int> oldam(Extend, CWRAP_EXTEND);
+ save_value<AccessMode> oldmode(cplus_mode, PUBLIC);
+ emit_children(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::applyDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::applyDirective(Node *n) {
+
+ Parm *pattern = Getattr(n, "pattern");
+ Node *c = firstChild(n);
+ while (c) {
+ Parm *apattern = Getattr(c, "pattern");
+ if (ParmList_len(pattern) != ParmList_len(apattern)) {
+ Swig_error(input_file, line_number, "Can't apply (%s) to (%s). Number of arguments don't match.\n", ParmList_str(pattern), ParmList_str(apattern));
+ } else {
+ if (!Swig_typemap_apply(pattern, apattern)) {
+ Swig_warning(WARN_TYPEMAP_APPLY_UNDEF, input_file, line_number, "Can't apply (%s). No typemaps are defined.\n", ParmList_str(pattern));
+ }
+ }
+ c = nextSibling(c);
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::clearDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::clearDirective(Node *n) {
+ Node *p;
+ for (p = firstChild(n); p; p = nextSibling(p)) {
+ ParmList *pattern = Getattr(p, "pattern");
+ Swig_typemap_clear_apply(pattern);
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::constantDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::constantDirective(Node *n) {
+
+ if (CurrentClass && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ if (!GetFlag(n, "feature:allowexcept")) {
+ UnsetFlag(n, "feature:except");
+ }
+ if (Getattr(n, "feature:exceptvar")) {
+ Setattr(n, "feature:except", Getattr(n, "feature:exceptvar"));
+ }
+
+ if (!ImportMode) {
+ Swig_require("constantDirective", n, "name", "?value", NIL);
+ String *name = Getattr(n, "name");
+ String *value = Getattr(n, "value");
+ if (!value) {
+ value = Copy(name);
+ } else {
+ /* if (checkAttribute(n,"type","char")) {
+ value = NewString(value);
+ } else {
+ value = NewStringf("%(escape)s", value);
+ }
+ */
+ Setattr(n, "rawvalue", value);
+ value = NewStringf("%(escape)s", value);
+ if (!Len(value))
+ Append(value, "\\0");
+ /* Printf(stdout,"'%s' = '%s'\n", name, value); */
+ }
+ Setattr(n, "value", value);
+ this->constantWrapper(n);
+ Swig_restore(n);
+ return SWIG_OK;
+ }
+ return SWIG_NOWRAP;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::fragmentDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::fragmentDirective(Node *n) {
+ if (!(Getattr(n, "emitonly") && ImportMode))
+ Swig_fragment_register(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::importDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::importDirective(Node *n) {
+ int oldim = ImportMode;
+ ImportMode = IMPORT_MODE;
+ emit_children(n);
+ ImportMode = oldim;
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::includeDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::includeDirective(Node *n) {
+ emit_children(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::insertDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::insertDirective(Node *n) {
+ /* %insert directive */
+ if ((!ImportMode) || Getattr(n, "generated")) {
+ String *code = Getattr(n, "code");
+ String *section = Getattr(n, "section");
+ File *f = 0;
+ if (!section) { /* %{ ... %} */
+ f = Swig_filebyname("header");
+ } else {
+ f = Swig_filebyname(section);
+ }
+ if (f) {
+ Printf(f, "%s\n", code);
+ } else {
+ Swig_error(input_file, line_number, "Unknown target '%s' for %%insert directive.\n", section);
+ }
+ return SWIG_OK;
+ } else {
+ return SWIG_NOWRAP;
+ }
+}
+
+/* ----------------------------------------------------------------------
+ * Language::moduleDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::moduleDirective(Node *n) {
+ (void) n;
+ /* %module directive */
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::nativeDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::nativeDirective(Node *n) {
+ if (!ImportMode) {
+ return nativeWrapper(n);
+ } else {
+ return SWIG_NOWRAP;
+ }
+}
+
+/* ----------------------------------------------------------------------
+ * Language::pragmaDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::pragmaDirective(Node *n) {
+ /* %pragma directive */
+ if (!ImportMode) {
+ String *lan = Getattr(n, "lang");
+ String *name = Getattr(n, "name");
+ String *value = Getattr(n, "value");
+ swig_pragma(Char(lan), Char(name), Char(value));
+ /* pragma(Char(lan),Char(name),Char(value)); */
+ return SWIG_OK;
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::typemapDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::typemapDirective(Node *n) {
+ /* %typemap directive */
+ String *method = Getattr(n, "method");
+ String *code = Getattr(n, "code");
+ Parm *kwargs = Getattr(n, "kwargs");
+ Node *items = firstChild(n);
+ static int namewarn = 0;
+
+
+ if (code && (Strstr(code, "$source") || (Strstr(code, "$target")))) {
+ Swig_warning(WARN_TYPEMAP_SOURCETARGET, Getfile(n), Getline(n), "Deprecated typemap feature ($source/$target).\n");
+ if (!namewarn) {
+ Swig_warning(WARN_TYPEMAP_SOURCETARGET, Getfile(n), Getline(n), "The use of $source and $target in a typemap declaration is deprecated.\n\
+For typemaps related to argument input (in,ignore,default,arginit,check), replace\n\
+$source by $input and $target by $1. For typemaps related to return values (out,\n\
+argout,ret,except), replace $source by $1 and $target by $result. See the file\n\
+Doc/Manual/Typemaps.html for complete details.\n");
+ namewarn = 1;
+ }
+ }
+
+ if (Strcmp(method, "except") == 0) {
+ Swig_warning(WARN_DEPRECATED_EXCEPT_TM, Getfile(n), Getline(n), "%%typemap(except) is deprecated. Use the %%exception directive.\n");
+ }
+
+ if (Strcmp(method, "in") == 0) {
+ Hash *k;
+ k = kwargs;
+ while (k) {
+ if (checkAttribute(k, "name", "numinputs")) {
+ if (!multiinput && (GetInt(k, "value") > 1)) {
+ Swig_error(Getfile(n), Getline(n), "Multiple-input typemaps (numinputs > 1) not supported by this target language module.\n");
+ return SWIG_ERROR;
+ }
+ break;
+ }
+ k = nextSibling(k);
+ }
+ if (!k) {
+ k = NewHash();
+ Setattr(k, "name", "numinputs");
+ Setattr(k, "value", "1");
+ set_nextSibling(k, kwargs);
+ Setattr(n, "kwargs", k);
+ kwargs = k;
+ }
+ }
+
+ if (Strcmp(method, "ignore") == 0) {
+ Swig_warning(WARN_DEPRECATED_IGNORE_TM, Getfile(n), Getline(n), "%%typemap(ignore) has been replaced by %%typemap(in,numinputs=0).\n");
+
+ Clear(method);
+ Append(method, "in");
+ Hash *k = NewHash();
+ Setattr(k, "name", "numinputs");
+ Setattr(k, "value", "0");
+ set_nextSibling(k, kwargs);
+ Setattr(n, "kwargs", k);
+ kwargs = k;
+ }
+
+ /* Replace $descriptor() macros */
+
+ if (code) {
+ Setfile(code, Getfile(n));
+ Setline(code, Getline(n));
+ Swig_cparse_replace_descriptor(code);
+ }
+
+ while (items) {
+ Parm *pattern = Getattr(items, "pattern");
+ Parm *parms = Getattr(items, "parms");
+
+ if (code) {
+ Swig_typemap_register(method, pattern, code, parms, kwargs);
+ } else {
+ Swig_typemap_clear(method, pattern);
+ }
+ items = nextSibling(items);
+ }
+ return SWIG_OK;
+
+}
+
+/* ----------------------------------------------------------------------
+ * Language::typemapcopyDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::typemapcopyDirective(Node *n) {
+ String *method = Getattr(n, "method");
+ Parm *pattern = Getattr(n, "pattern");
+ Node *items = firstChild(n);
+ int nsrc = 0;
+ nsrc = ParmList_len(pattern);
+ while (items) {
+ ParmList *npattern = Getattr(items, "pattern");
+ if (nsrc != ParmList_len(npattern)) {
+ Swig_error(input_file, line_number, "Can't copy typemap. Number of types differ.\n");
+ } else {
+ if (Swig_typemap_copy(method, pattern, npattern) < 0) {
+ Swig_error(input_file, line_number, "Can't copy typemap (%s) %s = %s\n", method, ParmList_str(pattern), ParmList_str(npattern));
+ }
+ }
+ items = nextSibling(items);
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::typesDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::typesDirective(Node *n) {
+ Parm *parms = Getattr(n, "parms");
+ String *convcode = Getattr(n, "convcode"); /* optional user supplied conversion code for custom casting */
+ while (parms) {
+ SwigType *t = Getattr(parms, "type");
+ String *v = Getattr(parms, "value");
+ if (!v) {
+ SwigType_remember(t);
+ } else {
+ if (SwigType_issimple(t)) {
+ SwigType_inherit(t, v, 0, convcode);
+ }
+ }
+ parms = nextSibling(parms);
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::cDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::cDeclaration(Node *n) {
+
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ SwigType *decl = Getattr(n, "decl");
+ String *storage = Getattr(n, "storage");
+ Node *over;
+ File *f_header = 0;
+ SwigType *ty, *fullty;
+
+ if (Getattr(n, "feature:onlychildren")) {
+ if (GetFlag(n, "feature:ignore")) {
+ return SWIG_NOWRAP;
+ } else {
+ // Found an unignored templated method that has an empty template instantiation (%template())
+ // Ignore it unless it has been %rename'd
+ if (Strncmp(symname, "__dummy_", 8) == 0 && Cmp(storage, "typedef") != 0) {
+ SetFlag(n, "feature:ignore");
+ Swig_warning(WARN_LANG_TEMPLATE_METHOD_IGNORE, input_file, line_number,
+ "%%template() contains no name. Template method ignored: %s\n", Swig_name_decl(n));
+ return SWIG_NOWRAP;
+ }
+ }
+ }
+
+ /* discards nodes following the access control rules */
+ if (cplus_mode != PUBLIC || !is_public(n)) {
+ /* except for friends, they are not affected by access control */
+ int isfriend = Cmp(storage, "friend") == 0;
+ if (!isfriend) {
+ /* Check what the director needs. If the method is pure virtual, it is always needed.
+ * Also wrap non-virtual protected members if asked for (allprotected mode). */
+ if (!(directorsEnabled() && ((is_member_director(CurrentClass, n) && need_nonpublic_member(n)) || isNonVirtualProtectedAccess(n)))) {
+ return SWIG_NOWRAP;
+ }
+ // Prevent wrapping protected overloaded director methods more than once -
+ // This bit of code is only needed due to the cDeclaration call in classHandler()
+ String *wrapname = NewStringf("nonpublic_%s%s", symname, Getattr(n, "sym:overname"));
+ if (Getattr(CurrentClass, wrapname)) {
+ Delete(wrapname);
+ return SWIG_NOWRAP;
+ }
+ SetFlag(CurrentClass, wrapname);
+ Delete(wrapname);
+ }
+ }
+
+ if (Cmp(storage, "typedef") == 0) {
+ Swig_save("cDeclaration", n, "type", NIL);
+ SwigType *t = Copy(type);
+ if (t) {
+ SwigType_push(t, decl);
+ Setattr(n, "type", t);
+ typedefHandler(n);
+ }
+ Swig_restore(n);
+ return SWIG_OK;
+ }
+
+ /* If in import mode, we proceed no further */
+ if (ImportMode)
+ return SWIG_NOWRAP;
+
+ /* If we're in extend mode and there is code, replace the $descriptor macros */
+ if (Extend) {
+ String *code = Getattr(n, "code");
+ if (code) {
+ Setfile(code, Getfile(n));
+ Setline(code, Getline(n));
+ Swig_cparse_replace_descriptor(code);
+ }
+ }
+
+ /* Overloaded symbol check */
+ over = Swig_symbol_isoverloaded(n);
+ if (!overloading) {
+ if (over)
+ over = first_nontemplate(over);
+ if (over && (over != n)) {
+ Swig_warning(WARN_LANG_OVERLOAD_DECL, input_file, line_number, "Overloaded declaration ignored. %s\n", Swig_name_decl(n));
+ Swig_warning(WARN_LANG_OVERLOAD_DECL, Getfile(over), Getline(over), "Previous declaration is %s\n", Swig_name_decl(over));
+ return SWIG_NOWRAP;
+ }
+ }
+
+ if (!validIdentifier(symname)) {
+ Swig_warning(WARN_LANG_IDENTIFIER, input_file, line_number, "Can't wrap '%s' unless renamed to a valid identifier.\n", SwigType_namestr(symname));
+ return SWIG_NOWRAP;
+ }
+
+ ty = NewString(type);
+ SwigType_push(ty, decl);
+ fullty = SwigType_typedef_resolve_all(ty);
+ if (SwigType_isfunction(fullty)) {
+ if (!SwigType_isfunction(ty)) {
+ Delete(ty);
+ ty = fullty;
+ fullty = 0;
+ ParmList *parms = SwigType_function_parms(ty, n);
+ Setattr(n, "parms", parms);
+ }
+ /* Transform the node into a 'function' node and emit */
+ if (!CurrentClass) {
+ f_header = Swig_filebyname("header");
+
+ if (AddExtern) {
+ if (f_header) {
+ if (Swig_storage_isextern(n) || (ForceExtern && !storage)) {
+ /* we don't need the 'extern' part in the C/C++ declaration,
+ and it produces some problems when namespace and SUN
+ Studio is used.
+
+ Printf(f_header,"extern %s", SwigType_str(ty,name));
+
+ In fact generating extern declarations is quite error prone and is
+ no longer the default. Getting it right seems impossible with namespaces
+ and default arguments and when a method is declared with the various Windows
+ calling conventions - SWIG doesn't understand Windows (non standard) calling
+ conventions in the first place, so can't regenerate them.
+ */
+ String *str = SwigType_str(ty, name);
+ Printf(f_header, "%s", str);
+ Delete(str);
+ {
+ DOH *t = Getattr(n, "throws");
+ if (t) {
+ Printf(f_header, " throw(");
+ while (t) {
+ Printf(f_header, "%s", Getattr(t, "type"));
+ t = nextSibling(t);
+ if (t)
+ Printf(f_header, ",");
+ }
+ Printf(f_header, ")");
+ }
+ }
+ Printf(f_header, ";\n");
+ } else if (Swig_storage_isexternc(n)) {
+ /* here 'extern "C"' is needed */
+ String *str = SwigType_str(ty, name);
+ Printf(f_header, "extern \"C\" %s;\n", str);
+ Delete(str);
+ }
+ }
+ }
+ }
+ /* This needs to check qualifiers */
+ if (SwigType_isqualifier(ty)) {
+ SwigType *qual = SwigType_pop(ty);
+ Setattr(n, "qualifier", qual);
+ Delete(qual);
+ }
+ Delete(SwigType_pop_function(ty));
+ DohIncref(type);
+ Setattr(n, "type", ty);
+
+ functionHandler(n);
+
+ Setattr(n, "type", type);
+ Delete(ty);
+ Delete(type);
+ return SWIG_OK;
+ } else {
+ /* Some kind of variable declaration */
+ String *declaration = Copy(decl);
+ Delattr(n, "decl");
+ if (!CurrentClass) {
+ if (Swig_storage_isextern(n) || ForceExtern) {
+ if (AddExtern) {
+ f_header = Swig_filebyname("header");
+ if (f_header) {
+ String *str = SwigType_str(ty, name);
+ Printf(f_header, "%s %s;\n", Getattr(n, "storage"), str);
+ Delete(str);
+ }
+ }
+ }
+ }
+ if (!SwigType_ismutable(ty)) {
+ SetFlag(n, "feature:immutable");
+ }
+ /* If an array and elements are const, then read-only */
+ if (SwigType_isarray(ty)) {
+ SwigType *tya = SwigType_array_type(ty);
+ if (SwigType_isconst(tya)) {
+ SetFlag(n, "feature:immutable");
+ }
+ Delete(tya);
+ }
+ DohIncref(type);
+ Setattr(n, "type", ty);
+ variableHandler(n);
+ Setattr(n, "type", type);
+ Setattr(n, "decl", declaration);
+ Delete(ty);
+ Delete(type);
+ Delete(fullty);
+ return SWIG_OK;
+ }
+}
+
+/* ----------------------------------------------------------------------
+ * Language::functionHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::functionHandler(Node *n) {
+ String *storage = Getattr(n, "storage");
+ int isfriend = CurrentClass && Cmp(storage, "friend") == 0;
+ int isstatic = CurrentClass && Swig_storage_isstatic(n) && !(SmartPointer && Getattr(n, "allocate:smartpointeraccess"));
+ Parm *p = Getattr(n, "parms");
+ if (GetFlag(n, "feature:del")) {
+ /* the method acts like a delete operator, ie, we need to disown the parameter */
+ if (CurrentClass && !isstatic && !isfriend) {
+ SetFlag(n, "feature:self:disown");
+ } else {
+ if (p)
+ SetFlag(p, "wrap:disown");
+ }
+ }
+ if (!CurrentClass) {
+ globalfunctionHandler(n);
+ } else {
+ if (isstatic) {
+ staticmemberfunctionHandler(n);
+ } else if (isfriend) {
+ int oldInClass = InClass;
+ InClass = 0;
+ globalfunctionHandler(n);
+ InClass = oldInClass;
+ } else {
+ // This is a member function, set a flag so the documentation type is correct
+ SetFlag(n, "memberfunction");
+ Node *explicit_n = 0;
+ if (directorsEnabled() && is_member_director(CurrentClass, n) && !extraDirectorProtectedCPPMethodsRequired()) {
+ bool virtual_but_not_pure_virtual = (!(Cmp(storage, "virtual")) && (Cmp(Getattr(n, "value"), "0") != 0));
+ if (virtual_but_not_pure_virtual) {
+ // Add additional wrapper which makes an explicit call to the virtual method (ie not a virtual call)
+ explicit_n = Copy(n);
+ String *new_symname = Copy(Getattr(n, "sym:name"));
+ String *suffix = Getattr(parentNode(n), "sym:name");
+ Printv(new_symname, "SwigExplicit", suffix, NIL);
+ Setattr(explicit_n, "sym:name", new_symname);
+ Delattr(explicit_n, "storage");
+ Delattr(explicit_n, "override");
+ Delattr(explicit_n, "hides");
+ SetFlag(explicit_n, "explicitcall");
+ Setattr(n, "explicitcallnode", explicit_n);
+ }
+ }
+
+ memberfunctionHandler(n);
+
+ if (explicit_n) {
+ memberfunctionHandler(explicit_n);
+ Delattr(explicit_n, "explicitcall");
+ Delete(explicit_n);
+ }
+ }
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::globalfunctionHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::globalfunctionHandler(Node *n) {
+
+ Swig_require("globalfunctionHandler", n, "name", "sym:name", "type", "?parms", NIL);
+
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ ParmList *parms = Getattr(n, "parms");
+
+ /* Check for callback mode */
+ String *cb = GetFlagAttr(n, "feature:callback");
+ if (cb) {
+ String *cbname = Getattr(n, "feature:callback:name");
+ if (!cbname) {
+ cbname = NewStringf(cb, symname);
+ Setattr(n, "feature:callback:name", cbname);
+ }
+
+ callbackfunctionHandler(n);
+ if (Cmp(cbname, symname) == 0) {
+ Delete(cbname);
+ Swig_restore(n);
+ return SWIG_NOWRAP;
+ }
+ Delete(cbname);
+ }
+ Setattr(n, "parms", nonvoid_parms(parms));
+
+ String *extendname = Getattr(n, "extendname");
+ String *call = Swig_cfunction_call(extendname ? extendname : name, parms);
+ String *cres = Swig_cresult(type, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ Delete(cres);
+ Delete(call);
+ functionWrapper(n);
+
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::callbackfunctionHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::callbackfunctionHandler(Node *n) {
+ Swig_require("callbackfunctionHandler", n, "name", "*sym:name", "*type", "?value", NIL);
+ String *type = Getattr(n, "type");
+ String *name = Getattr(n, "name");
+ String *parms = Getattr(n, "parms");
+ String *cbname = Getattr(n, "feature:callback:name");
+ String *calltype = NewStringf("(%s (*)(%s))(%s)", SwigType_str(type, 0), ParmList_str(parms), SwigType_namestr(name));
+ SwigType *cbty = Copy(type);
+ SwigType_add_function(cbty, parms);
+ SwigType_add_pointer(cbty);
+
+ Setattr(n, "sym:name", cbname);
+ Setattr(n, "type", cbty);
+ Setattr(n, "value", calltype);
+
+ Node *ns = symbolLookup(cbname);
+ if (!ns)
+ constantWrapper(n);
+
+ Delete(cbty);
+
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::memberfunctionHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::memberfunctionHandler(Node *n) {
+
+ Swig_require("memberfunctionHandler", n, "*name", "*sym:name", "*type", "?parms", "?value", NIL);
+
+ String *storage = Getattr(n, "storage");
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ ParmList *parms = Getattr(n, "parms");
+ String *cb = GetFlagAttr(n, "feature:callback");
+
+ if (Cmp(storage, "virtual") == 0) {
+ if (Cmp(value, "0") == 0) {
+ IsVirtual = PURE_VIRTUAL;
+ } else {
+ IsVirtual = PLAIN_VIRTUAL;
+ }
+ } else {
+ IsVirtual = 0;
+ }
+ if (cb) {
+ Node *cbn = NewHash();
+ String *cbname = Getattr(n, "feature:callback:name");
+ if (!cbname) {
+ cbname = NewStringf(cb, symname);
+ }
+
+ SwigType *cbty = Copy(type);
+ SwigType_add_function(cbty, parms);
+ SwigType_add_memberpointer(cbty, ClassName);
+ String *cbvalue = NewStringf("&%s::%s", ClassName, name);
+ Setattr(cbn, "sym:name", cbname);
+ Setattr(cbn, "type", cbty);
+ Setattr(cbn, "value", cbvalue);
+ Setattr(cbn, "name", name);
+ Setfile(cbn, Getfile(n));
+ Setline(cbn, Getline(n));
+
+ memberconstantHandler(cbn);
+ Setattr(n, "feature:callback:name", Swig_name_member(NSpace, ClassPrefix, cbname));
+
+ Delete(cb);
+ Delete(cbn);
+ Delete(cbvalue);
+ Delete(cbty);
+ Delete(cbname);
+ if (Cmp(cbname, symname) == 0) {
+ Swig_restore(n);
+ return SWIG_NOWRAP;
+ }
+ }
+
+ String *fname = Swig_name_member(NSpace, ClassPrefix, symname);
+ if (Extend && SmartPointer) {
+ if (!Getattr(n, "extendsmartclassname")) {
+ Setattr(n, "extendsmartclassname", Getattr(CurrentClass, "allocate:smartpointerpointeeclassname"));
+ }
+ }
+ // Set up the type for the cast to this class for use when wrapping const director (virtual) methods.
+ // Note: protected director methods or when allprotected mode turned on.
+ String *director_type = 0;
+ if (!is_public(n) && (is_member_director(CurrentClass, n) || GetFlag(n, "explicitcall") || isNonVirtualProtectedAccess(n))) {
+ director_type = Copy(DirectorClassName);
+ String *qualifier = Getattr(n, "qualifier");
+ if (qualifier)
+ SwigType_push(director_type, qualifier);
+ SwigType_add_pointer(director_type);
+ }
+
+ int DirectorExtraCall = 0;
+ if (directorsEnabled() && is_member_director(CurrentClass, n) && !SmartPointer)
+ if (extraDirectorProtectedCPPMethodsRequired())
+ DirectorExtraCall = CWRAP_DIRECTOR_TWO_CALLS;
+
+ if (GetFlag(n, "explicitcall"))
+ DirectorExtraCall = CWRAP_DIRECTOR_ONE_CALL;
+
+ int extendmember = GetFlag(n, "isextendmember") ? Extend : 0;
+ int flags = Getattr(n, "template") ? extendmember | SmartPointer : Extend | SmartPointer | DirectorExtraCall;
+ Swig_MethodToFunction(n, NSpace, ClassType, flags, director_type, is_member_director(CurrentClass, n));
+ Setattr(n, "sym:name", fname);
+ /* Explicitly save low-level and high-level documentation names */
+ Setattr(n, "doc:low:name", fname);
+ Setattr(n, "doc:high:name", symname);
+
+ functionWrapper(n);
+
+ Delete(director_type);
+ Delete(fname);
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::staticmemberfunctionHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::staticmemberfunctionHandler(Node *n) {
+
+ Swig_require("staticmemberfunctionHandler", n, "*name", "*sym:name", "*type", NIL);
+ Swig_save("staticmemberfunctionHandler", n, "storage", NIL);
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ ParmList *parms = Getattr(n, "parms");
+ String *cb = GetFlagAttr(n, "feature:callback");
+ String *cname, *mrename;
+
+ if (!Extend) {
+ Node *sb = Getattr(n, "cplus:staticbase");
+ String *sname = Getattr(sb, "name");
+ if (isNonVirtualProtectedAccess(n))
+ cname = NewStringf("%s::%s", DirectorClassName, name);
+ else
+ cname = NewStringf("%s::%s", sname, name);
+ } else {
+ String *mname = Swig_name_mangle(ClassName);
+ cname = Swig_name_member(NSpace, mname, name);
+ Delete(mname);
+ }
+ mrename = Swig_name_member(NSpace, ClassPrefix, symname);
+
+ if (Extend) {
+ String *code = Getattr(n, "code");
+ String *defaultargs = Getattr(n, "defaultargs");
+ String *mangled = Swig_name_mangle(mrename);
+ Delete(mrename);
+ mrename = mangled;
+
+ if (Getattr(n, "sym:overloaded") && code) {
+ Append(cname, Getattr(defaultargs ? defaultargs : n, "sym:overname"));
+ }
+
+ if (!defaultargs && code) {
+ /* Hmmm. An added static member. We have to create a little wrapper for this */
+ String *mangled_cname = Swig_name_mangle(cname);
+ Swig_add_extension_code(n, mangled_cname, parms, type, code, CPlusPlus, 0);
+ Setattr(n, "extendname", mangled_cname);
+ Delete(mangled_cname);
+ }
+ }
+
+ Setattr(n, "name", cname);
+ Setattr(n, "sym:name", mrename);
+ /* Explicitly save low-level and high-level documentation names */
+ Setattr(n, "doc:low:name", mrename);
+ Setattr(n, "doc:high:name", symname);
+
+ if (cb) {
+ String *cbname = NewStringf(cb, symname);
+ Setattr(n, "feature:callback:name", Swig_name_member(NSpace, ClassPrefix, cbname));
+ Setattr(n, "feature:callback:staticname", name);
+ }
+ Delattr(n, "storage");
+
+ globalfunctionHandler(n);
+
+ Delete(cname);
+ Delete(mrename);
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::variableHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::variableHandler(Node *n) {
+
+ /* If not a smart-pointer access or added method. We clear
+ feature:except. There is no way C++ or C would throw
+ an exception merely for accessing a member data.
+
+ Caveat: Some compilers seem to route attribute access through
+ methods which can generate exceptions. The feature:allowexcept
+ allows this. Also, the feature:exceptvar can be used to match
+ only variables.
+ */
+ if (!(Extend | SmartPointer)) {
+ if (!GetFlag(n, "feature:allowexcept")) {
+ UnsetFlag(n, "feature:except");
+ }
+ if (Getattr(n, "feature:exceptvar")) {
+ Setattr(n, "feature:except", Getattr(n, "feature:exceptvar"));
+ }
+ }
+
+ if (!CurrentClass) {
+ globalvariableHandler(n);
+ } else {
+ Swig_save("variableHandler", n, "feature:immutable", NIL);
+ if (SmartPointer) {
+ /* If a smart-pointer and it's a constant access, we have to set immutable */
+ if (!Getattr(CurrentClass, "allocate:smartpointermutable")) {
+ SetFlag(n, "feature:immutable");
+ }
+ }
+ if (Swig_storage_isstatic(n) && !(SmartPointer && Getattr(n, "allocate:smartpointeraccess"))) {
+ staticmembervariableHandler(n);
+ } else {
+ membervariableHandler(n);
+ }
+ Swig_restore(n);
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::globalvariableHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::globalvariableHandler(Node *n) {
+ variableWrapper(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::membervariableHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::membervariableHandler(Node *n) {
+
+ Swig_require("membervariableHandler", n, "*name", "*sym:name", "*type", NIL);
+ Swig_save("membervariableHandler", n, "parms", NIL);
+
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+
+ if (!AttributeFunctionGet) {
+ String *mname = Swig_name_member(0, ClassPrefix, symname);
+ String *mrename_get = Swig_name_get(NSpace, mname);
+ String *mrename_set = Swig_name_set(NSpace, mname);
+ Delete(mname);
+
+ /* Create a function to set the value of the variable */
+
+ int assignable = is_assignable(n);
+
+ if (SmartPointer) {
+ if (!Getattr(CurrentClass, "allocate:smartpointermutable")) {
+ assignable = 0;
+ }
+ }
+
+ if (assignable) {
+ int make_set_wrapper = 1;
+ String *tm = 0;
+ String *target = 0;
+ if (!Extend) {
+ if (SmartPointer) {
+ if (Swig_storage_isstatic(n)) {
+ Node *sn = Getattr(n, "cplus:staticbase");
+ String *base = Getattr(sn, "name");
+ target = NewStringf("%s::%s", base, name);
+ } else {
+ String *pname = Swig_cparm_name(0, 0);
+ target = NewStringf("(*%s)->%s", pname, name);
+ Delete(pname);
+ }
+ } else {
+ String *pname = isNonVirtualProtectedAccess(n) ? NewString("darg") : Swig_cparm_name(0, 0);
+ target = NewStringf("%s->%s", pname, name);
+ Delete(pname);
+ }
+
+ // This is an input type typemap lookup and so it should not use Node n
+ // otherwise qualification is done on the parameter name for the setter function
+ Parm *nin = NewParm(type, name, n);
+ tm = Swig_typemap_lookup("memberin", nin, target, 0);
+ Delete(nin);
+ }
+
+ int flags = Extend | SmartPointer | use_naturalvar_mode(n);
+ if (isNonVirtualProtectedAccess(n))
+ flags = flags | CWRAP_ALL_PROTECTED_ACCESS;
+
+ Swig_MembersetToFunction(n, ClassType, flags);
+ Setattr(n, "memberset", "1");
+ if (!Extend) {
+ /* Check for a member in typemap here */
+
+ if (!tm) {
+ if (SwigType_isarray(type)) {
+ Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(type, 0));
+ make_set_wrapper = 0;
+ }
+ } else {
+ String *pname0 = Swig_cparm_name(0, 0);
+ String *pname1 = Swig_cparm_name(0, 1);
+ Replace(tm, "$source", pname1, DOH_REPLACE_ANY);
+ Replace(tm, "$target", target, DOH_REPLACE_ANY);
+ Replace(tm, "$input", pname1, DOH_REPLACE_ANY);
+ Replace(tm, "$self", pname0, DOH_REPLACE_ANY);
+ Setattr(n, "wrap:action", tm);
+ Delete(tm);
+ Delete(pname0);
+ Delete(pname1);
+ }
+ Delete(target);
+ }
+ if (make_set_wrapper) {
+ Setattr(n, "sym:name", mrename_set);
+ functionWrapper(n);
+ } else {
+ SetFlag(n, "feature:immutable");
+ }
+ /* Restore parameters */
+ Setattr(n, "type", type);
+ Setattr(n, "name", name);
+ Setattr(n, "sym:name", symname);
+ Delattr(n, "memberset");
+
+ /* Delete all attached typemaps and typemap attributes */
+ Iterator ki;
+ for (ki = First(n); ki.key; ki = Next(ki)) {
+ if (Strncmp(ki.key, "tmap:", 5) == 0)
+ Delattr(n, ki.key);
+ }
+ }
+ /* Emit get function */
+ {
+ int flags = Extend | SmartPointer | use_naturalvar_mode(n);
+ if (isNonVirtualProtectedAccess(n))
+ flags = flags | CWRAP_ALL_PROTECTED_ACCESS;
+ Swig_MembergetToFunction(n, ClassType, flags);
+ Setattr(n, "sym:name", mrename_get);
+ Setattr(n, "memberget", "1");
+ functionWrapper(n);
+ Delattr(n, "memberget");
+ }
+ Delete(mrename_get);
+ Delete(mrename_set);
+
+ } else {
+
+ /* This code is used to support the attributefunction directive
+ where member variables are converted automagically to
+ accessor functions */
+
+#if 0
+ Parm *p;
+ String *gname;
+ SwigType *vty;
+ p = NewParm(type, 0, n);
+ gname = NewStringf(AttributeFunctionGet, symname);
+ if (!Extend) {
+ ActionFunc = Copy(Swig_cmemberget_call(name, type));
+ cpp_member_func(Char(gname), Char(gname), type, 0);
+ Delete(ActionFunc);
+ } else {
+ String *cname = Swig_name_get(NSpace, name);
+ cpp_member_func(Char(cname), Char(gname), type, 0);
+ Delete(cname);
+ }
+ Delete(gname);
+ if (!GetFlag(n, "feature:immutable")) {
+ gname = NewStringf(AttributeFunctionSet, symname);
+ vty = NewString("void");
+ if (!Extend) {
+ ActionFunc = Copy(Swig_cmemberset_call(name, type));
+ cpp_member_func(Char(gname), Char(gname), vty, p);
+ Delete(ActionFunc);
+ } else {
+ String *cname = Swig_name_set(NSpace, name);
+ cpp_member_func(Char(cname), Char(gname), vty, p);
+ Delete(cname);
+ }
+ Delete(gname);
+ }
+ ActionFunc = 0;
+#endif
+ }
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::staticmembervariableHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::staticmembervariableHandler(Node *n) {
+ Swig_require("staticmembervariableHandler", n, "*name", "*sym:name", "*type", "?value", NIL);
+ String *value = Getattr(n, "value");
+ String *classname = !SmartPointer ? (isNonVirtualProtectedAccess(n) ? DirectorClassName : ClassName) : Getattr(CurrentClass, "allocate:smartpointerpointeeclassname");
+
+ if (!value || !Getattr(n, "hasconsttype")) {
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *cname, *mrename;
+
+ /* Create the variable name */
+ mrename = Swig_name_member(0, ClassPrefix, symname);
+ cname = NewStringf("%s::%s", classname, name);
+
+ Setattr(n, "sym:name", mrename);
+ Setattr(n, "name", cname);
+
+ /* Wrap as an ordinary global variable */
+ variableWrapper(n);
+
+ Delete(mrename);
+ Delete(cname);
+ } else {
+
+ /* This is a C++ static member declaration with an initializer and it's const.
+ Certain C++ compilers optimize this out so that there is no linkage to a
+ memory address. Example:
+
+ class Foo {
+ public:
+ static const int x = 3;
+ };
+
+ Some discussion of this in section 9.4 of the C++ draft standard.
+
+ Also, we have to manage the case:
+
+ class Foo {
+ public:
+ %extend {
+ static const int x = 3;
+ }
+ };
+
+ in which there's no actual Foo::x variable to refer to. In this case,
+ the best we can do is to wrap the given value verbatim.
+ */
+
+
+ String *name = Getattr(n, "name");
+ String *cname = NewStringf("%s::%s", classname, name);
+ if (Extend) {
+ /* the variable is a synthesized one.
+ There's nothing we can do; we just keep the given value */
+ } else {
+ /* we refer to the value as Foo::x */
+ String *value = SwigType_namestr(cname);
+ Setattr(n, "value", value);
+ }
+
+ SwigType *t1 = SwigType_typedef_resolve_all(Getattr(n, "type"));
+ SwigType *t2 = SwigType_strip_qualifiers(t1);
+ Setattr(n, "type", t2);
+ Delete(t1);
+ Delete(t2);
+ SetFlag(n, "wrappedasconstant");
+ memberconstantHandler(n);
+ Delete(cname);
+ }
+
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+
+/* ----------------------------------------------------------------------
+ * Language::externDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::externDeclaration(Node *n) {
+ return emit_children(n);
+}
+
+/* ----------------------------------------------------------------------
+ * Language::enumDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::enumDeclaration(Node *n) {
+ if (CurrentClass && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ String *oldNSpace = NSpace;
+ NSpace = Getattr(n, "sym:nspace");
+
+ String *oldEnumClassPrefix = EnumClassPrefix;
+ if (GetFlag(n, "scopedenum")) {
+ assert(Getattr(n, "sym:name"));
+ assert(Getattr(n, "name"));
+ EnumClassPrefix = ClassPrefix ? NewStringf("%s_", ClassPrefix) : NewString("");
+ Printv(EnumClassPrefix, Getattr(n, "sym:name"), NIL);
+ EnumClassName = Copy(Getattr(n, "name"));
+ }
+ if (!ImportMode) {
+ emit_children(n);
+ }
+
+ if (GetFlag(n, "scopedenum")) {
+ Delete(EnumClassName);
+ EnumClassName = 0;
+ Delete(EnumClassPrefix);
+ EnumClassPrefix = oldEnumClassPrefix;
+ }
+ NSpace = oldNSpace;
+
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::enumvalueDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::enumvalueDeclaration(Node *n) {
+ if (CurrentClass && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ Swig_require("enumvalueDeclaration", n, "*name", "*sym:name", "?value", NIL);
+ String *value = Getattr(n, "value");
+ String *name = Getattr(n, "name");
+ String *tmpValue;
+
+ if (value)
+ tmpValue = NewString(value);
+ else
+ tmpValue = NewString(name);
+ Setattr(n, "value", tmpValue);
+
+ Node *parent = parentNode(n);
+ if (GetFlag(parent, "scopedenum")) {
+ String *symname = Swig_name_member(0, Getattr(parent, "sym:name"), Getattr(n, "sym:name"));
+ Setattr(n, "sym:name", symname);
+ Delete(symname);
+ }
+
+ if (!CurrentClass || !cparse_cplusplus) {
+ Setattr(n, "name", tmpValue); /* for wrapping of enums in a namespace when emit_action is used */
+ constantWrapper(n);
+ } else {
+ memberconstantHandler(n);
+ }
+
+ Delete(tmpValue);
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::enumforwardDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::enumforwardDeclaration(Node *n) {
+ (void) n;
+ if (GetFlag(n, "enumMissing"))
+ enumDeclaration(n); // Generate an empty enum in target language
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::memberconstantHandler()
+ * ----------------------------------------------------------------------------- */
+
+int Language::memberconstantHandler(Node *n) {
+
+ Swig_require("memberconstantHandler", n, "*name", "*sym:name", "value", NIL);
+
+ if (!GetFlag(n, "feature:allowexcept")) {
+ UnsetFlag(n, "feature:except");
+ }
+ if (Getattr(n, "feature:exceptvar")) {
+ Setattr(n, "feature:except", Getattr(n, "feature:exceptvar"));
+ }
+
+ String *enumvalue_symname = Getattr(n, "enumvalueDeclaration:sym:name"); // Only set if a strongly typed enum
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *value = Getattr(n, "value");
+
+ String *mrename = Swig_name_member(0, EnumClassPrefix, enumvalue_symname ? enumvalue_symname : symname);
+ Setattr(n, "sym:name", mrename);
+
+ String *new_name = 0;
+ if (Extend)
+ new_name = Copy(value);
+ else if (EnumClassName)
+ new_name = NewStringf("%s::%s", isNonVirtualProtectedAccess(n) ? DirectorClassName : EnumClassName, name);
+ else
+ new_name = NewStringf("%s::%s", isNonVirtualProtectedAccess(n) ? DirectorClassName : ClassName, name);
+ Setattr(n, "name", new_name);
+
+ constantWrapper(n);
+ Delete(mrename);
+ Delete(new_name);
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::typedefHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::typedefHandler(Node *n) {
+ /* since this is a recurring issue, we are going to remember the
+ typedef pointer, if already it is not a pointer or reference, as
+ in
+
+ typedef void NT;
+ int func(NT *p);
+
+ see director_basic.i for example.
+ */
+ SwigType *name = Getattr(n, "name");
+ SwigType *decl = Getattr(n, "decl");
+ if (!SwigType_ispointer(decl) && !SwigType_isreference(decl)) {
+ SwigType *pname = Copy(name);
+ SwigType_add_pointer(pname);
+ SwigType_remember(pname);
+ Delete(pname);
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorMethod()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorMethod(Node *n, Node *parent, String *super) {
+ (void) n;
+ (void) parent;
+ (void) super;
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorConstructor()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorConstructor(Node *n) {
+ (void) n;
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorDefaultConstructor()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorDefaultConstructor(Node *n) {
+ (void) n;
+ return SWIG_OK;
+}
+
+static String *vtable_method_id(Node *n) {
+ String *nodeType = Getattr(n, "nodeType");
+ int is_destructor = (Cmp(nodeType, "destructor") == 0);
+ if (is_destructor)
+ return 0;
+ String *name = Getattr(n, "name");
+ String *decl = Getattr(n, "decl");
+ String *local_decl = SwigType_typedef_resolve_all(decl);
+ String *tmp = SwigType_pop_function(local_decl);
+ Delete(local_decl);
+ local_decl = tmp;
+ Node *method_id = NewStringf("%s|%s", name, local_decl);
+ Delete(local_decl);
+ return method_id;
+}
+
+
+/* ----------------------------------------------------------------------
+ * Language::unrollVirtualMethods()
+ * ---------------------------------------------------------------------- */
+int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_director, int &virtual_destructor, int protectedbase) {
+ Node *ni;
+ String *nodeType;
+ String *classname;
+ String *decl;
+ bool first_base = false;
+ // recurse through all base classes to build the vtable
+ List *bl = Getattr(n, "bases");
+ if (bl) {
+ Iterator bi;
+ for (bi = First(bl); bi.item; bi = Next(bi)) {
+ if (first_base && !director_multiple_inheritance)
+ break;
+ unrollVirtualMethods(bi.item, parent, vm, default_director, virtual_destructor);
+ first_base = true;
+ }
+ }
+ // recurse through all protected base classes to build the vtable, as needed
+ bl = Getattr(n, "protectedbases");
+ if (bl) {
+ Iterator bi;
+ for (bi = First(bl); bi.item; bi = Next(bi)) {
+ if (first_base && !director_multiple_inheritance)
+ break;
+ unrollVirtualMethods(bi.item, parent, vm, default_director, virtual_destructor, 1);
+ first_base = true;
+ }
+ }
+ // find the methods that need directors
+ classname = Getattr(n, "name");
+ for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
+ /* we only need to check the virtual members */
+ nodeType = Getattr(ni, "nodeType");
+ int is_using = (Cmp(nodeType, "using") == 0);
+ Node *nn = is_using ? firstChild(ni) : ni; /* assume there is only one child node for "using" nodes */
+ if (is_using) {
+ if (nn)
+ nodeType = Getattr(nn, "nodeType");
+ else
+ continue; // A private "using" node
+ }
+ if (!checkAttribute(nn, "storage", "virtual"))
+ continue;
+ if (GetFlag(nn, "final"))
+ continue;
+ /* we need to add methods(cdecl) and destructor (to check for throw decl) */
+ int is_destructor = (Cmp(nodeType, "destructor") == 0);
+ if ((Cmp(nodeType, "cdecl") == 0) || is_destructor) {
+ decl = Getattr(nn, "decl");
+ /* extra check for function type and proper access */
+ if (SwigType_isfunction(decl) && (((!protectedbase || dirprot_mode()) && is_public(nn)) || need_nonpublic_member(nn))) {
+ String *name = Getattr(nn, "name");
+ Node *method_id = is_destructor ? NewStringf("~destructor") : vtable_method_id(nn);
+ /* Make sure that the new method overwrites the existing: */
+ int len = Len(vm);
+ const int DO_NOT_REPLACE = -1;
+ int replace = DO_NOT_REPLACE;
+ for (int i = 0; i < len; i++) {
+ Node *item = Getitem(vm, i);
+ String *check_vmid = Getattr(item, "vmid");
+
+ if (Strcmp(method_id, check_vmid) == 0) {
+ replace = i;
+ break;
+ }
+ }
+ /* filling a new method item */
+ String *fqdname = NewStringf("%s::%s", classname, name);
+ Hash *item = NewHash();
+ Setattr(item, "fqdname", fqdname);
+ Node *m = Copy(nn);
+
+ /* Store the complete return type - needed for non-simple return types (pointers, references etc.) */
+ SwigType *ty = NewString(Getattr(m, "type"));
+ SwigType_push(ty, decl);
+ if (SwigType_isqualifier(ty)) {
+ Delete(SwigType_pop(ty));
+ }
+ Delete(SwigType_pop_function(ty));
+ Setattr(m, "returntype", ty);
+
+ String *mname = NewStringf("%s::%s", Getattr(parent, "name"), name);
+ /* apply the features of the original method found in the base class */
+ Swig_features_get(Swig_cparse_features(), 0, mname, Getattr(m, "decl"), m);
+ Setattr(item, "methodNode", m);
+ Setattr(item, "vmid", method_id);
+ if (replace == DO_NOT_REPLACE)
+ Append(vm, item);
+ else
+ Setitem(vm, replace, item);
+ Setattr(nn, "directorNode", m);
+
+ Delete(mname);
+ }
+ if (is_destructor) {
+ virtual_destructor = 1;
+ }
+ }
+ }
+
+ /*
+ We delete all the nodirector methods. This prevents the
+ generation of 'empty' director classes.
+
+ But this has to be done outside the previous 'for'
+ and the recursive loop!.
+ */
+ if (n == parent) {
+ int len = Len(vm);
+ for (int i = 0; i < len; i++) {
+ Node *item = Getitem(vm, i);
+ Node *m = Getattr(item, "methodNode");
+ /* retrieve the director features */
+ int mdir = GetFlag(m, "feature:director");
+ int mndir = GetFlag(m, "feature:nodirector");
+ /* 'nodirector' has precedence over 'director' */
+ int dir = (mdir || mndir) ? (mdir && !mndir) : 1;
+ /* check if the method was found only in a base class */
+ Node *p = Getattr(m, "parentNode");
+ if (p != n) {
+ Node *c = Copy(m);
+ Setattr(c, "parentNode", n);
+ int cdir = GetFlag(c, "feature:director");
+ int cndir = GetFlag(c, "feature:nodirector");
+ dir = (cdir || cndir) ? (cdir && !cndir) : dir;
+ Delete(c);
+ }
+ if (dir) {
+ /* be sure the 'nodirector' feature is disabled */
+ if (mndir)
+ Delattr(m, "feature:nodirector");
+ } else {
+ /* or just delete from the vm, since is not a director method */
+ Delitem(vm, i);
+ len--;
+ i--;
+ }
+ }
+ }
+
+ return SWIG_OK;
+}
+
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorDisown()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorDisown(Node *n) {
+ Node *disown = NewHash();
+ String *mrename;
+ String *symname = Getattr(n, "sym:name");
+ mrename = Swig_name_disown(NSpace, symname);
+ String *type = NewString(ClassType);
+ String *name = NewString("self");
+ SwigType_add_pointer(type);
+ Parm *p = NewParm(type, name, n);
+ Delete(name);
+ Delete(type);
+ type = NewString("void");
+ String *action = NewString("");
+ Printv(action, "{\n", "Swig::Director *director = SWIG_DIRECTOR_CAST(arg1);\n", "if (director) director->swig_disown();\n", "}\n", NULL);
+ Setfile(disown, Getfile(n));
+ Setline(disown, Getline(n));
+ Setattr(disown, "wrap:action", action);
+ Setattr(disown, "name", mrename);
+ Setattr(disown, "sym:name", mrename);
+ Setattr(disown, "type", type);
+ Setattr(disown, "parms", p);
+ Delete(action);
+ Delete(mrename);
+ Delete(type);
+ Delete(p);
+
+ functionWrapper(disown);
+ Delete(disown);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorConstructors()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorConstructors(Node *n) {
+ Node *ni;
+ String *nodeType;
+ Node *parent = Swig_methodclass(n);
+ int default_ctor = Getattr(parent, "allocate:default_constructor") ? 1 : 0;
+ int protected_ctor = 0;
+ int constructor = 0;
+
+ /* emit constructors */
+ for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
+ nodeType = Getattr(ni, "nodeType");
+ if (Cmp(nodeType, "constructor") == 0) {
+ if (GetFlag(ni, "feature:ignore"))
+ continue;
+
+ Parm *parms = Getattr(ni, "parms");
+ if (is_public(ni)) {
+ /* emit public constructor */
+ classDirectorConstructor(ni);
+ constructor = 1;
+ if (default_ctor)
+ default_ctor = !ParmList_numrequired(parms);
+ } else {
+ /* emit protected constructor if needed */
+ if (need_nonpublic_ctor(ni)) {
+ classDirectorConstructor(ni);
+ constructor = 1;
+ protected_ctor = 1;
+ if (default_ctor)
+ default_ctor = !ParmList_numrequired(parms);
+ }
+ }
+ }
+ }
+ /* emit default constructor if needed */
+ if (!constructor) {
+ if (!default_ctor) {
+ /* we get here because the class has no public, protected or
+ default constructor, therefore, the director class can't be
+ created, ie, is kind of abstract. */
+ Swig_warning(WARN_LANG_DIRECTOR_ABSTRACT, Getfile(n), Getline(n), "Director class '%s' can't be constructed\n", SwigType_namestr(Getattr(n, "name")));
+ return SWIG_OK;
+ }
+ classDirectorDefaultConstructor(n);
+ default_ctor = 1;
+ }
+ /* this is just to support old java behavior, ie, the default
+ constructor is always emitted, even when protected, and not
+ needed, since there is a public constructor already defined.
+
+ (scottm) This code is needed here to make the director_abstract +
+ test generate compilable code (Example2 in director_abstract.i).
+
+ (mmatus) This is very strange, since swig compiled with gcc3.2.3
+ doesn't need it here....
+ */
+ if (!default_ctor && !protected_ctor) {
+ if (Getattr(parent, "allocate:default_base_constructor")) {
+ classDirectorDefaultConstructor(n);
+ }
+ }
+
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorMethods()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorMethods(Node *n) {
+ Node *vtable = Getattr(n, "vtable");
+
+ int len = Len(vtable);
+ for (int i = 0; i < len; i++) {
+ Node *item = Getitem(vtable, i);
+ String *method = Getattr(item, "methodNode");
+ String *fqdname = Getattr(item, "fqdname");
+ if (GetFlag(method, "feature:nodirector") || GetFlag(method, "final"))
+ continue;
+
+ String *wrn = Getattr(method, "feature:warnfilter");
+ if (wrn)
+ Swig_warnfilter(wrn, 1);
+
+ String *type = Getattr(method, "nodeType");
+ if (!Cmp(type, "destructor")) {
+ classDirectorDestructor(method);
+ } else {
+ Swig_require("classDirectorMethods", method, "*type", NIL);
+ assert(Getattr(method, "returntype"));
+ Setattr(method, "type", Getattr(method, "returntype"));
+ if (classDirectorMethod(method, n, fqdname) == SWIG_OK)
+ SetFlag(item, "director");
+ Swig_restore(method);
+ }
+ if (wrn)
+ Swig_warnfilter(wrn, 0);
+ }
+
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorInit()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorInit(Node *n) {
+ (void) n;
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorDestructor()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorDestructor(Node *n) {
+ /*
+ Always emit the virtual destructor in the declaration and in the
+ compilation unit. Been explicit here can't make any damage, and
+ can solve some nasty C++ compiler problems.
+ */
+ File *f_directors = Swig_filebyname("director");
+ File *f_directors_h = Swig_filebyname("director_h");
+ if (Getattr(n, "throw")) {
+ Printf(f_directors_h, " virtual ~%s() throw();\n", DirectorClassName);
+ Printf(f_directors, "%s::~%s() throw() {\n}\n\n", DirectorClassName, DirectorClassName);
+ } else {
+ Printf(f_directors_h, " virtual ~%s();\n", DirectorClassName);
+ Printf(f_directors, "%s::~%s() {\n}\n\n", DirectorClassName, DirectorClassName);
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorEnd()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorEnd(Node *n) {
+ (void) n;
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirector()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirector(Node *n) {
+ Node *module = Getattr(n, "module");
+ String *classtype = Getattr(n, "classtype");
+ Hash *directormap = 0;
+ if (module) {
+ directormap = Getattr(module, "wrap:directormap");
+ if (directormap == 0) {
+ directormap = NewHash();
+ Setattr(module, "wrap:directormap", directormap);
+ }
+ }
+ List *vtable = NewList();
+ int virtual_destructor = 0;
+ unrollVirtualMethods(n, n, vtable, 0, virtual_destructor);
+
+ // Emit all the using base::member statements for non virtual members (allprotected mode)
+ Node *ni;
+ String *using_protected_members_code = NewString("");
+ for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
+ Node *nodeType = Getattr(ni, "nodeType");
+ if (Cmp(nodeType, "destructor") == 0 && GetFlag(ni, "final")) {
+ String *classtype = Getattr(n, "classtype");
+ SWIG_WARN_NODE_BEGIN(ni);
+ Swig_warning(WARN_LANG_DIRECTOR_FINAL, input_file, line_number, "Destructor %s is final, %s cannot be a director class.\n", Swig_name_decl(ni), classtype);
+ SWIG_WARN_NODE_END(ni);
+ SetFlag(n, "feature:nodirector");
+ Delete(vtable);
+ Delete(using_protected_members_code);
+ return SWIG_OK;
+ }
+ bool cdeclaration = (Cmp(nodeType, "cdecl") == 0);
+ if (cdeclaration && !GetFlag(ni, "feature:ignore")) {
+ if (isNonVirtualProtectedAccess(ni)) {
+ Node *overloaded = Getattr(ni, "sym:overloaded");
+ // emit the using base::member statement (but only once if the method is overloaded)
+ if (!overloaded || (overloaded && (overloaded == ni)))
+ Printf(using_protected_members_code, " using %s::%s;\n", SwigType_namestr(ClassName), Getattr(ni, "name"));
+ }
+ }
+ }
+
+ if (virtual_destructor || Len(vtable) > 0) {
+ if (!virtual_destructor) {
+ String *classtype = Getattr(n, "classtype");
+ Swig_warning(WARN_LANG_DIRECTOR_VDESTRUCT, input_file, line_number, "Director base class %s has no virtual destructor.\n", classtype);
+ }
+
+ Setattr(n, "vtable", vtable);
+ if (directormap != 0) {
+ Setattr(directormap, classtype, n);
+ }
+ classDirectorInit(n);
+ classDirectorConstructors(n);
+ classDirectorMethods(n);
+
+ File *f_directors_h = Swig_filebyname("director_h");
+ Printv(f_directors_h, using_protected_members_code, NIL);
+
+ classDirectorEnd(n);
+ }
+ Delete(vtable);
+ Delete(using_protected_members_code);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDeclaration()
+ * ---------------------------------------------------------------------- */
+
+static void addCopyConstructor(Node *n) {
+ Node *cn = NewHash();
+ set_nodeType(cn, "constructor");
+ Setattr(cn, "access", "public");
+ Setfile(cn, Getfile(n));
+ Setline(cn, Getline(n));
+
+ String *cname = Getattr(n, "name");
+ SwigType *type = Copy(cname);
+ String *name = Swig_scopename_last(cname);
+ String *cc = NewStringf("r.q(const).%s", type);
+ String *decl = NewStringf("f(%s).", cc);
+ String *oldname = Getattr(n, "sym:name");
+
+ if (Getattr(n, "allocate:has_constructor")) {
+ // to work properly with '%rename Class', we must look
+ // for any other constructor in the class, which has not been
+ // renamed, and use its name as oldname.
+ Node *c;
+ for (c = firstChild(n); c; c = nextSibling(c)) {
+ const char *tag = Char(nodeType(c));
+ if (strcmp(tag, "constructor") == 0) {
+ String *cname = Getattr(c, "name");
+ String *csname = Getattr(c, "sym:name");
+ String *clast = Swig_scopename_last(cname);
+ if (Equal(csname, clast)) {
+ oldname = csname;
+ break;
+ }
+ }
+ }
+ }
+
+ String *symname = Swig_name_make(cn, cname, name, decl, oldname);
+ if (Strcmp(symname, "$ignore") != 0) {
+ Parm *p = NewParm(cc, "other", n);
+
+ Setattr(cn, "name", name);
+ Setattr(cn, "sym:name", symname);
+ SetFlag(cn, "feature:new");
+ Setattr(cn, "decl", decl);
+ Setattr(cn, "parentNode", n);
+ Setattr(cn, "parms", p);
+ Setattr(cn, "copy_constructor", "1");
+
+ Symtab *oldscope = Swig_symbol_setscope(Getattr(n, "symtab"));
+ Node *on = Swig_symbol_add(symname, cn);
+ Swig_features_get(Swig_cparse_features(), Swig_symbol_qualifiedscopename(0), name, decl, cn);
+ Swig_symbol_setscope(oldscope);
+
+ if (on == cn) {
+ Node *access = NewHash();
+ set_nodeType(access, "access");
+ Setattr(access, "kind", "public");
+ appendChild(n, access);
+ appendChild(n, cn);
+ Setattr(n, "has_copy_constructor", "1");
+ Setattr(n, "copy_constructor_decl", decl);
+ Setattr(n, "allocate:copy_constructor", "1");
+ Delete(access);
+ }
+ }
+ Delete(cn);
+ Delete(name);
+ Delete(decl);
+ Delete(symname);
+}
+
+static void addDefaultConstructor(Node *n) {
+ Node *cn = NewHash();
+ set_nodeType(cn, "constructor");
+ Setattr(cn, "access", "public");
+ Setfile(cn, Getfile(n));
+ Setline(cn, Getline(n));
+
+ String *cname = Getattr(n, "name");
+ String *name = Swig_scopename_last(cname);
+ String *decl = NewString("f().");
+ String *oldname = Getattr(n, "sym:name");
+ String *symname = Swig_name_make(cn, cname, name, decl, oldname);
+ if (Strcmp(symname, "$ignore") != 0) {
+ Setattr(cn, "name", name);
+ Setattr(cn, "sym:name", symname);
+ SetFlag(cn, "feature:new");
+ Setattr(cn, "decl", decl);
+ Setattr(cn, "parentNode", n);
+ Setattr(cn, "default_constructor", "1");
+ Symtab *oldscope = Swig_symbol_setscope(Getattr(n, "symtab"));
+ Node *on = Swig_symbol_add(symname, cn);
+ Swig_features_get(Swig_cparse_features(), Swig_symbol_qualifiedscopename(0), name, decl, cn);
+ Swig_symbol_setscope(oldscope);
+
+ if (on == cn) {
+ Node *access = NewHash();
+ set_nodeType(access, "access");
+ Setattr(access, "kind", "public");
+ appendChild(n, access);
+ appendChild(n, cn);
+ Setattr(n, "has_default_constructor", "1");
+ Setattr(n, "allocate:default_constructor", "1");
+ Delete(access);
+ }
+ }
+ Delete(cn);
+ Delete(name);
+ Delete(decl);
+ Delete(symname);
+}
+
+static void addDestructor(Node *n) {
+ Node *cn = NewHash();
+ set_nodeType(cn, "destructor");
+ Setattr(cn, "access", "public");
+ Setfile(cn, Getfile(n));
+ Setline(cn, Getline(n));
+
+ String *cname = Getattr(n, "name");
+ String *name = Swig_scopename_last(cname);
+ Insert(name, 0, "~");
+ String *decl = NewString("f().");
+ String *symname = Swig_name_make(cn, cname, name, decl, 0);
+ if (Strcmp(symname, "$ignore") != 0) {
+ String *possible_nonstandard_symname = NewStringf("~%s", Getattr(n, "sym:name"));
+
+ Setattr(cn, "name", name);
+ Setattr(cn, "sym:name", symname);
+ Setattr(cn, "decl", "f().");
+ Setattr(cn, "parentNode", n);
+
+ Symtab *oldscope = Swig_symbol_setscope(Getattr(n, "symtab"));
+ Node *nonstandard_destructor = Equal(possible_nonstandard_symname, symname) ? 0 : Swig_symbol_clookup(possible_nonstandard_symname, 0);
+ Node *on = Swig_symbol_add(symname, cn);
+ Swig_features_get(Swig_cparse_features(), Swig_symbol_qualifiedscopename(0), name, decl, cn);
+ Swig_symbol_setscope(oldscope);
+
+ if (on == cn) {
+ // SWIG accepts a non-standard named destructor in %extend that uses a typedef for the destructor name
+ // For example: typedef struct X {} XX; %extend X { ~XX() {...} }
+ // Don't add another destructor if a nonstandard one has been declared
+ if (!nonstandard_destructor) {
+ Node *access = NewHash();
+ set_nodeType(access, "access");
+ Setattr(access, "kind", "public");
+ appendChild(n, access);
+ appendChild(n, cn);
+ Setattr(n, "has_destructor", "1");
+ Setattr(n, "allocate:destructor", "1");
+ Delete(access);
+ }
+ }
+ Delete(possible_nonstandard_symname);
+ }
+ Delete(cn);
+ Delete(name);
+ Delete(decl);
+ Delete(symname);
+}
+
+int Language::classDeclaration(Node *n) {
+ String *ochildren = Getattr(n, "feature:onlychildren");
+ if (ochildren) {
+ Setattr(n, "feature:emitonlychildren", ochildren);
+ emit_children(n);
+ Delattr(n, "feature:emitonlychildren");
+ SetFlag(n, "feature:ignore");
+ return SWIG_NOWRAP;
+ }
+
+ // save class local variables for nested classes support
+ int oldInClass = InClass;
+ String *oldClassType = ClassType;
+ String *oldClassPrefix = ClassPrefix;
+ String *oldEnumClassPrefix = EnumClassPrefix;
+ String *oldClassName = ClassName;
+ String *oldDirectorClassName = DirectorClassName;
+ String *oldNSpace = NSpace;
+ Node *oldCurrentClass = CurrentClass;
+ int dir = 0;
+
+ String *kind = Getattr(n, "kind");
+ String *name = Getattr(n, "name");
+ String *tdname = Getattr(n, "tdname");
+ String *unnamed = Getattr(n, "unnamed");
+ String *symname = Getattr(n, "sym:name");
+
+ int strip = CPlusPlus ? 1 : unnamed && tdname;
+
+ if (cplus_mode != PUBLIC)
+ return SWIG_NOWRAP;
+ if (!name) {
+ Swig_warning(WARN_LANG_CLASS_UNNAMED, input_file, line_number, "Can't generate wrappers for unnamed struct/class.\n");
+ return SWIG_NOWRAP;
+ }
+
+ /* Check symbol name for template. If not renamed. Issue a warning */
+ if (!validIdentifier(symname)) {
+ Swig_warning(WARN_LANG_IDENTIFIER, input_file, line_number, "Can't wrap class %s unless renamed to a valid identifier.\n", SwigType_namestr(symname));
+ return SWIG_NOWRAP;
+ }
+ AccessMode oldAccessMode = cplus_mode;
+ Node *outerClass = Getattr(n, "nested:outer");
+ if (outerClass && oldAccessMode != PUBLIC)
+ return SWIG_NOWRAP;
+ ClassName = Copy(name);
+ ClassPrefix = Copy(symname);
+ if (Cmp(kind, "class") == 0) {
+ cplus_mode = PRIVATE;
+ } else {
+ cplus_mode = PUBLIC;
+ }
+ for (; outerClass; outerClass = Getattr(outerClass, "nested:outer")) {
+ Push(ClassPrefix, "_");
+ Push(ClassPrefix, Getattr(outerClass, "sym:name"));
+ }
+ EnumClassPrefix = Copy(ClassPrefix);
+ if (strip) {
+ ClassType = Copy(name);
+ } else {
+ ClassType = NewStringf("%s %s", kind, name);
+ }
+ Setattr(n, "classtypeobj", Copy(ClassType));
+ Setattr(n, "classtype", SwigType_namestr(ClassType));
+
+ InClass = 1;
+ CurrentClass = n;
+ NSpace = Getattr(n, "sym:nspace");
+ int oldAbstract = Abstract;
+
+ /* Call classHandler() here */
+ if (!ImportMode) {
+ if (directorsEnabled()) {
+ int ndir = GetFlag(n, "feature:director");
+ int nndir = GetFlag(n, "feature:nodirector");
+ /* 'nodirector' has precedence over 'director' */
+ dir = (ndir || nndir) ? (ndir && !nndir) : 0;
+ }
+ int abstract = !dir && abstractClassTest(n);
+ int odefault = (GenerateDefault && !GetFlag(n, "feature:nodefault"));
+
+ /* default constructor */
+ if (!abstract && !GetFlag(n, "feature:nodefaultctor") && odefault) {
+ if (!Getattr(n, "has_constructor") && !Getattr(n, "allocate:has_constructor") && (Getattr(n, "allocate:default_constructor"))) {
+ addDefaultConstructor(n);
+ }
+ }
+ /* copy constructor */
+ if (CPlusPlus && !abstract && GetFlag(n, "feature:copyctor")) {
+ if (!Getattr(n, "has_copy_constructor") && !Getattr(n, "allocate:has_copy_constructor")
+ && (Getattr(n, "allocate:copy_constructor"))
+ && (!GetFlag(n, "feature:ignore"))) {
+ addCopyConstructor(n);
+ }
+ }
+ /* default destructor */
+ if (!GetFlag(n, "feature:nodefaultdtor") && odefault) {
+ if (!Getattr(n, "has_destructor") && (!Getattr(n, "allocate:has_destructor"))
+ && (Getattr(n, "allocate:default_destructor"))
+ && (!GetFlag(n, "feature:ignore"))) {
+ addDestructor(n);
+ }
+ }
+
+ if (dir) {
+ DirectorClassName = directorClassName(n);
+ classDirector(n);
+ }
+ /* check for abstract after resolving directors */
+
+ Abstract = abstractClassTest(n);
+ classHandler(n);
+ } else {
+ Abstract = abstractClassTest(n);
+ Language::classHandler(n);
+ }
+
+ Abstract = oldAbstract;
+ cplus_mode = oldAccessMode;
+ NSpace = oldNSpace;
+ InClass = oldInClass;
+ CurrentClass = oldCurrentClass;
+ Delete(ClassType);
+ ClassType = oldClassType;
+ Delete(EnumClassPrefix);
+ EnumClassPrefix = oldEnumClassPrefix;
+ Delete(ClassPrefix);
+ ClassPrefix = oldClassPrefix;
+ Delete(ClassName);
+ ClassName = oldClassName;
+ if (dir) {
+ Delete(DirectorClassName);
+ }
+ DirectorClassName = oldDirectorClassName;
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::classHandler(Node *n) {
+ save_value<int> oldExtend(Extend);
+ if (Getattr(n, "template"))
+ Extend = 0;
+ bool hasDirector = Swig_directorclass(n) ? true : false;
+
+ /* Emit all of the class members */
+ emit_children(n);
+
+ /* Look for smart pointer handling */
+ if (Getattr(n, "allocate:smartpointer")) {
+ List *methods = Getattr(n, "allocate:smartpointer");
+ cplus_mode = PUBLIC;
+ SmartPointer = CWRAP_SMART_POINTER;
+ if (Getattr(n, "allocate:smartpointerconst") && Getattr(n, "allocate:smartpointermutable")) {
+ SmartPointer |= CWRAP_SMART_POINTER_OVERLOAD;
+ }
+ Iterator c;
+ for (c = First(methods); c.item; c = Next(c)) {
+ emit_one(c.item);
+ }
+ SmartPointer = 0;
+ }
+
+ cplus_mode = PUBLIC;
+
+ /* emit director disown method */
+ if (hasDirector) {
+ classDirectorDisown(n);
+
+ /* Emit additional protected virtual methods - only needed if the language module
+ * codes logic in the C++ layer instead of the director proxy class method - primarily
+ * to catch public use of protected methods by the scripting languages. */
+ if (dirprot_mode() && extraDirectorProtectedCPPMethodsRequired()) {
+ Node *vtable = Getattr(n, "vtable");
+ String *symname = Getattr(n, "sym:name");
+ save_value<AccessMode> old_mode(cplus_mode);
+ cplus_mode = PROTECTED;
+ int len = Len(vtable);
+ for (int i = 0; i < len; i++) {
+ Node *item = Getitem(vtable, i);
+ Node *method = Getattr(item, "methodNode");
+ SwigType *type = Getattr(method, "nodeType");
+ if (Strcmp(type, "cdecl") != 0)
+ continue;
+ if (GetFlag(method, "feature:ignore"))
+ continue;
+ String *methodname = Getattr(method, "sym:name");
+ String *wrapname = NewStringf("%s_%s", symname, methodname);
+ if (!symbolLookup(wrapname, "") && (!is_public(method))) {
+ Node *m = Copy(method);
+ Setattr(m, "director", "1");
+ Setattr(m, "parentNode", n);
+ /*
+ * There is a bug that needs fixing still...
+ * This area of code is creating methods which have not been overridden in a derived class (director methods that are protected in the base)
+ * If the method is overloaded, then Swig_overload_dispatch() incorrectly generates a call to the base wrapper, _wrap_xxx method
+ * See director_protected_overloaded.i - Possibly sym:overname needs correcting here.
+ Printf(stdout, "new method: %s::%s(%s)\n", Getattr(parentNode(m), "name"), Getattr(m, "name"), ParmList_str_defaultargs(Getattr(m, "parms")));
+ */
+ cDeclaration(m);
+ Delete(m);
+ }
+ Delete(wrapname);
+ }
+ }
+ }
+
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classforwardDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::classforwardDeclaration(Node *n) {
+ (void) n;
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::constructorDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::constructorDeclaration(Node *n) {
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+
+ if (!symname)
+ return SWIG_NOWRAP;
+ if (!CurrentClass)
+ return SWIG_NOWRAP;
+ if (ImportMode)
+ return SWIG_NOWRAP;
+
+ if (Extend) {
+ /* extend default constructor can be safely ignored if there is already one */
+ int num_required = ParmList_numrequired(Getattr(n, "parms"));
+ if ((num_required == 0) && Getattr(CurrentClass, "has_default_constructor")) {
+ return SWIG_NOWRAP;
+ }
+ if ((num_required == 1) && Getattr(CurrentClass, "has_copy_constructor")) {
+ String *ccdecl = Getattr(CurrentClass, "copy_constructor_decl");
+ if (ccdecl && (Strcmp(ccdecl, Getattr(n, "decl")) == 0)) {
+ return SWIG_NOWRAP;
+ }
+ }
+ }
+
+ /* clean protected overloaded constructors, in case they are not needed anymore */
+ Node *over = Swig_symbol_isoverloaded(n);
+ if (over && !Getattr(CurrentClass, "sym:cleanconstructor")) {
+ int dirclass = Swig_directorclass(CurrentClass);
+ Node *nn = over;
+ while (nn) {
+ if (!is_public(nn)) {
+ if (!dirclass || !need_nonpublic_ctor(nn)) {
+ SetFlag(nn, "feature:ignore");
+ }
+ }
+ nn = Getattr(nn, "sym:nextSibling");
+ }
+ clean_overloaded(over);
+ Setattr(CurrentClass, "sym:cleanconstructor", "1");
+ }
+
+ if ((cplus_mode != PUBLIC)) {
+ /* check only for director classes */
+ if (!Swig_directorclass(CurrentClass) || !need_nonpublic_ctor(n))
+ return SWIG_NOWRAP;
+ }
+
+ /* Name adjustment for %name */
+ Swig_save("constructorDeclaration", n, "sym:name", NIL);
+
+ {
+ String *base = Swig_scopename_last(name);
+ if ((Strcmp(base, symname) == 0) && (Strcmp(symname, ClassPrefix) != 0)) {
+ Setattr(n, "sym:name", ClassPrefix);
+ }
+ Delete(base);
+ }
+
+ /* Only create a constructor if the class is not abstract */
+ if (!Abstract) {
+ Node *over;
+ over = Swig_symbol_isoverloaded(n);
+ if (over)
+ over = first_nontemplate(over);
+ if ((over) && (!overloading)) {
+ /* If the symbol is overloaded. We check to see if it is a copy constructor. If so,
+ we invoke copyconstructorHandler() as a special case. */
+ if (Getattr(n, "copy_constructor") && (!Getattr(CurrentClass, "has_copy_constructor"))) {
+ copyconstructorHandler(n);
+ Setattr(CurrentClass, "has_copy_constructor", "1");
+ } else {
+ if (Getattr(over, "copy_constructor"))
+ over = Getattr(over, "sym:nextSibling");
+ if (over != n) {
+ Swig_warning(WARN_LANG_OVERLOAD_CONSTRUCT, input_file, line_number,
+ "Overloaded constructor ignored. %s\n", Swig_name_decl(n));
+ Swig_warning(WARN_LANG_OVERLOAD_CONSTRUCT, Getfile(over), Getline(over),
+ "Previous declaration is %s\n", Swig_name_decl(over));
+ } else {
+ constructorHandler(n);
+ }
+ }
+ } else {
+ String *expected_name = ClassName;
+ String *scope = Swig_scopename_check(ClassName) ? Swig_scopename_prefix(ClassName) : 0;
+ String *actual_name = scope ? NewStringf("%s::%s", scope, name) : NewString(name);
+ Delete(scope);
+ if (!Equal(actual_name, expected_name) && !SwigType_istemplate(expected_name) && !SwigType_istemplate(actual_name)) {
+ // Checking templates is skipped but they ought to be checked... they are just somewhat more tricky to check correctly
+ bool illegal_name = true;
+ if (Extend) {
+ // Check for typedef names used as a constructor name in %extend. This is deprecated except for anonymous
+ // typedef structs which have had their symbol names adjusted to the typedef name in the parser.
+ SwigType *name_resolved = SwigType_typedef_resolve_all(actual_name);
+ SwigType *expected_name_resolved = SwigType_typedef_resolve_all(expected_name);
+
+ if (!CPlusPlus) {
+ if (Strncmp(name_resolved, "struct ", 7) == 0)
+ Replace(name_resolved, "struct ", "", DOH_REPLACE_FIRST);
+ else if (Strncmp(name_resolved, "union ", 6) == 0)
+ Replace(name_resolved, "union ", "", DOH_REPLACE_FIRST);
+ }
+
+ illegal_name = !Equal(name_resolved, expected_name_resolved);
+ if (!illegal_name)
+ Swig_warning(WARN_LANG_EXTEND_CONSTRUCTOR, input_file, line_number, "Use of an illegal constructor name '%s' in %%extend is deprecated, the constructor name should be '%s'.\n",
+ SwigType_str(Swig_scopename_last(actual_name), 0), SwigType_str(Swig_scopename_last(expected_name), 0));
+ Delete(name_resolved);
+ Delete(expected_name_resolved);
+ }
+ if (illegal_name) {
+ Swig_warning(WARN_LANG_RETURN_TYPE, input_file, line_number, "Function %s must have a return type. Ignored.\n", Swig_name_decl(n));
+ Swig_restore(n);
+ return SWIG_NOWRAP;
+ }
+ }
+ constructorHandler(n);
+ }
+ }
+ Setattr(CurrentClass, "has_constructor", "1");
+
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * get_director_ctor_code()
+ * ---------------------------------------------------------------------- */
+
+static String *get_director_ctor_code(Node *n, String *director_ctor_code, String *director_prot_ctor_code, List *&abstracts) {
+ String *director_ctor = director_ctor_code;
+ int use_director = Swig_directorclass(n);
+ if (use_director) {
+ Node *pn = Swig_methodclass(n);
+ abstracts = Getattr(pn, "abstracts");
+ if (director_prot_ctor_code) {
+ int is_notabstract = GetFlag(pn, "feature:notabstract");
+ int is_abstract = abstracts && !is_notabstract;
+ if (is_protected(n) || is_abstract) {
+ director_ctor = director_prot_ctor_code;
+ abstracts = Copy(abstracts);
+ Delattr(pn, "abstracts");
+ } else {
+ if (is_notabstract) {
+ abstracts = Copy(abstracts);
+ Delattr(pn, "abstracts");
+ } else {
+ abstracts = 0;
+ }
+ }
+ }
+ }
+ return director_ctor;
+}
+
+
+/* ----------------------------------------------------------------------
+ * Language::constructorHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::constructorHandler(Node *n) {
+ Swig_require("constructorHandler", n, "?name", "*sym:name", "?type", "?parms", NIL);
+ String *symname = Getattr(n, "sym:name");
+ String *mrename = Swig_name_construct(NSpace, symname);
+ String *nodeType = Getattr(n, "nodeType");
+ int constructor = (!Cmp(nodeType, "constructor"));
+ List *abstracts = 0;
+ String *director_ctor = get_director_ctor_code(n, director_ctor_code,
+ director_prot_ctor_code,
+ abstracts);
+ if (!constructor) {
+ /* if not originally a constructor, still handle it as one */
+ Setattr(n, "handled_as_constructor", "1");
+ }
+
+ int extendmember = GetFlag(n, "isextendmember") ? Extend : 0;
+ int flags = Getattr(n, "template") ? extendmember : Extend;
+ Swig_ConstructorToFunction(n, NSpace, ClassType, none_comparison, director_ctor, CPlusPlus, flags, DirectorClassName);
+ Setattr(n, "sym:name", mrename);
+ functionWrapper(n);
+ Delete(mrename);
+ Swig_restore(n);
+ if (abstracts)
+ Setattr(Swig_methodclass(n), "abstracts", abstracts);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::copyconstructorHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::copyconstructorHandler(Node *n) {
+ Swig_require("copyconstructorHandler", n, "?name", "*sym:name", "?type", "?parms", NIL);
+ String *symname = Getattr(n, "sym:name");
+ String *mrename = Swig_name_copyconstructor(NSpace, symname);
+ List *abstracts = 0;
+ String *director_ctor = get_director_ctor_code(n, director_ctor_code,
+ director_prot_ctor_code,
+ abstracts);
+ Swig_ConstructorToFunction(n, NSpace, ClassType, none_comparison, director_ctor, CPlusPlus, Getattr(n, "template") ? 0 : Extend, DirectorClassName);
+ Setattr(n, "sym:name", mrename);
+ functionWrapper(n);
+ Delete(mrename);
+ Swig_restore(n);
+ if (abstracts)
+ Setattr(Swig_methodclass(n), "abstracts", abstracts);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::destructorDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::destructorDeclaration(Node *n) {
+
+ if (!CurrentClass)
+ return SWIG_NOWRAP;
+ if (cplus_mode != PUBLIC && !Getattr(CurrentClass, "feature:unref"))
+ return SWIG_NOWRAP;
+ if (ImportMode)
+ return SWIG_NOWRAP;
+
+ Swig_save("destructorDeclaration", n, "name", "sym:name", NIL);
+
+ char *c = GetChar(n, "sym:name");
+ if (c && (*c == '~')) {
+ Setattr(n, "sym:name", c + 1);
+ }
+
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+
+ if ((Strcmp(name, symname) == 0) || (Strcmp(symname, ClassPrefix) != 0)) {
+ Setattr(n, "sym:name", ClassPrefix);
+ }
+
+ String *expected_name = ClassName;
+ String *scope = Swig_scopename_check(ClassName) ? Swig_scopename_prefix(ClassName) : 0;
+ String *actual_name = scope ? NewStringf("%s::%s", scope, name) : NewString(name);
+ Delete(scope);
+ Replace(actual_name, "~", "", DOH_REPLACE_FIRST);
+ if (!Equal(actual_name, expected_name) && !(Getattr(n, "template"))) {
+ bool illegal_name = true;
+ if (Extend) {
+ // Check for typedef names used as a destructor name in %extend. This is deprecated except for anonymous
+ // typedef structs which have had their symbol names adjusted to the typedef name in the parser.
+ SwigType *name_resolved = SwigType_typedef_resolve_all(actual_name);
+ SwigType *expected_name_resolved = SwigType_typedef_resolve_all(expected_name);
+
+ if (!CPlusPlus) {
+ if (Strncmp(name_resolved, "struct ", 7) == 0)
+ Replace(name_resolved, "struct ", "", DOH_REPLACE_FIRST);
+ else if (Strncmp(name_resolved, "union ", 6) == 0)
+ Replace(name_resolved, "union ", "", DOH_REPLACE_FIRST);
+ }
+
+ illegal_name = !Equal(name_resolved, expected_name_resolved);
+ if (!illegal_name)
+ Swig_warning(WARN_LANG_EXTEND_DESTRUCTOR, input_file, line_number, "Use of an illegal destructor name '%s' in %%extend is deprecated, the destructor name should be '%s'.\n",
+ SwigType_str(Swig_scopename_last(actual_name), 0), SwigType_str(Swig_scopename_last(expected_name), 0));
+ Delete(name_resolved);
+ Delete(expected_name_resolved);
+ }
+
+ if (illegal_name) {
+ Swig_warning(WARN_LANG_ILLEGAL_DESTRUCTOR, input_file, line_number, "Illegal destructor name %s. Ignored.\n", Swig_name_decl(n));
+ Swig_restore(n);
+ return SWIG_NOWRAP;
+ }
+ }
+ destructorHandler(n);
+
+ Setattr(CurrentClass, "has_destructor", "1");
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::destructorHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::destructorHandler(Node *n) {
+ Swig_require("destructorHandler", n, "?name", "*sym:name", NIL);
+ Swig_save("destructorHandler", n, "type", "parms", NIL);
+
+ String *symname = Getattr(n, "sym:name");
+ String *mrename;
+ char *csymname = Char(symname);
+ if (*csymname == '~')
+ csymname += 1;
+
+ mrename = Swig_name_destroy(NSpace, csymname);
+
+ Swig_DestructorToFunction(n, NSpace, ClassType, CPlusPlus, Extend);
+ Setattr(n, "sym:name", mrename);
+ functionWrapper(n);
+ Delete(mrename);
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::accessDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::accessDeclaration(Node *n) {
+ String *kind = Getattr(n, "kind");
+ if (Cmp(kind, "public") == 0) {
+ cplus_mode = PUBLIC;
+ } else if (Cmp(kind, "private") == 0) {
+ cplus_mode = PRIVATE;
+ } else if (Cmp(kind, "protected") == 0) {
+ cplus_mode = PROTECTED;
+ }
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::namespaceDeclaration()
+ * ----------------------------------------------------------------------------- */
+
+int Language::namespaceDeclaration(Node *n) {
+ if (Getattr(n, "alias"))
+ return SWIG_OK;
+ if (Getattr(n, "unnamed"))
+ return SWIG_OK;
+ emit_children(n);
+ return SWIG_OK;
+}
+
+int Language::validIdentifier(String *s) {
+ char *c = Char(s);
+ while (*c) {
+ if (!(isalnum(*c) || (*c == '_')))
+ return 0;
+ c++;
+ }
+ return 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::usingDeclaration()
+ * ----------------------------------------------------------------------------- */
+
+int Language::usingDeclaration(Node *n) {
+ if ((cplus_mode == PUBLIC) || (!is_public(n) && dirprot_mode())) {
+ Node *np = Copy(n);
+ Node *c;
+ for (c = firstChild(np); c; c = nextSibling(c)) {
+ /* it seems for some cases this is needed, like A* A::boo() */
+ if (CurrentClass)
+ Setattr(c, "parentNode", CurrentClass);
+ emit_one(c);
+ }
+ Delete(np);
+ }
+ return SWIG_OK;
+}
+
+/* Stubs. Language modules need to implement these */
+
+/* ----------------------------------------------------------------------
+ * Language::constantWrapper()
+ * ---------------------------------------------------------------------- */
+
+int Language::constantWrapper(Node *n) {
+ String *name = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ String *str = SwigType_str(type, name);
+ Printf(stdout, "constantWrapper : %s = %s\n", str, value);
+ Delete(str);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::variableWrapper()
+ * ---------------------------------------------------------------------- */
+
+int Language::variableWrapper(Node *n) {
+ Swig_require("variableWrapper", n, "*name", "*sym:name", "*type", "?parms", "?varset", "?varget", NIL);
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *name = Getattr(n, "name");
+
+ Delattr(n,"varset");
+ Delattr(n,"varget");
+
+ String *newsymname = 0;
+ if (!CurrentClass && EnumClassPrefix) {
+ newsymname = Swig_name_member(0, EnumClassPrefix, symname);
+ symname = newsymname;
+ }
+
+ /* If no way to set variables. We simply create functions */
+ int assignable = is_assignable(n);
+ int flags = use_naturalvar_mode(n);
+ if (!GetFlag(n, "wrappedasconstant"))
+ flags = flags | Extend;
+
+ if (assignable) {
+ int make_set_wrapper = 1;
+ String *tm = Swig_typemap_lookup("globalin", n, name, 0);
+
+ Swig_VarsetToFunction(n, flags);
+ String *sname = Swig_name_set(NSpace, symname);
+ Setattr(n, "sym:name", sname);
+ Delete(sname);
+
+ if (!tm) {
+ if (SwigType_isarray(type)) {
+ Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(type, 0));
+ make_set_wrapper = 0;
+ }
+ } else {
+ String *pname0 = Swig_cparm_name(0, 0);
+ Replace(tm, "$source", pname0, DOH_REPLACE_ANY);
+ Replace(tm, "$target", name, DOH_REPLACE_ANY);
+ Replace(tm, "$input", pname0, DOH_REPLACE_ANY);
+ Setattr(n, "wrap:action", tm);
+ Delete(tm);
+ Delete(pname0);
+ }
+ if (make_set_wrapper) {
+ Setattr(n, "varset", "1");
+ functionWrapper(n);
+ } else {
+ SetFlag(n, "feature:immutable");
+ }
+ /* Restore parameters */
+ Setattr(n, "sym:name", symname);
+ Setattr(n, "type", type);
+ Setattr(n, "name", name);
+ Delattr(n, "varset");
+
+ /* Delete all attached typemaps and typemap attributes */
+ Iterator ki;
+ for (ki = First(n); ki.key; ki = Next(ki)) {
+ if (Strncmp(ki.key, "tmap:", 5) == 0)
+ Delattr(n, ki.key);
+ }
+ }
+
+ Swig_VargetToFunction(n, flags);
+ String *gname = Swig_name_get(NSpace, symname);
+ Setattr(n, "sym:name", gname);
+ Delete(gname);
+ Setattr(n, "varget", "1");
+ functionWrapper(n);
+ Delattr(n, "varget");
+ Swig_restore(n);
+ Delete(newsymname);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::functionWrapper()
+ * ---------------------------------------------------------------------- */
+
+int Language::functionWrapper(Node *n) {
+ String *name = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ ParmList *parms = Getattr(n, "parms");
+
+ Printf(stdout, "functionWrapper : %s\n", SwigType_str(type, NewStringf("%s(%s)", name, ParmList_str_defaultargs(parms))));
+ Printf(stdout, " action : %s\n", Getattr(n, "wrap:action"));
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::nativeWrapper()
+ * ----------------------------------------------------------------------------- */
+
+int Language::nativeWrapper(Node *n) {
+ (void) n;
+ return SWIG_OK;
+}
+
+void Language::main(int argc, char *argv[]) {
+ (void) argc;
+ (void) argv;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::addSymbol()
+ *
+ * Adds a symbol entry into the target language symbol tables.
+ * Returns 1 if the symbol is added successfully.
+ * Prints an error message and returns 0 if a conflict occurs.
+ * The scope is optional for target languages and if supplied must be a fully
+ * qualified scope and the symbol s must not contain any scope qualifiers.
+ * ----------------------------------------------------------------------------- */
+
+int Language::addSymbol(const String *s, const Node *n, const_String_or_char_ptr scope) {
+ //Printf( stdout, "addSymbol: %s %s\n", s, scope );
+ Hash *symbols = Getattr(symtabs, scope ? scope : "");
+ if (!symbols) {
+ symbols = symbolAddScope(scope);
+ } else {
+ Node *c = Getattr(symbols, s);
+ if (c && (c != n)) {
+ if (scope && Len(scope) > 0)
+ Swig_error(input_file, line_number, "'%s' is multiply defined in the generated target language module in scope '%s'.\n", s, scope);
+ else
+ Swig_error(input_file, line_number, "'%s' is multiply defined in the generated target language module.\n", s);
+ Swig_error(Getfile(c), Getline(c), "Previous declaration of '%s'\n", s);
+ return 0;
+ }
+ }
+ Setattr(symbols, s, n);
+ return 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::addInterfaceSymbol()
+ *
+ * Adds a symbol entry into the target language symbol tables - for the interface
+ * feature only.
+ * Returns 1 if the symbol is added successfully.
+ * The scope is as per addSymbol.
+ * ----------------------------------------------------------------------------- */
+
+int Language::addInterfaceSymbol(const String *interface_name, Node *n, const_String_or_char_ptr scope) {
+ if (interface_name) {
+ Node *existing_symbol = symbolLookup(interface_name, scope);
+ if (existing_symbol) {
+ String *proxy_class_name = Getattr(n, "sym:name");
+ Swig_error(input_file, line_number, "The interface feature name '%s' for proxy class '%s' is already defined in the generated target language module in scope '%s'.\n",
+ interface_name, proxy_class_name, scope);
+ Swig_error(Getfile(existing_symbol), Getline(existing_symbol), "Previous declaration of '%s'\n", interface_name);
+ return 0;
+ }
+ if (!addSymbol(interface_name, n, scope))
+ return 0;
+ }
+ return 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::symbolAddScope()
+ *
+ * Creates a scope (symbols Hash) for given name. This method is auxiliary,
+ * you don't have to call it - addSymbols will lazily create scopes automatically.
+ * If scope with given name already exists, then do nothing.
+ * Returns newly created (or already existing) scope.
+ * ----------------------------------------------------------------------------- */
+Hash* Language::symbolAddScope(const_String_or_char_ptr scope) {
+ Hash *symbols = symbolScopeLookup(scope);
+ if(!symbols) {
+ // The order in which the following code is executed is important. In the Language
+ // constructor addScope("") is called to create a top level scope.
+ // Thus we must first add a symbols hash to symtab and only then add pseudo
+ // symbols to the top-level scope.
+
+ // New scope which has not been added by the target language - lazily created.
+ symbols = NewHash();
+ Setattr(symtabs, scope, symbols);
+
+ // Add the new scope as a symbol in the top level scope.
+ // Alternatively the target language must add it in before attempting to add symbols into the scope.
+ const_String_or_char_ptr top_scope = "";
+ Hash *topscope_symbols = Getattr(symtabs, top_scope);
+ Hash *pseudo_symbol = NewHash();
+ Setattr(pseudo_symbol, "sym:scope", "1");
+ Setattr(topscope_symbols, scope, pseudo_symbol);
+ }
+ return symbols;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::symbolScopeLookup()
+ *
+ * Lookup and returns a symtable (hash) representing given scope. Hash contains
+ * all symbols in this scope.
+ * ----------------------------------------------------------------------------- */
+Hash* Language::symbolScopeLookup( const_String_or_char_ptr scope ) {
+ Hash *symbols = Getattr(symtabs, scope ? scope : "");
+ return symbols;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::symbolScopePseudoSymbolLookup()
+ *
+ * For every scope there is a special pseudo-symbol in the top scope (""). It
+ * exists solely to detect name clashes. This pseudo symbol may contain a few properties,
+ * but more could be added. This is also true for the top level scope ("").
+ * It contains a pseudo symbol with name "" (empty). Pseudo symbol contains the
+ * following properties:
+ * sym:scope = "1" - a flag that this is a scope pseudo symbol
+ *
+ * Pseudo symbols are a Hash*, not a Node*.
+ * There is no difference from symbolLookup() method except for signature
+ * and return type.
+ * ----------------------------------------------------------------------------- */
+Hash* Language::symbolScopePseudoSymbolLookup( const_String_or_char_ptr scope )
+{
+ /* Getting top scope */
+ const_String_or_char_ptr top_scope = "";
+ Hash *symbols = Getattr(symtabs, top_scope);
+ return Getattr(symbols, scope);
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::dumpSymbols()
+ * ----------------------------------------------------------------------------- */
+
+void Language::dumpSymbols() {
+ Printf(stdout, "LANGUAGE SYMBOLS start =======================================\n");
+
+ Node *table = symtabs;
+ Iterator ki = First(table);
+ while (ki.key) {
+ String *k = ki.key;
+ Printf(stdout, "===================================================\n");
+ Printf(stdout, "%s -\n", k);
+ {
+ Symtab *symtab = Getattr(table, k);
+ Iterator it = First(symtab);
+ while (it.key) {
+ String *symname = it.key;
+ Printf(stdout, " %s\n", symname);
+ it = Next(it);
+ }
+ }
+ ki = Next(ki);
+ }
+
+ Printf(stdout, "LANGUAGE SYMBOLS finish =======================================\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::symbolLookup()
+ * ----------------------------------------------------------------------------- */
+
+Node *Language::symbolLookup(const String *s, const_String_or_char_ptr scope) {
+ Hash *symbols = Getattr(symtabs, scope ? scope : "");
+ if (!symbols) {
+ return NULL;
+ }
+ return Getattr(symbols, s);
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::classLookup()
+ *
+ * Tries to locate a class from a type definition
+ * ----------------------------------------------------------------------------- */
+
+Node *Language::classLookup(const SwigType *s) {
+ static Hash *classtypes = 0;
+
+ Node *n = 0;
+
+ /* Look in hash of cached values */
+ n = classtypes ? Getattr(classtypes, s) : 0;
+ if (!n) {
+ Symtab *stab = 0;
+ SwigType *ty1 = SwigType_typedef_resolve_all(s);
+ SwigType *ty2 = SwigType_strip_qualifiers(ty1);
+
+ String *base = SwigType_base(ty2);
+
+ Replaceall(base, "class ", "");
+ Replaceall(base, "struct ", "");
+ Replaceall(base, "union ", "");
+
+ if (strncmp(Char(base), "::", 2) == 0) {
+ String *oldbase = base;
+ base = NewString(Char(base) + 2);
+ Delete(oldbase);
+ }
+
+ String *prefix = SwigType_prefix(ty2);
+
+ /* Do a symbol table search on the base type */
+ while (!n) {
+ Hash *nstab;
+ n = Swig_symbol_clookup(base, stab);
+ if (!n)
+ break;
+ if (Strcmp(nodeType(n), "class") == 0)
+ break;
+ Node *sibling = n;
+ while (sibling) {
+ sibling = Getattr(sibling, "csym:nextSibling");
+ if (sibling && Strcmp(nodeType(sibling), "class") == 0)
+ break;
+ }
+ if (sibling)
+ break;
+ n = parentNode(n);
+ if (!n)
+ break;
+ nstab = Getattr(n, "sym:symtab");
+ n = 0;
+ if ((!nstab) || (nstab == stab)) {
+ break;
+ }
+ stab = nstab;
+ }
+ if (n) {
+ /* Found a match. Look at the prefix. We only allow
+ the cases where we want a proxy class for the particular type */
+ bool acceptable_prefix =
+ (Len(prefix) == 0) || // simple type (pass by value)
+ (Strcmp(prefix, "p.") == 0) || // pointer
+ (Strcmp(prefix, "r.") == 0) || // reference
+ (Strcmp(prefix, "z.") == 0) || // rvalue reference
+ SwigType_prefix_is_simple_1D_array(prefix); // Simple 1D array (not arrays of pointers/references)
+ // Also accept pointer by const reference, not non-const pointer reference
+ if (!acceptable_prefix && (Strcmp(prefix, "r.p.") == 0)) {
+ Delete(prefix);
+ prefix = SwigType_prefix(ty1);
+ acceptable_prefix = (Strncmp(prefix, "r.q(const", 9) == 0);
+ }
+ if (acceptable_prefix) {
+ SwigType *cs = Copy(s);
+ if (!classtypes)
+ classtypes = NewHash();
+ Setattr(classtypes, cs, n);
+ Delete(cs);
+ } else {
+ n = 0;
+ }
+ }
+ Delete(prefix);
+ Delete(base);
+ Delete(ty2);
+ Delete(ty1);
+ }
+ if (n && (GetFlag(n, "feature:ignore") || Getattr(n, "feature:onlychildren"))) {
+ n = 0;
+ }
+
+ return n;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::enumLookup()
+ *
+ * Finds and returns the Node containing the enum declaration for the (enum)
+ * type passed in.
+ * ----------------------------------------------------------------------------- */
+
+Node *Language::enumLookup(SwigType *s) {
+ static Hash *enumtypes = 0;
+
+ Node *n = 0;
+
+ /* Look in hash of cached values */
+ n = enumtypes ? Getattr(enumtypes, s) : 0;
+ if (!n) {
+ Symtab *stab = 0;
+ SwigType *lt = SwigType_ltype(s);
+ SwigType *ty1 = SwigType_typedef_resolve_all(lt);
+ SwigType *ty2 = SwigType_strip_qualifiers(ty1);
+
+ String *base = SwigType_base(ty2);
+
+ Replaceall(base, "enum ", "");
+ String *prefix = SwigType_prefix(ty2);
+
+ if (strncmp(Char(base), "::", 2) == 0) {
+ String *oldbase = base;
+ base = NewString(Char(base) + 2);
+ Delete(oldbase);
+ }
+
+ /* Look for type in symbol table */
+ while (!n) {
+ Hash *nstab;
+ n = Swig_symbol_clookup(base, stab);
+ if (!n)
+ break;
+ if (Equal(nodeType(n), "enum"))
+ break;
+ if (Equal(nodeType(n), "enumforward") && GetFlag(n, "enumMissing"))
+ break;
+ n = parentNode(n);
+ if (!n)
+ break;
+ nstab = Getattr(n, "sym:symtab");
+ n = 0;
+ if ((!nstab) || (nstab == stab)) {
+ break;
+ }
+ stab = nstab;
+ }
+ if (n) {
+ /* Found a match. Look at the prefix. We only allow simple types. */
+ if (Len(prefix) == 0) { /* Simple type */
+ if (!enumtypes)
+ enumtypes = NewHash();
+ Setattr(enumtypes, Copy(s), n);
+ } else {
+ n = 0;
+ }
+ }
+ Delete(prefix);
+ Delete(base);
+ Delete(ty2);
+ Delete(ty1);
+ Delete(lt);
+ }
+ if (n && (GetFlag(n, "feature:ignore"))) {
+ n = 0;
+ }
+
+ return n;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::allow_overloading()
+ * ----------------------------------------------------------------------------- */
+
+void Language::allow_overloading(int val) {
+ overloading = val;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::allow_multiple_input()
+ * ----------------------------------------------------------------------------- */
+
+void Language::allow_multiple_input(int val) {
+ multiinput = val;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::enable_cplus_runtime_mode()
+ * ----------------------------------------------------------------------------- */
+
+void Language::enable_cplus_runtime_mode() {
+ cplus_runtime = 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::cplus_runtime_mode()
+ * ----------------------------------------------------------------------------- */
+
+int Language::cplus_runtime_mode() {
+ return cplus_runtime;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::allow_directors()
+ * ----------------------------------------------------------------------------- */
+
+void Language::allow_directors(int val) {
+ directors = val;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::directorsEnabled()
+ * ----------------------------------------------------------------------------- */
+
+int Language::directorsEnabled() const {
+ return director_language && CPlusPlus && (directors || director_mode);
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::allow_dirprot()
+ * ----------------------------------------------------------------------------- */
+
+void Language::allow_dirprot(int val) {
+ director_protected_mode = val;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::allow_allprotected()
+ * ----------------------------------------------------------------------------- */
+
+void Language::allow_allprotected(int val) {
+ all_protected_mode = val;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::dirprot_mode()
+ * ----------------------------------------------------------------------------- */
+
+int Language::dirprot_mode() const {
+ return directorsEnabled() ? director_protected_mode : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::need_nonpublic_ctor()
+ * ----------------------------------------------------------------------------- */
+
+int Language::need_nonpublic_ctor(Node *n) {
+ /*
+ detects when a protected constructor is needed, which is always
+ the case if 'dirprot' mode is used. However, if that is not the
+ case, we will try to strictly emit what is minimal to don't break
+ the generated, while preserving compatibility with java, which
+ always try to emit the default constructor.
+
+ rules:
+
+ - when dirprot mode is used, the protected constructors are
+ always needed.
+
+ - the protected default constructor is always needed.
+
+ - if dirprot mode is not used, the protected constructors will be
+ needed only if:
+
+ - there is no any public constructor in the class, and
+ - there is no protected default constructor
+
+ In that case, all the declared protected constructors are
+ needed since we don't know which one to pick up.
+
+ Note: given all the complications here, I am always in favor to
+ always enable 'dirprot', since is the C++ idea of protected
+ members, and use %ignore for the method you don't want to add in
+ the director class.
+ */
+ if (directorsEnabled()) {
+ if (is_protected(n)) {
+ if (dirprot_mode()) {
+ /* when using dirprot mode, the protected constructors are
+ always needed */
+ return 1;
+ } else {
+ int is_default_ctor = !ParmList_numrequired(Getattr(n, "parms"));
+ if (is_default_ctor) {
+ /* the default protected constructor is always needed, for java compatibility */
+ return 1;
+ } else {
+ /* check if there is a public constructor */
+ Node *parent = Swig_methodclass(n);
+ int public_ctor = Getattr(parent, "allocate:default_constructor")
+ || Getattr(parent, "allocate:public_constructor");
+ if (!public_ctor) {
+ /* if not, the protected constructor will be needed only
+ if there is no protected default constructor declared */
+ int no_prot_default_ctor = !Getattr(parent, "allocate:default_base_constructor");
+ return no_prot_default_ctor;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::need_nonpublic_member()
+ * ----------------------------------------------------------------------------- */
+int Language::need_nonpublic_member(Node *n) {
+ if (directorsEnabled() && DirectorClassName) {
+ if (is_protected(n)) {
+ if (dirprot_mode()) {
+ /* when using dirprot mode, the protected members are always needed. */
+ return 1;
+ } else {
+ /* if the method is pure virtual, we need it. */
+ int pure_virtual = (Cmp(Getattr(n, "value"), "0") == 0);
+ return pure_virtual;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Language::is_smart_pointer()
+ * ----------------------------------------------------------------------------- */
+
+int Language::is_smart_pointer() const {
+ return SmartPointer;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::makeParameterName()
+ *
+ * Inputs:
+ * n - Node
+ * p - parameter node
+ * arg_num - parameter argument number
+ * setter - set this flag when wrapping variables
+ * Return:
+ * arg - a unique parameter name
+ * ----------------------------------------------------------------------------- */
+String *Language::makeParameterName(Node *n, Parm *p, int arg_num, bool setter) const {
+
+ String *arg = 0;
+ String *pn = Getattr(p, "name");
+
+ // Check if parameter name is a duplicate.
+ int count = 0;
+ ParmList *plist = Getattr(n, "parms");
+ while (plist) {
+ if ((Cmp(pn, Getattr(plist, "name")) == 0))
+ count++;
+ plist = nextSibling(plist);
+ }
+
+ // If the parameter has no name at all or has a non-unique name, replace it with "argN".
+ if (!pn || count > 1) {
+ arg = NewStringf("arg%d", arg_num);
+ } else {
+ // Otherwise, try to use the original C name, but modify it if necessary to avoid conflicting with the language keywords.
+ arg = Swig_name_make(p, 0, pn, 0, 0);
+ }
+
+ if (setter && Cmp(arg, "self") != 0) {
+ // Some languages (C#) insist on calling the input variable "value" while
+ // others (D, Java) could, in principle, use something different but this
+ // would require more work, and so we just use "value" for them too.
+ // For setters the parameter name sometimes includes C++ scope resolution which needs removing.
+ Delete(arg);
+ arg = NewString("value");
+ }
+
+ return arg;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::()
+ * ----------------------------------------------------------------------------- */
+
+bool Language::isNonVirtualProtectedAccess(Node *n) const {
+ // Ideally is_non_virtual_protected_access() would contain all this logic, see
+ // comments therein about vtable.
+ return DirectorClassName && is_non_virtual_protected_access(n);
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::extraDirectorProtectedCPPMethodsRequired()
+ * ----------------------------------------------------------------------------- */
+
+bool Language::extraDirectorProtectedCPPMethodsRequired() const {
+ return true;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::nestedClassesSupport()
+ * ----------------------------------------------------------------------------- */
+
+Language::NestedClassSupport Language::nestedClassesSupport() const {
+ return NCS_Unknown;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::kwargsSupport()
+ * ----------------------------------------------------------------------------- */
+
+bool Language::kwargsSupport() const {
+ return false;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::is_wrapping_class()
+ * ----------------------------------------------------------------------------- */
+
+int Language::is_wrapping_class() const {
+ return InClass;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::getCurrentClass()
+ * ----------------------------------------------------------------------------- */
+
+Node *Language::getCurrentClass() const {
+ return CurrentClass;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::getNSpace()
+ * ----------------------------------------------------------------------------- */
+
+String *Language::getNSpace() const {
+ return NSpace;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::getClassName()
+ * ----------------------------------------------------------------------------- */
+
+String *Language::getClassName() const {
+ return ClassName;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::getClassPrefix()
+ * ----------------------------------------------------------------------------- */
+
+String *Language::getClassPrefix() const {
+ return ClassPrefix;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::getEnumClassPrefix()
+ * ----------------------------------------------------------------------------- */
+
+String *Language::getEnumClassPrefix() const {
+ return EnumClassPrefix;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::getClassType()
+ * ----------------------------------------------------------------------------- */
+
+String *Language::getClassType() const {
+ return ClassType;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::abstractClassTest()
+ * ----------------------------------------------------------------------------- */
+//#define SWIG_DEBUG
+int Language::abstractClassTest(Node *n) {
+ /* check for non public operator new */
+ if (GetFlag(n, "feature:notabstract"))
+ return 0;
+ if (Getattr(n, "allocate:nonew"))
+ return 1;
+
+ // A class cannot be instantiated if one of its bases has a private destructor
+ // Note that if the above does not hold the class can be instantiated if its own destructor is private
+ List *bases = Getattr(n, "bases");
+ if (bases) {
+ for (int i = 0; i < Len(bases); i++) {
+ Node *b = Getitem(bases, i);
+ if (GetFlag(b, "allocate:private_destructor"))
+ return 1;
+ }
+ }
+
+ /* now check for the rest */
+ List *abstracts = Getattr(n, "abstracts");
+ if (!abstracts)
+ return 0;
+ int labs = Len(abstracts);
+#ifdef SWIG_DEBUG
+ List *allbases = Getattr(n, "allbases");
+ Printf(stderr, "testing %s %d %d\n", Getattr(n, "name"), labs, Len(allbases));
+#endif
+ if (!labs)
+ return 0; /*strange, but need to be fixed */
+ if (abstracts && !directorsEnabled())
+ return 1;
+ if (!GetFlag(n, "feature:director"))
+ return 1;
+
+ Node *dirabstract = 0;
+ Node *vtable = Getattr(n, "vtable");
+ if (vtable) {
+#ifdef SWIG_DEBUG
+ Printf(stderr, "vtable %s %d %d\n", Getattr(n, "name"), Len(vtable), labs);
+#endif
+ for (int i = 0; i < labs; i++) {
+ Node *ni = Getitem(abstracts, i);
+ Node *method_id = vtable_method_id(ni);
+ if (!method_id)
+ continue;
+ bool exists_item = false;
+ int len = Len(vtable);
+ for (int i = 0; i < len; i++) {
+ Node *item = Getitem(vtable, i);
+ String *check_item = Getattr(item, "vmid");
+ if (Strcmp(method_id, check_item) == 0) {
+ exists_item = true;
+ break;
+ }
+ }
+#ifdef SWIG_DEBUG
+ Printf(stderr, "method %s %d\n", method_id, exists_item ? 1 : 0);
+#endif
+ Delete(method_id);
+ if (!exists_item) {
+ dirabstract = ni;
+ break;
+ }
+ }
+ if (dirabstract) {
+ if (is_public(dirabstract)) {
+ Swig_warning(WARN_LANG_DIRECTOR_ABSTRACT, Getfile(n), Getline(n),
+ "Director class '%s' is abstract, abstract method '%s' is not accessible, maybe due to multiple inheritance or 'nodirector' feature\n",
+ SwigType_namestr(Getattr(n, "name")), Getattr(dirabstract, "name"));
+ } else {
+ Swig_warning(WARN_LANG_DIRECTOR_ABSTRACT, Getfile(n), Getline(n),
+ "Director class '%s' is abstract, abstract method '%s' is private\n", SwigType_namestr(Getattr(n, "name")), Getattr(dirabstract, "name"));
+ }
+ return 1;
+ }
+ } else {
+ return 1;
+ }
+ return 0;
+}
+
+void Language::setSubclassInstanceCheck(String *nc) {
+ none_comparison = nc;
+}
+
+void Language::setOverloadResolutionTemplates(String *argc, String *argv) {
+ Delete(argc_template_string);
+ argc_template_string = Copy(argc);
+ Delete(argv_template_string);
+ argv_template_string = Copy(argv);
+}
+
+int Language::is_assignable(Node *n) {
+ if (GetFlag(n, "feature:immutable"))
+ return 0;
+ SwigType *type = Getattr(n, "type");
+ Node *cn = 0;
+ SwigType *ftd = SwigType_typedef_resolve_all(type);
+ SwigType *td = SwigType_strip_qualifiers(ftd);
+ if (SwigType_type(td) == T_USER) {
+ cn = Swig_symbol_clookup(td, 0);
+ if (cn) {
+ if ((Strcmp(nodeType(cn), "class") == 0)) {
+ if (Getattr(cn, "allocate:noassign")) {
+ SetFlag(n, "feature:immutable");
+ Delete(ftd);
+ Delete(td);
+ return 0;
+ }
+ }
+ }
+ }
+ Delete(ftd);
+ Delete(td);
+ return 1;
+}
+
+String *Language::runtimeCode() {
+ return NewString("");
+}
+
+String *Language::defaultExternalRuntimeFilename() {
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::replaceSpecialVariables()
+ *
+ * Language modules should implement this if special variables are to be handled
+ * correctly in the $typemap(...) special variable macro.
+ * method - typemap method name
+ * tm - string containing typemap contents
+ * parm - a parameter describing the typemap type to be handled
+ * ----------------------------------------------------------------------------- */
+void Language::replaceSpecialVariables(String *method, String *tm, Parm *parm) {
+ (void)method;
+ (void)tm;
+ (void)parm;
+}
+
+Language *Language::instance() {
+ return this_;
+}
+
+Hash *Language::getClassHash() const {
+ return classhash;
+}
+
diff --git a/contrib/tools/swig/Source/Modules/lua.cxx b/contrib/tools/swig/Source/Modules/lua.cxx
new file mode 100644
index 00000000000..188b11c2b0a
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/lua.cxx
@@ -0,0 +1,2282 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * lua.cxx
+ *
+ * Lua language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+/* NEW LANGUAGE NOTE:
+ * ver001
+ this is simply a copy of tcl8.cxx, which has been renamed
+ * ver002
+ all non essential code commented out, program now does virtually nothing
+ it prints to stderr the list of functions to wrap, but does not create
+ the XXX_wrap.c file
+ * ver003
+ added back top(), still prints the list of fns to stderr
+ but now creates a rather empty XXX_wrap.c with some basic boilerplate code
+ * ver004
+ very basic version of functionWrapper()
+ also uncommented usage_string() to keep compiler happy
+ this will start producing proper looking code soon (I hope)
+ produced the wrapper code, but without any type conversion (in or out)
+ generates a few warning because of no wrappering
+ does not generate SWIG_init()
+ reason for this is that lua.swg is empty
+ we will need to add code into this to make it work
+ * ver005/6
+ massive rework, basing work on the pike module instead of tcl
+ (pike module it only 1/3 of the size)(though not as complete)
+ * ver007
+ added simple type checking
+ * ver008
+ INPUT, OUTPUT, INOUT typemaps handled (though not all types yet)
+ * ver009
+ class support: ok for basic types, but methods still TDB
+ (code is VERY messed up & needs to be cleaned)
+ * ver010
+ Added support for embedded Lua. Try swig -lua -help for more information
+*/
+
+#include "swigmod.h"
+#include "cparse.h"
+
+/**** Diagnostics:
+ With the #define REPORT(), you can change the amount of diagnostics given
+ This helps me search the parse tree & figure out what is going on inside SWIG
+ (because its not clear or documented)
+*/
+#define REPORT(T,D) // no info:
+//#define REPORT(T,D) {Printf(stdout,T"\n");} // only title
+//#define REPORT(T,D) {Printf(stdout,T" %p\n",n);} // title & pointer
+//#define REPORT(T,D) {Printf(stdout,T"\n");display_mapping(D);} // the works
+//#define REPORT(T,D) {Printf(stdout,T"\n");if(D)Swig_print_node(D);} // the works
+
+void display_mapping(DOH *d) {
+ if (d == 0 || !DohIsMapping(d))
+ return;
+ for (Iterator it = First(d); it.item; it = Next(it)) {
+ if (DohIsString(it.item))
+ Printf(stdout, " %s = %s\n", it.key, it.item);
+ else if (DohIsMapping(it.item))
+ Printf(stdout, " %s = <mapping>\n", it.key);
+ else if (DohIsSequence(it.item))
+ Printf(stdout, " %s = <sequence>\n", it.key);
+ else
+ Printf(stdout, " %s = <unknown>\n", it.key);
+ }
+}
+
+extern "C"
+{
+ static int compareByLen(const DOH *f, const DOH *s) {
+ return Len(s) - Len(f);
+ }
+}
+
+
+/* NEW LANGUAGE NOTE:***********************************************
+ most of the default options are handled by SWIG
+ you can add new ones here
+ (though for now I have not bothered)
+NEW LANGUAGE NOTE:END ************************************************/
+static const char *usage = "\
+Lua Options (available with -lua)\n\
+ -elua - Generates LTR compatible wrappers for smaller devices running elua\n\
+ -eluac - LTR compatible wrappers in \"crass compress\" mode for elua\n\
+ -elua-emulate - Emulates behaviour of eLua. Useful only for testing.\n\
+ Incompatible with -elua/-eluac options.\n\
+ -nomoduleglobal - Do not register the module name as a global variable \n\
+ but return the module table from calls to require.\n\
+ -no-old-metatable-bindings\n\
+ - Disable support for old-style bindings name generation, some\n\
+ old-style members scheme etc.\n\
+ -squash-bases - Squashes symbols from all inheritance tree of a given class\n\
+ into itself. Emulates pre-SWIG3.0 inheritance. Insignificantly\n\
+ speeds things up, but increases memory consumption.\n\
+\n";
+
+static int nomoduleglobal = 0;
+static int elua_ltr = 0;
+static int eluac_ltr = 0;
+static int elua_emulate = 0;
+static int squash_bases = 0;
+/* The new metatable bindings were introduced in SWIG 3.0.0.
+ * old_metatable_bindings in v2:
+ * 1. static methods will be put into the scope their respective class
+ * belongs to as well as into the class scope itself. (only for classes without %nspace given)
+ * 2. The layout in elua mode is somewhat different
+ */
+static int old_metatable_bindings = 1;
+static int old_compatible_names = 1; // This flag can temporarily disable backward compatible names generation if old_metatable_bindings is enabled
+
+/* NEW LANGUAGE NOTE:***********************************************
+ To add a new language, you need to derive your class from
+ Language and the overload various virtual functions
+ (more on this as I figure it out)
+NEW LANGUAGE NOTE:END ************************************************/
+
+class LUA:public Language {
+private:
+
+ File *f_begin;
+ File *f_runtime;
+ File *f_header;
+ File *f_wrappers;
+ File *f_init;
+ File *f_initbeforefunc;
+ String *s_luacode; // luacode to be called during init
+ String *module; //name of the module
+
+ // Parameters for current class. NIL if not parsing class
+ int have_constructor;
+ int have_destructor;
+ String *destructor_action;
+ // This variable holds the name of the current class in Lua. Usually it is
+ // the same as C++ class name, but rename directives can change it.
+ String *proxy_class_name;
+ // This is a so called fully qualified symname - the above proxy class name
+ // prepended with class namespace. If class Lua name is the same as class C++ name,
+ // then it is basically C++ fully qualified name with colons replaced with dots.
+ String *full_proxy_class_name;
+ // All static methods and/or variables are treated as if they were in the
+ // special C++ namespace $(classname).SwigStatic. This is internal mechanism only
+ // and is not visible to user in any manner. This variable holds the name
+ // of such pseudo-namespace a.k.a the result of above expression evaluation
+ String *class_static_nspace;
+ // This variable holds the name of generated C function that acts as a constructor
+ // for the currently parsed class.
+ String *constructor_name;
+
+ // Many wrappers forward calls to each other, for example staticmembervariableHandler
+ // forwards calls to variableHandler, which, in turn, makes to call to functionWrapper.
+ // In order to access information about whether it is a static member of class or just
+ // a plain old variable, the current array is kept and used as a 'log' of the call stack.
+ enum TState {
+ NO_CPP,
+ VARIABLE,
+ GLOBAL_FUNC,
+ GLOBAL_VAR,
+ MEMBER_FUNC,
+ CONSTRUCTOR,
+ DESTRUCTOR,
+ MEMBER_VAR,
+ STATIC_FUNC,
+ STATIC_VAR,
+ STATIC_CONST, // enums and things like static const int x = 5;
+ ENUM_CONST, // This is only needed for backward compatibility in C mode
+
+ STATES_COUNT
+ };
+ bool current[STATES_COUNT];
+
+public:
+
+ /* ---------------------------------------------------------------------
+ * LUA()
+ *
+ * Initialize member data
+ * --------------------------------------------------------------------- */
+
+ LUA():
+ f_begin(0),
+ f_runtime(0),
+ f_header(0),
+ f_wrappers(0),
+ f_init(0),
+ f_initbeforefunc(0),
+ s_luacode(0),
+ module(0),
+ have_constructor(0),
+ have_destructor(0),
+ destructor_action(0),
+ proxy_class_name(0),
+ full_proxy_class_name(0),
+ class_static_nspace(0),
+ constructor_name(0) {
+ for (int i = 0; i < STATES_COUNT; i++)
+ current[i] = false;
+ }
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ This is called to initialise the system & read any command line args
+ most of this is boilerplate code, except the command line args
+ which depends upon what args your code supports
+ NEW LANGUAGE NOTE:END *********************************************** */
+
+ /* ---------------------------------------------------------------------
+ * main()
+ *
+ * Parse command line options and initializes variables.
+ * --------------------------------------------------------------------- */
+
+ virtual void main(int argc, char *argv[]) {
+
+ /* Set location of SWIG library */
+ SWIG_library_directory("lua");
+
+ /* Look for certain command line options */
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-help") == 0) { // usage flags
+ fputs(usage, stdout);
+ } else if (strcmp(argv[i], "-nomoduleglobal") == 0) {
+ nomoduleglobal = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-elua") == 0) {
+ elua_ltr = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-eluac") == 0) {
+ eluac_ltr = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-no-old-metatable-bindings") == 0) {
+ Swig_mark_arg(i);
+ old_metatable_bindings = 0;
+ } else if (strcmp(argv[i], "-squash-bases") == 0) {
+ Swig_mark_arg(i);
+ squash_bases = 1;
+ } else if (strcmp(argv[i], "-elua-emulate") == 0) {
+ Swig_mark_arg(i);
+ elua_emulate = 1;
+ }
+ }
+ }
+
+ if (elua_emulate && (eluac_ltr || elua_ltr )) {
+ Printf(stderr, "Cannot have -elua-emulate with either -eluac or -elua\n");
+ Swig_arg_error();
+ }
+
+ // Set elua_ltr if elua_emulate is requested
+ if(elua_emulate)
+ elua_ltr = 1;
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ This is the boilerplate code, setting a few #defines
+ and which lib directory to use
+ the SWIG_library_directory() is also boilerplate code
+ but it always seems to be the first line of code
+ NEW LANGUAGE NOTE:END *********************************************** */
+ /* Add a symbol to the parser for conditional compilation */
+ Preprocessor_define("SWIGLUA 1", 0);
+
+ /* Set language-specific configuration file */
+ SWIG_config_file("lua.swg");
+
+ /* Set typemap language */
+ SWIG_typemap_lang("lua");
+
+ /* Enable overloaded methods support */
+ allow_overloading();
+ }
+
+
+
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ After calling main, SWIG parses the code to wrap (I believe)
+ then calls top()
+ in this is more boilerplate code to set everything up
+ and a call to Language::top()
+ which begins the code generations by calling the member fns
+ after all that is more boilerplate code to close all down
+ (overall there is virtually nothing here that needs to be edited
+ just use as is)
+ NEW LANGUAGE NOTE:END *********************************************** */
+ /* ---------------------------------------------------------------------
+ * top()
+ * --------------------------------------------------------------------- */
+
+ virtual int top(Node *n) {
+ /* Get the module name */
+ module = Getattr(n, "name");
+
+ /* Get the output file name */
+ String *outfile = Getattr(n, "outfile");
+
+ /* Open the output file */
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+ f_initbeforefunc = NewString("");
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("initbeforefunc", f_initbeforefunc);
+
+
+ s_luacode = NewString("");
+ Swig_register_filebyname("luacode", s_luacode);
+
+ current[NO_CPP] = true;
+
+ /* Standard stuff for the SWIG runtime section */
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n\n#ifndef SWIGLUA\n#define SWIGLUA\n#endif\n\n");
+
+ emitLuaFlavor(f_runtime);
+
+ if (nomoduleglobal) {
+ Printf(f_runtime, "#define SWIG_LUA_NO_MODULE_GLOBAL\n");
+ } else {
+ Printf(f_runtime, "#define SWIG_LUA_MODULE_GLOBAL\n");
+ }
+ if (squash_bases)
+ Printf(f_runtime, "#define SWIG_LUA_SQUASH_BASES\n");
+
+ // if (NoInclude) {
+ // Printf(f_runtime, "#define SWIG_NOINCLUDE\n");
+ // }
+
+ Printf(f_runtime, "\n");
+
+ //String *init_name = NewStringf("%(title)s_Init", module);
+ //Printf(f_header, "#define SWIG_init %s\n", init_name);
+ //Printf(f_header, "#define SWIG_name \"%s\"\n", module);
+ /* SWIG_import is a special function name for importing within Lua5.1 */
+ //Printf(f_header, "#define SWIG_import luaopen_%s\n\n", module);
+ Printf(f_header, "#define SWIG_name \"%s\"\n", module);
+ Printf(f_header, "#define SWIG_init luaopen_%s\n", module);
+ Printf(f_header, "#define SWIG_init_user luaopen_%s_user\n\n", module);
+ Printf(f_header, "#define SWIG_LUACODE luaopen_%s_luacode\n", module);
+
+ Printf(f_wrappers, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
+
+ /* %init code inclusion, effectively in the SWIG_init function */
+ Printf(f_init, "void SWIG_init_user(lua_State* L)\n{\n");
+ Language::top(n);
+ Printf(f_init, "/* exec Lua code if applicable */\nSWIG_Lua_dostring(L,SWIG_LUACODE);\n");
+ Printf(f_init, "}\n");
+
+ // Done. Close up the module & write to the wrappers
+ closeNamespaces(f_wrappers);
+ Printf(f_wrappers, "#ifdef __cplusplus\n}\n#endif\n");
+
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ this basically combines several of the strings together
+ and then writes it all to a file
+ NEW LANGUAGE NOTE:END *********************************************** */
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+ Dump(f_wrappers, f_begin);
+ Dump(f_initbeforefunc, f_begin);
+ /* for the Lua code it needs to be properly escaped to be added into the C/C++ code */
+ escapeCode(s_luacode);
+ Printf(f_begin, "const char* SWIG_LUACODE=\n \"%s\";\n\n", s_luacode);
+ Wrapper_pretty_print(f_init, f_begin);
+ /* Close all of the files */
+ Delete(s_luacode);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_initbeforefunc);
+ Delete(f_runtime);
+ Delete(f_begin);
+
+ /* Done */
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * importDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int importDirective(Node *n) {
+ return Language::importDirective(n);
+ }
+
+ /* ------------------------------------------------------------
+ * cDeclaration()
+ * It copies sym:name to lua:name to preserve its original value
+ * ------------------------------------------------------------ */
+
+ virtual int cDeclaration(Node *n) {
+ // class 'Language' is messing with symname in a really heavy way.
+ // Although documentation states that sym:name is a name in
+ // the target language space, it is not true. sym:name and
+ // its derivatives are used in various places, including
+ // behind-the-scene C code generation. The best way is not to
+ // touch it at all.
+ // But we need to know what was the name of function/variable
+ // etc that user desired, that's why we store correct symname
+ // as lua:name
+ String *symname = Getattr(n, "sym:name");
+ if (symname)
+ Setattr(n, "lua:name", symname);
+ return Language::cDeclaration(n);
+ }
+ virtual int constructorDeclaration(Node *n) {
+ Setattr(n, "lua:name", Getattr(n, "sym:name"));
+ return Language::constructorDeclaration(n);
+ }
+ virtual int destructorDeclaration(Node *n) {
+ Setattr(n, "lua:name", Getattr(n, "sym:name"));
+ return Language::destructorDeclaration(n);
+ }
+ /* NEW LANGUAGE NOTE:***********************************************
+ This is it!
+ you get this one right, and most of your work is done
+ but its going to take some file to get it working right
+ quite a bit of this is generally boilerplate code
+ (or stuff I don't understand)
+ that which matters will have extra added comments
+ NEW LANGUAGE NOTE:END *********************************************** */
+ /* ---------------------------------------------------------------------
+ * functionWrapper()
+ *
+ * Create a function declaration and register it with the interpreter.
+ * --------------------------------------------------------------------- */
+
+ /* -----------------------------------------------------------------------
+ * registerMethod()
+ *
+ * Determines wrap name of a method, its scope etc and calls
+ * registerMethod overload with correct arguments
+ * Overloaded variant adds method to the "methods" array of specified lua scope/class
+ * ---------------------------------------------------------------------- */
+
+ void registerMethod(Node *n, bool overwrite = false, String *overwriteLuaScope = 0) {
+ String *symname = Getattr(n, "sym:name");
+ assert(symname);
+
+ if (Getattr(n, "sym:nextSibling"))
+ return;
+
+ // Lua scope. It is not symbol NSpace, it is the actual key to retrieve getCArraysHash.
+ String *luaScope = luaCurrentSymbolNSpace();
+ if (overwrite)
+ luaScope = overwriteLuaScope;
+
+ String *wrapname = 0;
+ String *mrename;
+ if (current[NO_CPP] || !getCurrentClass()) {
+ mrename = symname;
+ } else {
+ assert(!current[NO_CPP]);
+ if (current[STATIC_FUNC] || current[MEMBER_FUNC]) {
+ mrename = Swig_name_member(getNSpace(), getClassPrefix(), symname);
+ } else {
+ mrename = symname;
+ }
+ }
+ wrapname = Swig_name_wrapper(mrename);
+ registerMethod(n, wrapname, luaScope);
+ }
+
+ /* -----------------------------------------------------------------------
+ * registerMethod()
+ *
+ * Add method to the "methods" C array of given namespace/class
+ * ---------------------------------------------------------------------- */
+
+ void registerMethod(Node *n, String* wname, String *luaScope) {
+ assert(n);
+ Hash *nspaceHash = getCArraysHash(luaScope);
+ String *s_ns_methods_tab = Getattr(nspaceHash, "methods");
+ String *lua_name = Getattr(n, "lua:name");
+ if (elua_ltr || eluac_ltr)
+ Printv(s_ns_methods_tab, tab4, "{LSTRKEY(\"", lua_name, "\")", ", LFUNCVAL(", wname, ")", "},\n", NIL);
+ else
+ Printv(s_ns_methods_tab, tab4, "{ \"", lua_name, "\", ", wname, "},\n", NIL);
+ // Add to the metatable if method starts with '__'
+ const char * tn = Char(lua_name);
+ if (tn[0]=='_' && tn[1] == '_' && !eluac_ltr) {
+ String *metatable_tab = Getattr(nspaceHash, "metatable");
+ assert(metatable_tab);
+ if (elua_ltr)
+ Printv(metatable_tab, tab4, "{LSTRKEY(\"", lua_name, "\")", ", LFUNCVAL(", wname, ")", "},\n", NIL);
+ else
+ Printv(metatable_tab, tab4, "{ \"", lua_name, "\", ", wname, "},\n", NIL);
+ }
+ }
+
+ virtual int functionWrapper(Node *n) {
+ REPORT("functionWrapper", n);
+
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ String *lua_name = Getattr(n, "lua:name");
+ assert(lua_name);
+ SwigType *d = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ Parm *p;
+ String *tm;
+ int i;
+ //Printf(stdout,"functionWrapper %s %s %d\n",name,iname,current);
+
+ String *overname = 0;
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!luaAddSymbol(lua_name, n)) {
+ return SWIG_ERROR;
+ }
+ }
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ the wrapper object holds all the wrapper code
+ we need to add a couple of local variables
+ NEW LANGUAGE NOTE:END *********************************************** */
+ Wrapper *f = NewWrapper();
+ Wrapper_add_local(f, "SWIG_arg", "int SWIG_arg = 0");
+
+
+ String *wname = Swig_name_wrapper(iname);
+ if (overname) {
+ Append(wname, overname);
+ }
+ if (current[CONSTRUCTOR]) {
+ if (constructor_name != 0)
+ Delete(constructor_name);
+ constructor_name = Copy(wname);
+ }
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ the format of a lua fn is:
+ static int wrap_XXX(lua_State* L){...}
+ this line adds this into the wrapper code
+ NEW LANGUAGE NOTE:END *********************************************** */
+ Printv(f->def, "static int ", wname, "(lua_State* L) {", NIL);
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ this prints the list of args, eg for a C fn
+ int gcd(int x,int y);
+ it will print
+ int arg1;
+ int arg2;
+ NEW LANGUAGE NOTE:END *********************************************** */
+ /* Write code to extract function parameters. */
+ emit_parameter_variables(l, f);
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+ Setattr(n, "wrap:parms", l);
+
+ /* Get number of required and total arguments */
+ int num_arguments = emit_num_arguments(l);
+ int num_required = emit_num_required(l);
+ int varargs = emit_isvarargs(l);
+
+ // Check if we have to ignore arguments that are passed by LUA.
+ // Needed for unary minus, where lua passes two arguments and
+ // we have to ignore the second.
+
+ int args_to_ignore = 0;
+ if (Getattr(n, "lua:ignore_args")) {
+ args_to_ignore = GetInt(n, "lua:ignore_args");
+ }
+
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ from here on in, it gets rather hairy
+ this is the code to convert from the scripting language to C/C++
+ some of the stuff will refer to the typemaps code written in your swig file
+ (lua.swg), and some is done in the code here
+ I suppose you could do all the conversion in C, but it would be a nightmare to do
+ NEW LANGUAGE NOTE:END *********************************************** */
+ /* Generate code for argument marshalling */
+ // String *description = NewString("");
+ /* NEW LANGUAGE NOTE:***********************************************
+ argument_check is a new feature I added to check types of arguments:
+ eg for int gcd(int,int)
+ I want to check that arg1 & arg2 really are integers
+ NEW LANGUAGE NOTE:END *********************************************** */
+ String *argument_check = NewString("");
+ String *argument_parse = NewString("");
+ String *checkfn = NULL;
+ char source[64];
+ Printf(argument_check, "SWIG_check_num_args(\"%s\",%d,%d)\n", Swig_name_str(n), num_required + args_to_ignore, num_arguments + args_to_ignore);
+
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+
+ /* Look for an input typemap */
+ sprintf(source, "%d", i + 1);
+ if ((tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$source", source);
+ Replaceall(tm, "$target", ln);
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source);
+ if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+ /* NEW LANGUAGE NOTE:***********************************************
+ look for a 'checkfn' typemap
+ this an additional parameter added to the in typemap
+ if found the type will be tested for
+ this will result in code either in the
+ argument_check or argument_parse string
+ NEW LANGUAGE NOTE:END *********************************************** */
+ if ((checkfn = Getattr(p, "tmap:in:checkfn"))) {
+ if (i < num_required) {
+ Printf(argument_check, "if(!%s(L,%s))", checkfn, source);
+ } else {
+ Printf(argument_check, "if(lua_gettop(L)>=%s && !%s(L,%s))", source, checkfn, source);
+ }
+ Printf(argument_check, " SWIG_fail_arg(\"%s\",%s,\"%s\");\n", Swig_name_str(n), source, SwigType_str(pt, 0));
+ }
+ /* NEW LANGUAGE NOTE:***********************************************
+ lua states the number of arguments passed to a function using the fn
+ lua_gettop()
+ we can use this to deal with default arguments
+ NEW LANGUAGE NOTE:END *********************************************** */
+ if (i < num_required) {
+ Printf(argument_parse, "%s\n", tm);
+ } else {
+ Printf(argument_parse, "if(lua_gettop(L)>=%s){%s}\n", source, tm);
+ }
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ } else {
+ /* NEW LANGUAGE NOTE:***********************************************
+ // why is this code not called when I don't have a typemap?
+ // instead of giving a warning, no code is generated
+ NEW LANGUAGE NOTE:END *********************************************** */
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
+ break;
+ }
+ }
+
+ // add all argcheck code
+ Printv(f->code, argument_check, argument_parse, NIL);
+
+ /* Check for trailing varargs */
+ if (varargs) {
+ if (p && (tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$input", "varargs");
+ Printv(f->code, tm, "\n", NIL);
+ }
+ }
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ String *cleanup = NewString("");
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert argument output code */
+ String *outarg = NewString("");
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ // // managing the number of returning variables
+ // if (numoutputs=Getattr(p,"tmap:argout:numoutputs")){
+ // int i=GetInt(p,"tmap:argout:numoutputs");
+ // printf("got argout:numoutputs of %d\n",i);
+ // returnval+=GetInt(p,"tmap:argout:numoutputs");
+ // }
+ // else returnval++;
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+ Replaceall(tm, "$target", Swig_cresult_name());
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Remember C name of the wrapping function
+ Setattr(n, "wrap:name", wname);
+
+ /* Emit the function call */
+ String *actioncode = emit_action(n);
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ FIXME:
+ returns 1 if there is a void return type
+ this is because there is a typemap for void
+ NEW LANGUAGE NOTE:END *********************************************** */
+ // Return value if necessary
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ // managing the number of returning variables
+ // if (numoutputs=Getattr(tm,"numoutputs")){
+ // int i=GetInt(tm,"numoutputs");
+ // printf("return numoutputs %d\n",i);
+ // returnval+=GetInt(tm,"numoutputs");
+ // }
+ // else returnval++;
+ Replaceall(tm, "$source", Swig_cresult_name());
+ if (GetFlag(n, "feature:new")) {
+ Replaceall(tm, "$owner", "1");
+ } else {
+ Replaceall(tm, "$owner", "0");
+ }
+ Printf(f->code, "%s\n", tm);
+ // returnval++;
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name);
+ }
+ emit_return_variable(n, d, f);
+
+ /* Output argument output code */
+ Printv(f->code, outarg, NIL);
+
+ /* Output cleanup code */
+ Printv(f->code, cleanup, NIL);
+
+ /* Look to see if there is any newfree cleanup code */
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printf(f->code, "%s\n", tm);
+ }
+
+
+ /* Close the function */
+ Printv(f->code, "return SWIG_arg;\n", NIL);
+ // add the failure cleanup code:
+ Printv(f->code, "\nif(0) SWIG_fail;\n", NIL);
+ Printv(f->code, "\nfail:\n", NIL);
+ Printv(f->code, "$cleanup", "lua_error(L);\n", NIL);
+ Printv(f->code, "return SWIG_arg;\n", NIL);
+ Printf(f->code, "}\n");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", iname);
+ Replaceall(f->code, "$result", Swig_cresult_name());
+
+ /* Dump the function out */
+ /* in Lua we will not emit the destructor as a wrapper function,
+ Lua will automatically call the destructor when the object is free'd
+ However: you cannot just skip this function as it will not emit
+ any custom destructor (using %extend), as you need to call emit_action()
+ Therefore we go though the whole function,
+ but do not write the code into the wrapper
+ */
+ if (!current[DESTRUCTOR]) {
+ Wrapper_print(f, f_wrappers);
+ }
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ register the function in SWIG
+ different language mappings seem to use different ideas
+ NEW LANGUAGE NOTE:END *********************************************** */
+ /* Now register the function with the interpreter. */
+ int result = SWIG_OK;
+ if (Getattr(n, "sym:overloaded")) {
+ if (!Getattr(n, "sym:nextSibling")) {
+ result = dispatchFunction(n);
+ }
+ }
+
+ Delete(argument_check);
+ Delete(argument_parse);
+
+ Delete(cleanup);
+ Delete(outarg);
+ // Delete(description);
+ DelWrapper(f);
+
+ return result;
+ }
+
+ /* ------------------------------------------------------------
+ * dispatchFunction()
+ *
+ * Emit overloading dispatch function
+ * ------------------------------------------------------------ */
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ This is an extra function used for overloading of functions
+ it checks the args & then calls the relevant fn
+ most of the real work in again typemaps:
+ look for %typecheck(SWIG_TYPECHECK_*) in the .swg file
+ NEW LANGUAGE NOTE:END *********************************************** */
+ int dispatchFunction(Node *n) {
+ //REPORT("dispatchFunction", n);
+ /* Last node in overloaded chain */
+
+ int maxargs;
+ String *tmp = NewString("");
+ String *dispatch = Swig_overload_dispatch(n, "return %s(L);", &maxargs);
+
+ /* Generate a dispatch wrapper for all overloaded functions */
+
+ Wrapper *f = NewWrapper();
+ String *symname = Getattr(n, "sym:name");
+ String *lua_name = Getattr(n, "lua:name");
+ assert(lua_name);
+ String *wname = Swig_name_wrapper(symname);
+
+ //Printf(stdout,"Swig_overload_dispatch %s %s '%s' %d\n",symname,wname,dispatch,maxargs);
+
+ if (!luaAddSymbol(lua_name, n)) {
+ DelWrapper(f);
+ Delete(dispatch);
+ Delete(tmp);
+ return SWIG_ERROR;
+ }
+
+ Printv(f->def, "static int ", wname, "(lua_State* L) {", NIL);
+ Wrapper_add_local(f, "argc", "int argc");
+ Printf(tmp, "int argv[%d]={1", maxargs + 1);
+ for (int i = 1; i <= maxargs; i++) {
+ Printf(tmp, ",%d", i + 1);
+ }
+ Printf(tmp, "}");
+ Wrapper_add_local(f, "argv", tmp);
+ Printf(f->code, "argc = lua_gettop(L);\n");
+
+ Replaceall(dispatch, "$args", "self,args");
+ Printv(f->code, dispatch, "\n", NIL);
+
+ Node *sibl = n;
+ while (Getattr(sibl, "sym:previousSibling"))
+ sibl = Getattr(sibl, "sym:previousSibling"); // go all the way up
+ String *protoTypes = NewString("");
+ do {
+ String *fulldecl = Swig_name_decl(sibl);
+ Printf(protoTypes, "\n\" %s\\n\"", fulldecl);
+ Delete(fulldecl);
+ } while ((sibl = Getattr(sibl, "sym:nextSibling")));
+ Printf(f->code, "SWIG_Lua_pusherrstring(L,\"Wrong arguments for overloaded function '%s'\\n\"\n"
+ "\" Possible C/C++ prototypes are:\\n\"%s);\n", symname, protoTypes);
+ Delete(protoTypes);
+
+ Printf(f->code, "lua_error(L);return 0;\n");
+ Printv(f->code, "}\n", NIL);
+ Wrapper_print(f, f_wrappers);
+
+ // Remember C name of the wrapping function
+ Setattr(n, "wrap:name", wname);
+
+ if (current[CONSTRUCTOR]) {
+ if (constructor_name != 0)
+ Delete(constructor_name);
+ constructor_name = Copy(wname);
+ }
+
+ DelWrapper(f);
+ Delete(dispatch);
+ Delete(tmp);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * Add variable to "attributes" C arrays of given namespace or class.
+ * Input is node. Based on the state of "current" array it determines
+ * the name of the getter function, setter function etc and calls
+ * registerVariable overload with necessary params.
+ * Lua scope could be overwritten. (Used only for backward compatibility)
+ * ------------------------------------------------------------ */
+
+ void registerVariable(Node *n, bool overwrite = false, String *overwriteLuaScope = 0) {
+ int assignable = is_assignable(n);
+ String *symname = Getattr(n, "sym:name");
+ assert(symname);
+
+ // Lua scope. It is not symbol NSpace, it is the actual key to retrieve getCArraysHash.
+ String *luaScope = luaCurrentSymbolNSpace();
+ if (overwrite)
+ luaScope = overwriteLuaScope;
+
+ // Getter and setter
+ String *getName = 0;
+ String *setName = 0;
+ String *mrename = 0;
+ if (current[NO_CPP] || !getCurrentClass()) {
+ // Global variable
+ getName = Swig_name_get(getNSpace(), symname);
+ if (assignable)
+ setName = Swig_name_set(getNSpace(), symname);
+ } else {
+ assert(!current[NO_CPP]);
+ if (current[STATIC_VAR] ) {
+ mrename = Swig_name_member(getNSpace(), getClassPrefix(), symname);
+ getName = Swig_name_get(0, mrename);
+ if (assignable)
+ setName = Swig_name_set(0, mrename);
+ } else if (current[MEMBER_VAR]) {
+ mrename = Swig_name_member(0, getClassPrefix(), symname);
+ getName = Swig_name_get(getNSpace(), mrename);
+ if (assignable)
+ setName = Swig_name_set(getNSpace(), mrename);
+ } else {
+ assert(false);
+ }
+ }
+
+ getName = Swig_name_wrapper(getName);
+ if (setName)
+ setName = Swig_name_wrapper(setName);
+ registerVariable(luaScope, n, getName, setName);
+ }
+
+ /* ------------------------------------------------------------
+ * registerVariable()
+ *
+ * Add variable to the "attributes" (or "get"/"set" in
+ * case of elua_ltr) C arrays of given namespace or class
+ * ------------------------------------------------------------ */
+
+ void registerVariable(String *lua_nspace_or_class_name, Node *n, String *getName, String *setName) {
+ String *unassignable = NewString("SWIG_Lua_set_immutable");
+ if (setName == 0 || GetFlag(n, "feature:immutable")) {
+ setName = unassignable;
+ }
+ Hash *nspaceHash = getCArraysHash(lua_nspace_or_class_name);
+ String *s_ns_methods_tab = Getattr(nspaceHash, "methods");
+ String *s_ns_var_tab = Getattr(nspaceHash, "attributes");
+ String *lua_name = Getattr(n, "lua:name");
+ if (elua_ltr) {
+ String *s_ns_dot_get = Getattr(nspaceHash, "get");
+ String *s_ns_dot_set = Getattr(nspaceHash, "set");
+ Printf(s_ns_dot_get, "%s{LSTRKEY(\"%s\"), LFUNCVAL(%s)},\n", tab4, lua_name, getName);
+ Printf(s_ns_dot_set, "%s{LSTRKEY(\"%s\"), LFUNCVAL(%s)},\n", tab4, lua_name, setName);
+ } else if (eluac_ltr) {
+ Printv(s_ns_methods_tab, tab4, "{LSTRKEY(\"", lua_name, "_get", "\")", ", LFUNCVAL(", getName, ")", "},\n", NIL);
+ Printv(s_ns_methods_tab, tab4, "{LSTRKEY(\"", lua_name, "_set", "\")", ", LFUNCVAL(", setName, ")", "},\n", NIL);
+ } else {
+ Printf(s_ns_var_tab, "%s{ \"%s\", %s, %s },\n", tab4, lua_name, getName, setName);
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * variableWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int variableWrapper(Node *n) {
+ /* NEW LANGUAGE NOTE:***********************************************
+ Language::variableWrapper(n) will generate two wrapper fns
+ Foo_get & Foo_set by calling functionWrapper()
+ so we will just add these into the variable lists
+ ideally we should not have registered these as functions,
+ only WRT this variable will look into this later.
+ NEW LANGUAGE NOTE:END *********************************************** */
+ // REPORT("variableWrapper", n);
+ String *lua_name = Getattr(n, "lua:name");
+ assert(lua_name);
+ current[VARIABLE] = true;
+ // let SWIG generate the wrappers
+ int result = Language::variableWrapper(n);
+
+ // It is impossible to use registerVariable, because sym:name of the Node is currently
+ // in an undefined state - the callees of this function may have modified it.
+ // registerVariable should be used from respective callees.*
+ current[VARIABLE] = false;
+ return result;
+ }
+
+
+ /* ------------------------------------------------------------
+ * Add constant to appropriate C array. constantRecord is an array record.
+ * Actually, in current implementation it is resolved consttab typemap
+ * ------------------------------------------------------------ */
+
+ void registerConstant(String *nspace, String *constantRecord) {
+ Hash *nspaceHash = getCArraysHash(nspace);
+ String *s_const_tab = 0;
+ if (eluac_ltr || elua_ltr)
+ // In elua everything goes to "methods" tab
+ s_const_tab = Getattr(nspaceHash, "methods");
+ else
+ s_const_tab = Getattr(nspaceHash, "constants");
+
+ assert(s_const_tab);
+ Printf(s_const_tab, " %s,\n", constantRecord);
+
+ if ((eluac_ltr || elua_ltr) && old_metatable_bindings) {
+ s_const_tab = Getattr(nspaceHash, "constants");
+ assert(s_const_tab);
+ Printf(s_const_tab, " %s,\n", constantRecord);
+ }
+
+ }
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ REPORT("constantWrapper", n);
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ String *lua_name = Getattr(n, "lua:name");
+ if (lua_name == 0)
+ lua_name = iname;
+ String *nsname = Copy(iname);
+ SwigType *type = Getattr(n, "type");
+ String *rawval = Getattr(n, "rawval");
+ String *value = rawval ? rawval : Getattr(n, "value");
+ String *tm;
+ String *lua_name_v2 = 0;
+ String *tm_v2 = 0;
+ String *iname_v2 = 0;
+ Node *n_v2 = 0;
+
+ if (!luaAddSymbol(lua_name, n))
+ return SWIG_ERROR;
+
+ Swig_save("lua_constantMember", n, "sym:name", NIL);
+ Setattr(n, "sym:name", lua_name);
+ /* Special hook for member pointer */
+ if (SwigType_type(type) == T_MPOINTER) {
+ String *wname = Swig_name_wrapper(iname);
+ Printf(f_wrappers, "static %s = %s;\n", SwigType_str(type, wname), value);
+ value = Char(wname);
+ }
+
+ if ((tm = Swig_typemap_lookup("consttab", n, name, 0))) {
+ Replaceall(tm, "$source", value);
+ Replaceall(tm, "$target", lua_name);
+ Replaceall(tm, "$value", value);
+ Replaceall(tm, "$nsname", nsname);
+ registerConstant(luaCurrentSymbolNSpace(), tm);
+ } else if ((tm = Swig_typemap_lookup("constcode", n, name, 0))) {
+ Replaceall(tm, "$source", value);
+ Replaceall(tm, "$target", lua_name);
+ Replaceall(tm, "$value", value);
+ Replaceall(tm, "$nsname", nsname);
+ Printf(f_init, "%s\n", tm);
+ } else {
+ Delete(nsname);
+ nsname = 0;
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
+ Swig_restore(n);
+ return SWIG_NOWRAP;
+ }
+
+ bool make_v2_compatible = old_metatable_bindings && getCurrentClass() && old_compatible_names;
+
+ if (make_v2_compatible) {
+ // Don't do anything for enums in C mode - they are already
+ // wrapped correctly
+ if (CPlusPlus || !current[ENUM_CONST]) {
+ lua_name_v2 = Swig_name_member(0, proxy_class_name, lua_name);
+ iname_v2 = Swig_name_member(0, proxy_class_name, iname);
+ n_v2 = Copy(n);
+ if (!luaAddSymbol(iname_v2, n, getNSpace())) {
+ Swig_restore(n);
+ return SWIG_ERROR;
+ }
+
+ Setattr(n_v2, "sym:name", lua_name_v2);
+ tm_v2 = Swig_typemap_lookup("consttab", n_v2, name, 0);
+ if (tm_v2) {
+ Replaceall(tm_v2, "$source", value);
+ Replaceall(tm_v2, "$target", lua_name_v2);
+ Replaceall(tm_v2, "$value", value);
+ Replaceall(tm_v2, "$nsname", nsname);
+ registerConstant(getNSpace(), tm_v2);
+ } else {
+ tm_v2 = Swig_typemap_lookup("constcode", n_v2, name, 0);
+ if (!tm_v2) {
+ // This can't be.
+ assert(false);
+ Swig_restore(n);
+ return SWIG_ERROR;
+ }
+ Replaceall(tm_v2, "$source", value);
+ Replaceall(tm_v2, "$target", lua_name_v2);
+ Replaceall(tm_v2, "$value", value);
+ Replaceall(tm_v2, "$nsname", nsname);
+ Printf(f_init, "%s\n", tm_v2);
+ }
+ Delete(n_v2);
+ }
+ }
+
+ Swig_restore(n);
+ Delete(nsname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * nativeWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int nativeWrapper(Node *n) {
+ // REPORT("nativeWrapper", n);
+ String *symname = Getattr(n, "sym:name");
+ String *wrapname = Getattr(n, "wrap:name");
+ if (!luaAddSymbol(wrapname, n))
+ return SWIG_ERROR;
+
+ Hash *nspaceHash = getCArraysHash(getNSpace());
+ String *s_ns_methods_tab = Getattr(nspaceHash, "methods");
+ Printv(s_ns_methods_tab, tab4, "{ \"", symname, "\",", wrapname, "},\n", NIL);
+ // return Language::nativeWrapper(n); // this does nothing...
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * enumDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int enumDeclaration(Node *n) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ current[STATIC_CONST] = true;
+ current[ENUM_CONST] = true;
+ // There is some slightly specific behaviour with enums. Basically,
+ // their NSpace may be tracked separately. The code below tries to work around
+ // this issue to some degree.
+ // The idea is the same as in classHandler - to drop old names generation if
+ // enum is in class in namespace.
+ const int old_compatible_names_saved = old_compatible_names;
+ if (getNSpace() || ( Getattr(n, "sym:nspace") != 0 && Len(Getattr(n, "sym:nspace")) > 0 ) ) {
+ old_compatible_names = 0;
+ }
+ int result = Language::enumDeclaration(n);
+ current[STATIC_CONST] = false;
+ current[ENUM_CONST] = false;
+ old_compatible_names = old_compatible_names_saved;
+ return result;
+ }
+
+ /* ------------------------------------------------------------
+ * enumvalueDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int enumvalueDeclaration(Node *n) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ Swig_require("enumvalueDeclaration", n, "*name", "?value", "*sym:name", NIL);
+ String *symname = Getattr(n, "sym:name");
+ String *value = Getattr(n, "value");
+ String *name = Getattr(n, "name");
+ String *tmpValue;
+ Node *parent = parentNode(n);
+
+ if (value)
+ tmpValue = NewString(value);
+ else
+ tmpValue = NewString(name);
+ Setattr(n, "value", tmpValue);
+
+ Setattr(n, "name", tmpValue); /* for wrapping of enums in a namespace when emit_action is used */
+
+ if (GetFlag(parent, "scopedenum")) {
+ symname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
+ Setattr(n, "sym:name", symname);
+ Delete(symname);
+ }
+
+ int result = constantWrapper(n);
+
+ Delete(tmpValue);
+ Swig_restore(n);
+ return result;
+ }
+
+ /* ------------------------------------------------------------
+ * classDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int classDeclaration(Node *n) {
+ return Language::classDeclaration(n);
+ }
+
+
+ /* ------------------------------------------------------------
+ * Helper function that adds record to appropriate C arrays
+ * ------------------------------------------------------------ */
+
+ void registerClass(String *scope, String *wrap_class) {
+ assert(wrap_class);
+ Hash *nspaceHash = getCArraysHash(scope);
+ String *ns_classes = Getattr(nspaceHash, "classes");
+ Printv(ns_classes, "&", wrap_class, ",\n", NIL);
+ if (elua_ltr || eluac_ltr) {
+ String *ns_methods = Getattr(nspaceHash, "methods");
+ Hash *class_hash = getCArraysHash(class_static_nspace);
+ assert(class_hash);
+ String *cls_methods = Getattr(class_hash, "methods:name");
+ assert(cls_methods);
+ Printv(ns_methods, tab4, "{LSTRKEY(\"", proxy_class_name, "\")", ", LROVAL(", cls_methods, ")", "},\n", NIL);
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int classHandler(Node *n) {
+ //REPORT("classHandler", n);
+
+ String *mangled_full_proxy_class_name = 0;
+ String *destructor_name = 0;
+ String *nspace = getNSpace();
+
+ constructor_name = 0;
+ have_constructor = 0;
+ have_destructor = 0;
+ destructor_action = 0;
+ assert(class_static_nspace == 0);
+ assert(full_proxy_class_name == 0);
+ assert(proxy_class_name == 0);
+
+ current[NO_CPP] = false;
+
+ proxy_class_name = Getattr(n, "sym:name");
+ // We have to enforce nspace here, because technically we are already
+ // inside class parsing (getCurrentClass != 0), but we should register
+ // class in its parent namespace
+ if (!luaAddSymbol(proxy_class_name, n, nspace))
+ return SWIG_ERROR;
+
+ if (nspace == 0)
+ full_proxy_class_name = NewStringf("%s", proxy_class_name);
+ else
+ full_proxy_class_name = NewStringf("%s.%s", nspace, proxy_class_name);
+
+ assert(full_proxy_class_name);
+ mangled_full_proxy_class_name = Swig_name_mangle(full_proxy_class_name);
+
+ SwigType *t = Copy(Getattr(n, "name"));
+ SwigType *fr_t = SwigType_typedef_resolve_all(t); /* Create fully resolved type */
+ SwigType *t_tmp = 0;
+ t_tmp = SwigType_typedef_qualified(fr_t); // Temporal variable
+ Delete(fr_t);
+ fr_t = SwigType_strip_qualifiers(t_tmp);
+ String *mangled_fr_t = 0;
+ mangled_fr_t = SwigType_manglestr(fr_t);
+ // not sure exactly how this works,
+ // but tcl has a static hashtable of all classes emitted and then only emits code for them once.
+ // this fixes issues in test suites: template_default2 & template_specialization
+
+ // * if i understand correctly, this is a bug.
+ // * consider effect on template_specialization_defarg
+
+ static Hash *emitted = NewHash();
+ if (GetFlag(emitted, mangled_fr_t)) {
+ full_proxy_class_name = 0;
+ proxy_class_name = 0;
+ return SWIG_NOWRAP;
+ }
+ SetFlag(emitted, mangled_fr_t);
+
+ // We treat class T as both 'class' and 'namespace'. All static members, attributes
+ // and constants are considered part of namespace T, all members - part of the 'class'
+ // Now, here is a trick. Static methods, attributes and non-static methods and attributes
+ // are described with same structures - swig_lua_attribute/swig_lua_method. Instead of calling
+ // getCArraysHash(class name) to initialize things for static methods/attributes and then
+ // manually doing same initialization for non-static methods, we call getCArraysHash 2 times:
+ // 1) With name "class name" + "." + "SwigStatic" to initialize static things
+ // 2) With "class name" to initialize non-static things
+ Hash *instance_cls = getCArraysHash(full_proxy_class_name, false);
+ assert(instance_cls);
+ String *s_attr_tab_name = Getattr(instance_cls, "attributes:name");
+ String *s_methods_tab_name = Getattr(instance_cls, "methods:name");
+ SetFlag(instance_cls, "lua:no_namespaces");
+ SetFlag(instance_cls, "lua:no_classes");
+ SetFlag(instance_cls, "lua:class_instance");
+
+ /* There is no use for "constants", "classes" and "namespaces" arrays.
+ * All constants are considered part of static part of class.
+ */
+
+ class_static_nspace = NewStringf("%s%sSwigStatic", full_proxy_class_name, NSPACE_SEPARATOR);
+ Hash *static_cls = getCArraysHash(class_static_nspace, false);
+ assert(static_cls);
+ SetFlag(static_cls, "lua:no_namespaces");
+ SetFlag(static_cls, "lua:class_static");
+
+ // Notifying instance_cls and static_cls hashes about each other
+ Setattr(instance_cls, "lua:class_instance:static_hash", static_cls);
+ Setattr(static_cls, "lua:class_static:instance_hash", instance_cls);
+
+ const int old_compatible_names_saved = old_compatible_names;
+ // If class has %nspace enabled, then generation of backward compatible names
+ // should be disabled
+ if (getNSpace()) {
+ old_compatible_names = 0;
+ }
+
+ /* There is no use for "classes" and "namespaces" arrays. Subclasses are not supported
+ * by SWIG and namespaces couldn't be nested inside classes (C++ Standard)
+ */
+ // Generate normal wrappers
+ Language::classHandler(n);
+
+ old_compatible_names = old_compatible_names_saved;
+
+ SwigType_add_pointer(t);
+
+ // Catch all: eg. a class with only static functions and/or variables will not have 'remembered'
+ String *wrap_class_name = Swig_name_wrapper(NewStringf("class_%s", mangled_full_proxy_class_name));
+ String *wrap_class = NewStringf("&%s", wrap_class_name);
+ SwigType_remember_clientdata(t, wrap_class);
+
+ String *rt = Copy(getClassType());
+ SwigType_add_pointer(rt);
+
+ // Adding class to appropriate namespace
+ registerClass(nspace, wrap_class_name);
+ Hash *nspaceHash = getCArraysHash(nspace);
+
+ // Register the class structure with the type checker
+ // Printf(f_init,"SWIG_TypeClientData(SWIGTYPE%s, (void *) &_wrap_class_%s);\n", SwigType_manglestr(t), mangled_full_proxy_class_name);
+
+ // emit a function to be called to delete the object
+ if (have_destructor) {
+ destructor_name = NewStringf("swig_delete_%s", mangled_full_proxy_class_name);
+ Printv(f_wrappers, "static void ", destructor_name, "(void *obj) {\n", NIL);
+ if (destructor_action) {
+ Printv(f_wrappers, SwigType_str(rt, "arg1"), " = (", SwigType_str(rt, 0), ") obj;\n", NIL);
+ Printv(f_wrappers, destructor_action, "\n", NIL);
+ } else {
+ if (CPlusPlus) {
+ Printv(f_wrappers, " delete (", SwigType_str(rt, 0), ") obj;\n", NIL);
+ } else {
+ Printv(f_wrappers, " free((char *) obj);\n", NIL);
+ }
+ }
+ Printf(f_wrappers, "}\n");
+ }
+ // Wrap constructor wrapper into one more proxy function. It will be used as class namespace __call method, thus
+ // allowing both
+ // Module.ClassName.StaticMethod to access static method/variable/constant
+ // Module.ClassName() to create new object
+ if (have_constructor) {
+ assert(constructor_name);
+ String *constructor_proxy_name = NewStringf("_proxy_%s", constructor_name);
+ Printv(f_wrappers, "static int ", constructor_proxy_name, "(lua_State *L) {\n", NIL);
+ Printv(f_wrappers,
+ tab4, "assert(lua_istable(L,1));\n",
+ tab4, "lua_pushcfunction(L,", constructor_name, ");\n",
+ tab4, "assert(!lua_isnil(L,-1));\n",
+ tab4, "lua_replace(L,1); /* replace our table with real constructor */\n",
+ tab4, "lua_call(L,lua_gettop(L)-1,1);\n",
+ tab4, "return 1;\n}\n", NIL);
+ Delete(constructor_name);
+ constructor_name = constructor_proxy_name;
+ if (elua_ltr) {
+ String *static_cls_metatable_tab = Getattr(static_cls, "metatable");
+ assert(static_cls_metatable_tab);
+ Printf(static_cls_metatable_tab, " {LSTRKEY(\"__call\"), LFUNCVAL(%s)},\n", constructor_name);
+ } else if (eluac_ltr) {
+ String *ns_methods_tab = Getattr(nspaceHash, "methods");
+ assert(ns_methods_tab);
+ Printv(ns_methods_tab, tab4, "{LSTRKEY(\"", "new_", proxy_class_name, "\")", ", LFUNCVAL(", constructor_name, ")", "},\n", NIL);
+ }
+ }
+ if (have_destructor) {
+ if (eluac_ltr) {
+ String *ns_methods_tab = Getattr(nspaceHash, "methods");
+ assert(ns_methods_tab);
+ Printv(ns_methods_tab, tab4, "{LSTRKEY(\"", "free_", mangled_full_proxy_class_name, "\")", ", LFUNCVAL(", destructor_name, ")", "},\n", NIL);
+ }
+ }
+
+ closeCArraysHash(full_proxy_class_name, f_wrappers);
+ closeCArraysHash(class_static_nspace, f_wrappers);
+
+
+ // Handle inheritance
+ // note: with the idea of class hierarchies spread over multiple modules
+ // cf test-suite: imports.i
+ // it is not possible to just add the pointers to the base classes to the code
+ // (as sometimes these classes are not present)
+ // therefore we instead hold the name of the base class and a null pointer
+ // at runtime: we can query the swig type manager & see if the class exists
+ // if so, we can get the pointer to the base class & replace the null pointer
+ // if the type does not exist, then we cannot...
+ String *base_class = NewString("");
+ String *base_class_names = NewString("");
+
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator b;
+ int index = 0;
+ b = First(baselist);
+ while (b.item) {
+ String *bname = Getattr(b.item, "name");
+ if ((!bname) || GetFlag(b.item, "feature:ignore") || (!Getattr(b.item, "module"))) {
+ b = Next(b);
+ continue;
+ }
+ // stores a null pointer & the name
+ Printf(base_class, "0,");
+ Printf(base_class_names, "\"%s *\",", SwigType_namestr(bname));
+
+ b = Next(b);
+ index++;
+ }
+ }
+ // First, print class static part
+ printCArraysDefinition(class_static_nspace, proxy_class_name, f_wrappers);
+
+ assert(mangled_full_proxy_class_name);
+ assert(base_class);
+ assert(base_class_names);
+ assert(proxy_class_name);
+ assert(full_proxy_class_name);
+
+ // Then print class instance part
+ Printv(f_wrappers, "static swig_lua_class *swig_", mangled_full_proxy_class_name, "_bases[] = {", base_class, "0};\n", NIL);
+ Delete(base_class);
+ Printv(f_wrappers, "static const char *swig_", mangled_full_proxy_class_name, "_base_names[] = {", base_class_names, "0};\n", NIL);
+ Delete(base_class_names);
+
+ Printv(f_wrappers, "static swig_lua_class _wrap_class_", mangled_full_proxy_class_name, " = { \"", proxy_class_name, "\", \"", full_proxy_class_name, "\", &SWIGTYPE",
+ SwigType_manglestr(t), ",", NIL);
+
+ if (have_constructor) {
+ Printv(f_wrappers, constructor_name, NIL);
+ Delete(constructor_name);
+ constructor_name = 0;
+ } else {
+ Printf(f_wrappers, "0");
+ }
+
+ if (have_destructor) {
+ Printv(f_wrappers, ", ", destructor_name, NIL);
+ } else {
+ Printf(f_wrappers, ",0");
+ }
+ Printf(f_wrappers, ", %s, %s, &%s", s_methods_tab_name, s_attr_tab_name, Getattr(static_cls, "cname"));
+
+ if (!eluac_ltr) {
+ Printf(f_wrappers, ", %s", Getattr(instance_cls,"metatable:name"));
+ }
+ else
+ Printf(f_wrappers, ", 0");
+
+ Printf(f_wrappers, ", swig_%s_bases, swig_%s_base_names };\n\n", mangled_full_proxy_class_name, mangled_full_proxy_class_name);
+
+ current[NO_CPP] = true;
+ Delete(class_static_nspace);
+ class_static_nspace = 0;
+ Delete(mangled_full_proxy_class_name);
+ mangled_full_proxy_class_name = 0;
+ Delete(destructor_name);
+ destructor_name = 0;
+ Delete(full_proxy_class_name);
+ full_proxy_class_name = 0;
+ proxy_class_name = 0;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * memberfunctionHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int memberfunctionHandler(Node *n) {
+ String *symname = GetChar(n, "sym:name");
+ //Printf(stdout,"memberfunctionHandler %s %s\n",name,iname);
+
+ // Special case unary minus: LUA passes two parameters for the
+ // wrapper function while we want only one. Tell our
+ // functionWrapper to ignore a parameter.
+
+ if (Cmp(symname, "__unm") == 0) {
+ //Printf(stdout, "unary minus: ignore one argument\n");
+ SetInt(n, "lua:ignore_args", 1);
+ }
+
+ current[MEMBER_FUNC] = true;
+ Language::memberfunctionHandler(n);
+
+ registerMethod(n);
+ current[MEMBER_FUNC] = false;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * membervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int membervariableHandler(Node *n) {
+ // REPORT("membervariableHandler",n);
+ current[MEMBER_VAR] = true;
+ Language::membervariableHandler(n);
+ registerVariable(n);
+ current[MEMBER_VAR] = false;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constructorHandler()
+ *
+ * Method for adding C++ member constructor
+ * ------------------------------------------------------------ */
+
+ virtual int constructorHandler(Node *n) {
+ // REPORT("constructorHandler", n);
+ current[CONSTRUCTOR] = true;
+ Language::constructorHandler(n);
+ current[CONSTRUCTOR] = false;
+ //constructor_name = NewString(Getattr(n, "sym:name"));
+ have_constructor = 1;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * destructorHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int destructorHandler(Node *n) {
+ REPORT("destructorHandler", n);
+ current[DESTRUCTOR] = true;
+ Language::destructorHandler(n);
+ current[DESTRUCTOR] = false;
+ have_destructor = 1;
+ destructor_action = Getattr(n, "wrap:action");
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * globalfunctionHandler()
+ *
+ * It can be called:
+ * 1. Usual C/C++ global function.
+ * 2. During class parsing for functions declared/defined as friend
+ * 3. During class parsing from staticmemberfunctionHandler
+ * ---------------------------------------------------------------------- */
+
+ virtual int globalfunctionHandler(Node *n) {
+ bool oldVal = current[NO_CPP];
+ if (!current[STATIC_FUNC]) // If static function, don't switch to NO_CPP
+ current[NO_CPP] = true;
+ const int result = Language::globalfunctionHandler(n);
+
+ if (!current[STATIC_FUNC]) // Register only if not called from static function handler
+ registerMethod(n);
+ current[NO_CPP] = oldVal;
+ return result;
+ }
+
+ /* ----------------------------------------------------------------------
+ * globalvariableHandler()
+ *
+ * Sets "current" array correctly
+ * ---------------------------------------------------------------------- */
+
+ virtual int globalvariableHandler(Node *n) {
+ bool oldVal = current[NO_CPP];
+ current[GLOBAL_VAR] = true;
+ current[NO_CPP] = true;
+
+ const int result = Language::globalvariableHandler(n);
+ registerVariable(n);
+
+ current[GLOBAL_VAR] = false;
+ current[NO_CPP] = oldVal;
+ return result;
+ }
+
+
+ /* -----------------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ *
+ * Wrap a static C++ function
+ * ---------------------------------------------------------------------- */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ REPORT("staticmemberfunctionHandler", n);
+ current[STATIC_FUNC] = true;
+
+ const int result = Language::staticmemberfunctionHandler(n);
+ registerMethod(n);
+
+ if (old_metatable_bindings && result == SWIG_OK && old_compatible_names) {
+ Swig_require("lua_staticmemberfunctionHandler", n, "*lua:name", NIL);
+ String *lua_name = Getattr(n, "lua:name");
+ // Although this function uses Swig_name_member, it actually generates the Lua name,
+ // not the C++ name. This is because an earlier version used such a scheme for static function
+ // name generation and we have to maintain backward compatibility.
+ String *compat_name = Swig_name_member(0, proxy_class_name, lua_name);
+ Setattr(n, "lua:name", compat_name);
+ registerMethod(n, true, getNSpace());
+ Delete(compat_name);
+ Swig_restore(n);
+ }
+
+ current[STATIC_FUNC] = false;;
+ return result;
+ }
+
+ /* ------------------------------------------------------------
+ * memberconstantHandler()
+ *
+ * Create a C++ constant
+ * ------------------------------------------------------------ */
+
+ virtual int memberconstantHandler(Node *n) {
+ REPORT("memberconstantHandler", n);
+ int result = Language::memberconstantHandler(n);
+
+ return result;
+ }
+
+ /* ---------------------------------------------------------------------
+ * staticmembervariableHandler()
+ * --------------------------------------------------------------------- */
+
+ virtual int staticmembervariableHandler(Node *n) {
+ REPORT("staticmembervariableHandler", n);
+ current[STATIC_VAR] = true;
+ //String *symname = Getattr(n, "sym:name");
+ int result = Language::staticmembervariableHandler(n);
+ if (!GetFlag(n, "wrappedasconstant")) {
+ registerVariable(n);
+ }
+
+ if (result == SWIG_OK) {
+ // This will add static member variable to the class namespace with name ClassName_VarName
+ if (old_metatable_bindings && old_compatible_names) {
+ Swig_save("lua_staticmembervariableHandler", n, "lua:name", NIL);
+ String *lua_name = Getattr(n, "lua:name");
+ // Although this function uses Swig_name_member, it actually generates the Lua name,
+ // not the C++ name. This is because an earlier version used such a scheme for static function
+ // name generation and we have to maintain backward compatibility.
+ String *v2_name = Swig_name_member(NIL, proxy_class_name, lua_name);
+ if (!GetFlag(n, "wrappedasconstant")) {
+ Setattr(n, "lua:name", v2_name);
+ // Registering static var in the class parent nspace
+ registerVariable(n, true, getNSpace());
+ }
+ // If static member variable was wrapped as a constant, then
+ // constant wrapper has already performed all actions necessary for old_metatable_bindings
+ Delete(v2_name);
+ Swig_restore(n);
+ }
+ }
+ current[STATIC_VAR] = false;
+
+ return result;
+ }
+
+
+ /* ---------------------------------------------------------------------
+ * external runtime generation
+ * --------------------------------------------------------------------- */
+
+ /* This is to support the usage
+ SWIG -external-runtime <filename>
+ The code consists of two functions:
+ String *runtimeCode() // returns a large string with all the runtimes in
+ String *defaultExternalRuntimeFilename() // returns the default filename
+ I am writing a generic solution, even though SWIG-Lua only has one file right now...
+ */
+ String *runtimeCode() {
+ String *s = NewString("");
+ const char *filenames[] = { "luarun.swg", 0 }; // must be 0 terminated
+
+ emitLuaFlavor(s);
+
+ String *sfile = 0;
+ for (int i = 0; filenames[i] != 0; i++) {
+ sfile = Swig_include_sys(filenames[i]);
+ if (!sfile) {
+ Printf(stderr, "*** Unable to open '%s'\n", filenames[i]);
+ } else {
+ Append(s, sfile);
+ Delete(sfile);
+ }
+ }
+
+ return s;
+ }
+
+ String *defaultExternalRuntimeFilename() {
+ return NewString("swigluarun.h");
+ }
+
+ /* ---------------------------------------------------------------------
+ * helpers
+ * --------------------------------------------------------------------- */
+
+ void emitLuaFlavor(String *s) {
+ if (elua_emulate) {
+ Printf(s, "/*This is only emulation!*/\n");
+ Printf(s, "#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_ELUA\n");
+ Printf(s, "#define SWIG_LUA_ELUA_EMULATE\n");
+ } else if (elua_ltr)
+ Printf(s, "#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_ELUA\n");
+ else if (eluac_ltr)
+ Printf(s, "#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_ELUAC\n");
+ else
+ Printf(s, "#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_LUA\n");
+ }
+
+
+ /* -----------------------------------------------------------------------------
+ * escapeCode()
+ *
+ * This is to convert the string of Lua code into a proper string, which can then be
+ * emitted into the C/C++ code.
+ * Basically it is a lot of search & replacing of odd sequences
+ * ---------------------------------------------------------------------------- */
+
+ void escapeCode(String *str) {
+ //Printf(f_runtime,"/* original luacode:[[[\n%s\n]]]\n*/\n",str);
+ Chop(str); // trim
+ Replace(str, "\\", "\\\\", DOH_REPLACE_ANY); // \ to \\ (this must be done first)
+ Replace(str, "\"", "\\\"", DOH_REPLACE_ANY); // " to \"
+ Replace(str, "\n", "\\n\"\n \"", DOH_REPLACE_ANY); // \n to \n"\n" (ie quoting every line)
+ //Printf(f_runtime,"/* hacked luacode:[[[\n%s\n]]]\n*/\n",str);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * rawGetCArraysHash(String *name)
+ *
+ * A small helper to hide implementation of how CArrays hashes are stored
+ * ---------------------------------------------------------------------------- */
+
+ Hash *rawGetCArraysHash(const_String_or_char_ptr name) {
+ Hash *scope = symbolScopeLookup( name ? name : "" );
+ if(!scope)
+ return 0;
+
+ Hash *carrays_hash = Getattr(scope, "lua:cdata");
+ return carrays_hash;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getCArraysHash()
+ *
+ * Each namespace can be described with a hash that stores C arrays
+ * where members of the namespace should be added. All these hashes are stored
+ * inside the symbols table, in pseudo-symbol for every namespace.
+ * nspace could be NULL (NSPACE_TODO), that means functions and variables and classes
+ * that are not in any namespace (this is default for SWIG unless %nspace feature is used).
+ * You can later set some attributes that will affect behaviour of functions that use this hash:
+ * "lua:no_namespaces" will disable "namespaces" array.
+ * "lua:no_classes" will disable "classes" array.
+ * For every component ("attributes", "methods", etc) there are subcomponents:
+ * XXX:name - name of the C array that stores data for component
+ * XXX:decl - statement with forward declaration of this array;
+ * Namespace could be automatically registered to its parent if 'reg' == true. This can only be
+ * done during the first call (a.k.a when nspace is created).
+ * ---------------------------------------------------------------------------- */
+
+ Hash *getCArraysHash(String *nspace, bool reg = true) {
+ Hash *scope = symbolScopeLookup(nspace ? nspace : "");
+ if(!scope) {
+ symbolAddScope( nspace ? nspace : "" );
+ scope = symbolScopeLookup(nspace ? nspace : "");
+ assert(scope);
+ }
+ Hash *carrays_hash = Getattr(scope, "lua:cdata");
+ if (carrays_hash != 0)
+ return carrays_hash;
+ carrays_hash = NewHash();
+ String *mangled_name = 0;
+ if (nspace == 0 || Len(nspace) == 0)
+ mangled_name = NewString("SwigModule");
+ else
+ mangled_name = Swig_name_mangle(nspace);
+ String *cname = NewStringf("swig_%s", mangled_name);
+
+ Setattr(carrays_hash, "cname", cname);
+
+ String *attr_tab = NewString("");
+ String *attr_tab_name = NewStringf("swig_%s_attributes", mangled_name);
+ String *attr_tab_decl = NewString("");
+ Printv(attr_tab, "static swig_lua_attribute ", NIL);
+ Printv(attr_tab, attr_tab_name, "[]", NIL);
+ Printv(attr_tab_decl, attr_tab, ";\n", NIL);
+ Printv(attr_tab, " = {\n", NIL);
+ Setattr(carrays_hash, "attributes", attr_tab);
+ Setattr(carrays_hash, "attributes:name", attr_tab_name);
+ Setattr(carrays_hash, "attributes:decl", attr_tab_decl);
+
+ String *methods_tab = NewString("");
+ String *methods_tab_name = NewStringf("swig_%s_methods", mangled_name);
+ String *methods_tab_decl = NewString("");
+ if (elua_ltr || eluac_ltr) // In this case methods array also acts as namespace rotable
+ Printf(methods_tab, "const LUA_REG_TYPE ");
+ else
+ Printf(methods_tab, "static swig_lua_method ");
+ Printv(methods_tab, methods_tab_name, "[]", NIL);
+ Printv(methods_tab_decl, methods_tab, ";\n", NIL);
+ Printv(methods_tab, "= {\n", NIL);
+ Setattr(carrays_hash, "methods", methods_tab);
+ Setattr(carrays_hash, "methods:name", methods_tab_name);
+ Setattr(carrays_hash, "methods:decl", methods_tab_decl);
+
+ String *const_tab = NewString("");
+ String *const_tab_name = NewStringf("swig_%s_constants", mangled_name);
+ String *const_tab_decl = NewString("");
+ if (elua_ltr || eluac_ltr) // In this case const array holds rotable with namespace constants
+ Printf(const_tab, "const LUA_REG_TYPE ");
+ else
+ Printf(const_tab, "static swig_lua_const_info ");
+ Printv(const_tab, const_tab_name, "[]", NIL);
+ Printv(const_tab_decl, const_tab, ";", NIL);
+ Printv(const_tab, "= {\n", NIL);
+ Setattr(carrays_hash, "constants", const_tab);
+ Setattr(carrays_hash, "constants:name", const_tab_name);
+ Setattr(carrays_hash, "constants:decl", const_tab_decl);
+
+ String *classes_tab = NewString("");
+ String *classes_tab_name = NewStringf("swig_%s_classes", mangled_name);
+ String *classes_tab_decl = NewString("");
+ Printf(classes_tab, "static swig_lua_class* ");
+ Printv(classes_tab, classes_tab_name, "[]", NIL);
+ Printv(classes_tab_decl, classes_tab, ";", NIL);
+ Printv(classes_tab, "= {\n", NIL);
+ Setattr(carrays_hash, "classes", classes_tab);
+ Setattr(carrays_hash, "classes:name", classes_tab_name);
+ Setattr(carrays_hash, "classes:decl", classes_tab_decl);
+
+ String *namespaces_tab = NewString("");
+ String *namespaces_tab_name = NewStringf("swig_%s_namespaces", mangled_name);
+ String *namespaces_tab_decl = NewString("");
+ Printf(namespaces_tab, "static swig_lua_namespace* ");
+ Printv(namespaces_tab, namespaces_tab_name, "[]", NIL);
+ Printv(namespaces_tab_decl, namespaces_tab, ";", NIL);
+ Printv(namespaces_tab, " = {\n", NIL);
+ Setattr(carrays_hash, "namespaces", namespaces_tab);
+ Setattr(carrays_hash, "namespaces:name", namespaces_tab_name);
+ Setattr(carrays_hash, "namespaces:decl", namespaces_tab_decl);
+
+ if (elua_ltr) {
+ String *get_tab = NewString("");
+ String *get_tab_name = NewStringf("swig_%s_get", mangled_name);
+ String *get_tab_decl = NewString("");
+ Printv(get_tab, "const LUA_REG_TYPE ", get_tab_name, "[]", NIL);
+ Printv(get_tab_decl, get_tab, ";", NIL);
+ Printv(get_tab, " = {\n", NIL);
+ Setattr(carrays_hash, "get", get_tab);
+ Setattr(carrays_hash, "get:name", get_tab_name);
+ Setattr(carrays_hash, "get:decl", get_tab_decl);
+
+ String *set_tab = NewString("");
+ String *set_tab_name = NewStringf("swig_%s_set", mangled_name);
+ String *set_tab_decl = NewString("");
+ Printv(set_tab, "const LUA_REG_TYPE ", set_tab_name, "[]", NIL);
+ Printv(set_tab_decl, set_tab, ";", NIL);
+ Printv(set_tab, " = {\n", NIL);
+ Setattr(carrays_hash, "set", set_tab);
+ Setattr(carrays_hash, "set:name", set_tab_name);
+ Setattr(carrays_hash, "set:decl", set_tab_decl);
+
+ }
+ if (!eluac_ltr) {
+ String *metatable_tab = NewString("");
+ String *metatable_tab_name = NewStringf("swig_%s_meta", mangled_name);
+ String *metatable_tab_decl = NewString("");
+ if (elua_ltr) // In this case const array holds rotable with namespace constants
+ Printf(metatable_tab, "const LUA_REG_TYPE ");
+ else
+ Printf(metatable_tab, "static swig_lua_method ");
+ Printv(metatable_tab, metatable_tab_name, "[]", NIL);
+ Printv(metatable_tab_decl, metatable_tab, ";", NIL);
+ Printv(metatable_tab, " = {\n", NIL);
+ Setattr(carrays_hash, "metatable", metatable_tab);
+ Setattr(carrays_hash, "metatable:name", metatable_tab_name);
+ Setattr(carrays_hash, "metatable:decl", metatable_tab_decl);
+ }
+
+ Setattr(scope, "lua:cdata", carrays_hash);
+ assert(rawGetCArraysHash(nspace));
+
+ if (reg && nspace != 0 && Len(nspace) != 0 && GetFlag(carrays_hash, "lua:no_reg") == 0) {
+ // Split names into components
+ List *components = Split(nspace, '.', -1);
+ String *parent_path = NewString("");
+ int len = Len(components);
+ String *name = Copy(Getitem(components, len - 1));
+ for (int i = 0; i < len - 1; i++) {
+ if (i > 0)
+ Printv(parent_path, NSPACE_SEPARATOR, NIL);
+ String *item = Getitem(components, i);
+ Printv(parent_path, item, NIL);
+ }
+ Hash *parent = getCArraysHash(parent_path, true);
+ String *namespaces_tab = Getattr(parent, "namespaces");
+ Printv(namespaces_tab, "&", cname, ",\n", NIL);
+ if (elua_ltr || eluac_ltr) {
+ String *methods_tab = Getattr(parent, "methods");
+ Printv(methods_tab, tab4, "{LSTRKEY(\"", name, "\")", ", LROVAL(", methods_tab_name, ")", "},\n", NIL);
+ }
+ Setattr(carrays_hash, "name", name);
+
+ Delete(components);
+ Delete(parent_path);
+ } else if (!reg) // This namespace shouldn't be registered. Lets remember it.
+ SetFlag(carrays_hash, "lua:no_reg");
+
+ Delete(mangled_name);
+ mangled_name = 0;
+ return carrays_hash;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * closeCArraysHash()
+ *
+ * Functions add end markers {0,0,...,0} to all arrays, prints them to
+ * output and marks hash as closed (lua:closed). Consequent attempts to
+ * close the same hash will result in an error.
+ * closeCArraysHash DOES NOT print structure that describes namespace, it only
+ * prints array. You can use printCArraysDefinition to print structure.
+ * if "lua:no_namespaces" is set, then array for "namespaces" won't be printed
+ * if "lua:no_classes" is set, then array for "classes" won't be printed
+ * ----------------------------------------------------------------------------- */
+
+ void closeCArraysHash(String *nspace, File *output) {
+ Hash *carrays_hash = rawGetCArraysHash(nspace);
+ assert(carrays_hash);
+ assert(GetFlag(carrays_hash, "lua:closed") == 0);
+
+ SetFlag(carrays_hash, "lua:closed");
+
+ // Do arrays describe class instance part or class static part
+ const int is_instance = GetFlag(carrays_hash, "lua:class_instance");
+
+
+ String *attr_tab = Getattr(carrays_hash, "attributes");
+ Printf(attr_tab, " {0,0,0}\n};\n");
+ Printv(output, attr_tab, NIL);
+
+ String *const_tab = Getattr(carrays_hash, "constants");
+ String *const_tab_name = Getattr(carrays_hash, "constants:name");
+ if (elua_ltr || eluac_ltr)
+ Printv(const_tab, tab4, "{LNILKEY, LNILVAL}\n", "};\n", NIL);
+ else
+ Printf(const_tab, " {0,0,0,0,0,0}\n};\n");
+
+ // For the sake of compiling with -Wall -Werror we print constants
+ // only when necessary
+ int need_constants = 0;
+ if ( (elua_ltr || eluac_ltr) && (old_metatable_bindings) )
+ need_constants = 1;
+ else if (!is_instance) // static part need constants tab
+ need_constants = 1;
+
+ if (need_constants)
+ Printv(output, const_tab, NIL);
+
+ if (elua_ltr) {
+ // Put forward declaration of metatable array
+ Printv(output, "extern ", Getattr(carrays_hash, "metatable:decl"), "\n", NIL);
+ }
+ String *methods_tab = Getattr(carrays_hash, "methods");
+ String *metatable_tab_name = Getattr(carrays_hash, "metatable:name");
+ if (elua_ltr || eluac_ltr) {
+ if (old_metatable_bindings)
+ Printv(methods_tab, tab4, "{LSTRKEY(\"const\"), LROVAL(", const_tab_name, ")},\n", NIL);
+ if (elua_ltr) {
+ Printv(methods_tab, tab4, "{LSTRKEY(\"__metatable\"), LROVAL(", metatable_tab_name, ")},\n", NIL);
+ }
+
+ Printv(methods_tab, tab4, "{LSTRKEY(\"__disown\"), LFUNCVAL(SWIG_Lua_class_disown)},\n", NIL);
+ Printv(methods_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL);
+ } else
+ Printf(methods_tab, " {0,0}\n};\n");
+ Printv(output, methods_tab, NIL);
+
+ if (!GetFlag(carrays_hash, "lua:no_classes")) {
+ String *classes_tab = Getattr(carrays_hash, "classes");
+ Printf(classes_tab, " 0\n};\n");
+ Printv(output, classes_tab, NIL);
+ }
+
+ if (!GetFlag(carrays_hash, "lua:no_namespaces")) {
+ String *namespaces_tab = Getattr(carrays_hash, "namespaces");
+ Printf(namespaces_tab, " 0\n};\n");
+ Printv(output, namespaces_tab, NIL);
+ }
+ if (elua_ltr) {
+ String *get_tab = Getattr(carrays_hash, "get");
+ String *set_tab = Getattr(carrays_hash, "set");
+ Printv(get_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL);
+ Printv(set_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL);
+ Printv(output, get_tab, NIL);
+ Printv(output, set_tab, NIL);
+ }
+
+ // Heuristic whether we need to print metatable or not.
+ // For the sake of compiling with -Wall -Werror we don't print
+ // metatable for static part.
+ int need_metatable = 0;
+ if (eluac_ltr)
+ need_metatable = 0;
+ else if(!is_instance)
+ need_metatable = 0;
+ else
+ need_metatable = 1;
+
+ if (need_metatable) {
+ String *metatable_tab = Getattr(carrays_hash, "metatable");
+ assert(metatable_tab);
+ if (elua_ltr) {
+ String *get_tab_name = Getattr(carrays_hash, "get:name");
+ String *set_tab_name = Getattr(carrays_hash, "set:name");
+
+ if (GetFlag(carrays_hash, "lua:class_instance")) {
+ Printv(metatable_tab, tab4, "{LSTRKEY(\"__index\"), LFUNCVAL(SWIG_Lua_class_get)},\n", NIL);
+ Printv(metatable_tab, tab4, "{LSTRKEY(\"__newindex\"), LFUNCVAL(SWIG_Lua_class_set)},\n", NIL);
+ } else {
+ Printv(metatable_tab, tab4, "{LSTRKEY(\"__index\"), LFUNCVAL(SWIG_Lua_namespace_get)},\n", NIL);
+ Printv(metatable_tab, tab4, "{LSTRKEY(\"__newindex\"), LFUNCVAL(SWIG_Lua_namespace_set)},\n", NIL);
+ }
+
+ Printv(metatable_tab, tab4, "{LSTRKEY(\"__gc\"), LFUNCVAL(SWIG_Lua_class_destruct)},\n", NIL);
+ Printv(metatable_tab, tab4, "{LSTRKEY(\".get\"), LROVAL(", get_tab_name, ")},\n", NIL);
+ Printv(metatable_tab, tab4, "{LSTRKEY(\".set\"), LROVAL(", set_tab_name, ")},\n", NIL);
+ Printv(metatable_tab, tab4, "{LSTRKEY(\".fn\"), LROVAL(", Getattr(carrays_hash, "methods:name"), ")},\n", NIL);
+
+ if (GetFlag(carrays_hash, "lua:class_instance")) {
+ String *static_cls = Getattr(carrays_hash, "lua:class_instance:static_hash");
+ assert(static_cls);
+ // static_cls is swig_lua_namespace. This structure can't be use with eLua(LTR)
+ // Instead structure describing its methods isused
+ String *static_cls_cname = Getattr(static_cls, "methods:name");
+ assert(static_cls_cname);
+ Printv(metatable_tab, tab4, "{LSTRKEY(\".static\"), LROVAL(", static_cls_cname, ")},\n", NIL);
+ // Put forward declaration of this array
+ Printv(output, "extern ", Getattr(static_cls, "methods:decl"), "\n", NIL);
+ } else if (GetFlag(carrays_hash, "lua:class_static")) {
+ Hash *instance_cls = Getattr(carrays_hash, "lua:class_static:instance_hash");
+ assert(instance_cls);
+ String *instance_cls_metatable_name = Getattr(instance_cls, "metatable:name");
+ assert(instance_cls_metatable_name);
+ Printv(metatable_tab, tab4, "{LSTRKEY(\".instance\"), LROVAL(", instance_cls_metatable_name, ")},\n", NIL);
+ }
+
+ Printv(metatable_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL);
+ } else {
+ Printf(metatable_tab, " {0,0}\n};\n");
+ }
+
+ Printv(output, metatable_tab, NIL);
+ }
+
+ Printv(output, "\n", NIL);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * closeNamespaces()
+ *
+ * Recursively close all non-closed namespaces. Prints data to dataOutput.
+ * ----------------------------------------------------------------------------- */
+
+ void closeNamespaces(File *dataOutput) {
+ // Special handling for empty module.
+ if (symbolScopeLookup("") == 0 || rawGetCArraysHash("") == 0) {
+ // Module is empty. Create hash for global scope in order to have swig_SwigModule
+ // variable in resulting file
+ getCArraysHash(0);
+ }
+ // Because we can't directly access 'symtabs', instead we access
+ // top-level scope and look on all scope pseudo-symbols in it.
+ Hash *top_scope = symbolScopeLookup("");
+ assert(top_scope);
+ Iterator ki = First(top_scope);
+ List *to_close = NewList();
+ while (ki.key) {
+ assert(ki.item);
+ if (Getattr(ki.item, "sym:scope")) {
+ // We have a pseudo symbol. Lets get actual scope for this pseudo symbol
+ Hash *carrays_hash = rawGetCArraysHash(ki.key);
+ assert(carrays_hash);
+ if (GetFlag(carrays_hash, "lua:closed") == 0)
+ Append(to_close, ki.key);
+ }
+ ki = Next(ki);
+ }
+ SortList(to_close, &compareByLen);
+ int len = Len(to_close);
+ for (int i = 0; i < len; i++) {
+ String *key = Getitem(to_close, i);
+ closeCArraysHash(key, dataOutput);
+ Hash *carrays_hash = rawGetCArraysHash(key);
+ String *name = 0; // name - name of the namespace as it should be visible in Lua
+ if (DohLen(key) == 0) // This is global module
+ name = module;
+ else
+ name = Getattr(carrays_hash, "name");
+ assert(name);
+ printCArraysDefinition(key, name, dataOutput);
+ }
+ Delete(to_close);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * printCArraysDefinition()
+ *
+ * This function prints to output a definition of namespace in form
+ * swig_lua_namespace $cname = { attr_array, methods_array, ... , namespaces_array };
+ * You can call this function as many times as is necessary.
+ * 'name' is a user-visible name that this namespace will have in Lua. It shouldn't
+ * be a fully qualified name, just its own name.
+ * ----------------------------------------------------------------------------- */
+
+ void printCArraysDefinition(String *nspace, String *name, File *output) {
+ Hash *carrays_hash = getCArraysHash(nspace, false);
+
+ String *cname = Getattr(carrays_hash, "cname"); // cname - name of the C structure that describes namespace
+ assert(cname);
+ Printv(output, "static swig_lua_namespace ", cname, " = ", NIL);
+
+ String *null_string = NewString("0");
+ String *attr_tab_name = Getattr(carrays_hash, "attributes:name");
+ String *methods_tab_name = Getattr(carrays_hash, "methods:name");
+ String *const_tab_name = Getattr(carrays_hash, "constants:name");
+ String *classes_tab_name = Getattr(carrays_hash, "classes:name");
+ String *namespaces_tab_name = Getattr(carrays_hash, "namespaces:name");
+ bool has_classes = GetFlag(carrays_hash, "lua:no_classes") == 0;
+ bool has_namespaces = GetFlag(carrays_hash, "lua:no_namespaces") == 0;
+
+ Printv(output, "{\n",
+ tab4, "\"", name, "\",\n",
+ tab4, methods_tab_name, ",\n",
+ tab4, attr_tab_name, ",\n",
+ tab4, const_tab_name, ",\n",
+ tab4, (has_classes) ? classes_tab_name : null_string, ",\n",
+ tab4, (has_namespaces) ? namespaces_tab_name : null_string, "\n};\n", NIL);
+ Delete(null_string);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * luaCurrentSymbolNSpace()
+ *
+ * This function determines actual namespace/scope where any symbol at the
+ * current moment should be placed. It looks at the 'current' array
+ * and depending on where are we - static class member/function,
+ * instance class member/function or just global functions decides
+ * where symbol should be put.
+ * The namespace/scope doesn't depend from symbol, only from 'current'
+ * ----------------------------------------------------------------------------- */
+
+ String *luaCurrentSymbolNSpace() {
+ String *scope = 0;
+ // If outside class, than NSpace is used.
+ // If inside class, but current[NO_CPP], then this is friend function. It belongs to NSpace
+ if (!getCurrentClass() || current[NO_CPP]) {
+ scope = getNSpace();
+ } else if (current[ENUM_CONST] && !CPlusPlus ) {
+ // Enums in C mode go to NSpace
+ scope = getNSpace();
+ } else {
+ // If inside class, then either class static namespace or class fully qualified name is used
+ assert(!current[NO_CPP]);
+ if (current[STATIC_FUNC] || current[STATIC_VAR] || current[STATIC_CONST]) {
+ scope = class_static_nspace;
+ } else if (current[MEMBER_VAR] || current[CONSTRUCTOR] || current[DESTRUCTOR]
+ || current[MEMBER_FUNC]) {
+ scope = full_proxy_class_name;
+ } else { // Friend functions are handled this way
+ scope = class_static_nspace;
+ }
+ assert(scope);
+ }
+ return scope;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * luaAddSymbol()
+ *
+ * Our implementation of addSymbol. Determines scope correctly, then
+ * forwards to Language::addSymbol
+ * ----------------------------------------------------------------------------- */
+
+ int luaAddSymbol(const String *s, const Node *n) {
+ String *scope = luaCurrentSymbolNSpace();
+ return luaAddSymbol(s, n, scope);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * luaAddSymbol()
+ *
+ * Overload. Enforces given scope. Actually, it simply forwards call to Language::addSymbol
+ * ----------------------------------------------------------------------------- */
+
+ int luaAddSymbol(const String *s, const Node *n, const_String_or_char_ptr scope) {
+ int result = Language::addSymbol(s, n, scope);
+ if (!result)
+ Printf(stderr, "addSymbol(%s to scope %s) failed\n", s, scope);
+ return result;
+ }
+
+};
+
+/* NEW LANGUAGE NOTE:***********************************************
+ in order to add you language into swig, you need to make the following changes:
+ - write this file (obviously)
+ - add into the makefile (not 100% clear on how to do this)
+ - edit swigmain.cxx to add your module
+
+near the top of swigmain.cxx, look for this code & add you own codes
+======= begin change ==========
+extern "C" {
+ Language *swig_tcl(void);
+ Language *swig_python(void);
+ //etc,etc,etc...
+ Language *swig_lua(void); // this is my code
+}
+
+ //etc,etc,etc...
+
+swig_module modules[] = {
+ {"-guile", swig_guile, "Guile"},
+ {"-java", swig_java, "Java"},
+ //etc,etc,etc...
+ {"-lua", swig_lua, "Lua"}, // this is my code
+ {NULL, NULL, NULL} // this must come at the end of the list
+};
+======= end change ==========
+
+This is all that is needed
+
+NEW LANGUAGE NOTE:END ************************************************/
+
+/* -----------------------------------------------------------------------------
+ * swig_lua() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+extern "C" Language *swig_lua(void) {
+ return new LUA();
+}
diff --git a/contrib/tools/swig/Source/Modules/main.cxx b/contrib/tools/swig/Source/Modules/main.cxx
new file mode 100644
index 00000000000..d8f2ab6b4f0
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/main.cxx
@@ -0,0 +1,1416 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * main.cxx
+ *
+ * Main entry point to the SWIG core.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigconfig.h"
+
+#if defined(_WIN32)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+#include "swigmod.h"
+
+#include "swigwarn.h"
+#include "cparse.h"
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h> // for INT_MAX
+
+// Global variables
+
+static Language *lang = 0; // Language method
+int CPlusPlus = 0;
+int Extend = 0; // Extend flag
+int ForceExtern = 0; // Force extern mode
+int GenerateDefault = 1; // Generate default constructors
+int Verbose = 0;
+int AddExtern = 0;
+int NoExcept = 0;
+int SwigRuntime = 0; // 0 = no option, 1 = -runtime, 2 = -noruntime
+
+/* Suppress warning messages for private inheritance, preprocessor evaluation etc...
+ WARN_PP_EVALUATION 202
+ WARN_PARSE_PRIVATE_INHERIT 309
+ WARN_PARSE_BUILTIN_NAME 321
+ WARN_PARSE_REDUNDANT 322
+ WARN_TYPE_ABSTRACT 403
+ WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED 405
+ WARN_LANG_OVERLOAD_CONST 512
+ */
+#define EXTRA_WARNINGS "202,309,403,405,512,321,322"
+
+extern "C" {
+ extern String *ModuleName;
+ extern int ignore_nested_classes;
+ extern int kwargs_supported;
+}
+
+/* usage string split into multiple parts otherwise string is too big for some compilers */
+/* naming conventions for commandline options - no underscores, no capital letters, join words together
+ * except when using a common prefix, then use '-' to separate, eg the debug-xxx options */
+static const char *usage1 = (const char *) "\
+\nGeneral Options\n\
+ -addextern - Add extra extern declarations\n\
+ -c++ - Enable C++ processing\n\
+ -co <file> - Check <file> out of the SWIG library\n\
+ -copyctor - Automatically generate copy constructors wherever possible\n\
+ -cpperraswarn - Treat the preprocessor #error statement as #warning (default)\n\
+ -cppext <ext> - Change file extension of generated C++ files to <ext>\n\
+ (default is cxx)\n\
+ -copyright - Display copyright notices\n\
+ -debug-classes - Display information about the classes found in the interface\n\
+ -debug-module <n>- Display module parse tree at stages 1-4, <n> is a csv list of stages\n\
+ -debug-symtabs - Display symbol tables information\n\
+ -debug-symbols - Display target language symbols in the symbol tables\n\
+ -debug-csymbols - Display C symbols in the symbol tables\n\
+ -debug-lsymbols - Display target language layer symbols\n\
+ -debug-tags - Display information about the tags found in the interface\n\
+ -debug-template - Display information for debugging templates\n\
+ -debug-top <n> - Display entire parse tree at stages 1-4, <n> is a csv list of stages\n\
+ -debug-typedef - Display information about the types and typedefs in the interface\n\
+ -debug-typemap - Display typemap debugging information\n\
+ -debug-tmsearch - Display typemap search debugging information\n\
+ -debug-tmused - Display typemaps used debugging information\n\
+ -directors - Turn on director mode for all the classes, mainly for testing\n\
+ -dirprot - Turn on wrapping of protected members for director classes (default)\n\
+ -D<symbol> - Define a symbol <symbol> (for conditional compilation)\n\
+";
+
+static const char *usage2 = (const char *) "\
+ -E - Preprocess only, does not generate wrapper code\n\
+ -external-runtime [file] - Export the SWIG runtime stack\n\
+ -fakeversion <v>- Make SWIG fake the program version number to <v>\n\
+ -fcompact - Compile in compact mode\n\
+ -features <list>- Set global features, where <list> is a comma separated list of\n\
+ features, eg -features directors,autodoc=1\n\
+ If no explicit value is given to the feature, a default of 1 is used\n\
+ -fastdispatch - Enable fast dispatch mode to produce faster overload dispatcher code\n\
+ -Fmicrosoft - Display error/warning messages in Microsoft format\n\
+ -Fstandard - Display error/warning messages in commonly used format\n\
+ -fvirtual - Compile in virtual elimination mode\n\
+ -help - Display help\n\
+ -I- - Don't search the current directory\n\
+ -I<dir> - Look for SWIG files in directory <dir>\n\
+ -ignoremissing - Ignore missing include files\n\
+ -importall - Follow all #include statements as imports\n\
+ -includeall - Follow all #include statements\n\
+ -l<ifile> - Include SWIG library file <ifile>\n\
+";
+
+static const char *usage3 = (const char *) "\
+ -macroerrors - Report errors inside macros\n\
+ -makedefault - Create default constructors/destructors (the default)\n\
+ -M - List all dependencies\n\
+ -MD - Is equivalent to `-M -MF <file>', except `-E' is not implied\n\
+ -MF <file> - Generate dependencies into <file> and continue generating wrappers\n\
+ -MM - List dependencies, but omit files in SWIG library\n\
+ -MMD - Like `-MD', but omit files in SWIG library\n\
+ -module <name> - Set module name to <name>\n\
+ -MP - Generate phony targets for all dependencies\n\
+ -MT <target> - Set the target of the rule emitted by dependency generation\n\
+ -nocontract - Turn off contract checking\n\
+ -nocpperraswarn - Do not treat the preprocessor #error statement as #warning\n\
+ -nodefault - Do not generate default constructors nor default destructors\n\
+ -nodefaultctor - Do not generate implicit default constructors\n\
+ -nodefaultdtor - Do not generate implicit default destructors\n\
+ -nodirprot - Do not wrap director protected members\n\
+ -noexcept - Do not wrap exception specifiers\n\
+ -nofastdispatch - Disable fast dispatch mode (default)\n\
+ -nopreprocess - Skip the preprocessor step\n\
+ -notemplatereduce - Disable reduction of the typedefs in templates\n\
+";
+
+static const char *usage4 = (const char *) "\
+ -O - Enable the optimization options:\n\
+ -fastdispatch -fvirtual\n\
+ -o <outfile> - Set name of C/C++ output file to <outfile>\n\
+ -oh <headfile> - Set name of C++ output header file for directors to <headfile>\n\
+ -outcurrentdir - Set default output dir to current dir instead of input file's path\n\
+ -outdir <dir> - Set language specific files output directory to <dir>\n\
+ -pcreversion - Display PCRE version information\n\
+ -small - Compile in virtual elimination and compact mode\n\
+ -swiglib - Report location of SWIG library and exit\n\
+ -templatereduce - Reduce all the typedefs in templates\n\
+ -v - Run in verbose mode\n\
+ -version - Display SWIG version number\n\
+ -Wall - Remove all warning suppression, also implies -Wextra\n\
+ -Wallkw - Enable keyword warnings for all the supported languages\n\
+ -Werror - Treat warnings as errors\n\
+ -Wextra - Adds the following additional warnings: " EXTRA_WARNINGS "\n\
+ -w<list> - Suppress/add warning messages, eg -w401,+321 - see Warnings.html\n\
+ -xmlout <file> - Write XML version of the parse tree to <file> after normal processing\n\
+\n\
+Options can also be defined using the SWIG_FEATURES environment variable, for example:\n\
+\n\
+ $ SWIG_FEATURES=\"-Wall\"\n\
+ $ export SWIG_FEATURES\n\
+ $ swig -python interface.i\n\
+\n\
+is equivalent to:\n\
+\n\
+ $ swig -Wall -python interface.i\n\
+\n\
+Arguments may also be passed in a file, separated by whitespace. For example:\n\
+\n\
+ $ echo \"-Wall -python interface.i\" > args.txt\n\
+ $ swig @args.txt\n\
+\n";
+
+// Local variables
+static String *LangSubDir = 0; // Target language library subdirectory
+static String *SwigLib = 0; // Library directory
+static String *SwigLibWinUnix = 0; // Extra library directory on Windows
+static int freeze = 0;
+static String *lang_config = 0;
+static const char *hpp_extension = "h";
+static const char *cpp_extension = "cxx";
+static const char *depends_extension = "d";
+static String *outdir = 0;
+static String *xmlout = 0;
+static int outcurrentdir = 0;
+static int help = 0;
+static int checkout = 0;
+static int cpp_only = 0;
+static int no_cpp = 0;
+static String *outfile_name = 0;
+static String *outfile_name_h = 0;
+static int tm_debug = 0;
+static int dump_symtabs = 0;
+static int dump_symbols = 0;
+static int dump_csymbols = 0;
+static int dump_lang_symbols = 0;
+static int dump_tags = 0;
+static int dump_module = 0;
+static int dump_top = 0;
+static int dump_xml = 0;
+static int browse = 0;
+static int dump_typedef = 0;
+static int dump_classes = 0;
+static int werror = 0;
+static int depend = 0;
+static int depend_only = 0;
+static int depend_phony = 0;
+static int memory_debug = 0;
+static int allkw = 0;
+static DOH *cpps = 0;
+static String *dependencies_file = 0;
+static String *dependencies_target = 0;
+static int external_runtime = 0;
+static String *external_runtime_name = 0;
+enum { STAGE1=1, STAGE2=2, STAGE3=4, STAGE4=8, STAGEOVERFLOW=16 };
+static List *libfiles = 0;
+static List *all_output_files = 0;
+
+/* -----------------------------------------------------------------------------
+ * check_extension()
+ *
+ * Checks the extension of a file to see if we should emit extern declarations.
+ * ----------------------------------------------------------------------------- */
+
+static bool check_extension(String *filename) {
+ bool wanted = false;
+ const char *name = Char(filename);
+ if (!name)
+ return 0;
+ String *extension = Swig_file_extension(name);
+ const char *c = Char(extension);
+ if ((strcmp(c, ".c") == 0) ||
+ (strcmp(c, ".C") == 0) || (strcmp(c, ".cc") == 0) || (strcmp(c, ".cxx") == 0) || (strcmp(c, ".c++") == 0) || (strcmp(c, ".cpp") == 0)) {
+ wanted = true;
+ }
+ Delete(extension);
+ return wanted;
+}
+
+/* -----------------------------------------------------------------------------
+ * install_opts()
+ *
+ * Install all command line options as preprocessor symbols
+ * ----------------------------------------------------------------------------- */
+
+static void install_opts(int argc, char *argv[]) {
+ int i;
+ int noopt = 0;
+ char *c;
+ for (i = 1; i < (argc - 1); i++) {
+ if (argv[i]) {
+ if ((*argv[i] == '-') && (!isupper(*(argv[i] + 1)))) {
+ String *opt = NewStringf("SWIGOPT%(upper)s", argv[i]);
+ Replaceall(opt, "-", "_");
+ c = Char(opt);
+ noopt = 0;
+ while (*c) {
+ if (!(isalnum(*c) || (*c == '_'))) {
+ noopt = 1;
+ break;
+ }
+ c++;
+ }
+ if (((i + 1) < (argc - 1)) && (argv[i + 1]) && (*argv[i + 1] != '-')) {
+ Printf(opt, " %s", argv[i + 1]);
+ i++;
+ } else {
+ Printf(opt, " 1");
+ }
+ if (!noopt) {
+ /* Printf(stdout,"%s\n", opt); */
+ Preprocessor_define(opt, 0);
+ }
+ Delete(opt);
+ }
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * decode_numbers_list()
+ *
+ * Decode comma separated list into a binary number of the inputs or'd together
+ * eg list="1,4" will return (2^0 || 2^3) = 0x1001
+ * ----------------------------------------------------------------------------- */
+
+static unsigned int decode_numbers_list(String *numlist) {
+ unsigned int decoded_number = 0;
+ if (numlist) {
+ List *numbers = Split(numlist, ',', INT_MAX);
+ if (numbers && Len(numbers) > 0) {
+ for (Iterator it = First(numbers); it.item; it = Next(it)) {
+ String *numstring = it.item;
+ // TODO: check that it is a number
+ int number = atoi(Char(numstring));
+ if (number > 0 && number <= 16) {
+ decoded_number |= (1 << (number-1));
+ }
+ }
+ }
+ }
+ return decoded_number;
+}
+
+/* -----------------------------------------------------------------------------
+ * Sets the output directory for language specific (proxy) files from the
+ * C wrapper file if not set and corrects the directory name and adds a trailing
+ * file separator if necessary.
+ * ----------------------------------------------------------------------------- */
+
+static void configure_outdir(const String *c_wrapper_outfile) {
+
+ // Use the C wrapper file's directory if the output directory has not been set by user
+ if (!outdir || Len(outdir) == 0)
+ outdir = Swig_file_dirname(c_wrapper_outfile);
+
+ Swig_filename_correct(outdir);
+
+ // Add trailing file delimiter if not present in output directory name
+ if (Len(outdir) > 0) {
+ const char *outd = Char(outdir);
+ if (strcmp(outd + strlen(outd) - strlen(SWIG_FILE_DELIMITER), SWIG_FILE_DELIMITER) != 0)
+ Printv(outdir, SWIG_FILE_DELIMITER, NIL);
+ }
+}
+
+/* This function sets the name of the configuration file */
+void SWIG_config_file(const_String_or_char_ptr filename) {
+ lang_config = NewString(filename);
+}
+
+/* Sets the target language subdirectory name */
+void SWIG_library_directory(const char *subdirectory) {
+ LangSubDir = NewString(subdirectory);
+}
+
+// Returns the directory for generating language specific files (non C/C++ files)
+const String *SWIG_output_directory() {
+ assert(outdir);
+ return outdir;
+}
+
+void SWIG_config_cppext(const char *ext) {
+ cpp_extension = ext;
+}
+
+List *SWIG_output_files() {
+ assert(all_output_files);
+ return all_output_files;
+}
+
+void SWIG_setfeature(const char *cfeature, const char *cvalue) {
+ Hash *features_hash = Swig_cparse_features();
+ String *name = NewString("");
+ String *fname = NewString(cfeature);
+ String *fvalue = NewString(cvalue);
+ Swig_feature_set(features_hash, name, 0, fname, fvalue, 0);
+ Delete(name);
+ Delete(fname);
+ Delete(fvalue);
+}
+
+
+void SWIG_setfeatures(const char *c) {
+ char feature[64];
+ char *fb = feature;
+ char *fe = fb + 63;
+ Hash *features_hash = Swig_cparse_features();
+ String *name = NewString("");
+ /* Printf(stderr,"all features %s\n", c); */
+ while (*c) {
+ char *f = fb;
+ String *fname = NewString("feature:");
+ String *fvalue = NewString("");
+ while ((f != fe) && *c != '=' && *c != ',' && *c) {
+ *(f++) = *(c++);
+ }
+ *f = 0;
+ Printf(fname, "%s", feature);
+ if (*c && *(c++) == '=') {
+ char value[64];
+ char *v = value;
+ char *ve = v + 63;
+ while ((v != ve) && *c != ',' && *c && !isspace(*c)) {
+ *(v++) = *(c++);
+ }
+ *v = 0;
+ Printf(fvalue, "%s", value);
+ } else {
+ Printf(fvalue, "1");
+ }
+ /* Printf(stderr,"%s %s\n", fname, fvalue); */
+ Swig_feature_set(features_hash, name, 0, fname, fvalue, 0);
+ Delete(fname);
+ Delete(fvalue);
+ }
+ Delete(name);
+}
+
+/* This function handles the -external-runtime command option */
+static void SWIG_dump_runtime() {
+ String *outfile;
+ File *runtime;
+ String *s;
+
+ outfile = external_runtime_name;
+ if (!outfile) {
+ outfile = lang->defaultExternalRuntimeFilename();
+ if (!outfile) {
+ Printf(stderr, "*** Please provide a filename for the external runtime\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+
+ runtime = NewFile(outfile, "w", SWIG_output_files());
+ if (!runtime) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ Swig_banner(runtime);
+ Printf(runtime, "\n");
+
+ s = Swig_include_sys("swiglabels.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'swiglabels.swg'\n");
+ Delete(runtime);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Printf(runtime, "%s", s);
+ Delete(s);
+
+ s = Swig_include_sys("swigerrors.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'swigerrors.swg'\n");
+ Delete(runtime);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Printf(runtime, "%s", s);
+ Delete(s);
+
+ s = Swig_include_sys("swigrun.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'swigrun.swg'\n");
+ Delete(runtime);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Printf(runtime, "%s", s);
+ Delete(s);
+
+ s = lang->runtimeCode();
+ Printf(runtime, "%s", s);
+ Delete(s);
+
+ s = Swig_include_sys("runtime.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'runtime.swg'\n");
+ Delete(runtime);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Printf(runtime, "%s", s);
+ Delete(s);
+
+ Delete(runtime);
+ SWIG_exit(EXIT_SUCCESS);
+}
+
+static void getoptions(int argc, char *argv[]) {
+ int i;
+ // Get options
+ for (i = 1; i < argc; i++) {
+ if (argv[i] && !Swig_check_marked(i)) {
+ if (strncmp(argv[i], "-I-", 3) == 0) {
+ // Don't push/pop directories
+ Swig_set_push_dir(0);
+ Swig_mark_arg(i);
+ } else if (strncmp(argv[i], "-I", 2) == 0) {
+ // Add a new directory search path
+ char *a = Swig_copy_string(argv[i] + 2);
+ Swig_add_directory((DOH *) a);
+ free(a);
+ Swig_mark_arg(i);
+ } else if (strncmp(argv[i], "-D", 2) == 0) {
+ String *d = NewString(argv[i] + 2);
+ Replace(d, "=", " ", DOH_REPLACE_ANY | DOH_REPLACE_FIRST);
+ Preprocessor_define((DOH *) d, 0);
+ Delete(d);
+ // Create a symbol
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-E") == 0) {
+ cpp_only = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nopreprocess") == 0) {
+ no_cpp = 1;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-verbose") == 0) || (strcmp(argv[i], "-v") == 0)) {
+ Verbose = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-c++") == 0) {
+ CPlusPlus = 1;
+ Preprocessor_define((DOH *) "__cplusplus __cplusplus", 0);
+ Swig_cparse_cplusplus(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-c++out") == 0) {
+ // Undocumented
+ Swig_cparse_cplusplusout(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-fcompact") == 0) {
+ Wrapper_compact_print_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-fvirtual") == 0) {
+ Wrapper_virtual_elimination_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-fastdispatch") == 0) {
+ Wrapper_fast_dispatch_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nofastdispatch") == 0) {
+ Wrapper_fast_dispatch_mode_set(0);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-naturalvar") == 0) {
+ Wrapper_naturalvar_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-directors") == 0) {
+ SWIG_setfeature("feature:director", "1");
+ Wrapper_director_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-dirprot") == 0) {
+ Wrapper_director_protected_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nodirprot") == 0) {
+ Wrapper_director_protected_mode_set(0);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-pcreversion") == 0) {
+ String *version = Swig_pcre_version();
+ Printf(stdout, "%s\n", version);
+ Delete(version);
+ Swig_mark_arg(i);
+ SWIG_exit(EXIT_SUCCESS);
+ } else if (strcmp(argv[i], "-small") == 0) {
+ Wrapper_compact_print_mode_set(1);
+ Wrapper_virtual_elimination_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-runtime") == 0) { // Used to also accept -c. removed in swig-1.3.36
+ Swig_mark_arg(i);
+ Swig_warning(WARN_DEPRECATED_OPTC, "SWIG", 1, "-runtime, -noruntime command line options are deprecated.\n");
+ SwigRuntime = 1;
+ } else if (strcmp(argv[i], "-noruntime") == 0) {
+ Swig_mark_arg(i);
+ Swig_warning(WARN_DEPRECATED_OPTC, "SWIG", 1, "-runtime, -noruntime command line options are deprecated.\n");
+ SwigRuntime = 2;
+ } else if (strcmp(argv[i], "-external-runtime") == 0) {
+ external_runtime = 1;
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ external_runtime_name = NewString(argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ i++;
+ }
+ } else if ((strcmp(argv[i], "-make_default") == 0) || (strcmp(argv[i], "-makedefault") == 0)) {
+ GenerateDefault = 1;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-no_default") == 0) || (strcmp(argv[i], "-nodefault") == 0)) {
+ GenerateDefault = 0;
+ Swig_warning(WARN_DEPRECATED_NODEFAULT, "SWIG", 1, "dangerous, use -nodefaultctor, -nodefaultdtor instead.\n");
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-nodefaultctor") == 0)) {
+ SWIG_setfeature("feature:nodefaultctor", "1");
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-nodefaultdtor") == 0)) {
+ SWIG_setfeature("feature:nodefaultdtor", "1");
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-copyctor") == 0)) {
+ SWIG_setfeature("feature:copyctor", "1");
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-noexcept") == 0) {
+ NoExcept = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-noextern") == 0) {
+ Swig_warning(WARN_DEPRECATED_NOEXTERN, "SWIG", 1, "-noextern command line option is deprecated; extern is no longer generated by default.\n");
+ AddExtern = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-addextern") == 0) {
+ AddExtern = 1;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-debug-template") == 0) || (strcmp(argv[i], "-debug_template") == 0) || (strcmp(argv[i], "-show_templates") == 0)) {
+ Swig_cparse_debug_templates(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-templatereduce") == 0) {
+ SWIG_cparse_template_reduce(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-notemplatereduce") == 0) {
+ SWIG_cparse_template_reduce(0);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-macroerrors") == 0) {
+ Swig_cparse_follow_locators(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-swiglib") == 0) {
+ Printf(stdout, "%s\n", SwigLib);
+ if (SwigLibWinUnix)
+ Printf(stdout, "%s\n", SwigLibWinUnix);
+ SWIG_exit(EXIT_SUCCESS);
+ } else if (strcmp(argv[i], "-o") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ outfile_name = NewString(argv[i + 1]);
+ Swig_filename_correct(outfile_name);
+ if (!outfile_name_h || !dependencies_file) {
+ char *ext = strrchr(Char(outfile_name), '.');
+ String *basename = ext ? NewStringWithSize(Char(outfile_name), (int)(Char(ext) - Char(outfile_name))) : NewString(outfile_name);
+ if (!dependencies_file) {
+ dependencies_file = NewStringf("%s.%s", basename, depends_extension);
+ }
+ if (!outfile_name_h) {
+ Printf(basename, ".%s", hpp_extension);
+ outfile_name_h = NewString(basename);
+ }
+ Delete(basename);
+ }
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-oh") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ outfile_name_h = NewString(argv[i + 1]);
+ Swig_filename_correct(outfile_name_h);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-fakeversion") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ Swig_set_fakeversion(argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-version") == 0) {
+ fprintf(stdout, "\nSWIG Version %s\n", Swig_package_version());
+ fprintf(stdout, "\nCompiled with %s [%s]\n", SWIG_CXX, SWIG_PLATFORM);
+ fprintf(stdout, "\nConfigured options: %cpcre\n",
+#ifdef HAVE_PCRE
+ '+'
+#else
+ '-'
+#endif
+ );
+ fprintf(stdout, "\nPlease see %s for reporting bugs and further information\n", PACKAGE_BUGREPORT);
+ SWIG_exit(EXIT_SUCCESS);
+ } else if (strcmp(argv[i], "-copyright") == 0) {
+ fprintf(stdout, "\nSWIG Version %s\n", Swig_package_version());
+ fprintf(stdout, "Copyright (c) 1995-1998\n");
+ fprintf(stdout, "University of Utah and the Regents of the University of California\n");
+ fprintf(stdout, "Copyright (c) 1998-2005\n");
+ fprintf(stdout, "University of Chicago\n");
+ fprintf(stdout, "Copyright (c) 2005-2006\n");
+ fprintf(stdout, "Arizona Board of Regents (University of Arizona)\n");
+ SWIG_exit(EXIT_SUCCESS);
+ } else if (strncmp(argv[i], "-l", 2) == 0) {
+ // Add a new directory search path
+ Append(libfiles, argv[i] + 2);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-co") == 0) {
+ checkout = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-features") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ SWIG_setfeatures(argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-freeze") == 0) {
+ freeze = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-includeall") == 0) {
+ Preprocessor_include_all(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-importall") == 0) {
+ Preprocessor_import_all(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-ignoremissing") == 0) {
+ Preprocessor_ignore_missing(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-cpperraswarn") == 0) {
+ Preprocessor_error_as_warning(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocpperraswarn") == 0) {
+ Preprocessor_error_as_warning(0);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-cppext") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ SWIG_config_cppext(argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if ((strcmp(argv[i], "-debug-typemap") == 0) || (strcmp(argv[i], "-debug_typemap") == 0) || (strcmp(argv[i], "-tm_debug") == 0)) {
+ tm_debug = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-tmsearch") == 0) {
+ Swig_typemap_search_debug_set();
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-tmused") == 0) {
+ Swig_typemap_used_debug_set();
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-module") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ ModuleName = NewString(argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-M") == 0) {
+ depend = 1;
+ depend_only = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-MM") == 0) {
+ depend = 2;
+ depend_only = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-MF") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ dependencies_file = NewString(argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-MD") == 0) {
+ depend = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-MMD") == 0) {
+ depend = 2;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-MP") == 0) {
+ depend_phony = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-MT") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ if (!dependencies_target)
+ dependencies_target = NewString(argv[i + 1]);
+ else
+ Printf(dependencies_target, " %s", argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-outdir") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ outdir = NewString(argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-outcurrentdir") == 0) {
+ Swig_mark_arg(i);
+ outcurrentdir = 1;
+ } else if (strcmp(argv[i], "-Wall") == 0) {
+ Swig_mark_arg(i);
+ Swig_warnall();
+ } else if (strcmp(argv[i], "-Wallkw") == 0) {
+ allkw = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-Werror") == 0) {
+ werror = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-Wextra") == 0) {
+ Swig_mark_arg(i);
+ Swig_warnfilter(EXTRA_WARNINGS, 0);
+ } else if (strncmp(argv[i], "-w", 2) == 0) {
+ Swig_mark_arg(i);
+ Swig_warnfilter(argv[i] + 2, 1);
+ } else if (strcmp(argv[i], "-debug-symtabs") == 0) {
+ dump_symtabs = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-symbols") == 0) {
+ dump_symbols = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-csymbols") == 0) {
+ dump_csymbols = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-lsymbols") == 0) {
+ dump_lang_symbols = 1;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-debug-tags") == 0) || (strcmp(argv[i], "-dump_tags") == 0)) {
+ dump_tags = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-top") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ String *dump_list = NewString(argv[i + 1]);
+ dump_top = decode_numbers_list(dump_list);
+ if (dump_top < STAGE1 || dump_top >= STAGEOVERFLOW)
+ Swig_arg_error();
+ else
+ Swig_mark_arg(i + 1);
+ Delete(dump_list);
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-debug-module") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ String *dump_list = NewString(argv[i + 1]);
+ dump_module = decode_numbers_list(dump_list);
+ if (dump_module < STAGE1 || dump_module >= STAGEOVERFLOW)
+ Swig_arg_error();
+ else
+ Swig_mark_arg(i + 1);
+ Delete(dump_list);
+ } else {
+ Swig_arg_error();
+ }
+ } else if ((strcmp(argv[i], "-dump_tree") == 0) || (strcmp(argv[i], "-dump_top") == 0)) {
+ dump_top |= STAGE4;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-dump_module") == 0) {
+ dump_module |= STAGE4;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-dump_parse_module") == 0) {
+ dump_module |= STAGE1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-dump_parse_top") == 0) {
+ dump_top |= STAGE1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-dump_xml") == 0) {
+ dump_xml = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-xmlout") == 0) {
+ dump_xml = 1;
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ xmlout = NewString(argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-nocontract") == 0) {
+ Swig_mark_arg(i);
+ Swig_contract_mode_set(0);
+ } else if (strcmp(argv[i], "-browse") == 0) {
+ browse = 1;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-debug-typedef") == 0) || (strcmp(argv[i], "-dump_typedef") == 0)) {
+ dump_typedef = 1;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-debug-classes") == 0) || (strcmp(argv[i], "-dump_classes") == 0)) {
+ dump_classes = 1;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-debug-memory") == 0) || (strcmp(argv[i], "-dump_memory") == 0)) {
+ memory_debug = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-Fstandard") == 0) {
+ Swig_error_msg_format(EMF_STANDARD);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-Fmicrosoft") == 0) {
+ Swig_error_msg_format(EMF_MICROSOFT);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-O") == 0) {
+ Wrapper_virtual_elimination_mode_set(1);
+ Wrapper_fast_dispatch_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage1, stdout);
+ fputs(usage2, stdout);
+ fputs(usage3, stdout);
+ fputs(usage4, stdout);
+ Swig_mark_arg(i);
+ help = 1;
+ }
+ }
+ }
+}
+
+int SWIG_main(int argc, char *argv[], const TargetLanguageModule *tlm) {
+ char *c;
+
+ /* Initialize the SWIG core */
+ Swig_init();
+
+ // Default warning suppression
+ Swig_warnfilter(EXTRA_WARNINGS, 1);
+
+ // Initialize the preprocessor
+ Preprocessor_init();
+
+ // Set lang to a dummy value if no target language was specified so we
+ // can process options enough to handle -version, etc.
+ lang = tlm ? tlm->fac() : new Language;
+
+ // Set up some default symbols (available in both SWIG interface files
+ // and C files)
+
+ Preprocessor_define((DOH *) "SWIG 1", 0);
+ Preprocessor_define((DOH *) "__STDC__", 0);
+
+ // Set the SWIG version value in format 0xAABBCC from package version expected to be in format A.B.C
+ String *package_version = NewString(PACKAGE_VERSION); /* Note that the fakeversion has not been set at this point */
+ char *token = strtok(Char(package_version), ".");
+ String *vers = NewString("SWIG_VERSION 0x");
+ int count = 0;
+ while (token) {
+ int len = (int)strlen(token);
+ assert(len == 1 || len == 2);
+ Printf(vers, "%s%s", (len == 1) ? "0" : "", token);
+ token = strtok(NULL, ".");
+ count++;
+ }
+ Delete(package_version);
+ assert(count == 3); // Check version format is correct
+
+ /* Turn on contracts */
+
+ Swig_contract_mode_set(1);
+ Preprocessor_define(vers, 0);
+
+ /* Turn off directors mode */
+ Wrapper_director_mode_set(0);
+ Wrapper_director_protected_mode_set(1);
+
+ // Inform the parser if the nested classes should be ignored unless explicitly told otherwise via feature:flatnested
+ ignore_nested_classes = lang->nestedClassesSupport() == Language::NCS_Unknown ? 1 : 0;
+
+ kwargs_supported = lang->kwargsSupport() ? 1 : 0;
+
+ // Create Library search directories
+
+ // Check for SWIG_LIB environment variable
+ if ((c = getenv("SWIG_LIB")) == (char *) 0) {
+#if defined(_WIN32)
+ char buf[MAX_PATH];
+ char *p;
+ if (!(GetModuleFileName(0, buf, MAX_PATH) == 0 || (p = strrchr(buf, '\\')) == 0)) {
+ *(p + 1) = '\0';
+ SwigLib = NewStringf("%sLib", buf); // Native windows installation path
+ } else {
+ SwigLib = NewStringf(""); // Unexpected error
+ }
+ if (Len(SWIG_LIB_WIN_UNIX) > 0)
+ SwigLibWinUnix = NewString(SWIG_LIB_WIN_UNIX); // Unix installation path using a drive letter (for msys/mingw)
+#else
+ SwigLib = NewString(SWIG_LIB);
+#endif
+ } else {
+ SwigLib = NewString(c);
+ }
+
+ libfiles = NewList();
+ all_output_files = NewList();
+
+ /* Check for SWIG_FEATURES environment variable */
+
+ getoptions(argc, argv);
+
+ // Define the __cplusplus symbol
+ if (CPlusPlus)
+ Preprocessor_define((DOH *) "__cplusplus __cplusplus", 0);
+
+ // Parse language dependent options
+ lang->main(argc, argv);
+
+ if (help) {
+ Printf(stdout, "\nNote: 'swig -<lang> -help' displays options for a specific target language.\n\n");
+ SWIG_exit(EXIT_SUCCESS); // Exit if we're in help mode
+ }
+
+ // Check all of the options to make sure we're cool.
+ // Don't check for an input file if -external-runtime is passed
+ Swig_check_options(external_runtime ? 0 : 1);
+
+ if (CPlusPlus && cparse_cplusplusout) {
+ Printf(stderr, "The -c++out option is for C input but C++ input has been requested via -c++\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ install_opts(argc, argv);
+
+ // Add language dependent directory to the search path
+ {
+ String *rl = NewString("");
+ Printf(rl, ".%sswig_lib%s%s", SWIG_FILE_DELIMITER, SWIG_FILE_DELIMITER, LangSubDir);
+ Swig_add_directory(rl);
+ if (SwigLibWinUnix) {
+ rl = NewString("");
+ Printf(rl, "%s%s%s", SwigLibWinUnix, SWIG_FILE_DELIMITER, LangSubDir);
+ Swig_add_directory(rl);
+ }
+ rl = NewString("");
+ Printf(rl, "%s%s%s", SwigLib, SWIG_FILE_DELIMITER, LangSubDir);
+ Swig_add_directory(rl);
+ }
+
+ Swig_add_directory((String *) "." SWIG_FILE_DELIMITER "swig_lib");
+ if (SwigLibWinUnix)
+ Swig_add_directory((String *) SwigLibWinUnix);
+ Swig_add_directory(SwigLib);
+
+ if (Verbose) {
+ Printf(stdout, "Language subdirectory: %s\n", LangSubDir);
+ Printf(stdout, "Search paths:\n");
+ List *sp = Swig_search_path();
+ Iterator s;
+ for (s = First(sp); s.item; s = Next(s)) {
+ Printf(stdout, " %s\n", s.item);
+ }
+ }
+ // handle the -external-runtime argument
+ if (external_runtime)
+ SWIG_dump_runtime();
+
+ // If we made it this far, looks good. go for it....
+
+ input_file = NewString(argv[argc - 1]);
+ Swig_filename_correct(input_file);
+
+ // If the user has requested to check out a file, handle that
+ if (checkout) {
+ DOH *s;
+ String *outfile = input_file;
+ if (outfile_name)
+ outfile = outfile_name;
+
+ if (Verbose)
+ Printf(stdout, "Handling checkout...\n");
+
+ s = Swig_include(input_file);
+ if (!s) {
+ Printf(stderr, "Unable to locate '%s' in the SWIG library.\n", input_file);
+ } else {
+ FILE *f = Swig_open(outfile);
+ if (f) {
+ fclose(f);
+ Printf(stderr, "File '%s' already exists. Checkout aborted.\n", outfile);
+ } else {
+ File *f_outfile = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_outfile) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ } else {
+ if (Verbose)
+ Printf(stdout, "'%s' checked out from the SWIG library.\n", outfile);
+ Printv(f_outfile, s, NIL);
+ Delete(f_outfile);
+ }
+ }
+ }
+ } else {
+ // Run the preprocessor
+ if (Verbose)
+ Printf(stdout, "Preprocessing...\n");
+
+ {
+ int i;
+ String *fs = NewString("");
+ FILE *df = Swig_open(input_file);
+ if (!df) {
+ df = Swig_include_open(input_file);
+ if (!df) {
+ char *cfile = Char(input_file);
+ if (cfile && cfile[0] == '-') {
+ Printf(stderr, "Unable to find option or file '%s', ", input_file);
+ Printf(stderr, "Use 'swig -help' for more information.\n");
+ } else {
+ Printf(stderr, "Unable to find file '%s'.\n", input_file);
+ }
+ SWIG_exit(EXIT_FAILURE);
+ } else {
+ Swig_warning(WARN_DEPRECATED_INPUT_FILE, "SWIG", 1, "Use of the include path to find the input file is deprecated and will not work with ccache. Please include the path when specifying the input file.\n"); // so that behaviour is like c/c++ compilers
+ }
+ }
+
+ if (!tlm) {
+ Printf(stderr, "No target language specified.\n");
+ Printf(stderr, "Use 'swig -help' for more information.\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ if (!no_cpp) {
+ fclose(df);
+ Printf(fs, "%%include <swig.swg>\n");
+ if (allkw) {
+ Printf(fs, "%%include <allkw.swg>\n");
+ }
+ if (lang_config) {
+ Printf(fs, "\n%%include <%s>\n", lang_config);
+ }
+ Printf(fs, "%%include(maininput=\"%s\") \"%s\"\n", Swig_filename_escape(input_file), Swig_filename_escape(Swig_last_file()));
+ for (i = 0; i < Len(libfiles); i++) {
+ Printf(fs, "\n%%include \"%s\"\n", Swig_filename_escape(Getitem(libfiles, i)));
+ }
+ Seek(fs, 0, SEEK_SET);
+ cpps = Preprocessor_parse(fs);
+ Delete(fs);
+ } else {
+ cpps = Swig_read_file(df);
+ fclose(df);
+ }
+ if (Swig_error_count()) {
+ SWIG_exit(EXIT_FAILURE);
+ }
+ if (cpp_only) {
+ Printf(stdout, "%s", cpps);
+ SWIG_exit(EXIT_SUCCESS);
+ }
+ if (depend) {
+ if (!no_cpp) {
+ String *outfile;
+ File *f_dependencies_file = 0;
+
+ String *inputfile_filename = outcurrentdir ? Swig_file_filename(input_file): Copy(input_file);
+ String *basename = Swig_file_basename(inputfile_filename);
+ if (!outfile_name) {
+ if (CPlusPlus || lang->cplus_runtime_mode()) {
+ outfile = NewStringf("%s_wrap.%s", basename, cpp_extension);
+ } else {
+ outfile = NewStringf("%s_wrap.c", basename);
+ }
+ } else {
+ outfile = NewString(outfile_name);
+ }
+ if (dependencies_file && Len(dependencies_file) != 0) {
+ f_dependencies_file = NewFile(dependencies_file, "w", SWIG_output_files());
+ if (!f_dependencies_file) {
+ FileErrorDisplay(dependencies_file);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ } else if (!depend_only) {
+ String *filename = NewStringf("%s_wrap.%s", basename, depends_extension);
+ f_dependencies_file = NewFile(filename, "w", SWIG_output_files());
+ if (!f_dependencies_file) {
+ FileErrorDisplay(filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ } else
+ f_dependencies_file = stdout;
+ if (dependencies_target) {
+ Printf(f_dependencies_file, "%s: ", Swig_filename_escape_space(dependencies_target));
+ } else {
+ Printf(f_dependencies_file, "%s: ", Swig_filename_escape_space(outfile));
+ }
+ List *files = Preprocessor_depend();
+ List *phony_targets = NewList();
+ for (int i = 0; i < Len(files); i++) {
+ int use_file = 1;
+ if (depend == 2) {
+ if ((Strncmp(Getitem(files, i), SwigLib, Len(SwigLib)) == 0) || (SwigLibWinUnix && (Strncmp(Getitem(files, i), SwigLibWinUnix, Len(SwigLibWinUnix)) == 0)))
+ use_file = 0;
+ }
+ if (use_file) {
+ Printf(f_dependencies_file, "\\\n %s ", Swig_filename_escape_space(Getitem(files, i)));
+ if (depend_phony)
+ Append(phony_targets, Getitem(files, i));
+ }
+ }
+ Printf(f_dependencies_file, "\n");
+ if (depend_phony) {
+ for (int i = 0; i < Len(phony_targets); i++) {
+ Printf(f_dependencies_file, "\n%s:\n", Swig_filename_escape_space(Getitem(phony_targets, i)));
+ }
+ }
+
+ if (f_dependencies_file != stdout)
+ Delete(f_dependencies_file);
+ if (depend_only)
+ SWIG_exit(EXIT_SUCCESS);
+ Delete(inputfile_filename);
+ Delete(basename);
+ Delete(phony_targets);
+ } else {
+ Printf(stderr, "Cannot generate dependencies with -nopreprocess\n");
+ // Actually we could but it would be inefficient when just generating dependencies, as it would be done after Swig_cparse
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+ Seek(cpps, 0, SEEK_SET);
+ }
+
+ /* Register a null file with the file handler */
+ Swig_register_filebyname("null", NewString(""));
+
+ // Pass control over to the specific language interpreter
+ if (Verbose) {
+ fprintf(stdout, "Starting language-specific parse...\n");
+ fflush(stdout);
+ }
+
+ Node *top = Swig_cparse(cpps);
+
+ if (dump_top & STAGE1) {
+ Printf(stdout, "debug-top stage 1\n");
+ Swig_print_tree(top);
+ }
+ if (dump_module & STAGE1) {
+ Printf(stdout, "debug-module stage 1\n");
+ Swig_print_tree(Getattr(top, "module"));
+ }
+ if (!CPlusPlus) {
+ if (Verbose)
+ Printf(stdout, "Processing unnamed structs...\n");
+ Swig_nested_name_unnamed_c_structs(top);
+ }
+ Swig_extend_unused_check();
+
+ if (Verbose) {
+ Printf(stdout, "Processing types...\n");
+ }
+ Swig_process_types(top);
+
+ if (dump_top & STAGE2) {
+ Printf(stdout, "debug-top stage 2\n");
+ Swig_print_tree(top);
+ }
+ if (dump_module & STAGE2) {
+ Printf(stdout, "debug-module stage 2\n");
+ Swig_print_tree(Getattr(top, "module"));
+ }
+
+ if (Verbose) {
+ Printf(stdout, "C++ analysis...\n");
+ }
+ Swig_default_allocators(top);
+
+ if (CPlusPlus) {
+ if (Verbose)
+ Printf(stdout, "Processing nested classes...\n");
+ Swig_nested_process_classes(top);
+ }
+
+ if (dump_top & STAGE3) {
+ Printf(stdout, "debug-top stage 3\n");
+ Swig_print_tree(top);
+ }
+ if (top && (dump_module & STAGE3)) {
+ Printf(stdout, "debug-module stage 3\n");
+ Swig_print_tree(Getattr(top, "module"));
+ }
+
+ if (Verbose) {
+ Printf(stdout, "Generating wrappers...\n");
+ }
+
+ if (top && dump_classes) {
+ Hash *classes = Getattr(top, "classes");
+ if (classes) {
+ Printf(stdout, "Classes\n");
+ Printf(stdout, "------------\n");
+ Iterator ki;
+ for (ki = First(classes); ki.key; ki = Next(ki)) {
+ Printf(stdout, "%s\n", ki.key);
+ }
+ }
+ }
+
+ if (dump_typedef) {
+ SwigType_print_scope();
+ }
+
+ if (dump_symtabs) {
+ Swig_symbol_print_tables(Swig_symbol_global_scope());
+ Swig_symbol_print_tables_summary();
+ }
+
+ if (dump_symbols) {
+ Swig_symbol_print_symbols();
+ }
+
+ if (dump_csymbols) {
+ Swig_symbol_print_csymbols();
+ }
+
+ if (dump_tags) {
+ Swig_print_tags(top, 0);
+ }
+ if (top) {
+ if (!Getattr(top, "name")) {
+ Printf(stderr, "No module name specified using %%module or -module.\n");
+ SWIG_exit(EXIT_FAILURE);
+ } else {
+ /* Set some filename information on the object */
+ String *infile = scanner_get_main_input_file();
+ if (!infile) {
+ Printf(stderr, "Missing input file in preprocessed output.\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Setattr(top, "infile", infile); // Note: if nopreprocess then infile is the original input file, otherwise input_file
+ Setattr(top, "inputfile", input_file);
+
+ String *infile_filename = outcurrentdir ? Swig_file_filename(infile): Copy(infile);
+ String *basename = Swig_file_basename(infile_filename);
+ if (!outfile_name) {
+ if (CPlusPlus || lang->cplus_runtime_mode()) {
+ Setattr(top, "outfile", NewStringf("%s_wrap.%s", basename, cpp_extension));
+ } else {
+ Setattr(top, "outfile", NewStringf("%s_wrap.c", basename));
+ }
+ } else {
+ Setattr(top, "outfile", outfile_name);
+ }
+ if (!outfile_name_h) {
+ Setattr(top, "outfile_h", NewStringf("%s_wrap.%s", basename, hpp_extension));
+ } else {
+ Setattr(top, "outfile_h", outfile_name_h);
+ }
+ configure_outdir(Getattr(top, "outfile"));
+ if (Swig_contract_mode_get()) {
+ Swig_contracts(top);
+ }
+
+ // Check the extension for a c/c++ file. If so, we're going to declare everything we see as "extern"
+ ForceExtern = check_extension(input_file);
+
+ if (tlm->status == Experimental) {
+ Swig_warning(WARN_LANG_EXPERIMENTAL, "SWIG", 1, "Experimental target language. "
+ "Target language %s specified by %s is an experimental language. "
+ "Please read about SWIG experimental languages, http://swig.org/Doc4.0/Introduction.html#Introduction_experimental_status.\n",
+ tlm->help ? tlm->help : "", tlm->name);
+ }
+
+ lang->top(top);
+
+ if (browse) {
+ Swig_browser(top, 0);
+ }
+ Delete(infile_filename);
+ Delete(basename);
+ }
+ }
+ if (dump_lang_symbols) {
+ lang->dumpSymbols();
+ }
+ if (dump_top & STAGE4) {
+ Printf(stdout, "debug-top stage 4\n");
+ Swig_print_tree(top);
+ }
+ if (dump_module & STAGE4) {
+ Printf(stdout, "debug-module stage 4\n");
+ Swig_print_tree(Getattr(top, "module"));
+ }
+ if (dump_xml && top) {
+ delete lang;
+ lang = 0;
+ Swig_print_xml(top, xmlout);
+ }
+ Delete(top);
+ }
+ if (tm_debug)
+ Swig_typemap_debug();
+ if (memory_debug)
+ DohMemoryDebug();
+
+ char *outfiles = getenv("CCACHE_OUTFILES");
+ if (outfiles) {
+ File *f_outfiles = NewFile(outfiles, "w", 0);
+ if (!f_outfiles) {
+ Printf(stderr, "Failed to write list of output files to the filename '%s' specified in CCACHE_OUTFILES environment variable - ", outfiles);
+ FileErrorDisplay(outfiles);
+ SWIG_exit(EXIT_FAILURE);
+ } else {
+ int i;
+ for (i = 0; i < Len(all_output_files); i++)
+ Printf(f_outfiles, "%s\n", Getitem(all_output_files, i));
+ Delete(f_outfiles);
+ }
+ }
+
+ // Deletes
+ Delete(libfiles);
+ Preprocessor_delete();
+
+ while (freeze) {
+ }
+
+ delete lang;
+
+ int error_count = werror ? Swig_warn_count() : 0;
+ error_count += Swig_error_count();
+
+ if (error_count != 0)
+ SWIG_exit(error_count);
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * SWIG_exit()
+ *
+ * Cleanup and either freeze or exit
+ * ----------------------------------------------------------------------------- */
+
+void SWIG_exit(int exit_code) {
+ while (freeze) {
+ }
+
+ if (exit_code > 0) {
+ CloseAllOpenFiles();
+
+ /* Remove all generated files */
+ if (all_output_files) {
+ for (int i = 0; i < Len(all_output_files); i++) {
+ String *filename = Getitem(all_output_files, i);
+ int removed = remove(Char(filename));
+ if (removed == -1)
+ fprintf(stderr, "On exit, could not delete file %s: %s\n", Char(filename), strerror(errno));
+ }
+ }
+ }
+
+ exit(exit_code);
+}
diff --git a/contrib/tools/swig/Source/Modules/mzscheme.cxx b/contrib/tools/swig/Source/Modules/mzscheme.cxx
new file mode 100644
index 00000000000..788681330a9
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/mzscheme.cxx
@@ -0,0 +1,819 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * mzscheme.cxx
+ *
+ * Mzscheme language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+
+#include <ctype.h>
+
+static const char *usage = "\
+Mzscheme Options (available with -mzscheme)\n\
+ -declaremodule - Create extension that declares a module\n\
+ -dynamic-load <lib>,[lib,...] - Do not link with these libraries, dynamic load them\n\
+ -noinit - Do not emit module initialization code\n\
+ -prefix <name> - Set a prefix <name> to be prepended to all names\n\
+";
+
+static String *fieldnames_tab = 0;
+static String *convert_tab = 0;
+static String *convert_proto_tab = 0;
+static String *struct_name = 0;
+static String *mangled_struct_name = 0;
+
+static String *prefix = 0;
+static bool declaremodule = false;
+static bool noinit = false;
+static String *load_libraries = NULL;
+static String *module = 0;
+static const char *mzscheme_path = "mzscheme";
+static String *init_func_def = 0;
+
+static File *f_begin = 0;
+static File *f_runtime = 0;
+static File *f_header = 0;
+static File *f_wrappers = 0;
+static File *f_init = 0;
+
+// Used for garbage collection
+static int exporting_destructor = 0;
+static String *swigtype_ptr = 0;
+static String *cls_swigtype = 0;
+
+class MZSCHEME:public Language {
+public:
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+
+ int i;
+
+ SWIG_library_directory(mzscheme_path);
+
+ // Look for certain command line options
+ for (i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ SWIG_exit(0);
+ } else if (strcmp(argv[i], "-prefix") == 0) {
+ if (argv[i + 1]) {
+ prefix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-declaremodule") == 0) {
+ declaremodule = true;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-noinit") == 0) {
+ noinit = true;
+ Swig_mark_arg(i);
+ }
+ else if (strcmp(argv[i], "-dynamic-load") == 0) {
+ if (argv[i + 1]) {
+ Delete(load_libraries);
+ load_libraries = NewString(argv[i + 1]);
+ Swig_mark_arg(i++);
+ Swig_mark_arg(i);
+ } else {
+ Swig_arg_error();
+ }
+ }
+ }
+ }
+
+ // If a prefix has been specified make sure it ends in a '_' (not actually used!)
+ if (prefix) {
+ const char *px = Char(prefix);
+ if (px[Len(prefix) - 1] != '_')
+ Printf(prefix, "_");
+ } else
+ prefix = NewString("swig_");
+
+ // Add a symbol for this module
+
+ Preprocessor_define("SWIGMZSCHEME 1", 0);
+
+ // Set name of typemaps
+
+ SWIG_typemap_lang("mzscheme");
+
+ // Read in default typemaps */
+ SWIG_config_file("mzscheme.swg");
+ allow_overloading();
+
+ }
+
+ /* ------------------------------------------------------------
+ * top()
+ * ------------------------------------------------------------ */
+
+ virtual int top(Node *n) {
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+
+ init_func_def = NewString("");
+ Swig_register_filebyname("init", init_func_def);
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n\n#ifndef SWIGMZSCHEME\n#define SWIGMZSCHEME\n#endif\n\n");
+
+ module = Getattr(n, "name");
+
+ Language::top(n);
+
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+ if (!noinit) {
+ if (declaremodule) {
+ Printf(f_init, "#define SWIG_MZSCHEME_CREATE_MENV(env) scheme_primitive_module(scheme_intern_symbol(\"%s\"), env)\n", module);
+ } else {
+ Printf(f_init, "#define SWIG_MZSCHEME_CREATE_MENV(env) (env)\n");
+ }
+ Printf(f_init, "%s\n", Char(init_func_def));
+ if (declaremodule) {
+ Printf(f_init, "\tscheme_finish_primitive_module(menv);\n");
+ }
+ Printf(f_init, "\treturn scheme_void;\n}\n");
+ Printf(f_init, "Scheme_Object *scheme_initialize(Scheme_Env *env) {\n");
+
+ if (load_libraries) {
+ Printf(f_init, "mz_set_dlopen_libraries(\"%s\");\n", load_libraries);
+ }
+
+ Printf(f_init, "\treturn scheme_reload(env);\n");
+ Printf(f_init, "}\n");
+
+ Printf(f_init, "Scheme_Object *scheme_module_name(void) {\n");
+ if (declaremodule) {
+ Printf(f_init, " return scheme_intern_symbol((char*)\"%s\");\n", module);
+ } else {
+ Printf(f_init, " return scheme_make_symbol((char*)\"%s\");\n", module);
+ }
+ Printf(f_init, "}\n");
+ }
+
+ /* Close all of the files */
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+ Dump(f_wrappers, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_runtime);
+ Delete(f_begin);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * functionWrapper()
+ * Create a function declaration and register it with the interpreter.
+ * ------------------------------------------------------------ */
+
+ void throw_unhandled_mzscheme_type_error(SwigType *d) {
+ Swig_warning(WARN_TYPEMAP_UNDEF, input_file, line_number, "Unable to handle type %s.\n", SwigType_str(d, 0));
+ }
+
+ /* Return true iff T is a pointer type */
+
+ int
+ is_a_pointer(SwigType *t) {
+ return SwigType_ispointer(SwigType_typedef_resolve_all(t));
+ }
+
+ virtual int functionWrapper(Node *n) {
+ char *iname = GetChar(n, "sym:name");
+ SwigType *d = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ Parm *p;
+
+ Wrapper *f = NewWrapper();
+ String *proc_name = NewString("");
+ String *target = NewString("");
+ String *arg = NewString("");
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ String *build = NewString("");
+ String *tm;
+ int i = 0;
+ int numargs;
+ int numreq;
+ String *overname = 0;
+
+ if (load_libraries) {
+ ParmList *parms = Getattr(n, "parms");
+ SwigType *type = Getattr(n, "type");
+ String *name = NewString("caller");
+ Setattr(n, "wrap:action", Swig_cresult(type, Swig_cresult_name(), Swig_cfunction_call(name, parms)));
+ }
+
+ // Make a wrapper name for this
+ String *wname = Swig_name_wrapper(iname);
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n)) {
+ DelWrapper(f);
+ return SWIG_ERROR;
+ }
+ }
+ if (overname) {
+ Append(wname, overname);
+ }
+ Setattr(n, "wrap:name", wname);
+
+ // Build the name for Scheme.
+ Printv(proc_name, iname, NIL);
+ Replaceall(proc_name, "_", "-");
+
+ // writing the function wrapper function
+ Printv(f->def, "static Scheme_Object *", wname, " (", NIL);
+ Printv(f->def, "int argc, Scheme_Object **argv", NIL);
+ Printv(f->def, ")\n{", NIL);
+
+ /* Define the scheme name in C. This define is used by several
+ macros. */
+ Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL);
+
+ // Emit all of the local variables for holding arguments.
+ emit_parameter_variables(l, f);
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+ Setattr(n, "wrap:parms", l);
+
+ numargs = emit_num_arguments(l);
+ numreq = emit_num_required(l);
+
+ /* Add the holder for the pointer to the function to be opened */
+ if (load_libraries) {
+ Wrapper_add_local(f, "_function_loaded", "static int _function_loaded=(1==0)");
+ Wrapper_add_local(f, "_the_function", "static void *_the_function=NULL");
+ {
+ String *parms = ParmList_protostr(l);
+ String *func = NewStringf("(*caller)(%s)", parms);
+ Wrapper_add_local(f, "caller", SwigType_lstr(d, func)); /*"(*caller)()")); */
+ }
+ }
+
+ // adds local variables
+ Wrapper_add_local(f, "lenv", "int lenv = 1");
+ Wrapper_add_local(f, "values", "Scheme_Object *values[MAXVALUES]");
+
+ if (load_libraries) {
+ Printf(f->code, "if (!_function_loaded) { _the_function=mz_load_function(\"%s\");_function_loaded=(1==1); }\n", iname);
+ Printf(f->code, "if (!_the_function) { scheme_signal_error(\"Cannot load C function '%s'\"); }\n", iname);
+ Printf(f->code, "caller=_the_function;\n");
+ }
+
+ // Now write code to extract the parameters (this is super ugly)
+
+ for (i = 0, p = l; i < numargs; i++) {
+ /* Skip ignored arguments */
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+
+ // Produce names of source and target
+ Clear(target);
+ Clear(arg);
+ String *source = NewStringf("argv[%d]", i);
+ Printf(target, "%s", ln);
+ Printv(arg, Getattr(p, "name"), NIL);
+
+ if (i >= numreq) {
+ Printf(f->code, "if (argc > %d) {\n", i);
+ }
+ // Handle parameter types.
+ if ((tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$source", source);
+ Replaceall(tm, "$target", target);
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source);
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ // no typemap found
+ // check if typedef and resolve
+ throw_unhandled_mzscheme_type_error(pt);
+ p = nextSibling(p);
+ }
+ if (i >= numreq) {
+ Printf(f->code, "}\n");
+ }
+ Delete(source);
+ }
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Pass output arguments back to the caller.
+
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ Replaceall(tm, "$source", Getattr(p, "emit:input")); /* Deprecated */
+ Replaceall(tm, "$target", Getattr(p, "lname")); /* Deprecated */
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Free up any memory allocated for the arguments.
+
+ /* Insert cleanup code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Now write code to make the function call
+
+ String *actioncode = emit_action(n);
+
+ // Now have return value, figure out what to do with it.
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Replaceall(tm, "$target", "values[0]");
+ Replaceall(tm, "$result", "values[0]");
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "1");
+ else
+ Replaceall(tm, "$owner", "0");
+ Printv(f->code, tm, "\n", NIL);
+ } else {
+ throw_unhandled_mzscheme_type_error(d);
+ }
+ emit_return_variable(n, d, f);
+
+ // Dump the argument output code
+ Printv(f->code, Char(outarg), NIL);
+
+ // Dump the argument cleanup code
+ Printv(f->code, Char(cleanup), NIL);
+
+ // Look for any remaining cleanup
+
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printv(f->code, tm, "\n", NIL);
+ }
+ }
+ // Free any memory allocated by the function being wrapped..
+
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printv(f->code, tm, "\n", NIL);
+ }
+ // Wrap things up (in a manner of speaking)
+
+ Printv(f->code, tab4, "return SWIG_MzScheme_PackageValues(lenv, values);\n", NIL);
+ Printf(f->code, "#undef FUNC_NAME\n");
+ Printv(f->code, "}\n", NIL);
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", iname);
+
+ Wrapper_print(f, f_wrappers);
+
+ if (!Getattr(n, "sym:overloaded")) {
+
+ // Now register the function
+ char temp[256];
+ sprintf(temp, "%d", numargs);
+ if (exporting_destructor) {
+ Printf(init_func_def, "SWIG_TypeClientData(SWIGTYPE%s, (void *) %s);\n", swigtype_ptr, wname);
+ }
+ Printf(init_func_def, "scheme_add_global(\"%s\", scheme_make_prim_w_arity(%s,\"%s\",%d,%d),menv);\n", proc_name, wname, proc_name, numreq, numargs);
+ } else {
+ if (!Getattr(n, "sym:nextSibling")) {
+ /* Emit overloading dispatch function */
+
+ int maxargs;
+ String *dispatch = Swig_overload_dispatch(n, "return %s(argc,argv);", &maxargs);
+
+ /* Generate a dispatch wrapper for all overloaded functions */
+
+ Wrapper *df = NewWrapper();
+ String *dname = Swig_name_wrapper(iname);
+
+ Printv(df->def, "static Scheme_Object *\n", dname, "(int argc, Scheme_Object **argv) {", NIL);
+ Printv(df->code, dispatch, "\n", NIL);
+ Printf(df->code, "scheme_signal_error(\"No matching function for overloaded '%s'\");\n", iname);
+ Printf(df->code, "return NULL;\n", iname);
+ Printv(df->code, "}\n", NIL);
+ Wrapper_print(df, f_wrappers);
+ Printf(init_func_def, "scheme_add_global(\"%s\", scheme_make_prim_w_arity(%s,\"%s\",%d,%d),menv);\n", proc_name, dname, proc_name, 0, maxargs);
+ DelWrapper(df);
+ Delete(dispatch);
+ Delete(dname);
+ }
+ }
+
+ Delete(proc_name);
+ Delete(target);
+ Delete(arg);
+ Delete(outarg);
+ Delete(cleanup);
+ Delete(build);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * variableWrapper()
+ *
+ * Create a link to a C variable.
+ * This creates a single function _wrap_swig_var_varname().
+ * This function takes a single optional argument. If supplied, it means
+ * we are setting this variable to some value. If omitted, it means we are
+ * simply evaluating this variable. Either way, we return the variables
+ * value.
+ * ------------------------------------------------------------ */
+
+ virtual int variableWrapper(Node *n) {
+
+ char *name = GetChar(n, "name");
+ char *iname = GetChar(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+
+ String *proc_name = NewString("");
+ String *tm;
+ String *tm2 = NewString("");
+ String *argnum = NewString("0");
+ String *arg = NewString("argv[0]");
+ Wrapper *f;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ f = NewWrapper();
+
+ // evaluation function names
+ String *var_name = Swig_name_wrapper(iname);
+
+ // Build the name for scheme.
+ Printv(proc_name, iname, NIL);
+ Replaceall(proc_name, "_", "-");
+ Setattr(n, "wrap:name", proc_name);
+
+ if ((SwigType_type(t) != T_USER) || (is_a_pointer(t))) {
+
+ Printf(f->def, "static Scheme_Object *%s(int argc, Scheme_Object** argv) {\n", var_name);
+ Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL);
+
+ Wrapper_add_local(f, "swig_result", "Scheme_Object *swig_result");
+
+ if (!GetFlag(n, "feature:immutable")) {
+ /* Check for a setting of the variable value */
+ Printf(f->code, "if (argc) {\n");
+ if ((tm = Swig_typemap_lookup("varin", n, name, 0))) {
+ Replaceall(tm, "$source", "argv[0]");
+ Replaceall(tm, "$target", name);
+ Replaceall(tm, "$input", "argv[0]");
+ Replaceall(tm, "$argnum", "1");
+ emit_action_code(n, f->code, tm);
+ } else {
+ throw_unhandled_mzscheme_type_error(t);
+ }
+ Printf(f->code, "}\n");
+ }
+ // Now return the value of the variable (regardless
+ // of evaluating or setting)
+
+ if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
+ Replaceall(tm, "$source", name);
+ Replaceall(tm, "$target", "swig_result");
+ Replaceall(tm, "$result", "swig_result");
+ /* Printf (f->code, "%s\n", tm); */
+ emit_action_code(n, f->code, tm);
+ } else {
+ throw_unhandled_mzscheme_type_error(t);
+ }
+ Printf(f->code, "\nreturn swig_result;\n");
+ Printf(f->code, "#undef FUNC_NAME\n");
+ Printf(f->code, "}\n");
+
+ Wrapper_print(f, f_wrappers);
+
+ // Now add symbol to the MzScheme interpreter
+
+ Printv(init_func_def,
+ "scheme_add_global(\"", proc_name, "\", scheme_make_prim_w_arity(", var_name, ", \"", proc_name, "\", ", "0", ", ", "1", "), menv);\n", NIL);
+
+ } else {
+ Swig_warning(WARN_TYPEMAP_VAR_UNDEF, input_file, line_number, "Unsupported variable type %s (ignored).\n", SwigType_str(t, 0));
+ }
+ Delete(var_name);
+ Delete(proc_name);
+ Delete(argnum);
+ Delete(arg);
+ Delete(tm2);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ char *name = GetChar(n, "name");
+ char *iname = GetChar(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+
+ String *var_name = NewString("");
+ String *proc_name = NewString("");
+ String *rvalue = NewString("");
+ String *temp = NewString("");
+ String *tm;
+
+ // Make a static variable;
+
+ Printf(var_name, "_wrap_const_%s", Swig_name_mangle(Getattr(n, "sym:name")));
+
+ // Build the name for scheme.
+ Printv(proc_name, iname, NIL);
+ Replaceall(proc_name, "_", "-");
+
+ if ((SwigType_type(type) == T_USER) && (!is_a_pointer(type))) {
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
+ return SWIG_NOWRAP;
+ }
+ // See if there's a typemap
+
+ Printv(rvalue, value, NIL);
+ if ((SwigType_type(type) == T_CHAR) && (is_a_pointer(type) == 1)) {
+ temp = Copy(rvalue);
+ Clear(rvalue);
+ Printv(rvalue, "\"", temp, "\"", NIL);
+ }
+ if ((SwigType_type(type) == T_CHAR) && (is_a_pointer(type) == 0)) {
+ Delete(temp);
+ temp = Copy(rvalue);
+ Clear(rvalue);
+ Printv(rvalue, "'", temp, "'", NIL);
+ }
+ if ((tm = Swig_typemap_lookup("constant", n, name, 0))) {
+ Replaceall(tm, "$source", rvalue);
+ Replaceall(tm, "$value", rvalue);
+ Replaceall(tm, "$target", name);
+ Printf(f_init, "%s\n", tm);
+ } else {
+ // Create variable and assign it a value
+
+ Printf(f_header, "static %s = ", SwigType_lstr(type, var_name));
+ bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
+ if ((SwigType_type(type) == T_STRING)) {
+ Printf(f_header, "\"%s\";\n", value);
+ } else if (SwigType_type(type) == T_CHAR && !is_enum_item) {
+ Printf(f_header, "\'%s\';\n", value);
+ } else {
+ Printf(f_header, "%s;\n", value);
+ }
+
+ // Now create a variable declaration
+
+ {
+ /* Hack alert: will cleanup later -- Dave */
+ Node *nn = NewHash();
+ Setfile(nn, Getfile(n));
+ Setline(nn, Getline(n));
+ Setattr(nn, "name", var_name);
+ Setattr(nn, "sym:name", iname);
+ Setattr(nn, "type", type);
+ SetFlag(nn, "feature:immutable");
+ variableWrapper(nn);
+ Delete(nn);
+ }
+ }
+ Delete(proc_name);
+ Delete(rvalue);
+ Delete(temp);
+ return SWIG_OK;
+ }
+
+ virtual int destructorHandler(Node *n) {
+ exporting_destructor = true;
+ Language::destructorHandler(n);
+ exporting_destructor = false;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ * ------------------------------------------------------------ */
+ virtual int classHandler(Node *n) {
+ String *mangled_classname = 0;
+ String *real_classname = 0;
+ String *scm_structname = NewString("");
+ SwigType *ctype_ptr = NewStringf("p.%s", getClassType());
+
+ SwigType *t = NewStringf("p.%s", Getattr(n, "name"));
+ swigtype_ptr = SwigType_manglestr(t);
+ Delete(t);
+
+ cls_swigtype = SwigType_manglestr(Getattr(n, "name"));
+
+
+ fieldnames_tab = NewString("");
+ convert_tab = NewString("");
+ convert_proto_tab = NewString("");
+
+ struct_name = Getattr(n, "sym:name");
+ mangled_struct_name = Swig_name_mangle(Getattr(n, "sym:name"));
+
+ Printv(scm_structname, struct_name, NIL);
+ Replaceall(scm_structname, "_", "-");
+
+ real_classname = Getattr(n, "name");
+ mangled_classname = Swig_name_mangle(real_classname);
+
+ Printv(fieldnames_tab, "static const char *_swig_struct_", cls_swigtype, "_field_names[] = { \n", NIL);
+
+ Printv(convert_proto_tab, "static Scheme_Object *_swig_convert_struct_", cls_swigtype, "(", SwigType_str(ctype_ptr, "ptr"), ");\n", NIL);
+
+ Printv(convert_tab, "static Scheme_Object *_swig_convert_struct_", cls_swigtype, "(", SwigType_str(ctype_ptr, "ptr"), ")\n {\n", NIL);
+
+ Printv(convert_tab,
+ tab4, "Scheme_Object *obj;\n", tab4, "Scheme_Object *fields[_swig_struct_", cls_swigtype, "_field_names_cnt];\n", tab4, "int i = 0;\n\n", NIL);
+
+ /* Generate normal wrappers */
+ Language::classHandler(n);
+
+ Printv(convert_tab, tab4, "obj = scheme_make_struct_instance(", "_swig_struct_type_", cls_swigtype, ", i, fields);\n", NIL);
+ Printv(convert_tab, tab4, "return obj;\n}\n\n", NIL);
+
+ Printv(fieldnames_tab, "};\n", NIL);
+
+ Printv(f_header, "static Scheme_Object *_swig_struct_type_", cls_swigtype, ";\n", NIL);
+
+ Printv(f_header, fieldnames_tab, NIL);
+ Printv(f_header, "#define _swig_struct_", cls_swigtype, "_field_names_cnt (sizeof(_swig_struct_", cls_swigtype, "_field_names)/sizeof(char*))\n", NIL);
+
+ Printv(f_header, convert_proto_tab, NIL);
+ Printv(f_wrappers, convert_tab, NIL);
+
+ Printv(init_func_def, "_swig_struct_type_", cls_swigtype,
+ " = SWIG_MzScheme_new_scheme_struct(menv, \"", scm_structname, "\", ",
+ "_swig_struct_", cls_swigtype, "_field_names_cnt,", "(char**) _swig_struct_", cls_swigtype, "_field_names);\n", NIL);
+
+ Delete(mangled_classname);
+ Delete(swigtype_ptr);
+ swigtype_ptr = 0;
+ Delete(fieldnames_tab);
+ Delete(convert_tab);
+ Delete(ctype_ptr);
+ Delete(convert_proto_tab);
+ struct_name = 0;
+ mangled_struct_name = 0;
+ Delete(cls_swigtype);
+ cls_swigtype = 0;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * membervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int membervariableHandler(Node *n) {
+ Language::membervariableHandler(n);
+
+ if (!is_smart_pointer()) {
+ String *symname = Getattr(n, "sym:name");
+ String *name = Getattr(n, "name");
+ SwigType *type = Getattr(n, "type");
+ String *swigtype = SwigType_manglestr(Getattr(n, "type"));
+ String *tm = 0;
+ String *access_mem = NewString("");
+ SwigType *ctype_ptr = NewStringf("p.%s", Getattr(n, "type"));
+
+ Printv(fieldnames_tab, tab4, "\"", symname, "\",\n", NIL);
+ Printv(access_mem, "(ptr)->", name, NIL);
+ if ((SwigType_type(type) == T_USER) && (!is_a_pointer(type))) {
+ Printv(convert_tab, tab4, "fields[i++] = ", NIL);
+ Printv(convert_tab, "_swig_convert_struct_", swigtype, "((", SwigType_str(ctype_ptr, 0), ")&((ptr)->", name, "));\n", NIL);
+ } else if ((tm = Swig_typemap_lookup("varout", n, access_mem, 0))) {
+ Replaceall(tm, "$result", "fields[i++]");
+ Printv(convert_tab, tm, "\n", NIL);
+ } else
+ Swig_warning(WARN_TYPEMAP_VAR_UNDEF, input_file, line_number, "Unsupported member variable type %s (ignored).\n", SwigType_str(type, 0));
+
+ Delete(access_mem);
+ }
+ return SWIG_OK;
+ }
+
+
+ /* ------------------------------------------------------------
+ * validIdentifier()
+ * ------------------------------------------------------------ */
+
+ virtual int validIdentifier(String *s) {
+ char *c = Char(s);
+ /* Check whether we have an R5RS identifier. */
+ /* <identifier> --> <initial> <subsequent>* | <peculiar identifier> */
+ /* <initial> --> <letter> | <special initial> */
+ if (!(isalpha(*c) || (*c == '!') || (*c == '$') || (*c == '%')
+ || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':')
+ || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?')
+ || (*c == '^') || (*c == '_') || (*c == '~'))) {
+ /* <peculiar identifier> --> + | - | ... */
+ if ((strcmp(c, "+") == 0)
+ || strcmp(c, "-") == 0 || strcmp(c, "...") == 0)
+ return 1;
+ else
+ return 0;
+ }
+ /* <subsequent> --> <initial> | <digit> | <special subsequent> */
+ while (*c) {
+ if (!(isalnum(*c) || (*c == '!') || (*c == '$') || (*c == '%')
+ || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':')
+ || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?')
+ || (*c == '^') || (*c == '_') || (*c == '~') || (*c == '+')
+ || (*c == '-') || (*c == '.') || (*c == '@')))
+ return 0;
+ c++;
+ }
+ return 1;
+ }
+
+ String *runtimeCode() {
+ String *s = Swig_include_sys("mzrun.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'mzrun.swg'\n");
+ s = NewString("");
+ }
+ return s;
+ }
+
+ String *defaultExternalRuntimeFilename() {
+ return NewString("swigmzrun.h");
+ }
+};
+
+/* -----------------------------------------------------------------------------
+ * swig_mzscheme() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_mzscheme() {
+ return new MZSCHEME();
+}
+extern "C" Language *swig_mzscheme(void) {
+ return new_swig_mzscheme();
+}
diff --git a/contrib/tools/swig/Source/Modules/nested.cxx b/contrib/tools/swig/Source/Modules/nested.cxx
new file mode 100644
index 00000000000..0fcd5ad1820
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/nested.cxx
@@ -0,0 +1,453 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * nested.cxx
+ *
+ * Nested structs support
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+
+// Nested classes processing section
+static Hash *classhash = 0;
+
+static String *make_name(Node *n, String *name, SwigType *decl) {
+ int destructor = name && (*(Char(name)) == '~');
+ if (String *yyrename = Getattr(n, "class_rename")) {
+ String *s = NewString(yyrename);
+ Delattr(n, "class_rename");
+ if (destructor && (*(Char(s)) != '~')) {
+ Insert(s, 0, "~");
+ }
+ return s;
+ }
+
+ if (!name)
+ return 0;
+ return Swig_name_make(n, 0, name, decl, 0);
+}
+
+// C version of add_symbols()
+static void add_symbols_c(Node *n) {
+ String *decl;
+ String *wrn = 0;
+ String *symname = 0;
+ int iscdecl = Cmp(nodeType(n), "cdecl") == 0;
+ Setattr(n, "ismember", "1");
+ Setattr(n, "access", "public");
+ if (Getattr(n, "sym:name"))
+ return;
+ decl = Getattr(n, "decl");
+ if (!SwigType_isfunction(decl)) {
+ String *name = Getattr(n, "name");
+ String *makename = Getattr(n, "parser:makename");
+ if (iscdecl) {
+ String *storage = Getattr(n, "storage");
+ if (Cmp(storage, "typedef") == 0) {
+ Setattr(n, "kind", "typedef");
+ } else {
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ Setattr(n, "kind", "variable");
+ if (value && Len(value)) {
+ Setattr(n, "hasvalue", "1");
+ }
+ if (type) {
+ SwigType *ty;
+ SwigType *tmp = 0;
+ if (decl) {
+ ty = tmp = Copy(type);
+ SwigType_push(ty, decl);
+ } else {
+ ty = type;
+ }
+ if (!SwigType_ismutable(ty)) {
+ SetFlag(n, "hasconsttype");
+ SetFlag(n, "feature:immutable");
+ }
+ if (tmp)
+ Delete(tmp);
+ }
+ if (!type) {
+ Printf(stderr, "notype name %s\n", name);
+ }
+ }
+ }
+ Swig_features_get(Swig_cparse_features(), 0, name, 0, n);
+ if (makename) {
+ symname = make_name(n, makename, 0);
+ Delattr(n, "parser:makename"); /* temporary information, don't leave it hanging around */
+ } else {
+ makename = name;
+ symname = make_name(n, makename, 0);
+ }
+
+ if (!symname) {
+ symname = Copy(Getattr(n, "unnamed"));
+ }
+ if (symname) {
+ wrn = Swig_name_warning(n, 0, symname, 0);
+ }
+ } else {
+ String *name = Getattr(n, "name");
+ SwigType *fdecl = Copy(decl);
+ SwigType *fun = SwigType_pop_function(fdecl);
+ if (iscdecl) {
+ Setattr(n, "kind", "function");
+ }
+
+ Swig_features_get(Swig_cparse_features(), 0, name, fun, n);
+
+ symname = make_name(n, name, fun);
+ wrn = Swig_name_warning(n, 0, symname, fun);
+
+ Delete(fdecl);
+ Delete(fun);
+
+ }
+ if (!symname)
+ return;
+ if (GetFlag(n, "feature:ignore")) {
+ /* Only add to C symbol table and continue */
+ Swig_symbol_add(0, n);
+ } else if (strncmp(Char(symname), "$ignore", 7) == 0) {
+ char *c = Char(symname) + 7;
+ SetFlag(n, "feature:ignore");
+ if (strlen(c)) {
+ SWIG_WARN_NODE_BEGIN(n);
+ Swig_warning(0, Getfile(n), Getline(n), "%s\n", c + 1);
+ SWIG_WARN_NODE_END(n);
+ }
+ Swig_symbol_add(0, n);
+ } else {
+ Node *c;
+ if ((wrn) && (Len(wrn))) {
+ String *metaname = symname;
+ if (!Getmeta(metaname, "already_warned")) {
+ SWIG_WARN_NODE_BEGIN(n);
+ Swig_warning(0, Getfile(n), Getline(n), "%s\n", wrn);
+ SWIG_WARN_NODE_END(n);
+ Setmeta(metaname, "already_warned", "1");
+ }
+ }
+ c = Swig_symbol_add(symname, n);
+
+ if (c != n) {
+ /* symbol conflict attempting to add in the new symbol */
+ if (Getattr(n, "sym:weak")) {
+ Setattr(n, "sym:name", symname);
+ } else {
+ String *e = NewStringEmpty();
+ String *en = NewStringEmpty();
+ String *ec = NewStringEmpty();
+ int redefined = Swig_need_redefined_warn(n, c, true);
+ if (redefined) {
+ Printf(en, "Identifier '%s' redefined (ignored)", symname);
+ Printf(ec, "previous definition of '%s'", symname);
+ } else {
+ Printf(en, "Redundant redeclaration of '%s'", symname);
+ Printf(ec, "previous declaration of '%s'", symname);
+ }
+ if (Cmp(symname, Getattr(n, "name"))) {
+ Printf(en, " (Renamed from '%s')", SwigType_namestr(Getattr(n, "name")));
+ }
+ Printf(en, ",");
+ if (Cmp(symname, Getattr(c, "name"))) {
+ Printf(ec, " (Renamed from '%s')", SwigType_namestr(Getattr(c, "name")));
+ }
+ Printf(ec, ".");
+ SWIG_WARN_NODE_BEGIN(n);
+ if (redefined) {
+ Swig_warning(WARN_PARSE_REDEFINED, Getfile(n), Getline(n), "%s\n", en);
+ Swig_warning(WARN_PARSE_REDEFINED, Getfile(c), Getline(c), "%s\n", ec);
+ } else {
+ Swig_warning(WARN_PARSE_REDUNDANT, Getfile(n), Getline(n), "%s\n", en);
+ Swig_warning(WARN_PARSE_REDUNDANT, Getfile(c), Getline(c), "%s\n", ec);
+ }
+ SWIG_WARN_NODE_END(n);
+ Printf(e, "%s:%d:%s\n%s:%d:%s\n", Getfile(n), Getline(n), en, Getfile(c), Getline(c), ec);
+ Setattr(n, "error", e);
+ Delete(e);
+ Delete(en);
+ Delete(ec);
+ }
+ }
+ }
+ Delete(symname);
+}
+
+/* Strips C-style and C++-style comments from string in-place. */
+static void strip_comments(char *string) {
+ int state = 0;
+ /*
+ * 0 - not in comment
+ * 1 - in c-style comment
+ * 2 - in c++-style comment
+ * 3 - in string
+ * 4 - after reading / not in comments
+ * 5 - after reading * in c-style comments
+ * 6 - after reading \ in strings
+ */
+ char *c = string;
+ while (*c) {
+ switch (state) {
+ case 0:
+ if (*c == '\"')
+ state = 3;
+ else if (*c == '/')
+ state = 4;
+ break;
+ case 1:
+ if (*c == '*')
+ state = 5;
+ *c = ' ';
+ break;
+ case 2:
+ if (*c == '\n')
+ state = 0;
+ else
+ *c = ' ';
+ break;
+ case 3:
+ if (*c == '\"')
+ state = 0;
+ else if (*c == '\\')
+ state = 6;
+ break;
+ case 4:
+ if (*c == '/') {
+ *(c - 1) = ' ';
+ *c = ' ';
+ state = 2;
+ } else if (*c == '*') {
+ *(c - 1) = ' ';
+ *c = ' ';
+ state = 1;
+ } else
+ state = 0;
+ break;
+ case 5:
+ if (*c == '/')
+ state = 0;
+ else
+ state = 1;
+ *c = ' ';
+ break;
+ case 6:
+ state = 3;
+ break;
+ }
+ ++c;
+ }
+}
+
+// Create a %insert with a typedef to make a new name visible to C
+static Node *create_insert(Node *n, bool noTypedef = false) {
+ // format a typedef
+ String *ccode = Getattr(n, "code");
+ Push(ccode, " ");
+ if (noTypedef) {
+ Push(ccode, Getattr(n, "name"));
+ Push(ccode, " ");
+ Push(ccode, Getattr(n, "kind"));
+ } else {
+ Push(ccode, Getattr(n, "kind"));
+ Push(ccode, "typedef ");
+ Append(ccode, " ");
+ Append(ccode, Getattr(n, "tdname"));
+ }
+ Append(ccode, ";");
+
+ /* Strip comments - further code may break in presence of comments. */
+ strip_comments(Char(ccode));
+
+ /* Make all SWIG created typedef structs/unions/classes unnamed else
+ redefinition errors occur - nasty hack alert. */
+ if (!noTypedef) {
+ const char *types_array[3] = { "struct", "union", "class" };
+ for (int i = 0; i < 3; i++) {
+ char *code_ptr = Char(ccode);
+ while (code_ptr) {
+ /* Replace struct name (as in 'struct name {...}' ) with whitespace
+ name will be between struct and opening brace */
+
+ code_ptr = strstr(code_ptr, types_array[i]);
+ if (code_ptr) {
+ char *open_bracket_pos;
+ code_ptr += strlen(types_array[i]);
+ open_bracket_pos = strchr(code_ptr, '{');
+ if (open_bracket_pos) {
+ /* Make sure we don't have something like struct A a; */
+ char *semi_colon_pos = strchr(code_ptr, ';');
+ if (!(semi_colon_pos && (semi_colon_pos < open_bracket_pos)))
+ while (code_ptr < open_bracket_pos)
+ *code_ptr++ = ' ';
+ }
+ }
+ }
+ }
+ }
+ {
+ /* Remove SWIG directive %constant which may be left in the SWIG created typedefs */
+ char *code_ptr = Char(ccode);
+ while (code_ptr) {
+ code_ptr = strstr(code_ptr, "%constant");
+ if (code_ptr) {
+ char *directive_end_pos = strchr(code_ptr, ';');
+ if (directive_end_pos) {
+ while (code_ptr <= directive_end_pos)
+ *code_ptr++ = ' ';
+ }
+ }
+ }
+ }
+ Node *newnode = NewHash();
+ set_nodeType(newnode, "insert");
+ Setfile(newnode, Getfile(n));
+ Setline(newnode, Getline(n));
+ String *code = NewStringEmpty();
+ Wrapper_pretty_print(ccode, code);
+ Setattr(newnode, "code", code);
+ Delete(code);
+ Delattr(n, "code");
+ return newnode;
+}
+
+static void insertNodeAfter(Node *n, Node *c) {
+ Node *g = parentNode(n);
+ set_parentNode(c, g);
+ Node *ns = nextSibling(n);
+ if (Node *outer = Getattr(c, "nested:outer")) {
+ while (ns && outer == Getattr(ns, "nested:outer")) {
+ n = ns;
+ ns = nextSibling(n);
+ }
+ }
+ if (!ns) {
+ set_lastChild(g, c);
+ } else {
+ set_nextSibling(c, ns);
+ set_previousSibling(ns, c);
+ }
+ set_nextSibling(n, c);
+ set_previousSibling(c, n);
+}
+
+void Swig_nested_name_unnamed_c_structs(Node *n) {
+ if (!n)
+ return;
+ if (!classhash)
+ classhash = Getattr(n, "classes");
+ Node *c = firstChild(n);
+ while (c) {
+ Node *next = nextSibling(c);
+ if (String *declName = Getattr(c, "nested:unnamed")) {
+ if (Node *outer = Getattr(c, "nested:outer")) {
+ // generate a name
+ String *name = NewStringf("%s_%s", Getattr(outer, "name"), declName);
+ Delattr(c, "nested:unnamed");
+ // set the name to the class and symbol table
+ Setattr(c, "tdname", name);
+ Setattr(c, "name", name);
+ Swig_symbol_setscope(Getattr(c, "symtab"));
+ Swig_symbol_setscopename(name);
+ // now that we have a name - gather base symbols
+ if (List *publicBases = Getattr(c, "baselist")) {
+ List *bases = Swig_make_inherit_list(name, publicBases, 0);
+ Swig_inherit_base_symbols(bases);
+ Delete(bases);
+ }
+ Setattr(classhash, name, c);
+
+ // Merge the extension into the symbol table
+ if (Node *am = Getattr(Swig_extend_hash(), name)) {
+ Swig_extend_merge(c, am);
+ Swig_extend_append_previous(c, am);
+ Delattr(Swig_extend_hash(), name);
+ }
+ Swig_symbol_popscope();
+
+ // process declarations following this type (assign correct new type)
+ SwigType *ty = Copy(name);
+ Node *decl = nextSibling(c);
+ List *declList = NewList();
+ while (decl && Getattr(decl, "nested:unnamedtype") == c) {
+ Setattr(decl, "type", ty);
+ Append(declList, decl);
+ Delattr(decl, "nested:unnamedtype");
+ SetFlag(decl, "feature:immutable");
+ add_symbols_c(decl);
+ decl = nextSibling(decl);
+ }
+ Delete(ty);
+ Swig_symbol_setscope(Swig_symbol_global_scope());
+ add_symbols_c(c);
+
+ Node *ins = create_insert(c);
+ insertNodeAfter(c, ins);
+ removeNode(c);
+ insertNodeAfter(n, c);
+ Delete(ins);
+ Delattr(c, "nested:outer");
+ } else {
+ // global unnamed struct - ignore it and it's instances
+ SetFlag(c, "feature:ignore");
+ while (next && Getattr(next, "nested:unnamedtype") == c) {
+ SetFlag(next, "feature:ignore");
+ next = nextSibling(next);
+ }
+ c = next;
+ continue;
+ }
+ } else if (cparse_cplusplusout) {
+ if (Getattr(c, "nested:outer")) {
+ Node *ins = create_insert(c, true);
+ insertNodeAfter(c, ins);
+ Delete(ins);
+ Delattr(c, "nested:outer");
+ }
+ }
+ // process children
+ Swig_nested_name_unnamed_c_structs(c);
+ c = next;
+ }
+}
+
+static void remove_outer_class_reference(Node *n) {
+ for (Node *c = firstChild(n); c; c = nextSibling(c)) {
+ if (GetFlag(c, "feature:flatnested") || Language::instance()->nestedClassesSupport() == Language::NCS_None) {
+ Delattr(c, "nested:outer");
+ remove_outer_class_reference(c);
+ }
+ }
+}
+
+void Swig_nested_process_classes(Node *n) {
+ if (!n)
+ return;
+ Node *c = firstChild(n);
+ while (c) {
+ Node *next = nextSibling(c);
+ if (!Getattr(c, "templatetype")) {
+ if (GetFlag(c, "nested") && (GetFlag(c, "feature:flatnested") || Language::instance()->nestedClassesSupport() == Language::NCS_None)) {
+ removeNode(c);
+ if (!checkAttribute(c, "access", "public"))
+ SetFlag(c, "feature:ignore");
+ else if (Strcmp(nodeType(n),"extend") == 0 && Strcmp(nodeType(parentNode(n)),"class") == 0)
+ insertNodeAfter(parentNode(n), c);
+ else
+ insertNodeAfter(n, c);
+ }
+ Swig_nested_process_classes(c);
+ }
+ c = next;
+ }
+ remove_outer_class_reference(n);
+}
+
diff --git a/contrib/tools/swig/Source/Modules/ocaml.cxx b/contrib/tools/swig/Source/Modules/ocaml.cxx
new file mode 100644
index 00000000000..9f7504b871c
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/ocaml.cxx
@@ -0,0 +1,1889 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * ocaml.cxx
+ *
+ * Ocaml language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+
+#include <ctype.h>
+
+static const char *usage = "\
+Ocaml Options (available with -ocaml)\n\
+ -oldvarnames - Old intermediary method names for variable wrappers\n\
+ -prefix <name> - Set a prefix <name> to be prepended to all names\n\
+ -suffix <name> - Deprecated alias for general option -cppext\n\
+ -where - Emit library location\n\
+\n";
+
+static int classmode = 0;
+static int in_constructor = 0, in_destructor = 0, in_copyconst = 0;
+static int const_enum = 0;
+static int static_member_function = 0;
+static int generate_sizeof = 0;
+static String *prefix = 0;
+static const char *ocaml_path = "ocaml";
+static bool old_variable_names = false;
+static String *classname = 0;
+static String *module = 0;
+static String *init_func_def = 0;
+static String *f_classtemplate = 0;
+static SwigType *name_qualifier_type = 0;
+
+static Hash *seen_enums = 0;
+static Hash *seen_enumvalues = 0;
+static Hash *seen_constructors = 0;
+
+static File *f_header = 0;
+static File *f_begin = 0;
+static File *f_runtime = 0;
+static File *f_wrappers = 0;
+static File *f_directors = 0;
+static File *f_directors_h = 0;
+static File *f_init = 0;
+static File *f_mlout = 0;
+static File *f_mliout = 0;
+static File *f_mlbody = 0;
+static File *f_mlibody = 0;
+static File *f_mltail = 0;
+static File *f_mlitail = 0;
+static File *f_enumtypes_type = 0;
+static File *f_enumtypes_value = 0;
+static File *f_class_ctors = 0;
+static File *f_class_ctors_end = 0;
+static File *f_enum_to_int = 0;
+static File *f_int_to_enum = 0;
+
+class OCAML:public Language {
+public:
+
+ OCAML() {
+ director_prot_ctor_code = NewString("");
+ Printv(director_prot_ctor_code,
+ "if ( $comparison ) { /* subclassed */\n",
+ " $director_new \n", "} else {\n", " caml_failwith(\"accessing abstract class or protected constructor\"); \n", "}\n", NIL);
+ director_multiple_inheritance = 1;
+ director_language = 1;
+ }
+
+ String *Swig_class_name(Node *n) {
+ String *name;
+ name = Copy(Getattr(n, "sym:name"));
+ return name;
+ }
+
+ void PrintIncludeArg() {
+ Printv(stdout, SWIG_LIB, SWIG_FILE_DELIMITER, ocaml_path, "\n", NIL);
+ }
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+ int i;
+
+ prefix = 0;
+
+ SWIG_library_directory(ocaml_path);
+
+ // Look for certain command line options
+ for (i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ SWIG_exit(0);
+ } else if (strcmp(argv[i], "-where") == 0) {
+ PrintIncludeArg();
+ SWIG_exit(0);
+ } else if (strcmp(argv[i], "-prefix") == 0) {
+ if (argv[i + 1]) {
+ prefix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-suffix") == 0) {
+ if (argv[i + 1]) {
+ Printf(stderr, "swig: warning: -suffix option deprecated. SWIG 3.0.4 and later provide a -cppext option which should be used instead.\n");
+ SWIG_config_cppext(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else
+ Swig_arg_error();
+ } else if (strcmp(argv[i], "-oldvarnames") == 0) {
+ Swig_mark_arg(i);
+ old_variable_names = true;
+ }
+ }
+ }
+
+ // If a prefix has been specified make sure it ends in a '_' (not actually used!)
+ if (prefix) {
+ const char *px = Char(prefix);
+ if (px[Len(prefix) - 1] != '_')
+ Printf(prefix, "_");
+ } else
+ prefix = NewString("swig_");
+
+ // Add a symbol for this module
+
+ Preprocessor_define("SWIGOCAML 1", 0);
+ // Set name of typemaps
+
+ SWIG_typemap_lang("ocaml");
+
+ // Read in default typemaps */
+ SWIG_config_file("ocaml.i");
+ allow_overloading();
+
+ }
+
+ /* Swig_director_declaration()
+ *
+ * Generate the full director class declaration, complete with base classes.
+ * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
+ *
+ */
+
+ String *Swig_director_declaration(Node *n) {
+ String *classname = Swig_class_name(n);
+ String *directorname = NewStringf("SwigDirector_%s", classname);
+ String *base = Getattr(n, "classtype");
+ String *declaration = Swig_class_declaration(n, directorname);
+ Printf(declaration, " : public %s, public Swig::Director {\n", base);
+ Delete(classname);
+ Delete(directorname);
+ return declaration;
+ }
+
+ void emitBanner(File *f) {
+ Printf(f, "(* ----------------------------------------------------------------------------\n");
+ Swig_banner_target_lang(f, " *");
+ Printf(f, " * ---------------------------------------------------------------------------- *)\n\n");
+ }
+
+ /* ------------------------------------------------------------
+ * top()
+ *
+ * Recognize the %module, and capture the module name.
+ * Create the default enum cases.
+ * Set up the named outputs:
+ *
+ * init
+ * ml
+ * mli
+ * wrapper
+ * header
+ * runtime
+ * directors
+ * directors_h
+ * ------------------------------------------------------------ */
+
+ virtual int top(Node *n) {
+ /* Set comparison with none for ConstructorToFunction */
+ setSubclassInstanceCheck(NewString("caml_list_nth(args,0) != Val_unit"));
+
+ /* check if directors are enabled for this module. note: this
+ * is a "master" switch, without which no director code will be
+ * emitted. %feature("director") statements are also required
+ * to enable directors for individual classes or methods.
+ *
+ * use %module(directors="1") modulename at the start of the
+ * interface file to enable director generation.
+ */
+ String *mod_docstring = NULL;
+ {
+ Node *module = Getattr(n, "module");
+ if (module) {
+ Node *options = Getattr(module, "options");
+ if (options) {
+ if (Getattr(options, "directors")) {
+ allow_directors();
+ }
+ if (Getattr(options, "dirprot")) {
+ allow_dirprot();
+ }
+ if (Getattr(options, "sizeof")) {
+ generate_sizeof = 1;
+ }
+ mod_docstring = Getattr(options, "docstring");
+ }
+ }
+ }
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+ f_directors = NewString("");
+ f_directors_h = NewString("");
+ f_enumtypes_type = NewString("");
+ f_enumtypes_value = NewString("");
+ init_func_def = NewString("");
+ f_mlbody = NewString("");
+ f_mlibody = NewString("");
+ f_mltail = NewString("");
+ f_mlitail = NewString("");
+ f_class_ctors = NewString("");
+ f_class_ctors_end = NewString("");
+ f_enum_to_int = NewString("");
+ f_int_to_enum = NewString("");
+ f_classtemplate = NewString("");
+
+ module = Getattr(n, "name");
+
+ seen_constructors = NewHash();
+ seen_enums = NewHash();
+ seen_enumvalues = NewHash();
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("init", init_func_def);
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("mli", f_mlibody);
+ Swig_register_filebyname("ml", f_mlbody);
+ Swig_register_filebyname("mlitail", f_mlitail);
+ Swig_register_filebyname("mltail", f_mltail);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+ Swig_register_filebyname("classtemplate", f_classtemplate);
+ Swig_register_filebyname("class_ctors", f_class_ctors);
+
+ if (old_variable_names) {
+ Swig_name_register("set", "%n%v__set__");
+ Swig_name_register("get", "%n%v__get__");
+ }
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n\n#ifndef SWIGOCAML\n#define SWIGOCAML\n#endif\n\n");
+
+ Printf(f_runtime, "#define SWIG_MODULE \"%s\"\n", module);
+ /* Module name */
+ Printf(f_mlbody, "let module_name = \"%s\"\n", module);
+ Printf(f_mlibody, "val module_name : string\n");
+ Printf(f_enum_to_int,
+ "let enum_to_int x (v : c_obj) =\n"
+ " match v with\n"
+ " C_enum _y ->\n"
+ " (let y = _y in match (x : c_enum_type) with\n"
+ " `unknown -> " " (match y with\n" " `Int x -> (Swig.C_int x)\n" " | _ -> raise (LabelNotFromThisEnum v))\n");
+
+ Printf(f_int_to_enum, "let int_to_enum x y =\n" " match (x : c_enum_type) with\n" " `unknown -> C_enum (`Int y)\n");
+
+ if (directorsEnabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+ }
+
+ Printf(f_runtime, "\n");
+
+ /* Produce the enum_to_int and int_to_enum functions */
+
+ Printf(f_enumtypes_type, "open Swig\n" "type c_enum_type = [ \n `unknown\n");
+ Printf(f_enumtypes_value, "type c_enum_value = [ \n `Int of int\n");
+ String *mlfile = NewString("");
+ String *mlifile = NewString("");
+
+ Printv(mlfile, module, ".ml", NIL);
+ Printv(mlifile, module, ".mli", NIL);
+
+ String *mlfilen = NewStringf("%s%s", SWIG_output_directory(), mlfile);
+ if ((f_mlout = NewFile(mlfilen, "w", SWIG_output_files())) == 0) {
+ FileErrorDisplay(mlfilen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ String *mlifilen = NewStringf("%s%s", SWIG_output_directory(), mlifile);
+ if ((f_mliout = NewFile(mlifilen, "w", SWIG_output_files())) == 0) {
+ FileErrorDisplay(mlifilen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ emitBanner(f_mlout);
+ emitBanner(f_mliout);
+
+ Language::top(n);
+
+ if (mod_docstring) {
+ if (Len(mod_docstring)) {
+ Printv(f_mliout, "(** ", mod_docstring, " *)\n", NIL);
+ }
+ Delete(mod_docstring);
+ mod_docstring = NULL;
+ }
+
+ Printf(f_enum_to_int, ") | _ -> (C_int (get_int v))\n" "let _ = Callback.register \"%s_enum_to_int\" enum_to_int\n", module);
+ Printf(f_mlibody, "val enum_to_int : c_enum_type -> c_obj -> Swig.c_obj\n");
+
+ Printf(f_int_to_enum, "let _ = Callback.register \"%s_int_to_enum\" int_to_enum\n", module);
+ Printf(f_mlibody, "val int_to_enum : c_enum_type -> int -> c_obj\n");
+ Printf(f_init, "#define SWIG_init f_%s_init\n" "%s" "}\n", module, init_func_def);
+ Printf(f_mlbody, "external f_init : unit -> unit = \"f_%s_init\" ;;\n" "let _ = f_init ()\n", module);
+ Printf(f_enumtypes_type, "]\n");
+ Printf(f_enumtypes_value, "]\n\n" "type c_obj = c_enum_value c_obj_t\n");
+
+ if (directorsEnabled()) {
+ // Insert director runtime into the f_runtime file (make it occur before %header section)
+ Swig_insert_file("director_common.swg", f_runtime);
+ Swig_insert_file("director.swg", f_runtime);
+ }
+
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+ /* Close all of the files */
+ Dump(f_runtime, f_begin);
+ Dump(f_directors_h, f_header);
+ Dump(f_header, f_begin);
+ Dump(f_directors, f_wrappers);
+ Dump(f_wrappers, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_runtime);
+ Delete(f_begin);
+
+ Dump(f_enumtypes_type, f_mlout);
+ Dump(f_enumtypes_value, f_mlout);
+ Dump(f_mlbody, f_mlout);
+ Dump(f_enum_to_int, f_mlout);
+ Dump(f_int_to_enum, f_mlout);
+ Delete(f_int_to_enum);
+ Delete(f_enum_to_int);
+ Dump(f_class_ctors, f_mlout);
+ Dump(f_class_ctors_end, f_mlout);
+ Dump(f_mltail, f_mlout);
+ Delete(f_mlout);
+
+ Dump(f_enumtypes_type, f_mliout);
+ Dump(f_enumtypes_value, f_mliout);
+ Dump(f_mlibody, f_mliout);
+ Dump(f_mlitail, f_mliout);
+ Delete(f_mliout);
+
+ return SWIG_OK;
+ }
+
+ /* Produce an error for the given type */
+ void throw_unhandled_ocaml_type_error(SwigType *d, const char *types) {
+ Swig_warning(WARN_TYPEMAP_UNDEF, input_file, line_number, "Unable to handle type %s (%s).\n", SwigType_str(d, 0), types);
+ }
+
+ /* Return true iff T is a pointer type */
+ int
+ is_a_pointer(SwigType *t) {
+ return SwigType_ispointer(SwigType_typedef_resolve_all(t));
+ }
+
+ /*
+ * Delete one reference from a given type.
+ */
+
+ void oc_SwigType_del_reference(SwigType *t) {
+ char *c = Char(t);
+ if (strncmp(c, "q(", 2) == 0) {
+ Delete(SwigType_pop(t));
+ c = Char(t);
+ }
+ if (strncmp(c, "r.", 2)) {
+ printf("Fatal error. SwigType_del_pointer applied to non-pointer.\n");
+ abort();
+ }
+ Replace(t, "r.", "", DOH_REPLACE_ANY | DOH_REPLACE_FIRST);
+ }
+
+ void oc_SwigType_del_array(SwigType *t) {
+ char *c = Char(t);
+ if (strncmp(c, "q(", 2) == 0) {
+ Delete(SwigType_pop(t));
+ c = Char(t);
+ }
+ if (strncmp(c, "a(", 2) == 0) {
+ Delete(SwigType_pop(t));
+ }
+ }
+
+ /*
+ * Return true iff T is a reference type
+ */
+
+ int
+ is_a_reference(SwigType *t) {
+ return SwigType_isreference(SwigType_typedef_resolve_all(t));
+ }
+
+ int
+ is_an_array(SwigType *t) {
+ return SwigType_isarray(SwigType_typedef_resolve_all(t));
+ }
+
+ virtual int membervariableHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ Language::membervariableHandler(n);
+
+ String *mname = Swig_name_member(NSPACE_TODO, classname, symname);
+ String *getname = Swig_name_get(NSPACE_TODO, mname);
+ String *mangled_getname = mangleNameForCaml(getname);
+ Delete(getname);
+
+ if (!GetFlag(n, "feature:immutable")) {
+ String *setname = Swig_name_set(NSPACE_TODO, mname);
+ String *mangled_setname = mangleNameForCaml(setname);
+ Delete(setname);
+ Printf(f_class_ctors, " \"[%s]\", (fun args -> " "if args = (C_list [ raw_ptr ]) then _%s args else _%s args) ;\n", symname, mangled_getname, mangled_setname);
+ Delete(mangled_setname);
+ } else {
+ Printf(f_class_ctors, " \"[%s]\", (fun args -> " "if args = (C_list [ raw_ptr ]) then _%s args else C_void) ;\n", symname, mangled_getname);
+ }
+ Delete(mangled_getname);
+ Delete(mname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * functionWrapper()
+ * Create a function declaration and register it with the interpreter.
+ * ------------------------------------------------------------ */
+
+ virtual int functionWrapper(Node *n) {
+ char *iname = GetChar(n, "sym:name");
+ SwigType *d = Getattr(n, "type");
+ String *return_type_normalized = normalizeTemplatedClassName(d);
+ ParmList *l = Getattr(n, "parms");
+ int director_method = 0;
+ Parm *p;
+
+ Wrapper *f = NewWrapper();
+ String *proc_name = NewString("");
+ String *target = NewString("");
+ String *arg = NewString("");
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ String *build = NewString("");
+ String *tm;
+ int i = 0;
+ int numargs;
+ int numreq;
+ int newobj = GetFlag(n, "feature:new");
+ String *nodeType = Getattr(n, "nodeType");
+ int destructor = (!Cmp(nodeType, "destructor"));
+ String *overname = 0;
+ bool isOverloaded = Getattr(n, "sym:overloaded") ? true : false;
+ // For overloaded functions, only the dispatch function needs to be exposed in the ml and mli files.
+ bool expose_func = !isOverloaded || !Getattr(n, "sym:nextSibling");
+
+ // Make a wrapper name for this
+ String *wname = Swig_name_wrapper(iname);
+ if (isOverloaded) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n)) {
+ DelWrapper(f);
+ return SWIG_ERROR;
+ }
+ }
+ if (overname) {
+ Append(wname, overname);
+ }
+ /* Do this to disambiguate functions emitted from different modules */
+ Append(wname, module);
+
+ Setattr(n, "wrap:name", wname);
+
+ // Build the name for Scheme.
+ Printv(proc_name, "_", iname, NIL);
+ String *mangled_name = mangleNameForCaml(proc_name);
+
+ if (classmode && in_constructor && expose_func) { // Emit constructor for object
+ String *mangled_name_nounder = NewString((char *) (Char(mangled_name)) + 1);
+ Printf(f_class_ctors_end, "let %s clst = _%s clst\n", mangled_name_nounder, mangled_name_nounder);
+ Printf(f_mlibody, "val %s : c_obj -> c_obj\n", mangled_name_nounder);
+ Delete(mangled_name_nounder);
+ } else if (classmode && in_destructor) {
+ Printf(f_class_ctors, " \"~\", %s ;\n", mangled_name);
+ } else if (classmode && !in_constructor && !in_destructor && !static_member_function &&
+ !Getattr(n, "membervariableHandler:sym:name") && expose_func) {
+ String *opname = Copy(Getattr(n, "memberfunctionHandler:sym:name"));
+
+ Replaceall(opname, "operator ", "");
+ Printf(f_class_ctors, " \"%s\", %s ;\n", opname, mangled_name);
+ Delete(opname);
+ }
+
+ if (classmode && in_constructor) {
+ Setattr(seen_constructors, mangled_name, "true");
+ }
+ // writing the function wrapper function
+ Printv(f->def, "SWIGEXT CAML_VALUE ", wname, " (", NIL);
+ Printv(f->def, "CAML_VALUE args", NIL);
+ Printv(f->def, ")\n{", NIL);
+
+ /* Define the scheme name in C. This define is used by several
+ macros. */
+ //Printv(f->def, "#define FUNC_NAME \"", mangled_name, "\"", NIL);
+
+ // adds local variables
+ Wrapper_add_local(f, "args", "CAMLparam1(args)");
+ Wrapper_add_local(f, "ret", "SWIG_CAMLlocal2(swig_result,rv)");
+ d = SwigType_typedef_qualified(d);
+ emit_parameter_variables(l, f);
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+ Setattr(n, "wrap:parms", l);
+
+ numargs = emit_num_arguments(l);
+ numreq = emit_num_required(l);
+ if (!isOverloaded) {
+ if (numargs > 0) {
+ if (numreq > 0) {
+ Printf(f->code, "if (caml_list_length(args) < %d || caml_list_length(args) > %d) {\n", numreq, numargs);
+ } else {
+ Printf(f->code, "if (caml_list_length(args) > %d) {\n", numargs);
+ }
+ Printf(f->code, "caml_invalid_argument(\"Incorrect number of arguments passed to '%s'\");\n}\n", iname);
+ } else {
+ Printf(f->code, "if (caml_list_length(args) > 0) caml_invalid_argument(\"'%s' takes no arguments\");\n", iname);
+ }
+ }
+ Printf(f->code, "swig_result = Val_unit;\n");
+
+ // Now write code to extract the parameters (this is super ugly)
+
+ for (i = 0, p = l; i < numargs; i++) {
+ /* Skip ignored arguments */
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+ pt = SwigType_typedef_qualified(pt);
+
+ // Produce names of source and target
+ Clear(target);
+ Clear(arg);
+ String *source = NewStringf("caml_list_nth(args,%d)", i);
+ Printf(target, "%s", ln);
+ Printv(arg, Getattr(p, "name"), NIL);
+
+ if (i >= numreq) {
+ Printf(f->code, "if (caml_list_length(args) > %d) {\n", i);
+ }
+ // Handle parameter types.
+ if ((tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$source", source);
+ Replaceall(tm, "$target", target);
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source);
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ // no typemap found
+ // check if typedef and resolve
+ throw_unhandled_ocaml_type_error(pt, "in");
+ p = nextSibling(p);
+ }
+ if (i >= numreq) {
+ Printf(f->code, "}\n");
+ }
+ Delete(source);
+ }
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Pass output arguments back to the caller.
+
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ Replaceall(tm, "$source", Getattr(p, "emit:input")); /* Deprecated */
+ Replaceall(tm, "$target", Getattr(p, "lname")); /* Deprecated */
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Replaceall(tm, "$ntype", normalizeTemplatedClassName(Getattr(p, "type")));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Free up any memory allocated for the arguments.
+
+ /* Insert cleanup code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* if the object is a director, and the method call originated from its
+ * underlying ocaml object, resolve the call by going up the c++
+ * inheritance chain. otherwise try to resolve the method in ocaml.
+ * without this check an infinite loop is set up between the director and
+ * shadow class method calls.
+ */
+
+ // NOTE: this code should only be inserted if this class is the
+ // base class of a director class. however, in general we haven't
+ // yet analyzed all classes derived from this one to see if they are
+ // directors. furthermore, this class may be used as the base of
+ // a director class defined in a completely different module at a
+ // later time, so this test must be included whether or not directorbase
+ // is true. we do skip this code if directors have not been enabled
+ // at the command line to preserve source-level compatibility with
+ // non-polymorphic swig. also, if this wrapper is for a smart-pointer
+ // method, there is no need to perform the test since the calling object
+ // (the smart-pointer) and the director object (the "pointee") are
+ // distinct.
+
+ director_method = is_member_director(n) && !is_smart_pointer() && !destructor;
+ if (director_method) {
+ Wrapper_add_local(f, "director", "Swig::Director *director = 0");
+ Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n");
+ Wrapper_add_local(f, "upcall", "bool upcall = false");
+ Append(f->code, "upcall = (director);\n");
+ }
+
+ // Now write code to make the function call
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ Replaceall(tm, "$source", "swig_result");
+ Replaceall(tm, "$target", "rv");
+ Replaceall(tm, "$result", "rv");
+ Replaceall(tm, "$ntype", return_type_normalized);
+ Printv(f->code, tm, "\n", NIL);
+ } else {
+ throw_unhandled_ocaml_type_error(d, "out");
+ }
+ emit_return_variable(n, d, f);
+
+ // Dump the argument output code
+ Printv(f->code, Char(outarg), NIL);
+
+ // Dump the argument cleanup code
+ Printv(f->code, Char(cleanup), NIL);
+
+ // Look for any remaining cleanup
+
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", "swig_result");
+ Printv(f->code, tm, "\n", NIL);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+
+ // Free any memory allocated by the function being wrapped..
+
+ if ((tm = Swig_typemap_lookup("swig_result", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printv(f->code, tm, "\n", NIL);
+ }
+ // Wrap things up (in a manner of speaking)
+
+ Printv(f->code, tab4, "swig_result = caml_list_append(swig_result,rv);\n", NIL);
+ Printv(f->code, tab4, "CAMLreturn(swig_result);\n", NIL);
+ Printv(f->code, "}\n", NIL);
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", iname);
+
+ Wrapper_print(f, f_wrappers);
+
+ if (isOverloaded) {
+ if (!Getattr(n, "sym:nextSibling")) {
+ int maxargs;
+ Wrapper *df = NewWrapper();
+ String *dispatch = Swig_overload_dispatch(n,
+ "free(argv);\n" "CAMLreturn(%s(args));\n",
+ &maxargs);
+
+ Wrapper_add_local(df, "argv", "CAML_VALUE *argv");
+
+ /* Undifferentiate name .. this is the dispatch function */
+ wname = Swig_name_wrapper(iname);
+ /* Do this to disambiguate functions emitted from different
+ * modules */
+ Append(wname, module);
+
+ Printv(df->def,
+ "SWIGEXT CAML_VALUE ", wname, "(CAML_VALUE args) {\n" " CAMLparam1(args);\n" " int i;\n" " int argc = caml_list_length(args);\n", NIL);
+ Printv(df->code,
+ "argv = (CAML_VALUE *)malloc( argc * sizeof( CAML_VALUE ) );\n"
+ "for( i = 0; i < argc; i++ ) {\n" " argv[i] = caml_list_nth(args,i);\n" "}\n", NIL);
+ Printv(df->code, dispatch, "\nfree(argv);\n", NIL);
+ Node *sibl = n;
+ while (Getattr(sibl, "sym:previousSibling"))
+ sibl = Getattr(sibl, "sym:previousSibling");
+ String *protoTypes = NewString("");
+ do {
+ String *fulldecl = Swig_name_decl(sibl);
+ Printf(protoTypes, "\n\" %s\\n\"", fulldecl);
+ Delete(fulldecl);
+ } while ((sibl = Getattr(sibl, "sym:nextSibling")));
+ Printf(df->code, "caml_failwith(\"Wrong number or type of arguments for overloaded function '%s'.\\n\""
+ "\n\" Possible C/C++ prototypes are:\\n\"%s);\n", iname, protoTypes);
+ Delete(protoTypes);
+ Printv(df->code, "}\n", NIL);
+ Wrapper_print(df, f_wrappers);
+
+ DelWrapper(df);
+ Delete(dispatch);
+ }
+ }
+
+ if (expose_func) {
+ Printf(f_mlbody, "external %s_f : c_obj list -> c_obj list = \"%s\" ;;\n", mangled_name, wname);
+ Printf(f_mlbody, "let %s arg = match %s_f (%s(fnhelper arg)) with\n", mangled_name, mangled_name,
+ in_constructor && Swig_directorclass(getCurrentClass()) ? "director_core_helper " : "");
+ Printf(f_mlbody, " [] -> C_void\n"
+ "| [x] -> (if %s then Gc.finalise \n"
+ " (fun x -> ignore ((invoke x) \"~\" C_void)) x) ; x\n"
+ "| lst -> C_list lst ;;\n", newobj ? "true" : "false");
+ }
+
+ if ((!classmode || in_constructor || in_destructor || static_member_function) && expose_func)
+ Printf(f_mlibody, "val %s : c_obj -> c_obj\n", mangled_name);
+
+ Delete(proc_name);
+ Delete(target);
+ Delete(arg);
+ Delete(outarg);
+ Delete(cleanup);
+ Delete(build);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * variableWrapper()
+ *
+ * Create a link to a C variable.
+ * This creates a single function _wrap_varname().
+ * This function takes a single optional argument. If supplied, it means
+ * we are setting this variable to some value. If omitted, it means we are
+ * simply evaluating this variable. We return the value of the variable
+ * in both cases.
+ *
+ * symname is the name of the variable with respect to C. This
+ * may need to differ from the original name in the case of enums.
+ * enumvname is the name of the variable with respect to ocaml. This
+ * will vary if the variable has been renamed.
+ * ------------------------------------------------------------ */
+
+ virtual int variableWrapper(Node *n) {
+ char *name = GetChar(n, "feature:symname");
+ String *iname = Getattr(n, "feature:enumvname");
+ String *mname = mangleNameForCaml(iname);
+ SwigType *t = Getattr(n, "type");
+
+ String *proc_name = NewString("");
+ String *tm;
+ Wrapper *f;
+
+ if (!name) {
+ name = GetChar(n, "name");
+ }
+
+ if (!iname) {
+ iname = Getattr(n, "sym:name");
+ mname = mangleNameForCaml(NewString(iname));
+ }
+
+ if (!iname || !addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ f = NewWrapper();
+
+ // evaluation function names
+ String *var_name = Swig_name_wrapper(iname);
+
+ // Build the name for OCaml.
+ Printv(proc_name, iname, NIL);
+ Setattr(n, "wrap:name", proc_name);
+
+ Printf(f->def, "SWIGEXT CAML_VALUE %s(CAML_VALUE args) {\n", var_name);
+ // Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL);
+
+ Wrapper_add_local(f, "args", "CAMLparam1(args)");
+ Wrapper_add_local(f, "swig_result", "SWIG_CAMLlocal1(swig_result)");
+ Printf(f->code, "swig_result = Val_unit;\n");
+
+ if (!GetFlag(n, "feature:immutable")) {
+ /* Check for a setting of the variable value */
+ Printf(f->code, "if (args != Val_int(0)) {\n");
+ if ((tm = Swig_typemap_lookup("varin", n, name, 0))) {
+ Replaceall(tm, "$source", "args");
+ Replaceall(tm, "$target", name);
+ Replaceall(tm, "$input", "args");
+ emit_action_code(n, f->code, tm);
+ } else if ((tm = Swig_typemap_lookup("in", n, name, 0))) {
+ Replaceall(tm, "$source", "args");
+ Replaceall(tm, "$target", name);
+ Replaceall(tm, "$input", "args");
+ emit_action_code(n, f->code, tm);
+ } else {
+ throw_unhandled_ocaml_type_error(t, "varin/in");
+ }
+ Printf(f->code, "}\n");
+ }
+ // Now return the value of the variable (regardless
+ // of evaluating or setting)
+
+ if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
+ Replaceall(tm, "$source", name);
+ Replaceall(tm, "$target", "swig_result");
+ Replaceall(tm, "$result", "swig_result");
+ emit_action_code(n, f->code, tm);
+ } else if ((tm = Swig_typemap_lookup("out", n, name, 0))) {
+ Replaceall(tm, "$source", name);
+ Replaceall(tm, "$target", "swig_result");
+ Replaceall(tm, "$result", "swig_result");
+ emit_action_code(n, f->code, tm);
+ } else {
+ throw_unhandled_ocaml_type_error(t, "varout/out");
+ }
+
+ Printf(f->code, "\nCAMLreturn(swig_result);\n");
+ Printf(f->code, "}\n");
+
+ Wrapper_print(f, f_wrappers);
+
+ // Now add symbol to the Ocaml interpreter
+
+ if (GetFlag(n, "feature:immutable")) {
+ Printf(f_mlbody, "external _%s : c_obj -> Swig.c_obj = \"%s\" \n", mname, var_name);
+ Printf(f_mlibody, "val _%s : c_obj -> Swig.c_obj\n", iname);
+ if (const_enum) {
+ Printf(f_enum_to_int, " | `%s -> _%s C_void\n", mname, mname);
+ Printf(f_int_to_enum, " if y = (get_int (_%s C_void)) then `%s else\n", mname, mname);
+ }
+ } else {
+ Printf(f_mlbody, "external _%s : c_obj -> c_obj = \"%s\"\n", mname, var_name);
+ Printf(f_mlibody, "external _%s : c_obj -> c_obj = \"%s\"\n", mname, var_name);
+ }
+
+ Delete(var_name);
+ Delete(proc_name);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * staticmemberfunctionHandler --
+ * Overridden to set static_member_function
+ * ------------------------------------------------------------ */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ static_member_function = 1;
+ Language::staticmemberfunctionHandler(n);
+ static_member_function = 0;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ *
+ * The one trick here is that we have to make sure we rename the
+ * constant to something useful that doesn't collide with the
+ * original if any exists.
+ * ------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ String *name = Getattr(n, "feature:symname");
+ SwigType *type = Getattr(n, "type");
+ String *rawval = Getattr(n, "rawval");
+ String *value = rawval ? rawval : Getattr(n, "value");
+ SwigType *qname = Getattr(n, "qualified:name");
+
+ if (qname)
+ value = qname;
+
+ if (!name) {
+ name = mangleNameForCaml(Getattr(n, "name"));
+ Insert(name, 0, "_swig_wrap_");
+ Setattr(n, "feature:symname", name);
+ }
+ // See if there's a typemap
+
+ // Create variable and assign it a value
+ Printf(f_header, "static %s = %s;\n", SwigType_str(type, name), value);
+ SetFlag(n, "feature:immutable");
+ variableWrapper(n);
+ return SWIG_OK;
+ }
+
+ int constructorHandler(Node *n) {
+ int ret;
+
+ in_constructor = 1;
+ ret = Language::constructorHandler(n);
+ in_constructor = 0;
+
+ return ret;
+ }
+
+ /* destructorHandler:
+ * Turn on destructor flag to inform decisions in functionWrapper
+ */
+
+ int destructorHandler(Node *n) {
+ int ret;
+
+ in_destructor = 1;
+ ret = Language::destructorHandler(n);
+ in_destructor = 0;
+
+ return ret;
+ }
+
+ /* copyconstructorHandler:
+ * Turn on constructor and copyconstructor flags for functionWrapper
+ */
+
+ int copyconstructorHandler(Node *n) {
+ int ret;
+
+ in_copyconst = 1;
+ in_constructor = 1;
+ ret = Language::copyconstructorHandler(n);
+ in_constructor = 0;
+ in_copyconst = 0;
+
+ return ret;
+ }
+
+ /**
+ * A simple, somewhat general purpose function for writing to multiple
+ * streams from a source template. This allows the user to define the
+ * class definition in ways different from the one I have here if they
+ * want to. It will also make the class definition system easier to
+ * fiddle with when I want to change methods, etc.
+ */
+
+ void Multiwrite(String *s) {
+ char *find_marker = strstr(Char(s), "(*Stream:");
+ while (find_marker) {
+ char *next = strstr(find_marker, "*)");
+ find_marker += strlen("(*Stream:");
+
+ if (next) {
+ int num_chars = (int)(next - find_marker);
+ String *stream_name = NewString(find_marker);
+ Delslice(stream_name, num_chars, Len(stream_name));
+ File *fout = Swig_filebyname(stream_name);
+ if (fout) {
+ next += strlen("*)");
+ char *following = strstr(next, "(*Stream:");
+ find_marker = following;
+ if (!following)
+ following = next + strlen(next);
+ String *chunk = NewString(next);
+ Delslice(chunk, (int)(following - next), Len(chunk));
+ Printv(fout, chunk, NIL);
+ }
+ }
+ }
+ }
+
+ bool isSimpleType(String *name) {
+ char *ch = Char(name);
+
+ return !(strchr(ch, '(') || strchr(ch, '<') || strchr(ch, ')') || strchr(ch, '>'));
+ }
+
+ /* We accept all chars in identifiers because we use strings to index
+ * them. */
+ int validIdentifier(String *name) {
+ return Len(name) > 0 ? 1 : 0;
+ }
+
+ /* classHandler
+ *
+ * Create a "class" definition for ocaml. I thought quite a bit about
+ * how I should do this part of it, and arrived here, using a function
+ * invocation to select a method, and dispatch. This can obviously be
+ * done better, but I can't see how, given that I want to support
+ * overloaded methods, out parameters, and operators.
+ *
+ * I needed a system that would do this:
+ *
+ * a Be able to call these methods:
+ * int foo( int x );
+ * float foo( int x, int &out );
+ *
+ * b Be typeable, even in the presence of mutually dependent classes.
+ *
+ * c Support some form of operator invocation.
+ *
+ * (c) I chose strings for the method names so that "+=" would be a
+ * valid method name, and the somewhat natural << (invoke x) "+=" y >>
+ * would work.
+ *
+ * (a) (b) Since the c_obj type exists, it's easy to return C_int in one
+ * case and C_list [ C_float ; C_int ] in the other. This makes tricky
+ * problems with out parameters disappear; they're simply appended to the
+ * return list.
+ *
+ * (b) Since every item that comes from C++ is the same type, there is no
+ * problem with the following:
+ *
+ * class Foo;
+ * class Bar { Foo *toFoo(); }
+ * class Foo { Bar *toBar(); }
+ *
+ * Since the Objective caml types of Foo and Bar are the same. Now that
+ * I correctly incorporate SWIG's typechecking, this isn't a big deal.
+ *
+ * The class is in the form of a function returning a c_obj. The c_obj
+ * is a C_obj containing a function which invokes a method on the
+ * underlying object given its type.
+ *
+ * The name emitted here is normalized before being sent to
+ * Callback.register, because we need this string to look up properly
+ * when the typemap passes the descriptor string. I've been considering
+ * some, possibly more forgiving method that would do some transformations
+ * on the $descriptor in order to find a potential match. This is for
+ * later.
+ *
+ * Important things to note:
+ *
+ * We rely on exception handling (BadMethodName) in order to call an
+ * ancestor. This can be improved.
+ *
+ * The method used to get :classof could be improved to look at the type
+ * info that the base pointer contains. It's really an error to have a
+ * SWIG-generated object that does not contain type info, since the
+ * existence of the object means that SWIG knows the type.
+ *
+ * :parents could use :classof to tell what class it is and make a better
+ * decision. This could be nice, (i.e. provide a run-time graph of C++
+ * classes represented);.
+ *
+ * I can't think of a more elegant way of converting a C_obj fun to a
+ * pointer than "operator &"...
+ *
+ * Added a 'sizeof' that will allow you to do the expected thing.
+ * This should help users to fill buffer structs and the like (as is
+ * typical in windows-styled code). It's only enabled if you give
+ * %feature(sizeof) and then, only for simple types.
+ *
+ * Overall, carrying the list of methods and base classes has worked well.
+ * It allows me to give the Ocaml user introspection over their objects.
+ */
+
+ int classHandler(Node *n) {
+ String *name = Getattr(n, "name");
+ classname = Getattr(n, "sym:name");
+
+ if (!name)
+ return SWIG_OK;
+
+ String *mangled_name = mangleNameForCaml(name);
+ String *this_class_def = NewString(f_classtemplate);
+ String *name_normalized = normalizeTemplatedClassName(name);
+ String *old_class_ctors = f_class_ctors;
+ String *base_classes = NewString("");
+ f_class_ctors = NewString("");
+ bool sizeof_feature = generate_sizeof && isSimpleType(name);
+
+
+ classmode = true;
+ int rv = Language::classHandler(n);
+ classmode = false;
+
+ if (sizeof_feature) {
+ Printf(f_wrappers,
+ "SWIGEXT CAML_VALUE _wrap_%s_sizeof( CAML_VALUE args ) {\n"
+ " CAMLparam1(args);\n" " CAMLreturn(Val_int(sizeof(%s)));\n" "}\n", mangled_name, name_normalized);
+
+ Printf(f_mlbody, "external __%s_sizeof : unit -> int = " "\"_wrap_%s_sizeof\"\n", mangled_name, mangled_name);
+ }
+
+
+ /* Insert sizeof operator for concrete classes */
+ if (sizeof_feature) {
+ Printv(f_class_ctors, "\"sizeof\" , (fun args -> C_int (__", mangled_name, "_sizeof ())) ;\n", NIL);
+ }
+ /* Handle up-casts in a nice way */
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator b;
+ b = First(baselist);
+ while (b.item) {
+ String *bname = Getattr(b.item, "name");
+ if (bname) {
+ String *base_create = NewString("");
+ Printv(base_create, "(create_class \"", bname, "\")", NIL);
+ Printv(f_class_ctors, " \"::", bname, "\", (fun args -> ", base_create, " args) ;\n", NIL);
+ Printv(base_classes, base_create, " ;\n", NIL);
+ }
+ b = Next(b);
+ }
+ }
+
+ Replaceall(this_class_def, "$classname", mangled_name);
+ Replaceall(this_class_def, "$normalized", name_normalized);
+ Replaceall(this_class_def, "$realname", name);
+ Replaceall(this_class_def, "$baselist", base_classes);
+ Replaceall(this_class_def, "$classbody", f_class_ctors);
+
+ Delete(f_class_ctors);
+ f_class_ctors = old_class_ctors;
+
+ // Actually write out the class definition
+
+ Multiwrite(this_class_def);
+
+ Setattr(n, "ocaml:ctor", mangled_name);
+
+ return rv;
+ }
+
+ String *normalizeTemplatedClassName(String *name) {
+ String *name_normalized = SwigType_typedef_resolve_all(name);
+ bool took_action;
+
+ do {
+ took_action = false;
+
+ if (is_a_pointer(name_normalized)) {
+ SwigType_del_pointer(name_normalized);
+ took_action = true;
+ }
+
+ if (is_a_reference(name_normalized)) {
+ oc_SwigType_del_reference(name_normalized);
+ took_action = true;
+ }
+
+ if (is_an_array(name_normalized)) {
+ oc_SwigType_del_array(name_normalized);
+ took_action = true;
+ }
+ } while (took_action);
+
+ return SwigType_str(name_normalized, 0);
+ }
+
+ /*
+ * Produce the symbol name that ocaml will use when referring to the
+ * target item. I wonder if there's a better way to do this:
+ *
+ * I shudder to think about doing it with a hash lookup, but that would
+ * make a couple of things easier:
+ */
+
+ String *mangleNameForCaml(String *s) {
+ String *out = Copy(s);
+ Replaceall(out, " ", "_xx");
+ Replaceall(out, "::", "_xx");
+ Replaceall(out, ",", "_x");
+ Replaceall(out, "+", "_xx_plus");
+ Replaceall(out, "-", "_xx_minus");
+ Replaceall(out, "<", "_xx_ldbrace");
+ Replaceall(out, ">", "_xx_rdbrace");
+ Replaceall(out, "!", "_xx_not");
+ Replaceall(out, "%", "_xx_mod");
+ Replaceall(out, "^", "_xx_xor");
+ Replaceall(out, "*", "_xx_star");
+ Replaceall(out, "&", "_xx_amp");
+ Replaceall(out, "|", "_xx_or");
+ Replaceall(out, "(", "_xx_lparen");
+ Replaceall(out, ")", "_xx_rparen");
+ Replaceall(out, "[", "_xx_lbrace");
+ Replaceall(out, "]", "_xx_rbrace");
+ Replaceall(out, "~", "_xx_bnot");
+ Replaceall(out, "=", "_xx_equals");
+ Replaceall(out, "/", "_xx_slash");
+ Replaceall(out, ".", "_xx_dot");
+ return out;
+ }
+
+ SwigType *fully_qualified_enum_type(Node *n) {
+ Node *parent = 0;
+ String *fully_qualified_name = NewString("");
+ String *parent_type = 0;
+
+ parent = parentNode(n);
+ while (parent) {
+ parent_type = nodeType(parent);
+ if (Getattr(parent, "name")) {
+ String *parent_copy = NewStringf("%s::", Getattr(parent, "name"));
+ if (Cmp(parent_type, "class") == 0 || Cmp(parent_type, "namespace") == 0)
+ Insert(fully_qualified_name, 0, parent_copy);
+ Delete(parent_copy);
+ }
+ if (!Cmp(parent_type, "class"))
+ break;
+ parent = parentNode(parent);
+ }
+
+ return fully_qualified_name;
+ }
+
+ /* Benedikt Grundmann inspired --> Enum wrap styles */
+
+ int enumvalueDeclaration(Node *n) {
+ String *name = Getattr(n, "name");
+ SwigType *qtype = 0;
+
+ if (name_qualifier_type) {
+ qtype = Copy(name_qualifier_type);
+ Printv(qtype, name, NIL);
+ }
+
+ if (const_enum && qtype && name && !Getattr(seen_enumvalues, name)) {
+ Setattr(seen_enumvalues, name, "true");
+ SetFlag(n, "feature:immutable");
+ Setattr(n, "feature:enumvalue", "1"); // this does not appear to be used
+
+ Setattr(n, "qualified:name", SwigType_namestr(qtype));
+
+ String *evname = SwigType_manglestr(qtype);
+ Insert(evname, 0, "SWIG_ENUM_");
+
+ Setattr(n, "feature:enumvname", name);
+ Setattr(n, "feature:symname", evname);
+ Delete(evname);
+ Printf(f_enumtypes_value, "| `%s\n", name);
+
+ return Language::enumvalueDeclaration(n);
+ } else
+ return SWIG_OK;
+ }
+
+ /* -------------------------------------------------------------------
+ * This function is a bit uglier than it deserves.
+ *
+ * I used to direct lookup the name of the enum. Now that certain fixes
+ * have been made in other places, the names of enums are now fully
+ * qualified, which is a good thing, overall, but requires me to do
+ * some legwork.
+ *
+ * The other thing that uglifies this function is the varying way that
+ * typedef enum and enum are handled. I need to produce consistent names,
+ * which means looking up and registering by typedef and enum name. */
+ int enumDeclaration(Node *n) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ String *name = Getattr(n, "name");
+ if (name) {
+ String *oname = NewString(name);
+ /* name is now fully qualified */
+ String *fully_qualified_name = NewString(name);
+ bool seen_enum = false;
+ if (name_qualifier_type)
+ Delete(name_qualifier_type);
+ char *strip_position;
+ name_qualifier_type = fully_qualified_enum_type(n);
+
+ strip_position = strstr(Char(oname), "::");
+
+ while (strip_position) {
+ strip_position += 2;
+ oname = NewString(strip_position);
+ strip_position = strstr(Char(oname), "::");
+ }
+
+ seen_enum = (Getattr(seen_enums, fully_qualified_name) ? true : false);
+
+ if (!seen_enum) {
+ const_enum = true;
+ Printf(f_enum_to_int, "| `%s -> (match y with\n", oname);
+ Printf(f_int_to_enum, "| `%s -> C_enum (\n", oname);
+ /* * * * A note about enum name resolution * * * *
+ * This code should now work, but I think we can do a bit better.
+ * The problem I'm having is that swig isn't very precise about
+ * typedef name resolution. My opinion is that SwigType_typedef
+ * resolve_all should *always* return the enum tag if one exists,
+ * rather than the admittedly friendlier enclosing typedef.
+ *
+ * This would make one of the cases below unnecessary.
+ * * * */
+ Printf(f_mlbody, "let _ = Callback.register \"%s_marker\" (`%s)\n", fully_qualified_name, oname);
+ if (!strncmp(Char(fully_qualified_name), "enum ", 5)) {
+ String *fq_noenum = NewString(Char(fully_qualified_name) + 5);
+ Printf(f_mlbody,
+ "let _ = Callback.register \"%s_marker\" (`%s)\n" "let _ = Callback.register \"%s_marker\" (`%s)\n", fq_noenum, oname, fq_noenum, name);
+ }
+
+ Printf(f_enumtypes_type, "| `%s\n", oname);
+ Insert(fully_qualified_name, 0, "enum ");
+ Setattr(seen_enums, fully_qualified_name, n);
+ }
+ }
+
+ int ret = Language::enumDeclaration(n);
+
+ if (const_enum) {
+ Printf(f_int_to_enum, "`Int y)\n");
+ Printf(f_enum_to_int, "| `Int x -> Swig.C_int x\n" "| _ -> raise (LabelNotFromThisEnum v))\n");
+ }
+
+ const_enum = false;
+
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------------
+ * BEGIN C++ Director Class modifications
+ * ------------------------------------------------------------------------- */
+
+ /*
+ * Modified polymorphism code for Ocaml language module.
+ *
+ * TODO
+ *
+ * Move some boilerplate code generation to Swig_...() functions.
+ *
+ */
+
+ /* ---------------------------------------------------------------
+ * classDirectorMethod()
+ *
+ * Emit a virtual director method to pass a method call on to the
+ * underlying Python object.
+ *
+ * --------------------------------------------------------------- */
+
+ int classDirectorMethod(Node *n, Node *parent, String *super) {
+ int is_void = 0;
+ int is_pointer = 0;
+ String *storage = Getattr(n, "storage");
+ String *value = Getattr(n, "value");
+ String *decl = Getattr(n, "decl");
+ String *returntype = Getattr(n, "type");
+ String *name = Getattr(n, "name");
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *declaration = NewString("");
+ ParmList *l = Getattr(n, "parms");
+ Wrapper *w = NewWrapper();
+ String *tm;
+ String *wrap_args = NewString("");
+ int status = SWIG_OK;
+ int idx;
+ bool pure_virtual = false;
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+
+ if (Cmp(storage, "virtual") == 0) {
+ if (Cmp(value, "0") == 0) {
+ pure_virtual = true;
+ }
+ }
+ Printf(w->locals, "CAMLparam0();\n");
+
+ /* determine if the method returns a pointer */
+ is_pointer = SwigType_ispointer_return(decl);
+ is_void = (!Cmp(returntype, "void") && !is_pointer);
+
+ /* virtual method definition */
+ String *target;
+ String *pclassname = NewStringf("SwigDirector_%s", classname);
+ String *qualified_name = NewStringf("%s::%s", pclassname, name);
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ /* header declaration */
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Get any exception classes in the throws typemap
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ ParmList *throw_parm_list = 0;
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ Parm *p;
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list)
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+ String *str = SwigType_str(Getattr(p, "type"), 0);
+ Append(w->def, str);
+ Append(declaration, str);
+ Delete(str);
+ }
+ }
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+ /* declare method return value
+ * if the return value is a reference or const reference, a specialized typemap must
+ * handle it, including declaration of c_result ($result).
+ */
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ }
+ } else {
+ String *cres = SwigType_lstr(returntype, "c_result");
+ Printf(w->code, "%s;\n", cres);
+ Delete(cres);
+ }
+ }
+
+ if (ignored_method) {
+ if (!pure_virtual) {
+ String *super_call = Swig_method_call(super, l);
+ if (is_void)
+ Printf(w->code, "%s;\n", super_call);
+ else
+ Printf(w->code, "CAMLreturn_type(%s);\n", super_call);
+ Delete(super_call);
+ } else {
+ Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname),
+ SwigType_namestr(name));
+ }
+ } else {
+ Wrapper_add_local(w, "swig_result", "SWIG_CAMLlocal2(swig_result, args)");
+ /* attach typemaps to arguments (C/C++ -> Ocaml) */
+ String *arglist = NewString("");
+
+ Swig_director_parms_fixup(l);
+
+ Swig_typemap_attach_parms("in", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ Parm *p;
+ int num_arguments = emit_num_arguments(l);
+ int i;
+ char source[256];
+
+ int outputs = 0;
+ if (!is_void)
+ outputs++;
+
+ /* build argument list and type conversion string */
+ for (i = 0, idx = 0, p = l; i < num_arguments; i++) {
+
+ while (Getattr(p, "tmap:ignore")) {
+ p = Getattr(p, "tmap:ignore:next");
+ }
+
+ if (Getattr(p, "tmap:directorargout") != 0)
+ outputs++;
+
+ String *pname = Getattr(p, "name");
+ String *ptype = Getattr(p, "type");
+
+ Putc(',', arglist);
+ if ((tm = Getattr(p, "tmap:directorin")) != 0) {
+ Setattr(p, "emit:directorinput", pname);
+ Replaceall(tm, "$input", pname);
+ Replaceall(tm, "$owner", "0");
+ if (Len(tm) == 0)
+ Append(tm, pname);
+ Printv(wrap_args, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorin:next");
+ continue;
+ } else if (Cmp(ptype, "void")) {
+ /* special handling for pointers to other C++ director classes.
+ * ideally this would be left to a typemap, but there is currently no
+ * way to selectively apply the dynamic_cast<> to classes that have
+ * directors. in other words, the type "SwigDirector_$1_lname" only exists
+ * for classes with directors. we avoid the problem here by checking
+ * module.wrap::directormap, but it's not clear how to get a typemap to
+ * do something similar. perhaps a new default typemap (in addition
+ * to SWIGTYPE) called DIRECTORTYPE?
+ */
+ if (SwigType_ispointer(ptype) || SwigType_isreference(ptype)) {
+ Node *module = Getattr(parent, "module");
+ Node *target = Swig_directormap(module, ptype);
+ sprintf(source, "obj%d", idx++);
+ String *nonconst = 0;
+ /* strip pointer/reference --- should move to Swig/stype.c */
+ String *nptype = NewString(Char(ptype) + 2);
+ /* name as pointer */
+ String *ppname = Copy(pname);
+ if (SwigType_isreference(ptype)) {
+ Insert(ppname, 0, "&");
+ }
+ /* if necessary, cast away const since Python doesn't support it! */
+ if (SwigType_isconst(nptype)) {
+ nonconst = NewStringf("nc_tmp_%s", pname);
+ String *nonconst_i = NewStringf("= const_cast< %s >(%s)", SwigType_lstr(ptype, 0), ppname);
+ Wrapper_add_localv(w, nonconst, SwigType_lstr(ptype, 0), nonconst, nonconst_i, NIL);
+ Delete(nonconst_i);
+ Swig_warning(WARN_LANG_DISCARD_CONST, input_file, line_number,
+ "Target language argument '%s' discards const in director method %s::%s.\n", SwigType_str(ptype, pname),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ } else {
+ nonconst = Copy(ppname);
+ }
+ Delete(nptype);
+ Delete(ppname);
+ String *mangle = SwigType_manglestr(ptype);
+ if (target) {
+ String *director = NewStringf("director_%s", mangle);
+ Wrapper_add_localv(w, director, "Swig::Director *", director, "= 0", NIL);
+ Wrapper_add_localv(w, source, "CAML_VALUE", source, "= Val_unit", NIL);
+ Printf(wrap_args, "%s = dynamic_cast<Swig::Director *>(%s);\n", director, nonconst);
+ Printf(wrap_args, "if (!%s) {\n", director);
+ Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
+ Printf(wrap_args, "} else {\n");
+ Printf(wrap_args, "%s = %s->swig_get_self();\n", source, director);
+ Printf(wrap_args, "}\n");
+ Delete(director);
+ Printv(arglist, source, NIL);
+ } else {
+ Wrapper_add_localv(w, source, "CAML_VALUE", source, "= Val_unit", NIL);
+ Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
+ //Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE_p_%s, 0);\n",
+ // source, nonconst, base);
+ Printv(arglist, source, NIL);
+ }
+ Delete(mangle);
+ Delete(nonconst);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
+ "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(ptype, 0),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_NOWRAP;
+ break;
+ }
+ }
+ p = nextSibling(p);
+ }
+
+ Printv(w->code, "swig_result = Val_unit;\n", 0);
+ Printf(w->code, "args = Val_unit;\n");
+
+ /* wrap complex arguments to values */
+ Printv(w->code, wrap_args, NIL);
+
+ /* pass the method call on to the OCaml object */
+ Printv(w->code,
+ "swig_result = caml_swig_alloc(1,C_list);\n" "SWIG_Store_field(swig_result,0,args);\n" "args = swig_result;\n" "swig_result = Val_unit;\n", 0);
+ Printf(w->code, "static const CAML_VALUE *swig_ocaml_func_val = NULL;\n" "if (!swig_ocaml_func_val) {\n");
+ Printf(w->code, " swig_ocaml_func_val = caml_named_value(\"swig_runmethod\");\n }\n");
+ Printf(w->code, "swig_result = caml_callback3(*swig_ocaml_func_val,swig_get_self(),caml_copy_string(\"%s\"),args);\n", Getattr(n, "name"));
+ /* exception handling */
+ tm = Swig_typemap_lookup("director:except", n, Swig_cresult_name(), 0);
+ if (!tm) {
+ tm = Getattr(n, "feature:director:except");
+ }
+ if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
+ Printf(w->code, "if (!%s) {\n", Swig_cresult_name());
+ Printf(w->code, " CAML_VALUE error = *caml_named_value(\"director_except\");\n");
+ Replaceall(tm, "$error", "error");
+ Printv(w->code, Str(tm), "\n", NIL);
+ Printf(w->code, "}\n");
+ }
+
+ /*
+ * Python method may return a simple object, or a tuple.
+ * for in/out arguments, we have to extract the appropriate values from the
+ * argument list, then marshal everything back to C/C++ (return value and
+ * output arguments).
+ */
+
+ /* marshal return value and other outputs (if any) from value to C/C++
+ * type */
+
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+
+ tm = Swig_typemap_lookup("directorout", n, "c_result", w);
+ if (tm != 0) {
+ Replaceall(tm, "$input", "swig_result");
+ /* TODO check this */
+ if (Getattr(n, "wrap:disown")) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, tm, "\n", NIL);
+ }
+
+ /* marshal outputs */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout")) != 0) {
+ Replaceall(tm, "$result", "swig_result");
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ Delete(arglist);
+ Delete(cleanup);
+ Delete(outarg);
+ }
+
+ /* any existing helper functions to handle this? */
+ if (!is_void) {
+ if (!(ignored_method && !pure_virtual)) {
+ /* A little explanation:
+ * The director_enum test case makes a method whose return type
+ * is an enum type. returntype here is "int". gcc complains
+ * about an implicit enum conversion, and although i don't strictly
+ * agree with it, I'm working on fixing the error:
+ *
+ * Below is what I came up with. It's not great but it should
+ * always essentially work.
+ */
+ if (!SwigType_isreference(returntype)) {
+ Printf(w->code, "CAMLreturn_type((%s)c_result);\n", SwigType_lstr(returntype, ""));
+ } else {
+ Printf(w->code, "CAMLreturn_type(*c_result);\n");
+ }
+ }
+ } else {
+ Printf(w->code, "CAMLreturn0;\n");
+ }
+
+ Printf(w->code, "}\n");
+
+ // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewString("");
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+
+ /* emit the director method */
+ if (status == SWIG_OK) {
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+
+ /* clean up */
+ Delete(wrap_args);
+ Delete(pclassname);
+ DelWrapper(w);
+ return status;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorConstructor(Node *n) {
+ Node *parent = Getattr(n, "parentNode");
+ String *sub = NewString("");
+ String *decl = Getattr(n, "decl");
+ String *supername = Swig_class_name(parent);
+ String *classname = NewString("");
+ Printf(classname, "SwigDirector_%s", supername);
+
+ /* insert self parameter */
+ Parm *p, *q;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms = CopyParmList(superparms);
+ String *type = NewString("CAML_VALUE");
+ p = NewParm(type, NewString("self"), n);
+ q = Copy(p);
+ set_nextSibling(q, superparms);
+ set_nextSibling(p, parms);
+ parms = p;
+
+ if (!Getattr(n, "defaultargs")) {
+ /* constructor */
+ {
+ Wrapper *w = NewWrapper();
+ String *call;
+ String *basetype = Getattr(parent, "classtype");
+ String *target = Swig_method_decl(0, decl, classname, parms, 0);
+ call = Swig_csuperclass_call(0, basetype, superparms);
+ Printf(w->def, "%s::%s: %s, Swig::Director(self) { }", classname, target, call);
+ Delete(target);
+ Wrapper_print(w, f_directors);
+ Delete(call);
+ DelWrapper(w);
+ }
+
+ /* constructor header */
+ {
+ String *target = Swig_method_decl(0, decl, classname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Setattr(n, "parms", q);
+ Language::classDirectorConstructor(n);
+
+ Delete(sub);
+ Delete(classname);
+ Delete(supername);
+ //Delete(parms);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDefaultConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorDefaultConstructor(Node *n) {
+ String *classname;
+ classname = Swig_class_name(n);
+
+ /* insert self parameter */
+ Parm *p, *q;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms = CopyParmList(superparms);
+ String *type = NewString("CAML_VALUE");
+ p = NewParm(type, NewString("self"), n);
+ q = Copy(p);
+ set_nextSibling(p, parms);
+
+ {
+ Wrapper *w = NewWrapper();
+ Printf(w->def, "SwigDirector_%s::SwigDirector_%s(CAML_VALUE self) : Swig::Director(self) { }", classname, classname);
+ Wrapper_print(w, f_directors);
+ DelWrapper(w);
+ }
+ Printf(f_directors_h, " SwigDirector_%s(CAML_VALUE self);\n", classname);
+ Delete(classname);
+ Setattr(n, "parms", q);
+ return Language::classDirectorDefaultConstructor(n);
+ }
+
+ int classDirectorInit(Node *n) {
+ String *declaration = Swig_director_declaration(n);
+ Printf(f_directors_h, "\n" "%s\n" "public:\n", declaration);
+ Delete(declaration);
+ return Language::classDirectorInit(n);
+ }
+
+ int classDirectorEnd(Node *n) {
+ Printf(f_directors_h, "};\n\n");
+ return Language::classDirectorEnd(n);
+ }
+
+ /* ---------------------------------------------------------------------
+ * typedefHandler
+ *
+ * This is here in order to maintain the correct association between
+ * typedef names and enum names.
+ *
+ * Since I implement enums as polymorphic variant tags, I need to call
+ * back into ocaml to evaluate them. This requires a string that can
+ * be generated in the typemaps, and also at SWIG time to be the same
+ * string. The problem that arises is that SWIG variously generates
+ * enum e_name_tag
+ * e_name_tag
+ * e_typedef_name
+ * for
+ * typedef enum e_name_tag { ... } e_typedef_name;
+ *
+ * Since I need these strings to be consistent, I must maintain a correct
+ * association list between typedef and enum names.
+ * --------------------------------------------------------------------- */
+ int typedefHandler(Node *n) {
+ String *type = Getattr(n, "type");
+ Node *enum_node = type ? Getattr(seen_enums, type) : 0;
+ if (enum_node) {
+ String *name = Getattr(enum_node, "name");
+
+ Printf(f_mlbody, "let _ = Callback.register \"%s_marker\" (`%s)\n", Getattr(n, "name"), name);
+
+ }
+ return SWIG_OK;
+ }
+
+ String *runtimeCode() {
+ String *s = Swig_include_sys("ocamlrun.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'ocamlrun.swg'\n");
+ s = NewString("");
+ }
+ return s;
+ }
+
+ String *defaultExternalRuntimeFilename() {
+ return NewString("swigocamlrun.h");
+ }
+};
+
+/* -------------------------------------------------------------------------
+ * swig_ocaml() - Instantiate module
+ * ------------------------------------------------------------------------- */
+
+static Language *new_swig_ocaml() {
+ return new OCAML();
+}
+extern "C" Language *swig_ocaml(void) {
+ return new_swig_ocaml();
+}
diff --git a/contrib/tools/swig/Source/Modules/octave.cxx b/contrib/tools/swig/Source/Modules/octave.cxx
new file mode 100644
index 00000000000..b1769e42a7b
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/octave.cxx
@@ -0,0 +1,1590 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * octave.cxx
+ *
+ * Octave language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+
+static String *global_name = 0;
+static String *op_prefix = 0;
+
+static const char *usage = "\
+Octave Options (available with -octave)\n\
+ -globals <name> - Set <name> used to access C global variables [default: 'cvar']\n\
+ Use '.' to load C global variables into module namespace\n\
+ -opprefix <str> - Prefix <str> for global operator functions [default: 'op_']\n\
+\n";
+
+
+class OCTAVE:public Language {
+private:
+ File *f_begin;
+ File *f_runtime;
+ File *f_header;
+ File *f_doc;
+ File *f_wrappers;
+ File *f_init;
+ File *f_initbeforefunc;
+ File *f_directors;
+ File *f_directors_h;
+ String *s_global_tab;
+ String *s_members_tab;
+ String *class_name;
+
+ int have_constructor;
+ int have_destructor;
+ String *constructor_name;
+
+ Hash *docs;
+
+ void Octave_begin_function(Node *n, File *f, const_String_or_char_ptr cname, const_String_or_char_ptr wname, bool dld) {
+ if (dld) {
+ String *tname = texinfo_name(n, "std::string()");
+ Printf(f, "SWIG_DEFUN( %s, %s, %s ) {", cname, wname, tname);
+ }
+ else {
+ Printf(f, "static octave_value_list %s (const octave_value_list& args, int nargout) {", wname);
+ }
+ }
+
+public:
+ OCTAVE():
+ f_begin(0),
+ f_runtime(0),
+ f_header(0),
+ f_doc(0),
+ f_wrappers(0),
+ f_init(0),
+ f_initbeforefunc(0),
+ f_directors(0),
+ f_directors_h(0),
+ s_global_tab(0),
+ s_members_tab(0),
+ class_name(0),
+ have_constructor(0),
+ have_destructor(0),
+ constructor_name(0),
+ docs(0)
+ {
+ /* Add code to manage protected constructors and directors */
+ director_prot_ctor_code = NewString("");
+ Printv(director_prot_ctor_code,
+ "if ( $comparison ) { /* subclassed */\n",
+ " $director_new \n",
+ "} else {\n", " error(\"accessing abstract class or protected constructor\"); \n", " SWIG_fail;\n", "}\n", NIL);
+
+ enable_cplus_runtime_mode();
+ allow_overloading();
+ director_multiple_inheritance = 1;
+ director_language = 1;
+ docs = NewHash();
+ }
+
+ virtual void main(int argc, char *argv[]) {
+
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ } else if (strcmp(argv[i], "-globals") == 0) {
+ if (argv[i + 1]) {
+ global_name = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-opprefix") == 0) {
+ if (argv[i + 1]) {
+ op_prefix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-cppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]);
+ Swig_mark_arg(i);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ if (!global_name)
+ global_name = NewString("cvar");
+ if (!op_prefix)
+ op_prefix = NewString("op_");
+
+ SWIG_library_directory("octave");
+ Preprocessor_define("SWIGOCTAVE 1", 0);
+ SWIG_config_file("octave.swg");
+ SWIG_typemap_lang("octave");
+ allow_overloading();
+
+ // Octave API is C++, so output must be C++ compatible even when wrapping C code
+ if (!cparse_cplusplus)
+ Swig_cparse_cplusplusout(1);
+ }
+
+ virtual int top(Node *n) {
+ {
+ Node *mod = Getattr(n, "module");
+ if (mod) {
+ Node *options = Getattr(mod, "options");
+ if (options) {
+ int dirprot = 0;
+ if (Getattr(options, "dirprot")) {
+ dirprot = 1;
+ }
+ if (Getattr(options, "nodirprot")) {
+ dirprot = 0;
+ }
+ if (Getattr(options, "directors")) {
+ allow_directors();
+ if (dirprot)
+ allow_dirprot();
+ }
+ }
+ }
+ }
+
+ String *module = Getattr(n, "name");
+ String *outfile = Getattr(n, "outfile");
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ f_runtime = NewString("");
+ f_header = NewString("");
+ f_doc = NewString("");
+ f_wrappers = NewString("");
+ f_init = NewString("");
+ f_initbeforefunc = NewString("");
+ f_directors_h = NewString("");
+ f_directors = NewString("");
+ s_global_tab = NewString("");
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("doc", f_doc);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("initbeforefunc", f_initbeforefunc);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n\n#ifndef SWIGOCTAVE\n#define SWIGOCTAVE\n#endif\n\n");
+
+ Printf(f_runtime, "#define SWIG_name_d \"%s\"\n", module);
+ Printf(f_runtime, "#define SWIG_name %s\n", module);
+
+ Printf(f_runtime, "\n");
+ Printf(f_runtime, "#define SWIG_global_name \"%s\"\n", global_name);
+ Printf(f_runtime, "#define SWIG_op_prefix \"%s\"\n", op_prefix);
+
+ if (directorsEnabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+ Swig_banner(f_directors_h);
+ if (dirprot_mode()) {
+ // Printf(f_directors_h, "#include <map>\n");
+ // Printf(f_directors_h, "#include <string>\n\n");
+ }
+ }
+
+ Printf(f_runtime, "\n");
+
+ Printf(s_global_tab, "\nstatic const struct swig_octave_member swig_globals[] = {\n");
+ Printf(f_init, "static bool SWIG_init_user(octave_swig_type* module_ns)\n{\n");
+
+ if (!CPlusPlus)
+ Printf(f_header,"extern \"C\" {\n");
+
+ Language::top(n);
+
+ if (!CPlusPlus)
+ Printf(f_header,"}\n");
+
+ if (Len(docs))
+ emit_doc_texinfo();
+
+ if (directorsEnabled()) {
+ Swig_insert_file("director_common.swg", f_runtime);
+ Swig_insert_file("director.swg", f_runtime);
+ }
+
+ Printf(f_init, "return true;\n}\n");
+ Printf(s_global_tab, "{0,0,0,0,0,0}\n};\n");
+
+ Printv(f_wrappers, s_global_tab, NIL);
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+ Dump(f_doc, f_begin);
+ if (directorsEnabled()) {
+ Dump(f_directors_h, f_begin);
+ Dump(f_directors, f_begin);
+ }
+ Dump(f_wrappers, f_begin);
+ Dump(f_initbeforefunc, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+
+ Delete(s_global_tab);
+ Delete(f_initbeforefunc);
+ Delete(f_init);
+ Delete(f_wrappers);
+ Delete(f_doc);
+ Delete(f_header);
+ Delete(f_directors);
+ Delete(f_directors_h);
+ Delete(f_runtime);
+ Delete(f_begin);
+
+ return SWIG_OK;
+ }
+
+ String *texinfo_escape(String *_s) {
+ const char* s=(const char*)Data(_s);
+ while (*s&&(*s=='\t'||*s=='\r'||*s=='\n'||*s==' '))
+ ++s;
+ String *r = NewString("");
+ for (int j=0;s[j];++j) {
+ if (s[j] == '\n') {
+ Append(r, "\\n\\\n");
+ } else if (s[j] == '\r') {
+ Append(r, "\\r");
+ } else if (s[j] == '\t') {
+ Append(r, "\\t");
+ } else if (s[j] == '\\') {
+ Append(r, "\\\\");
+ } else if (s[j] == '\'') {
+ Append(r, "\\\'");
+ } else if (s[j] == '\"') {
+ Append(r, "\\\"");
+ } else
+ Putc(s[j], r);
+ }
+ return r;
+ }
+ void emit_doc_texinfo() {
+ for (Iterator it = First(docs); it.key; it = Next(it)) {
+ String *wrap_name = it.key;
+
+ String *synopsis = Getattr(it.item, "synopsis");
+ String *decl_info = Getattr(it.item, "decl_info");
+ String *cdecl_info = Getattr(it.item, "cdecl_info");
+ String *args_info = Getattr(it.item, "args_info");
+
+ String *doc_str = NewString("");
+ Printv(doc_str, synopsis, decl_info, cdecl_info, args_info, NIL);
+ String *escaped_doc_str = texinfo_escape(doc_str);
+
+ if (Len(doc_str)>0) {
+ Printf(f_doc,"static const char* %s_texinfo = ",wrap_name);
+ Printf(f_doc,"\"-*- texinfo -*-\\n\\\n%s", escaped_doc_str);
+ if (Len(decl_info))
+ Printf(f_doc,"\\n\\\n@end deftypefn");
+ Printf(f_doc,"\";\n");
+ }
+
+ Delete(escaped_doc_str);
+ Delete(doc_str);
+ Delete(wrap_name);
+ }
+ Printf(f_doc,"\n");
+ }
+ bool is_empty_doc_node(Node* n) {
+ if (!n)
+ return true;
+ String *synopsis = Getattr(n, "synopsis");
+ String *decl_info = Getattr(n, "decl_info");
+ String *cdecl_info = Getattr(n, "cdecl_info");
+ String *args_info = Getattr(n, "args_info");
+ return !Len(synopsis) && !Len(decl_info) &&
+ !Len(cdecl_info) && !Len(args_info);
+ }
+ String *texinfo_name(Node* n, const char* defval = "0") {
+ String *tname = NewString("");
+ String *iname = Getattr(n, "sym:name");
+ String *wname = Swig_name_wrapper(iname);
+ Node* d = Getattr(docs, wname);
+
+ if (is_empty_doc_node(d))
+ Printf(tname, defval);
+ else
+ Printf(tname, "%s_texinfo", wname);
+
+ return tname;
+ }
+ void process_autodoc(Node *n) {
+ String *iname = Getattr(n, "sym:name");
+ String *name = Getattr(n, "name");
+ String *wname = Swig_name_wrapper(iname);
+ String *str = Getattr(n, "feature:docstring");
+ bool autodoc_enabled = !Cmp(Getattr(n, "feature:autodoc"), "1");
+ Node* d = Getattr(docs, wname);
+ if (!d) {
+ d = NewHash();
+ Setattr(d, "synopsis", NewString(""));
+ Setattr(d, "decl_info", NewString(""));
+ Setattr(d, "cdecl_info", NewString(""));
+ Setattr(d, "args_info", NewString(""));
+ Setattr(docs, wname, d);
+ }
+
+ String *synopsis = Getattr(d, "synopsis");
+ String *decl_info = Getattr(d, "decl_info");
+ // String *cdecl_info = Getattr(d, "cdecl_info");
+ String *args_info = Getattr(d, "args_info");
+
+ // * couldn't we just emit the docs here?
+
+ if (autodoc_enabled) {
+ String *decl_str = NewString("");
+ String *args_str = NewString("");
+ make_autodocParmList(n, decl_str, args_str);
+ Append(decl_info, "@deftypefn {Loadable Function} ");
+
+ SwigType *type = Getattr(n, "type");
+ if (type && Strcmp(type, "void")) {
+ Node *nn = classLookup(Getattr(n, "type"));
+ String *type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
+ Append(decl_info, "@var{retval} = ");
+ Printf(args_str, "%s@var{retval} is of type %s. ", args_str, type_str);
+ Delete(type_str);
+ }
+
+ Append(decl_info, name);
+ Append(decl_info, " (");
+ Append(decl_info, decl_str);
+ Append(decl_info, ")\n");
+ Append(args_info, args_str);
+ Delete(decl_str);
+ Delete(args_str);
+ }
+
+ if (str && Len(str) > 0) {
+ // strip off {} if necessary
+ char *t = Char(str);
+ if (*t == '{') {
+ Delitem(str, 0);
+ Delitem(str, DOH_END);
+ }
+
+ // emit into synopsis section
+ Append(synopsis, str);
+ }
+ }
+
+ virtual int importDirective(Node *n) {
+ String *modname = Getattr(n, "module");
+ if (modname)
+ Printf(f_init, "if (!SWIG_Octave_LoadModule(\"%s\")) return false;\n", modname);
+ return Language::importDirective(n);
+ }
+
+ const char *get_implicitconv_flag(Node *n) {
+ int conv = 0;
+ if (n && GetFlag(n, "feature:implicitconv")) {
+ conv = 1;
+ }
+ return conv ? "SWIG_POINTER_IMPLICIT_CONV" : "0";
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addMissingParameterNames()
+ * For functions that have not had nameless parameters set in the Language class.
+ *
+ * Inputs:
+ * plist - entire parameter list
+ * arg_offset - argument number for first parameter
+ * Side effects:
+ * The "lname" attribute in each parameter in plist will be contain a parameter name
+ * ----------------------------------------------------------------------------- */
+
+ void addMissingParameterNames(Node* n, ParmList *plist, int arg_offset) {
+ Parm *p = plist;
+ int i = arg_offset;
+ while (p) {
+ if (!Getattr(p, "lname")) {
+ String *name = makeParameterName(n, p, i);
+ Setattr(p, "lname", name);
+ Delete(name);
+ }
+ i++;
+ p = nextSibling(p);
+ }
+ }
+
+ void make_autodocParmList(Node *n, String *decl_str, String *args_str) {
+ String *pdocs = 0;
+ ParmList *plist = CopyParmList(Getattr(n, "parms"));
+ Parm *p;
+ Parm *pnext;
+ int arg_num = is_wrapping_class() ? 1 : 0;
+
+ addMissingParameterNames(n, plist, arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms
+
+ Swig_typemap_attach_parms("in", plist, 0);
+ Swig_typemap_attach_parms("doc", plist, 0);
+
+ for (p = plist; p; p = pnext, arg_num++) {
+
+ String *tm = Getattr(p, "tmap:in");
+ if (tm) {
+ pnext = Getattr(p, "tmap:in:next");
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ continue;
+ }
+ } else {
+ pnext = nextSibling(p);
+ }
+
+ String *name = 0;
+ String *type = 0;
+ String *value = 0;
+ String *pdoc = Getattr(p, "tmap:doc");
+ if (pdoc) {
+ name = Getattr(p, "tmap:doc:name");
+ type = Getattr(p, "tmap:doc:type");
+ value = Getattr(p, "tmap:doc:value");
+ }
+
+ String *made_name = 0;
+ if (!name) {
+ name = made_name = makeParameterName(n, p, arg_num);
+ }
+
+ type = type ? type : Getattr(p, "type");
+ value = value ? value : Getattr(p, "value");
+
+ if (SwigType_isvarargs(type))
+ break;
+
+ String *tex_name = NewString("");
+ if (name)
+ Printf(tex_name, "@var{%s}", name);
+ else
+ Printf(tex_name, "@var{?}");
+
+ if (Len(decl_str))
+ Append(decl_str, ", ");
+ Append(decl_str, tex_name);
+
+ if (value) {
+ String *new_value = convertValue(value, Getattr(p, "type"));
+ if (new_value) {
+ value = new_value;
+ } else {
+ Node *lookup = Swig_symbol_clookup(value, 0);
+ if (lookup)
+ value = Getattr(lookup, "sym:name");
+ }
+ Printf(decl_str, " = %s", value);
+ }
+
+ Node *nn = classLookup(Getattr(p, "type"));
+ String *type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
+ Printf(args_str, "%s is of type %s. ", tex_name, type_str);
+
+ Delete(type_str);
+ Delete(tex_name);
+ Delete(made_name);
+ }
+ if (pdocs)
+ Setattr(n, "feature:pdocs", pdocs);
+ Delete(plist);
+ }
+
+ /* ------------------------------------------------------------
+ * convertValue()
+ * Check if string v can be an Octave value literal,
+ * (eg. number or string), or translate it to an Octave literal.
+ * ------------------------------------------------------------ */
+ String *convertValue(String *v, SwigType *t) {
+ if (v && Len(v) > 0) {
+ char fc = (Char(v))[0];
+ if (('0' <= fc && fc <= '9') || '\'' == fc || '"' == fc) {
+ /* number or string (or maybe NULL pointer) */
+ if (SwigType_ispointer(t) && Strcmp(v, "0") == 0)
+ return NewString("None");
+ else
+ return v;
+ }
+ if (Strcmp(v, "NULL") == 0 || Strcmp(v, "nullptr") == 0)
+ return SwigType_ispointer(t) ? NewString("nil") : NewString("0");
+ if (Strcmp(v, "true") == 0 || Strcmp(v, "TRUE") == 0)
+ return NewString("true");
+ if (Strcmp(v, "false") == 0 || Strcmp(v, "FALSE") == 0)
+ return NewString("false");
+ }
+ return 0;
+ }
+
+ virtual int functionWrapper(Node *n) {
+ Parm *p;
+ String *tm;
+ int j;
+
+ String *nodeType = Getattr(n, "nodeType");
+ int constructor = (!Cmp(nodeType, "constructor"));
+ int destructor = (!Cmp(nodeType, "destructor"));
+ String *storage = Getattr(n, "storage");
+
+ bool overloaded = !!Getattr(n, "sym:overloaded");
+ bool last_overload = overloaded && !Getattr(n, "sym:nextSibling");
+ String *iname = Getattr(n, "sym:name");
+ String *wname = Swig_name_wrapper(iname);
+ String *overname = Copy(wname);
+ SwigType *d = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+
+ if (!overloaded && !addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ if (overloaded)
+ Append(overname, Getattr(n, "sym:overname"));
+
+ if (!overloaded || last_overload)
+ process_autodoc(n);
+
+ Wrapper *f = NewWrapper();
+ Octave_begin_function(n, f->def, iname, overname, !overloaded);
+
+ // Start default try block to execute
+ // cleanup code if exception is thrown
+ Printf(f->code, "try {\n");
+
+ emit_parameter_variables(l, f);
+ emit_attach_parmmaps(l, f);
+ Setattr(n, "wrap:parms", l);
+
+ int num_arguments = emit_num_arguments(l);
+ int num_required = emit_num_required(l);
+ int varargs = emit_isvarargs(l);
+ char source[64];
+
+ Printf(f->code, "if (!SWIG_check_num_args(\"%s\",args.length(),%i,%i,%i)) "
+ "{\n SWIG_fail;\n }\n", iname, num_arguments, num_required, varargs);
+
+ if (constructor && num_arguments == 1 && num_required == 1) {
+ if (Cmp(storage, "explicit") == 0) {
+ Node *parent = Swig_methodclass(n);
+ if (GetFlag(parent, "feature:implicitconv")) {
+ String *desc = NewStringf("SWIGTYPE%s", SwigType_manglestr(Getattr(n, "type")));
+ Printf(f->code, "if (SWIG_CheckImplicit(%s)) SWIG_fail;\n", desc);
+ Delete(desc);
+ }
+ }
+ }
+
+ for (j = 0, p = l; j < num_arguments; ++j) {
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+
+ String *tm = Getattr(p, "tmap:in");
+ if (tm) {
+ if (!tm || checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = nextSibling(p);
+ continue;
+ }
+
+ sprintf(source, "args(%d)", j);
+ Setattr(p, "emit:input", source);
+
+ Replaceall(tm, "$source", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+
+ if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+
+ if (Getattr(p, "tmap:in:implicitconv")) {
+ const char *convflag = "0";
+ if (!Getattr(p, "hidden")) {
+ SwigType *ptype = Getattr(p, "type");
+ convflag = get_implicitconv_flag(classLookup(ptype));
+ }
+ Replaceall(tm, "$implicitconv", convflag);
+ Setattr(p, "implicitconv", convflag);
+ }
+
+ String *getargs = NewString("");
+ if (j >= num_required)
+ Printf(getargs, "if (%d<args.length()) {\n%s\n}", j, tm);
+ else
+ Printv(getargs, tm, NIL);
+ Printv(f->code, getargs, "\n", NIL);
+ Delete(getargs);
+
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ } else {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
+ break;
+ }
+ }
+
+ // Check for trailing varargs
+ if (varargs) {
+ if (p && (tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$input", "varargs");
+ Printv(f->code, tm, "\n", NIL);
+ }
+ }
+
+ // Insert constraint checking code
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Insert cleanup code
+ String *cleanup = NewString("");
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ if (Getattr(p, "tmap:freearg:implicitconv")) {
+ const char *convflag = "0";
+ if (!Getattr(p, "hidden")) {
+ SwigType *ptype = Getattr(p, "type");
+ convflag = get_implicitconv_flag(classLookup(ptype));
+ }
+ if (strcmp(convflag, "0") == 0) {
+ tm = 0;
+ }
+ }
+ if (tm && (Len(tm) != 0)) {
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+ Printv(cleanup, tm, "\n", NIL);
+ }
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Insert argument output code
+ String *outarg = NewString("");
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+ Replaceall(tm, "$target", "_outp");
+ Replaceall(tm, "$result", "_outp");
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ int director_method = is_member_director(n) && !is_smart_pointer() && !destructor;
+ if (director_method) {
+ Wrapper_add_local(f, "upcall", "bool upcall = false");
+ Append(f->code, "upcall = !!dynamic_cast<Swig::Director*>(arg1);\n");
+ }
+
+ Setattr(n, "wrap:name", overname);
+
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ Wrapper_add_local(f, "_out", "octave_value_list _out");
+ Wrapper_add_local(f, "_outp", "octave_value_list *_outp=&_out");
+ Wrapper_add_local(f, "_outv", "octave_value _outv");
+
+ // Return the function value
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Replaceall(tm, "$target", "_outv");
+ Replaceall(tm, "$result", "_outv");
+
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "1");
+ else
+ Replaceall(tm, "$owner", "0");
+
+ Printf(f->code, "%s\n", tm);
+ Printf(f->code, "if (_outv.is_defined()) _outp = " "SWIG_Octave_AppendOutput(_outp, _outv);\n");
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), iname);
+ }
+ emit_return_variable(n, d, f);
+
+ Printv(f->code, outarg, NIL);
+ Printv(f->code, cleanup, NIL);
+
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Replaceall(tm, "$result", "_outv");
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+
+ Printf(f->code, "return _out;\n");
+
+ // Execute cleanup code if branched to fail: label
+ Printf(f->code, "fail:\n");
+ Printv(f->code, cleanup, NIL);
+ Printf(f->code, "return octave_value_list();\n");
+
+ // Execute cleanup code if exception was thrown
+ Printf(f->code, "}\n");
+ Printf(f->code, "catch(...) {\n");
+ Printv(f->code, cleanup, NIL);
+ Printf(f->code, "throw;\n");
+ Printf(f->code, "}\n");
+
+ // End wrapper function
+ Printf(f->code, "}\n");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ Replaceall(f->code, "$symname", iname);
+ Wrapper_print(f, f_wrappers);
+ DelWrapper(f);
+
+ if (last_overload)
+ dispatchFunction(n);
+
+ if (!overloaded || last_overload) {
+ String *tname = texinfo_name(n);
+ Printf(s_global_tab, "{\"%s\",%s,0,0,2,%s},\n", iname, wname, tname);
+ Delete(tname);
+ }
+
+ Delete(overname);
+ Delete(wname);
+ Delete(cleanup);
+ Delete(outarg);
+
+ return SWIG_OK;
+ }
+
+ void dispatchFunction(Node *n) {
+ Wrapper *f = NewWrapper();
+
+ String *iname = Getattr(n, "sym:name");
+ String *wname = Swig_name_wrapper(iname);
+ int maxargs;
+ String *dispatch = Swig_overload_dispatch(n, "return %s(args, nargout);", &maxargs);
+ String *tmp = NewString("");
+
+ Octave_begin_function(n, f->def, iname, wname, true);
+ Wrapper_add_local(f, "argc", "int argc = args.length()");
+ Printf(tmp, "octave_value_ref argv[%d]={", maxargs);
+ for (int j = 0; j < maxargs; ++j)
+ Printf(tmp, "%soctave_value_ref(args,%d)", j ? "," : " ", j);
+ Printf(tmp, "}");
+ Wrapper_add_local(f, "argv", tmp);
+ Printv(f->code, dispatch, "\n", NIL);
+ Printf(f->code, "error(\"No matching function for overload\");\n", iname);
+ Printf(f->code, "return octave_value_list();\n");
+ Printv(f->code, "}\n", NIL);
+
+ Wrapper_print(f, f_wrappers);
+ Delete(tmp);
+ DelWrapper(f);
+ Delete(dispatch);
+ Delete(wname);
+ }
+
+ virtual int variableWrapper(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ String *tm;
+ Wrapper *getf = NewWrapper();
+ Wrapper *setf = NewWrapper();
+
+ String *getname = Swig_name_get(NSPACE_TODO, iname);
+ String *setname = Swig_name_set(NSPACE_TODO, iname);
+
+ String *getwname = Swig_name_wrapper(getname);
+ String *setwname = Swig_name_wrapper(setname);
+
+ Octave_begin_function(n, setf->def, setname, setwname, true);
+ Printf(setf->code, "if (!SWIG_check_num_args(\"%s_set\",args.length(),1,1,0)) return octave_value_list();", iname);
+ if (is_assignable(n)) {
+ Setattr(n, "wrap:name", setname);
+ if ((tm = Swig_typemap_lookup("varin", n, name, 0))) {
+ Replaceall(tm, "$source", "args(0)");
+ Replaceall(tm, "$target", name);
+ Replaceall(tm, "$input", "args(0)");
+ if (Getattr(n, "tmap:varin:implicitconv")) {
+ Replaceall(tm, "$implicitconv", get_implicitconv_flag(n));
+ }
+ emit_action_code(n, setf->code, tm);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0));
+ }
+ Append(setf->code, "return octave_value_list();\n");
+ Append(setf->code, "fail:\n");
+ Append(setf->code, "return octave_value_list();\n");
+ } else {
+ Printf(setf->code, "return octave_set_immutable(args,nargout);");
+ }
+ Append(setf->code, "}\n");
+ Wrapper_print(setf, f_wrappers);
+
+ Setattr(n, "wrap:name", getname);
+ int addfail = 0;
+ Octave_begin_function(n, getf->def, getname, getwname, true);
+ Wrapper_add_local(getf, "obj", "octave_value obj");
+ if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
+ Replaceall(tm, "$source", name);
+ Replaceall(tm, "$target", "obj");
+ Replaceall(tm, "$result", "obj");
+ addfail = emit_action_code(n, getf->code, tm);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
+ }
+ Append(getf->code, "return obj;\n");
+ if (addfail) {
+ Append(getf->code, "fail:\n");
+ Append(getf->code, "return octave_value_list();\n");
+ }
+ Append(getf->code, "}\n");
+ Wrapper_print(getf, f_wrappers);
+
+ Printf(s_global_tab, "{\"%s\",0,%s,%s,2,0},\n", iname, getwname, setwname);
+
+ Delete(getwname);
+ Delete(setwname);
+ DelWrapper(setf);
+ DelWrapper(getf);
+
+ return SWIG_OK;
+ }
+
+ virtual int constantWrapper(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *rawval = Getattr(n, "rawval");
+ String *value = rawval ? rawval : Getattr(n, "value");
+ String *cppvalue = Getattr(n, "cppvalue");
+ String *tm;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ if (SwigType_type(type) == T_MPOINTER) {
+ String *wname = Swig_name_wrapper(iname);
+ String *str = SwigType_str(type, wname);
+ Printf(f_header, "static %s = %s;\n", str, value);
+ Delete(str);
+ value = wname;
+ }
+ if ((tm = Swig_typemap_lookup("constcode", n, name, 0))) {
+ Replaceall(tm, "$source", value);
+ Replaceall(tm, "$target", name);
+ Replaceall(tm, "$value", cppvalue ? cppvalue : value);
+ Replaceall(tm, "$nsname", iname);
+ Printf(f_init, "%s\n", tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
+ return SWIG_NOWRAP;
+ }
+
+ return SWIG_OK;
+ }
+
+ virtual int nativeWrapper(Node *n) {
+ return Language::nativeWrapper(n);
+ }
+
+ virtual int enumDeclaration(Node *n) {
+ return Language::enumDeclaration(n);
+ }
+
+ virtual int enumvalueDeclaration(Node *n) {
+ return Language::enumvalueDeclaration(n);
+ }
+
+ virtual int classDeclaration(Node *n) {
+ return Language::classDeclaration(n);
+ }
+
+ virtual int classHandler(Node *n) {
+ have_constructor = 0;
+ have_destructor = 0;
+ constructor_name = 0;
+
+ class_name = Getattr(n, "sym:name");
+
+ if (!addSymbol(class_name, n))
+ return SWIG_ERROR;
+
+ // This is a bug, due to the fact that swig_type -> octave_class mapping
+ // is 1-to-n.
+ static Hash *emitted = NewHash();
+ String *mangled_classname = Swig_name_mangle(Getattr(n, "name"));
+ if (Getattr(emitted, mangled_classname)) {
+ Delete(mangled_classname);
+ return SWIG_NOWRAP;
+ }
+ Setattr(emitted, mangled_classname, "1");
+ Delete(mangled_classname);
+
+ assert(!s_members_tab);
+ s_members_tab = NewString("");
+ Printv(s_members_tab, "static swig_octave_member swig_", class_name, "_members[] = {\n", NIL);
+
+ Language::classHandler(n);
+
+ SwigType *t = Copy(Getattr(n, "name"));
+ SwigType_add_pointer(t);
+
+ // Replace storing a pointer to underlying class with a smart pointer (intended for use with non-intrusive smart pointers)
+ SwigType *smart = Swig_cparse_smartptr(n);
+ String *wrap_class = NewStringf("&_wrap_class_%s", class_name);
+ if (smart) {
+ SwigType_add_pointer(smart);
+ SwigType_remember_clientdata(smart, wrap_class);
+ }
+ //String *wrap_class = NewStringf("&_wrap_class_%s", class_name);
+ SwigType_remember_clientdata(t, wrap_class);
+
+ int use_director = Swig_directorclass(n);
+ if (use_director) {
+ String *nspace = Getattr(n, "sym:nspace");
+ String *cname = Swig_name_disown(nspace, class_name);
+ String *wcname = Swig_name_wrapper(cname);
+ String *cnameshdw = NewStringf("%s_shadow", cname);
+ String *wcnameshdw = Swig_name_wrapper(cnameshdw);
+ Octave_begin_function(n, f_wrappers, cnameshdw, wcnameshdw, true);
+ Printf(f_wrappers, " if (args.length()!=1) {\n");
+ Printf(f_wrappers, " error(\"disown takes no arguments\");\n");
+ Printf(f_wrappers, " return octave_value_list();\n");
+ Printf(f_wrappers, " }\n");
+ Printf(f_wrappers, " %s (args, nargout);\n", wcname);
+ Printf(f_wrappers, " return args;\n");
+ Printf(f_wrappers, "}\n");
+ Printf(s_members_tab, "{\"__disown\",%s,0,0,0,0},\n", wcnameshdw);
+ Delete(wcname);
+ Delete(cname);
+ Delete(wcnameshdw);
+ Delete(cnameshdw);
+ }
+
+ Printf(s_members_tab, "{0,0,0,0,0,0}\n};\n");
+ Printv(f_wrappers, s_members_tab, NIL);
+
+ String *base_class_names = NewString("");
+ String *base_class = NewString("");
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator b;
+ int index = 0;
+ b = First(baselist);
+ while (b.item) {
+ String *bname = Getattr(b.item, "name");
+ if ((!bname) || GetFlag(b.item, "feature:ignore") || (!Getattr(b.item, "module"))) {
+ b = Next(b);
+ continue;
+ }
+
+ String *bname_mangled = SwigType_manglestr(SwigType_add_pointer(Copy(bname)));
+ Printf(base_class_names, "\"%s\",", bname_mangled);
+ Printf(base_class, "0,");
+ b = Next(b);
+ index++;
+ Delete(bname_mangled);
+ }
+ }
+
+ Printv(f_wrappers, "static const char *swig_", class_name, "_base_names[] = {", base_class_names, "0};\n", NIL);
+ Printv(f_wrappers, "static const swig_type_info *swig_", class_name, "_base[] = {", base_class, "0};\n", NIL);
+ Printv(f_wrappers, "static swig_octave_class _wrap_class_", class_name, " = {\"", class_name, "\", &SWIGTYPE", SwigType_manglestr(t), ",", NIL);
+ Printv(f_wrappers, Swig_directorclass(n) ? "1," : "0,", NIL);
+ if (have_constructor) {
+ String *nspace = Getattr(n, "sym:nspace");
+ String *cname = Swig_name_construct(nspace, constructor_name);
+ String *wcname = Swig_name_wrapper(cname);
+ String *tname = texinfo_name(n);
+ Printf(f_wrappers, "%s,%s,", wcname, tname);
+ Delete(tname);
+ Delete(wcname);
+ Delete(cname);
+ } else
+ Printv(f_wrappers, "0,0,", NIL);
+ if (have_destructor) {
+ String *nspace = Getattr(n, "sym:nspace");
+ String *cname = Swig_name_destroy(nspace, class_name);
+ String *wcname = Swig_name_wrapper(cname);
+ Printf(f_wrappers, "%s,", wcname);
+ Delete(wcname);
+ Delete(cname);
+ } else
+ Printv(f_wrappers, "0", ",", NIL);
+ Printf(f_wrappers, "swig_%s_members,swig_%s_base_names,swig_%s_base };\n\n", class_name, class_name, class_name);
+
+ Delete(base_class);
+ Delete(base_class_names);
+ Delete(smart);
+ Delete(t);
+ Delete(s_members_tab);
+ s_members_tab = 0;
+ class_name = 0;
+
+ return SWIG_OK;
+ }
+
+ virtual int memberfunctionHandler(Node *n) {
+ Language::memberfunctionHandler(n);
+
+ assert(s_members_tab);
+ assert(class_name);
+ String *name = Getattr(n, "name");
+ String *iname = GetChar(n, "sym:name");
+ String *realname = iname ? iname : name;
+ String *wname = Getattr(n, "wrap:name");
+ assert(wname);
+
+ if (!Getattr(n, "sym:nextSibling")) {
+ String *tname = texinfo_name(n);
+ String *rname = Copy(wname);
+ bool overloaded = !!Getattr(n, "sym:overloaded");
+ if (overloaded)
+ Delslice(rname, Len(rname) - Len(Getattr(n, "sym:overname")), DOH_END);
+ Printf(s_members_tab, "{\"%s\",%s,0,0,0,%s},\n",
+ realname, rname, tname);
+ Delete(rname);
+ Delete(tname);
+ }
+
+ return SWIG_OK;
+ }
+
+ virtual int membervariableHandler(Node *n) {
+ Setattr(n, "feature:autodoc", "0");
+
+ Language::membervariableHandler(n);
+
+ assert(s_members_tab);
+ assert(class_name);
+ String *symname = Getattr(n, "sym:name");
+ String *getname = Swig_name_get(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname));
+ String *setname = Swig_name_set(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname));
+ String *getwname = Swig_name_wrapper(getname);
+ String *setwname = GetFlag(n, "feature:immutable") ? NewString("octave_set_immutable") : Swig_name_wrapper(setname);
+ assert(s_members_tab);
+
+ Printf(s_members_tab, "{\"%s\",0,%s,%s,0,0},\n", symname, getwname, setwname);
+
+ Delete(getname);
+ Delete(setname);
+ Delete(getwname);
+ Delete(setwname);
+ return SWIG_OK;
+ }
+
+ virtual int constructorHandler(Node *n) {
+ have_constructor = 1;
+ if (!constructor_name)
+ constructor_name = NewString(Getattr(n, "sym:name"));
+
+ int use_director = Swig_directorclass(n);
+ if (use_director) {
+ Parm *parms = Getattr(n, "parms");
+ Parm *self;
+ String *name = NewString("self");
+ String *type = NewString("void");
+ SwigType_add_pointer(type);
+ self = NewParm(type, name, n);
+ Delete(type);
+ Delete(name);
+ Setattr(self, "lname", "self_obj");
+ if (parms)
+ set_nextSibling(self, parms);
+ Setattr(n, "parms", self);
+ Setattr(n, "wrap:self", "1");
+ Setattr(n, "hidden", "1");
+ Delete(self);
+ }
+
+ return Language::constructorHandler(n);
+ }
+
+ virtual int destructorHandler(Node *n) {
+ have_destructor = 1;
+ return Language::destructorHandler(n);
+ }
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ Language::staticmemberfunctionHandler(n);
+
+ assert(s_members_tab);
+ assert(class_name);
+ String *name = Getattr(n, "name");
+ String *iname = GetChar(n, "sym:name");
+ String *realname = iname ? iname : name;
+ String *wname = Getattr(n, "wrap:name");
+ assert(wname);
+
+ if (!Getattr(n, "sym:nextSibling")) {
+ String *tname = texinfo_name(n);
+ String *rname = Copy(wname);
+ bool overloaded = !!Getattr(n, "sym:overloaded");
+ if (overloaded)
+ Delslice(rname, Len(rname) - Len(Getattr(n, "sym:overname")), DOH_END);
+ Printf(s_members_tab, "{\"%s\",%s,0,0,1,%s},\n",
+ realname, rname, tname);
+ Delete(rname);
+ Delete(tname);
+ }
+
+ return SWIG_OK;
+ }
+
+ virtual int memberconstantHandler(Node *n) {
+ return Language::memberconstantHandler(n);
+ }
+
+ virtual int staticmembervariableHandler(Node *n) {
+ Setattr(n, "feature:autodoc", "0");
+
+ Language::staticmembervariableHandler(n);
+
+ if (!GetFlag(n, "wrappedasconstant")) {
+ assert(s_members_tab);
+ assert(class_name);
+ String *symname = Getattr(n, "sym:name");
+ String *getname = Swig_name_get(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname));
+ String *setname = Swig_name_set(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname));
+ String *getwname = Swig_name_wrapper(getname);
+ String *setwname = GetFlag(n, "feature:immutable") ? NewString("octave_set_immutable") : Swig_name_wrapper(setname);
+ assert(s_members_tab);
+
+ Printf(s_members_tab, "{\"%s\",0,%s,%s,1,0},\n", symname, getwname, setwname);
+
+ Delete(getname);
+ Delete(setname);
+ Delete(getwname);
+ Delete(setwname);
+ }
+ return SWIG_OK;
+ }
+
+ int classDirectorInit(Node *n) {
+ String *declaration = Swig_director_declaration(n);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "%s\n", declaration);
+ Printf(f_directors_h, "public:\n");
+ Delete(declaration);
+ return Language::classDirectorInit(n);
+ }
+
+ int classDirectorEnd(Node *n) {
+ Printf(f_directors_h, "};\n\n");
+ return Language::classDirectorEnd(n);
+ }
+
+ int classDirectorConstructor(Node *n) {
+ Node *parent = Getattr(n, "parentNode");
+ String *sub = NewString("");
+ String *decl = Getattr(n, "decl");
+ String *supername = Swig_class_name(parent);
+ String *classname = NewString("");
+ Printf(classname, "SwigDirector_%s", supername);
+
+ // insert self parameter
+ Parm *p;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms = CopyParmList(superparms);
+ String *type = NewString("void");
+ SwigType_add_pointer(type);
+ p = NewParm(type, NewString("self"), n);
+ set_nextSibling(p, parms);
+ parms = p;
+
+ if (!Getattr(n, "defaultargs")) {
+ // constructor
+ {
+ Wrapper *w = NewWrapper();
+ String *call;
+ String *basetype = Getattr(parent, "classtype");
+ String *target = Swig_method_decl(0, decl, classname, parms, 0);
+ call = Swig_csuperclass_call(0, basetype, superparms);
+ Printf(w->def, "%s::%s: %s," "\nSwig::Director(static_cast<%s*>(this)) { \n", classname, target, call, basetype);
+ Append(w->def, "}\n");
+ Delete(target);
+ Wrapper_print(w, f_directors);
+ Delete(call);
+ DelWrapper(w);
+ }
+
+ // constructor header
+ {
+ String *target = Swig_method_decl(0, decl, classname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Delete(sub);
+ Delete(classname);
+ Delete(supername);
+ Delete(parms);
+ return Language::classDirectorConstructor(n);
+ }
+
+ int classDirectorDefaultConstructor(Node *n) {
+ String *classname = Swig_class_name(n);
+ {
+ Wrapper *w = NewWrapper();
+ Printf(w->def, "SwigDirector_%s::SwigDirector_%s(void* self) :"
+ "\nSwig::Director((octave_swig_type*)self,static_cast<%s*>(this)) { \n", classname, classname, classname);
+ Append(w->def, "}\n");
+ Wrapper_print(w, f_directors);
+ DelWrapper(w);
+ }
+ Printf(f_directors_h, " SwigDirector_%s(octave_swig_type* self);\n", classname);
+ Delete(classname);
+ return Language::classDirectorDefaultConstructor(n);
+ }
+
+ int classDirectorMethod(Node *n, Node *parent, String *super) {
+ int is_void = 0;
+ int is_pointer = 0;
+ String *decl = Getattr(n, "decl");
+ String *returntype = Getattr(n, "type");
+ String *name = Getattr(n, "name");
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *declaration = NewString("");
+ ParmList *l = Getattr(n, "parms");
+ Wrapper *w = NewWrapper();
+ String *tm;
+ String *wrap_args = NewString("");
+ String *value = Getattr(n, "value");
+ String *storage = Getattr(n, "storage");
+ bool pure_virtual = false;
+ int status = SWIG_OK;
+ int idx;
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+
+ if (Cmp(storage, "virtual") == 0) {
+ if (Cmp(value, "0") == 0) {
+ pure_virtual = true;
+ }
+ }
+
+ // determine if the method returns a pointer
+ is_pointer = SwigType_ispointer_return(decl);
+ is_void = (!Cmp(returntype, "void") && !is_pointer);
+
+ // virtual method definition
+ String *target;
+ String *pclassname = NewStringf("SwigDirector_%s", classname);
+ String *qualified_name = NewStringf("%s::%s", pclassname, name);
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+
+ // header declaration
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Get any exception classes in the throws typemap
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ ParmList *throw_parm_list = 0;
+
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ Parm *p;
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list)
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+ String *str = SwigType_str(Getattr(p, "type"), 0);
+ Append(w->def, str);
+ Append(declaration, str);
+ Delete(str);
+ }
+ }
+
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+
+ // declare method return value
+ // if the return value is a reference or const reference, a specialized typemap must
+ // handle it, including declaration of c_result ($result).
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ }
+ } else {
+ String *cres = SwigType_lstr(returntype, "c_result");
+ Printf(w->code, "%s;\n", cres);
+ Delete(cres);
+ }
+ }
+
+ if (ignored_method) {
+ if (!pure_virtual) {
+ if (!is_void)
+ Printf(w->code, "return ");
+ String *super_call = Swig_method_call(super, l);
+ Printf(w->code, "%s;\n", super_call);
+ Delete(super_call);
+ } else {
+ Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname),
+ SwigType_namestr(name));
+ }
+ } else {
+ // attach typemaps to arguments (C/C++ -> Octave)
+ String *parse_args = NewString("");
+
+ Swig_director_parms_fixup(l);
+
+ Swig_typemap_attach_parms("in", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ Parm *p;
+
+ int outputs = 0;
+ if (!is_void)
+ outputs++;
+
+ // build argument list and type conversion string
+ p = l;
+ while (p) {
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ if (Getattr(p, "tmap:directorargout") != 0)
+ outputs++;
+
+ String *pname = Getattr(p, "name");
+ String *ptype = Getattr(p, "type");
+ Wrapper_add_local(w, "tmpv", "octave_value tmpv");
+
+ if ((tm = Getattr(p, "tmap:directorin")) != 0) {
+ String *parse = Getattr(p, "tmap:directorin:parse");
+ if (!parse) {
+ Setattr(p, "emit:directorinput", "tmpv");
+ Replaceall(tm, "$input", "tmpv");
+ Replaceall(tm, "$owner", "0");
+ Printv(wrap_args, tm, "\n", NIL);
+ Printf(wrap_args, "args.append(tmpv);\n");
+ Putc('O', parse_args);
+ } else {
+ Append(parse_args, parse);
+ Setattr(p, "emit:directorinput", pname);
+ Replaceall(tm, "$input", pname);
+ Replaceall(tm, "$owner", "0");
+ if (Len(tm) == 0)
+ Append(tm, pname);
+ }
+ p = Getattr(p, "tmap:directorin:next");
+ continue;
+ } else if (Cmp(ptype, "void")) {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
+ "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(ptype, 0),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_NOWRAP;
+ break;
+ }
+ p = nextSibling(p);
+ }
+
+ String *method_name = Getattr(n, "sym:name");
+
+ Printv(w->code, wrap_args, NIL);
+
+ // emit method invocation
+ Wrapper_add_local(w, "args", "octave_value_list args");
+ Wrapper_add_local(w, "out", "octave_value_list out");
+ Wrapper_add_local(w, "idx", "std::list<octave_value_list> idx");
+ Printf(w->code, "idx.push_back(octave_value_list(\"%s\"));\n", method_name);
+ Printf(w->code, "idx.push_back(args);\n");
+ Printf(w->code, "out=swig_get_self()->subsref(\".(\",idx,%d);\n", outputs);
+
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ idx = 0;
+
+ // marshal return value
+ if (!is_void) {
+ Printf(w->code, "if (out.length()<%d) {\n", outputs);
+ Printf(w->code, "Swig::DirectorTypeMismatchException::raise(\"Octave "
+ "method %s.%s failed to return the required number " "of arguments.\");\n", classname, method_name);
+ Printf(w->code, "}\n");
+
+ tm = Swig_typemap_lookup("directorout", n, Swig_cresult_name(), w);
+ if (tm != 0) {
+ char temp[24];
+ sprintf(temp, "out(%d)", idx);
+ Replaceall(tm, "$input", temp);
+ // Replaceall(tm, "$argnum", temp);
+ Replaceall(tm, "$disown", Getattr(n, "wrap:disown") ? "SWIG_POINTER_DISOWN" : "0");
+ if (Getattr(n, "tmap:directorout:implicitconv")) {
+ Replaceall(tm, "$implicitconv", get_implicitconv_flag(n));
+ }
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, tm, "\n", NIL);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s in director method %s::%s (skipping method).\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_ERROR;
+ }
+ }
+ idx++;
+
+ // marshal outputs
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout")) != 0) {
+ char temp[24];
+ sprintf(temp, "out(%d)", idx);
+ Replaceall(tm, "$result", temp);
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ Delete(parse_args);
+ Delete(cleanup);
+ Delete(outarg);
+ }
+
+ if (!is_void) {
+ if (!(ignored_method && !pure_virtual)) {
+ String *rettype = SwigType_str(returntype, 0);
+ if (!SwigType_isreference(returntype)) {
+ Printf(w->code, "return (%s) c_result;\n", rettype);
+ } else {
+ Printf(w->code, "return (%s) *c_result;\n", rettype);
+ }
+ Delete(rettype);
+ }
+ }
+
+ Append(w->code, "}\n");
+
+ // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewString("");
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+ // emit the director method
+ if (status == SWIG_OK) {
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+ // clean up
+ Delete(wrap_args);
+ Delete(pclassname);
+ DelWrapper(w);
+ return status;
+ }
+
+ String *runtimeCode() {
+ String *s = NewString("");
+ String *srun = Swig_include_sys("octrun.swg");
+ if (!srun) {
+ Printf(stderr, "*** Unable to open 'octrun.swg'\n");
+ } else {
+ Append(s, srun);
+ Delete(srun);
+ }
+ return s;
+ }
+
+ String *defaultExternalRuntimeFilename() {
+ return NewString("swigoctaverun.h");
+ }
+};
+
+extern "C" Language *swig_octave(void) {
+ return new OCTAVE();
+}
diff --git a/contrib/tools/swig/Source/Modules/overload.cxx b/contrib/tools/swig/Source/Modules/overload.cxx
new file mode 100644
index 00000000000..5d278107cab
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/overload.cxx
@@ -0,0 +1,866 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * overload.cxx
+ *
+ * This file is used to analyze overloaded functions and methods.
+ * It looks at signatures and tries to gather information for
+ * building a dispatch function.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+
+#define MAX_OVERLOAD 4096
+
+/* Overload "argc" and "argv" */
+String *argv_template_string;
+String *argc_template_string;
+
+struct Overloaded {
+ Node *n; /* Node */
+ int argc; /* Argument count */
+ ParmList *parms; /* Parameters used for overload check */
+ int error; /* Ambiguity error */
+ bool implicitconv_function; /* For ordering implicitconv functions*/
+};
+
+static int fast_dispatch_mode = 0;
+static int cast_dispatch_mode = 0;
+
+/* Set fast_dispatch_mode */
+void Wrapper_fast_dispatch_mode_set(int flag) {
+ fast_dispatch_mode = flag;
+}
+
+void Wrapper_cast_dispatch_mode_set(int flag) {
+ cast_dispatch_mode = flag;
+}
+
+/* -----------------------------------------------------------------------------
+ * mark_implicitconv_function()
+ *
+ * Mark function if it contains an implicitconv type in the parameter list
+ * ----------------------------------------------------------------------------- */
+static void mark_implicitconv_function(Overloaded& onode) {
+ Parm *parms = onode.parms;
+ if (parms) {
+ bool is_implicitconv_function = false;
+ Parm *p = parms;
+ while (p) {
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+ if (GetFlag(p, "implicitconv")) {
+ is_implicitconv_function = true;
+ break;
+ }
+ p = nextSibling(p);
+ }
+ if (is_implicitconv_function)
+ onode.implicitconv_function = true;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_overload_rank()
+ *
+ * This function takes an overloaded declaration and creates a list that ranks
+ * all overloaded methods in an order that can be used to generate a dispatch
+ * function.
+ * Slight difference in the way this function is used by scripting languages and
+ * statically typed languages. The script languages call this method via
+ * Swig_overload_dispatch() - where wrappers for all overloaded methods are generated,
+ * however sometimes the code can never be executed. The non-scripting languages
+ * call this method via Swig_overload_check() for each overloaded method in order
+ * to determine whether or not the method should be wrapped. Note the slight
+ * difference when overloading methods that differ by const only. The
+ * scripting languages will ignore the const method, whereas the non-scripting
+ * languages ignore the first method parsed.
+ * ----------------------------------------------------------------------------- */
+
+List *Swig_overload_rank(Node *n, bool script_lang_wrapping) {
+ Overloaded nodes[MAX_OVERLOAD];
+ int nnodes = 0;
+ Node *o = Getattr(n, "sym:overloaded");
+ Node *c;
+
+ if (!o)
+ return 0;
+
+ c = o;
+ while (c) {
+ if (Getattr(c, "error")) {
+ c = Getattr(c, "sym:nextSibling");
+ continue;
+ }
+ /* if (SmartPointer && Getattr(c,"cplus:staticbase")) {
+ c = Getattr(c,"sym:nextSibling");
+ continue;
+ } */
+
+ /* Make a list of all the declarations (methods) that are overloaded with
+ * this one particular method name */
+ if (Getattr(c, "wrap:name")) {
+ assert(nnodes < MAX_OVERLOAD);
+ nodes[nnodes].n = c;
+ nodes[nnodes].parms = Getattr(c, "wrap:parms");
+ nodes[nnodes].argc = emit_num_required(nodes[nnodes].parms);
+ nodes[nnodes].error = 0;
+ nodes[nnodes].implicitconv_function = false;
+
+ mark_implicitconv_function(nodes[nnodes]);
+ nnodes++;
+ }
+ c = Getattr(c, "sym:nextSibling");
+ }
+
+ /* Sort the declarations by required argument count */
+ {
+ int i, j;
+ for (i = 0; i < nnodes; i++) {
+ for (j = i + 1; j < nnodes; j++) {
+ if (nodes[i].argc > nodes[j].argc) {
+ Overloaded t = nodes[i];
+ nodes[i] = nodes[j];
+ nodes[j] = t;
+ }
+ }
+ }
+ }
+
+ /* Sort the declarations by argument types */
+ {
+ int i, j;
+ for (i = 0; i < nnodes - 1; i++) {
+ if (nodes[i].argc == nodes[i + 1].argc) {
+ for (j = i + 1; (j < nnodes) && (nodes[j].argc == nodes[i].argc); j++) {
+ Parm *p1 = nodes[i].parms;
+ Parm *p2 = nodes[j].parms;
+ int differ = 0;
+ int num_checked = 0;
+ while (p1 && p2 && (num_checked < nodes[i].argc)) {
+ // Printf(stdout,"p1 = '%s', p2 = '%s'\n", Getattr(p1,"type"), Getattr(p2,"type"));
+ if (checkAttribute(p1, "tmap:in:numinputs", "0")) {
+ p1 = Getattr(p1, "tmap:in:next");
+ continue;
+ }
+ if (checkAttribute(p2, "tmap:in:numinputs", "0")) {
+ p2 = Getattr(p2, "tmap:in:next");
+ continue;
+ }
+ String *t1 = Getattr(p1, "tmap:typecheck:precedence");
+ String *t2 = Getattr(p2, "tmap:typecheck:precedence");
+ if ((!t1) && (!nodes[i].error)) {
+ Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n",
+ Swig_name_decl(nodes[i].n), SwigType_str(Getattr(p1, "type"), 0));
+ nodes[i].error = 1;
+ } else if ((!t2) && (!nodes[j].error)) {
+ Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n",
+ Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0));
+ nodes[j].error = 1;
+ }
+ if (t1 && t2) {
+ int t1v, t2v;
+ t1v = atoi(Char(t1));
+ t2v = atoi(Char(t2));
+ differ = t1v - t2v;
+ } else if (!t1 && t2)
+ differ = 1;
+ else if (t1 && !t2)
+ differ = -1;
+ else if (!t1 && !t2)
+ differ = -1;
+ num_checked++;
+ if (differ > 0) {
+ Overloaded t = nodes[i];
+ nodes[i] = nodes[j];
+ nodes[j] = t;
+ break;
+ } else if ((differ == 0) && (Strcmp(t1, "0") == 0)) {
+ t1 = Getattr(p1, "equivtype");
+ t1 = t1 ? t1 : Getattr(p1, "ltype");
+ if (!t1) {
+ t1 = SwigType_ltype(Getattr(p1, "type"));
+ if (Getattr(p1, "tmap:typecheck:SWIGTYPE")) {
+ SwigType_add_pointer(t1);
+ }
+ Setattr(p1, "ltype", t1);
+ }
+ t2 = Getattr(p2, "equivtype");
+ t2 = t2 ? t2 : Getattr(p2, "ltype");
+ if (!t2) {
+ t2 = SwigType_ltype(Getattr(p2, "type"));
+ if (Getattr(p2, "tmap:typecheck:SWIGTYPE")) {
+ SwigType_add_pointer(t2);
+ }
+ Setattr(p2, "ltype", t2);
+ }
+
+ /* Need subtype check here. If t2 is a subtype of t1, then we need to change the
+ order */
+
+ if (SwigType_issubtype(t2, t1)) {
+ Overloaded t = nodes[i];
+ nodes[i] = nodes[j];
+ nodes[j] = t;
+ }
+
+ if (Strcmp(t1, t2) != 0) {
+ differ = 1;
+ break;
+ }
+ } else if (differ) {
+ break;
+ }
+ if (Getattr(p1, "tmap:in:next")) {
+ p1 = Getattr(p1, "tmap:in:next");
+ } else {
+ p1 = nextSibling(p1);
+ }
+ if (Getattr(p2, "tmap:in:next")) {
+ p2 = Getattr(p2, "tmap:in:next");
+ } else {
+ p2 = nextSibling(p2);
+ }
+ }
+ if (!differ) {
+ /* See if declarations differ by const only */
+ String *decl1 = Getattr(nodes[i].n, "decl");
+ String *decl2 = Getattr(nodes[j].n, "decl");
+ if (decl1 && decl2) {
+ /* Remove ref-qualifiers. Note that rvalue ref-qualifiers are already ignored and
+ * it is illegal to overload a function with and without ref-qualifiers. So with
+ * all the combinations of ref-qualifiers and cv-qualifiers, we just detect
+ * the cv-qualifier (const) overloading. */
+ String *d1 = Copy(decl1);
+ String *d2 = Copy(decl2);
+ if (SwigType_isreference(d1) || SwigType_isrvalue_reference(d1)) {
+ Delete(SwigType_pop(d1));
+ }
+ if (SwigType_isreference(d2) || SwigType_isrvalue_reference(d2)) {
+ Delete(SwigType_pop(d2));
+ }
+ String *dq1 = Copy(d1);
+ String *dq2 = Copy(d2);
+ if (SwigType_isconst(d1)) {
+ Delete(SwigType_pop(dq1));
+ }
+ if (SwigType_isconst(d2)) {
+ Delete(SwigType_pop(dq2));
+ }
+ if (Strcmp(dq1, dq2) == 0) {
+
+ if (SwigType_isconst(d1) && !SwigType_isconst(d2)) {
+ if (script_lang_wrapping) {
+ // Swap nodes so that the const method gets ignored (shadowed by the non-const method)
+ Overloaded t = nodes[i];
+ nodes[i] = nodes[j];
+ nodes[j] = t;
+ }
+ differ = 1;
+ if (!nodes[j].error) {
+ if (script_lang_wrapping) {
+ Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n));
+ } else {
+ if (!Getattr(nodes[j].n, "overload:ignore")) {
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using %s instead.\n", Swig_name_decl(nodes[i].n));
+ }
+ }
+ }
+ nodes[j].error = 1;
+ } else if (!SwigType_isconst(d1) && SwigType_isconst(d2)) {
+ differ = 1;
+ if (!nodes[j].error) {
+ if (script_lang_wrapping) {
+ Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n));
+ } else {
+ if (!Getattr(nodes[j].n, "overload:ignore")) {
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using %s instead.\n", Swig_name_decl(nodes[i].n));
+ }
+ }
+ }
+ nodes[j].error = 1;
+ }
+ }
+ Delete(dq1);
+ Delete(dq2);
+ }
+ }
+ if (!differ) {
+ if (!nodes[j].error) {
+ if (script_lang_wrapping) {
+ Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s effectively ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "as it is shadowed by %s.\n", Swig_name_decl(nodes[i].n));
+ } else {
+ if (!Getattr(nodes[j].n, "overload:ignore")) {
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using %s instead.\n", Swig_name_decl(nodes[i].n));
+ }
+ }
+ nodes[j].error = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ List *result = NewList();
+ {
+ int i;
+ int argc_changed_index = -1;
+ for (i = 0; i < nnodes; i++) {
+ if (nodes[i].error)
+ Setattr(nodes[i].n, "overload:ignore", "1");
+ Append(result, nodes[i].n);
+ // Printf(stdout,"[ %d ] %d %s\n", i, nodes[i].implicitconv_function, ParmList_errorstr(nodes[i].parms));
+ // Swig_print_node(nodes[i].n);
+ if (i == nnodes-1 || nodes[i].argc != nodes[i+1].argc) {
+ if (argc_changed_index+2 < nnodes && (nodes[argc_changed_index+1].argc == nodes[argc_changed_index+2].argc)) {
+ // Add additional implicitconv functions in same order as already ranked.
+ // Consider overloaded functions by argument count... only add additional implicitconv functions if
+ // the number of functions with the same arg count > 1, ie, only if overloaded by same argument count.
+ int j;
+ for (j = argc_changed_index + 1; j <= i; j++) {
+ if (nodes[j].implicitconv_function) {
+ SetFlag(nodes[j].n, "implicitconvtypecheckoff");
+ Append(result, nodes[j].n);
+ // Printf(stdout,"[ %d ] %d + %s\n", j, nodes[j].implicitconv_function, ParmList_errorstr(nodes[j].parms));
+ // Swig_print_node(nodes[j].n);
+ }
+ }
+ }
+ argc_changed_index = i;
+ }
+ }
+ }
+ return result;
+}
+
+// /* -----------------------------------------------------------------------------
+// * print_typecheck()
+// * ----------------------------------------------------------------------------- */
+
+static bool print_typecheck(String *f, int j, Parm *pj, bool implicitconvtypecheckoff) {
+ char tmp[256];
+ sprintf(tmp, Char(argv_template_string), j);
+ String *tm = Getattr(pj, "tmap:typecheck");
+ if (tm) {
+ tm = Copy(tm);
+ Replaceid(tm, Getattr(pj, "lname"), "_v");
+ String *conv = Getattr(pj, "implicitconv");
+ if (conv && !implicitconvtypecheckoff) {
+ Replaceall(tm, "$implicitconv", conv);
+ } else {
+ Replaceall(tm, "$implicitconv", "0");
+ }
+ Replaceall(tm, "$input", tmp);
+ Printv(f, tm, "\n", NIL);
+ Delete(tm);
+ return true;
+ } else
+ return false;
+}
+
+/* -----------------------------------------------------------------------------
+ * ReplaceFormat()
+ * ----------------------------------------------------------------------------- */
+
+static String *ReplaceFormat(const_String_or_char_ptr fmt, int j) {
+ String *lfmt = NewString(fmt);
+ char buf[50];
+ sprintf(buf, "%d", j);
+ Replaceall(lfmt, "$numargs", buf);
+ int i;
+ String *commaargs = NewString("");
+ for (i = 0; i < j; i++) {
+ Printv(commaargs, ", ", NIL);
+ Printf(commaargs, Char(argv_template_string), i);
+ }
+ Replaceall(lfmt, "$commaargs", commaargs);
+ return lfmt;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_overload_dispatch()
+ *
+ * Generate a dispatch function. argc is assumed to hold the argument count.
+ * argv is the argument vector.
+ *
+ * Note that for C++ class member functions, Swig_overload_dispatch() assumes
+ * that argc includes the "self" argument and that the first element of argv[]
+ * is the "self" argument. So for a member function:
+ *
+ * Foo::bar(int x, int y, int z);
+ *
+ * the argc should be 4 (not 3!) and the first element of argv[] would be
+ * the appropriate scripting language reference to "self". For regular
+ * functions (and static class functions) the argc and argv only include
+ * the regular function arguments.
+ * ----------------------------------------------------------------------------- */
+
+/*
+ Cast dispatch mechanism.
+*/
+String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int *maxargs) {
+ int i, j;
+
+ *maxargs = 1;
+
+ String *f = NewString("");
+ String *sw = NewString("");
+ Printf(f, "{\n");
+ Printf(f, "unsigned long _index = 0;\n");
+ Printf(f, "SWIG_TypeRank _rank = 0; \n");
+
+ /* Get a list of methods ranked by precedence values and argument count */
+ List *dispatch = Swig_overload_rank(n, true);
+ int nfunc = Len(dispatch);
+
+ /* Loop over the functions */
+
+ bool emitcheck = true;
+ for (i = 0; i < nfunc; i++) {
+ int fn = 0;
+ Node *ni = Getitem(dispatch, i);
+ Parm *pi = Getattr(ni, "wrap:parms");
+ bool implicitconvtypecheckoff = GetFlag(ni, "implicitconvtypecheckoff") != 0;
+ int num_required = emit_num_required(pi);
+ int num_arguments = emit_num_arguments(pi);
+ if (num_arguments > *maxargs)
+ *maxargs = num_arguments;
+
+ if (num_required == num_arguments) {
+ Printf(f, "if (%s == %d) {\n", argc_template_string, num_required);
+ } else {
+ Printf(f, "if ((%s >= %d) && (%s <= %d)) {\n", argc_template_string, num_required, argc_template_string, num_arguments);
+ }
+ Printf(f, "SWIG_TypeRank _ranki = 0;\n");
+ Printf(f, "SWIG_TypeRank _rankm = 0;\n");
+ if (num_arguments)
+ Printf(f, "SWIG_TypeRank _pi = 1;\n");
+
+ /* create a list with the wrappers that collide with the
+ current one based on argument number */
+ List *coll = NewList();
+ for (int k = i + 1; k < nfunc; k++) {
+ Node *nk = Getitem(dispatch, k);
+ Parm *pk = Getattr(nk, "wrap:parms");
+ int nrk = emit_num_required(pk);
+ int nak = emit_num_arguments(pk);
+ if ((nrk >= num_required && nrk <= num_arguments) || (nak >= num_required && nak <= num_arguments) || (nrk <= num_required && nak >= num_arguments))
+ Append(coll, nk);
+ }
+
+ // printf("overload: %s coll=%d\n", Char(Getattr(n, "sym:name")), Len(coll));
+
+ int num_braces = 0;
+ bool test = (num_arguments > 0);
+ if (test) {
+ int need_v = 1;
+ j = 0;
+ Parm *pj = pi;
+ while (pj) {
+ if (checkAttribute(pj, "tmap:in:numinputs", "0")) {
+ pj = Getattr(pj, "tmap:in:next");
+ continue;
+ }
+
+ String *tm = Getattr(pj, "tmap:typecheck");
+ if (tm) {
+ tm = Copy(tm);
+ /* normalise for comparison later */
+ Replaceid(tm, Getattr(pj, "lname"), "_v");
+
+ /* if all the wrappers have the same type check on this
+ argument we can optimize it out */
+ for (int k = 0; k < Len(coll) && !emitcheck; k++) {
+ Node *nk = Getitem(coll, k);
+ Parm *pk = Getattr(nk, "wrap:parms");
+ int nak = emit_num_arguments(pk);
+ if (nak <= j)
+ continue;
+ int l = 0;
+ Parm *pl = pk;
+ /* finds arg j on the collider wrapper */
+ while (pl && l <= j) {
+ if (checkAttribute(pl, "tmap:in:numinputs", "0")) {
+ pl = Getattr(pl, "tmap:in:next");
+ continue;
+ }
+ if (l == j) {
+ /* we are at arg j, so we compare the tmaps now */
+ String *tml = Getattr(pl, "tmap:typecheck");
+ /* normalise it before comparing */
+ if (tml)
+ Replaceid(tml, Getattr(pl, "lname"), "_v");
+ if (!tml || Cmp(tm, tml))
+ emitcheck = true;
+ //printf("tmap: %s[%d] (%d) => %s\n\n",
+ // Char(Getattr(nk, "sym:name")),
+ // l, emitcheck, tml?Char(tml):0);
+ }
+ Parm *pl1 = Getattr(pl, "tmap:in:next");
+ if (pl1)
+ pl = pl1;
+ else
+ pl = nextSibling(pl);
+ l++;
+ }
+ }
+
+ if (emitcheck) {
+ if (need_v) {
+ Printf(f, "int _v = 0;\n");
+ need_v = 0;
+ }
+ if (j >= num_required) {
+ Printf(f, "if (%s > %d) {\n", argc_template_string, j);
+ num_braces++;
+ }
+ String *tmp = NewStringf(argv_template_string, j);
+
+ String *conv = Getattr(pj, "implicitconv");
+ if (conv && !implicitconvtypecheckoff) {
+ Replaceall(tm, "$implicitconv", conv);
+ } else {
+ Replaceall(tm, "$implicitconv", "0");
+ }
+ Replaceall(tm, "$input", tmp);
+ Printv(f, "{\n", tm, "}\n", NIL);
+ Delete(tm);
+ fn = i + 1;
+ Printf(f, "if (!_v) goto check_%d;\n", fn);
+ Printf(f, "_ranki += _v*_pi;\n");
+ Printf(f, "_rankm += _pi;\n");
+ Printf(f, "_pi *= SWIG_MAXCASTRANK;\n");
+ }
+ }
+ if (!Getattr(pj, "tmap:in:SWIGTYPE") && Getattr(pj, "tmap:typecheck:SWIGTYPE")) {
+ /* we emit a warning if the argument defines the 'in' typemap, but not the 'typecheck' one */
+ Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
+ "Overloaded method %s with no explicit typecheck typemap for arg %d of type '%s'\n",
+ Swig_name_decl(n), j, SwigType_str(Getattr(pj, "type"), 0));
+ }
+ Parm *pj1 = Getattr(pj, "tmap:in:next");
+ if (pj1)
+ pj = pj1;
+ else
+ pj = nextSibling(pj);
+ j++;
+ }
+ }
+
+ /* close braces */
+ for ( /* empty */ ; num_braces > 0; num_braces--)
+ Printf(f, "}\n");
+
+ Printf(f, "if (!_index || (_ranki < _rank)) {\n");
+ Printf(f, " _rank = _ranki; _index = %d;\n", i + 1);
+ Printf(f, " if (_rank == _rankm) goto dispatch;\n");
+ Printf(f, "}\n");
+ String *lfmt = ReplaceFormat(fmt, num_arguments);
+ Printf(sw, "case %d:\n", i + 1);
+ Printf(sw, Char(lfmt), Getattr(ni, "wrap:name"));
+ Printf(sw, "\n");
+
+ Printf(f, "}\n"); /* braces closes "if" for this method */
+ if (fn)
+ Printf(f, "check_%d:\n\n", fn);
+
+ if (implicitconvtypecheckoff)
+ Delattr(ni, "implicitconvtypecheckoff");
+
+ Delete(lfmt);
+ Delete(coll);
+ }
+ Delete(dispatch);
+ Printf(f, "dispatch:\n");
+ Printf(f, "switch(_index) {\n");
+ Printf(f, "%s", sw);
+ Printf(f, "}\n");
+
+ Printf(f, "}\n");
+ return f;
+}
+
+/*
+ Fast dispatch mechanism, provided by Salvador Fandi~no Garc'ia (#930586).
+*/
+static String *overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *maxargs, const_String_or_char_ptr fmt_fastdispatch) {
+ int i, j;
+
+ *maxargs = 1;
+
+ String *f = NewString("");
+
+ /* Get a list of methods ranked by precedence values and argument count */
+ List *dispatch = Swig_overload_rank(n, true);
+ int nfunc = Len(dispatch);
+
+ /* Loop over the functions */
+
+ for (i = 0; i < nfunc; i++) {
+ int fn = 0;
+ Node *ni = Getitem(dispatch, i);
+ Parm *pi = Getattr(ni, "wrap:parms");
+ bool implicitconvtypecheckoff = GetFlag(ni, "implicitconvtypecheckoff") != 0;
+ int num_required = emit_num_required(pi);
+ int num_arguments = emit_num_arguments(pi);
+ if (num_arguments > *maxargs)
+ *maxargs = num_arguments;
+
+ if (num_required == num_arguments) {
+ Printf(f, "if (%s == %d) {\n", argc_template_string, num_required);
+ } else {
+ Printf(f, "if ((%s >= %d) && (%s <= %d)) {\n", argc_template_string, num_required, argc_template_string, num_arguments);
+ }
+
+ /* create a list with the wrappers that collide with the
+ current one based on argument number */
+ List *coll = NewList();
+ for (int k = i + 1; k < nfunc; k++) {
+ Node *nk = Getitem(dispatch, k);
+ Parm *pk = Getattr(nk, "wrap:parms");
+ int nrk = emit_num_required(pk);
+ int nak = emit_num_arguments(pk);
+ if ((nrk >= num_required && nrk <= num_arguments) || (nak >= num_required && nak <= num_arguments) || (nrk <= num_required && nak >= num_arguments))
+ Append(coll, nk);
+ }
+
+ // printf("overload: %s coll=%d\n", Char(Getattr(n, "sym:name")), Len(coll));
+
+ bool emitcheck = false;
+ int num_braces = 0;
+ bool test = (Len(coll) > 0 && num_arguments);
+ if (test) {
+ int need_v = 1;
+ j = 0;
+ Parm *pj = pi;
+ while (pj) {
+ if (checkAttribute(pj, "tmap:in:numinputs", "0")) {
+ pj = Getattr(pj, "tmap:in:next");
+ continue;
+ }
+
+ String *tm = Getattr(pj, "tmap:typecheck");
+ if (tm) {
+ tm = Copy(tm);
+ /* normalise for comparison later */
+ Replaceid(tm, Getattr(pj, "lname"), "_v");
+
+ /* if all the wrappers have the same type check on this
+ argument we can optimize it out */
+ emitcheck = false;
+ for (int k = 0; k < Len(coll) && !emitcheck; k++) {
+ Node *nk = Getitem(coll, k);
+ Parm *pk = Getattr(nk, "wrap:parms");
+ int nak = emit_num_arguments(pk);
+ if (nak <= j)
+ continue;
+ int l = 0;
+ Parm *pl = pk;
+ /* finds arg j on the collider wrapper */
+ while (pl && l <= j) {
+ if (checkAttribute(pl, "tmap:in:numinputs", "0")) {
+ pl = Getattr(pl, "tmap:in:next");
+ continue;
+ }
+ if (l == j) {
+ /* we are at arg j, so we compare the tmaps now */
+ String *tml = Getattr(pl, "tmap:typecheck");
+ /* normalise it before comparing */
+ if (tml)
+ Replaceid(tml, Getattr(pl, "lname"), "_v");
+ if (!tml || Cmp(tm, tml))
+ emitcheck = true;
+ //printf("tmap: %s[%d] (%d) => %s\n\n",
+ // Char(Getattr(nk, "sym:name")),
+ // l, emitcheck, tml?Char(tml):0);
+ }
+ Parm *pl1 = Getattr(pl, "tmap:in:next");
+ if (pl1)
+ pl = pl1;
+ else
+ pl = nextSibling(pl);
+ l++;
+ }
+ }
+
+ if (emitcheck) {
+ if (need_v) {
+ Printf(f, "int _v = 0;\n");
+ need_v = 0;
+ }
+ if (j >= num_required) {
+ Printf(f, "if (%s > %d) {\n", argc_template_string, j);
+ num_braces++;
+ }
+ String *tmp = NewStringf(argv_template_string, j);
+
+ String *conv = Getattr(pj, "implicitconv");
+ if (conv && !implicitconvtypecheckoff) {
+ Replaceall(tm, "$implicitconv", conv);
+ } else {
+ Replaceall(tm, "$implicitconv", "0");
+ }
+ Replaceall(tm, "$input", tmp);
+ Printv(f, "{\n", tm, "}\n", NIL);
+ Delete(tm);
+ fn = i + 1;
+ Printf(f, "if (!_v) goto check_%d;\n", fn);
+ }
+ }
+ if (!Getattr(pj, "tmap:in:SWIGTYPE") && Getattr(pj, "tmap:typecheck:SWIGTYPE")) {
+ /* we emit a warning if the argument defines the 'in' typemap, but not the 'typecheck' one */
+ Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
+ "Overloaded method %s with no explicit typecheck typemap for arg %d of type '%s'\n",
+ Swig_name_decl(n), j, SwigType_str(Getattr(pj, "type"), 0));
+ }
+ Parm *pj1 = Getattr(pj, "tmap:in:next");
+ if (pj1)
+ pj = pj1;
+ else
+ pj = nextSibling(pj);
+ j++;
+ }
+ }
+
+ /* close braces */
+ for ( /* empty */ ; num_braces > 0; num_braces--)
+ Printf(f, "}\n");
+
+ // The language module may want to generate different code for last overloaded function called (with same number of arguments)
+ String *lfmt = ReplaceFormat(!emitcheck && fmt_fastdispatch ? fmt_fastdispatch : fmt, num_arguments);
+ Printf(f, Char(lfmt), Getattr(ni, "wrap:name"));
+
+ Printf(f, "}\n"); /* braces closes "if" for this method */
+ if (fn)
+ Printf(f, "check_%d:\n\n", fn);
+
+ if (implicitconvtypecheckoff)
+ Delattr(ni, "implicitconvtypecheckoff");
+
+ Delete(lfmt);
+ Delete(coll);
+ }
+ Delete(dispatch);
+ return f;
+}
+
+String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *maxargs, const_String_or_char_ptr fmt_fastdispatch) {
+
+ if (fast_dispatch_mode || GetFlag(n, "feature:fastdispatch")) {
+ return overload_dispatch_fast(n, fmt, maxargs, fmt_fastdispatch);
+ }
+
+ int i, j;
+
+ *maxargs = 1;
+
+ String *f = NewString("");
+
+ /* Get a list of methods ranked by precedence values and argument count */
+ List *dispatch = Swig_overload_rank(n, true);
+ int nfunc = Len(dispatch);
+
+ /* Loop over the functions */
+
+ for (i = 0; i < nfunc; i++) {
+ Node *ni = Getitem(dispatch, i);
+ Parm *pi = Getattr(ni, "wrap:parms");
+ bool implicitconvtypecheckoff = GetFlag(ni, "implicitconvtypecheckoff") != 0;
+ int num_required = emit_num_required(pi);
+ int num_arguments = emit_num_arguments(pi);
+ if (GetFlag(n, "wrap:this")) {
+ num_required++;
+ num_arguments++;
+ }
+ if (num_arguments > *maxargs)
+ *maxargs = num_arguments;
+
+ if (num_required == num_arguments) {
+ Printf(f, "if (%s == %d) {\n", argc_template_string, num_required);
+ } else {
+ Printf(f, "if ((%s >= %d) && (%s <= %d)) {\n", argc_template_string, num_required, argc_template_string, num_arguments);
+ }
+
+ if (num_arguments) {
+ Printf(f, "int _v;\n");
+ }
+
+ int num_braces = 0;
+ j = 0;
+ Parm *pj = pi;
+ while (pj) {
+ if (checkAttribute(pj, "tmap:in:numinputs", "0")) {
+ pj = Getattr(pj, "tmap:in:next");
+ continue;
+ }
+ if (j >= num_required) {
+ String *lfmt = ReplaceFormat(fmt, num_arguments);
+ Printf(f, "if (%s <= %d) {\n", argc_template_string, j);
+ Printf(f, Char(lfmt), Getattr(ni, "wrap:name"));
+ Printf(f, "}\n");
+ Delete(lfmt);
+ }
+ if (print_typecheck(f, (GetFlag(n, "wrap:this") ? j + 1 : j), pj, implicitconvtypecheckoff)) {
+ Printf(f, "if (_v) {\n");
+ num_braces++;
+ }
+ if (!Getattr(pj, "tmap:in:SWIGTYPE") && Getattr(pj, "tmap:typecheck:SWIGTYPE")) {
+ /* we emit a warning if the argument defines the 'in' typemap, but not the 'typecheck' one */
+ Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
+ "Overloaded method %s with no explicit typecheck typemap for arg %d of type '%s'\n",
+ Swig_name_decl(n), j, SwigType_str(Getattr(pj, "type"), 0));
+ }
+ Parm *pk = Getattr(pj, "tmap:in:next");
+ if (pk)
+ pj = pk;
+ else
+ pj = nextSibling(pj);
+ j++;
+ }
+ String *lfmt = ReplaceFormat(fmt, num_arguments);
+ Printf(f, Char(lfmt), Getattr(ni, "wrap:name"));
+ Delete(lfmt);
+ /* close braces */
+ for ( /* empty */ ; num_braces > 0; num_braces--)
+ Printf(f, "}\n");
+ Printf(f, "}\n"); /* braces closes "if" for this method */
+ if (implicitconvtypecheckoff)
+ Delattr(ni, "implicitconvtypecheckoff");
+ }
+ Delete(dispatch);
+ return f;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_overload_check()
+ * ----------------------------------------------------------------------------- */
+void Swig_overload_check(Node *n) {
+ Swig_overload_rank(n, false);
+}
diff --git a/contrib/tools/swig/Source/Modules/perl5.cxx b/contrib/tools/swig/Source/Modules/perl5.cxx
new file mode 100644
index 00000000000..dfa85f3c8ed
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/perl5.cxx
@@ -0,0 +1,2528 @@
+/* ----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * perl5.cxx
+ *
+ * Perl5 language module for SWIG.
+ * ------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+#include <ctype.h>
+
+static const char *usage = "\
+Perl 5 Options (available with -perl5)\n\
+ -compat - Compatibility mode\n\
+ -const - Wrap constants as constants and not variables (implies -proxy)\n\
+ -nopm - Do not generate the .pm file\n\
+ -noproxy - Don't create proxy classes\n\
+ -proxy - Create proxy classes\n\
+ -static - Omit code related to dynamic loading\n\
+\n";
+
+static int compat = 0;
+
+static int no_pmfile = 0;
+
+static int export_all = 0;
+
+/*
+ * pmfile
+ * set by the -pm flag, overrides the name of the .pm file
+ */
+static String *pmfile = 0;
+
+/*
+ * module
+ * set by the %module directive, e.g. "Xerces". It will determine
+ * the name of the .pm file, and the dynamic library, and the name
+ * used by any module wanting to %import the module.
+ */
+static String *module = 0;
+
+/*
+ * namespace_module
+ * the fully namespace qualified name of the module. It will be used
+ * to set the package namespace in the .pm file, as well as the name
+ * of the initialization methods in the glue library. This will be
+ * the same as module, above, unless the %module directive is given
+ * the 'package' option, e.g. %module(package="Foo::Bar") "baz"
+ */
+static String *namespace_module = 0;
+
+/*
+ * cmodule
+ * the namespace of the internal glue code, set to the value of
+ * module with a 'c' appended
+ */
+static String *cmodule = 0;
+
+/*
+ * dest_package
+ * an optional namespace to put all classes into. Specified by using
+ * the %module(package="Foo::Bar") "baz" syntax
+ */
+static String *dest_package = 0;
+
+static String *command_tab = 0;
+static String *constant_tab = 0;
+static String *variable_tab = 0;
+
+static File *f_begin = 0;
+static File *f_runtime = 0;
+static File *f_runtime_h = 0;
+static File *f_header = 0;
+static File *f_wrappers = 0;
+static File *f_directors = 0;
+static File *f_directors_h = 0;
+static File *f_init = 0;
+static File *f_pm = 0;
+static String *pm; /* Package initialization code */
+static String *magic; /* Magic variable wrappers */
+
+static int staticoption = 0;
+
+// controlling verbose output
+static int verbose = 0;
+
+/* The following variables are used to manage Perl5 classes */
+
+static int blessed = 1; /* Enable object oriented features */
+static int do_constants = 0; /* Constant wrapping */
+static List *classlist = 0; /* List of classes */
+static int have_constructor = 0;
+static int have_destructor = 0;
+static int have_data_members = 0;
+static String *class_name = 0; /* Name of the class (what Perl thinks it is) */
+static String *real_classname = 0; /* Real name of C/C++ class */
+static String *fullclassname = 0;
+
+static String *pcode = 0; /* Perl code associated with each class */
+ /* static String *blessedmembers = 0; *//* Member data associated with each class */
+static int member_func = 0; /* Set to 1 when wrapping a member function */
+static String *func_stubs = 0; /* Function stubs */
+static String *const_stubs = 0; /* Constant stubs */
+static int num_consts = 0; /* Number of constants */
+static String *var_stubs = 0; /* Variable stubs */
+static String *exported = 0; /* Exported symbols */
+static String *pragma_include = 0;
+static String *additional_perl_code = 0; /* Additional Perl code from %perlcode %{ ... %} */
+static Hash *operators = 0;
+static int have_operators = 0;
+
+class PERL5:public Language {
+public:
+
+ PERL5():Language () {
+ Clear(argc_template_string);
+ Printv(argc_template_string, "items", NIL);
+ Clear(argv_template_string);
+ Printv(argv_template_string, "ST(%d)", NIL);
+ director_language = 1;
+ }
+
+ /* Test to see if a type corresponds to something wrapped with a shadow class */
+ Node *is_shadow(SwigType *t) {
+ Node *n;
+ n = classLookup(t);
+ /* Printf(stdout,"'%s' --> '%p'\n", t, n); */
+ if (n) {
+ if (!Getattr(n, "perl5:proxy")) {
+ setclassname(n);
+ }
+ return Getattr(n, "perl5:proxy");
+ }
+ return 0;
+ }
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+ int i = 1;
+
+ SWIG_library_directory("perl5");
+
+ for (i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-package") == 0) {
+ Printv(stderr,
+ "*** -package is no longer supported\n*** use the directive '%module A::B::C' in your interface file instead\n*** see the Perl section in the manual for details.\n", NIL);
+ SWIG_exit(EXIT_FAILURE);
+ } else if (strcmp(argv[i], "-interface") == 0) {
+ Printv(stderr,
+ "*** -interface is no longer supported\n*** use the directive '%module A::B::C' in your interface file instead\n*** see the Perl section in the manual for details.\n", NIL);
+ SWIG_exit(EXIT_FAILURE);
+ } else if (strcmp(argv[i], "-exportall") == 0) {
+ export_all = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-static") == 0) {
+ staticoption = 1;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-shadow") == 0) || ((strcmp(argv[i], "-proxy") == 0))) {
+ blessed = 1;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-noproxy") == 0)) {
+ blessed = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-const") == 0) {
+ do_constants = 1;
+ blessed = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nopm") == 0) {
+ no_pmfile = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-pm") == 0) {
+ Swig_mark_arg(i);
+ i++;
+ pmfile = NewString(argv[i]);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i],"-v") == 0) {
+ Swig_mark_arg(i);
+ verbose++;
+ } else if (strcmp(argv[i], "-compat") == 0) {
+ compat = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ } else if (strcmp(argv[i], "-cppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]);
+ Swig_mark_arg(i);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ Preprocessor_define("SWIGPERL 1", 0);
+ // SWIGPERL5 is deprecated, and no longer documented.
+ Preprocessor_define("SWIGPERL5 1", 0);
+ SWIG_typemap_lang("perl5");
+ SWIG_config_file("perl5.swg");
+ allow_overloading();
+ }
+
+ /* ------------------------------------------------------------
+ * top()
+ * ------------------------------------------------------------ */
+
+ virtual int top(Node *n) {
+ /* check if directors are enabled for this module. note: this
+ * is a "master" switch, without which no director code will be
+ * emitted. %feature("director") statements are also required
+ * to enable directors for individual classes or methods.
+ *
+ * use %module(directors="1") modulename at the start of the
+ * interface file to enable director generation.
+ *
+ * TODO: directors are disallowed in conjunction with many command
+ * line options. Some of them are probably safe, but it will take
+ * some effort to validate each one.
+ */
+ {
+ Node *mod = Getattr(n, "module");
+ if (mod) {
+ Node *options = Getattr(mod, "options");
+ if (options) {
+ int dirprot = 0;
+ if (Getattr(options, "dirprot"))
+ dirprot = 1;
+ if (Getattr(options, "nodirprot"))
+ dirprot = 0;
+ if (Getattr(options, "directors")) {
+ int allow = 1;
+ if (export_all) {
+ Printv(stderr, "*** directors are not supported with -exportall\n", NIL);
+ allow = 0;
+ }
+ if (staticoption) {
+ Printv(stderr, "*** directors are not supported with -static\n", NIL);
+ allow = 0;
+ }
+ if (!blessed) {
+ Printv(stderr, "*** directors are not supported with -noproxy\n", NIL);
+ allow = 0;
+ }
+ if (no_pmfile) {
+ Printv(stderr, "*** directors are not supported with -nopm\n", NIL);
+ allow = 0;
+ }
+ if (compat) {
+ Printv(stderr, "*** directors are not supported with -compat\n", NIL);
+ allow = 0;
+ }
+ if (allow) {
+ allow_directors();
+ if (dirprot)
+ allow_dirprot();
+ }
+ }
+ }
+ }
+ }
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+ String *outfile_h = Getattr(n, "outfile_h");
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+ f_directors_h = NewString("");
+ f_directors = NewString("");
+
+ if (directorsEnabled()) {
+ f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
+ if (!f_runtime_h) {
+ FileErrorDisplay(outfile_h);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+
+ classlist = NewList();
+
+ pm = NewString("");
+ func_stubs = NewString("");
+ var_stubs = NewString("");
+ const_stubs = NewString("");
+ exported = NewString("");
+ magic = NewString("");
+ pragma_include = NewString("");
+ additional_perl_code = NewString("");
+
+ command_tab = NewString("static swig_command_info swig_commands[] = {\n");
+ constant_tab = NewString("static swig_constant_info swig_constants[] = {\n");
+ variable_tab = NewString("static swig_variable_info swig_variables[] = {\n");
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n\n#ifndef SWIGPERL\n#define SWIGPERL\n#endif\n\n");
+
+ if (directorsEnabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+ }
+ Printf(f_runtime, "#define SWIG_CASTRANK_MODE\n");
+ Printf(f_runtime, "\n");
+
+ // Is the imported module in another package? (IOW, does it use the
+ // %module(package="name") option and it's different than the package
+ // of this module.)
+ Node *mod = Getattr(n, "module");
+ Node *options = Getattr(mod, "options");
+ module = Copy(Getattr(n,"name"));
+
+ String *underscore_module = Copy(module);
+ Replaceall(underscore_module,":","_");
+
+ if (verbose > 0) {
+ fprintf(stdout, "top: using namespace_module: %s\n", Char(namespace_module));
+ }
+
+ if (directorsEnabled()) {
+ Swig_banner(f_directors_h);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", underscore_module);
+ Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", underscore_module);
+ if (dirprot_mode()) {
+ Printf(f_directors_h, "#include <map>\n");
+ Printf(f_directors_h, "#include <string>\n\n");
+ }
+
+ Printf(f_directors, "\n\n");
+ Printf(f_directors, "/* ---------------------------------------------------\n");
+ Printf(f_directors, " * C++ director class methods\n");
+ Printf(f_directors, " * --------------------------------------------------- */\n\n");
+ if (outfile_h) {
+ String *filename = Swig_file_filename(outfile_h);
+ Printf(magic, "#include \"%s\"\n\n", filename);
+ Delete(filename);
+ }
+ }
+
+ if (verbose > 0) {
+ fprintf(stdout, "top: using module: %s\n", Char(module));
+ }
+
+ dest_package = options ? Getattr(options, "package") : 0;
+ if (dest_package) {
+ namespace_module = Copy(dest_package);
+ if (verbose > 0) {
+ fprintf(stdout, "top: Found package: %s\n",Char(dest_package));
+ }
+ } else {
+ namespace_module = Copy(module);
+ if (verbose > 0) {
+ fprintf(stdout, "top: No package found\n");
+ }
+ }
+ /* If we're in blessed mode, change the package name to "packagec" */
+
+ if (blessed) {
+ cmodule = NewStringf("%sc",namespace_module);
+ } else {
+ cmodule = NewString(namespace_module);
+ }
+
+ /* Create a .pm file
+ * Need to strip off any prefixes that might be found in
+ * the module name */
+
+ if (no_pmfile) {
+ f_pm = NewString(0);
+ } else {
+ if (!pmfile) {
+ char *m = Char(module) + Len(module);
+ while (m != Char(module)) {
+ if (*m == ':') {
+ m++;
+ break;
+ }
+ m--;
+ }
+ pmfile = NewStringf("%s.pm", m);
+ }
+ String *filen = NewStringf("%s%s", SWIG_output_directory(), pmfile);
+ if ((f_pm = NewFile(filen, "w", SWIG_output_files())) == 0) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(filen);
+ filen = NULL;
+ Swig_register_filebyname("pm", f_pm);
+ Swig_register_filebyname("perl", f_pm);
+ }
+ {
+ String *boot_name = NewStringf("boot_%s", underscore_module);
+ Printf(f_header,"#define SWIG_init %s\n\n", boot_name);
+ Printf(f_header,"#define SWIG_name \"%s::%s\"\n", cmodule, boot_name);
+ Printf(f_header,"#define SWIG_prefix \"%s::\"\n", cmodule);
+ Delete(boot_name);
+ }
+
+ Swig_banner_target_lang(f_pm, "#");
+ Printf(f_pm, "\n");
+
+ Printf(f_pm, "package %s;\n", module);
+
+ /*
+ * If the package option has been given we are placing our
+ * symbols into some other packages namespace, so we do not
+ * mess with @ISA or require for that package
+ */
+ if (dest_package) {
+ Printf(f_pm,"use base qw(DynaLoader);\n");
+ } else {
+ Printf(f_pm,"use base qw(Exporter);\n");
+ if (!staticoption) {
+ Printf(f_pm,"use base qw(DynaLoader);\n");
+ }
+ }
+
+ /* Start creating magic code */
+
+ Printv(magic,
+ "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n",
+ "#ifdef PERL_OBJECT\n",
+ "#define MAGIC_CLASS _wrap_", underscore_module, "_var::\n",
+ "class _wrap_", underscore_module, "_var : public CPerlObj {\n",
+ "public:\n",
+ "#else\n",
+ "#define MAGIC_CLASS\n",
+ "#endif\n",
+ "SWIGCLASS_STATIC int swig_magic_readonly(pTHX_ SV *SWIGUNUSEDPARM(sv), MAGIC *SWIGUNUSEDPARM(mg)) {\n",
+ tab4, "MAGIC_PPERL\n", tab4, "croak(\"Value is read-only.\");\n", tab4, "return 0;\n", "}\n", NIL);
+
+ Printf(f_wrappers, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
+
+ /* emit wrappers */
+ Language::top(n);
+
+ if (directorsEnabled()) {
+ // Insert director runtime into the f_runtime file (make it occur before %header section)
+ Swig_insert_file("director_common.swg", f_runtime);
+ Swig_insert_file("director.swg", f_runtime);
+ }
+
+ String *base = NewString("");
+
+ /* Dump out variable wrappers */
+
+ Printv(magic, "\n\n#ifdef PERL_OBJECT\n", "};\n", "#endif\n", NIL);
+ Printv(magic, "\n#ifdef __cplusplus\n}\n#endif\n", NIL);
+
+ Printf(f_header, "%s\n", magic);
+
+ String *type_table = NewString("");
+
+ /* Patch the type table to reflect the names used by shadow classes */
+ if (blessed) {
+ Iterator cls;
+ for (cls = First(classlist); cls.item; cls = Next(cls)) {
+ String *pname = Getattr(cls.item, "perl5:proxy");
+ if (pname) {
+ SwigType *type = Getattr(cls.item, "classtypeobj");
+ if (!type)
+ continue; /* If unnamed class, no type will be found */
+ type = Copy(type);
+
+ SwigType_add_pointer(type);
+ String *mangled = SwigType_manglestr(type);
+ SwigType_remember_mangleddata(mangled, NewStringf("\"%s\"", pname));
+ Delete(type);
+ Delete(mangled);
+ }
+ }
+ }
+ SwigType_emit_type_table(f_runtime, type_table);
+
+ Printf(f_wrappers, "%s", type_table);
+ Delete(type_table);
+
+ Printf(constant_tab, "{0,0,0,0,0,0}\n};\n");
+ Printv(f_wrappers, constant_tab, NIL);
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n}\n#endif\n");
+
+ Printf(f_init, "\t ST(0) = &PL_sv_yes;\n");
+ Printf(f_init, "\t XSRETURN(1);\n");
+ Printf(f_init, "}\n");
+
+ /* Finish off tables */
+ Printf(variable_tab, "{0,0,0,0}\n};\n");
+ Printv(f_wrappers, variable_tab, NIL);
+
+ Printf(command_tab, "{0,0}\n};\n");
+ Printv(f_wrappers, command_tab, NIL);
+
+
+ Printf(f_pm, "package %s;\n", cmodule);
+
+ if (!staticoption) {
+ Printf(f_pm,"bootstrap %s;\n", module);
+ } else {
+ Printf(f_pm,"package %s;\n", cmodule);
+ Printf(f_pm,"boot_%s();\n", underscore_module);
+ }
+
+ Printf(f_pm, "package %s;\n", module);
+ /*
+ * If the package option has been given we are placing our
+ * symbols into some other packages namespace, so we do not
+ * mess with @EXPORT
+ */
+ if (!dest_package) {
+ Printf(f_pm,"@EXPORT = qw(%s);\n", exported);
+ }
+
+ Printf(f_pm, "%s", pragma_include);
+
+ if (blessed) {
+
+ /*
+ * These methods will be duplicated if package
+ * has been specified, so we do not output them
+ */
+ if (!dest_package) {
+ Printv(base, "\n# ---------- BASE METHODS -------------\n\n", "package ", namespace_module, ";\n\n", NIL);
+
+ /* Write out the TIE method */
+
+ Printv(base, "sub TIEHASH {\n", tab4, "my ($classname,$obj) = @_;\n", tab4, "return bless $obj, $classname;\n", "}\n\n", NIL);
+
+ /* Output a CLEAR method. This is just a place-holder, but by providing it we
+ * can make declarations such as
+ * %$u = ( x => 2, y=>3, z =>4 );
+ *
+ * Where x,y,z are the members of some C/C++ object. */
+
+ Printf(base, "sub CLEAR { }\n\n");
+
+ /* Output default firstkey/nextkey methods */
+
+ Printf(base, "sub FIRSTKEY { }\n\n");
+ Printf(base, "sub NEXTKEY { }\n\n");
+
+ /* Output a FETCH method. This is actually common to all classes */
+ Printv(base,
+ "sub FETCH {\n",
+ tab4, "my ($self,$field) = @_;\n", tab4, "my $member_func = \"swig_${field}_get\";\n", tab4, "$self->$member_func();\n", "}\n\n", NIL);
+
+ /* Output a STORE method. This is also common to all classes (might move to base class) */
+
+ Printv(base,
+ "sub STORE {\n",
+ tab4, "my ($self,$field,$newval) = @_;\n",
+ tab4, "my $member_func = \"swig_${field}_set\";\n", tab4, "$self->$member_func($newval);\n", "}\n\n", NIL);
+
+ /* Output a 'this' method */
+
+ Printv(base, "sub this {\n", tab4, "my $ptr = shift;\n", tab4, "return tied(%$ptr);\n", "}\n\n", NIL);
+
+ Printf(f_pm, "%s", base);
+ }
+
+ /* Emit function stubs for stand-alone functions */
+ Printf(f_pm, "\n# ------- FUNCTION WRAPPERS --------\n\n");
+ Printf(f_pm, "package %s;\n\n", namespace_module);
+ Printf(f_pm, "%s", func_stubs);
+
+ /* Emit package code for different classes */
+ Printf(f_pm, "%s", pm);
+
+ if (num_consts > 0) {
+ /* Emit constant stubs */
+ Printf(f_pm, "\n# ------- CONSTANT STUBS -------\n\n");
+ Printf(f_pm, "package %s;\n\n", namespace_module);
+ Printf(f_pm, "%s", const_stubs);
+ }
+
+ /* Emit variable stubs */
+
+ Printf(f_pm, "\n# ------- VARIABLE STUBS --------\n\n");
+ Printf(f_pm, "package %s;\n\n", namespace_module);
+ Printf(f_pm, "%s", var_stubs);
+ }
+
+ /* Add additional Perl code at the end */
+ Printf(f_pm, "%s", additional_perl_code);
+
+ Printf(f_pm, "1;\n");
+ Delete(f_pm);
+ Delete(base);
+ Delete(dest_package);
+ Delete(underscore_module);
+
+ /* Close all of the files */
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+
+ if (directorsEnabled()) {
+ Dump(f_directors_h, f_runtime_h);
+ Printf(f_runtime_h, "\n");
+ Printf(f_runtime_h, "#endif\n");
+ Dump(f_directors, f_begin);
+ }
+
+ Dump(f_wrappers, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_directors);
+ Delete(f_directors_h);
+ Delete(f_runtime);
+ Delete(f_begin);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * importDirective(Node *n)
+ * ------------------------------------------------------------ */
+
+ virtual int importDirective(Node *n) {
+ if (blessed) {
+ String *modname = Getattr(n, "module");
+ if (modname) {
+ Printf(f_pm, "require %s;\n", modname);
+ }
+ }
+ return Language::importDirective(n);
+ }
+
+ /* ------------------------------------------------------------
+ * functionWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int functionWrapper(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *d = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *overname = 0;
+ int director_method = 0;
+
+ Parm *p;
+ int i;
+ Wrapper *f;
+ char source[256], temp[256];
+ String *tm;
+ String *cleanup, *outarg;
+ int num_saved = 0;
+ int num_arguments, num_required;
+ int varargs = 0;
+
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+ }
+
+ f = NewWrapper();
+ cleanup = NewString("");
+ outarg = NewString("");
+
+ String *wname = Swig_name_wrapper(iname);
+ if (overname) {
+ Append(wname, overname);
+ }
+ Setattr(n, "wrap:name", wname);
+ Printv(f->def, "XS(", wname, ") {\n", "{\n", /* scope to destroy C++ objects before croaking */
+ NIL);
+
+ emit_parameter_variables(l, f);
+ emit_attach_parmmaps(l, f);
+ Setattr(n, "wrap:parms", l);
+
+ num_arguments = emit_num_arguments(l);
+ num_required = emit_num_required(l);
+ varargs = emit_isvarargs(l);
+
+ Wrapper_add_local(f, "argvi", "int argvi = 0");
+
+ /* Check the number of arguments */
+ if (!varargs) {
+ Printf(f->code, " if ((items < %d) || (items > %d)) {\n", num_required, num_arguments);
+ } else {
+ Printf(f->code, " if (items < %d) {\n", num_required);
+ }
+ Printf(f->code, " SWIG_croak(\"Usage: %s\");\n", usage_func(Char(iname), d, l));
+ Printf(f->code, "}\n");
+
+ /* Write code to extract parameters. */
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ /* Skip ignored arguments */
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+
+ /* Produce string representation of source and target arguments */
+ sprintf(source, "ST(%d)", i);
+ String *target = Getattr(p, "lname");
+
+ if (i >= num_required) {
+ Printf(f->code, " if (items > %d) {\n", i);
+ }
+ if ((tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$target", target);
+ Replaceall(tm, "$source", source);
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source); /* Save input location */
+
+ if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+
+ Printf(f->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(pt, 0));
+ p = nextSibling(p);
+ }
+ if (i >= num_required) {
+ Printf(f->code, " }\n");
+ }
+ }
+
+ if (varargs) {
+ if (p && (tm = Getattr(p, "tmap:in"))) {
+ sprintf(source, "ST(%d)", i);
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source);
+ Printf(f->code, "if (items >= %d) {\n", i);
+ Printv(f->code, tm, "\n", NIL);
+ Printf(f->code, "}\n");
+ }
+ }
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ for (i = 0, p = l; p; i++) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert argument output code */
+ num_saved = 0;
+ for (i = 0, p = l; p; i++) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ SwigType *t = Getattr(p, "type");
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+ Replaceall(tm, "$target", "ST(argvi)");
+ Replaceall(tm, "$result", "ST(argvi)");
+ if (is_shadow(t)) {
+ Replaceall(tm, "$shadow", "SWIG_SHADOW");
+ } else {
+ Replaceall(tm, "$shadow", "0");
+ }
+
+ String *in = Getattr(p, "emit:input");
+ if (in) {
+ sprintf(temp, "_saved[%d]", num_saved);
+ Replaceall(tm, "$arg", temp);
+ Replaceall(tm, "$input", temp);
+ Printf(f->code, "_saved[%d] = %s;\n", num_saved, in);
+ num_saved++;
+ }
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* If there were any saved arguments, emit a local variable for them */
+ if (num_saved) {
+ sprintf(temp, "_saved[%d]", num_saved);
+ Wrapper_add_localv(f, "_saved", "SV *", temp, NIL);
+ }
+
+ director_method = is_member_director(n) && !is_smart_pointer() && 0 != Cmp(nodeType(n), "destructor");
+ if (director_method) {
+ Wrapper_add_local(f, "director", "Swig::Director *director = 0");
+ Append(f->code, "director = SWIG_DIRECTOR_CAST(arg1);\n");
+ if (dirprot_mode() && !is_public(n)) {
+ Printf(f->code, "if (!director || !(director->swig_get_inner(\"%s\"))) {\n", name);
+ Printf(f->code, "SWIG_exception_fail(SWIG_RuntimeError, \"accessing protected member %s\");\n", name);
+ Append(f->code, "}\n");
+ }
+ Wrapper_add_local(f, "upcall", "bool upcall = false");
+ Printf(f->code, "upcall = director && SvSTASH(SvRV(ST(0))) == gv_stashpv(director->swig_get_class(), 0);\n");
+ }
+
+ /* Emit the function call */
+ if (director_method) {
+ Append(f->code, "try {\n");
+ }
+
+ /* Now write code to make the function call */
+
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ if (director_method) {
+ Append(actioncode, "} catch (Swig::DirectorException& swig_err) {\n");
+ Append(actioncode, " sv_setsv(ERRSV, swig_err.getNative());\n");
+ Append(actioncode, " SWIG_fail;\n");
+ Append(actioncode, "}\n");
+ }
+
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ SwigType *t = Getattr(n, "type");
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Replaceall(tm, "$target", "ST(argvi)");
+ Replaceall(tm, "$result", "ST(argvi)");
+ if (is_shadow(t)) {
+ Replaceall(tm, "$shadow", "SWIG_SHADOW");
+ } else {
+ Replaceall(tm, "$shadow", "0");
+ }
+ if (GetFlag(n, "feature:new")) {
+ Replaceall(tm, "$owner", "SWIG_OWNER");
+ } else {
+ Replaceall(tm, "$owner", "0");
+ }
+ Printf(f->code, "%s\n", tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name);
+ }
+ emit_return_variable(n, d, f);
+
+ /* If there were any output args, take care of them. */
+
+ Printv(f->code, outarg, NIL);
+
+ /* If there was any cleanup, do that. */
+
+ Printv(f->code, cleanup, NIL);
+
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printf(f->code, "%s\n", tm);
+ }
+
+ if (director_method) {
+ if ((tm = Swig_typemap_lookup("directorfree", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ Replaceall(tm, "$result", "ST(argvi)");
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+ }
+
+ Printv(f->code, "XSRETURN(argvi);\n", "fail:\n", cleanup, "SWIG_croak_null();\n" "}\n" "}\n", NIL);
+
+ /* Add the dXSARGS last */
+
+ Wrapper_add_local(f, "dXSARGS", "dXSARGS");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+ Replaceall(f->code, "$symname", iname);
+
+ /* Dump the wrapper function */
+
+ Wrapper_print(f, f_wrappers);
+
+ /* Now register the function */
+
+ if (!Getattr(n, "sym:overloaded")) {
+ Printf(command_tab, "{\"%s::%s\", %s},\n", cmodule, iname, wname);
+ } else if (!Getattr(n, "sym:nextSibling")) {
+ /* Generate overloaded dispatch function */
+ int maxargs;
+ String *dispatch = Swig_overload_dispatch_cast(n, "PUSHMARK(MARK); SWIG_CALLXS(%s); return;", &maxargs);
+
+ /* Generate a dispatch wrapper for all overloaded functions */
+
+ Wrapper *df = NewWrapper();
+ String *dname = Swig_name_wrapper(iname);
+
+ Printv(df->def, "XS(", dname, ") {\n", NIL);
+
+ Wrapper_add_local(df, "dXSARGS", "dXSARGS");
+ Printv(df->code, dispatch, "\n", NIL);
+ Printf(df->code, "croak(\"No matching function for overloaded '%s'\");\n", iname);
+ Printf(df->code, "XSRETURN(0);\n");
+ Printv(df->code, "}\n", NIL);
+ Wrapper_print(df, f_wrappers);
+ Printf(command_tab, "{\"%s::%s\", %s},\n", cmodule, iname, dname);
+ DelWrapper(df);
+ Delete(dispatch);
+ Delete(dname);
+ }
+ if (!Getattr(n, "sym:nextSibling")) {
+ if (export_all) {
+ Printf(exported, "%s ", iname);
+ }
+
+ /* --------------------------------------------------------------------
+ * Create a stub for this function, provided it's not a member function
+ * -------------------------------------------------------------------- */
+
+ if ((blessed) && (!member_func)) {
+ Printv(func_stubs, "*", iname, " = *", cmodule, "::", iname, ";\n", NIL);
+ }
+
+ }
+ Delete(cleanup);
+ Delete(outarg);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * variableWrapper()
+ * ------------------------------------------------------------ */
+ virtual int variableWrapper(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+ Wrapper *getf, *setf;
+ String *tm;
+ String *getname = Swig_name_get(NSPACE_TODO, iname);
+ String *setname = Swig_name_set(NSPACE_TODO, iname);
+
+ String *get_name = Swig_name_wrapper(getname);
+ String *set_name = Swig_name_wrapper(setname);
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ getf = NewWrapper();
+ setf = NewWrapper();
+
+ /* Create a Perl function for setting the variable value */
+
+ if (!GetFlag(n, "feature:immutable")) {
+ Setattr(n, "wrap:name", set_name);
+ Printf(setf->def, "SWIGCLASS_STATIC int %s(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) {\n", set_name);
+ Printv(setf->code, tab4, "MAGIC_PPERL\n", NIL);
+
+ /* Check for a few typemaps */
+ tm = Swig_typemap_lookup("varin", n, name, 0);
+ if (tm) {
+ Replaceall(tm, "$source", "sv");
+ Replaceall(tm, "$target", name);
+ Replaceall(tm, "$input", "sv");
+ /* Printf(setf->code,"%s\n", tm); */
+ emit_action_code(n, setf->code, tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0));
+ DelWrapper(setf);
+ DelWrapper(getf);
+ return SWIG_NOWRAP;
+ }
+ Printf(setf->code, "fail:\n");
+ Printf(setf->code, " return 1;\n}\n");
+ Replaceall(setf->code, "$symname", iname);
+ Wrapper_print(setf, magic);
+ }
+
+ /* Now write a function to evaluate the variable */
+ Setattr(n, "wrap:name", get_name);
+ int addfail = 0;
+ Printf(getf->def, "SWIGCLASS_STATIC int %s(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) {\n", get_name);
+ Printv(getf->code, tab4, "MAGIC_PPERL\n", NIL);
+
+ if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
+ Replaceall(tm, "$target", "sv");
+ Replaceall(tm, "$result", "sv");
+ Replaceall(tm, "$source", name);
+ if (is_shadow(t)) {
+ Replaceall(tm, "$shadow", "SWIG_SHADOW");
+ } else {
+ Replaceall(tm, "$shadow", "0");
+ }
+ /* Printf(getf->code,"%s\n", tm); */
+ addfail = emit_action_code(n, getf->code, tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
+ DelWrapper(setf);
+ DelWrapper(getf);
+ return SWIG_NOWRAP;
+ }
+ Printf(getf->code, " return 1;\n");
+ if (addfail) {
+ Append(getf->code, "fail:\n");
+ Append(getf->code, " return 0;\n");
+ }
+ Append(getf->code, "}\n");
+
+
+ Replaceall(getf->code, "$symname", iname);
+ Wrapper_print(getf, magic);
+
+ String *tt = Getattr(n, "tmap:varout:type");
+ if (tt) {
+ tt = NewStringf("&%s", tt);
+ } else {
+ tt = NewString("0");
+ }
+ /* Now add symbol to the PERL interpreter */
+ if (GetFlag(n, "feature:immutable")) {
+ Printv(variable_tab, tab4, "{ \"", cmodule, "::", iname, "\", MAGIC_CLASS swig_magic_readonly, MAGIC_CLASS ", get_name, ",", tt, " },\n", NIL);
+
+ } else {
+ Printv(variable_tab, tab4, "{ \"", cmodule, "::", iname, "\", MAGIC_CLASS ", set_name, ", MAGIC_CLASS ", get_name, ",", tt, " },\n", NIL);
+ }
+
+ /* If we're blessed, try to figure out what to do with the variable
+ 1. If it's a Perl object of some sort, create a tied-hash
+ around it.
+ 2. Otherwise, just hack Perl's symbol table */
+
+ if (blessed) {
+ if (is_shadow(t)) {
+ Printv(var_stubs,
+ "\nmy %__", iname, "_hash;\n",
+ "tie %__", iname, "_hash,\"", is_shadow(t), "\", $",
+ cmodule, "::", iname, ";\n", "$", iname, "= \\%__", iname, "_hash;\n", "bless $", iname, ", ", is_shadow(t), ";\n", NIL);
+ } else {
+ Printv(var_stubs, "*", iname, " = *", cmodule, "::", iname, ";\n", NIL);
+ }
+ }
+ if (export_all)
+ Printf(exported, "$%s ", iname);
+
+ Delete(tt);
+ DelWrapper(setf);
+ DelWrapper(getf);
+ Delete(getname);
+ Delete(setname);
+ Delete(set_name);
+ Delete(get_name);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *rawval = Getattr(n, "rawval");
+ String *value = rawval ? rawval : Getattr(n, "value");
+ String *tm;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ /* Special hook for member pointer */
+ if (SwigType_type(type) == T_MPOINTER) {
+ String *wname = Swig_name_wrapper(iname);
+ Printf(f_wrappers, "static %s = %s;\n", SwigType_str(type, wname), value);
+ value = Char(wname);
+ }
+
+ if ((tm = Swig_typemap_lookup("consttab", n, name, 0))) {
+ Replaceall(tm, "$source", value);
+ Replaceall(tm, "$target", name);
+ Replaceall(tm, "$value", value);
+ if (is_shadow(type)) {
+ Replaceall(tm, "$shadow", "SWIG_SHADOW");
+ } else {
+ Replaceall(tm, "$shadow", "0");
+ }
+ Printf(constant_tab, "%s,\n", tm);
+ } else if ((tm = Swig_typemap_lookup("constcode", n, name, 0))) {
+ Replaceall(tm, "$source", value);
+ Replaceall(tm, "$target", name);
+ Replaceall(tm, "$value", value);
+ if (is_shadow(type)) {
+ Replaceall(tm, "$shadow", "SWIG_SHADOW");
+ } else {
+ Replaceall(tm, "$shadow", "0");
+ }
+ Printf(f_init, "%s\n", tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
+ return SWIG_NOWRAP;
+ }
+
+ if (blessed) {
+ if (is_shadow(type)) {
+ Printv(var_stubs,
+ "\nmy %__", iname, "_hash;\n",
+ "tie %__", iname, "_hash,\"", is_shadow(type), "\", $",
+ cmodule, "::", iname, ";\n", "$", iname, "= \\%__", iname, "_hash;\n", "bless $", iname, ", ", is_shadow(type), ";\n", NIL);
+ } else if (do_constants) {
+ Printv(const_stubs, "sub ", name, " () { $", cmodule, "::", name, " }\n", NIL);
+ num_consts++;
+ } else {
+ Printv(var_stubs, "*", iname, " = *", cmodule, "::", iname, ";\n", NIL);
+ }
+ }
+ if (export_all) {
+ if (do_constants && !is_shadow(type)) {
+ Printf(exported, "%s ", name);
+ } else {
+ Printf(exported, "$%s ", iname);
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * usage_func()
+ * ------------------------------------------------------------ */
+ char *usage_func(char *iname, SwigType *, ParmList *l) {
+ static String *temp = 0;
+ Parm *p;
+ int i;
+
+ if (!temp)
+ temp = NewString("");
+ Clear(temp);
+ Printf(temp, "%s(", iname);
+
+ /* Now go through and print parameters */
+ p = l;
+ i = 0;
+ while (p != 0) {
+ SwigType *pt = Getattr(p, "type");
+ String *pn = Getattr(p, "name");
+ if (!checkAttribute(p,"tmap:in:numinputs","0")) {
+ /* If parameter has been named, use that. Otherwise, just print a type */
+ if (SwigType_type(pt) != T_VOID) {
+ if (Len(pn) > 0) {
+ Printf(temp, "%s", pn);
+ } else {
+ Printf(temp, "%s", SwigType_str(pt, 0));
+ }
+ }
+ i++;
+ p = nextSibling(p);
+ if (p)
+ if (!checkAttribute(p,"tmap:in:numinputs","0"))
+ Putc(',', temp);
+ } else {
+ p = nextSibling(p);
+ if (p)
+ if ((i > 0) && (!checkAttribute(p,"tmap:in:numinputs","0")))
+ Putc(',', temp);
+ }
+ }
+ Printf(temp, ");");
+ return Char(temp);
+ }
+
+ /* ------------------------------------------------------------
+ * nativeWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int nativeWrapper(Node *n) {
+ String *name = Getattr(n, "sym:name");
+ String *funcname = Getattr(n, "wrap:name");
+
+ if (!addSymbol(funcname, n))
+ return SWIG_ERROR;
+
+ Printf(command_tab, "{\"%s::%s\", %s},\n", cmodule, name, funcname);
+ if (export_all)
+ Printf(exported, "%s ", name);
+ if (blessed) {
+ Printv(func_stubs, "*", name, " = *", cmodule, "::", name, ";\n", NIL);
+ }
+ return SWIG_OK;
+ }
+
+/* ----------------------------------------------------------------------------
+ * OBJECT-ORIENTED FEATURES
+ *
+ * These extensions provide a more object-oriented interface to C++
+ * classes and structures. The code here is based on extensions
+ * provided by David Fletcher and Gary Holt.
+ *
+ * I have generalized these extensions to make them more general purpose
+ * and to resolve object-ownership problems.
+ *
+ * The approach here is very similar to the Python module :
+ * 1. All of the original methods are placed into a single
+ * package like before except that a 'c' is appended to the
+ * package name.
+ *
+ * 2. All methods and function calls are wrapped with a new
+ * perl function. While possibly inefficient this allows
+ * us to catch complex function arguments (which are hard to
+ * track otherwise).
+ *
+ * 3. Classes are represented as tied-hashes in a manner similar
+ * to Gary Holt's extension. This allows us to access
+ * member data.
+ *
+ * 4. Stand-alone (global) C functions are modified to take
+ * tied hashes as arguments for complex datatypes (if
+ * appropriate).
+ *
+ * 5. Global variables involving a class/struct is encapsulated
+ * in a tied hash.
+ *
+ * ------------------------------------------------------------------------- */
+
+
+ void setclassname(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ String *fullname;
+ String *actualpackage;
+ Node *clsmodule = Getattr(n, "module");
+
+ if (!clsmodule) {
+ /* imported module does not define a module name. Oh well */
+ return;
+ }
+
+ /* Do some work on the class name */
+ if (verbose > 0) {
+ String *modulename = Getattr(clsmodule, "name");
+ fprintf(stdout, "setclassname: Found sym:name: %s\n", Char(symname));
+ fprintf(stdout, "setclassname: Found module: %s\n", Char(modulename));
+ fprintf(stdout, "setclassname: No package found\n");
+ }
+
+ if (dest_package) {
+ fullname = NewStringf("%s::%s", namespace_module, symname);
+ } else {
+ actualpackage = Getattr(clsmodule,"name");
+
+ if (verbose > 0) {
+ fprintf(stdout, "setclassname: Found actualpackage: %s\n", Char(actualpackage));
+ }
+ if ((!compat) && (!Strchr(symname,':'))) {
+ fullname = NewStringf("%s::%s",actualpackage,symname);
+ } else {
+ fullname = NewString(symname);
+ }
+ }
+ if (verbose > 0) {
+ fprintf(stdout, "setclassname: setting proxy: %s\n", Char(fullname));
+ }
+ Setattr(n, "perl5:proxy", fullname);
+ }
+
+ /* ------------------------------------------------------------
+ * classDeclaration()
+ * ------------------------------------------------------------ */
+ virtual int classDeclaration(Node *n) {
+ /* Do some work on the class name */
+ if (!Getattr(n, "feature:onlychildren")) {
+ if (blessed) {
+ setclassname(n);
+ Append(classlist, n);
+ }
+ }
+
+ return Language::classDeclaration(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int classHandler(Node *n) {
+
+ if (blessed) {
+ have_constructor = 0;
+ have_operators = 0;
+ have_destructor = 0;
+ have_data_members = 0;
+ operators = NewHash();
+
+ class_name = Getattr(n, "sym:name");
+
+ if (!addSymbol(class_name, n))
+ return SWIG_ERROR;
+
+ /* Use the fully qualified name of the Perl class */
+ if (!compat) {
+ fullclassname = NewStringf("%s::%s", namespace_module, class_name);
+ } else {
+ fullclassname = NewString(class_name);
+ }
+ real_classname = Getattr(n, "name");
+ pcode = NewString("");
+ // blessedmembers = NewString("");
+ }
+
+ /* Emit all of the members */
+ Language::classHandler(n);
+
+
+ /* Finish the rest of the class */
+ if (blessed) {
+ /* Generate a client-data entry */
+ SwigType *ct = NewStringf("p.%s", real_classname);
+ Printv(f_init, "SWIG_TypeClientData(SWIGTYPE", SwigType_manglestr(ct), ", (void*) \"", fullclassname, "\");\n", NIL);
+ SwigType_remember(ct);
+ Delete(ct);
+
+ Printv(pm, "\n############# Class : ", fullclassname, " ##############\n", "\npackage ", fullclassname, ";\n", NIL);
+
+ if (have_operators) {
+ Printf(pm, "use overload\n");
+ Iterator ki;
+ for (ki = First(operators); ki.key; ki = Next(ki)) {
+ char *name = Char(ki.key);
+ // fprintf(stderr,"found name: <%s>\n", name);
+ if (strstr(name, "__eq__")) {
+ Printv(pm, tab4, "\"==\" => sub { $_[0]->__eq__($_[1])},\n",NIL);
+ } else if (strstr(name, "__ne__")) {
+ Printv(pm, tab4, "\"!=\" => sub { $_[0]->__ne__($_[1])},\n",NIL);
+ // there are no tests for this in operator_overload_runme.pl
+ // it is likely to be broken
+ // } else if (strstr(name, "__assign__")) {
+ // Printv(pm, tab4, "\"=\" => sub { $_[0]->__assign__($_[1])},\n",NIL);
+ } else if (strstr(name, "__str__")) {
+ Printv(pm, tab4, "'\"\"' => sub { $_[0]->__str__()},\n",NIL);
+ } else if (strstr(name, "__plusplus__")) {
+ Printv(pm, tab4, "\"++\" => sub { $_[0]->__plusplus__()},\n",NIL);
+ } else if (strstr(name, "__minmin__")) {
+ Printv(pm, tab4, "\"--\" => sub { $_[0]->__minmin__()},\n",NIL);
+ } else if (strstr(name, "__add__")) {
+ Printv(pm, tab4, "\"+\" => sub { $_[0]->__add__($_[1])},\n",NIL);
+ } else if (strstr(name, "__sub__")) {
+ Printv(pm, tab4, "\"-\" => sub { if( not $_[2] ) { $_[0]->__sub__($_[1]) }\n",NIL);
+ Printv(pm, tab8, "elsif( $_[0]->can('__rsub__') ) { $_[0]->__rsub__($_[1]) }\n",NIL);
+ Printv(pm, tab8, "else { die(\"reverse subtraction not supported\") }\n",NIL);
+ Printv(pm, tab8, "},\n",NIL);
+ } else if (strstr(name, "__mul__")) {
+ Printv(pm, tab4, "\"*\" => sub { $_[0]->__mul__($_[1])},\n",NIL);
+ } else if (strstr(name, "__div__")) {
+ Printv(pm, tab4, "\"/\" => sub { $_[0]->__div__($_[1])},\n",NIL);
+ } else if (strstr(name, "__mod__")) {
+ Printv(pm, tab4, "\"%\" => sub { $_[0]->__mod__($_[1])},\n",NIL);
+ // there are no tests for this in operator_overload_runme.pl
+ // it is likely to be broken
+ // } else if (strstr(name, "__and__")) {
+ // Printv(pm, tab4, "\"&\" => sub { $_[0]->__and__($_[1])},\n",NIL);
+
+ // there are no tests for this in operator_overload_runme.pl
+ // it is likely to be broken
+ // } else if (strstr(name, "__or__")) {
+ // Printv(pm, tab4, "\"|\" => sub { $_[0]->__or__($_[1])},\n",NIL);
+ } else if (strstr(name, "__gt__")) {
+ Printv(pm, tab4, "\">\" => sub { $_[0]->__gt__($_[1])},\n",NIL);
+ } else if (strstr(name, "__ge__")) {
+ Printv(pm, tab4, "\">=\" => sub { $_[0]->__ge__($_[1])},\n",NIL);
+ } else if (strstr(name, "__not__")) {
+ Printv(pm, tab4, "\"!\" => sub { $_[0]->__not__()},\n",NIL);
+ } else if (strstr(name, "__lt__")) {
+ Printv(pm, tab4, "\"<\" => sub { $_[0]->__lt__($_[1])},\n",NIL);
+ } else if (strstr(name, "__le__")) {
+ Printv(pm, tab4, "\"<=\" => sub { $_[0]->__le__($_[1])},\n",NIL);
+ } else if (strstr(name, "__pluseq__")) {
+ Printv(pm, tab4, "\"+=\" => sub { $_[0]->__pluseq__($_[1])},\n",NIL);
+ } else if (strstr(name, "__mineq__")) {
+ Printv(pm, tab4, "\"-=\" => sub { $_[0]->__mineq__($_[1])},\n",NIL);
+ } else if (strstr(name, "__neg__")) {
+ Printv(pm, tab4, "\"neg\" => sub { $_[0]->__neg__()},\n",NIL);
+ } else {
+ fprintf(stderr,"Unknown operator: %s\n", name);
+ }
+ }
+ Printv(pm, tab4,
+ "\"=\" => sub { my $class = ref($_[0]); $class->new($_[0]) },\n", NIL);
+ Printv(pm, tab4, "\"fallback\" => 1;\n", NIL);
+ }
+ // make use strict happy
+ Printv(pm, "use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);\n", NIL);
+
+ /* If we are inheriting from a base class, set that up */
+
+ Printv(pm, "@ISA = qw(", NIL);
+
+ /* Handle inheritance */
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator b;
+ b = First(baselist);
+ while (b.item) {
+ String *bname = Getattr(b.item, "perl5:proxy");
+ if (!bname) {
+ b = Next(b);
+ continue;
+ }
+ Printv(pm, " ", bname, NIL);
+ b = Next(b);
+ }
+ }
+
+ /* Module comes last */
+ if (!compat || Cmp(namespace_module, fullclassname)) {
+ Printv(pm, " ", namespace_module, NIL);
+ }
+
+ Printf(pm, " );\n");
+
+ /* Dump out a hash table containing the pointers that we own */
+ Printf(pm, "%%OWNER = ();\n");
+ if (have_data_members || have_destructor)
+ Printf(pm, "%%ITERATORS = ();\n");
+
+ /* Dump out the package methods */
+
+ Printv(pm, pcode, NIL);
+ Delete(pcode);
+
+ /* Output methods for managing ownership */
+
+ String *director_disown;
+ if (Getattr(n, "perl5:directordisown")) {
+ director_disown = NewStringf("%s%s($self);\n", tab4, Getattr(n, "perl5:directordisown"));
+ } else {
+ director_disown = NewString("");
+ }
+ Printv(pm,
+ "sub DISOWN {\n",
+ tab4, "my $self = shift;\n",
+ director_disown,
+ tab4, "my $ptr = tied(%$self);\n",
+ tab4, "delete $OWNER{$ptr};\n",
+ "}\n\n", "sub ACQUIRE {\n", tab4, "my $self = shift;\n", tab4, "my $ptr = tied(%$self);\n", tab4, "$OWNER{$ptr} = 1;\n", "}\n\n", NIL);
+ Delete(director_disown);
+
+ /* Only output the following methods if a class has member data */
+
+ Delete(operators);
+ operators = 0;
+ if (Swig_directorclass(n)) {
+ /* director classes need a way to recover subclass instance attributes */
+ Node *get_attr = NewHash();
+ String *mrename;
+ String *symname = Getattr(n, "sym:name");
+ mrename = Swig_name_disown(NSPACE_TODO, symname);
+ Replaceall(mrename, "disown", "swig_get_attr");
+ String *type = NewString(getClassType());
+ String *name = NewString("self");
+ SwigType_add_pointer(type);
+ Parm *p = NewParm(type, name, n);
+ Delete(name);
+ Delete(type);
+ type = NewString("SV");
+ SwigType_add_pointer(type);
+ String *action = NewString("");
+ Printv(action, "{\n", " Swig::Director *director = SWIG_DIRECTOR_CAST(arg1);\n",
+ " result = sv_newmortal();\n" " if (director) sv_setsv(result, director->swig_get_self());\n", "}\n", NIL);
+ Setfile(get_attr, Getfile(n));
+ Setline(get_attr, Getline(n));
+ Setattr(get_attr, "wrap:action", action);
+ Setattr(get_attr, "name", mrename);
+ Setattr(get_attr, "sym:name", mrename);
+ Setattr(get_attr, "type", type);
+ Setattr(get_attr, "parms", p);
+ Delete(action);
+ Delete(type);
+ Delete(p);
+
+ member_func = 1;
+ functionWrapper(get_attr);
+ member_func = 0;
+ Delete(get_attr);
+
+ Printv(pm, "sub FETCH {\n", tab4, "my ($self,$field) = @_;\n", tab4, "my $member_func = \"swig_${field}_get\";\n", tab4,
+ "if (not $self->can($member_func)) {\n", tab8, "my $h = ", cmodule, "::", mrename, "($self);\n", tab8, "return $h->{$field} if $h;\n",
+ tab4, "}\n", tab4, "return $self->$member_func;\n", "}\n", "\n", "sub STORE {\n", tab4, "my ($self,$field,$newval) = @_;\n", tab4,
+ "my $member_func = \"swig_${field}_set\";\n", tab4, "if (not $self->can($member_func)) {\n", tab8, "my $h = ", cmodule, "::", mrename,
+ "($self);\n", tab8, "return $h->{$field} = $newval if $h;\n", tab4, "}\n", tab4, "return $self->$member_func($newval);\n", "}\n", NIL);
+
+ Delete(mrename);
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * memberfunctionHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int memberfunctionHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+
+ member_func = 1;
+ Language::memberfunctionHandler(n);
+ member_func = 0;
+
+ if ((blessed) && (!Getattr(n, "sym:nextSibling"))) {
+
+ if (Strstr(symname, "__eq__")) {
+ DohSetInt(operators, "__eq__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__ne__")) {
+ DohSetInt(operators, "__ne__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__assign__")) {
+ DohSetInt(operators, "__assign__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__str__")) {
+ DohSetInt(operators, "__str__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__add__")) {
+ DohSetInt(operators, "__add__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__sub__")) {
+ DohSetInt(operators, "__sub__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__mul__")) {
+ DohSetInt(operators, "__mul__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__div__")) {
+ DohSetInt(operators, "__div__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__mod__")) {
+ DohSetInt(operators, "__mod__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__and__")) {
+ DohSetInt(operators, "__and__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__or__")) {
+ DohSetInt(operators, "__or__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__not__")) {
+ DohSetInt(operators, "__not__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__gt__")) {
+ DohSetInt(operators, "__gt__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__ge__")) {
+ DohSetInt(operators, "__ge__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__lt__")) {
+ DohSetInt(operators, "__lt__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__le__")) {
+ DohSetInt(operators, "__le__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__neg__")) {
+ DohSetInt(operators, "__neg__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__plusplus__")) {
+ DohSetInt(operators, "__plusplus__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__minmin__")) {
+ DohSetInt(operators, "__minmin__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__mineq__")) {
+ DohSetInt(operators, "__mineq__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__pluseq__")) {
+ DohSetInt(operators, "__pluseq__", 1);
+ have_operators = 1;
+ }
+
+ if (Getattr(n, "feature:shadow")) {
+ String *plcode = perlcode(Getattr(n, "feature:shadow"), 0);
+ String *plaction = NewStringf("%s::%s", cmodule, Swig_name_member(NSPACE_TODO, class_name, symname));
+ Replaceall(plcode, "$action", plaction);
+ Delete(plaction);
+ Printv(pcode, plcode, NIL);
+ } else {
+ Printv(pcode, "*", symname, " = *", cmodule, "::", Swig_name_member(NSPACE_TODO, class_name, symname), ";\n", NIL);
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * membervariableHandler()
+ *
+ * Adds an instance member.
+ * ----------------------------------------------------------------------------- */
+
+ virtual int membervariableHandler(Node *n) {
+
+ String *symname = Getattr(n, "sym:name");
+ /* SwigType *t = Getattr(n,"type"); */
+
+ /* Emit a pair of get/set functions for the variable */
+
+ member_func = 1;
+ Language::membervariableHandler(n);
+ member_func = 0;
+
+ if (blessed) {
+
+ Printv(pcode, "*swig_", symname, "_get = *", cmodule, "::", Swig_name_get(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname)), ";\n", NIL);
+ Printv(pcode, "*swig_", symname, "_set = *", cmodule, "::", Swig_name_set(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname)), ";\n", NIL);
+
+ /* Now we need to generate a little Perl code for this */
+
+ /* if (is_shadow(t)) {
+
+ *//* This is a Perl object that we have already seen. Add an
+ entry to the members list *//*
+ Printv(blessedmembers,
+ tab4, symname, " => '", is_shadow(t), "',\n",
+ NIL);
+
+ }
+ */
+ }
+ have_data_members++;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constructorDeclaration()
+ *
+ * Emits a blessed constructor for our class. In addition to our construct
+ * we manage a Perl hash table containing all of the pointers created by
+ * the constructor. This prevents us from accidentally trying to free
+ * something that wasn't necessarily allocated by malloc or new
+ * ------------------------------------------------------------ */
+
+ virtual int constructorHandler(Node *n) {
+
+ String *symname = Getattr(n, "sym:name");
+
+ member_func = 1;
+
+ Swig_save("perl5:constructorHandler", n, "parms", NIL);
+ if (Swig_directorclass(n)) {
+ Parm *parms = Getattr(n, "parms");
+ Parm *self;
+ String *name = NewString("self");
+ String *type = NewString("SV");
+ SwigType_add_pointer(type);
+ self = NewParm(type, name, n);
+ Delete(type);
+ Delete(name);
+ Setattr(self, "lname", "O");
+ if (parms)
+ set_nextSibling(self, parms);
+ Setattr(n, "parms", self);
+ Setattr(n, "wrap:self", "1");
+ Setattr(n, "hidden", "1");
+ Delete(self);
+ }
+
+ String *saved_nc = none_comparison;
+ none_comparison = NewStringf("strcmp(SvPV_nolen(ST(0)), \"%s::%s\") != 0", module, class_name);
+ String *saved_director_prot_ctor_code = director_prot_ctor_code;
+ director_prot_ctor_code = NewStringf("if ($comparison) { /* subclassed */\n" " $director_new\n" "} else {\n"
+ "SWIG_exception_fail(SWIG_RuntimeError, \"accessing abstract class or protected constructor\");\n" "}\n");
+ Language::constructorHandler(n);
+ Delete(none_comparison);
+ none_comparison = saved_nc;
+ Delete(director_prot_ctor_code);
+ director_prot_ctor_code = saved_director_prot_ctor_code;
+ Swig_restore(n);
+
+ if ((blessed) && (!Getattr(n, "sym:nextSibling"))) {
+ if (Getattr(n, "feature:shadow")) {
+ String *plcode = perlcode(Getattr(n, "feature:shadow"), 0);
+ String *plaction = NewStringf("%s::%s", module, Swig_name_member(NSPACE_TODO, class_name, symname));
+ Replaceall(plcode, "$action", plaction);
+ Delete(plaction);
+ Printv(pcode, plcode, NIL);
+ } else {
+ if ((Cmp(symname, class_name) == 0)) {
+ /* Emit a blessed constructor */
+ Printf(pcode, "sub new {\n");
+ } else {
+ /* Constructor doesn't match classname so we'll just use the normal name */
+ Printv(pcode, "sub ", Swig_name_construct(NSPACE_TODO, symname), " {\n", NIL);
+ }
+
+ const char *pkg = getCurrentClass() && Swig_directorclass(getCurrentClass())? "$_[0]" : "shift";
+ Printv(pcode,
+ tab4, "my $pkg = ", pkg, ";\n",
+ tab4, "my $self = ", cmodule, "::", Swig_name_construct(NSPACE_TODO, symname), "(@_);\n", tab4, "bless $self, $pkg if defined($self);\n", "}\n\n", NIL);
+
+ have_constructor = 1;
+ }
+ }
+ member_func = 0;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * destructorHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int destructorHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ member_func = 1;
+ Language::destructorHandler(n);
+ if (blessed) {
+ if (Getattr(n, "feature:shadow")) {
+ String *plcode = perlcode(Getattr(n, "feature:shadow"), 0);
+ String *plaction = NewStringf("%s::%s", module, Swig_name_member(NSPACE_TODO, class_name, symname));
+ Replaceall(plcode, "$action", plaction);
+ Delete(plaction);
+ Printv(pcode, plcode, NIL);
+ } else {
+ Printv(pcode,
+ "sub DESTROY {\n",
+ tab4, "return unless $_[0]->isa('HASH');\n",
+ tab4, "my $self = tied(%{$_[0]});\n",
+ tab4, "return unless defined $self;\n",
+ tab4, "delete $ITERATORS{$self};\n",
+ tab4, "if (exists $OWNER{$self}) {\n",
+ tab8, cmodule, "::", Swig_name_destroy(NSPACE_TODO, symname), "($self);\n", tab8, "delete $OWNER{$self};\n", tab4, "}\n}\n\n", NIL);
+ have_destructor = 1;
+ }
+ }
+ member_func = 0;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ member_func = 1;
+ Language::staticmemberfunctionHandler(n);
+ member_func = 0;
+ if ((blessed) && (!Getattr(n, "sym:nextSibling"))) {
+ String *symname = Getattr(n, "sym:name");
+ Printv(pcode, "*", symname, " = *", cmodule, "::", Swig_name_member(NSPACE_TODO, class_name, symname), ";\n", NIL);
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * staticmembervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int staticmembervariableHandler(Node *n) {
+ Language::staticmembervariableHandler(n);
+ if (blessed) {
+ String *symname = Getattr(n, "sym:name");
+ Printv(pcode, "*", symname, " = *", cmodule, "::", Swig_name_member(NSPACE_TODO, class_name, symname), ";\n", NIL);
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * memberconstantHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int memberconstantHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ int oldblessed = blessed;
+
+ /* Create a normal constant */
+ blessed = 0;
+ Language::memberconstantHandler(n);
+ blessed = oldblessed;
+
+ if (blessed) {
+ Printv(pcode, "*", symname, " = *", cmodule, "::", Swig_name_member(NSPACE_TODO, class_name, symname), ";\n", NIL);
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * pragma()
+ *
+ * Pragma directive.
+ *
+ * %pragma(perl5) code="String" # Includes a string in the .pm file
+ * %pragma(perl5) include="file.pl" # Includes a file in the .pm file
+ * ------------------------------------------------------------ */
+
+ virtual int pragmaDirective(Node *n) {
+ String *lang;
+ String *code;
+ String *value;
+ if (!ImportMode) {
+ lang = Getattr(n, "lang");
+ code = Getattr(n, "name");
+ value = Getattr(n, "value");
+ if (Strcmp(lang, "perl5") == 0) {
+ if (Strcmp(code, "code") == 0) {
+ /* Dump the value string into the .pm file */
+ if (value) {
+ Printf(pragma_include, "%s\n", value);
+ }
+ } else if (Strcmp(code, "include") == 0) {
+ /* Include a file into the .pm file */
+ if (value) {
+ FILE *f = Swig_include_open(value);
+ if (!f) {
+ Swig_error(input_file, line_number, "Unable to locate file %s\n", value);
+ } else {
+ char buffer[4096];
+ while (fgets(buffer, 4095, f)) {
+ Printf(pragma_include, "%s", buffer);
+ }
+ fclose(f);
+ }
+ }
+ } else {
+ Swig_error(input_file, line_number, "Unrecognized pragma.\n");
+ }
+ }
+ }
+ return Language::pragmaDirective(n);
+ }
+
+ /* ------------------------------------------------------------
+ * perlcode() - Output perlcode code into the shadow file
+ * ------------------------------------------------------------ */
+
+ String *perlcode(String *code, const String *indent) {
+ String *out = NewString("");
+ String *temp;
+ char *t;
+ if (!indent)
+ indent = "";
+
+ temp = NewString(code);
+
+ t = Char(temp);
+ if (*t == '{') {
+ Delitem(temp, 0);
+ Delitem(temp, DOH_END);
+ }
+
+ /* Split the input text into lines */
+ List *clist = SplitLines(temp);
+ Delete(temp);
+ int initial = 0;
+ String *s = 0;
+ Iterator si;
+ /* Get the initial indentation */
+
+ for (si = First(clist); si.item; si = Next(si)) {
+ s = si.item;
+ if (Len(s)) {
+ char *c = Char(s);
+ while (*c) {
+ if (!isspace(*c))
+ break;
+ initial++;
+ c++;
+ }
+ if (*c && !isspace(*c))
+ break;
+ else {
+ initial = 0;
+ }
+ }
+ }
+ while (si.item) {
+ s = si.item;
+ if (Len(s) > initial) {
+ char *c = Char(s);
+ c += initial;
+ Printv(out, indent, c, "\n", NIL);
+ } else {
+ Printv(out, "\n", NIL);
+ }
+ si = Next(si);
+ }
+ Delete(clist);
+ return out;
+ }
+
+ /* ------------------------------------------------------------
+ * insertDirective()
+ *
+ * Hook for %insert directive.
+ * ------------------------------------------------------------ */
+
+ virtual int insertDirective(Node *n) {
+ String *code = Getattr(n, "code");
+ String *section = Getattr(n, "section");
+
+ if ((!ImportMode) && (Cmp(section, "perl") == 0)) {
+ Printv(additional_perl_code, code, NIL);
+ } else {
+ Language::insertDirective(n);
+ }
+ return SWIG_OK;
+ }
+
+ String *runtimeCode() {
+ String *s = NewString("");
+ String *shead = Swig_include_sys("perlhead.swg");
+ if (!shead) {
+ Printf(stderr, "*** Unable to open 'perlhead.swg'\n");
+ } else {
+ Append(s, shead);
+ Delete(shead);
+ }
+ String *serrors = Swig_include_sys("perlerrors.swg");
+ if (!serrors) {
+ Printf(stderr, "*** Unable to open 'perlerrors.swg'\n");
+ } else {
+ Append(s, serrors);
+ Delete(serrors);
+ }
+ String *srun = Swig_include_sys("perlrun.swg");
+ if (!srun) {
+ Printf(stderr, "*** Unable to open 'perlrun.swg'\n");
+ } else {
+ Append(s, srun);
+ Delete(srun);
+ }
+ return s;
+ }
+
+ String *defaultExternalRuntimeFilename() {
+ return NewString("swigperlrun.h");
+ }
+
+ virtual int classDirectorInit(Node *n) {
+ String *declaration = Swig_director_declaration(n);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "%s\n", declaration);
+ Printf(f_directors_h, "public:\n");
+ Delete(declaration);
+ return Language::classDirectorInit(n);
+ }
+
+ virtual int classDirectorEnd(Node *n) {
+ if (dirprot_mode()) {
+ /*
+ This implementation uses a std::map<std::string,int>.
+
+ It should be possible to rewrite it using a more elegant way,
+ like copying the Java approach for the 'override' array.
+
+ But for now, this seems to be the least intrusive way.
+ */
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "/* Internal director utilities */\n");
+ Printf(f_directors_h, "public:\n");
+ Printf(f_directors_h, " bool swig_get_inner(const char *swig_protected_method_name) const {\n");
+ Printf(f_directors_h, " std::map<std::string, bool>::const_iterator iv = swig_inner.find(swig_protected_method_name);\n");
+ Printf(f_directors_h, " return (iv != swig_inner.end() ? iv->second : false);\n");
+ Printf(f_directors_h, " }\n");
+
+ Printf(f_directors_h, " void swig_set_inner(const char *swig_protected_method_name, bool swig_val) const {\n");
+ Printf(f_directors_h, " swig_inner[swig_protected_method_name] = swig_val;\n");
+ Printf(f_directors_h, " }\n");
+ Printf(f_directors_h, "private:\n");
+ Printf(f_directors_h, " mutable std::map<std::string, bool> swig_inner;\n");
+ }
+ Printf(f_directors_h, "};\n");
+ return Language::classDirectorEnd(n);
+ }
+
+ virtual int classDirectorConstructor(Node *n) {
+ Node *parent = Getattr(n, "parentNode");
+ String *sub = NewString("");
+ String *decl = Getattr(n, "decl");
+ String *supername = Swig_class_name(parent);
+ String *classname = NewString("");
+ Printf(classname, "SwigDirector_%s", supername);
+
+ /* insert self parameter */
+ Parm *p;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms = CopyParmList(superparms);
+ String *type = NewString("SV");
+ SwigType_add_pointer(type);
+ p = NewParm(type, NewString("self"), n);
+ set_nextSibling(p, parms);
+ parms = p;
+
+ if (!Getattr(n, "defaultargs")) {
+ /* constructor */
+ {
+ Wrapper *w = NewWrapper();
+ String *call;
+ String *basetype = Getattr(parent, "classtype");
+ String *target = Swig_method_decl(0, decl, classname, parms, 0);
+ call = Swig_csuperclass_call(0, basetype, superparms);
+ Printf(w->def, "%s::%s: %s, Swig::Director(self) { \n", classname, target, call);
+ Printf(w->def, " SWIG_DIRECTOR_RGTR((%s *)this, this); \n", basetype);
+ Append(w->def, "}\n");
+ Delete(target);
+ Wrapper_print(w, f_directors);
+ Delete(call);
+ DelWrapper(w);
+ }
+
+ /* constructor header */
+ {
+ String *target = Swig_method_decl(0, decl, classname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Delete(sub);
+ Delete(classname);
+ Delete(supername);
+ Delete(parms);
+ return Language::classDirectorConstructor(n);
+ }
+
+ virtual int classDirectorMethod(Node *n, Node *parent, String *super) {
+ int is_void = 0;
+ int is_pointer = 0;
+ String *decl = Getattr(n, "decl");
+ String *name = Getattr(n, "name");
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *declaration = NewString("");
+ ParmList *l = Getattr(n, "parms");
+ Wrapper *w = NewWrapper();
+ String *tm;
+ String *wrap_args = NewString("");
+ String *returntype = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ String *storage = Getattr(n, "storage");
+ bool pure_virtual = false;
+ int status = SWIG_OK;
+ int idx;
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+
+ if (Cmp(storage, "virtual") == 0) {
+ if (Cmp(value, "0") == 0) {
+ pure_virtual = true;
+ }
+ }
+
+ /* determine if the method returns a pointer */
+ is_pointer = SwigType_ispointer_return(decl);
+ is_void = (!Cmp(returntype, "void") && !is_pointer);
+
+ /* virtual method definition */
+ String *target;
+ String *pclassname = NewStringf("SwigDirector_%s", classname);
+ String *qualified_name = NewStringf("%s::%s", pclassname, name);
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ /* header declaration */
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Get any exception classes in the throws typemap
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ ParmList *throw_parm_list = 0;
+
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ Parm *p;
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list)
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+ String *str = SwigType_str(Getattr(p, "type"), 0);
+ Append(w->def, str);
+ Append(declaration, str);
+ Delete(str);
+ }
+ }
+
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+
+ /* declare method return value
+ * if the return value is a reference or const reference, a specialized typemap must
+ * handle it, including declaration of c_result ($result).
+ */
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ }
+ } else {
+ String *cres = SwigType_lstr(returntype, "c_result");
+ Printf(w->code, "%s;\n", cres);
+ Delete(cres);
+ }
+ }
+
+ if (!is_void && !ignored_method) {
+ String *pres = NewStringf("SV *%s", Swig_cresult_name());
+ Wrapper_add_local(w, Swig_cresult_name(), pres);
+ Delete(pres);
+ }
+
+ if (ignored_method) {
+ if (!pure_virtual) {
+ if (!is_void)
+ Printf(w->code, "return ");
+ String *super_call = Swig_method_call(super, l);
+ Printf(w->code, "%s;\n", super_call);
+ Delete(super_call);
+ } else {
+ Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname),
+ SwigType_namestr(name));
+ }
+ } else {
+ /* attach typemaps to arguments (C/C++ -> Perl) */
+ String *parse_args = NewString("");
+ String *pstack = NewString("");
+
+ Swig_director_parms_fixup(l);
+
+ /* remove the wrapper 'w' since it was producing spurious temps */
+ Swig_typemap_attach_parms("in", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ Wrapper_add_local(w, "SP", "dSP");
+
+ {
+ String *ptype = Copy(getClassType());
+ SwigType_add_pointer(ptype);
+ String *mangle = SwigType_manglestr(ptype);
+
+ Wrapper_add_local(w, "swigself", "SV *swigself");
+ Printf(w->code, "swigself = SWIG_NewPointerObj(SWIG_as_voidptr(this), SWIGTYPE%s, SWIG_SHADOW);\n", mangle);
+ Printf(w->code, "sv_bless(swigself, gv_stashpv(swig_get_class(), 0));\n");
+ Delete(mangle);
+ Delete(ptype);
+ Append(pstack, "XPUSHs(swigself);\n");
+ }
+
+ Parm *p;
+ char source[256];
+
+ int outputs = 0;
+ if (!is_void)
+ outputs++;
+
+ /* build argument list and type conversion string */
+ idx = 0;
+ p = l;
+ while (p) {
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ /* old style? caused segfaults without the p!=0 check
+ in the for() condition, and seems dangerous in the
+ while loop as well.
+ while (Getattr(p, "tmap:ignore")) {
+ p = Getattr(p, "tmap:ignore:next");
+ }
+ */
+
+ if (Getattr(p, "tmap:directorargout") != 0)
+ outputs++;
+
+ String *pname = Getattr(p, "name");
+ String *ptype = Getattr(p, "type");
+
+ if ((tm = Getattr(p, "tmap:directorin")) != 0) {
+ sprintf(source, "obj%d", idx++);
+ String *input = NewString(source);
+ Setattr(p, "emit:directorinput", input);
+ Replaceall(tm, "$input", input);
+ Delete(input);
+ Replaceall(tm, "$owner", "0");
+ Replaceall(tm, "$shadow", "0");
+ /* Wrapper_add_localv(w, source, "SV *", source, "= 0", NIL); */
+ Printv(wrap_args, "SV *", source, ";\n", NIL);
+
+ Printv(wrap_args, tm, "\n", NIL);
+ Putc('O', parse_args);
+ Printv(pstack, "XPUSHs(", source, ");\n", NIL);
+ p = Getattr(p, "tmap:directorin:next");
+ continue;
+ } else if (Cmp(ptype, "void")) {
+ /* special handling for pointers to other C++ director classes.
+ * ideally this would be left to a typemap, but there is currently no
+ * way to selectively apply the dynamic_cast<> to classes that have
+ * directors. in other words, the type "SwigDirector_$1_lname" only exists
+ * for classes with directors. we avoid the problem here by checking
+ * module.wrap::directormap, but it's not clear how to get a typemap to
+ * do something similar. perhaps a new default typemap (in addition
+ * to SWIGTYPE) called DIRECTORTYPE?
+ */
+ if (SwigType_ispointer(ptype) || SwigType_isreference(ptype)) {
+ Node *module = Getattr(parent, "module");
+ Node *target = Swig_directormap(module, ptype);
+ sprintf(source, "obj%d", idx++);
+ String *nonconst = 0;
+ /* strip pointer/reference --- should move to Swig/stype.c */
+ String *nptype = NewString(Char(ptype) + 2);
+ /* name as pointer */
+ String *ppname = Copy(pname);
+ if (SwigType_isreference(ptype)) {
+ Insert(ppname, 0, "&");
+ }
+ /* if necessary, cast away const since Perl doesn't support it! */
+ if (SwigType_isconst(nptype)) {
+ nonconst = NewStringf("nc_tmp_%s", pname);
+ String *nonconst_i = NewStringf("= const_cast< %s >(%s)", SwigType_lstr(ptype, 0), ppname);
+ Wrapper_add_localv(w, nonconst, SwigType_lstr(ptype, 0), nonconst, nonconst_i, NIL);
+ Delete(nonconst_i);
+ Swig_warning(WARN_LANG_DISCARD_CONST, input_file, line_number,
+ "Target language argument '%s' discards const in director method %s::%s.\n",
+ SwigType_str(ptype, pname), SwigType_namestr(c_classname), SwigType_namestr(name));
+ } else {
+ nonconst = Copy(ppname);
+ }
+ Delete(nptype);
+ Delete(ppname);
+ String *mangle = SwigType_manglestr(ptype);
+ if (target) {
+ String *director = NewStringf("director_%s", mangle);
+ Wrapper_add_localv(w, director, "Swig::Director *", director, "= 0", NIL);
+ Wrapper_add_localv(w, source, "SV *", source, "= 0", NIL);
+ Printf(wrap_args, "%s = SWIG_DIRECTOR_CAST(%s);\n", director, nonconst);
+ Printf(wrap_args, "if (!%s) {\n", director);
+ Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
+ Append(wrap_args, "} else {\n");
+ Printf(wrap_args, "%s = %s->swig_get_self();\n", source, director);
+ Printf(wrap_args, "SvREFCNT_inc((SV *)%s);\n", source);
+ Append(wrap_args, "}\n");
+ Delete(director);
+ } else {
+ Wrapper_add_localv(w, source, "SV *", source, "= 0", NIL);
+ Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
+ Printf(pstack, "XPUSHs(sv_2mortal(%s));\n", source);
+ }
+ Putc('O', parse_args);
+ Delete(mangle);
+ Delete(nonconst);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
+ "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(ptype, 0),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_NOWRAP;
+ break;
+ }
+ }
+ p = nextSibling(p);
+ }
+
+ /* add the method name as a PyString */
+ String *pyname = Getattr(n, "sym:name");
+
+ /* wrap complex arguments to PyObjects */
+ Printv(w->code, wrap_args, NIL);
+
+ /* pass the method call on to the Python object */
+ if (dirprot_mode() && !is_public(n)) {
+ Printf(w->code, "swig_set_inner(\"%s\", true);\n", name);
+ }
+
+ Append(w->code, "ENTER;\n");
+ Append(w->code, "SAVETMPS;\n");
+ Append(w->code, "PUSHMARK(SP);\n");
+ Append(w->code, pstack);
+ Delete(pstack);
+ Append(w->code, "PUTBACK;\n");
+ Printf(w->code, "call_method(\"%s\", G_EVAL | G_SCALAR);\n", pyname);
+
+ if (dirprot_mode() && !is_public(n))
+ Printf(w->code, "swig_set_inner(\"%s\", false);\n", name);
+
+ /* exception handling */
+ tm = Swig_typemap_lookup("director:except", n, Swig_cresult_name(), 0);
+ if (!tm) {
+ tm = Getattr(n, "feature:director:except");
+ if (tm)
+ tm = Copy(tm);
+ }
+ Append(w->code, "if (SvTRUE(ERRSV)) {\n");
+ Append(w->code, " PUTBACK;\n FREETMPS;\n LEAVE;\n");
+ if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
+ Replaceall(tm, "$error", "ERRSV");
+ Printv(w->code, Str(tm), "\n", NIL);
+ } else {
+ Printf(w->code, " Swig::DirectorMethodException::raise(ERRSV);\n", classname, pyname);
+ }
+ Append(w->code, "}\n");
+ Delete(tm);
+
+ /*
+ * Python method may return a simple object, or a tuple.
+ * for in/out arguments, we have to extract the appropriate PyObjects from the tuple,
+ * then marshal everything back to C/C++ (return value and output arguments).
+ *
+ */
+
+ /* marshal return value and other outputs (if any) from PyObject to C/C++ type */
+
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+
+ if (outputs > 1) {
+ Wrapper_add_local(w, "output", "SV *output");
+ Printf(w->code, "if (count != %d) {\n", outputs);
+ Printf(w->code, " Swig::DirectorTypeMismatchException::raise(\"Perl method %s.%sfailed to return a list.\");\n", classname, pyname);
+ Append(w->code, "}\n");
+ }
+
+ idx = 0;
+
+ /* marshal return value */
+ if (!is_void) {
+ Append(w->code, "SPAGAIN;\n");
+ Printf(w->code, "%s = POPs;\n", Swig_cresult_name());
+ tm = Swig_typemap_lookup("directorout", n, Swig_cresult_name(), w);
+ if (tm != 0) {
+ if (outputs > 1) {
+ Printf(w->code, "output = POPs;\n");
+ Replaceall(tm, "$input", "output");
+ } else {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ }
+ char temp[24];
+ sprintf(temp, "%d", idx);
+ Replaceall(tm, "$argnum", temp);
+
+ /* TODO check this */
+ if (Getattr(n, "wrap:disown")) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, tm, "\n", NIL);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s in director method %s::%s (skipping method).\n", SwigType_str(returntype, 0),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_ERROR;
+ }
+ }
+
+ /* marshal outputs */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout")) != 0) {
+ if (outputs > 1) {
+ Printf(w->code, "output = POPs;\n");
+ Replaceall(tm, "$result", "output");
+ } else {
+ Replaceall(tm, "$result", Swig_cresult_name());
+ }
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ Delete(parse_args);
+ Delete(cleanup);
+ Delete(outarg);
+ }
+
+ if (!ignored_method) {
+ Append(w->code, "PUTBACK;\n");
+ Append(w->code, "FREETMPS;\n");
+ Append(w->code, "LEAVE;\n");
+ }
+
+ if (!is_void) {
+ if (!(ignored_method && !pure_virtual)) {
+ String *rettype = SwigType_str(returntype, 0);
+ if (!SwigType_isreference(returntype)) {
+ Printf(w->code, "return (%s) c_result;\n", rettype);
+ } else {
+ Printf(w->code, "return (%s) *c_result;\n", rettype);
+ }
+ Delete(rettype);
+ }
+ }
+
+ Append(w->code, "}\n");
+
+ // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewString("");
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+
+ /* emit the director method */
+ if (status == SWIG_OK) {
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+
+ /* clean up */
+ Delete(wrap_args);
+ Delete(pclassname);
+ DelWrapper(w);
+ return status;
+ }
+ int classDirectorDisown(Node *n) {
+ int rv;
+ member_func = 1;
+ rv = Language::classDirectorDisown(n);
+ member_func = 0;
+ if (rv == SWIG_OK && Swig_directorclass(n)) {
+ String *symname = Getattr(n, "sym:name");
+ String *disown = Swig_name_disown(NSPACE_TODO, symname);
+ Setattr(n, "perl5:directordisown", NewStringf("%s::%s", cmodule, disown));
+ }
+ return rv;
+ }
+ int classDirectorDestructor(Node *n) {
+ /* TODO: it would be nice if this didn't have to copy the body of Language::classDirectorDestructor() */
+ String *DirectorClassName = directorClassName(getCurrentClass());
+ String *body = NewString("\n");
+
+ String *ptype = Copy(getClassType());
+ SwigType_add_pointer(ptype);
+ String *mangle = SwigType_manglestr(ptype);
+
+ Printv(body, tab4, "dSP;\n", tab4, "SV *self = SWIG_NewPointerObj(SWIG_as_voidptr(this), SWIGTYPE", mangle, ", SWIG_SHADOW);\n", tab4, "\n", tab4,
+ "sv_bless(self, gv_stashpv(swig_get_class(), 0));\n", tab4, "ENTER;\n", tab4, "SAVETMPS;\n", tab4, "PUSHMARK(SP);\n", tab4,
+ "XPUSHs(self);\n", tab4, "XPUSHs(&PL_sv_yes);\n", tab4, "PUTBACK;\n", tab4, "call_method(\"DESTROY\", G_EVAL | G_VOID);\n", tab4,
+ "FREETMPS;\n", tab4, "LEAVE;\n", NIL);
+
+ Delete(mangle);
+ Delete(ptype);
+
+ if (Getattr(n, "noexcept")) {
+ Printf(f_directors_h, " virtual ~%s() noexcept;\n", DirectorClassName);
+ Printf(f_directors, "%s::~%s() noexcept {%s}\n\n", DirectorClassName, DirectorClassName, body);
+ } else if (Getattr(n, "throw")) {
+ Printf(f_directors_h, " virtual ~%s() throw();\n", DirectorClassName);
+ Printf(f_directors, "%s::~%s() throw() {%s}\n\n", DirectorClassName, DirectorClassName, body);
+ } else {
+ Printf(f_directors_h, " virtual ~%s();\n", DirectorClassName);
+ Printf(f_directors, "%s::~%s() {%s}\n\n", DirectorClassName, DirectorClassName, body);
+ }
+ return SWIG_OK;
+ }
+};
+
+/* -----------------------------------------------------------------------------
+ * swig_perl5() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_perl5() {
+ return new PERL5();
+}
+extern "C" Language *swig_perl5(void) {
+ return new_swig_perl5();
+}
diff --git a/contrib/tools/swig/Source/Modules/php.cxx b/contrib/tools/swig/Source/Modules/php.cxx
new file mode 100644
index 00000000000..1edbd874cc9
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/php.cxx
@@ -0,0 +1,2876 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * php.cxx
+ *
+ * PHP language module for SWIG.
+ * -----------------------------------------------------------------------------
+ */
+
+/* FIXME: PHP OO wrapping TODO list:
+ *
+ * Medium term:
+ *
+ * Handle default parameters on overloaded methods in PHP where possible.
+ * (Mostly done - just need to handle cases of overloaded methods with
+ * default parameters...)
+ * This is an optimisation - we could handle this case using a PHP
+ * default value, but currently we treat it as we would for a default
+ * value which is a compound C++ expression (i.e. as if we had a
+ * method with two overloaded forms instead of a single method with
+ * a default parameter value).
+ *
+ * Long term:
+ *
+ * Sort out locale-dependent behaviour of strtod() - it's harmless unless
+ * SWIG ever sets the locale and DOH/base.c calls atof, so we're probably
+ * OK currently at least.
+ */
+
+/*
+ * TODO: Replace remaining stderr messages with Swig_error or Swig_warning
+ * (may need to add more WARN_PHP_xxx codes...)
+ */
+
+#include "swigmod.h"
+
+#include <ctype.h>
+#include <errno.h>
+
+static const char *usage = "\
+PHP 7 Options (available with -php7)\n\
+ -noproxy - Don't generate proxy classes.\n\
+ -prefix <prefix> - Prepend <prefix> to all class names in PHP wrappers\n\
+\n";
+
+/* The original class wrappers for PHP stored the pointer to the C++ class in
+ * the object property _cPtr. If we use the same name for the member variable
+ * which we put the pointer to the C++ class in, then the flat function
+ * wrappers will automatically pull it out without any changes being required.
+ * FIXME: Isn't using a leading underscore a bit suspect here?
+ */
+#define SWIG_PTR "_cPtr"
+
+/* This is the name of the hash where the variables existing only in PHP
+ * classes are stored.
+ */
+#define SWIG_DATA "_pData"
+
+static int constructors = 0;
+static String *NOTCLASS = NewString("Not a class");
+static Node *classnode = 0;
+static String *module = 0;
+static String *cap_module = 0;
+static String *prefix = 0;
+
+static String *shadow_classname = 0;
+
+static File *f_begin = 0;
+static File *f_runtime = 0;
+static File *f_runtime_h = 0;
+static File *f_h = 0;
+static File *f_phpcode = 0;
+static File *f_directors = 0;
+static File *f_directors_h = 0;
+static String *phpfilename = 0;
+
+static String *s_header;
+static String *s_wrappers;
+static String *s_init;
+static String *r_init; // RINIT user code
+static String *s_shutdown; // MSHUTDOWN user code
+static String *r_shutdown; // RSHUTDOWN user code
+static String *s_vinit; // varinit initialization code.
+static String *s_vdecl;
+static String *s_cinit; // consttab initialization code.
+static String *s_oinit;
+static String *s_arginfo;
+static String *s_entry;
+static String *cs_entry;
+static String *all_cs_entry;
+static String *pragma_incl;
+static String *pragma_code;
+static String *pragma_phpinfo;
+static String *pragma_version;
+static String *s_oowrappers;
+static String *s_fakeoowrappers;
+static String *s_phpclasses;
+
+/* To reduce code size (generated and compiled) we only want to emit each
+ * different arginfo once, so we need to track which have been used.
+ */
+static Hash *arginfo_used;
+
+/* Variables for using PHP classes */
+static Node *current_class = 0;
+
+static Hash *shadow_get_vars;
+static Hash *shadow_set_vars;
+static Hash *zend_types = 0;
+
+static int shadow = 1;
+
+static bool class_has_ctor = false;
+static String *wrapping_member_constant = NULL;
+
+// These static variables are used to pass some state from Handlers into functionWrapper
+static enum {
+ standard = 0,
+ memberfn,
+ staticmemberfn,
+ membervar,
+ staticmembervar,
+ constructor,
+ directorconstructor
+} wrapperType = standard;
+
+extern "C" {
+ static void (*r_prevtracefunc) (const SwigType *t, String *mangled, String *clientdata) = 0;
+}
+
+static void SwigPHP_emit_resource_registrations() {
+ Iterator ki;
+ bool emitted_default_dtor = false;
+
+ if (!zend_types)
+ return;
+
+ ki = First(zend_types);
+ if (ki.key)
+ Printf(s_oinit, "\n /* Register resource destructors for pointer types */\n");
+ while (ki.key) {
+ DOH *key = ki.key;
+ Node *class_node = ki.item;
+ String *human_name = key;
+ String *rsrc_dtor_name = NULL;
+
+ // write out body
+ if (class_node != NOTCLASS) {
+ String *destructor = Getattr(class_node, "destructor");
+ human_name = Getattr(class_node, "sym:name");
+ if (!human_name)
+ human_name = Getattr(class_node, "name");
+ // Do we have a known destructor for this type?
+ if (destructor) {
+ rsrc_dtor_name = NewStringf("_wrap_destroy%s", key);
+ // Write out custom destructor function
+ Printf(s_wrappers, "static ZEND_RSRC_DTOR_FUNC(%s) {\n", rsrc_dtor_name);
+ Printf(s_wrappers, " %s(res, SWIGTYPE%s->name);\n", destructor, key);
+ Printf(s_wrappers, "}\n");
+ }
+ }
+
+ if (!rsrc_dtor_name) {
+ rsrc_dtor_name = NewString("_swig_default_rsrc_destroy");
+ if (!emitted_default_dtor) {
+ // Write out custom destructor function
+ Printf(s_wrappers, "static ZEND_RSRC_DTOR_FUNC(%s) {\n", rsrc_dtor_name);
+ Printf(s_wrappers, " efree(res->ptr);\n");
+ Printf(s_wrappers, "}\n");
+ emitted_default_dtor = true;
+ }
+ }
+
+ // declare le_swig_<mangled> to store php registration
+ Printf(s_vdecl, "static int le_swig_%s=0; /* handle for %s */\n", key, human_name);
+
+ // register with php
+ Printf(s_oinit, " le_swig_%s=zend_register_list_destructors_ex"
+ "(%s, NULL, SWIGTYPE%s->name, module_number);\n", key, rsrc_dtor_name, key);
+
+ // store php type in class struct
+ Printf(s_oinit, " SWIG_TypeClientData(SWIGTYPE%s,&le_swig_%s);\n", key, key);
+
+ Delete(rsrc_dtor_name);
+
+ ki = Next(ki);
+ }
+}
+
+class PHP : public Language {
+public:
+ PHP() {
+ director_language = 1;
+ }
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+ SWIG_library_directory("php");
+
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-prefix") == 0) {
+ if (argv[i + 1]) {
+ prefix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if ((strcmp(argv[i], "-noshadow") == 0) || (strcmp(argv[i], "-noproxy") == 0)) {
+ shadow = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ }
+ }
+
+ Preprocessor_define("SWIGPHP 1", 0);
+ Preprocessor_define("SWIGPHP7 1", 0);
+ SWIG_typemap_lang("php");
+ SWIG_config_file("php.swg");
+ allow_overloading();
+ }
+
+ /* ------------------------------------------------------------
+ * top()
+ * ------------------------------------------------------------ */
+
+ virtual int top(Node *n) {
+
+ String *filen;
+
+ /* Check if directors are enabled for this module. */
+ Node *mod = Getattr(n, "module");
+ if (mod) {
+ Node *options = Getattr(mod, "options");
+ if (options && Getattr(options, "directors")) {
+ allow_directors();
+ }
+ }
+
+ /* Set comparison with null for ConstructorToFunction */
+ setSubclassInstanceCheck(NewString("Z_TYPE_P($arg) != IS_NULL"));
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+ String *outfile_h = Getattr(n, "outfile_h");
+
+ /* main output file */
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ f_runtime = NewStringEmpty();
+
+ /* sections of the output file */
+ s_init = NewStringEmpty();
+ r_init = NewStringEmpty();
+ s_shutdown = NewStringEmpty();
+ r_shutdown = NewStringEmpty();
+ s_header = NewString("/* header section */\n");
+ s_wrappers = NewString("/* wrapper section */\n");
+ /* subsections of the init section */
+ s_vinit = NewStringEmpty();
+ s_vdecl = NewString("/* vdecl subsection */\n");
+ s_cinit = NewString(" /* cinit subsection */\n");
+ s_oinit = NewString(" /* oinit subsection */\n");
+ pragma_phpinfo = NewStringEmpty();
+ s_phpclasses = NewString("/* PHP Proxy Classes */\n");
+ f_directors_h = NewStringEmpty();
+ f_directors = NewStringEmpty();
+
+ if (directorsEnabled()) {
+ f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
+ if (!f_runtime_h) {
+ FileErrorDisplay(outfile_h);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", s_init);
+ Swig_register_filebyname("rinit", r_init);
+ Swig_register_filebyname("shutdown", s_shutdown);
+ Swig_register_filebyname("rshutdown", r_shutdown);
+ Swig_register_filebyname("header", s_header);
+ Swig_register_filebyname("wrapper", s_wrappers);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n\n#ifndef SWIGPHP\n#define SWIGPHP\n#endif\n\n");
+
+ if (directorsEnabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+ }
+
+ /* Set the module name */
+ module = Copy(Getattr(n, "name"));
+ cap_module = NewStringf("%(upper)s", module);
+ if (!prefix)
+ prefix = NewStringEmpty();
+
+ Printf(f_runtime, "#define SWIG_PREFIX \"%s\"\n", prefix);
+ Printf(f_runtime, "#define SWIG_PREFIX_LEN %lu\n", (unsigned long)Len(prefix));
+
+ if (directorsEnabled()) {
+ Swig_banner(f_directors_h);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", cap_module);
+ Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", cap_module);
+
+ String *filename = Swig_file_filename(outfile_h);
+ Printf(f_directors, "\n#include \"%s\"\n\n", filename);
+ Delete(filename);
+ }
+
+ /* PHP module file */
+ filen = NewStringEmpty();
+ Printv(filen, SWIG_output_directory(), module, ".php", NIL);
+ phpfilename = NewString(filen);
+
+ f_phpcode = NewFile(filen, "w", SWIG_output_files());
+ if (!f_phpcode) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ Printf(f_phpcode, "<?php\n\n");
+
+ Swig_banner(f_phpcode);
+
+ Printf(f_phpcode, "\n");
+ Printf(f_phpcode, "// Try to load our extension if it's not already loaded.\n");
+ Printf(f_phpcode, "if (!extension_loaded('%s')) {\n", module);
+ Printf(f_phpcode, " if (strtolower(substr(PHP_OS, 0, 3)) === 'win') {\n");
+ Printf(f_phpcode, " if (!dl('php_%s.dll')) return;\n", module);
+ Printf(f_phpcode, " } else {\n");
+ Printf(f_phpcode, " // PHP_SHLIB_SUFFIX gives 'dylib' on MacOS X but modules are 'so'.\n");
+ Printf(f_phpcode, " if (PHP_SHLIB_SUFFIX === 'dylib') {\n");
+ Printf(f_phpcode, " if (!dl('%s.so')) return;\n", module);
+ Printf(f_phpcode, " } else {\n");
+ Printf(f_phpcode, " if (!dl('%s.'.PHP_SHLIB_SUFFIX)) return;\n", module);
+ Printf(f_phpcode, " }\n");
+ Printf(f_phpcode, " }\n");
+ Printf(f_phpcode, "}\n\n");
+
+ /* sub-sections of the php file */
+ pragma_code = NewStringEmpty();
+ pragma_incl = NewStringEmpty();
+ pragma_version = NULL;
+
+ /* Initialize the rest of the module */
+
+ Printf(s_oinit, " ZEND_INIT_MODULE_GLOBALS(%s, %s_init_globals, NULL);\n", module, module);
+
+ /* start the header section */
+ Printf(s_header, "ZEND_BEGIN_MODULE_GLOBALS(%s)\n", module);
+ Printf(s_header, "const char *error_msg;\n");
+ Printf(s_header, "int error_code;\n");
+ Printf(s_header, "ZEND_END_MODULE_GLOBALS(%s)\n", module);
+ Printf(s_header, "ZEND_DECLARE_MODULE_GLOBALS(%s)\n", module);
+ Printf(s_header, "#define SWIG_ErrorMsg() ZEND_MODULE_GLOBALS_ACCESSOR(%s, error_msg)\n", module);
+ Printf(s_header, "#define SWIG_ErrorCode() ZEND_MODULE_GLOBALS_ACCESSOR(%s, error_code)\n", module);
+
+ /* The following can't go in Lib/php/phprun.swg as it uses SWIG_ErrorMsg(), etc
+ * which has to be dynamically generated as it depends on the module name.
+ */
+ Append(s_header, "#ifdef __GNUC__\n");
+ Append(s_header, "static void SWIG_FAIL(void) __attribute__ ((__noreturn__));\n");
+ Append(s_header, "#endif\n\n");
+ Append(s_header, "static void SWIG_FAIL(void) {\n");
+ Append(s_header, " zend_error(SWIG_ErrorCode(), \"%s\", SWIG_ErrorMsg());\n");
+ // zend_error() should never return with the parameters we pass, but if it
+ // does, we really don't want to let SWIG_FAIL() return. This also avoids
+ // a warning about returning from a function marked as "__noreturn__".
+ Append(s_header, " abort();\n");
+ Append(s_header, "}\n\n");
+
+ Printf(s_header, "static void %s_init_globals(zend_%s_globals *globals ) {\n", module, module);
+ Printf(s_header, " globals->error_msg = default_error_msg;\n");
+ Printf(s_header, " globals->error_code = default_error_code;\n");
+ Printf(s_header, "}\n");
+
+ Printf(s_header, "static void SWIG_ResetError(void) {\n");
+ Printf(s_header, " SWIG_ErrorMsg() = default_error_msg;\n");
+ Printf(s_header, " SWIG_ErrorCode() = default_error_code;\n");
+ Printf(s_header, "}\n");
+
+ Append(s_header, "\n");
+ Printf(s_header, "ZEND_NAMED_FUNCTION(_wrap_swig_%s_alter_newobject) {\n", module);
+ Append(s_header, " zval args[2];\n");
+ Append(s_header, " swig_object_wrapper *value;\n");
+ Append(s_header, "\n");
+ Append(s_header, " SWIG_ResetError();\n");
+ Append(s_header, " if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {\n");
+ Append(s_header, " WRONG_PARAM_COUNT;\n");
+ Append(s_header, " }\n");
+ Append(s_header, "\n");
+ Append(s_header, " value = (swig_object_wrapper *) Z_RES_VAL(args[0]);\n");
+ Append(s_header, " value->newobject = zval_is_true(&args[1]);\n");
+ Append(s_header, "\n");
+ Append(s_header, " return;\n");
+ Append(s_header, "}\n");
+ Printf(s_header, "ZEND_NAMED_FUNCTION(_wrap_swig_%s_get_newobject) {\n", module);
+ Append(s_header, " zval args[1];\n");
+ Append(s_header, " swig_object_wrapper *value;\n");
+ Append(s_header, "\n");
+ Append(s_header, " SWIG_ResetError();\n");
+ Append(s_header, " if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {\n");
+ Append(s_header, " WRONG_PARAM_COUNT;\n");
+ Append(s_header, " }\n");
+ Append(s_header, "\n");
+ Append(s_header, " value = (swig_object_wrapper *) Z_RES_VAL(args[0]);\n");
+ Append(s_header, " RETVAL_LONG(value->newobject);\n");
+ Append(s_header, "\n");
+ Append(s_header, " return;\n");
+ Append(s_header, "}\n");
+
+ Printf(s_header, "#define SWIG_name \"%s\"\n", module);
+ Printf(s_header, "#ifdef __cplusplus\n");
+ Printf(s_header, "extern \"C\" {\n");
+ Printf(s_header, "#endif\n");
+ Printf(s_header, "#include \"php.h\"\n");
+ Printf(s_header, "#include \"php_ini.h\"\n");
+ Printf(s_header, "#include \"ext/standard/info.h\"\n");
+ Printf(s_header, "#include \"php_%s.h\"\n", module);
+ Printf(s_header, "#ifdef __cplusplus\n");
+ Printf(s_header, "}\n");
+ Printf(s_header, "#endif\n\n");
+
+ if (directorsEnabled()) {
+ // Insert director runtime
+ Swig_insert_file("director_common.swg", s_header);
+ Swig_insert_file("director.swg", s_header);
+ }
+
+ /* Create the .h file too */
+ filen = NewStringEmpty();
+ Printv(filen, SWIG_output_directory(), "php_", module, ".h", NIL);
+ f_h = NewFile(filen, "w", SWIG_output_files());
+ if (!f_h) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ Swig_banner(f_h);
+
+ Printf(f_h, "\n");
+ Printf(f_h, "#ifndef PHP_%s_H\n", cap_module);
+ Printf(f_h, "#define PHP_%s_H\n\n", cap_module);
+ Printf(f_h, "extern zend_module_entry %s_module_entry;\n", module);
+ Printf(f_h, "#define phpext_%s_ptr &%s_module_entry\n\n", module, module);
+ Printf(f_h, "#ifdef PHP_WIN32\n");
+ Printf(f_h, "# define PHP_%s_API __declspec(dllexport)\n", cap_module);
+ Printf(f_h, "#else\n");
+ Printf(f_h, "# define PHP_%s_API\n", cap_module);
+ Printf(f_h, "#endif\n\n");
+
+ /* start the arginfo section */
+ s_arginfo = NewString("/* arginfo subsection */\n");
+ arginfo_used = NewHash();
+
+ /* start the function entry section */
+ s_entry = NewString("/* entry subsection */\n");
+
+ /* holds all the per-class function entry sections */
+ all_cs_entry = NewString("/* class entry subsection */\n");
+ cs_entry = NULL;
+
+ Printf(s_entry, "/* Every non-class user visible function must have an entry here */\n");
+ Printf(s_entry, "static zend_function_entry %s_functions[] = {\n", module);
+
+ /* Emit all of the code */
+ Language::top(n);
+
+ SwigPHP_emit_resource_registrations();
+
+ /* start the init section */
+ {
+ String * s_init_old = s_init;
+ s_init = NewString("/* init section */\n");
+ Printv(s_init, "zend_module_entry ", module, "_module_entry = {\n", NIL);
+ Printf(s_init, " STANDARD_MODULE_HEADER,\n");
+ Printf(s_init, " \"%s\",\n", module);
+ Printf(s_init, " %s_functions,\n", module);
+ Printf(s_init, " PHP_MINIT(%s),\n", module);
+ if (Len(s_shutdown) > 0) {
+ Printf(s_init, " PHP_MSHUTDOWN(%s),\n", module);
+ } else {
+ Printf(s_init, " NULL, /* No MSHUTDOWN code */\n");
+ }
+ if (Len(r_init) > 0 || Len(s_vinit) > 0) {
+ Printf(s_init, " PHP_RINIT(%s),\n", module);
+ } else {
+ Printf(s_init, " NULL, /* No RINIT code */\n");
+ }
+ if (Len(r_shutdown) > 0) {
+ Printf(s_init, " PHP_RSHUTDOWN(%s),\n", module);
+ } else {
+ Printf(s_init, " NULL, /* No RSHUTDOWN code */\n");
+ }
+ if (Len(pragma_phpinfo) > 0) {
+ Printf(s_init, " PHP_MINFO(%s),\n", module);
+ } else {
+ Printf(s_init, " NULL, /* No MINFO code */\n");
+ }
+ if (Len(pragma_version) > 0) {
+ Printf(s_init, " \"%s\",\n", pragma_version);
+ } else {
+ Printf(s_init, " NO_VERSION_YET,\n");
+ }
+ Printf(s_init, " STANDARD_MODULE_PROPERTIES\n");
+ Printf(s_init, "};\n");
+ Printf(s_init, "zend_module_entry* SWIG_module_entry = &%s_module_entry;\n\n", module);
+
+ Printf(s_init, "#ifdef __cplusplus\n");
+ Printf(s_init, "extern \"C\" {\n");
+ Printf(s_init, "#endif\n");
+ // We want to write "SWIGEXPORT ZEND_GET_MODULE(%s)" but ZEND_GET_MODULE
+ // in PHP7 has "extern "C" { ... }" around it so we can't do that.
+ Printf(s_init, "SWIGEXPORT zend_module_entry *get_module(void) { return &%s_module_entry; }\n", module);
+ Printf(s_init, "#ifdef __cplusplus\n");
+ Printf(s_init, "}\n");
+ Printf(s_init, "#endif\n\n");
+
+ Printf(s_init, "#define SWIG_php_minit PHP_MINIT_FUNCTION(%s)\n\n", module);
+
+ Printv(s_init, s_init_old, NIL);
+ Delete(s_init_old);
+ }
+
+ /* We have to register the constants before they are (possibly) used
+ * by the pointer typemaps. This all needs re-arranging really as
+ * things are being called in the wrong order
+ */
+
+ // Printv(s_init,s_resourcetypes,NIL);
+ /* We need this after all classes written out by ::top */
+ Printf(s_oinit, " CG(active_class_entry) = NULL;\n");
+ Printf(s_oinit, " /* end oinit subsection */\n");
+ Printf(s_init, "%s\n", s_oinit);
+
+ /* Constants generated during top call */
+ Printf(s_cinit, " /* end cinit subsection */\n");
+ Printf(s_init, "%s\n", s_cinit);
+ Clear(s_cinit);
+ Delete(s_cinit);
+
+ Printf(s_init, " return SUCCESS;\n");
+ Printf(s_init, "}\n\n");
+
+ // Now do REQUEST init which holds any user specified %rinit, and also vinit
+ if (Len(r_init) > 0 || Len(s_vinit) > 0) {
+ Printf(f_h, "PHP_RINIT_FUNCTION(%s);\n", module);
+
+ Printf(s_init, "PHP_RINIT_FUNCTION(%s)\n{\n", module);
+ if (Len(r_init) > 0) {
+ Printv(s_init,
+ "/* rinit section */\n",
+ r_init, "\n",
+ NIL);
+ }
+
+ if (Len(s_vinit) > 0) {
+ /* finish our init section which will have been used by class wrappers */
+ Printv(s_init,
+ " /* vinit subsection */\n",
+ s_vinit, "\n"
+ " /* end vinit subsection */\n",
+ NIL);
+ Clear(s_vinit);
+ }
+ Delete(s_vinit);
+
+ Printf(s_init, " return SUCCESS;\n");
+ Printf(s_init, "}\n\n");
+ }
+
+ Printf(f_h, "PHP_MINIT_FUNCTION(%s);\n", module);
+
+ if (Len(s_shutdown) > 0) {
+ Printf(f_h, "PHP_MSHUTDOWN_FUNCTION(%s);\n", module);
+
+ Printv(s_init, "PHP_MSHUTDOWN_FUNCTION(", module, ")\n"
+ "/* shutdown section */\n"
+ "{\n",
+ s_shutdown,
+ " return SUCCESS;\n"
+ "}\n\n", NIL);
+ }
+
+ if (Len(r_shutdown) > 0) {
+ Printf(f_h, "PHP_RSHUTDOWN_FUNCTION(%s);\n", module);
+
+ Printf(s_init, "PHP_RSHUTDOWN_FUNCTION(%s)\n{\n", module);
+ Printf(s_init, "/* rshutdown section */\n");
+ Printf(s_init, "%s\n", r_shutdown);
+ Printf(s_init, " return SUCCESS;\n");
+ Printf(s_init, "}\n\n");
+ }
+
+ if (Len(pragma_phpinfo) > 0) {
+ Printf(f_h, "PHP_MINFO_FUNCTION(%s);\n", module);
+
+ Printf(s_init, "PHP_MINFO_FUNCTION(%s)\n{\n", module);
+ Printf(s_init, "%s", pragma_phpinfo);
+ Printf(s_init, "}\n");
+ }
+
+ Printf(s_init, "/* end init section */\n");
+
+ Printf(f_h, "\n#endif /* PHP_%s_H */\n", cap_module);
+
+ Delete(f_h);
+
+ String *type_table = NewStringEmpty();
+ SwigType_emit_type_table(f_runtime, type_table);
+ Printf(s_header, "%s", type_table);
+ Delete(type_table);
+
+ /* Oh dear, more things being called in the wrong order. This whole
+ * function really needs totally redoing.
+ */
+
+ if (directorsEnabled()) {
+ Dump(f_directors_h, f_runtime_h);
+ Printf(f_runtime_h, "\n");
+ Printf(f_runtime_h, "#endif\n");
+ Delete(f_runtime_h);
+ }
+
+ Printf(s_header, "/* end header section */\n");
+ Printf(s_wrappers, "/* end wrapper section */\n");
+ Printf(s_vdecl, "/* end vdecl subsection */\n");
+
+ Dump(f_runtime, f_begin);
+ Printv(f_begin, s_header, NIL);
+ if (directorsEnabled()) {
+ Dump(f_directors, f_begin);
+ }
+ Printv(f_begin, s_vdecl, s_wrappers, NIL);
+ Printv(f_begin, all_cs_entry, "\n\n", s_arginfo, "\n\n", s_entry,
+ " SWIG_ZEND_NAMED_FE(swig_", module, "_alter_newobject,_wrap_swig_", module, "_alter_newobject,NULL)\n"
+ " SWIG_ZEND_NAMED_FE(swig_", module, "_get_newobject,_wrap_swig_", module, "_get_newobject,NULL)\n"
+ " ZEND_FE_END\n};\n\n", NIL);
+ Printv(f_begin, s_init, NIL);
+ Delete(s_header);
+ Delete(s_wrappers);
+ Delete(s_init);
+ Delete(s_vdecl);
+ Delete(all_cs_entry);
+ Delete(s_entry);
+ Delete(s_arginfo);
+ Delete(f_runtime);
+ Delete(f_begin);
+ Delete(arginfo_used);
+
+ Printf(f_phpcode, "%s\n%s\n", pragma_incl, pragma_code);
+ if (s_fakeoowrappers) {
+ Printf(f_phpcode, "abstract class %s {", Len(prefix) ? prefix : module);
+ Printf(f_phpcode, "%s", s_fakeoowrappers);
+ Printf(f_phpcode, "}\n\n");
+ Delete(s_fakeoowrappers);
+ s_fakeoowrappers = NULL;
+ }
+ Printf(f_phpcode, "%s\n", s_phpclasses);
+ Delete(f_phpcode);
+
+ return SWIG_OK;
+ }
+
+ /* Just need to append function names to function table to register with PHP. */
+ void create_command(String *cname, String *iname, Node *n) {
+ // This is for the single main zend_function_entry record
+ Printf(f_h, "ZEND_NAMED_FUNCTION(%s);\n", iname);
+
+ // We want to only emit each different arginfo once, as that reduces the
+ // size of both the generated source code and the compiled extension
+ // module. To do this, we name the arginfo to encode the number of
+ // parameters and which (if any) are passed by reference by using a
+ // sequence of 0s (for non-reference) and 1s (for by references).
+ ParmList *l = Getattr(n, "parms");
+ String * arginfo_code = NewStringEmpty();
+ for (Parm *p = l; p; p = Getattr(p, "tmap:in:next")) {
+ /* Ignored parameters */
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ continue;
+ }
+ Append(arginfo_code, GetFlag(p, "tmap:in:byref") ? "1" : "0");
+ }
+
+ if (!GetFlag(arginfo_used, arginfo_code)) {
+ // Not had this one before, so emit it.
+ SetFlag(arginfo_used, arginfo_code);
+ Printf(s_arginfo, "ZEND_BEGIN_ARG_INFO_EX(swig_arginfo_%s, 0, 0, 0)\n", arginfo_code);
+ for (const char * p = Char(arginfo_code); *p; ++p) {
+ Printf(s_arginfo, " ZEND_ARG_PASS_INFO(%c)\n", *p);
+ }
+ Printf(s_arginfo, "ZEND_END_ARG_INFO()\n");
+ }
+
+ String * s = cs_entry;
+ if (!s) s = s_entry;
+ Printf(s, " SWIG_ZEND_NAMED_FE(%(lower)s,%s,swig_arginfo_%s)\n", cname, iname, arginfo_code);
+ Delete(arginfo_code);
+ }
+
+ /* ------------------------------------------------------------
+ * dispatchFunction()
+ * ------------------------------------------------------------ */
+ void dispatchFunction(Node *n) {
+ /* Last node in overloaded chain */
+
+ int maxargs;
+ String *tmp = NewStringEmpty();
+ if (Swig_directorclass(n) && wrapperType == directorconstructor) {
+ /* We have an extra 'this' parameter. */
+ SetFlag(n, "wrap:this");
+ }
+ String *dispatch = Swig_overload_dispatch(n, "%s(INTERNAL_FUNCTION_PARAM_PASSTHRU); return;", &maxargs);
+
+ /* Generate a dispatch wrapper for all overloaded functions */
+
+ Wrapper *f = NewWrapper();
+ String *symname = Getattr(n, "sym:name");
+ String *wname = Swig_name_wrapper(symname);
+
+ create_command(symname, wname, n);
+ Printv(f->def, "ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL);
+
+ Wrapper_add_local(f, "argc", "int argc");
+
+ Printf(tmp, "zval argv[%d]", maxargs);
+ Wrapper_add_local(f, "argv", tmp);
+
+ Printf(f->code, "argc = ZEND_NUM_ARGS();\n");
+
+ Printf(f->code, "zend_get_parameters_array_ex(argc, argv);\n");
+
+ Replaceall(dispatch, "$args", "self,args");
+
+ Printv(f->code, dispatch, "\n", NIL);
+
+ Printf(f->code, "SWIG_ErrorCode() = E_ERROR;\n");
+ Printf(f->code, "SWIG_ErrorMsg() = \"No matching function for overloaded '%s'\";\n", symname);
+ Printv(f->code, "SWIG_FAIL();\n", NIL);
+
+ Printv(f->code, "}\n", NIL);
+ Wrapper_print(f, s_wrappers);
+
+ DelWrapper(f);
+ Delete(dispatch);
+ Delete(tmp);
+ Delete(wname);
+ }
+
+ /* ------------------------------------------------------------
+ * functionWrapper()
+ * ------------------------------------------------------------ */
+
+ /* Helper method for PHP::functionWrapper */
+ bool is_class(SwigType *t) {
+ Node *n = classLookup(t);
+ if (n) {
+ String *r = Getattr(n, "php:proxy"); // Set by classDeclaration()
+ if (!r)
+ r = Getattr(n, "sym:name"); // Not seen by classDeclaration yet, but this is the name
+ if (r)
+ return true;
+ }
+ return false;
+ }
+
+ virtual int functionWrapper(Node *n) {
+ String *name = GetChar(n, "name");
+ String *iname = GetChar(n, "sym:name");
+ SwigType *d = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *nodeType = Getattr(n, "nodeType");
+ int newobject = GetFlag(n, "feature:new");
+ int constructor = (Cmp(nodeType, "constructor") == 0);
+
+ Parm *p;
+ int i;
+ int numopt;
+ String *tm;
+ Wrapper *f;
+
+ String *wname;
+ int overloaded = 0;
+ String *overname = 0;
+
+ if (Cmp(nodeType, "destructor") == 0) {
+ // We just generate the Zend List Destructor and let Zend manage the
+ // reference counting. There's no explicit destructor, but the user can
+ // just do `$obj = null;' to remove a reference to an object.
+ return CreateZendListDestructor(n);
+ }
+ // Test for overloading;
+ if (Getattr(n, "sym:overloaded")) {
+ overloaded = 1;
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+ }
+
+ wname = Swig_name_wrapper(iname);
+ if (overname) {
+ Printf(wname, "%s", overname);
+ }
+
+ f = NewWrapper();
+
+ String *outarg = NewStringEmpty();
+ String *cleanup = NewStringEmpty();
+
+ Printv(f->def, "ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL);
+
+ emit_parameter_variables(l, f);
+ /* Attach standard typemaps */
+
+ emit_attach_parmmaps(l, f);
+ // Not issued for overloaded functions.
+ if (!overloaded) {
+ create_command(iname, wname, n);
+ }
+
+ // wrap:parms is used by overload resolution.
+ Setattr(n, "wrap:parms", l);
+
+ int num_arguments = emit_num_arguments(l);
+ int num_required = emit_num_required(l);
+ numopt = num_arguments - num_required;
+
+ if (wrapperType == directorconstructor)
+ num_arguments++;
+
+ if (num_arguments > 0) {
+ String *args = NewStringEmpty();
+ if (wrapperType == directorconstructor)
+ Wrapper_add_local(f, "arg0", "zval * arg0");
+ Printf(args, "zval args[%d]", num_arguments);
+ Wrapper_add_local(f, "args", args);
+ Delete(args);
+ args = NULL;
+ }
+
+ // This generated code may be called:
+ // 1) as an object method, or
+ // 2) as a class-method/function (without a "this_ptr")
+ // Option (1) has "this_ptr" for "this", option (2) needs it as
+ // first parameter
+
+ // NOTE: possible we ignore this_ptr as a param for native constructor
+
+ Printf(f->code, "SWIG_ResetError();\n");
+
+ if (numopt > 0) { // membervariable wrappers do not have optional args
+ Wrapper_add_local(f, "arg_count", "int arg_count");
+ Printf(f->code, "arg_count = ZEND_NUM_ARGS();\n");
+ Printf(f->code, "if(arg_count<%d || arg_count>%d ||\n", num_required, num_arguments);
+ Printf(f->code, " zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)\n");
+ Printf(f->code, "\tWRONG_PARAM_COUNT;\n\n");
+ } else {
+ if (num_arguments == 0) {
+ Printf(f->code, "if(ZEND_NUM_ARGS() != 0) {\n");
+ } else {
+ Printf(f->code, "if(ZEND_NUM_ARGS() != %d || zend_get_parameters_array_ex(%d, args) != SUCCESS) {\n", num_arguments, num_arguments);
+ }
+ Printf(f->code, "WRONG_PARAM_COUNT;\n}\n\n");
+ }
+ if (wrapperType == directorconstructor)
+ Printf(f->code, "arg0 = &args[0];\n \n");
+
+ /* Now convert from PHP to C variables */
+ // At this point, argcount if used is the number of deliberately passed args
+ // not including this_ptr even if it is used.
+ // It means error messages may be out by argbase with error
+ // reports. We can either take argbase into account when raising
+ // errors, or find a better way of dealing with _thisptr.
+ // I would like, if objects are wrapped, to assume _thisptr is always
+ // _this and not the first argument.
+ // This may mean looking at Language::memberfunctionHandler
+
+ int limit = num_arguments;
+ if (wrapperType == directorconstructor)
+ limit--;
+ for (i = 0, p = l; i < limit; i++) {
+ String *source;
+
+ /* Skip ignored arguments */
+ //while (Getattr(p,"tmap:ignore")) { p = Getattr(p,"tmap:ignore:next");}
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+
+ if (wrapperType == directorconstructor) {
+ source = NewStringf("args[%d]", i+1);
+ } else {
+ source = NewStringf("args[%d]", i);
+ }
+
+ String *ln = Getattr(p, "lname");
+
+ /* Check if optional */
+ if (i >= num_required) {
+ Printf(f->code, "\tif(arg_count > %d) {\n", i);
+ }
+
+ if ((tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$source", &source);
+ Replaceall(tm, "$target", ln);
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source);
+ Printf(f->code, "%s\n", tm);
+ if (i == 0 && Getattr(p, "self")) {
+ Printf(f->code, "\tif(!arg1) SWIG_PHP_Error(E_ERROR, \"this pointer is NULL\");\n");
+ }
+ p = Getattr(p, "tmap:in:next");
+ if (i >= num_required) {
+ Printf(f->code, "}\n");
+ }
+ continue;
+ } else {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
+ }
+ if (i >= num_required) {
+ Printf(f->code, "\t}\n");
+ }
+ Delete(source);
+ }
+
+ if (is_member_director(n)) {
+ Wrapper_add_local(f, "upcall", "bool upcall = false");
+ Printf(f->code, "upcall = !Swig::Director::swig_is_overridden_method(\"%s%s\", \"%s\");\n",
+ prefix, Swig_class_name(Swig_methodclass(n)), name);
+ }
+
+ Swig_director_emit_dynamic_cast(n, f);
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ for (i = 0, p = l; p; i++) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert argument output code */
+ bool hasargout = false;
+ for (i = 0, p = l; p; i++) {
+ if ((tm = Getattr(p, "tmap:argout")) && Len(tm)) {
+ hasargout = true;
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+ // Replaceall(tm,"$input",Getattr(p,"lname"));
+ Replaceall(tm, "$target", "return_value");
+ Replaceall(tm, "$result", "return_value");
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ Setattr(n, "wrap:name", wname);
+
+ /* emit function call */
+ String *actioncode = emit_action(n);
+
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Replaceall(tm, "$target", "return_value");
+ Replaceall(tm, "$result", "return_value");
+ Replaceall(tm, "$owner", newobject ? "1" : "0");
+ Printf(f->code, "%s\n", tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name);
+ }
+ emit_return_variable(n, d, f);
+
+ if (outarg) {
+ Printv(f->code, outarg, NIL);
+ }
+
+ if (cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+
+ /* Look to see if there is any newfree cleanup code */
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+
+ Printf(f->code, "thrown:\n");
+ Printf(f->code, "return;\n");
+
+ /* Error handling code */
+ Printf(f->code, "fail:\n");
+ Printv(f->code, cleanup, NIL);
+ Append(f->code, "SWIG_FAIL();\n");
+
+ Printf(f->code, "}\n");
+
+ Replaceall(f->code, "$cleanup", cleanup);
+ Replaceall(f->code, "$symname", iname);
+
+ Wrapper_print(f, s_wrappers);
+ DelWrapper(f);
+ f = NULL;
+
+ if (overloaded && !Getattr(n, "sym:nextSibling")) {
+ dispatchFunction(n);
+ }
+
+ Delete(wname);
+ wname = NULL;
+
+ if (!shadow) {
+ return SWIG_OK;
+ }
+
+ // Handle getters and setters.
+ if (wrapperType == membervar) {
+ const char *p = Char(iname);
+ if (strlen(p) > 4) {
+ p += strlen(p) - 4;
+ String *varname = Getattr(n, "membervariableHandler:sym:name");
+ if (strcmp(p, "_get") == 0) {
+ Setattr(shadow_get_vars, varname, Getattr(n, "type"));
+ } else if (strcmp(p, "_set") == 0) {
+ Setattr(shadow_set_vars, varname, iname);
+ }
+ }
+ return SWIG_OK;
+ }
+
+ // Only look at non-overloaded methods and the last entry in each overload
+ // chain (we check the last so that wrap:parms and wrap:name have been set
+ // for them all).
+ if (overloaded && Getattr(n, "sym:nextSibling") != 0)
+ return SWIG_OK;
+
+ if (!s_oowrappers)
+ s_oowrappers = NewStringEmpty();
+
+ if (newobject || wrapperType == memberfn || wrapperType == staticmemberfn || wrapperType == standard || wrapperType == staticmembervar) {
+ bool handle_as_overload = false;
+ String **arg_names;
+ String **arg_values;
+ unsigned char * byref;
+ // Method or static method or plain function.
+ const char *methodname = 0;
+ String *output = s_oowrappers;
+ if (constructor) {
+ class_has_ctor = true;
+ // Skip the Foo:: prefix.
+ char *ptr = strrchr(GetChar(current_class, "sym:name"), ':');
+ if (ptr) {
+ ptr++;
+ } else {
+ ptr = GetChar(current_class, "sym:name");
+ }
+ if (strcmp(ptr, GetChar(n, "constructorHandler:sym:name")) == 0) {
+ methodname = "__construct";
+ } else {
+ // The class has multiple constructors and this one is
+ // renamed, so this will be a static factory function
+ methodname = GetChar(n, "constructorHandler:sym:name");
+ }
+ } else if (wrapperType == memberfn) {
+ methodname = Char(Getattr(n, "memberfunctionHandler:sym:name"));
+ } else if (wrapperType == staticmemberfn) {
+ methodname = Char(Getattr(n, "staticmemberfunctionHandler:sym:name"));
+ } else if (wrapperType == staticmembervar) {
+ // Static member variable, wrapped as a function due to PHP limitations.
+ methodname = Char(Getattr(n, "staticmembervariableHandler:sym:name"));
+ } else { // wrapperType == standard
+ methodname = Char(iname);
+ if (!s_fakeoowrappers)
+ s_fakeoowrappers = NewStringEmpty();
+ output = s_fakeoowrappers;
+ }
+
+ bool really_overloaded = overloaded ? true : false;
+ int min_num_of_arguments = emit_num_required(l);
+ int max_num_of_arguments = emit_num_arguments(l);
+
+ Hash *ret_types = NewHash();
+ Setattr(ret_types, d, d);
+
+ bool non_void_return = (Cmp(d, "void") != 0);
+
+ if (overloaded) {
+ // Look at all the overloaded versions of this method in turn to
+ // decide if it's really an overloaded method, or just one where some
+ // parameters have default values.
+ Node *o = Getattr(n, "sym:overloaded");
+ while (o) {
+ if (o == n) {
+ o = Getattr(o, "sym:nextSibling");
+ continue;
+ }
+
+ SwigType *d2 = Getattr(o, "type");
+ if (!d2) {
+ assert(constructor);
+ } else if (!Getattr(ret_types, d2)) {
+ Setattr(ret_types, d2, d2);
+ non_void_return = non_void_return || (Cmp(d2, "void") != 0);
+ }
+
+ ParmList *l2 = Getattr(o, "wrap:parms");
+ int num_arguments = emit_num_arguments(l2);
+ int num_required = emit_num_required(l2);
+ if (num_required < min_num_of_arguments)
+ min_num_of_arguments = num_required;
+
+ if (num_arguments > max_num_of_arguments) {
+ max_num_of_arguments = num_arguments;
+ }
+ o = Getattr(o, "sym:nextSibling");
+ }
+
+ o = Getattr(n, "sym:overloaded");
+ while (o) {
+ if (o == n) {
+ o = Getattr(o, "sym:nextSibling");
+ continue;
+ }
+
+ ParmList *l2 = Getattr(o, "wrap:parms");
+ Parm *p = l, *p2 = l2;
+ if (wrapperType == memberfn) {
+ p = nextSibling(p);
+ p2 = nextSibling(p2);
+ }
+ while (p && p2) {
+ if (Cmp(Getattr(p, "type"), Getattr(p2, "type")) != 0)
+ break;
+ if (Cmp(Getattr(p, "name"), Getattr(p2, "name")) != 0)
+ break;
+ String *value = Getattr(p, "value");
+ String *value2 = Getattr(p2, "value");
+ if (value && !value2)
+ break;
+ if (!value && value2)
+ break;
+ if (value) {
+ if (Cmp(value, value2) != 0)
+ break;
+ }
+ p = nextSibling(p);
+ p2 = nextSibling(p2);
+ }
+ if (p && p2)
+ break;
+ // One parameter list is a prefix of the other, so check that all
+ // remaining parameters of the longer list are optional.
+ if (p2)
+ p = p2;
+ while (p && Getattr(p, "value"))
+ p = nextSibling(p);
+ if (p)
+ break;
+ o = Getattr(o, "sym:nextSibling");
+ }
+ if (!o) {
+ // This "overloaded method" is really just one with default args.
+ really_overloaded = false;
+ }
+ }
+
+ if (wrapperType == memberfn) {
+ // Allow for the "this" pointer.
+ --min_num_of_arguments;
+ --max_num_of_arguments;
+ }
+
+ arg_names = (String **) malloc(max_num_of_arguments * sizeof(String *));
+ if (!arg_names) {
+ /* FIXME: How should this be handled? The rest of SWIG just seems
+ * to not bother checking for malloc failing! */
+ fprintf(stderr, "Malloc failed!\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+ for (i = 0; i < max_num_of_arguments; ++i) {
+ arg_names[i] = NULL;
+ }
+
+ arg_values = (String **) malloc(max_num_of_arguments * sizeof(String *));
+ byref = (unsigned char *) malloc(max_num_of_arguments);
+ if (!arg_values || !byref) {
+ /* FIXME: How should this be handled? The rest of SWIG just seems
+ * to not bother checking for malloc failing! */
+ fprintf(stderr, "Malloc failed!\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+ for (i = 0; i < max_num_of_arguments; ++i) {
+ arg_values[i] = NULL;
+ byref[i] = false;
+ }
+
+ Node *o;
+ if (overloaded) {
+ o = Getattr(n, "sym:overloaded");
+ } else {
+ o = n;
+ }
+ while (o) {
+ int argno = 0;
+ Parm *p = Getattr(o, "wrap:parms");
+ if (wrapperType == memberfn)
+ p = nextSibling(p);
+ while (p) {
+ if (GetInt(p, "tmap:in:numinputs") == 0) {
+ p = nextSibling(p);
+ continue;
+ }
+ assert(0 <= argno && argno < max_num_of_arguments);
+ byref[argno] = GetFlag(p, "tmap:in:byref");
+ String *&pname = arg_names[argno];
+ const char *pname_cstr = GetChar(p, "name");
+ // Just get rid of the C++ namespace part for now.
+ const char *ptr = NULL;
+ if (pname_cstr && (ptr = strrchr(pname_cstr, ':'))) {
+ pname_cstr = ptr + 1;
+ }
+ if (!pname_cstr) {
+ // Unnamed parameter, e.g. int foo(int);
+ } else if (!pname) {
+ pname = NewString(pname_cstr);
+ } else {
+ size_t len = strlen(pname_cstr);
+ size_t spc = 0;
+ size_t len_pname = strlen(Char(pname));
+ while (spc + len <= len_pname) {
+ if (strncmp(pname_cstr, Char(pname) + spc, len) == 0) {
+ char ch = ((char *) Char(pname))[spc + len];
+ if (ch == '\0' || ch == ' ') {
+ // Already have this pname_cstr.
+ pname_cstr = NULL;
+ break;
+ }
+ }
+ char *p = strchr(Char(pname) + spc, ' ');
+ if (!p)
+ break;
+ spc = (p + 4) - Char(pname);
+ }
+ if (pname_cstr) {
+ Printf(pname, " or_%s", pname_cstr);
+ }
+ }
+ String *value = NewString(Getattr(p, "value"));
+ if (Len(value)) {
+ /* Check that value is a valid constant in PHP (and adjust it if
+ * necessary, or replace it with "?" if it's just not valid). */
+ SwigType *type = Getattr(p, "type");
+ switch (SwigType_type(type)) {
+ case T_BOOL: {
+ if (Strcmp(value, "true") == 0 || Strcmp(value, "false") == 0)
+ break;
+ char *p;
+ errno = 0;
+ long n = strtol(Char(value), &p, 0);
+ Clear(value);
+ if (errno || *p) {
+ Append(value, "?");
+ } else if (n) {
+ Append(value, "true");
+ } else {
+ Append(value, "false");
+ }
+ break;
+ }
+ case T_CHAR:
+ case T_SCHAR:
+ case T_SHORT:
+ case T_INT:
+ case T_LONG:
+ case T_LONGLONG: {
+ char *p;
+ errno = 0;
+ long n = strtol(Char(value), &p, 0);
+ (void) n;
+ if (errno || *p) {
+ Clear(value);
+ Append(value, "?");
+ }
+ break;
+ }
+ case T_UCHAR:
+ case T_USHORT:
+ case T_UINT:
+ case T_ULONG:
+ case T_ULONGLONG: {
+ char *p;
+ errno = 0;
+ unsigned int n = strtoul(Char(value), &p, 0);
+ (void) n;
+ if (errno || *p) {
+ Clear(value);
+ Append(value, "?");
+ }
+ break;
+ }
+ case T_FLOAT:
+ case T_DOUBLE:
+ case T_LONGDOUBLE: {
+ char *p;
+ errno = 0;
+ /* FIXME: strtod is locale dependent... */
+ double val = strtod(Char(value), &p);
+ if (errno || *p) {
+ Clear(value);
+ Append(value, "?");
+ } else if (strchr(Char(value), '.') == 0) {
+ // Ensure value is a double constant, not an integer one.
+ Append(value, ".0");
+ double val2 = strtod(Char(value), &p);
+ if (errno || *p || val != val2) {
+ Clear(value);
+ Append(value, "?");
+ }
+ }
+ break;
+ }
+ case T_STRING:
+ if (Len(value) < 2) {
+ // How can a string (including "" be less than 2 characters?)
+ Clear(value);
+ Append(value, "?");
+ } else {
+ const char *v = Char(value);
+ if (v[0] != '"' || v[Len(value) - 1] != '"') {
+ Clear(value);
+ Append(value, "?");
+ }
+ // Strings containing "$" require special handling, but we do
+ // that later.
+ }
+ break;
+ case T_VOID:
+ assert(false);
+ break;
+ case T_POINTER: {
+ const char *v = Char(value);
+ if (v[0] == '(') {
+ // Handle "(void*)0", "(TYPE*)0", "(char*)NULL", etc.
+ v += strcspn(v + 1, "*()") + 1;
+ if (*v == '*') {
+ do {
+ v++;
+ v += strspn(v, " \t");
+ } while (*v == '*');
+ if (*v++ == ')') {
+ v += strspn(v, " \t");
+ String * old = value;
+ value = NewString(v);
+ Delete(old);
+ }
+ }
+ }
+ if (Strcmp(value, "NULL") == 0 ||
+ Strcmp(value, "nullptr") == 0 ||
+ Strcmp(value, "0") == 0 ||
+ Strcmp(value, "0L") == 0) {
+ Clear(value);
+ Append(value, "null");
+ } else {
+ Clear(value);
+ Append(value, "?");
+ }
+ break;
+ }
+ default:
+ /* Safe default */
+ Clear(value);
+ Append(value, "?");
+ break;
+ }
+
+ if (!arg_values[argno]) {
+ arg_values[argno] = value;
+ value = NULL;
+ } else if (Cmp(arg_values[argno], value) != 0) {
+ // If a parameter has two different default values in
+ // different overloaded forms of the function, we can't
+ // set its default in PHP. Flag this by setting its
+ // default to `?'.
+ Delete(arg_values[argno]);
+ arg_values[argno] = NewString("?");
+ }
+ } else if (arg_values[argno]) {
+ // This argument already has a default value in another overloaded
+ // form, but doesn't in this form. So don't try to do anything
+ // clever, just let the C wrappers resolve the overload and set the
+ // default values.
+ //
+ // This handling is safe, but I'm wondering if it may be overly
+ // conservative (FIXME) in some cases. It seems it's only bad when
+ // there's an overloaded form with the appropriate number of
+ // parameters which doesn't want the default value, but I need to
+ // think about this more.
+ Delete(arg_values[argno]);
+ arg_values[argno] = NewString("?");
+ }
+ Delete(value);
+ p = nextSibling(p);
+ ++argno;
+ }
+ if (!really_overloaded)
+ break;
+ o = Getattr(o, "sym:nextSibling");
+ }
+
+ /* Clean up any parameters which haven't yet got names, or whose
+ * names clash. */
+ Hash *seen = NewHash();
+ /* We need $this to refer to the current class, so can't allow it
+ * to be used as a parameter. */
+ Setattr(seen, "this", seen);
+
+ for (int argno = 0; argno < max_num_of_arguments; ++argno) {
+ String *&pname = arg_names[argno];
+ if (pname) {
+ Replaceall(pname, " ", "_");
+ } else {
+ /* We get here if the SWIG .i file has "int foo(int);" */
+ pname = NewStringEmpty();
+ Printf(pname, "arg%d", argno + 1);
+ }
+ // Check if we've already used this parameter name.
+ while (Getattr(seen, pname)) {
+ // Append "_" to clashing names until they stop clashing...
+ Printf(pname, "_");
+ }
+ Setattr(seen, Char(pname), seen);
+
+ if (arg_values[argno] && Cmp(arg_values[argno], "?") == 0) {
+ handle_as_overload = true;
+ }
+ }
+ Delete(seen);
+ seen = NULL;
+
+ String *invoke = NewStringEmpty();
+ String *prepare = NewStringEmpty();
+ String *args = NewStringEmpty();
+
+ if (!handle_as_overload && !(really_overloaded && max_num_of_arguments > min_num_of_arguments)) {
+ Printf(invoke, "%s(", iname);
+ if (wrapperType == memberfn) {
+ Printf(invoke, "$this->%s", SWIG_PTR);
+ }
+ for (int i = 0; i < max_num_of_arguments; ++i) {
+ if (i)
+ Printf(args, ",");
+ if (i || wrapperType == memberfn)
+ Printf(invoke, ",");
+ if (byref[i]) Printf(args, "&");
+ String *value = arg_values[i];
+ if (value) {
+ const char *v = Char(value);
+ if (v[0] == '"') {
+ /* In a PHP double quoted string, $ needs to be escaped as \$. */
+ Replaceall(value, "$", "\\$");
+ }
+ Printf(args, "$%s=%s", arg_names[i], value);
+ } else if (constructor && strcmp(methodname, "__construct") == 0 && i >= 1 && i < min_num_of_arguments) {
+ // We need to be able to call __construct($resource).
+ Printf(args, "$%s=null", arg_names[i]);
+ } else {
+ Printf(args, "$%s", arg_names[i]);
+ }
+ Printf(invoke, "$%s", arg_names[i]);
+ }
+ Printf(invoke, ")");
+ } else {
+ int i;
+ for (i = 0; i < min_num_of_arguments; ++i) {
+ if (i)
+ Printf(args, ",");
+ Printf(args, "$%s", arg_names[i]);
+ }
+ String *invoke_args = NewStringEmpty();
+ if (wrapperType == memberfn) {
+ Printf(invoke_args, "$this->%s", SWIG_PTR);
+ if (min_num_of_arguments > 0)
+ Printf(invoke_args, ",");
+ }
+ Printf(invoke_args, "%s", args);
+ if (constructor && min_num_of_arguments > 1) {
+ // We need to be able to call __construct($resource).
+ Clear(args);
+ Printf(args, "$%s", arg_names[0]);
+ for (i = 1; i < min_num_of_arguments; ++i) {
+ Printf(args, ",");
+ Printf(args, "$%s=null", arg_names[i]);
+ }
+ }
+ bool had_a_case = false;
+ int last_handled_i = i - 1;
+ for (; i < max_num_of_arguments; ++i) {
+ if (i)
+ Printf(args, ",");
+ const char *value = Char(arg_values[i]);
+ // FIXME: (really_overloaded && handle_as_overload) is perhaps a
+ // little conservative, but it doesn't hit any cases that it
+ // shouldn't for Xapian at least (and we need it to handle
+ // "Enquire::get_mset()" correctly).
+ bool non_php_default = ((really_overloaded && handle_as_overload) ||
+ !value || strcmp(value, "?") == 0);
+ if (non_php_default)
+ value = "null";
+ Printf(args, "$%s=%s", arg_names[i], value);
+ if (non_php_default) {
+ if (!had_a_case) {
+ Printf(prepare, "\t\tswitch (func_num_args()) {\n");
+ had_a_case = true;
+ }
+ Printf(prepare, "\t\t");
+ while (last_handled_i < i) {
+ Printf(prepare, "case %d: ", ++last_handled_i);
+ }
+ if (non_void_return) {
+ if ((!directorsEnabled() || !Swig_directorclass(n)) && !constructor) {
+ Append(prepare, "$r=");
+ } else if (wrapperType == staticmemberfn || wrapperType == staticmembervar) {
+ Append(prepare, "$r=");
+ } else {
+ Printf(prepare, "$this->%s=", SWIG_PTR);
+ }
+ }
+ if (!directorsEnabled() || !Swig_directorclass(n) || !constructor) {
+ Printf(prepare, "%s(%s); break;\n", iname, invoke_args);
+ } else if (!i) {
+ Printf(prepare, "%s($_this%s); break;\n", iname, invoke_args);
+ } else {
+ Printf(prepare, "%s($_this, %s); break;\n", iname, invoke_args);
+ }
+ }
+ if (i || wrapperType == memberfn)
+ Printf(invoke_args, ",");
+ Printf(invoke_args, "$%s", arg_names[i]);
+ }
+ Printf(prepare, "\t\t");
+ if (had_a_case)
+ Printf(prepare, "default: ");
+ if (non_void_return) {
+ if ((!directorsEnabled() || !Swig_directorclass(n)) && !constructor) {
+ Append(prepare, "$r=");
+ } else if (wrapperType == staticmemberfn || wrapperType == staticmembervar) {
+ Append(prepare, "$r=");
+ } else {
+ Printf(prepare, "$this->%s=", SWIG_PTR);
+ }
+ }
+
+ if (!directorsEnabled() || !Swig_directorclass(n) || !constructor) {
+ Printf(prepare, "%s(%s);\n", iname, invoke_args);
+ } else {
+ Printf(prepare, "%s($_this, %s);\n", iname, invoke_args);
+ }
+ if (had_a_case)
+ Printf(prepare, "\t\t}\n");
+ Delete(invoke_args);
+ Printf(invoke, "$r");
+ }
+
+ Printf(output, "\n");
+ // If it's a member function or a class constructor...
+ if (wrapperType == memberfn || (constructor && current_class)) {
+ String *acc = NewString(Getattr(n, "access"));
+ // If a base has the same method with public access, then PHP
+ // requires to have it here as public as well
+ Node *bases = Getattr(Swig_methodclass(n), "bases");
+ if (bases && Strcmp(acc, "public") != 0) {
+ String *warnmsg = 0;
+ int haspublicbase = 0;
+ Iterator i = First(bases);
+ while (i.item) {
+ Node *j = firstChild(i.item);
+ while (j) {
+ String *jname = Getattr(j, "name");
+ if (!jname || Strcmp(jname, Getattr(n, "name")) != 0) {
+ j = nextSibling(j);
+ continue;
+ }
+ if (Strcmp(nodeType(j), "cdecl") == 0) {
+ if (!Getattr(j, "access") || checkAttribute(j, "access", "public")) {
+ haspublicbase = 1;
+ }
+ } else if (Strcmp(nodeType(j), "using") == 0 && firstChild(j) && Strcmp(nodeType(firstChild(j)), "cdecl") == 0) {
+ if (!Getattr(firstChild(j), "access") || checkAttribute(firstChild(j), "access", "public")) {
+ haspublicbase = 1;
+ }
+ }
+ if (haspublicbase) {
+ warnmsg = NewStringf("Modifying the access of '%s::%s' to public, as the base '%s' has it as public as well.\n", Getattr(current_class, "classtype"), Getattr(n, "name"), Getattr(i.item, "classtype"));
+ break;
+ }
+ j = nextSibling(j);
+ }
+ i = Next(i);
+ if (haspublicbase) {
+ break;
+ }
+ }
+ if (Getattr(n, "access") && haspublicbase) {
+ Delete(acc);
+ acc = NewStringEmpty(); // implicitly public
+ Swig_warning(WARN_PHP_PUBLIC_BASE, input_file, line_number, Char(warnmsg));
+ Delete(warnmsg);
+ }
+ }
+
+ if (Cmp(acc, "public") == 0) {
+ // The default visibility for methods is public, so don't specify
+ // that explicitly to keep the wrapper size down.
+ Delete(acc);
+ acc = NewStringEmpty();
+ } else if (Cmp(acc, "") != 0) {
+ Append(acc, " ");
+ }
+
+ if (constructor) {
+ // Discriminate between the PHP constructor and a C++ constructor
+ // renamed to become a factory function in PHP.
+ bool php_constructor = (strcmp(methodname, "__construct") == 0);
+ const char * arg0 = NULL;
+ if (max_num_of_arguments > 0) {
+ arg0 = Char(arg_names[0]);
+ } else if (php_constructor) {
+ // The PHP constructor needs to be able to wrap a resource, but a
+ // renamed constructor doesn't.
+ arg0 = "res";
+ Delete(args);
+ args = NewString("$res=null");
+ }
+ String *mangled_type = SwigType_manglestr(Getattr(n, "type"));
+ if (!php_constructor) {
+ // A renamed constructor should be a static method.
+ Append(acc, "static ");
+ }
+ Printf(output, "\t%sfunction %s(%s) {\n", acc, methodname, args);
+ if (php_constructor) {
+ // The PHP constructor needs to be able to wrap a resource, but a
+ // renamed constructor doesn't.
+ Printf(output, "\t\tif (is_resource($%s) && get_resource_type($%s) === '%s') {\n", arg0, arg0, mangled_type);
+ Printf(output, "\t\t\t$this->%s=$%s;\n", SWIG_PTR, arg0);
+ Printf(output, "\t\t\treturn;\n");
+ Printf(output, "\t\t}\n");
+ }
+ } else {
+ Printf(output, "\t%sfunction %s(%s) {\n", acc, methodname, args);
+ }
+ Delete(acc);
+ } else if (wrapperType == staticmembervar) {
+ // We're called twice for a writable static member variable - first
+ // with "foo_set" and then with "foo_get" - so generate half the
+ // wrapper function each time.
+ //
+ // For a const static member, we only get called once.
+ static bool started = false;
+ if (!started) {
+ Printf(output, "\tstatic function %s() {\n", methodname);
+ if (max_num_of_arguments) {
+ // Setter.
+ Printf(output, "\t\tif (func_num_args()) {\n");
+ Printf(output, "\t\t\t%s(func_get_arg(0));\n", iname);
+ Printf(output, "\t\t\treturn;\n");
+ Printf(output, "\t\t}\n");
+ started = true;
+ goto done;
+ }
+ }
+ started = false;
+ } else {
+ Printf(output, "\tstatic function %s(%s) {\n", methodname, args);
+ }
+
+ if (!constructor)
+ Printf(output, "%s", prepare);
+ if (constructor) {
+ if (!directorsEnabled() || !Swig_directorclass(n)) {
+ if (!Len(prepare)) {
+ if (strcmp(methodname, "__construct") == 0) {
+ Printf(output, "\t\t$this->%s=%s;\n", SWIG_PTR, invoke);
+ } else {
+ String *classname = Swig_class_name(current_class);
+ Printf(output, "\t\treturn new %s%s(%s);\n", prefix, classname, invoke);
+ }
+ }
+ } else {
+ Node *parent = Swig_methodclass(n);
+ String *classname = Swig_class_name(parent);
+ Printf(output, "\t\tif (get_class($this) === '%s%s') {\n", prefix, classname);
+ Printf(output, "\t\t\t$_this = null;\n");
+ Printf(output, "\t\t} else {\n");
+ Printf(output, "\t\t\t$_this = $this;\n");
+ Printf(output, "\t\t}\n");
+ if (!Len(prepare)) {
+ if (num_arguments > 1) {
+ Printf(output, "\t\t$this->%s=%s($_this, %s);\n", SWIG_PTR, iname, args);
+ } else {
+ Printf(output, "\t\t$this->%s=%s($_this);\n", SWIG_PTR, iname);
+ }
+ }
+ }
+ Printf(output, "%s", prepare);
+ } else if (!non_void_return && !hasargout) {
+ if (Cmp(invoke, "$r") != 0)
+ Printf(output, "\t\t%s;\n", invoke);
+ } else if (is_class(d)) {
+ if (Cmp(invoke, "$r") != 0)
+ Printf(output, "\t\t$r=%s;\n", invoke);
+ if (Len(ret_types) == 1) {
+ /* If d is abstract we can't create a new wrapper type d. */
+ Node *d_class = classLookup(d);
+ int is_abstract = 0;
+ if (Getattr(d_class, "abstracts")) {
+ is_abstract = 1;
+ }
+ if (newobject || !is_abstract) {
+ Printf(output, "\t\tif (is_resource($r)) {\n");
+ if (Getattr(classLookup(Getattr(n, "type")), "module")) {
+ /*
+ * _p_Foo -> Foo, _p_ns__Bar -> Bar
+ * TODO: do this in a more elegant way
+ */
+ if (Len(prefix) == 0) {
+ Printf(output, "\t\t\t$c=substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));\n");
+ } else {
+ Printf(output, "\t\t\t$c='%s'.substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));\n", prefix);
+ }
+ Printf(output, "\t\t\tif (class_exists($c)) return new $c($r);\n");
+ Printf(output, "\t\t\treturn new %s%s($r);\n", prefix, Getattr(classLookup(d), "sym:name"));
+ } else {
+ Printf(output, "\t\t\t$c = new stdClass();\n");
+ Printf(output, "\t\t\t$c->" SWIG_PTR " = $r;\n");
+ Printf(output, "\t\t\treturn $c;\n");
+ }
+ Printf(output, "\t\t}\n\t\treturn $r;\n");
+ } else {
+ Printf(output, "\t\t$this->%s = $r;\n", SWIG_PTR);
+ Printf(output, "\t\treturn $this;\n");
+ }
+ } else {
+ Printf(output, "\t\tif (!is_resource($r)) return $r;\n");
+ String *wrapobj = NULL;
+ String *common = NULL;
+ Iterator i = First(ret_types);
+ while (i.item) {
+ SwigType *ret_type = i.item;
+ i = Next(i);
+ String *mangled = NewString("_p");
+ Printf(mangled, "%s", SwigType_manglestr(ret_type));
+ Node *class_node = Getattr(zend_types, mangled);
+ if (!class_node) {
+ /* This is needed when we're returning a pointer to a type
+ * rather than returning the type by value or reference. */
+ Delete(mangled);
+ mangled = NewString(SwigType_manglestr(ret_type));
+ class_node = Getattr(zend_types, mangled);
+ if (!class_node) {
+ // Return type isn't an object, so will be handled by the
+ // !is_resource() check before the switch.
+ continue;
+ }
+ }
+ const char *classname = GetChar(class_node, "sym:name");
+ if (!classname)
+ classname = GetChar(class_node, "name");
+ String * action = NewStringEmpty();
+ if (classname)
+ Printf(action, "return new %s%s($r);\n", prefix, classname);
+ else
+ Printf(action, "return $r;\n");
+ if (!wrapobj) {
+ wrapobj = NewString("\t\tswitch (get_resource_type($r)) {\n");
+ common = action;
+ } else {
+ if (common && Cmp(common, action) != 0) {
+ Delete(common);
+ common = NULL;
+ }
+ }
+ Printf(wrapobj, "\t\t");
+ if (i.item) {
+ Printf(wrapobj, "case '%s': ", mangled);
+ } else {
+ Printf(wrapobj, "default: ");
+ }
+ Printv(wrapobj, action, NIL);
+ if (action != common) Delete(action);
+ Delete(mangled);
+ }
+ Printf(wrapobj, "\t\t}\n");
+ if (common) {
+ // All cases have the same action, so eliminate the switch
+ // wrapper.
+ Printf(output, "\t\t%s", common);
+ Delete(common);
+ } else {
+ Printv(output, wrapobj, NIL);
+ }
+ Delete(wrapobj);
+ }
+ } else {
+ if (non_void_return || hasargout) {
+ Printf(output, "\t\treturn %s;\n", invoke);
+ } else if (Cmp(invoke, "$r") != 0) {
+ Printf(output, "\t\t%s;\n", invoke);
+ }
+ }
+ Printf(output, "\t}\n");
+
+done:
+ Delete(prepare);
+ Delete(invoke);
+ free(arg_values);
+
+ Delete(args);
+ args = NULL;
+
+ for (int i = 0; i < max_num_of_arguments; ++i) {
+ Delete(arg_names[i]);
+ }
+ free(arg_names);
+ arg_names = NULL;
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * globalvariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int globalvariableHandler(Node *n) {
+ char *name = GetChar(n, "name");
+ char *iname = GetChar(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+ String *tm;
+
+ /* First do the wrappers such as name_set(), name_get()
+ * as provided by the baseclass's implementation of variableWrapper
+ */
+ if (Language::globalvariableHandler(n) == SWIG_NOWRAP) {
+ return SWIG_NOWRAP;
+ }
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ /* First link C variables to PHP */
+
+ tm = Swig_typemap_lookup("varinit", n, name, 0);
+ if (tm) {
+ Replaceall(tm, "$target", name);
+ Printf(s_vinit, "%s\n", tm);
+ } else {
+ Swig_error(input_file, line_number, "Unable to link with type %s\n", SwigType_str(t, 0));
+ }
+
+ /* Now generate PHP -> C sync blocks */
+ /*
+ tm = Swig_typemap_lookup("varin", n, name, 0);
+ if(tm) {
+ Replaceall(tm, "$symname", iname);
+ Printf(f_c->code, "%s\n", tm);
+ } else {
+ Swig_error(input_file, line_number, "Unable to link with type %s\n", SwigType_str(t, 0));
+ }
+ */
+ /* Now generate C -> PHP sync blocks */
+ /*
+ if(!GetFlag(n,"feature:immutable")) {
+
+ tm = Swig_typemap_lookup("varout", n, name, 0);
+ if(tm) {
+ Replaceall(tm, "$symname", iname);
+ Printf(f_php->code, "%s\n", tm);
+ } else {
+ Swig_error(input_file, line_number, "Unable to link with type %s\n", SwigType_str(t, 0));
+ }
+ }
+ */
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ String *name = GetChar(n, "name");
+ String *iname = GetChar(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *rawval = Getattr(n, "rawval");
+ String *value = rawval ? rawval : Getattr(n, "value");
+ String *tm;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ SwigType_remember(type);
+
+ if ((tm = Swig_typemap_lookup("consttab", n, name, 0))) {
+ Replaceall(tm, "$source", value);
+ Replaceall(tm, "$target", name);
+ Replaceall(tm, "$value", value);
+ Printf(s_cinit, "%s\n", tm);
+ }
+
+ if (shadow) {
+ String *enumvalue = GetChar(n, "enumvalue");
+ String *set_to = iname;
+
+ if (!enumvalue) {
+ enumvalue = GetChar(n, "enumvalueex");
+ }
+
+ if (enumvalue && *Char(enumvalue)) {
+ // Check for a simple constant expression which is valid in PHP.
+ // If we find one, initialise the const member with it; otherwise
+ // we initialise it using the C/C++ wrapped constant.
+ const char *p;
+ for (p = Char(enumvalue); *p; ++p) {
+ if (!isdigit((unsigned char)*p) && !strchr(" +-", *p)) {
+ // FIXME: enhance to handle `<previous_enum> + 1' which is what
+ // we get for enums that don't have an explicit value set.
+ break;
+ }
+ }
+ if (!*p)
+ set_to = enumvalue;
+ }
+
+ if (wrapping_member_constant) {
+ if (!s_oowrappers)
+ s_oowrappers = NewStringEmpty();
+ Printf(s_oowrappers, "\n\tconst %s = %s;\n", wrapping_member_constant, set_to);
+ } else {
+ if (!s_fakeoowrappers)
+ s_fakeoowrappers = NewStringEmpty();
+ Printf(s_fakeoowrappers, "\n\tconst %s = %s;\n", iname, set_to);
+ }
+ }
+
+ return SWIG_OK;
+ }
+
+ /*
+ * PHP::pragma()
+ *
+ * Pragma directive.
+ *
+ * %pragma(php) code="String" # Includes a string in the .php file
+ * %pragma(php) include="file.php" # Includes a file in the .php file
+ */
+
+ virtual int pragmaDirective(Node *n) {
+ if (!ImportMode) {
+ String *lang = Getattr(n, "lang");
+ String *type = Getattr(n, "name");
+ String *value = Getattr(n, "value");
+
+ if (Strcmp(lang, "php") == 0) {
+ if (Strcmp(type, "code") == 0) {
+ if (value) {
+ Printf(pragma_code, "%s\n", value);
+ }
+ } else if (Strcmp(type, "include") == 0) {
+ if (value) {
+ Printf(pragma_incl, "include '%s';\n", value);
+ }
+ } else if (Strcmp(type, "phpinfo") == 0) {
+ if (value) {
+ Printf(pragma_phpinfo, "%s\n", value);
+ }
+ } else if (Strcmp(type, "version") == 0) {
+ if (value) {
+ pragma_version = value;
+ }
+ } else {
+ Swig_warning(WARN_PHP_UNKNOWN_PRAGMA, input_file, line_number, "Unrecognized pragma <%s>.\n", type);
+ }
+ }
+ }
+ return Language::pragmaDirective(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int classDeclaration(Node *n) {
+ if (!Getattr(n, "feature:onlychildren")) {
+ String *symname = Getattr(n, "sym:name");
+ Setattr(n, "php:proxy", symname);
+ }
+
+ return Language::classDeclaration(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int classHandler(Node *n) {
+ constructors = 0;
+ current_class = n;
+
+ if (shadow) {
+ char *rename = GetChar(n, "sym:name");
+
+ if (!addSymbol(rename, n))
+ return SWIG_ERROR;
+ shadow_classname = NewString(rename);
+
+ shadow_get_vars = NewHash();
+ shadow_set_vars = NewHash();
+
+ /* Deal with inheritance */
+ List *baselist = Getattr(n, "bases");
+ if (baselist) {
+ Iterator base = First(baselist);
+ while (base.item && GetFlag(base.item, "feature:ignore")) {
+ base = Next(base);
+ }
+ base = Next(base);
+ if (base.item) {
+ /* Warn about multiple inheritance for additional base class(es) */
+ while (base.item) {
+ if (GetFlag(base.item, "feature:ignore")) {
+ base = Next(base);
+ continue;
+ }
+ String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
+ String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
+ Swig_warning(WARN_PHP_MULTIPLE_INHERITANCE, input_file, line_number,
+ "Warning for %s, base %s ignored. Multiple inheritance is not supported in PHP.\n", proxyclassname, baseclassname);
+ base = Next(base);
+ }
+ }
+ }
+ }
+
+ classnode = n;
+ Language::classHandler(n);
+ classnode = 0;
+
+ if (shadow) {
+ List *baselist = Getattr(n, "bases");
+ Iterator ki, base;
+
+ if (baselist) {
+ base = First(baselist);
+ while (base.item && GetFlag(base.item, "feature:ignore")) {
+ base = Next(base);
+ }
+ } else {
+ base.item = NULL;
+ }
+
+ if (Getattr(n, "abstracts") && !GetFlag(n, "feature:notabstract")) {
+ Printf(s_phpclasses, "abstract ");
+ }
+
+ Printf(s_phpclasses, "class %s%s ", prefix, shadow_classname);
+ String *baseclass = NULL;
+ if (base.item && Getattr(base.item, "module")) {
+ baseclass = Getattr(base.item, "sym:name");
+ if (!baseclass)
+ baseclass = Getattr(base.item, "name");
+ Printf(s_phpclasses, "extends %s%s ", prefix, baseclass);
+ } else if (GetFlag(n, "feature:exceptionclass")) {
+ Append(s_phpclasses, "extends Exception ");
+ }
+ {
+ Node *node = NewHash();
+ Setattr(node, "type", Getattr(n, "name"));
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ String * interfaces = Swig_typemap_lookup("phpinterfaces", node, "", 0);
+ if (interfaces) {
+ Printf(s_phpclasses, "implements %s ", interfaces);
+ }
+ Delete(node);
+ }
+ Printf(s_phpclasses, "{\n\tpublic $%s=null;\n", SWIG_PTR);
+ if (!baseclass) {
+ // Only store this in the base class (NB !baseclass means we *are*
+ // a base class...)
+ Printf(s_phpclasses, "\tprotected $%s=array();\n", SWIG_DATA);
+ }
+
+ // Write property SET handlers
+ ki = First(shadow_set_vars);
+ if (ki.key) {
+ // This class has setters.
+ Printf(s_phpclasses, "\n\tfunction __set($var,$value) {\n");
+ // FIXME: tune this threshold...
+ if (Len(shadow_set_vars) <= 2) {
+ // Not many setters, so avoid call_user_func.
+ for (; ki.key; ki = Next(ki)) {
+ DOH *key = ki.key;
+ String *iname = ki.item;
+ Printf(s_phpclasses, "\t\tif ($var === '%s') return %s($this->%s,$value);\n", key, iname, SWIG_PTR);
+ }
+ } else {
+ Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_set';\n", shadow_classname);
+ Printf(s_phpclasses, "\t\tif (function_exists($func)) return call_user_func($func,$this->%s,$value);\n", SWIG_PTR);
+ }
+ Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_alter_newobject($this->%s,$value);\n", module, SWIG_PTR);
+ if (baseclass) {
+ Printf(s_phpclasses, "\t\t%s%s::__set($var,$value);\n", prefix, baseclass);
+ } else {
+ Printf(s_phpclasses, "\t\t$this->%s[$var] = $value;\n", SWIG_DATA);
+ }
+ Printf(s_phpclasses, "\t}\n");
+ } else {
+ Printf(s_phpclasses, "\n\tfunction __set($var,$value) {\n");
+ Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_alter_newobject($this->%s,$value);\n", module, SWIG_PTR);
+ if (baseclass) {
+ Printf(s_phpclasses, "\t\t%s%s::__set($var,$value);\n", prefix, baseclass);
+ } else {
+ Printf(s_phpclasses, "\t\t$this->%s[$var] = $value;\n", SWIG_DATA);
+ }
+ Printf(s_phpclasses, "\t}\n");
+ }
+
+ // Write property GET handlers
+ ki = First(shadow_get_vars);
+ if (ki.key) {
+ // This class has getters.
+ Printf(s_phpclasses, "\n\tfunction __get($var) {\n");
+ int non_class_getters = 0;
+ for (; ki.key; ki = Next(ki)) {
+ DOH *key = ki.key;
+ SwigType *d = ki.item;
+ if (!is_class(d)) {
+ ++non_class_getters;
+ continue;
+ }
+ Printv(s_phpclasses, "\t\tif ($var === '", key, "') return new ", prefix, Getattr(classLookup(d), "sym:name"), "(", shadow_classname, "_", key, "_get($this->", SWIG_PTR, "));\n", NIL);
+ }
+ // FIXME: tune this threshold...
+ if (non_class_getters <= 2) {
+ // Not many non-class getters, so avoid call_user_func.
+ for (ki = First(shadow_get_vars); non_class_getters && ki.key; ki = Next(ki)) {
+ DOH *key = ki.key;
+ SwigType *d = ki.item;
+ if (is_class(d)) continue;
+ Printv(s_phpclasses, "\t\tif ($var === '", key, "') return ", shadow_classname, "_", key, "_get($this->", SWIG_PTR, ");\n", NIL);
+ --non_class_getters;
+ }
+ } else {
+ Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_get';\n", shadow_classname);
+ Printf(s_phpclasses, "\t\tif (function_exists($func)) return call_user_func($func,$this->%s);\n", SWIG_PTR);
+ }
+ Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_get_newobject($this->%s);\n", module, SWIG_PTR);
+ if (baseclass) {
+ Printf(s_phpclasses, "\t\treturn %s%s::__get($var);\n", prefix, baseclass);
+ } else {
+ // Reading an unknown property name gives null in PHP.
+ Printf(s_phpclasses, "\t\treturn $this->%s[$var];\n", SWIG_DATA);
+ }
+ Printf(s_phpclasses, "\t}\n");
+
+ /* __isset() should return true for read-only properties, so check for
+ * *_get() not *_set(). */
+ Printf(s_phpclasses, "\n\tfunction __isset($var) {\n");
+ Printf(s_phpclasses, "\t\tif (function_exists('%s_'.$var.'_get')) return true;\n", shadow_classname);
+ Printf(s_phpclasses, "\t\tif ($var === 'thisown') return true;\n");
+ if (baseclass) {
+ Printf(s_phpclasses, "\t\treturn %s%s::__isset($var);\n", prefix, baseclass);
+ } else {
+ Printf(s_phpclasses, "\t\treturn array_key_exists($var, $this->%s);\n", SWIG_DATA);
+ }
+ Printf(s_phpclasses, "\t}\n");
+ } else {
+ Printf(s_phpclasses, "\n\tfunction __get($var) {\n");
+ Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_get_newobject($this->%s);\n", module, SWIG_PTR);
+ if (baseclass) {
+ Printf(s_phpclasses, "\t\treturn %s%s::__get($var);\n", prefix, baseclass);
+ } else {
+ Printf(s_phpclasses, "\t\treturn $this->%s[$var];\n", SWIG_DATA);
+ }
+ Printf(s_phpclasses, "\t}\n");
+ Printf(s_phpclasses, "\n\tfunction __isset($var) {\n");
+ Printf(s_phpclasses, "\t\tif ($var === 'thisown') return true;\n");
+ if (baseclass) {
+ Printf(s_phpclasses, "\t\treturn %s%s::__isset($var);\n", prefix, baseclass);
+ } else {
+ Printf(s_phpclasses, "\t\treturn array_key_exists($var, $this->%s);\n", SWIG_DATA);
+ }
+ Printf(s_phpclasses, "\t}\n");
+ }
+
+ if (!class_has_ctor) {
+ Printf(s_phpclasses, "\tfunction __construct($h) {\n");
+ Printf(s_phpclasses, "\t\t$this->%s=$h;\n", SWIG_PTR);
+ Printf(s_phpclasses, "\t}\n");
+ }
+
+ if (s_oowrappers) {
+ Printf(s_phpclasses, "%s", s_oowrappers);
+ Delete(s_oowrappers);
+ s_oowrappers = NULL;
+ }
+ class_has_ctor = false;
+
+ Printf(s_phpclasses, "}\n\n");
+
+ Delete(shadow_classname);
+ shadow_classname = NULL;
+
+ Delete(shadow_set_vars);
+ shadow_set_vars = NULL;
+ Delete(shadow_get_vars);
+ shadow_get_vars = NULL;
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * memberfunctionHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int memberfunctionHandler(Node *n) {
+ wrapperType = memberfn;
+ Language::memberfunctionHandler(n);
+ wrapperType = standard;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * membervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int membervariableHandler(Node *n) {
+ wrapperType = membervar;
+ Language::membervariableHandler(n);
+ wrapperType = standard;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * staticmembervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int staticmembervariableHandler(Node *n) {
+ wrapperType = staticmembervar;
+ Language::staticmembervariableHandler(n);
+ wrapperType = standard;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ wrapperType = staticmemberfn;
+ Language::staticmemberfunctionHandler(n);
+ wrapperType = standard;
+
+ return SWIG_OK;
+ }
+
+ int abstractConstructorHandler(Node *) {
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constructorHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int constructorHandler(Node *n) {
+ constructors++;
+ if (Swig_directorclass(n)) {
+ String *name = GetChar(Swig_methodclass(n), "name");
+ String *ctype = GetChar(Swig_methodclass(n), "classtype");
+ String *sname = GetChar(Swig_methodclass(n), "sym:name");
+ String *args = NewStringEmpty();
+ ParmList *p = Getattr(n, "parms");
+ int i;
+
+ for (i = 0; p; p = nextSibling(p), i++) {
+ if (i) {
+ Printf(args, ", ");
+ }
+ if (Strcmp(GetChar(p, "type"), SwigType_str(GetChar(p, "type"), 0))) {
+ SwigType *t = Getattr(p, "type");
+ Printf(args, "%s", SwigType_rcaststr(t, 0));
+ if (SwigType_isreference(t)) {
+ Append(args, "*");
+ }
+ }
+ Printf(args, "arg%d", i+1);
+ }
+
+ /* director ctor code is specific for each class */
+ Delete(director_ctor_code);
+ director_ctor_code = NewStringEmpty();
+ director_prot_ctor_code = NewStringEmpty();
+ Printf(director_ctor_code, "if (Z_TYPE_P(arg0) == IS_NULL) { /* not subclassed */\n");
+ Printf(director_prot_ctor_code, "if (Z_TYPE_P(arg0) == IS_NULL) { /* not subclassed */\n");
+ Printf(director_ctor_code, " %s = (%s *)new %s(%s);\n", Swig_cresult_name(), ctype, ctype, args);
+ Printf(director_prot_ctor_code, " SWIG_PHP_Error(E_ERROR, \"accessing abstract class or protected constructor\");\n", name, name, args);
+ if (i) {
+ Insert(args, 0, ", ");
+ }
+ Printf(director_ctor_code, "} else {\n %s = (%s *)new SwigDirector_%s(arg0%s);\n}\n", Swig_cresult_name(), ctype, sname, args);
+ Printf(director_prot_ctor_code, "} else {\n %s = (%s *)new SwigDirector_%s(arg0%s);\n}\n", Swig_cresult_name(), ctype, sname, args);
+ Delete(args);
+
+ wrapperType = directorconstructor;
+ } else {
+ wrapperType = constructor;
+ }
+ Language::constructorHandler(n);
+ wrapperType = standard;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * CreateZendListDestructor()
+ * ------------------------------------------------------------ */
+ //virtual int destructorHandler(Node *n) {
+ //}
+ int CreateZendListDestructor(Node *n) {
+ String *name = GetChar(Swig_methodclass(n), "name");
+ String *iname = GetChar(n, "sym:name");
+ ParmList *l = Getattr(n, "parms");
+
+ String *destructorname = NewStringEmpty();
+ Printf(destructorname, "_%s", Swig_name_wrapper(iname));
+ Setattr(classnode, "destructor", destructorname);
+
+ Wrapper *f = NewWrapper();
+ Printf(f->def, "/* This function is designed to be called by the zend list destructors */\n");
+ Printf(f->def, "/* to typecast and do the actual destruction */\n");
+ Printf(f->def, "static void %s(zend_resource *res, const char *type_name) {\n", destructorname);
+
+ Wrapper_add_localv(f, "value", "swig_object_wrapper *value=(swig_object_wrapper *) res->ptr", NIL);
+ Wrapper_add_localv(f, "ptr", "void *ptr=value->ptr", NIL);
+ Wrapper_add_localv(f, "newobject", "int newobject=value->newobject", NIL);
+
+ emit_parameter_variables(l, f);
+ emit_attach_parmmaps(l, f);
+
+ // Get type of first arg, thing to be destructed
+ // Skip ignored arguments
+ Parm *p = l;
+ //while (Getattr(p,"tmap:ignore")) {p = Getattr(p,"tmap:ignore:next");}
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+ SwigType *pt = Getattr(p, "type");
+
+ Printf(f->code, " efree(value);\n");
+ Printf(f->code, " if (! newobject) return; /* can't delete it! */\n");
+ Printf(f->code, " arg1 = (%s)SWIG_ConvertResourceData(ptr, type_name, SWIGTYPE%s);\n", SwigType_lstr(pt, 0), SwigType_manglestr(pt));
+ Printf(f->code, " if (! arg1) zend_error(E_ERROR, \"%s resource already free'd\");\n", Char(name));
+
+ Setattr(n, "wrap:name", destructorname);
+
+ String *actioncode = emit_action(n);
+ Append(f->code, actioncode);
+ Delete(actioncode);
+
+ Printf(f->code, "thrown:\n");
+ Append(f->code, "return;\n");
+ Append(f->code, "fail:\n");
+ Append(f->code, "SWIG_FAIL();\n");
+ Printf(f->code, "}\n");
+
+ Wrapper_print(f, s_wrappers);
+ DelWrapper(f);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * memberconstantHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int memberconstantHandler(Node *n) {
+ wrapping_member_constant = Getattr(n, "sym:name");
+ Language::memberconstantHandler(n);
+ wrapping_member_constant = NULL;
+ return SWIG_OK;
+ }
+
+ int classDirectorInit(Node *n) {
+ String *declaration = Swig_director_declaration(n);
+ Printf(f_directors_h, "%s\n", declaration);
+ Printf(f_directors_h, "public:\n");
+ Delete(declaration);
+ return Language::classDirectorInit(n);
+ }
+
+ int classDirectorEnd(Node *n) {
+ Printf(f_directors_h, "};\n");
+ return Language::classDirectorEnd(n);
+ }
+
+ int classDirectorConstructor(Node *n) {
+ Node *parent = Getattr(n, "parentNode");
+ String *decl = Getattr(n, "decl");
+ String *supername = Swig_class_name(parent);
+ String *classname = NewStringEmpty();
+ Printf(classname, "SwigDirector_%s", supername);
+
+ /* insert self parameter */
+ Parm *p;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms = CopyParmList(superparms);
+ String *type = NewString("zval");
+ SwigType_add_pointer(type);
+ p = NewParm(type, NewString("self"), n);
+ set_nextSibling(p, parms);
+ parms = p;
+
+ if (!Getattr(n, "defaultargs")) {
+ // There should always be a "self" parameter first.
+ assert(ParmList_len(parms) > 0);
+
+ /* constructor */
+ {
+ Wrapper *w = NewWrapper();
+ String *call;
+ String *basetype = Getattr(parent, "classtype");
+
+ String *target = Swig_method_decl(0, decl, classname, parms, 0);
+ call = Swig_csuperclass_call(0, basetype, superparms);
+ Printf(w->def, "%s::%s: %s, Swig::Director(self) {", classname, target, call);
+ Append(w->def, "}");
+ Delete(target);
+ Wrapper_print(w, f_directors);
+ Delete(call);
+ DelWrapper(w);
+ }
+
+ /* constructor header */
+ {
+ String *target = Swig_method_decl(0, decl, classname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+ return Language::classDirectorConstructor(n);
+ }
+
+ int classDirectorMethod(Node *n, Node *parent, String *super) {
+ int is_void = 0;
+ int is_pointer = 0;
+ String *decl = Getattr(n, "decl");
+ String *returntype = Getattr(n, "type");
+ String *name = Getattr(n, "name");
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *declaration = NewStringEmpty();
+ ParmList *l = Getattr(n, "parms");
+ Wrapper *w = NewWrapper();
+ String *tm;
+ String *wrap_args = NewStringEmpty();
+ String *value = Getattr(n, "value");
+ String *storage = Getattr(n, "storage");
+ bool pure_virtual = false;
+ int status = SWIG_OK;
+ int idx;
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+
+ if (Cmp(storage, "virtual") == 0) {
+ if (Cmp(value, "0") == 0) {
+ pure_virtual = true;
+ }
+ }
+
+ /* determine if the method returns a pointer */
+ is_pointer = SwigType_ispointer_return(decl);
+ is_void = (Cmp(returntype, "void") == 0 && !is_pointer);
+
+ /* virtual method definition */
+ String *target;
+ String *pclassname = NewStringf("SwigDirector_%s", classname);
+ String *qualified_name = NewStringf("%s::%s", pclassname, name);
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ /* header declaration */
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Get any exception classes in the throws typemap
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ ParmList *throw_parm_list = 0;
+
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ Parm *p;
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list)
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+ String *str = SwigType_str(Getattr(p, "type"), 0);
+ Append(w->def, str);
+ Append(declaration, str);
+ Delete(str);
+ }
+ }
+
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+
+ /* declare method return value
+ * if the return value is a reference or const reference, a specialized typemap must
+ * handle it, including declaration of c_result ($result).
+ */
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ }
+ } else {
+ String *cres = SwigType_lstr(returntype, "c_result");
+ Printf(w->code, "%s;\n", cres);
+ Delete(cres);
+ }
+ }
+
+ if (ignored_method) {
+ if (!pure_virtual) {
+ if (!is_void)
+ Printf(w->code, "return ");
+ String *super_call = Swig_method_call(super, l);
+ Printf(w->code, "%s;\n", super_call);
+ Delete(super_call);
+ } else {
+ Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname),
+ SwigType_namestr(name));
+ }
+ } else {
+ /* attach typemaps to arguments (C/C++ -> PHP) */
+ String *parse_args = NewStringEmpty();
+
+ Swig_director_parms_fixup(l);
+
+ /* remove the wrapper 'w' since it was producing spurious temps */
+ Swig_typemap_attach_parms("in", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ Parm *p;
+
+ int outputs = 0;
+ if (!is_void)
+ outputs++;
+
+ /* build argument list and type conversion string */
+ idx = 0;
+ p = l;
+ while (p) {
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ if (Getattr(p, "tmap:directorargout") != 0)
+ outputs++;
+
+ String *pname = Getattr(p, "name");
+ String *ptype = Getattr(p, "type");
+
+ if ((tm = Getattr(p, "tmap:directorin")) != 0) {
+ String *parse = Getattr(p, "tmap:directorin:parse");
+ if (!parse) {
+ String *input = NewStringf("&args[%d]", idx++);
+ Setattr(p, "emit:directorinput", input);
+ Replaceall(tm, "$input", input);
+ Delete(input);
+ Replaceall(tm, "$owner", "0");
+ Printv(wrap_args, tm, "\n", NIL);
+ Putc('O', parse_args);
+ } else {
+ Append(parse_args, parse);
+ Setattr(p, "emit:directorinput", pname);
+ Replaceall(tm, "$input", pname);
+ Replaceall(tm, "$owner", "0");
+ if (Len(tm) == 0)
+ Append(tm, pname);
+ }
+ p = Getattr(p, "tmap:directorin:next");
+ continue;
+ } else if (Cmp(ptype, "void")) {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
+ "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(ptype, 0),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_NOWRAP;
+ break;
+ }
+ p = nextSibling(p);
+ }
+
+ /* exception handling */
+ bool error_used_in_typemap = false;
+ tm = Swig_typemap_lookup("director:except", n, Swig_cresult_name(), 0);
+ if (!tm) {
+ tm = Getattr(n, "feature:director:except");
+ if (tm)
+ tm = Copy(tm);
+ }
+ if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
+ if (Replaceall(tm, "$error", "error")) {
+ /* Only declare error if it is used by the typemap. */
+ error_used_in_typemap = true;
+ Append(w->code, "int error;\n");
+ }
+ } else {
+ Delete(tm);
+ tm = NULL;
+ }
+
+ if (!idx) {
+ Printf(w->code, "zval *args = NULL;\n");
+ } else {
+ Printf(w->code, "zval args[%d];\n", idx);
+ }
+ // typemap_directorout testcase requires that 0 can be assigned to the
+ // variable named after the result of Swig_cresult_name(), so that can't
+ // be a zval - make it a pointer to one instead.
+ Printf(w->code, "zval swig_zval_result, swig_funcname;\n", Swig_cresult_name());
+ Printf(w->code, "zval * SWIGUNUSED %s = &swig_zval_result;\n", Swig_cresult_name());
+ const char * funcname = GetChar(n, "sym:name");
+ Printf(w->code, "ZVAL_STRINGL(&swig_funcname, \"%s\", %d);\n", funcname, strlen(funcname));
+
+ /* wrap complex arguments to zvals */
+ Printv(w->code, wrap_args, NIL);
+
+ if (error_used_in_typemap) {
+ Append(w->code, "error = ");
+ }
+ Append(w->code, "call_user_function(EG(function_table), &swig_self, &swig_funcname,");
+ Printf(w->code, " &swig_zval_result, %d, args);\n", idx);
+
+ if (tm) {
+ Printv(w->code, Str(tm), "\n", NIL);
+ Delete(tm);
+ }
+
+ /* marshal return value from PHP to C/C++ type */
+
+ String *cleanup = NewStringEmpty();
+ String *outarg = NewStringEmpty();
+
+ idx = 0;
+
+ /* marshal return value */
+ if (!is_void) {
+ tm = Swig_typemap_lookup("directorout", n, Swig_cresult_name(), w);
+ if (tm != 0) {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ char temp[24];
+ sprintf(temp, "%d", idx);
+ Replaceall(tm, "$argnum", temp);
+
+ /* TODO check this */
+ if (Getattr(n, "wrap:disown")) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, tm, "\n", NIL);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s in director method %s::%s (skipping method).\n", SwigType_str(returntype, 0), SwigType_namestr(c_classname),
+ SwigType_namestr(name));
+ status = SWIG_ERROR;
+ }
+ }
+
+ /* marshal outputs */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout")) != 0) {
+ Replaceall(tm, "$result", Swig_cresult_name());
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ Delete(parse_args);
+ Delete(cleanup);
+ Delete(outarg);
+ }
+
+ Append(w->code, "thrown:\n");
+ if (!is_void) {
+ if (!(ignored_method && !pure_virtual)) {
+ String *rettype = SwigType_str(returntype, 0);
+ if (!SwigType_isreference(returntype)) {
+ Printf(w->code, "return (%s) c_result;\n", rettype);
+ } else {
+ Printf(w->code, "return (%s) *c_result;\n", rettype);
+ }
+ Delete(rettype);
+ }
+ } else {
+ Append(w->code, "return;\n");
+ }
+
+ Append(w->code, "fail:\n");
+ Append(w->code, "SWIG_FAIL();\n");
+ Append(w->code, "}\n");
+
+ // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewStringEmpty();
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+
+ /* emit the director method */
+ if (status == SWIG_OK) {
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+
+ /* clean up */
+ Delete(wrap_args);
+ Delete(pclassname);
+ DelWrapper(w);
+ return status;
+ }
+
+ int classDirectorDisown(Node *) {
+ return SWIG_OK;
+ }
+}; /* class PHP */
+
+static PHP *maininstance = 0;
+
+// We use this function to be able to write out zend_register_list_destructor_ex
+// lines for most things in the type table
+// NOTE: it's a function NOT A PHP::METHOD
+extern "C" {
+static void typetrace(const SwigType *ty, String *mangled, String *clientdata) {
+ Node *class_node;
+ if (!zend_types) {
+ zend_types = NewHash();
+ }
+ // we want to know if the type which reduced to this has a constructor
+ if ((class_node = maininstance->classLookup(ty))) {
+ if (!Getattr(zend_types, mangled)) {
+ // OK it may have been set before by a different SwigType but it would
+ // have had the same underlying class node I think
+ // - it is certainly required not to have different originating class
+ // nodes for the same SwigType
+ Setattr(zend_types, mangled, class_node);
+ }
+ } else { // a non-class pointer
+ Setattr(zend_types, mangled, NOTCLASS);
+ }
+ if (r_prevtracefunc)
+ (*r_prevtracefunc) (ty, mangled, (String *) clientdata);
+}
+}
+
+/* -----------------------------------------------------------------------------
+ * new_swig_php() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_php() {
+ maininstance = new PHP;
+ if (!r_prevtracefunc) {
+ r_prevtracefunc = SwigType_remember_trace(typetrace);
+ } else {
+ Printf(stderr, "php Typetrace vector already saved!\n");
+ assert(0);
+ }
+ return maininstance;
+}
+
+extern "C" Language *swig_php(void) {
+ return new_swig_php();
+}
diff --git a/contrib/tools/swig/Source/Modules/python.cxx b/contrib/tools/swig/Source/Modules/python.cxx
new file mode 100644
index 00000000000..c8c45df35c4
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/python.cxx
@@ -0,0 +1,5718 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * python.cxx
+ *
+ * Python language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include <limits.h>
+#include "cparse.h"
+#include <ctype.h>
+#include <errno.h>
+#include "pydoc.h"
+
+#include <stdint.h>
+
+#define PYSHADOW_MEMBER 0x2
+#define WARN_PYTHON_MULTIPLE_INH 405
+
+#define PYTHON_INT_MAX (2147483647)
+#define PYTHON_INT_MIN (-2147483647-1)
+
+static String *const_code = 0;
+static String *module = 0;
+static String *package = 0;
+static String *mainmodule = 0;
+static String *interface = 0;
+static String *global_name = 0;
+static int shadow = 1;
+static int use_kw = 0;
+static int director_method_index = 0;
+static int builtin = 0;
+
+static File *f_begin = 0;
+static File *f_runtime = 0;
+static File *f_runtime_h = 0;
+static File *f_header = 0;
+static File *f_wrappers = 0;
+static File *f_directors = 0;
+static File *f_directors_h = 0;
+static File *f_init = 0;
+static File *f_shadow_py = 0;
+static String *f_shadow = 0;
+static String *f_shadow_begin = 0;
+static Hash *f_shadow_imports = 0;
+static String *f_shadow_after_begin = 0;
+static String *f_shadow_stubs = 0;
+static Hash *builtin_getset = 0;
+static Hash *builtin_closures = 0;
+static Hash *class_members = 0;
+static File *f_builtins = 0;
+static String *builtin_tp_init = 0;
+static String *builtin_methods = 0;
+static String *builtin_default_unref = 0;
+static String *builtin_closures_code = 0;
+
+static String *methods;
+static String *methods_proxydocs;
+static String *class_name;
+static String *shadow_indent = 0;
+static int in_class = 0;
+static int no_header_file = 0;
+static int max_bases = 0;
+static int builtin_bases_needed = 0;
+
+static int py3 = 0;
+
+/* C++ Support + Shadow Classes */
+
+static int have_constructor;
+static int have_repr;
+static String *real_classname;
+
+/* Thread Support */
+static int threads = 0;
+static int nothreads = 0;
+
+/* Other options */
+static int dirvtable = 0;
+static int doxygen = 0;
+static int fastunpack = 1;
+static int fastproxy = 0;
+static int olddefs = 0;
+static int castmode = 0;
+static int extranative = 0;
+static int nortti = 0;
+static int relativeimport = 0;
+
+/* flags for the make_autodoc function */
+enum autodoc_t {
+ AUTODOC_CLASS,
+ AUTODOC_CTOR,
+ AUTODOC_DTOR,
+ AUTODOC_STATICFUNC,
+ AUTODOC_FUNC,
+ AUTODOC_METHOD,
+ AUTODOC_CONST,
+ AUTODOC_VAR
+};
+
+
+static const char *usage1 = "\
+Python Options (available with -python)\n\
+ -builtin - Create Python built-in types rather than proxy classes, for better performance\n\
+ -castmode - Enable the casting mode, which allows implicit cast between types in Python\n\
+ -debug-doxygen-parser - Display doxygen parser module debugging information\n\
+ -debug-doxygen-translator - Display doxygen translator module debugging information\n\
+ -dirvtable - Generate a pseudo virtual table for directors for faster dispatch\n\
+ -doxygen - Convert C++ doxygen comments to pydoc comments in proxy classes\n\
+ -extranative - Return extra native wrappers for C++ std containers wherever possible\n\
+ -fastproxy - Use fast proxy mechanism for member methods\n\
+ -globals <name> - Set <name> used to access C global variable (default: 'cvar')\n\
+ -interface <mod>- Set low-level C/C++ module name to <mod> (default: module name prefixed by '_')\n\
+ -keyword - Use keyword arguments\n";
+static const char *usage2 = "\
+ -nofastunpack - Use traditional UnpackTuple method to parse the argument functions\n\
+ -noh - Don't generate the output header file\n";
+static const char *usage3 = "\
+ -noproxy - Don't generate proxy classes\n\
+ -nortti - Disable the use of the native C++ RTTI with directors\n\
+ -nothreads - Disable thread support for the entire interface\n\
+ -olddefs - Keep the old method definitions when using -fastproxy\n\
+ -py3 - Generate code with Python 3 specific features and syntax\n\
+ -relativeimport - Use relative Python imports\n\
+ -threads - Add thread support for all the interface\n\
+ -O - Enable the following optimization options:\n\
+ -fastdispatch -fastproxy -fvirtual\n\
+\n";
+
+static String *getSlot(Node *n = NULL, const char *key = NULL, String *default_slot = NULL) {
+ static String *zero = NewString("0");
+ String *val = n && key && *key ? Getattr(n, key) : NULL;
+ return val ? val : default_slot ? default_slot : zero;
+}
+
+static void printSlot(File *f, String *slotval, const char *slotname, const char *functype = NULL) {
+ String *slotval_override = 0;
+ if (functype && Strcmp(slotval, "0") == 0)
+ slotval = slotval_override = NewStringf("(%s) %s", functype, slotval);
+ int len = Len(slotval);
+ int fieldwidth = len > 41 ? (len > 61 ? 0 : 61 - len) : 41 - len;
+ Printf(f, " %s,%*s/* %s */\n", slotval, fieldwidth, "", slotname);
+ Delete(slotval_override);
+}
+
+static String *getClosure(String *functype, String *wrapper, int funpack = 0) {
+ static const char *functypes[] = {
+ "unaryfunc", "SWIGPY_UNARYFUNC_CLOSURE",
+ "destructor", "SWIGPY_DESTRUCTOR_CLOSURE",
+ "inquiry", "SWIGPY_INQUIRY_CLOSURE",
+ "getiterfunc", "SWIGPY_GETITERFUNC_CLOSURE",
+ "binaryfunc", "SWIGPY_BINARYFUNC_CLOSURE",
+ "ternaryfunc", "SWIGPY_TERNARYFUNC_CLOSURE",
+ "ternarycallfunc", "SWIGPY_TERNARYCALLFUNC_CLOSURE",
+ "lenfunc", "SWIGPY_LENFUNC_CLOSURE",
+ "ssizeargfunc", "SWIGPY_SSIZEARGFUNC_CLOSURE",
+ "ssizessizeargfunc", "SWIGPY_SSIZESSIZEARGFUNC_CLOSURE",
+ "ssizeobjargproc", "SWIGPY_SSIZEOBJARGPROC_CLOSURE",
+ "ssizessizeobjargproc", "SWIGPY_SSIZESSIZEOBJARGPROC_CLOSURE",
+ "objobjproc", "SWIGPY_OBJOBJPROC_CLOSURE",
+ "objobjargproc", "SWIGPY_OBJOBJARGPROC_CLOSURE",
+ "reprfunc", "SWIGPY_REPRFUNC_CLOSURE",
+ "hashfunc", "SWIGPY_HASHFUNC_CLOSURE",
+ "iternextfunc", "SWIGPY_ITERNEXTFUNC_CLOSURE",
+ NULL
+ };
+
+ static const char *funpack_functypes[] = {
+ "unaryfunc", "SWIGPY_UNARYFUNC_CLOSURE",
+ "destructor", "SWIGPY_DESTRUCTOR_CLOSURE",
+ "inquiry", "SWIGPY_INQUIRY_CLOSURE",
+ "getiterfunc", "SWIGPY_GETITERFUNC_CLOSURE",
+ "ternaryfunc", "SWIGPY_TERNARYFUNC_CLOSURE",
+ "ternarycallfunc", "SWIGPY_TERNARYCALLFUNC_CLOSURE",
+ "lenfunc", "SWIGPY_LENFUNC_CLOSURE",
+ "ssizeargfunc", "SWIGPY_FUNPACK_SSIZEARGFUNC_CLOSURE",
+ "ssizessizeargfunc", "SWIGPY_SSIZESSIZEARGFUNC_CLOSURE",
+ "ssizeobjargproc", "SWIGPY_SSIZEOBJARGPROC_CLOSURE",
+ "ssizessizeobjargproc", "SWIGPY_SSIZESSIZEOBJARGPROC_CLOSURE",
+ "objobjproc", "SWIGPY_FUNPACK_OBJOBJPROC_CLOSURE",
+ "objobjargproc", "SWIGPY_OBJOBJARGPROC_CLOSURE",
+ "reprfunc", "SWIGPY_REPRFUNC_CLOSURE",
+ "hashfunc", "SWIGPY_HASHFUNC_CLOSURE",
+ "iternextfunc", "SWIGPY_ITERNEXTFUNC_CLOSURE",
+ NULL
+ };
+
+ if (!functype)
+ return NULL;
+ char *c = Char(functype);
+ int i;
+ if (funpack) {
+ for (i = 0; funpack_functypes[i] != NULL; i += 2) {
+ if (!strcmp(c, funpack_functypes[i]))
+ return NewStringf("%s(%s)", funpack_functypes[i + 1], wrapper);
+ }
+ } else {
+ for (i = 0; functypes[i] != NULL; i += 2) {
+ if (!strcmp(c, functypes[i]))
+ return NewStringf("%s(%s)", functypes[i + 1], wrapper);
+ }
+ }
+ return NULL;
+}
+
+class PYTHON:public Language {
+public:
+ PYTHON() {
+ /* Add code to manage protected constructors and directors */
+ director_prot_ctor_code = NewString("");
+ Printv(director_prot_ctor_code,
+ "if ( $comparison ) { /* subclassed */\n",
+ " $director_new \n",
+ "} else {\n", " SWIG_SetErrorMsg(PyExc_RuntimeError,\"accessing abstract class or protected constructor\"); \n", " SWIG_fail;\n", "}\n", NIL);
+ director_multiple_inheritance = 1;
+ director_language = 1;
+ }
+
+ ~PYTHON() {
+ delete doxygenTranslator;
+ }
+
+ /* ------------------------------------------------------------
+ * Thread Implementation
+ * ------------------------------------------------------------ */
+ int threads_enable(Node *n) const {
+ return threads && !GetFlagAttr(n, "feature:nothread");
+ }
+
+ int initialize_threads(String *f_init) {
+ if (!threads) {
+ return SWIG_OK;
+ }
+ Printf(f_init, "\n");
+ Printf(f_init, "/* Initialize threading */\n");
+ Printf(f_init, "SWIG_PYTHON_INITIALIZE_THREADS;\n");
+
+ return SWIG_OK;
+ }
+
+ virtual void thread_begin_block(Node *n, String *f) {
+ if (!GetFlag(n, "feature:nothreadblock")) {
+ String *bb = Getattr(n, "feature:threadbeginblock");
+ if (bb) {
+ Append(f, bb);
+ } else {
+ Append(f, "SWIG_PYTHON_THREAD_BEGIN_BLOCK;\n");
+ }
+ }
+ }
+
+ virtual void thread_end_block(Node *n, String *f) {
+ if (!GetFlag(n, "feature:nothreadblock")) {
+ String *eb = Getattr(n, "feature:threadendblock");
+ if (eb) {
+ Append(f, eb);
+ } else {
+ Append(f, "SWIG_PYTHON_THREAD_END_BLOCK;\n");
+ }
+ }
+ }
+
+ virtual void thread_begin_allow(Node *n, String *f) {
+ if (!GetFlag(n, "feature:nothreadallow")) {
+ String *bb = Getattr(n, "feature:threadbeginallow");
+ Append(f, "{\n");
+ if (bb) {
+ Append(f, bb);
+ } else {
+ Append(f, "SWIG_PYTHON_THREAD_BEGIN_ALLOW;\n");
+ }
+ }
+ }
+
+ virtual void thread_end_allow(Node *n, String *f) {
+ if (!GetFlag(n, "feature:nothreadallow")) {
+ String *eb = Getattr(n, "feature:threadendallow");
+ Append(f, "\n");
+ if (eb) {
+ Append(f, eb);
+ } else {
+ Append(f, "SWIG_PYTHON_THREAD_END_ALLOW;");
+ }
+ Append(f, "\n}");
+ }
+ }
+
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+
+ SWIG_library_directory("python");
+
+ int doxygen_translator_flags = 0;
+
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-interface") == 0) {
+ if (argv[i + 1]) {
+ interface = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ /* end added */
+ } else if (strcmp(argv[i], "-globals") == 0) {
+ if (argv[i + 1]) {
+ global_name = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if ((strcmp(argv[i], "-shadow") == 0) || ((strcmp(argv[i], "-proxy") == 0))) {
+ shadow = 1;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-noproxy") == 0)) {
+ shadow = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-keyword") == 0) {
+ use_kw = 1;
+ SWIG_cparse_set_compact_default_args(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nortti") == 0) {
+ nortti = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-threads") == 0) {
+ threads = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nothreads") == 0) {
+ /* Turn off thread support mode */
+ nothreads = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-dirvtable") == 0) {
+ dirvtable = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-doxygen") == 0) {
+ doxygen = 1;
+ scan_doxygen_comments = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-doxygen-translator") == 0) {
+ doxygen_translator_flags |= DoxygenTranslator::debug_translator;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-doxygen-parser") == 0) {
+ doxygen_translator_flags |= DoxygenTranslator::debug_parser;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nofastunpack") == 0) {
+ fastunpack = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-fastproxy") == 0) {
+ fastproxy = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-olddefs") == 0) {
+ olddefs = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-castmode") == 0) {
+ castmode = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-extranative") == 0) {
+ extranative = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-noh") == 0) {
+ no_header_file = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-newvwm") == 0) {
+ /* Turn on new value wrapper mode */
+ /* Undocumented option, did have -help text: New value wrapper mode, use only when everything else fails */
+ Swig_value_wrapper_mode(1);
+ no_header_file = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-O") == 0) {
+ fastproxy = 1;
+ Wrapper_fast_dispatch_mode_set(1);
+ Wrapper_virtual_elimination_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage1, stdout);
+ fputs(usage2, stdout);
+ fputs(usage3, stdout);
+ } else if (strcmp(argv[i], "-py3") == 0) {
+ py3 = 1;
+ Preprocessor_define("SWIGPYTHON_PY3", 0);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-builtin") == 0) {
+ builtin = 1;
+ Preprocessor_define("SWIGPYTHON_BUILTIN", 0);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-relativeimport") == 0) {
+ relativeimport = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-cppcast") == 0 ||
+ strcmp(argv[i], "-fastinit") == 0 ||
+ strcmp(argv[i], "-fastquery") == 0 ||
+ strcmp(argv[i], "-fastunpack") == 0 ||
+ strcmp(argv[i], "-modern") == 0 ||
+ strcmp(argv[i], "-modernargs") == 0 ||
+ strcmp(argv[i], "-noproxydel") == 0 ||
+ strcmp(argv[i], "-safecstrings") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-aliasobj0") == 0 ||
+ strcmp(argv[i], "-buildnone") == 0 ||
+ strcmp(argv[i], "-classic") == 0 ||
+ strcmp(argv[i], "-classptr") == 0 ||
+ strcmp(argv[i], "-new_repr") == 0 ||
+ strcmp(argv[i], "-new_vwm") == 0 ||
+ strcmp(argv[i], "-newrepr") == 0 ||
+ strcmp(argv[i], "-noaliasobj0") == 0 ||
+ strcmp(argv[i], "-nobuildnone") == 0 ||
+ strcmp(argv[i], "-nocastmode") == 0 ||
+ strcmp(argv[i], "-nocppcast") == 0 ||
+ strcmp(argv[i], "-nodirvtable") == 0 ||
+ strcmp(argv[i], "-noextranative") == 0 ||
+ strcmp(argv[i], "-nofastinit") == 0 ||
+ strcmp(argv[i], "-nofastproxy") == 0 ||
+ strcmp(argv[i], "-nofastquery") == 0 ||
+ strcmp(argv[i], "-nomodern") == 0 ||
+ strcmp(argv[i], "-nomodernargs") == 0 ||
+ strcmp(argv[i], "-noolddefs") == 0 ||
+ strcmp(argv[i], "-nooutputtuple") == 0 ||
+ strcmp(argv[i], "-noproxyimport") == 0 ||
+ strcmp(argv[i], "-nosafecstrings") == 0 ||
+ strcmp(argv[i], "-old_repr") == 0 ||
+ strcmp(argv[i], "-oldrepr") == 0 ||
+ strcmp(argv[i], "-outputtuple") == 0 ||
+ strcmp(argv[i], "-proxydel") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]);
+ Swig_mark_arg(i);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ }
+ }
+
+ if (doxygen)
+ doxygenTranslator = new PyDocConverter(doxygen_translator_flags);
+
+ if (!global_name)
+ global_name = NewString("cvar");
+ Preprocessor_define("SWIGPYTHON 1", 0);
+ SWIG_typemap_lang("python");
+ SWIG_config_file("python.swg");
+ allow_overloading();
+ }
+
+
+ /* ------------------------------------------------------------
+ * top()
+ * ------------------------------------------------------------ */
+
+ virtual int top(Node *n) {
+ /* check if directors are enabled for this module. note: this
+ * is a "master" switch, without which no director code will be
+ * emitted. %feature("director") statements are also required
+ * to enable directors for individual classes or methods.
+ *
+ * use %module(directors="1") modulename at the start of the
+ * interface file to enable director generation.
+ */
+ String *mod_docstring = NULL;
+ String *moduleimport = NULL;
+ {
+ Node *mod = Getattr(n, "module");
+ if (mod) {
+ Node *options = Getattr(mod, "options");
+ if (options) {
+ int dirprot = 0;
+ if (Getattr(options, "dirprot")) {
+ dirprot = 1;
+ }
+ if (Getattr(options, "nodirprot")) {
+ dirprot = 0;
+ }
+ if (Getattr(options, "directors")) {
+ allow_directors();
+ if (dirprot)
+ allow_dirprot();
+ }
+ if (Getattr(options, "threads")) {
+ threads = 1;
+ }
+ if (Getattr(options, "castmode")) {
+ castmode = 1;
+ }
+ if (Getattr(options, "nocastmode")) {
+ Printf(stderr, "Deprecated module option: %s. This option is no longer supported.\n", "nocastmode");
+ SWIG_exit(EXIT_FAILURE);
+ }
+ if (Getattr(options, "extranative")) {
+ extranative = 1;
+ }
+ if (Getattr(options, "noextranative")) {
+ Printf(stderr, "Deprecated module option: %s. This option is no longer supported.\n", "noextranative");
+ SWIG_exit(EXIT_FAILURE);
+ }
+ if (Getattr(options, "outputtuple")) {
+ Printf(stderr, "Deprecated module option: %s. This option is no longer supported.\n", "outputtuple");
+ SWIG_exit(EXIT_FAILURE);
+ }
+ if (Getattr(options, "nooutputtuple")) {
+ Printf(stderr, "Deprecated module option: %s. This option is no longer supported.\n", "nooutputtuple");
+ SWIG_exit(EXIT_FAILURE);
+ }
+ mod_docstring = Getattr(options, "docstring");
+ package = Getattr(options, "package");
+ moduleimport = Getattr(options, "moduleimport");
+ }
+ }
+ }
+
+ /* Set comparison with none for ConstructorToFunction */
+ setSubclassInstanceCheck(NewString("$arg != Py_None"));
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+ String *outfile_h = !no_header_file ? Getattr(n, "outfile_h") : 0;
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+ f_directors_h = NewString("");
+ f_directors = NewString("");
+ builtin_getset = NewHash();
+ builtin_closures = NewHash();
+ builtin_closures_code = NewString("");
+ class_members = NewHash();
+ builtin_methods = NewString("");
+ builtin_default_unref = NewString("delete $self;");
+
+ if (builtin) {
+ f_builtins = NewString("");
+ }
+
+ if (directorsEnabled()) {
+ if (!no_header_file) {
+ f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
+ if (!f_runtime_h) {
+ FileErrorDisplay(outfile_h);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ } else {
+ f_runtime_h = f_runtime;
+ }
+ }
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+
+ const_code = NewString("");
+ methods = NewString("");
+ methods_proxydocs = NewString("");
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n\n#ifndef SWIGPYTHON\n#define SWIGPYTHON\n#endif\n\n");
+
+ if (directorsEnabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+ }
+
+ if (nothreads) {
+ Printf(f_runtime, "#define SWIG_PYTHON_NO_THREADS\n");
+ } else if (threads) {
+ Printf(f_runtime, "#define SWIG_PYTHON_THREADS\n");
+ }
+
+ if (!dirvtable) {
+ Printf(f_runtime, "#define SWIG_PYTHON_DIRECTOR_NO_VTABLE\n");
+ }
+
+ if (nortti) {
+ Printf(f_runtime, "#ifndef SWIG_DIRECTOR_NORTTI\n");
+ Printf(f_runtime, "#define SWIG_DIRECTOR_NORTTI\n");
+ Printf(f_runtime, "#endif\n");
+ }
+
+ if (castmode) {
+ Printf(f_runtime, "#define SWIG_CASTRANK_MODE\n");
+ Printf(f_runtime, "#define SWIG_PYTHON_CAST_MODE\n");
+ }
+
+ if (extranative) {
+ Printf(f_runtime, "#define SWIG_PYTHON_EXTRA_NATIVE_CONTAINERS\n");
+ }
+
+ if (builtin) {
+ Printf(f_runtime, "#define SWIGPYTHON_BUILTIN\n");
+ }
+
+ Printf(f_runtime, "\n");
+
+ Printf(f_header, "#ifdef SWIG_TypeQuery\n");
+ Printf(f_header, "# undef SWIG_TypeQuery\n");
+ Printf(f_header, "#endif\n");
+ Printf(f_header, "#define SWIG_TypeQuery SWIG_Python_TypeQuery\n");
+
+
+ /* Set module name */
+ module = Copy(Getattr(n, "name"));
+ mainmodule = Getattr(n, "name");
+
+ if (directorsEnabled()) {
+ Swig_banner(f_directors_h);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module);
+ Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module);
+ if (dirprot_mode()) {
+ Printf(f_directors_h, "#include <map>\n");
+ Printf(f_directors_h, "#include <string>\n\n");
+ }
+
+ Printf(f_directors, "\n\n");
+ Printf(f_directors, "/* ---------------------------------------------------\n");
+ Printf(f_directors, " * C++ director class methods\n");
+ Printf(f_directors, " * --------------------------------------------------- */\n\n");
+ if (outfile_h) {
+ String *filename = Swig_file_filename(outfile_h);
+ Printf(f_directors, "#include \"%s\"\n\n", filename);
+ Delete(filename);
+ }
+ }
+
+ /* If shadow classing is enabled, we're going to change the module name to "_module" */
+ String *default_import_code = NewString("");
+ if (shadow) {
+ String *filen = NewStringf("%s%s.py", SWIG_output_directory(), Char(module));
+ // If we don't have an interface then change the module name X to _X
+ if (interface)
+ module = interface;
+ else
+ Insert(module, 0, "_");
+ if ((f_shadow_py = NewFile(filen, "w", SWIG_output_files())) == 0) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(filen);
+ filen = NULL;
+
+ f_shadow = NewString("");
+ f_shadow_begin = NewString("");
+ f_shadow_imports = NewHash();
+ f_shadow_after_begin = NewString("");
+ f_shadow_stubs = NewString("");
+
+ Swig_register_filebyname("shadow", f_shadow);
+ Swig_register_filebyname("python", f_shadow);
+
+ if (!builtin) {
+ /* Import the low-level C/C++ module. This should be a relative import,
+ * since the shadow module may also have been imported by a relative
+ * import, and there is thus no guarantee that the low-level C/C++ module is on
+ * sys.path. Relative imports must be explicitly specified from 2.6.0
+ * onwards (implicit relative imports raised a DeprecationWarning in 2.6,
+ * and fail in 2.7 onwards).
+ *
+ * First check for __package__ which is available from 2.6 onwards, see PEP366.
+ * Next try determine the shadow wrapper's package based on the __name__ it
+ * was given by the importer that loaded it.
+ * If the module is in a package, load the low-level C/C++ module from the
+ * same package, otherwise load it as a global module.
+ */
+ Printv(default_import_code, "# Import the low-level C/C++ module\n", NULL);
+ Printv(default_import_code, "if __package__ or \".\" in __name__:\n", NULL);
+ Printv(default_import_code, tab4, "from . import ", module, "\n", NULL);
+ Printv(default_import_code, "else:\n", NULL);
+ Printv(default_import_code, tab4, "import ", module, "\n", NULL);
+ } else {
+ Printv(default_import_code, "# Pull in all the attributes from the low-level C/C++ module\n", NULL);
+ Printv(default_import_code, "if __package__ or \".\" in __name__:\n", NULL);
+ Printv(default_import_code, tab4, "from .", module, " import *\n", NULL);
+ Printv(default_import_code, "else:\n", NULL);
+ Printv(default_import_code, tab4, "from ", module, " import *\n", NULL);
+ }
+
+ /* Need builtins to qualify names like Exception that might also be
+ defined in this module (try both Python 3 and Python 2 names) */
+ Printv(f_shadow, "try:\n", tab4, "import builtins as __builtin__\n", "except ImportError:\n", tab4, "import __builtin__\n", NULL);
+
+ if (!builtin && fastproxy) {
+ Printf(f_shadow, "\n");
+ Printf(f_shadow, "_swig_new_instance_method = %s.SWIG_PyInstanceMethod_New\n", module);
+ Printf(f_shadow, "_swig_new_static_method = %s.SWIG_PyStaticMethod_New\n", module);
+ }
+
+ Printv(f_shadow, "\n",
+ "def _swig_repr(self):\n",
+ tab4, "try:\n",
+ tab4, tab4, "strthis = \"proxy of \" + self.this.__repr__()\n",
+ tab4, "except __builtin__.Exception:\n",
+ tab4, tab4, "strthis = \"\"\n",
+ tab4, "return \"<%s.%s; %s >\" % (self.__class__.__module__, self.__class__.__name__, strthis,)\n\n", NIL);
+
+ Printv(f_shadow, "\n",
+ "def _swig_setattr_nondynamic_instance_variable(set):\n",
+ tab4, "def set_instance_attr(self, name, value):\n",
+#ifdef USE_THISOWN
+ tab4, tab4, "if name in (\"this\", \"thisown\"):\n",
+ tab4, tab4, tab4, "set(self, name, value)\n",
+#else
+ tab4, tab4, "if name == \"thisown\":\n",
+ tab4, tab4, tab4, "self.this.own(value)\n",
+ tab4, tab4, "elif name == \"this\":\n",
+ tab4, tab4, tab4, "set(self, name, value)\n",
+#endif
+ tab4, tab4, "elif hasattr(self, name) and isinstance(getattr(type(self), name), property):\n",
+ tab4, tab4, tab4, "set(self, name, value)\n",
+ tab4, tab4, "else:\n",
+ tab4, tab4, tab4, "raise AttributeError(\"You cannot add instance attributes to %s\" % self)\n",
+ tab4, "return set_instance_attr\n\n", NIL);
+
+ Printv(f_shadow, "\n",
+ "def _swig_setattr_nondynamic_class_variable(set):\n",
+ tab4, "def set_class_attr(cls, name, value):\n",
+ tab4, tab4, "if hasattr(cls, name) and not isinstance(getattr(cls, name), property):\n",
+ tab4, tab4, tab4, "set(cls, name, value)\n",
+ tab4, tab4, "else:\n",
+ tab4, tab4, tab4, "raise AttributeError(\"You cannot add class attributes to %s\" % cls)\n",
+ tab4, "return set_class_attr\n\n", NIL);
+
+ Printv(f_shadow, "\n",
+ "def _swig_add_metaclass(metaclass):\n",
+ tab4, "\"\"\"Class decorator for adding a metaclass to a SWIG wrapped class - a slimmed down version of six.add_metaclass\"\"\"\n",
+ tab4, "def wrapper(cls):\n",
+ tab4, tab4, "return metaclass(cls.__name__, cls.__bases__, cls.__dict__.copy())\n",
+ tab4, "return wrapper\n\n", NIL);
+
+ Printv(f_shadow, "\n",
+ "class _SwigNonDynamicMeta(type):\n",
+ tab4, "\"\"\"Meta class to enforce nondynamic attributes (no new attributes) for a class\"\"\"\n",
+ tab4, "__setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__)\n",
+ "\n", NIL);
+
+ Printv(f_shadow, "\n", NIL);
+
+ if (directorsEnabled()) {
+ Printv(f_shadow, "import weakref\n\n", NIL);
+ }
+ }
+ // Include some information in the code
+ Printf(f_header, "\n/*-----------------------------------------------\n @(target):= %s.so\n\
+ ------------------------------------------------*/\n", module);
+
+ Printf(f_header, "#if PY_VERSION_HEX >= 0x03000000\n");
+ Printf(f_header, "# define SWIG_init PyInit_%s\n\n", module);
+ Printf(f_header, "#else\n");
+ Printf(f_header, "# define SWIG_init init%s\n\n", module);
+ Printf(f_header, "#endif\n");
+ Printf(f_header, "#define SWIG_name \"%s\"\n", module);
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n");
+ Printf(f_wrappers, "extern \"C\" {\n");
+ Printf(f_wrappers, "#endif\n");
+ Append(const_code, "static swig_const_info swig_const_table[] = {\n");
+ Append(methods, "static PyMethodDef SwigMethods[] = {\n");
+ Append(methods_proxydocs, "static PyMethodDef SwigMethods_proxydocs[] = {\n");
+
+ /* the method exported for replacement of new.instancemethod in Python 3 */
+ add_pyinstancemethod_new();
+ add_pystaticmethod_new();
+
+ if (builtin) {
+ SwigType *s = NewString("SwigPyObject");
+ SwigType_add_pointer(s);
+ SwigType_remember(s);
+ Delete(s);
+ }
+
+ /* emit code */
+ Language::top(n);
+
+ if (directorsEnabled()) {
+ // Insert director runtime into the f_runtime file (make it occur before %header section)
+ Swig_insert_file("director_common.swg", f_runtime);
+ Swig_insert_file("director.swg", f_runtime);
+ }
+
+ /* Close language module */
+ Append(methods, "\t { NULL, NULL, 0, NULL }\n");
+ Append(methods, "};\n");
+ Printf(f_wrappers, "%s\n", methods);
+ Append(methods_proxydocs, "\t { NULL, NULL, 0, NULL }\n");
+ Append(methods_proxydocs, "};\n");
+ Printf(f_wrappers, "%s\n", methods_proxydocs);
+
+ if (builtin) {
+ Dump(f_builtins, f_wrappers);
+ }
+
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+
+ Append(const_code, "{0, 0, 0, 0.0, 0, 0}};\n");
+ Printf(f_wrappers, "%s\n", const_code);
+ initialize_threads(f_init);
+
+ Printf(f_init, "#if PY_VERSION_HEX >= 0x03000000\n");
+ Printf(f_init, " return m;\n");
+ Printf(f_init, "#else\n");
+ Printf(f_init, " return;\n");
+ Printf(f_init, "#endif\n");
+ Printf(f_init, "}\n");
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n");
+ Printf(f_wrappers, "}\n");
+ Printf(f_wrappers, "#endif\n");
+
+ if (shadow) {
+ Swig_banner_target_lang(f_shadow_py, "#");
+
+ if (mod_docstring) {
+ if (Len(mod_docstring)) {
+ const char *triple_double = "\"\"\"";
+ // follow PEP257 rules: https://www.python.org/dev/peps/pep-0257/
+ // reported by pep257: https://github.com/GreenSteam/pep257
+ bool multi_line_ds = Strchr(mod_docstring, '\n') != 0;
+ Printv(f_shadow_py, "\n", triple_double, multi_line_ds ? "\n":"", mod_docstring, multi_line_ds ? "\n":"", triple_double, "\n", NIL);
+ }
+ Delete(mod_docstring);
+ mod_docstring = NULL;
+ }
+
+ if (Len(f_shadow_begin) > 0)
+ Printv(f_shadow_py, "\n", f_shadow_begin, "\n", NIL);
+
+ Printv(f_shadow_py, "\nfrom sys import version_info as _swig_python_version_info\n", NULL);
+ Printv(f_shadow_py, "if _swig_python_version_info < (2, 7, 0):\n", NULL);
+ Printv(f_shadow_py, tab4, "raise RuntimeError(\"Python 2.7 or later required\")\n\n", NULL);
+
+ if (Len(f_shadow_after_begin) > 0)
+ Printv(f_shadow_py, f_shadow_after_begin, "\n", NIL);
+
+ if (moduleimport) {
+ Replaceall(moduleimport, "$module", module);
+ Printv(f_shadow_py, moduleimport, "\n", NIL);
+ } else {
+ Printv(f_shadow_py, default_import_code, NIL);
+ }
+
+ Printv(f_shadow_py, "\n", f_shadow, "\n", NIL);
+ Printv(f_shadow_py, f_shadow_stubs, "\n", NIL);
+ Delete(f_shadow_py);
+ }
+
+ /* Close all of the files */
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+
+ if (directorsEnabled()) {
+ Dump(f_directors_h, f_runtime_h);
+ Printf(f_runtime_h, "\n");
+ Printf(f_runtime_h, "#endif\n");
+ if (f_runtime_h != f_begin)
+ Delete(f_runtime_h);
+ Dump(f_directors, f_begin);
+ }
+
+ Dump(f_wrappers, f_begin);
+ if (builtin && builtin_bases_needed)
+ Printf(f_begin, "static PyTypeObject *builtin_bases[%d];\n\n", max_bases + 2);
+ Wrapper_pretty_print(f_init, f_begin);
+
+ Delete(default_import_code);
+ Delete(f_shadow_after_begin);
+ Delete(f_shadow_imports);
+ Delete(f_shadow_begin);
+ Delete(f_shadow);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_builtins);
+ Delete(f_init);
+ Delete(f_directors);
+ Delete(f_directors_h);
+ Delete(f_runtime);
+ Delete(f_begin);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * Emit the wrapper for PyInstanceMethod_New to MethodDef array.
+ * This wrapper is used to implement -fastproxy,
+ * as a replacement of new.instancemethod in Python 3.
+ * ------------------------------------------------------------ */
+ int add_pyinstancemethod_new() {
+ String *name = NewString("SWIG_PyInstanceMethod_New");
+ String *line = NewString("");
+ Printf(line, "\t { \"%s\", %s, METH_O, NULL},\n", name, name);
+ Append(methods, line);
+ if (fastproxy) {
+ Append(methods_proxydocs, line);
+ }
+ Delete(line);
+ Delete(name);
+ return 0;
+ }
+
+ /* ------------------------------------------------------------
+ * Emit the wrapper for PyStaticMethod_New to MethodDef array.
+ * This wrapper is used to ensure the correct documentation is
+ * generated for static methods when using -fastproxy
+ * ------------------------------------------------------------ */
+ int add_pystaticmethod_new() {
+ if (fastproxy) {
+ String *name = NewString("SWIG_PyStaticMethod_New");
+ String *line = NewString("");
+ Printf(line, "\t { \"%s\", %s, METH_O, NULL},\n", name, name);
+ Append(methods, line);
+ Append(methods_proxydocs, line);
+ Delete(line);
+ Delete(name);
+ }
+ return 0;
+ }
+
+ /* ------------------------------------------------------------
+ * subpkg_tail()
+ *
+ * Return the name of 'other' package relative to 'base'.
+ *
+ * 1. If 'other' is a sub-package of 'base', returns the 'other' relative to
+ * 'base'.
+ * 2. If 'other' and 'base' are equal, returns empty string "".
+ * 3. In any other case, NULL pointer is returned.
+ *
+ * The 'base' and 'other' are expected to be fully qualified names.
+ *
+ * NOTE: none of 'base' nor 'other' can be null.
+ *
+ * Examples:
+ *
+ * # base other tail
+ * -- ---- ----- ----
+ * 1 "Foo" "Foo.Bar" -> "Bar"
+ * 2 "Foo" "Foo." -> ""
+ * 3 "Foo" "FooB.ar" -> NULL
+ * 4 "Foo.Bar" "Foo.Bar" -> ""
+ * 5 "Foo.Bar" "Foo" -> NULL
+ * 6 "Foo.Bar" "Foo.Gez" -> NULL
+ *
+ * NOTE: the example #2 is actually a syntax error (at input). I believe
+ * swig parser prevents us from this case happening here.
+ * ------------------------------------------------------------ */
+
+ static String *subpkg_tail(const String *base, const String *other) {
+ int baselen = Len(base);
+ int otherlen = Len(other);
+
+ if (Strncmp(other, base, baselen) == 0) {
+ if ((baselen < otherlen) && (Char(other))[baselen] == '.') {
+ return NewString((Char(other)) + baselen + 1);
+ } else if (baselen == otherlen) {
+ return NewString("");
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * abs_import_directive_string()
+ *
+ * Return a string containing python code to import module.
+ *
+ * pkg package name or the module being imported
+ * mod module name of the module being imported
+ * pfx optional prefix to module name
+ *
+ * NOTE: keep this function consistent with abs_import_name_string().
+ * ------------------------------------------------------------ */
+
+ static String *abs_import_directive_string(const String *pkg, const String *mod, const char *pfx = "") {
+ String *out = NewString("");
+
+ if (pkg && *Char(pkg)) {
+ Printf(out, "import %s.%s%s\n", pkg, pfx, mod);
+ } else {
+ Printf(out, "import %s%s\n", pfx, mod);
+ }
+ return out;
+ }
+
+ /* ------------------------------------------------------------
+ * rel_import_directive_string()
+ *
+ * Return a string containing python code to import module that
+ * is potentially within a package.
+ *
+ * mainpkg package name of the module which imports the other module
+ * pkg package name or the module being imported
+ * mod module name of the module being imported
+ * pfx optional prefix to module name
+ *
+ * NOTE: keep this function consistent with rel_import_name_string().
+ * ------------------------------------------------------------ */
+
+ static String *rel_import_directive_string(const String *mainpkg, const String *pkg, const String *mod, const char *pfx = "") {
+
+ /* NOTE: things are not so trivial. This is what we do here (by examples):
+ *
+ * 0. To import module 'foo', which is not in any package, we do absolute
+ * import:
+ *
+ * import foo
+ *
+ * 1. To import 'pkg1.pkg2.foo', when mainpkg != "pkg1" and
+ * mainpkg != "pkg1.pkg2" or when mainpkg is not given we do absolute
+ * import:
+ *
+ * import pkg1.pkg2.foo
+ *
+ * 2. To import module pkg1.foo, when mainpkg == "pkg1", we do:
+ *
+ * - for py3 = 0:
+ *
+ * import foo
+ *
+ * - for py3 = 1:
+ *
+ * from . import foo
+ *
+ * 3. To import "pkg1.pkg2.pkg3.foo", when mainpkg = "pkg1", we do:
+ *
+ * - for py3 == 0:
+ *
+ * import pkg2.pkg3.foo
+ *
+ * - for py3 == 1:
+ *
+ * from . import pkg2 # [1]
+ * import pkg1.pkg2.pkg3.foo
+ *
+ * NOTE: [1] is necessary for pkg2.foo to be present in the importing module
+ */
+
+ String *apkg = 0; // absolute (FQDN) package name of pkg
+ String *rpkg = 0; // relative package name
+ int py3_rlen1 = 0; // length of 1st level sub-package name, used by py3
+ String *out = NewString("");
+
+ if (pkg && *Char(pkg)) {
+ if (mainpkg) {
+ String *tail = subpkg_tail(mainpkg, pkg);
+ if (tail) {
+ if (*Char(tail)) {
+ rpkg = NewString(tail);
+ const char *py3_end1 = Strchr(rpkg, '.');
+ if (!py3_end1)
+ py3_end1 = (Char(rpkg)) + Len(rpkg);
+ py3_rlen1 = (int)(py3_end1 - Char(rpkg));
+ } else {
+ rpkg = NewString("");
+ }
+ Delete(tail);
+ } else {
+ apkg = NewString(pkg);
+ }
+ } else {
+ apkg = NewString(pkg);
+ }
+ } else {
+ apkg = NewString("");
+ }
+
+ if (apkg) {
+ Printf(out, "import %s%s%s%s\n", apkg, *Char(apkg) ? "." : "", pfx, mod);
+ Delete(apkg);
+ } else {
+ if (py3_rlen1)
+ Printf(out, "from . import %.*s\n", py3_rlen1, rpkg);
+ Printf(out, "from .%s import %s%s\n", rpkg, pfx, mod);
+ Delete(rpkg);
+ }
+ return out;
+ }
+
+ /* ------------------------------------------------------------
+ * import_directive_string()
+ * ------------------------------------------------------------ */
+
+ static String *import_directive_string(const String *mainpkg, const String *pkg, const String *mod, const char *pfx = "") {
+ if (!relativeimport) {
+ return abs_import_directive_string(pkg, mod, pfx);
+ } else {
+ return rel_import_directive_string(mainpkg, pkg, mod, pfx);
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * abs_import_name_string()
+ *
+ * Return a string with the name of a symbol (perhaps imported
+ * from external module by absolute import directive).
+ *
+ * mainpkg package name of current module
+ * mainmod module name of current module
+ * pkg package name of (perhaps other) module
+ * mod module name of (perhaps other) module
+ * sym symbol name
+ *
+ * NOTE: mainmod, mod, and sym can't be NULL.
+ * NOTE: keep this function consistent with abs_import_directive_string()
+ * ------------------------------------------------------------ */
+
+ static String *abs_import_name_string(const String *mainpkg, const String *mainmod, const String *pkg, const String *mod, const String *sym) {
+ String *out = NewString("");
+ if (pkg && *Char(pkg)) {
+ if (mainpkg && *Char(mainpkg)) {
+ if (Strcmp(mainpkg,pkg) != 0 || Strcmp(mainmod, mod) != 0) {
+ Printf(out, "%s.%s.", pkg, mod);
+ }
+ } else {
+ Printf(out, "%s.%s.", pkg, mod);
+ }
+ } else if ((mainpkg && *Char(mainpkg)) || Strcmp(mainmod, mod) != 0) {
+ Printf(out, "%s.", mod);
+ }
+ Append(out, sym);
+ return out;
+ }
+
+ /* ------------------------------------------------------------
+ * rel_import_name_string()
+ *
+ * Return a string with the name of a symbol (perhaps imported
+ * from external module by relative import directive).
+ *
+ * mainpkg package name of current module
+ * mainmod module name of current module
+ * pkg package name of (perhaps other) module
+ * mod module name of (perhaps other) module
+ * sym symbol name
+ *
+ * NOTE: mainmod, mod, and sym can't be NULL.
+ * NOTE: keep this function consistent with rel_import_directive_string()
+ * ------------------------------------------------------------ */
+
+ static String *rel_import_name_string(const String *mainpkg, const String *mainmod, const String *pkg, const String *mod, const String *sym) {
+ String *out = NewString("");
+ if (pkg && *Char(pkg)) {
+ String *tail = 0;
+ if (mainpkg)
+ tail = subpkg_tail(mainpkg, pkg);
+ if (!tail)
+ tail = NewString(pkg);
+ if (*Char(tail)) {
+ Printf(out, "%s.%s.", tail, mod);
+ } else if (Strcmp(mainmod, mod) != 0) {
+ Printf(out, "%s.", mod);
+ }
+ Delete(tail);
+ } else if ((mainpkg && *Char(mainpkg)) || Strcmp(mainmod, mod) != 0) {
+ Printf(out, "%s.", mod);
+ }
+ Append(out, sym);
+ return out;
+ }
+
+ /* ------------------------------------------------------------
+ * import_name_string()
+ * ------------------------------------------------------------ */
+
+ static String *import_name_string(const String *mainpkg, const String *mainmod, const String *pkg, const String *mod, const String *sym) {
+ if (!relativeimport) {
+ return abs_import_name_string(mainpkg,mainmod,pkg,mod,sym);
+ } else {
+ return rel_import_name_string(mainpkg,mainmod,pkg,mod,sym);
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * importDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int importDirective(Node *n) {
+ if (shadow) {
+ String *modname = Getattr(n, "module");
+
+ if (modname) {
+ // Find the module node for this imported module. It should be the
+ // first child but search just in case.
+ Node *mod = firstChild(n);
+ while (mod && Strcmp(nodeType(mod), "module") != 0)
+ mod = nextSibling(mod);
+
+ Node *options = Getattr(mod, "options");
+ String *pkg = options ? Getattr(options, "package") : 0;
+
+ if (!options || (!Getattr(options, "noshadow") && !Getattr(options, "noproxy"))) {
+ String *_import = import_directive_string(package, pkg, modname, "_");
+ if (!GetFlagAttr(f_shadow_imports, _import)) {
+ String *import = import_directive_string(package, pkg, modname);
+ Printf(builtin ? f_shadow_after_begin : f_shadow, "%s", import);
+ Delete(import);
+ SetFlag(f_shadow_imports, _import);
+ }
+ Delete(_import);
+ }
+
+ }
+ }
+ return Language::importDirective(n);
+ }
+
+ /* ------------------------------------------------------------
+ * funcCall()
+ *
+ * Emit shadow code to call a function in the extension
+ * module. Using proper argument and calling style for
+ * given node n.
+ * ------------------------------------------------------------ */
+ String *funcCall(String *name, String *parms) {
+ String *str = NewString("");
+
+ Printv(str, module, ".", name, "(", parms, ")", NIL);
+ return str;
+ }
+
+ /* ------------------------------------------------------------
+ * indent_pythoncode()
+ *
+ * Format (indent) Python code.
+ * Remove leading whitespace from 'code' and re-indent using
+ * the indentation string in 'indent'.
+ * ------------------------------------------------------------ */
+
+ String *indent_pythoncode(const String *code, const_String_or_char_ptr indent, String *file, int line, const char *directive_name) {
+ String *out = NewString("");
+ String *temp;
+ char *t;
+ if (!indent)
+ indent = "";
+
+ temp = NewString(code);
+
+ t = Char(temp);
+ if (*t == '{') {
+ Delitem(temp, 0);
+ Delitem(temp, DOH_END);
+ }
+
+ /* Split the input text into lines */
+ List *clist = SplitLines(temp);
+ Delete(temp);
+
+ // Line number within the pythoncode.
+ int py_line = 0;
+
+ String *initial = 0;
+ Iterator si;
+
+ /* Get the initial indentation. Skip lines which only contain whitespace
+ * and/or a comment, as the indentation of those doesn't matter:
+ *
+ * A logical line that contains only spaces, tabs, formfeeds and
+ * possibly a comment, is ignored (i.e., no NEWLINE token is
+ * generated).
+ *
+ * see:
+ * https://docs.python.org/2/reference/lexical_analysis.html#blank-lines
+ * https://docs.python.org/3/reference/lexical_analysis.html#blank-lines
+ */
+ for (si = First(clist); si.item; si = Next(si), ++py_line) {
+ const char *c = Char(si.item);
+ int i;
+ for (i = 0; isspace((unsigned char)c[i]); i++) {
+ // Scan forward until we find a non-space (which may be a null byte).
+ }
+ char ch = c[i];
+ if (ch && ch != '#') {
+ // Found a line with actual content.
+ initial = NewStringWithSize(c, i);
+ break;
+ }
+ if (ch) {
+ Printv(out, indent, c, NIL);
+ }
+ Putc('\n', out);
+ }
+
+ // Process remaining lines.
+ for ( ; si.item; si = Next(si), ++py_line) {
+ const char *c = Char(si.item);
+ // If no prefixed line was found, the above loop should have completed.
+ assert(initial);
+
+ int i;
+ for (i = 0; isspace((unsigned char)c[i]); i++) {
+ // Scan forward until we find a non-space (which may be a null byte).
+ }
+ char ch = c[i];
+ if (!ch) {
+ // Line is just whitespace - emit an empty line.
+ Putc('\n', out);
+ continue;
+ }
+
+ if (ch == '#') {
+ // Comment - the indentation doesn't matter to python, but try to
+ // adjust the whitespace for the benefit of human readers (though SWIG
+ // currently seems to always remove any whitespace before a '#' before
+ // we get here, in which case we'll just leave the comment at the start
+ // of the line).
+ if (i >= Len(initial)) {
+ Printv(out, indent, NIL);
+ }
+
+ Printv(out, c + i, "\n", NIL);
+ continue;
+ }
+
+ if (i < Len(initial)) {
+ // There's non-whitespace in the initial prefix of this line.
+ Swig_error(file, line, "Line indented less than expected (line %d of %s) as no line should be indented less than the indentation in line 1\n", py_line, directive_name);
+ Printv(out, indent, c, "\n", NIL);
+ } else {
+ if (memcmp(c, Char(initial), Len(initial)) == 0) {
+ // Prefix matches initial, so just remove it.
+ Printv(out, indent, c + Len(initial), "\n", NIL);
+ continue;
+ }
+ Swig_warning(WARN_PYTHON_INDENT_MISMATCH,
+ file, line, "Whitespace indentation is inconsistent compared to earlier lines (line %d of %s)\n", py_line, directive_name);
+ // To avoid gratuitously breaking interface files which worked with
+ // SWIG <= 3.0.5, we remove a prefix of the same number of bytes for
+ // lines which start with different whitespace to the line we got
+ // 'initial' from.
+ Printv(out, indent, c + Len(initial), "\n", NIL);
+ }
+ }
+ Delete(clist);
+ return out;
+ }
+
+ /* ------------------------------------------------------------
+ * indent_docstring()
+ *
+ * Format (indent) a Python docstring.
+ * Remove leading whitespace from 'code' and re-indent using
+ * the indentation string in 'indent'.
+ * ------------------------------------------------------------ */
+
+ String *indent_docstring(const String *code, const_String_or_char_ptr indent) {
+ String *out = NewString("");
+ String *temp;
+ char *t;
+ if (!indent)
+ indent = "";
+
+ temp = NewString(code);
+
+ t = Char(temp);
+ if (*t == '{') {
+ Delitem(temp, 0);
+ Delitem(temp, DOH_END);
+ }
+
+ /* Split the input text into lines */
+ List *clist = SplitLines(temp);
+ Delete(temp);
+
+ Iterator si;
+
+ int truncate_characters_count = INT_MAX;
+ for (si = First(clist); si.item; si = Next(si)) {
+ const char *c = Char(si.item);
+ int i;
+ for (i = 0; isspace((unsigned char)c[i]); i++) {
+ // Scan forward until we find a non-space (which may be a null byte).
+ }
+ char ch = c[i];
+ if (ch) {
+ // Found a line which isn't just whitespace
+ if (i < truncate_characters_count)
+ truncate_characters_count = i;
+ }
+ }
+
+ if (truncate_characters_count == INT_MAX)
+ truncate_characters_count = 0;
+
+ for (si = First(clist); si.item; si = Next(si)) {
+ const char *c = Char(si.item);
+
+ int i;
+ for (i = 0; isspace((unsigned char)c[i]); i++) {
+ // Scan forward until we find a non-space (which may be a null byte).
+ }
+ char ch = c[i];
+ if (!ch) {
+ // Line is just whitespace - emit an empty line.
+ Putc('\n', out);
+ continue;
+ }
+
+ Printv(out, indent, c + truncate_characters_count, "\n", NIL);
+ }
+ Delete(clist);
+ return out;
+ }
+
+ /* ------------------------------------------------------------
+ * autodoc level declarations
+ * ------------------------------------------------------------ */
+
+ enum autodoc_l {
+ NO_AUTODOC = -2, // no autodoc
+ STRING_AUTODOC = -1, // use provided string
+ NAMES_AUTODOC = 0, // only parameter names
+ TYPES_AUTODOC = 1, // parameter names and types
+ EXTEND_AUTODOC = 2, // extended documentation and parameter names
+ EXTEND_TYPES_AUTODOC = 3 // extended documentation and parameter types + names
+ };
+
+
+ autodoc_l autodoc_level(String *autodoc) {
+ autodoc_l dlevel = NO_AUTODOC;
+ char *c = Char(autodoc);
+ if (c) {
+ if (isdigit(c[0])) {
+ dlevel = (autodoc_l) atoi(c);
+ } else {
+ if (strcmp(c, "extended") == 0) {
+ dlevel = EXTEND_AUTODOC;
+ } else {
+ dlevel = STRING_AUTODOC;
+ }
+ }
+ }
+ return dlevel;
+ }
+
+
+ /* ------------------------------------------------------------
+ * have_docstring()
+ *
+ * Check if there is a docstring directive and it has text,
+ * or there is an autodoc flag set
+ * ------------------------------------------------------------ */
+
+ bool have_docstring(Node *n) {
+ String *str = Getattr(n, "feature:docstring");
+ return ((str && Len(str) > 0)
+ || (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc"))
+ || (doxygen && doxygenTranslator->hasDocumentation(n))
+ );
+ }
+
+ /* ------------------------------------------------------------
+ * build_combined_docstring()
+ *
+ * Build the full docstring which may be a combination of the
+ * explicit docstring and autodoc string or, if none of them
+ * is specified, obtained by translating Doxygen comment to
+ * Python.
+ *
+ * Return new string to be deleted by caller (never NIL but
+ * may be empty if there is no docstring).
+ * ------------------------------------------------------------ */
+
+ String *build_combined_docstring(Node *n, autodoc_t ad_type, const String *indent = "", bool low_level = false) {
+ String *docstr = Getattr(n, "feature:docstring");
+ if (docstr) {
+ // Simplify the code below by just ignoring empty docstrings.
+ if (!Len(docstr))
+ docstr = NULL;
+ else
+ docstr = Copy(docstr);
+ }
+
+ if (docstr) {
+ char *t = Char(docstr);
+ if (*t == '{') {
+ Delitem(docstr, 0);
+ Delitem(docstr, DOH_END);
+ }
+ }
+
+ if (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc")) {
+ String *autodoc = make_autodoc(n, ad_type, low_level);
+ if (autodoc && Len(autodoc) > 0) {
+ if (docstr) {
+ Append(autodoc, "\n");
+ Append(autodoc, docstr);
+ }
+
+ String *tmp = autodoc;
+ autodoc = docstr;
+ docstr = tmp;
+ }
+
+ Delete(autodoc);
+ }
+
+ if (!docstr) {
+ if (doxygen) {
+ docstr = Getattr(n, "python:docstring");
+ if (!docstr && doxygenTranslator->hasDocumentation(n)) {
+ docstr = doxygenTranslator->getDocumentation(n, 0);
+
+ // Avoid rebuilding it again the next time: notice that we can't do
+ // this for the combined doc string as autodoc part of it depends on
+ // the sym:name of the node and it is changed while handling it, so
+ // the cached results become incorrect. But Doxygen docstring only
+ // depends on the comment which is not going to change, so we can
+ // safely cache it.
+ Setattr(n, "python:docstring", Copy(docstr));
+ } else {
+ // Must copy here since if the docstring is multi-line, the String*
+ // here will get Deleted below, which is bad if it is a pointer to
+ // the cached object!
+ docstr = Copy(docstr);
+ }
+ }
+ }
+
+ if (!docstr)
+ docstr = NewString("");
+
+ // If there is more than one line then make docstrings like this:
+ //
+ // """
+ // This is line1
+ // And here is line2 followed by the rest of them
+ // """
+ //
+ // otherwise, put it all on a single line
+ if (Strchr(docstr, '\n')) {
+ String *tmp = NewString("");
+ Append(tmp, "\n");
+ Append(tmp, indent_docstring(docstr, indent));
+ Append(tmp, indent);
+ Delete(docstr);
+ docstr = tmp;
+ }
+
+ return docstr;
+ }
+
+ /* ------------------------------------------------------------
+ * docstring()
+ *
+ * Get the docstring text, stripping off {} if necessary,
+ * and enclose in triple double quotes. If autodoc is also
+ * set then it will build a combined docstring.
+ * ------------------------------------------------------------ */
+
+ String *docstring(Node *n, autodoc_t ad_type, const String *indent, bool low_level = false) {
+ String *docstr = build_combined_docstring(n, ad_type, indent, low_level);
+ const int len = Len(docstr);
+ if (!len)
+ return docstr;
+
+ // Notice that all comments are created as raw strings (prefix "r"),
+ // because '\' is used often in comments, but may break Python module from
+ // loading. For example, in doxy comment one may write path in quotes:
+ //
+ // This is path to file "C:\x\file.txt"
+ //
+ // Python will not load the module with such comment because of illegal
+ // escape '\x'. '\' may additionally appear in verbatim or htmlonly sections
+ // of doxygen doc, Latex expressions, ...
+ String *doc = NewString("");
+
+ // Determine which kind of quotes to use as delimiters: for single line
+ // strings we can avoid problems with having a quote as the last character
+ // of the docstring by using different kind of quotes as delimiters. For
+ // multi-line strings this problem doesn't arise, as we always have a new
+ // line or spaces at the end of it, but it still does no harm to do it for
+ // them too.
+ //
+ // Note: we use double quotes by default, i.e. if there is no reason to
+ // prefer using single ones, for consistency with the older SWIG versions.
+ const bool useSingleQuotes = (Char(docstr))[len - 1] == '"';
+
+ Append(doc, useSingleQuotes ? "r'''" : "r\"\"\"");
+
+ // We also need to avoid having triple quotes of whichever type we use, as
+ // this would break Python doc string syntax too. Unfortunately there is no
+ // way to have triple quotes inside of raw-triple-quoted string, so we have
+ // to break the string in parts and rely on concatenation of the adjacent
+ // string literals.
+ if (useSingleQuotes)
+ Replaceall(docstr, "'''", "''' \"'''\" '''");
+ else
+ Replaceall(docstr, "\"\"\"", "\"\"\" '\"\"\"' \"\"\"");
+
+ Append(doc, docstr);
+ Append(doc, useSingleQuotes ? "'''" : "\"\"\"");
+ Delete(docstr);
+
+ return doc;
+ }
+
+ /* ------------------------------------------------------------
+ * cdocstring()
+ *
+ * Get the docstring text as it would appear in C-language
+ * source code (but without quotes around it).
+ * ------------------------------------------------------------ */
+
+ String *cdocstring(Node *n, autodoc_t ad_type, bool low_level = false) {
+ String *ds = build_combined_docstring(n, ad_type, "", low_level);
+ Replaceall(ds, "\\", "\\\\");
+ Replaceall(ds, "\"", "\\\"");
+ Replaceall(ds, "\n", "\\n\"\n\t\t\"");
+ return ds;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addMissingParameterNames()
+ *
+ * For functions that have not had nameless parameters set in the Language class.
+ *
+ * Inputs:
+ * plist - entire parameter list
+ * arg_num - the number to start from when naming arguments
+ * Side effects:
+ * The "lname" attribute in each parameter in plist will be contain a parameter name
+ * ----------------------------------------------------------------------------- */
+
+ void addMissingParameterNames(Node *n, ParmList *plist, int arg_num) {
+ Parm *p = plist;
+ int i = arg_num;
+ while (p) {
+ if (!Getattr(p, "lname")) {
+ String *name = makeParameterName(n, p, i);
+ Setattr(p, "lname", name);
+ Delete(name);
+ }
+ i++;
+ p = nextSibling(p);
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * make_autodocParmList()
+ *
+ * Generate the documentation for the function parameters
+ * Parameters:
+ * arg_num: The number to start assigning unnamed arguments from
+ * func_annotation: Function annotation support
+ * ------------------------------------------------------------ */
+
+ String *make_autodocParmList(Node *n, bool showTypes, int arg_num = 1, bool calling = false, bool func_annotation = false) {
+
+ String *doc = NewString("");
+ String *pdocs = 0;
+ ParmList *plist = CopyParmList(Getattr(n, "parms"));
+ Parm *p;
+ Parm *pnext;
+
+ if (calling)
+ func_annotation = false;
+
+ addMissingParameterNames(n, plist, arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms
+ Swig_typemap_attach_parms("in", plist, 0);
+ Swig_typemap_attach_parms("doc", plist, 0);
+
+ if (Strcmp(ParmList_protostr(plist), "void") == 0) {
+ //No parameters actually
+ return doc;
+ }
+
+ for (p = plist; p; p = pnext) {
+ String *tm = Getattr(p, "tmap:in");
+ if (tm) {
+ pnext = Getattr(p, "tmap:in:next");
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ continue;
+ }
+ } else {
+ pnext = nextSibling(p);
+ }
+
+ String *name = 0;
+ String *type = 0;
+ String *value = 0;
+ String *pdoc = Getattr(p, "tmap:doc");
+ if (pdoc) {
+ name = Getattr(p, "tmap:doc:name");
+ type = Getattr(p, "tmap:doc:type");
+ value = Getattr(p, "tmap:doc:value");
+ }
+
+ // Skip the "self" argument - it is added to the parameter list automatically
+ // and shouldn't be included in the Parameters block
+ if (Getattr(p, "self")) {
+ continue;
+ }
+
+ // Note: the generated name should be consistent with that in kwnames[]
+ String *made_name = 0;
+ if (!name) {
+ name = made_name = makeParameterName(n, p, arg_num);
+ }
+
+ // Increment the argument number once we are sure this is a real argument to count
+ arg_num++;
+
+ type = type ? type : Getattr(p, "type");
+ value = value ? value : Getattr(p, "value");
+
+ if (SwigType_isvarargs(type)) {
+ Delete(made_name);
+ break;
+ }
+
+ if (Len(doc)) {
+ // add a comma to the previous one if any
+ Append(doc, ", ");
+ }
+
+ // Do the param type too?
+ Node *nn = classLookup(Getattr(p, "type"));
+ String *type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
+ if (showTypes)
+ Printf(doc, "%s ", type_str);
+
+ Append(doc, name);
+ if (pdoc) {
+ if (!pdocs)
+ // numpydoc style: https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
+ pdocs = NewString("\nParameters\n----------\n");
+ Printf(pdocs, "%s\n", pdoc);
+ }
+ // Write the function annotation
+ if (func_annotation)
+ Printf(doc, ": \"%s\"", type_str);
+
+ // Write default value
+ if (value && !calling) {
+ String *new_value = convertValue(value, Getattr(p, "type"));
+ if (new_value) {
+ value = new_value;
+ } else {
+ // Even if the value is not representable in the target language, still use it in the documentation, for compatibility with the previous SWIG versions
+ // and because it can still be useful to see the C++ expression there.
+ Node *lookup = Swig_symbol_clookup(value, 0);
+ if (lookup)
+ value = Getattr(lookup, "sym:name");
+ }
+ Printf(doc, "=%s", value);
+
+ if (new_value)
+ Delete(new_value);
+ }
+ Delete(type_str);
+ Delete(made_name);
+ }
+ if (pdocs)
+ Setattr(n, "feature:pdocs", pdocs);
+ Delete(plist);
+ return doc;
+ }
+
+ /* ------------------------------------------------------------
+ * make_autodoc()
+ *
+ * Build a docstring for the node, using parameter and other
+ * info in the parse tree. If the value of the autodoc
+ * attribute is "0" then do not include parameter types, if
+ * it is "1" (the default) then do. If it has some other
+ * value then assume it is supplied by the extension writer
+ * and use it directly.
+ * ------------------------------------------------------------ */
+
+ String *make_autodoc(Node *n, autodoc_t ad_type, bool low_level = false) {
+ int extended = 0;
+ bool first_func = true;
+ // If the function is overloaded then this function is called
+ // for the last one. Rewind to the first so the docstrings are
+ // in order.
+ while (Getattr(n, "sym:previousSibling"))
+ n = Getattr(n, "sym:previousSibling");
+
+ String *doc = NewString("");
+ while (n) {
+ bool showTypes = false;
+ bool skipAuto = false;
+ String *autodoc = Getattr(n, "feature:autodoc");
+ autodoc_l dlevel = autodoc_level(autodoc);
+ switch (dlevel) {
+ case NO_AUTODOC:
+ break;
+ case NAMES_AUTODOC:
+ showTypes = false;
+ break;
+ case TYPES_AUTODOC:
+ showTypes = true;
+ break;
+ case EXTEND_AUTODOC:
+ extended = 1;
+ showTypes = false;
+ break;
+ case EXTEND_TYPES_AUTODOC:
+ extended = 1;
+ showTypes = true;
+ break;
+ case STRING_AUTODOC:
+ Append(doc, autodoc);
+ skipAuto = true;
+ break;
+ }
+
+ if (!skipAuto) {
+ /* Check if a documentation name was given for either the low-level C API or high-level Python shadow API */
+ String *symname = Getattr(n, low_level ? "doc:low:name" : "doc:high:name");
+ if (!symname) {
+ symname = Getattr(n, "sym:name");
+ }
+
+ SwigType *type = Getattr(n, "type");
+ String *type_str = NULL;
+
+ // If the function has default arguments, then that documentation covers this version too
+ if (Getattr(n, "defaultargs") != NULL) {
+ n = Getattr(n, "sym:nextSibling");
+ continue;
+ }
+
+ if (!first_func)
+ Append(doc, "\n");
+
+ if (type) {
+ if (Strcmp(type, "void") == 0) {
+ type_str = NULL;
+ } else {
+ Node *nn = classLookup(type);
+ type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
+ }
+ }
+
+ /* Treat the low-level C API functions for getting/setting variables as methods for documentation purposes */
+ String *kind = Getattr(n, "kind");
+ if (kind && Strcmp(kind, "variable") == 0) {
+ if (ad_type == AUTODOC_FUNC) {
+ ad_type = AUTODOC_METHOD;
+ }
+ }
+ /* Treat destructors as methods for documentation purposes */
+ String *nodeType = Getattr(n, "nodeType");
+ if (nodeType && Strcmp(nodeType, "destructor") == 0) {
+ if (ad_type == AUTODOC_FUNC) {
+ ad_type = AUTODOC_METHOD;
+ }
+ }
+
+ switch (ad_type) {
+ case AUTODOC_CLASS:
+ {
+ // Only do the autodoc if there isn't a docstring for the class
+ String *str = Getattr(n, "feature:docstring");
+ if (!str || Len(str) == 0) {
+ if (builtin) {
+ String *name = Getattr(n, "name");
+ String *rname = add_explicit_scope(SwigType_namestr(name));
+ Printf(doc, "%s", rname);
+ Delete(rname);
+ } else {
+ if (CPlusPlus) {
+ Printf(doc, "Proxy of C++ %s class.", SwigType_namestr(real_classname));
+ } else {
+ Printf(doc, "Proxy of C %s struct.", SwigType_namestr(real_classname));
+ }
+ }
+ }
+ }
+ break;
+ case AUTODOC_CTOR:
+ if (Strcmp(class_name, symname) == 0) {
+ String *paramList = make_autodocParmList(n, showTypes, 2);
+ Printf(doc, "__init__(");
+ if (showTypes)
+ Printf(doc, "%s ", class_name);
+ if (Len(paramList))
+ Printf(doc, "self, %s) -> %s", paramList, class_name);
+ else
+ Printf(doc, "self) -> %s", class_name);
+ } else
+ Printf(doc, "%s(%s) -> %s", symname, make_autodocParmList(n, showTypes), class_name);
+ break;
+
+ case AUTODOC_DTOR:
+ if (showTypes)
+ Printf(doc, "__del__(%s self)", class_name);
+ else
+ Printf(doc, "__del__(self)");
+ break;
+
+ case AUTODOC_STATICFUNC:
+ Printf(doc, "%s(%s)", symname, make_autodocParmList(n, showTypes));
+ if (type_str)
+ Printf(doc, " -> %s", type_str);
+ break;
+
+ case AUTODOC_FUNC:
+ Printf(doc, "%s(%s)", symname, make_autodocParmList(n, showTypes));
+ if (type_str)
+ Printf(doc, " -> %s", type_str);
+ break;
+
+ case AUTODOC_METHOD:
+ {
+ String *paramList = make_autodocParmList(n, showTypes, 2);
+ Printf(doc, "%s(", symname);
+ if (showTypes)
+ Printf(doc, "%s ", class_name);
+ if (Len(paramList))
+ Printf(doc, "self, %s)", paramList);
+ else
+ Printf(doc, "self)");
+ if (type_str)
+ Printf(doc, " -> %s", type_str);
+ }
+ break;
+
+ case AUTODOC_CONST:
+ // There is no autodoc support for constants currently, this enum
+ // element only exists to allow calling docstring() with it.
+ return NULL;
+ case AUTODOC_VAR:
+ // Variables can also be documented (e.g. through the property() function in python)
+ Printf(doc, "%s", symname);
+ if (showTypes) {
+ String *type = Getattr(n, "tmap:doc:type");
+ if (!type)
+ type = Getattr(n, "membervariableHandler:type");
+ if (!type)
+ type = Getattr(n, "type");
+ Printf(doc, " : %s", type);
+ }
+ break;
+ }
+ Delete(type_str);
+
+ // Special case: wrapper functions to get a variable should have no parameters.
+ // Because the node is re-used for the setter and getter, the feature:pdocs field will
+ // exist for the getter function, so explicitly avoid printing parameters in this case.
+ bool variable_getter = kind && Strcmp(kind, "variable") == 0 && Getattr(n, "memberget");
+ if (extended && ad_type != AUTODOC_VAR && !variable_getter) {
+ String *pdocs = Getattr(n, "feature:pdocs");
+ if (pdocs) {
+ Printv(doc, "\n", pdocs, NULL);
+ }
+ }
+ }
+ // if it's overloaded then get the next decl and loop around again
+ n = Getattr(n, "sym:nextSibling");
+ if (n)
+ first_func = false;
+ }
+
+ return doc;
+ }
+
+ /* ------------------------------------------------------------
+ * convertIntegerValue()
+ *
+ * Check if string v is an integer and can be represented in
+ * Python. If so, return an appropriate Python representation,
+ * otherwise (or if we are unsure), return NIL.
+ * ------------------------------------------------------------ */
+ String *convertIntegerValue(String *v, SwigType *resolved_type) {
+ const char *const s = Char(v);
+ char *end;
+ String *result = NIL;
+
+ // Check if this is an integer number in any base.
+ errno = 0;
+ long value = strtol(s, &end, 0);
+ if (errno == ERANGE || end == s)
+ return NIL;
+
+ if (*end != '\0') {
+ // If there is a suffix after the number, we can safely ignore "l"
+ // and (provided the number is unsigned) "u", and also combinations of
+ // these, but not anything else.
+ for (char *p = end; *p != '\0'; ++p) {
+ switch (*p) {
+ case 'l':
+ case 'L':
+ break;
+ case 'u':
+ case 'U':
+ if (value < 0)
+ return NIL;
+ break;
+ default:
+ return NIL;
+ }
+ }
+ }
+ // So now we are certain that we are indeed dealing with an integer
+ // that has a representation as long given by value.
+
+ // Restrict to guaranteed supported range in Python, see maxint docs: https://docs.python.org/2/library/sys.html#sys.maxint
+ // Don't do this pointless check when long is 32 bits or smaller as strtol will have already failed with ERANGE
+#if LONG_MAX > PYTHON_INT_MAX || LONG_MIN < PYTHON_INT_MIN
+ if (value > PYTHON_INT_MAX || value < PYTHON_INT_MIN) {
+ return NIL;
+ }
+#endif
+
+ if (Cmp(resolved_type, "bool") == 0)
+ // Allow integers as the default value for a bool parameter.
+ return NewString(value ? "True" : "False");
+
+ if (value == 0)
+ return NewString(SwigType_ispointer(resolved_type) ? "None" : "0");
+
+ // v may still be octal or hexadecimal:
+ const char *p = s;
+ if (*p == '+' || *p == '-')
+ ++p;
+ if (*p == '0' && *(p+1) != 'x' && *(p+1) != 'X') {
+ // This must have been an octal number. This is the only case we
+ // cannot use in Python directly, since Python 2 and 3 use non-
+ // compatible representations.
+ result = NewString(*s == '-' ? "int(\"-" : "int(\"");
+ String *octal_string = NewStringWithSize(p, (int) (end - p));
+ Append(result, octal_string);
+ Append(result, "\", 8)");
+ Delete(octal_string);
+ return result;
+ }
+ result = *end == '\0' ? Copy(v) : NewStringWithSize(s, (int) (end - s));
+ return result;
+ }
+
+ /* ------------------------------------------------------------
+ * convertDoubleValue()
+ *
+ * Check if the given string looks like a decimal floating point constant
+ * and return it if it does, otherwise return NIL.
+ * ------------------------------------------------------------ */
+ String *convertDoubleValue(String *v) {
+ const char *const s = Char(v);
+ char *end;
+
+ errno = 0;
+ double value = strtod(s, &end);
+ (void) value;
+ if (errno != ERANGE && end != s) {
+ // An added complication: at least some versions of strtod() recognize
+ // hexadecimal floating point numbers which don't exist in Python, so
+ // detect them ourselves and refuse to convert them (this can't be done
+ // without loss of precision in general).
+ //
+ // Also don't accept neither "NAN" nor "INFINITY" (both of which
+ // conveniently contain "n").
+ if (strpbrk(s, "xXnN"))
+ return NIL;
+
+ // Disregard optional "f" suffix, it can be just dropped in Python as it
+ // uses doubles for everything anyhow.
+ for (char * p = end; *p != '\0'; ++p) {
+ switch (*p) {
+ case 'f':
+ case 'F':
+ break;
+
+ default:
+ return NIL;
+ }
+ }
+
+ // Avoid unnecessary string allocation in the common case when we don't
+ // need to remove any suffix.
+ return *end == '\0' ? Copy(v) : NewStringWithSize(s, (int)(end - s));
+ }
+
+ return NIL;
+ }
+
+ /* ------------------------------------------------------------
+ * convertValue()
+ *
+ * Check if string v can be a Python value literal or a
+ * constant. Return an equivalent Python representation,
+ * or NIL if it isn't, or we are unsure.
+ * ------------------------------------------------------------ */
+ String *convertValue(String *v, SwigType *type) {
+ const char *const s = Char(v);
+ String *result = NIL;
+ SwigType *resolved_type = SwigType_typedef_resolve_all(type);
+
+ result = convertIntegerValue(v, resolved_type);
+ if (!result) {
+ result = convertDoubleValue(v);
+ if (!result) {
+ if (Strcmp(v, "true") == 0)
+ result = NewString("True");
+ else if (Strcmp(v, "false") == 0)
+ result = NewString("False");
+ else if (Strcmp(v, "NULL") == 0 || Strcmp(v, "nullptr") == 0)
+ result = SwigType_ispointer(resolved_type) ? NewString("None") : NewString("0");
+ // This could also be an enum type, default value of which could be
+ // representable in Python if it doesn't include any scope (which could,
+ // but currently is not, translated).
+ else if (!Strchr(s, ':')) {
+ Node *lookup = Swig_symbol_clookup(v, 0);
+ if (lookup) {
+ if (Cmp(Getattr(lookup, "nodeType"), "enumitem") == 0)
+ result = Copy(Getattr(lookup, "sym:name"));
+ }
+ }
+ }
+ }
+
+ Delete(resolved_type);
+ return result;
+ }
+
+ /* ------------------------------------------------------------
+ * is_representable_as_pyargs()
+ *
+ * Check if the function parameters default argument values
+ * can be represented in Python.
+ *
+ * If this method returns false, the parameters will be translated
+ * to a generic "*args" which allows us to deal with default values
+ * at C++ code level where they can always be handled.
+ * ------------------------------------------------------------ */
+ bool is_representable_as_pyargs(Node *n) {
+ ParmList *plist = CopyParmList(Getattr(n, "parms"));
+ Swig_typemap_attach_parms("default", plist, NULL);
+
+ Parm *p;
+ Parm *pnext;
+
+ for (p = plist; p; p = pnext) {
+ pnext = nextSibling(p);
+ String *tm = Getattr(p, "tmap:in");
+ if (tm) {
+ Parm *in_next = Getattr(p, "tmap:in:next");
+ if (in_next)
+ pnext = in_next;
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ continue;
+ }
+ }
+
+ // "default" typemap can contain arbitrary C++ code, so while it could, in
+ // principle, be possible to examine it and check if it's just something
+ // simple of the form "$1 = expression" and then use convertValue() to
+ // check if expression can be used in Python, but for now we just
+ // pessimistically give up and prefer to handle this at C++ level only.
+ if (Getattr(p, "tmap:default"))
+ return false;
+
+ String *value = Getattr(p, "value");
+ if (value) {
+ String *convertedValue = convertValue(value, Getattr(p, "type"));
+ if (!convertedValue)
+ return false;
+ Delete(convertedValue);
+ }
+ }
+
+ return true;
+ }
+
+
+ /* ------------------------------------------------------------
+ * is_real_overloaded()
+ *
+ * Check if the function is overloaded, but not just have some
+ * siblings generated due to the original function having
+ * default arguments.
+ * ------------------------------------------------------------ */
+ bool is_real_overloaded(Node *n) {
+ Node *h = Getattr(n, "sym:overloaded");
+ Node *i;
+ if (!h)
+ return false;
+
+ i = Getattr(h, "sym:nextSibling");
+ while (i) {
+ Node *nn = Getattr(i, "defaultargs");
+ if (nn != h) {
+ /* Check if overloaded function has defaultargs and
+ * pointed to the first overloaded. */
+ return true;
+ }
+ i = Getattr(i, "sym:nextSibling");
+ }
+
+ return false;
+ }
+
+ /* ------------------------------------------------------------
+ * make_pyParmList()
+ *
+ * Generate parameter list for Python functions or methods,
+ * reuse make_autodocParmList() to do so.
+ * ------------------------------------------------------------ */
+ String *make_pyParmList(Node *n, bool in_class, bool is_calling, int kw, bool has_self_for_count = false) {
+ /* Get the original function for a defaultargs copy,
+ * see default_arguments() in parser.y. */
+ Node *nn = Getattr(n, "defaultargs");
+ if (nn)
+ n = nn;
+
+ Parm *parms = Getattr(n, "parms");
+ int varargs = parms ? emit_isvarargs(parms) : 0;
+
+ /* We prefer to explicitly list all parameters of the C function in the
+ generated Python code as this makes the function more convenient to use,
+ however in some cases we must replace the real parameters list with just
+ the catch all "*args". This happens when:
+
+ 1. The function is overloaded as Python doesn't support this.
+ 2. We were explicitly asked to use the "compact" arguments form.
+ 3. We were explicitly asked to use default args from C via the "python:cdefaultargs" feature.
+ 4. One of the default argument values can't be represented in Python.
+ 5. Varargs that haven't been forced to use a fixed number of arguments with %varargs.
+ */
+ if (is_real_overloaded(n) || GetFlag(n, "feature:compactdefaultargs") || GetFlag(n, "feature:python:cdefaultargs") || !is_representable_as_pyargs(n) || varargs) {
+ String *parms = NewString("");
+ if (in_class)
+ Printf(parms, "self, ");
+ Printf(parms, "*args");
+ if (kw)
+ Printf(parms, ", **kwargs");
+ return parms;
+ }
+
+ bool funcanno = py3 ? true : false;
+ String *params = NewString("");
+ String *_params = make_autodocParmList(n, false, ((in_class || has_self_for_count)? 2 : 1), is_calling, funcanno);
+
+ if (in_class) {
+ Printf(params, "self");
+ if (Len(_params) > 0)
+ Printf(params, ", ");
+ }
+
+ Printv(params, _params, NULL);
+
+ return params;
+ }
+
+ /* ------------------------------------------------------------
+ * have_pythonprepend()
+ *
+ * Check if there is a %pythonprepend directive and it has text
+ * ------------------------------------------------------------ */
+
+ bool have_pythonprepend(Node *n) {
+ String *str = Getattr(n, "feature:pythonprepend");
+ return (str && Len(str) > 0);
+ }
+
+ /* ------------------------------------------------------------
+ * pythonprepend()
+ *
+ * Get the %pythonprepend code, stripping off {} if necessary
+ * ------------------------------------------------------------ */
+
+ String *pythonprepend(Node *n) {
+ String *str = Getattr(n, "feature:pythonprepend");
+ char *t = Char(str);
+ if (*t == '{') {
+ Delitem(str, 0);
+ Delitem(str, DOH_END);
+ }
+ return str;
+ }
+
+ /* ------------------------------------------------------------
+ * have_pythonappend()
+ *
+ * Check if there is a %pythonappend directive and it has text
+ * ------------------------------------------------------------ */
+
+ bool have_pythonappend(Node *n) {
+ String *str = Getattr(n, "feature:pythonappend");
+ if (!str)
+ str = Getattr(n, "feature:addtofunc");
+ return (str && Len(str) > 0);
+ }
+
+ /* ------------------------------------------------------------
+ * pythonappend()
+ *
+ * Get the %pythonappend code, stripping off {} if necessary
+ * ------------------------------------------------------------ */
+
+ String *pythonappend(Node *n) {
+ String *str = Getattr(n, "feature:pythonappend");
+ if (!str)
+ str = Getattr(n, "feature:addtofunc");
+
+ char *t = Char(str);
+ if (*t == '{') {
+ Delitem(str, 0);
+ Delitem(str, DOH_END);
+ }
+ return str;
+ }
+
+ /* ------------------------------------------------------------
+ * have_addtofunc()
+ *
+ * Check if there is a %addtofunc directive and it has text
+ * ------------------------------------------------------------ */
+
+ bool have_addtofunc(Node *n) {
+ return have_pythonappend(n) || have_pythonprepend(n);
+ }
+
+
+ /* ------------------------------------------------------------
+ * returnTypeAnnotation()
+ *
+ * Helper function for constructing the function annotation
+ * of the returning type, return a empty string for Python 2.x
+ * ------------------------------------------------------------ */
+ String *returnTypeAnnotation(Node *n) {
+ String *ret = 0;
+ Parm *p = Getattr(n, "parms");
+ String *tm;
+ /* Try to guess the returning type by argout typemap,
+ * however the result may not accurate. */
+ while (p) {
+ if ((tm = Getattr(p, "tmap:argout:match_type"))) {
+ tm = SwigType_str(tm, 0);
+ if (ret)
+ Printv(ret, ", ", tm, NULL);
+ else
+ ret = tm;
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ /* If no argout typemap, then get the returning type from
+ * the function prototype. */
+ if (!ret) {
+ ret = Getattr(n, "type");
+ if (ret)
+ ret = SwigType_str(ret, 0);
+ }
+ return (ret && py3) ? NewStringf(" -> \"%s\"", ret)
+ : NewString("");
+ }
+
+ /* ------------------------------------------------------------
+ * emitFunctionShadowHelper()
+ *
+ * Refactoring some common code out of functionWrapper and
+ * dispatchFunction that writes the proxy code for non-member
+ * functions.
+ * ------------------------------------------------------------ */
+
+ void emitFunctionShadowHelper(Node *n, File *f_dest, String *name, int kw) {
+ String *parms = make_pyParmList(n, false, false, kw);
+ String *callParms = make_pyParmList(n, false, true, kw);
+
+ // Callbacks need the C function in order to extract the pointer from the swig_ptr: string
+ bool fast = (fastproxy && !have_addtofunc(n)) || Getattr(n, "feature:callback");
+
+ if (!fast || olddefs) {
+ /* Make a wrapper function to insert the code into */
+ Printv(f_dest, "\n", "def ", name, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
+ if (have_docstring(n))
+ Printv(f_dest, tab4, docstring(n, AUTODOC_FUNC, tab4, true), "\n", NIL);
+ if (have_pythonprepend(n))
+ Printv(f_dest, indent_pythoncode(pythonprepend(n), tab4, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL);
+ if (have_pythonappend(n)) {
+ Printv(f_dest, tab4 "val = ", funcCall(name, callParms), "\n", NIL);
+ Printv(f_dest, indent_pythoncode(pythonappend(n), tab4, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL);
+ Printv(f_dest, tab4 "return val\n", NIL);
+ } else {
+ Printv(f_dest, tab4 "return ", funcCall(name, callParms), "\n", NIL);
+ }
+ }
+
+ // Below may result in a 2nd definition of the method when -olddefs is used. The Python interpreter will use the second definition as it overwrites the first.
+ if (fast) {
+ /* If there is no addtofunc directive then just assign from the extension module (for speed up) */
+ Printv(f_dest, name, " = ", module, ".", name, "\n", NIL);
+ }
+ }
+
+
+ /* ------------------------------------------------------------
+ * check_kwargs()
+ *
+ * check if using kwargs is allowed for this Node
+ * ------------------------------------------------------------ */
+
+ int check_kwargs(Node *n) const {
+ return (use_kw || GetFlag(n, "feature:kwargs"))
+ && !GetFlag(n, "memberset") && !GetFlag(n, "memberget");
+ }
+
+
+
+ /* ------------------------------------------------------------
+ * add_method()
+ * ------------------------------------------------------------ */
+
+ void add_method(String *name, String *function, int kw, Node *n = 0, int funpack = 0, int num_required = -1, int num_arguments = -1) {
+ String * meth_str = NewString("");
+ if (!kw) {
+ if (funpack) {
+ if (num_required == 0 && num_arguments == 0) {
+ Printf(meth_str, "\t { \"%s\", %s, METH_NOARGS, ", name, function);
+ } else if (num_required == 1 && num_arguments == 1) {
+ Printf(meth_str, "\t { \"%s\", %s, METH_O, ", name, function);
+ } else {
+ Printf(meth_str, "\t { \"%s\", %s, METH_VARARGS, ", name, function);
+ }
+ } else {
+ Printf(meth_str, "\t { \"%s\", %s, METH_VARARGS, ", name, function);
+ }
+ } else {
+ // Cast via void(*)(void) to suppress GCC -Wcast-function-type warning.
+ // Python should always call the function correctly, but the Python C API
+ // requires us to store it in function pointer of a different type.
+ Printf(meth_str, "\t { \"%s\", (PyCFunction)(void(*)(void))%s, METH_VARARGS|METH_KEYWORDS, ", name, function);
+ }
+ Append(methods, meth_str);
+ if (fastproxy) {
+ Append(methods_proxydocs, meth_str);
+ }
+ Delete(meth_str);
+
+ if (!n) {
+ Append(methods, "NULL");
+ if (fastproxy) {
+ Append(methods_proxydocs, "NULL");
+ }
+ } else if (have_docstring(n)) {
+ /* Use the low-level docstring here since this is the docstring that will be used for the C API */
+ String *ds = cdocstring(n, Getattr(n, "memberfunction") ? AUTODOC_METHOD : AUTODOC_FUNC, true);
+ Printf(methods, "\"%s\"", ds);
+ if (fastproxy) {
+ /* In the fastproxy case, we must also record the high-level docstring for use in the Python shadow API */
+ Delete(ds);
+ ds = cdocstring(n, Getattr(n, "memberfunction") ? AUTODOC_METHOD : AUTODOC_FUNC);
+ Printf(methods_proxydocs, "\"%s\"", ds);
+ }
+ Delete(ds);
+ } else if (Getattr(n, "feature:callback")) {
+ Printf(methods, "\"swig_ptr: %s\"", Getattr(n, "feature:callback:name"));
+ if (fastproxy) {
+ Printf(methods_proxydocs, "\"swig_ptr: %s\"", Getattr(n, "feature:callback:name"));
+ }
+ } else {
+ Append(methods, "NULL");
+ if (fastproxy) {
+ Append(methods_proxydocs, "NULL");
+ }
+ }
+
+ Append(methods, "},\n");
+ if (fastproxy) {
+ Append(methods_proxydocs, "},\n");
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * dispatchFunction()
+ * ------------------------------------------------------------ */
+ void dispatchFunction(Node *n, String *linkage, int funpack = 0, bool builtin_self = false, bool builtin_ctor = false, bool director_class = false) {
+ /* Last node in overloaded chain */
+
+ bool add_self = builtin_self && (!builtin_ctor || director_class);
+
+ int maxargs;
+
+ String *tmp = NewString("");
+ String *dispatch;
+
+ const char *dispatch_call = funpack ? "%s(self, argc, argv);" : (builtin_ctor ? "%s(self, args, NULL);" : "%s(self, args);");
+ String *dispatch_code = NewStringf("return %s", dispatch_call);
+
+ if (castmode) {
+ dispatch = Swig_overload_dispatch_cast(n, dispatch_code, &maxargs);
+ } else {
+ String *fastdispatch_code;
+ if (builtin_ctor)
+ fastdispatch_code = NewStringf("int retval = %s\nif (retval == 0 || !SWIG_Python_TypeErrorOccurred(NULL)) return retval;\nSWIG_fail;", dispatch_call);
+ else
+ fastdispatch_code = NewStringf("PyObject *retobj = %s\nif (!SWIG_Python_TypeErrorOccurred(retobj)) return retobj;\nSWIG_fail;", dispatch_call);
+ if (!CPlusPlus) {
+ Insert(fastdispatch_code, 0, "{\n");
+ Append(fastdispatch_code, "\n}");
+ }
+ dispatch = Swig_overload_dispatch(n, dispatch_code, &maxargs, fastdispatch_code);
+ Delete(fastdispatch_code);
+ }
+
+ /* Generate a dispatch wrapper for all overloaded functions */
+
+ Wrapper *f = NewWrapper();
+ String *symname = Getattr(n, "sym:name");
+ String *wname = Swig_name_wrapper(symname);
+
+ const char *builtin_kwargs = builtin_ctor ? ", PyObject *kwargs" : "";
+ Printv(f->def, linkage, builtin_ctor ? "int " : "PyObject *", wname, "(PyObject *self, PyObject *args", builtin_kwargs, ") {", NIL);
+
+ Wrapper_add_local(f, "argc", "Py_ssize_t argc");
+ Printf(tmp, "PyObject *argv[%d] = {0}", maxargs + 1);
+ Wrapper_add_local(f, "argv", tmp);
+
+ if (!fastunpack) {
+ Wrapper_add_local(f, "ii", "Py_ssize_t ii");
+
+ if (builtin_ctor)
+ Printf(f->code, "if (!SWIG_Python_CheckNoKeywords(kwargs, \"%s\")) SWIG_fail;\n", symname);
+
+ if (maxargs - (add_self ? 1 : 0) > 0) {
+ Append(f->code, "if (!PyTuple_Check(args)) SWIG_fail;\n");
+ Append(f->code, "argc = PyObject_Length(args);\n");
+ } else {
+ Append(f->code, "argc = args ? PyObject_Length(args) : 0;\n");
+ }
+
+ if (add_self)
+ Append(f->code, "argv[0] = self;\n");
+ Printf(f->code, "for (ii = 0; (ii < %d) && (ii < argc); ii++) {\n", add_self ? maxargs - 1 : maxargs);
+ Printf(f->code, "argv[ii%s] = PyTuple_GET_ITEM(args,ii);\n", add_self ? " + 1" : "");
+ Append(f->code, "}\n");
+ if (add_self)
+ Append(f->code, "argc++;\n");
+ } else {
+ if (builtin_ctor)
+ Printf(f->code, "if (!SWIG_Python_CheckNoKeywords(kwargs, \"%s\")) SWIG_fail;\n", symname);
+ Printf(f->code, "if (!(argc = SWIG_Python_UnpackTuple(args, \"%s\", 0, %d, argv%s))) SWIG_fail;\n", symname, maxargs, add_self ? "+1" : "");
+ if (add_self)
+ Append(f->code, "argv[0] = self;\n");
+ else
+ Append(f->code, "--argc;\n");
+ }
+
+ Replaceall(dispatch, "$args", "self, args");
+
+ Printv(f->code, dispatch, "\n", NIL);
+
+ if (GetFlag(n, "feature:python:maybecall")) {
+ Append(f->code, "fail:\n");
+ Append(f->code, " Py_INCREF(Py_NotImplemented);\n");
+ Append(f->code, " return Py_NotImplemented;\n");
+ } else {
+ Node *sibl = n;
+ while (Getattr(sibl, "sym:previousSibling"))
+ sibl = Getattr(sibl, "sym:previousSibling"); // go all the way up
+ String *protoTypes = NewString("");
+ do {
+ String *fulldecl = Swig_name_decl(sibl);
+ Printf(protoTypes, "\n\" %s\\n\"", fulldecl);
+ Delete(fulldecl);
+ } while ((sibl = Getattr(sibl, "sym:nextSibling")));
+ Append(f->code, "fail:\n");
+ Printf(f->code, " SWIG_Python_RaiseOrModifyTypeError("
+ "\"Wrong number or type of arguments for overloaded function '%s'.\\n\"" "\n\" Possible C/C++ prototypes are:\\n\"%s);\n", symname, protoTypes);
+ Printf(f->code, "return %s;\n", builtin_ctor ? "-1" : "0");
+ Delete(protoTypes);
+ }
+ Printv(f->code, "}\n", NIL);
+ Wrapper_print(f, f_wrappers);
+ Node *p = Getattr(n, "sym:previousSibling");
+ if (!builtin_self)
+ add_method(symname, wname, 0, p);
+
+ /* Create a shadow for this function (if enabled and not in a member function) */
+ if (!builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER))) {
+ emitFunctionShadowHelper(n, in_class ? f_shadow_stubs : f_shadow, symname, 0);
+ }
+ DelWrapper(f);
+ Delete(dispatch);
+ Delete(dispatch_code);
+ Delete(tmp);
+ Delete(wname);
+ }
+
+ /* ------------------------------------------------------------
+ * functionWrapper()
+ * ------------------------------------------------------------ */
+
+ /*
+ A note about argument marshalling with built-in types.
+ There are three distinct cases for member (non-static) methods:
+
+ 1) An ordinary member function. In this case, the first param in
+ the param list is 'this'. For builtin types, 'this' is taken from
+ the first argument to the wrapper (usually called 'self); it's not
+ extracted from the second argument (which is usually a tuple).
+
+ 2) A constructor for a non-director class. In this case, the
+ param list doesn't contain an entry for 'this', but the first ('self')
+ argument to the wrapper *does* contain the newly-allocated,
+ uninitialized object.
+
+ 3) A constructor for a director class. In this case, the param
+ list contains a 'self' param, which comes from the first argument
+ to the wrapper function.
+ */
+
+ const char *get_implicitconv_flag(Node *klass) {
+ int conv = 0;
+ if (klass && GetFlag(klass, "feature:implicitconv")) {
+ conv = 1;
+ }
+ return conv ? "SWIG_POINTER_IMPLICIT_CONV" : "0";
+ }
+
+
+ virtual int functionWrapper(Node *n) {
+
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *d = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ Node *parent = Swig_methodclass(n);
+
+ int director_method = 0;
+
+ Parm *p;
+ int i;
+ char source[64];
+ Wrapper *f;
+ String *self_parse;
+ String *parse_args;
+ String *arglist;
+ String *get_pointers;
+ String *cleanup;
+ String *outarg;
+ String *kwargs;
+ String *tm;
+ String *overname = 0;
+
+ int num_required;
+ int num_arguments;
+ int num_fixed_arguments;
+ int tuple_required;
+ int tuple_arguments;
+ int varargs = 0;
+ int allow_kwargs = check_kwargs(n);
+
+ String *nodeType = Getattr(n, "nodeType");
+ int constructor = (!Cmp(nodeType, "constructor"));
+ int destructor = (!Cmp(nodeType, "destructor"));
+ String *storage = Getattr(n, "storage");
+ /* Only the first constructor is handled as init method. Others
+ constructor can be emitted via %rename */
+ int handled_as_init = 0;
+ if (!have_constructor && (constructor || Getattr(n, "handled_as_constructor"))
+ && ((shadow & PYSHADOW_MEMBER))) {
+ String *nname = Getattr(n, "sym:name");
+ String *sname = Getattr(getCurrentClass(), "sym:name");
+ String *cname = Swig_name_construct(NSPACE_TODO, sname);
+ handled_as_init = (Strcmp(nname, sname) == 0) || (Strcmp(nname, cname) == 0);
+ Delete(cname);
+ }
+ bool builtin_self = builtin && in_class && (constructor || (l && Getattr(l, "self")));
+ bool builtin_ctor = false;
+ if (builtin_self && constructor) {
+ String *class_mname = Getattr(getCurrentClass(), "sym:name");
+ String *mrename = Swig_name_construct(getNSpace(), class_mname);
+ if (Cmp(iname, mrename))
+ builtin_self = false;
+ else
+ builtin_ctor = true;
+ Delete(mrename);
+ }
+ bool director_class = (getCurrentClass() && Swig_directorclass(getCurrentClass()));
+ bool add_self = builtin_self && (!builtin_ctor || director_class);
+ bool builtin_getter = (builtin && GetFlag(n, "memberget"));
+ bool builtin_setter = (builtin && GetFlag(n, "memberset") && !builtin_getter);
+ char const *self_param = builtin ? "self" : "SWIGUNUSEDPARM(self)";
+ char const *wrap_return = builtin_ctor ? "int " : "PyObject *";
+ String *linkage = NewString("SWIGINTERN ");
+ String *wrapper_name = Swig_name_wrapper(iname);
+
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+ }
+
+ f = NewWrapper();
+ self_parse = NewString("");
+ parse_args = NewString("");
+ arglist = NewString("");
+ get_pointers = NewString("");
+ cleanup = NewString("");
+ outarg = NewString("");
+ kwargs = NewString("");
+
+ int allow_thread = threads_enable(n);
+
+ Wrapper_add_local(f, "resultobj", "PyObject *resultobj = 0");
+
+ // Emit all of the local variables for holding arguments.
+ emit_parameter_variables(l, f);
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+ Setattr(n, "wrap:parms", l);
+ /* Get number of required and total arguments */
+ tuple_arguments = num_arguments = emit_num_arguments(l);
+ tuple_required = num_required = emit_num_required(l);
+ if (add_self) {
+ --tuple_arguments;
+ --tuple_required;
+ }
+ num_fixed_arguments = tuple_required;
+
+ // builtin handles/checks kwargs by default except in constructor wrappers so we need to explicitly handle them in the C constructor wrapper
+ // The check below is for zero arguments. Sometimes (eg directors) self is the first argument for a method with zero arguments.
+ if (((num_arguments == 0) && (num_required == 0)) || ((num_arguments == 1) && (num_required == 1) && Getattr(l, "self")))
+ if (!builtin_ctor)
+ allow_kwargs = 0;
+ varargs = emit_isvarargs(l);
+
+ String *wname = Copy(wrapper_name);
+ if (overname) {
+ Append(wname, overname);
+ }
+
+ const char *builtin_kwargs = builtin_ctor ? ", PyObject *kwargs" : "";
+ if (!allow_kwargs || overname) {
+ if (!varargs) {
+ Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args", builtin_kwargs, ") {", NIL);
+ } else {
+ Printv(f->def, linkage, wrap_return, wname, "__varargs__", "(PyObject *", self_param, ", PyObject *args, PyObject *varargs) {", NIL);
+ }
+ if (allow_kwargs) {
+ Swig_warning(WARN_LANG_OVERLOAD_KEYWORD, input_file, line_number, "Can't use keyword arguments with overloaded functions (%s).\n", Swig_name_decl(n));
+ allow_kwargs = 0;
+ }
+ } else {
+ if (varargs) {
+ Swig_warning(WARN_LANG_VARARGS_KEYWORD, input_file, line_number, "Can't wrap varargs with keyword arguments enabled\n");
+ varargs = 0;
+ }
+ Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args, PyObject *kwargs) {", NIL);
+ }
+ if (!builtin || !in_class || tuple_arguments > 0 || builtin_ctor) {
+ if (!allow_kwargs) {
+ Append(parse_args, " if (!PyArg_ParseTuple(args, \"");
+ } else {
+ Append(parse_args, " if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"");
+ Append(arglist, ", kwnames");
+ }
+ }
+
+ bool over_varargs = emit_isvarargs_function(n);
+
+ int funpack = fastunpack && !varargs && !over_varargs && !allow_kwargs;
+ int noargs = funpack && (tuple_required == 0 && tuple_arguments == 0);
+ int onearg = funpack && (tuple_required == 1 && tuple_arguments == 1);
+
+ if (builtin && funpack && !overname && !builtin_ctor) {
+ int compactdefargs = ParmList_is_compactdefargs(l);
+ if (!(compactdefargs && (tuple_arguments > tuple_required || varargs))) {
+ String *argattr = NewStringf("%d", tuple_arguments);
+ Setattr(n, "python:argcount", argattr);
+ Delete(argattr);
+ }
+ }
+
+ /* Generate code for argument marshalling */
+ if (funpack) {
+ if (num_arguments > 0 && !overname) {
+ sprintf(source, "PyObject *swig_obj[%d]", num_arguments);
+ Wrapper_add_localv(f, "swig_obj", source, NIL);
+ }
+ }
+
+
+ if (constructor && num_arguments == 1 && num_required == 1) {
+ if (Cmp(storage, "explicit") == 0) {
+ if (GetFlag(parent, "feature:implicitconv")) {
+ String *desc = NewStringf("SWIGTYPE%s", SwigType_manglestr(Getattr(n, "type")));
+ Printf(f->code, "if (SWIG_CheckImplicit(%s)) SWIG_fail;\n", desc);
+ Delete(desc);
+ }
+ }
+ }
+
+ if (builtin_ctor && checkAttribute(n, "access", "protected")) {
+ String *tmp_none_comparison = Copy(none_comparison);
+ Replaceall(tmp_none_comparison, "$arg", "self");
+ Printf(self_parse, "if (!(%s)) {\n", tmp_none_comparison);
+ Printv(self_parse, " SWIG_SetErrorMsg(PyExc_RuntimeError, \"accessing abstract class or protected constructor\");\n SWIG_fail;\n}\n", NIL);
+ Delete(tmp_none_comparison);
+ }
+
+ int use_parse = 0;
+ Append(kwargs, "{");
+ for (i = 0, p = l; i < num_arguments; i++) {
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+ bool parse_from_tuple = (i > 0 || !add_self);
+ if (SwigType_type(pt) == T_VARARGS) {
+ parse_from_tuple = false;
+ num_fixed_arguments -= atoi(Char(Getattr(p, "tmap:in:numinputs")));
+ }
+ if (!parse_from_tuple)
+ sprintf(source, "self");
+ else if (funpack)
+ sprintf(source, "swig_obj[%d]", add_self && !overname ? i - 1 : i);
+ else
+ sprintf(source, "obj%d", builtin_ctor ? i + 1 : i);
+
+ if (parse_from_tuple) {
+ Printf(arglist, ", ");
+ if (i == num_required)
+ Putc('|', parse_args); /* Optional argument separator */
+ }
+
+ /* Keyword argument handling */
+ if (allow_kwargs && parse_from_tuple) {
+ String *name = makeParameterName(n, p, i + 1);
+ Printf(kwargs, " (char *)\"%s\", ", name);
+ Delete(name);
+ }
+
+ /* Look for an input typemap */
+ if ((tm = Getattr(p, "tmap:in"))) {
+ String *parse = Getattr(p, "tmap:in:parse");
+ if (!parse) {
+ if (builtin_self) {
+ Replaceall(tm, "$self", "self");
+ } else if (funpack) {
+ Replaceall(tm, "$self", "swig_obj[0]");
+ } else {
+ Replaceall(tm, "$self", "obj0");
+ }
+ Replaceall(tm, "$source", source);
+ Replaceall(tm, "$target", ln);
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source); /* Save the location of the object */
+
+ if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+
+ if (Getattr(p, "tmap:in:implicitconv")) {
+ const char *convflag = "0";
+ if (!Getattr(p, "hidden")) {
+ SwigType *ptype = Getattr(p, "type");
+ convflag = get_implicitconv_flag(classLookup(ptype));
+ }
+ Replaceall(tm, "$implicitconv", convflag);
+ Setattr(p, "implicitconv", convflag);
+ }
+
+ if (parse_from_tuple)
+ Putc('O', parse_args);
+ if (!funpack && parse_from_tuple) {
+ Wrapper_add_localv(f, source, "PyObject *", source, "= 0", NIL);
+ Printf(arglist, "&%s", source);
+ }
+ if (i >= num_required)
+ Printv(get_pointers, "if (", source, ") {\n", NIL);
+ Printv(get_pointers, tm, "\n", NIL);
+ if (i >= num_required)
+ Printv(get_pointers, "}\n", NIL);
+
+ } else {
+ use_parse = 1;
+ Append(parse_args, parse);
+ if (parse_from_tuple)
+ Printf(arglist, "&%s", ln);
+ }
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ } else {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
+ break;
+ }
+ }
+
+ /* finish argument marshalling */
+ Append(kwargs, " NULL }");
+ if (allow_kwargs) {
+ Printv(f->locals, " char * kwnames[] = ", kwargs, ";\n", NIL);
+ }
+
+ if (use_parse || allow_kwargs) {
+ Printf(parse_args, ":%s\"", iname);
+ Printv(parse_args, arglist, ")) SWIG_fail;\n", NIL);
+ funpack = 0;
+ } else {
+ Clear(parse_args);
+
+ if (funpack) {
+ Clear(f->def);
+ if (overname) {
+ if (noargs) {
+ Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", Py_ssize_t nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) {", NIL);
+ } else {
+ Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", Py_ssize_t nobjs, PyObject **swig_obj) {", NIL);
+ }
+ Printf(parse_args, "if ((nobjs < %d) || (nobjs > %d)) SWIG_fail;\n", num_required, num_arguments);
+ } else {
+ int is_tp_call = Equal(Getattr(n, "feature:python:slot"), "tp_call");
+ Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args", builtin_kwargs, ") {", NIL);
+ if (builtin_ctor)
+ Printf(parse_args, "if (!SWIG_Python_CheckNoKeywords(kwargs, \"%s\")) SWIG_fail;\n", iname);
+ if (onearg && !builtin_ctor && !is_tp_call) {
+ Printf(parse_args, "if (!args) SWIG_fail;\n");
+ Append(parse_args, "swig_obj[0] = args;\n");
+ } else if (!noargs) {
+ Printf(parse_args, "if (!SWIG_Python_UnpackTuple(args, \"%s\", %d, %d, swig_obj)) SWIG_fail;\n", iname, num_fixed_arguments, tuple_arguments);
+ } else if (noargs) {
+ Printf(parse_args, "if (!SWIG_Python_UnpackTuple(args, \"%s\", %d, %d, 0)) SWIG_fail;\n", iname, num_fixed_arguments, tuple_arguments);
+ }
+ }
+ } else {
+ if (builtin_ctor)
+ Printf(parse_args, "if (!SWIG_Python_CheckNoKeywords(kwargs, \"%s\")) SWIG_fail;\n", iname);
+ if (builtin && in_class && tuple_arguments == 0) {
+ Printf(parse_args, " if (args && PyTuple_Check(args) && PyTuple_GET_SIZE(args) > 0) SWIG_exception_fail(SWIG_TypeError, \"%s takes no arguments\");\n", iname);
+ } else {
+ Printf(parse_args, "if (!PyArg_UnpackTuple(args, \"%s\", %d, %d", iname, num_fixed_arguments, tuple_arguments);
+ Printv(parse_args, arglist, ")) SWIG_fail;\n", NIL);
+ }
+ }
+ }
+
+ /* Now piece together the first part of the wrapper function */
+ Printv(f->code, self_parse, parse_args, get_pointers, NIL);
+
+ /* Check for trailing varargs */
+ if (varargs) {
+ if (p && (tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$input", "varargs");
+ Printv(f->code, tm, "\n", NIL);
+ }
+ }
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ for (p = l; p;) {
+ if (!Getattr(p, "tmap:in:parse") && (tm = Getattr(p, "tmap:freearg"))) {
+ if (Getattr(p, "tmap:freearg:implicitconv")) {
+ const char *convflag = "0";
+ if (!Getattr(p, "hidden")) {
+ SwigType *ptype = Getattr(p, "type");
+ convflag = get_implicitconv_flag(classLookup(ptype));
+ }
+ if (strcmp(convflag, "0") == 0) {
+ tm = 0;
+ }
+ }
+ if (tm && (Len(tm) != 0)) {
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+ Printv(cleanup, tm, "\n", NIL);
+ }
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert argument output code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+ Replaceall(tm, "$target", "resultobj");
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* if the object is a director, and the method call originated from its
+ * underlying python object, resolve the call by going up the c++
+ * inheritance chain. otherwise try to resolve the method in python.
+ * without this check an infinite loop is set up between the director and
+ * shadow class method calls.
+ */
+
+ // NOTE: this code should only be inserted if this class is the
+ // base class of a director class. however, in general we haven't
+ // yet analyzed all classes derived from this one to see if they are
+ // directors. furthermore, this class may be used as the base of
+ // a director class defined in a completely different module at a
+ // later time, so this test must be included whether or not directorbase
+ // is true. we do skip this code if directors have not been enabled
+ // at the command line to preserve source-level compatibility with
+ // non-polymorphic swig. also, if this wrapper is for a smart-pointer
+ // method, there is no need to perform the test since the calling object
+ // (the smart-pointer) and the director object (the "pointee") are
+ // distinct.
+
+ director_method = is_member_director(n) && !is_smart_pointer() && !destructor;
+ if (director_method) {
+ Wrapper_add_local(f, "director", "Swig::Director *director = 0");
+ Append(f->code, "director = SWIG_DIRECTOR_CAST(arg1);\n");
+ if (dirprot_mode() && !is_public(n)) {
+ Printf(f->code, "if (!director || !(director->swig_get_inner(\"%s\"))) {\n", name);
+ Printf(f->code, "SWIG_SetErrorMsg(PyExc_RuntimeError,\"accessing protected member %s\");\n", name);
+ Append(f->code, "SWIG_fail;\n");
+ Append(f->code, "}\n");
+ }
+ Wrapper_add_local(f, "upcall", "bool upcall = false");
+ if (funpack) {
+ const char *self_parm = builtin_self ? "self" : "swig_obj[0]";
+ Printf(f->code, "upcall = (director && (director->swig_get_self()==%s));\n", self_parm);
+ } else {
+ const char *self_parm = builtin_self ? "self" : "obj0";
+ Printf(f->code, "upcall = (director && (director->swig_get_self()==%s));\n", self_parm);
+ }
+ }
+
+ /* Emit the function call */
+ if (director_method) {
+ Append(f->code, "try {\n");
+ } else {
+ if (allow_thread) {
+ String *preaction = NewString("");
+ thread_begin_allow(n, preaction);
+ Setattr(n, "wrap:preaction", preaction);
+
+ String *postaction = NewString("");
+ thread_end_allow(n, postaction);
+ Setattr(n, "wrap:postaction", postaction);
+ }
+ }
+
+ Setattr(n, "wrap:name", wname);
+
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ if (director_method) {
+ Append(actioncode, "} catch (Swig::DirectorException&) {\n");
+ Append(actioncode, " SWIG_fail;\n");
+ Append(actioncode, "}\n");
+ }
+
+ /* This part below still needs cleanup */
+
+ /* Return the function value */
+ tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode);
+
+ if (tm) {
+ if (builtin_self) {
+ Replaceall(tm, "$self", "self");
+ } else if (funpack) {
+ Replaceall(tm, "$self", "swig_obj[0]");
+ } else {
+ Replaceall(tm, "$self", "obj0");
+ }
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Replaceall(tm, "$target", "resultobj");
+ Replaceall(tm, "$result", "resultobj");
+ if (builtin_ctor) {
+ Replaceall(tm, "$owner", "SWIG_BUILTIN_INIT");
+ } else if (handled_as_init) {
+ Replaceall(tm, "$owner", "SWIG_POINTER_NEW");
+ } else {
+ if (GetFlag(n, "feature:new")) {
+ Replaceall(tm, "$owner", "SWIG_POINTER_OWN");
+ } else {
+ Replaceall(tm, "$owner", "0");
+ }
+ }
+ // FIXME: this will not try to unwrap directors returned as non-director
+ // base class pointers!
+
+ /* New addition to unwrap director return values so that the original
+ * python object is returned instead.
+ */
+#if 1
+ int unwrap = 0;
+ String *decl = Getattr(n, "decl");
+ int is_pointer = SwigType_ispointer_return(decl);
+ int is_reference = SwigType_isreference_return(decl);
+ if (is_pointer || is_reference) {
+ String *type = Getattr(n, "type");
+ //Node *classNode = Swig_methodclass(n);
+ //Node *module = Getattr(classNode, "module");
+ Node *module = Getattr(parent, "module");
+ Node *target = Swig_directormap(module, type);
+ if (target)
+ unwrap = 1;
+ }
+ if (unwrap) {
+ Wrapper_add_local(f, "director", "Swig::Director *director = 0");
+ Printf(f->code, "director = SWIG_DIRECTOR_CAST(%s);\n", Swig_cresult_name());
+ Append(f->code, "if (director) {\n");
+ Append(f->code, " resultobj = director->swig_get_self();\n");
+ Append(f->code, " Py_INCREF(resultobj);\n");
+ Append(f->code, "} else {\n");
+ Printf(f->code, "%s\n", tm);
+ Append(f->code, "}\n");
+ } else {
+ Printf(f->code, "%s\n", tm);
+ }
+#else
+ Printf(f->code, "%s\n", tm);
+#endif
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name);
+ }
+ emit_return_variable(n, d, f);
+
+ /* Output argument output code */
+ Printv(f->code, outarg, NIL);
+
+ /* Output cleanup code */
+ int need_cleanup = Len(cleanup) != 0;
+ if (need_cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+
+ /* Look to see if there is any newfree cleanup code */
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+
+ if (director_method) {
+ if ((tm = Swig_typemap_lookup("directorfree", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ Replaceall(tm, "$result", "resultobj");
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+ }
+
+ if (builtin_ctor)
+ Append(f->code, " return resultobj == Py_None ? -1 : 0;\n");
+ else
+ Append(f->code, " return resultobj;\n");
+
+ /* Error handling code */
+
+ Append(f->code, "fail:\n");
+ if (need_cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+ if (builtin_ctor) {
+ Printv(f->code, " return -1;\n", NIL);
+ } else {
+ if (GetFlag(n, "feature:python:maybecall")) {
+ Append(f->code, " PyErr_Clear();\n");
+ Append(f->code, " Py_INCREF(Py_NotImplemented);\n");
+ Append(f->code, " return Py_NotImplemented;\n");
+ } else {
+ Printv(f->code, " return NULL;\n", NIL);
+ }
+ }
+
+ Append(f->code, "}\n");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", iname);
+ Replaceall(f->code, "$result", "resultobj");
+
+ if (builtin_self) {
+ Replaceall(f->code, "$self", "self");
+ } else if (funpack) {
+ Replaceall(f->code, "$self", "swig_obj[0]");
+ } else {
+ Replaceall(f->code, "$self", "obj0");
+ }
+
+ /* Dump the function out */
+ Wrapper_print(f, f_wrappers);
+
+ /* If varargs. Need to emit a varargs stub */
+ if (varargs) {
+ DelWrapper(f);
+ f = NewWrapper();
+ if (funpack) {
+ // Note: funpack is currently always false for varargs
+ Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", Py_ssize_t nobjs, PyObject **swig_obj) {", NIL);
+ } else {
+ Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args", builtin_kwargs, ") {", NIL);
+ }
+ Wrapper_add_local(f, "resultobj", builtin_ctor ? "int resultobj" : "PyObject *resultobj");
+ Wrapper_add_local(f, "varargs", "PyObject *varargs");
+ Wrapper_add_local(f, "newargs", "PyObject *newargs");
+ if (funpack) {
+ Wrapper_add_local(f, "i", "int i");
+ Printf(f->code, "newargs = PyTuple_New(%d);\n", num_fixed_arguments);
+ Printf(f->code, "for (i = 0; i < %d; ++i) {\n", num_fixed_arguments);
+ Printf(f->code, " PyTuple_SET_ITEM(newargs, i, swig_obj[i]);\n");
+ Printf(f->code, " Py_XINCREF(swig_obj[i]);\n");
+ Printf(f->code, "}\n");
+ Printf(f->code, "varargs = PyTuple_New(nobjs > %d ? nobjs - %d : 0);\n", num_fixed_arguments, num_fixed_arguments);
+ Printf(f->code, "for (i = 0; i < nobjs - %d; ++i) {\n", num_fixed_arguments);
+ Printf(f->code, " PyTuple_SET_ITEM(newargs, i, swig_obj[i + %d]);\n", num_fixed_arguments);
+ Printf(f->code, " Py_XINCREF(swig_obj[i + %d]);\n", num_fixed_arguments);
+ Printf(f->code, "}\n");
+ } else {
+ Printf(f->code, "newargs = PyTuple_GetSlice(args,0,%d);\n", num_fixed_arguments);
+ Printf(f->code, "varargs = PyTuple_GetSlice(args,%d,PyTuple_Size(args));\n", num_fixed_arguments);
+ }
+ Printf(f->code, "resultobj = %s__varargs__(%s,newargs,varargs);\n", wname, builtin ? "self" : "NULL");
+ Append(f->code, "Py_XDECREF(newargs);\n");
+ Append(f->code, "Py_XDECREF(varargs);\n");
+ Append(f->code, "return resultobj;\n");
+ Append(f->code, "}\n");
+ Wrapper_print(f, f_wrappers);
+ }
+
+ /* Now register the function with the interpreter. */
+ if (!Getattr(n, "sym:overloaded")) {
+ if (!builtin_self)
+ add_method(iname, wname, allow_kwargs, n, funpack, num_required, num_arguments);
+
+ /* Create a shadow for this function (if enabled and not in a member function) */
+ if (!builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER))) {
+ emitFunctionShadowHelper(n, in_class ? f_shadow_stubs : f_shadow, iname, allow_kwargs);
+ }
+ } else {
+ if (!Getattr(n, "sym:nextSibling")) {
+ dispatchFunction(n, linkage, funpack, builtin_self, builtin_ctor, director_class);
+ }
+ }
+
+ // Put this in tp_init of the PyTypeObject
+ if (builtin_ctor) {
+ if ((director_method || !is_private(n)) && !Getattr(class_members, iname)) {
+ Setattr(class_members, iname, n);
+ if (!builtin_tp_init)
+ builtin_tp_init = Swig_name_wrapper(iname);
+ }
+ }
+
+ /* If this is a builtin type, create a PyGetSetDef entry for this member variable. */
+ if (builtin) {
+ const char *memname = "__dict__";
+ Hash *h = Getattr(builtin_getset, memname);
+ if (!h) {
+ h = NewHash();
+ Setattr(builtin_getset, memname, h);
+ Delete(h);
+ }
+ Setattr(h, "getter", "SwigPyObject_get___dict__");
+ if (!Getattr(h, "doc")) {
+ Setattr(n, "doc:high:name", Getattr(n, "name"));
+ Setattr(h, "doc", cdocstring(n, AUTODOC_VAR));
+ }
+ }
+
+ if (builtin_getter) {
+ String *memname = Getattr(n, "membervariableHandler:sym:name");
+ if (!memname)
+ memname = iname;
+ Hash *h = Getattr(builtin_getset, memname);
+ if (!h) {
+ h = NewHash();
+ Setattr(builtin_getset, memname, h);
+ Delete(h);
+ }
+ Setattr(h, "getter", wrapper_name);
+ Delattr(n, "memberget");
+ if (!Getattr(h, "doc")) {
+ Setattr(n, "doc:high:name", Getattr(n, "name"));
+ String *ds = cdocstring(n, AUTODOC_VAR);
+ Setattr(h, "doc", ds);
+ Delete(ds);
+ }
+ }
+ if (builtin_setter) {
+ String *memname = Getattr(n, "membervariableHandler:sym:name");
+ if (!memname)
+ memname = iname;
+ Hash *h = Getattr(builtin_getset, memname);
+ if (!h) {
+ h = NewHash();
+ Setattr(builtin_getset, memname, h);
+ Delete(h);
+ }
+ Setattr(h, "setter", wrapper_name);
+ Delattr(n, "memberset");
+ if (!Getattr(h, "doc")) {
+ Setattr(n, "doc:high:name", Getattr(n, "name"));
+ String *ds = cdocstring(n, AUTODOC_VAR);
+ Setattr(h, "doc", ds);
+ Delete(ds);
+ }
+ }
+
+ if (in_class && builtin) {
+ /* Handle operator overloads for builtin types */
+ String *slot = Getattr(n, "feature:python:slot");
+ if (slot) {
+ String *func_type = Getattr(n, "feature:python:slot:functype");
+ String *closure_decl = getClosure(func_type, wrapper_name, overname ? 0 : funpack);
+ String *feature_name = NewStringf("feature:python:%s", slot);
+ String *closure_name = 0;
+ if (closure_decl) {
+ closure_name = NewStringf("%s_%s_closure", wrapper_name, func_type);
+ if (!GetFlag(builtin_closures, closure_name))
+ Printf(builtin_closures_code, "%s /* defines %s */\n\n", closure_decl, closure_name);
+ SetFlag(builtin_closures, closure_name);
+ Delete(closure_decl);
+ } else {
+ closure_name = Copy(wrapper_name);
+ }
+ if (func_type) {
+ String *s = NewStringf("%s", closure_name);
+ Delete(closure_name);
+ closure_name = s;
+ }
+ Setattr(parent, feature_name, closure_name);
+ Delete(feature_name);
+ Delete(closure_name);
+ }
+
+ /* Handle comparison operators for builtin types */
+ String *compare = Getattr(n, "feature:python:compare");
+ if (compare) {
+ Hash *richcompare = Getattr(parent, "python:richcompare");
+ assert(richcompare);
+ Setattr(richcompare, compare, wrapper_name);
+ }
+ }
+
+ Delete(self_parse);
+ Delete(parse_args);
+ Delete(linkage);
+ Delete(arglist);
+ Delete(get_pointers);
+ Delete(cleanup);
+ Delete(outarg);
+ Delete(kwargs);
+ Delete(wname);
+ DelWrapper(f);
+ Delete(wrapper_name);
+ return SWIG_OK;
+ }
+
+
+
+ /* ------------------------------------------------------------
+ * variableWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int variableWrapper(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+
+ static int have_globals = 0;
+ String *tm;
+ Wrapper *getf, *setf;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ getf = NewWrapper();
+ setf = NewWrapper();
+
+ /* If this is our first call, add the globals variable to the
+ Python dictionary. */
+
+ if (!have_globals) {
+ Printf(f_init, "\t globals = SWIG_globals();\n");
+ Printf(f_init, "\t if (!globals) {\n");
+ Printf(f_init, " PyErr_SetString(PyExc_TypeError, \"Failure to create SWIG globals.\");\n");
+ Printf(f_init, "#if PY_VERSION_HEX >= 0x03000000\n");
+ Printf(f_init, "\t return NULL;\n");
+ Printf(f_init, "#else\n");
+ Printf(f_init, "\t return;\n");
+ Printf(f_init, "#endif\n");
+ Printf(f_init, "\t }\n");
+ Printf(f_init, "\t PyDict_SetItemString(md, \"%s\", globals);\n", global_name);
+ Printf(f_init, "\t Py_DECREF(globals);\n");
+ if (builtin)
+ Printf(f_init, "\t SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", global_name);
+ have_globals = 1;
+ if (!builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER))) {
+ Printf(f_shadow_stubs, "%s = %s.%s\n", global_name, module, global_name);
+ }
+ }
+ int assignable = is_assignable(n);
+
+ if (!builtin && shadow && !assignable && !in_class)
+ Printf(f_shadow_stubs, "%s = %s.%s\n", iname, global_name, iname);
+
+ String *getname = Swig_name_get(NSPACE_TODO, iname);
+ String *setname = Swig_name_set(NSPACE_TODO, iname);
+ String *vargetname = NewStringf("Swig_var_%s", getname);
+ String *varsetname = NewStringf("Swig_var_%s", setname);
+
+ /* Create a function for setting the value of the variable */
+ if (assignable) {
+ Setattr(n, "wrap:name", varsetname);
+ if (builtin && in_class) {
+ String *set_wrapper = Swig_name_wrapper(setname);
+ Setattr(n, "pybuiltin:setter", set_wrapper);
+ Delete(set_wrapper);
+ }
+ Printf(setf->def, "SWIGINTERN int %s(PyObject *_val) {", varsetname);
+ if ((tm = Swig_typemap_lookup("varin", n, name, 0))) {
+ Replaceall(tm, "$source", "_val");
+ Replaceall(tm, "$target", name);
+ Replaceall(tm, "$input", "_val");
+ if (Getattr(n, "tmap:varin:implicitconv")) {
+ Replaceall(tm, "$implicitconv", get_implicitconv_flag(n));
+ }
+ emit_action_code(n, setf->code, tm);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0));
+ }
+ Printv(setf->code, " return 0;\n", NULL);
+ Append(setf->code, "fail:\n");
+ Printv(setf->code, " return 1;\n", NULL);
+ } else {
+ /* Is a readonly variable. Issue an error */
+ if (CPlusPlus) {
+ Printf(setf->def, "SWIGINTERN int %s(PyObject *) {", varsetname);
+ } else {
+ Printf(setf->def, "SWIGINTERN int %s(PyObject *_val SWIGUNUSED) {", varsetname);
+ }
+ Printv(setf->code, " SWIG_Error(SWIG_AttributeError,\"Variable ", iname, " is read-only.\");\n", " return 1;\n", NIL);
+ }
+
+ Append(setf->code, "}\n");
+ Wrapper_print(setf, f_wrappers);
+
+ /* Create a function for getting the value of a variable */
+ Setattr(n, "wrap:name", vargetname);
+ if (builtin && in_class) {
+ String *get_wrapper = Swig_name_wrapper(getname);
+ Setattr(n, "pybuiltin:getter", get_wrapper);
+ Delete(get_wrapper);
+ }
+ int addfail = 0;
+ Printf(getf->def, "SWIGINTERN PyObject *%s(void) {", vargetname);
+ Wrapper_add_local(getf, "pyobj", "PyObject *pyobj = 0");
+ if (builtin) {
+ Wrapper_add_local(getf, "self", "PyObject *self = 0");
+ Append(getf->code, " (void)self;\n");
+ }
+ if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
+ Replaceall(tm, "$source", name);
+ Replaceall(tm, "$target", "pyobj");
+ Replaceall(tm, "$result", "pyobj");
+ addfail = emit_action_code(n, getf->code, tm);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
+ }
+ Append(getf->code, " return pyobj;\n");
+ if (addfail) {
+ Append(getf->code, "fail:\n");
+ Append(getf->code, " return NULL;\n");
+ }
+ Append(getf->code, "}\n");
+
+ Wrapper_print(getf, f_wrappers);
+
+ /* Now add this to the variable linking mechanism */
+ Printf(f_init, "\t SWIG_addvarlink(globals, \"%s\", %s, %s);\n", iname, vargetname, varsetname);
+ if (builtin && shadow && !assignable && !in_class) {
+ Printf(f_init, "\t PyDict_SetItemString(md, \"%s\", PyObject_GetAttrString(globals, \"%s\"));\n", iname, iname);
+ Printf(f_init, "\t SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", iname);
+ }
+ Delete(vargetname);
+ Delete(varsetname);
+ Delete(getname);
+ Delete(setname);
+ DelWrapper(setf);
+ DelWrapper(getf);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ * ------------------------------------------------------------ */
+
+ /* Determine if the node requires the _swigconstant code to be generated */
+ bool needs_swigconstant(Node *n) {
+ SwigType *type = Getattr(n, "type");
+ SwigType *qtype = SwigType_typedef_resolve_all(type);
+ SwigType *uqtype = SwigType_strip_qualifiers(qtype);
+ bool result = false;
+
+ /* Note, that we need special handling for function pointers, as
+ * SwigType_base(fptr) does not return the underlying pointer-to-function
+ * type but the return-type of function. */
+ if (!SwigType_isfunction(uqtype) && !SwigType_isfunctionpointer(uqtype)) {
+ SwigType *basetype = SwigType_base(uqtype);
+ result = SwigType_isclass(basetype) != 0;
+ Delete(basetype);
+ }
+
+ Delete(qtype);
+ Delete(uqtype);
+
+ return result;
+ }
+
+ virtual int constantWrapper(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *rawval = Getattr(n, "rawval");
+ String *value = rawval ? rawval : Getattr(n, "value");
+ String *tm;
+ int have_tm = 0;
+ int have_builtin_symname = 0;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ /* Special hook for member pointer */
+ if (SwigType_type(type) == T_MPOINTER) {
+ String *wname = Swig_name_wrapper(iname);
+ String *str = SwigType_str(type, wname);
+ Printf(f_header, "static %s = %s;\n", str, value);
+ Delete(str);
+ value = wname;
+ }
+
+ if ((tm = Swig_typemap_lookup("consttab", n, name, 0))) {
+ Replaceall(tm, "$source", value);
+ Replaceall(tm, "$target", name);
+ Replaceall(tm, "$value", value);
+ Printf(const_code, "%s,\n", tm);
+ Delete(tm);
+ have_tm = 1;
+ }
+
+
+ if (builtin && in_class && Getattr(n, "pybuiltin:symname")) {
+ have_builtin_symname = 1;
+ Swig_require("builtin_constantWrapper", n, "*sym:name", "pybuiltin:symname", NIL);
+ Setattr(n, "sym:name", Getattr(n, "pybuiltin:symname"));
+ }
+
+ if ((tm = Swig_typemap_lookup("constcode", n, name, 0))) {
+ Replaceall(tm, "$source", value);
+ Replaceall(tm, "$target", name);
+ Replaceall(tm, "$value", value);
+ if (needs_swigconstant(n) && !builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER)) && (!in_class || !Getattr(n, "feature:python:callback"))) {
+ // Generate `*_swigconstant()` method which registers the new constant.
+ //
+ // *_swigconstant methods are required for constants of class type.
+ // Class types are registered in shadow file (see *_swigregister). The
+ // instances of class must be created (registered) after the type is
+ // registered, so we can't let SWIG_init() to register constants of
+ // class type (the SWIG_init() is called before shadow classes are
+ // defined and registered).
+ Printf(f_wrappers, "SWIGINTERN PyObject *%s_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {\n", iname);
+ Printf(f_wrappers, tab2 "PyObject *module;\n", tm);
+ Printf(f_wrappers, tab2 "PyObject *d;\n");
+ Printf(f_wrappers, tab2 "if (!SWIG_Python_UnpackTuple(args, \"swigconstant\", 1, 1, &module)) return NULL;\n");
+ Printf(f_wrappers, tab2 "d = PyModule_GetDict(module);\n");
+ Printf(f_wrappers, tab2 "if (!d) return NULL;\n");
+ Printf(f_wrappers, tab2 "%s\n", tm);
+ Printf(f_wrappers, tab2 "return SWIG_Py_Void();\n");
+ Printf(f_wrappers, "}\n\n\n");
+
+ // Register the method in SwigMethods array
+ String *cname = NewStringf("%s_swigconstant", iname);
+ add_method(cname, cname, 0, 0, 1, 1, 1);
+ Delete(cname);
+ } else {
+ Printf(f_init, "%s\n", tm);
+ }
+ Delete(tm);
+ have_tm = 1;
+ }
+
+ if (have_builtin_symname)
+ Swig_restore(n);
+
+ if (!have_tm) {
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
+ return SWIG_NOWRAP;
+ }
+
+ if (!builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER))) {
+ String *f_s;
+ if (!in_class) {
+ f_s = f_shadow;
+ } else {
+ f_s = Getattr(n, "feature:python:callback") ? NIL : f_shadow_stubs;
+ }
+
+ if (f_s) {
+ if (needs_swigconstant(n)) {
+ Printv(f_s, "\n",NIL);
+ Printv(f_s, module, ".", iname, "_swigconstant(",module,")\n", NIL);
+ }
+ Printv(f_s, iname, " = ", module, ".", iname, "\n", NIL);
+ if (have_docstring(n))
+ Printv(f_s, docstring(n, AUTODOC_CONST, tab4), "\n", NIL);
+ }
+ }
+ return SWIG_OK;
+ }
+
+
+ /* ------------------------------------------------------------
+ * nativeWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int nativeWrapper(Node *n) {
+ String *name = Getattr(n, "sym:name");
+ String *wrapname = Getattr(n, "wrap:name");
+
+ if (!addSymbol(wrapname, n))
+ return SWIG_ERROR;
+
+ add_method(name, wrapname, 0);
+ if (!builtin && shadow) {
+ Printv(f_shadow_stubs, name, " = ", module, ".", name, "\n", NIL);
+ }
+ return SWIG_OK;
+ }
+
+
+
+ /* ----------------------------------------------------------------------------
+ * BEGIN C++ Director Class modifications
+ * ------------------------------------------------------------------------- */
+
+ /* C++/Python polymorphism demo code
+ *
+ * TODO
+ *
+ * Move some boilerplate code generation to Swig_...() functions.
+ *
+ */
+
+ /* ---------------------------------------------------------------
+ * classDirectorMethod()
+ *
+ * Emit a virtual director method to pass a method call on to the
+ * underlying Python object.
+ * ** Moved down due to gcc-2.96 internal error **
+ * --------------------------------------------------------------- */
+
+ int classDirectorMethods(Node *n);
+
+ int classDirectorMethod(Node *n, Node *parent, String *super);
+
+ /* ------------------------------------------------------------
+ * classDirectorConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorConstructor(Node *n) {
+ Node *parent = Getattr(n, "parentNode");
+ String *sub = NewString("");
+ String *decl = Getattr(n, "decl");
+ String *supername = Swig_class_name(parent);
+ String *classname = NewString("");
+ Printf(classname, "SwigDirector_%s", supername);
+
+ /* insert self parameter */
+ Parm *p;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms = CopyParmList(superparms);
+ String *type = NewString("PyObject");
+ SwigType_add_pointer(type);
+ p = NewParm(type, NewString("self"), n);
+ set_nextSibling(p, parms);
+ parms = p;
+
+ if (!Getattr(n, "defaultargs")) {
+ /* constructor */
+ {
+ Wrapper *w = NewWrapper();
+ String *call;
+ String *basetype = Getattr(parent, "classtype");
+ String *target = Swig_method_decl(0, decl, classname, parms, 0);
+ call = Swig_csuperclass_call(0, basetype, superparms);
+ Printf(w->def, "%s::%s: %s, Swig::Director(self) { \n", classname, target, call);
+ Printf(w->def, " SWIG_DIRECTOR_RGTR((%s *)this, this); \n", basetype);
+ Append(w->def, "}\n");
+ Delete(target);
+ Wrapper_print(w, f_directors);
+ Delete(call);
+ DelWrapper(w);
+ }
+
+ /* constructor header */
+ {
+ String *target = Swig_method_decl(0, decl, classname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Delete(sub);
+ Delete(classname);
+ Delete(supername);
+ Delete(parms);
+ return Language::classDirectorConstructor(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDefaultConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorDefaultConstructor(Node *n) {
+ String *classname = Swig_class_name(n);
+ {
+ Node *parent = Swig_methodclass(n);
+ String *basetype = Getattr(parent, "classtype");
+ Wrapper *w = NewWrapper();
+ Printf(w->def, "SwigDirector_%s::SwigDirector_%s(PyObject *self) : Swig::Director(self) { \n", classname, classname);
+ Printf(w->def, " SWIG_DIRECTOR_RGTR((%s *)this, this); \n", basetype);
+ Append(w->def, "}\n");
+ Wrapper_print(w, f_directors);
+ DelWrapper(w);
+ }
+ Printf(f_directors_h, " SwigDirector_%s(PyObject *self);\n", classname);
+ Delete(classname);
+ return Language::classDirectorDefaultConstructor(n);
+ }
+
+
+ /* ------------------------------------------------------------
+ * classDirectorInit()
+ * ------------------------------------------------------------ */
+
+ int classDirectorInit(Node *n) {
+ String *declaration = Swig_director_declaration(n);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "%s\n", declaration);
+ Printf(f_directors_h, "public:\n");
+ Delete(declaration);
+ return Language::classDirectorInit(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorEnd()
+ * ------------------------------------------------------------ */
+
+ int classDirectorEnd(Node *n) {
+ String *classname = Swig_class_name(n);
+
+ if (dirprot_mode()) {
+ /*
+ This implementation uses a std::map<std::string,int>.
+
+ It should be possible to rewrite it using a more elegant way,
+ like copying the Java approach for the 'override' array.
+
+ But for now, this seems to be the least intrusive way.
+ */
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "/* Internal director utilities */\n");
+ Printf(f_directors_h, "public:\n");
+ Printf(f_directors_h, " bool swig_get_inner(const char *swig_protected_method_name) const {\n");
+ Printf(f_directors_h, " std::map<std::string, bool>::const_iterator iv = swig_inner.find(swig_protected_method_name);\n");
+ Printf(f_directors_h, " return (iv != swig_inner.end() ? iv->second : false);\n");
+ Printf(f_directors_h, " }\n");
+
+ Printf(f_directors_h, " void swig_set_inner(const char *swig_protected_method_name, bool swig_val) const {\n");
+ Printf(f_directors_h, " swig_inner[swig_protected_method_name] = swig_val;\n");
+ Printf(f_directors_h, " }\n");
+ Printf(f_directors_h, "private:\n");
+ Printf(f_directors_h, " mutable std::map<std::string, bool> swig_inner;\n");
+
+ }
+ if (director_method_index) {
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "#if defined(SWIG_PYTHON_DIRECTOR_VTABLE)\n");
+ Printf(f_directors_h, "/* VTable implementation */\n");
+ Printf(f_directors_h, " PyObject *swig_get_method(size_t method_index, const char *method_name) const {\n");
+ Printf(f_directors_h, " PyObject *method = vtable[method_index];\n");
+ Printf(f_directors_h, " if (!method) {\n");
+ Printf(f_directors_h, " swig::SwigVar_PyObject name = SWIG_Python_str_FromChar(method_name);\n");
+ Printf(f_directors_h, " method = PyObject_GetAttr(swig_get_self(), name);\n");
+ Printf(f_directors_h, " if (!method) {\n");
+ Printf(f_directors_h, " std::string msg = \"Method in class %s doesn't exist, undefined \";\n", classname);
+ Printf(f_directors_h, " msg += method_name;\n");
+ Printf(f_directors_h, " Swig::DirectorMethodException::raise(msg.c_str());\n");
+ Printf(f_directors_h, " }\n");
+ Printf(f_directors_h, " vtable[method_index] = method;\n");
+ Printf(f_directors_h, " }\n");
+ Printf(f_directors_h, " return method;\n");
+ Printf(f_directors_h, " }\n");
+ Printf(f_directors_h, "private:\n");
+ Printf(f_directors_h, " mutable swig::SwigVar_PyObject vtable[%d];\n", director_method_index);
+ Printf(f_directors_h, "#endif\n\n");
+ }
+
+ Printf(f_directors_h, "};\n\n");
+ return Language::classDirectorEnd(n);
+ }
+
+
+ /* ------------------------------------------------------------
+ * classDirectorDisown()
+ * ------------------------------------------------------------ */
+
+ int classDirectorDisown(Node *n) {
+ int result;
+ int oldshadow = shadow;
+ /* disable shadowing */
+ if (shadow)
+ shadow = shadow | PYSHADOW_MEMBER;
+ result = Language::classDirectorDisown(n);
+ shadow = oldshadow;
+ if (shadow) {
+ if (builtin) {
+ String *rname = SwigType_namestr(real_classname);
+ Printf(builtin_methods, " { \"__disown__\", Swig::Director::swig_pyobj_disown< %s >, METH_NOARGS, \"\" },\n", rname);
+ Delete(rname);
+ } else {
+ String *symname = Getattr(n, "sym:name");
+ String *mrename = Swig_name_disown(NSPACE_TODO, symname); //Getattr(n, "name"));
+ Printv(f_shadow, tab4, "def __disown__(self):\n", NIL);
+#ifdef USE_THISOWN
+ Printv(f_shadow, tab8, "self.thisown = 0\n", NIL);
+#else
+ Printv(f_shadow, tab8, "self.this.disown()\n", NIL);
+#endif
+ Printv(f_shadow, tab8, module, ".", mrename, "(self)\n", NIL);
+ Printv(f_shadow, tab8, "return weakref.proxy(self)\n", NIL);
+ Delete(mrename);
+ }
+ }
+ return result;
+ }
+
+ /* ----------------------------------------------------------------------------
+ * END of C++ Director Class modifications
+ * ------------------------------------------------------------------------- */
+
+
+ /* ------------------------------------------------------------
+ * classDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int classDeclaration(Node *n) {
+ if (shadow && !Getattr(n, "feature:onlychildren")) {
+ Node *mod = Getattr(n, "module");
+ if (mod) {
+ String *modname = Getattr(mod, "name");
+ Node *options = Getattr(mod, "options");
+ String *pkg = options ? Getattr(options, "package") : 0;
+ String *sym = Getattr(n, "sym:name");
+ String *importname = import_name_string(package, mainmodule, pkg, modname, sym);
+ Setattr(n, "python:proxy", importname);
+ Delete(importname);
+ }
+ }
+ int result = Language::classDeclaration(n);
+ return result;
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ * ------------------------------------------------------------ */
+
+ String *add_explicit_scope(String *s) {
+ if (!Strstr(s, "::")) {
+ String *ss = NewStringf("::%s", s);
+ Delete(s);
+ s = ss;
+ }
+ return s;
+ }
+
+ void builtin_pre_decl(Node *n) {
+ String *name = Getattr(n, "name");
+ String *rname = add_explicit_scope(SwigType_namestr(name));
+ String *mname = SwigType_manglestr(rname);
+
+ Printf(f_init, "\n/* type '%s' */\n", rname);
+ Printf(f_init, " builtin_pytype = (PyTypeObject *)&SwigPyBuiltin_%s_type;\n", mname);
+ Printf(f_init, " builtin_pytype->tp_dict = d = PyDict_New();\n");
+
+ Delete(rname);
+ Delete(mname);
+ }
+
+ void builtin_post_decl(File *f, Node *n) {
+ String *name = Getattr(n, "name");
+ String *pname = Copy(name);
+ SwigType_add_pointer(pname);
+ String *symname = Getattr(n, "sym:name");
+ String *rname = add_explicit_scope(SwigType_namestr(name));
+ String *mname = SwigType_manglestr(rname);
+ String *pmname = SwigType_manglestr(pname);
+ String *templ = NewStringf("SwigPyBuiltin_%s", mname);
+ int funpack = fastunpack;
+ static String *tp_new = NewString("PyType_GenericNew");
+
+ Printv(f_init, " SwigPyBuiltin_SetMetaType(builtin_pytype, metatype);\n", NIL);
+
+ // We can’t statically initialize a structure member with a function defined in another C module
+ // So this is done in the initialization function instead, see https://docs.python.org/2/extending/newtypes.html
+ Printf(f_init, " builtin_pytype->tp_new = %s;\n", getSlot(n, "feature:python:tp_new", tp_new));
+
+ Printv(f_init, " builtin_base_count = 0;\n", NIL);
+ List *baselist = Getattr(n, "bases");
+ if (baselist) {
+ int base_count = 0;
+ for (Iterator b = First(baselist); b.item; b = Next(b)) {
+ String *bname = Getattr(b.item, "name");
+ if (!bname || GetFlag(b.item, "feature:ignore"))
+ continue;
+ base_count++;
+ String *base_name = Copy(bname);
+ SwigType_add_pointer(base_name);
+ String *base_mname = SwigType_manglestr(base_name);
+ Printf(f_init, " builtin_basetype = SWIG_MangledTypeQuery(\"%s\");\n", base_mname);
+ Printv(f_init, " if (builtin_basetype && builtin_basetype->clientdata && ((SwigPyClientData *) builtin_basetype->clientdata)->pytype) {\n", NIL);
+ Printv(f_init, " builtin_bases[builtin_base_count++] = ((SwigPyClientData *) builtin_basetype->clientdata)->pytype;\n", NIL);
+ Printv(f_init, " } else {\n", NIL);
+ Printf(f_init, " PyErr_SetString(PyExc_TypeError, \"Could not create type '%s' as base '%s' has not been initialized.\\n\");\n", symname, bname);
+ Printv(f_init, "#if PY_VERSION_HEX >= 0x03000000\n", NIL);
+ Printv(f_init, " return NULL;\n", NIL);
+ Printv(f_init, "#else\n", NIL);
+ Printv(f_init, " return;\n", NIL);
+ Printv(f_init, "#endif\n", NIL);
+ Printv(f_init, " }\n", NIL);
+ Delete(base_name);
+ Delete(base_mname);
+ }
+ if (base_count > max_bases)
+ max_bases = base_count;
+ }
+ Printv(f_init, " builtin_bases[builtin_base_count] = NULL;\n", NIL);
+ Printv(f_init, " SwigPyBuiltin_InitBases(builtin_pytype, builtin_bases);\n", NIL);
+ builtin_bases_needed = 1;
+
+ // Check for non-public destructor, in which case tp_dealloc will issue
+ // a warning and allow the memory to leak. Any class that doesn't explicitly
+ // have a private/protected destructor has an implicit public destructor.
+ static String *tp_dealloc_bad = NewString("SwigPyBuiltin_BadDealloc");
+
+ String *getset_name = NewStringf("%s_getset", templ);
+ String *methods_name = NewStringf("%s_methods", templ);
+ String *getset_def = NewString("");
+ Printf(getset_def, "SWIGINTERN PyGetSetDef %s[] = {\n", getset_name);
+
+ // All objects have 'this' and 'thisown' attributes
+ Printv(f_init, "PyDict_SetItemString(d, \"this\", this_descr);\n", NIL);
+ Printv(f_init, "PyDict_SetItemString(d, \"thisown\", thisown_descr);\n", NIL);
+
+ // Now, the rest of the attributes
+ for (Iterator member_iter = First(builtin_getset); member_iter.item; member_iter = Next(member_iter)) {
+ String *memname = member_iter.key;
+ Hash *mgetset = member_iter.item;
+ String *getter = Getattr(mgetset, "getter");
+ String *setter = Getattr(mgetset, "setter");
+ const char *getter_closure = getter ? funpack ? "SwigPyBuiltin_FunpackGetterClosure" : "SwigPyBuiltin_GetterClosure" : "0";
+ const char *setter_closure = setter ? funpack ? "SwigPyBuiltin_FunpackSetterClosure" : "SwigPyBuiltin_SetterClosure" : "0";
+ String *gspair = NewStringf("%s_%s_getset", symname, memname);
+ Printf(f, "static SwigPyGetSet %s = { %s, %s };\n", gspair, getter ? getter : "0", setter ? setter : "0");
+ String *doc = Getattr(mgetset, "doc");
+ if (!doc)
+ doc = NewStringf("%s.%s", name, memname);
+ String *entry = NewStringf("{ (char *)\"%s\", %s, %s, (char *)\"%s\", &%s }", memname, getter_closure, setter_closure, doc, gspair);
+ if (GetFlag(mgetset, "static")) {
+ Printf(f, "static PyGetSetDef %s_def = %s;\n", gspair, entry);
+ Printf(f_init, "static_getset = SwigPyStaticVar_new_getset(metatype, &%s_def);\n", gspair);
+ Printf(f_init, "PyDict_SetItemString(d, static_getset->d_getset->name, (PyObject *) static_getset);\n", memname);
+ Printf(f_init, "Py_DECREF(static_getset);\n");
+ } else {
+ Printf(getset_def, " %s,\n", entry);
+ }
+ Delete(gspair);
+ Delete(entry);
+ }
+ Printv(f, getset_def, " { NULL, NULL, NULL, NULL, NULL } /* Sentinel */\n", "};\n\n", NIL);
+
+ // Rich compare function
+ Hash *richcompare = Getattr(n, "python:richcompare");
+ String *richcompare_func = NewStringf("%s_richcompare", templ);
+ assert(richcompare);
+ Printf(f, "SWIGINTERN PyObject *\n");
+ Printf(f, "%s(PyObject *self, PyObject *other, int op) {\n", richcompare_func);
+ Printf(f, " PyObject *result = NULL;\n");
+ if (!funpack) {
+ Printf(f, " PyObject *tuple = PyTuple_New(1);\n");
+ Printf(f, " assert(tuple);\n");
+ Printf(f, " PyTuple_SET_ITEM(tuple, 0, other);\n");
+ Printf(f, " Py_XINCREF(other);\n");
+ }
+ Iterator rich_iter = First(richcompare);
+ if (rich_iter.item) {
+ Printf(f, " switch (op) {\n");
+ for (; rich_iter.item; rich_iter = Next(rich_iter))
+ Printf(f, " case %s : result = %s(self, %s); break;\n", rich_iter.key, rich_iter.item, funpack ? "other" : "tuple");
+ Printv(f, " default : break;\n", NIL);
+ Printf(f, " }\n");
+ }
+ Printv(f, " if (!result) {\n", NIL);
+ Printv(f, " if (SwigPyObject_Check(self) && SwigPyObject_Check(other)) {\n", NIL);
+ Printv(f, " result = SwigPyObject_richcompare((SwigPyObject *)self, (SwigPyObject *)other, op);\n", NIL);
+ Printv(f, " } else {\n", NIL);
+ Printv(f, " result = Py_NotImplemented;\n", NIL);
+ Printv(f, " Py_INCREF(result);\n", NIL);
+ Printv(f, " }\n", NIL);
+ Printv(f, " }\n", NIL);
+ if (!funpack)
+ Printf(f, " Py_DECREF(tuple);\n");
+ Printf(f, " return result;\n");
+ Printf(f, "}\n\n");
+
+ // Methods
+ Printf(f, "SWIGINTERN PyMethodDef %s_methods[] = {\n", templ);
+ Dump(builtin_methods, f);
+ Printf(f, " { NULL, NULL, 0, NULL } /* Sentinel */\n};\n\n");
+
+ // No instance dict for nondynamic objects
+ if (GetFlag(n, "feature:python:nondynamic"))
+ Setattr(n, "feature:python:tp_setattro", "SWIG_Python_NonDynamicSetAttr");
+
+ Node *mod = Getattr(n, "module");
+ String *modname = mod ? Getattr(mod, "name") : 0;
+ String *quoted_symname;
+ if (package) {
+ if (modname)
+ quoted_symname = NewStringf("\"%s.%s.%s\"", package, modname, symname);
+ else
+ quoted_symname = NewStringf("\"%s.%s\"", package, symname);
+ } else {
+ if (modname)
+ quoted_symname = NewStringf("\"%s.%s\"", modname, symname);
+ else
+ quoted_symname = NewStringf("\"%s\"", symname);
+ }
+ String *quoted_tp_doc_str = NewStringf("\"%s\"", getSlot(n, "feature:python:tp_doc"));
+ String *tp_init = NewString(builtin_tp_init ? Char(builtin_tp_init) : Swig_directorclass(n) ? "0" : "SwigPyBuiltin_BadInit");
+ String *tp_flags = NewString("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES");
+ String *tp_flags_py3 = NewString("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE");
+
+ static String *tp_basicsize = NewStringf("sizeof(SwigPyObject)");
+ static String *tp_dictoffset_default = NewString("offsetof(SwigPyObject, dict)");
+ static String *tp_hash = NewString("SwigPyObject_hash");
+ String *tp_as_number = NewStringf("&%s_type.as_number", templ);
+ String *tp_as_sequence = NewStringf("&%s_type.as_sequence", templ);
+ String *tp_as_mapping = NewStringf("&%s_type.as_mapping", templ);
+ String *tp_as_buffer = NewStringf("&%s_type.as_buffer", templ);
+
+ Printf(f, "static PyHeapTypeObject %s_type = {\n", templ);
+
+ // PyTypeObject ht_type
+ Printf(f, " {\n");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL);
+ Printv(f, " PyVarObject_HEAD_INIT(NULL, 0)\n", NIL);
+ Printv(f, "#else\n", NIL);
+ Printf(f, " PyObject_HEAD_INIT(NULL)\n");
+ printSlot(f, getSlot(), "ob_size");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, quoted_symname, "tp_name");
+ printSlot(f, getSlot(n, "feature:python:tp_basicsize", tp_basicsize), "tp_basicsize");
+ printSlot(f, getSlot(n, "feature:python:tp_itemsize"), "tp_itemsize");
+ printSlot(f, getSlot(n, "feature:python:tp_dealloc", tp_dealloc_bad), "tp_dealloc", "destructor");
+ printSlot(f, getSlot(n, "feature:python:tp_print"), "tp_print", "printfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_getattr"), "tp_getattr", "getattrfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_setattr"), "tp_setattr", "setattrfunc");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_compare"), "tp_compare");
+ Printv(f, "#else\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_compare"), "tp_compare", "cmpfunc");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_repr"), "tp_repr", "reprfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_as_number", tp_as_number), "tp_as_number");
+ printSlot(f, getSlot(n, "feature:python:tp_as_sequence", tp_as_sequence), "tp_as_sequence");
+ printSlot(f, getSlot(n, "feature:python:tp_as_mapping", tp_as_mapping), "tp_as_mapping");
+ printSlot(f, getSlot(n, "feature:python:tp_hash", tp_hash), "tp_hash", "hashfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_call"), "tp_call", "ternaryfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_str"), "tp_str", "reprfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_getattro"), "tp_getattro", "getattrofunc");
+ printSlot(f, getSlot(n, "feature:python:tp_setattro"), "tp_setattro", "setattrofunc");
+ printSlot(f, getSlot(n, "feature:python:tp_as_buffer", tp_as_buffer), "tp_as_buffer");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_flags", tp_flags_py3), "tp_flags");
+ Printv(f, "#else\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_flags", tp_flags), "tp_flags");
+ Printv(f, "#endif\n", NIL);
+ if (have_docstring(n)) {
+ String *ds = cdocstring(n, AUTODOC_CLASS);
+ String *tp_doc = NewString("");
+ Printf(tp_doc, "\"%s\"", ds);
+ Delete(ds);
+ printSlot(f, tp_doc, "tp_doc");
+ Delete(tp_doc);
+ } else {
+ printSlot(f, quoted_tp_doc_str, "tp_doc");
+ }
+ printSlot(f, getSlot(n, "feature:python:tp_traverse"), "tp_traverse", "traverseproc");
+ printSlot(f, getSlot(n, "feature:python:tp_clear"), "tp_clear", "inquiry");
+ printSlot(f, getSlot(n, "feature:python:tp_richcompare", richcompare_func), "tp_richcompare", "richcmpfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_weaklistoffset"), "tp_weaklistoffset");
+ printSlot(f, getSlot(n, "feature:python:tp_iter"), "tp_iter", "getiterfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_iternext"), "tp_iternext", "iternextfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_methods", methods_name), "tp_methods");
+ printSlot(f, getSlot(n, "feature:python:tp_members"), "tp_members");
+ printSlot(f, getSlot(n, "feature:python:tp_getset", getset_name), "tp_getset");
+ printSlot(f, getSlot(n, "feature:python:tp_base"), "tp_base");
+ printSlot(f, getSlot(n, "feature:python:tp_dict"), "tp_dict");
+ printSlot(f, getSlot(n, "feature:python:tp_descr_get"), "tp_descr_get", "descrgetfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_descr_set"), "tp_descr_set", "descrsetfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_dictoffset", tp_dictoffset_default), "tp_dictoffset", "Py_ssize_t");
+ printSlot(f, getSlot(n, "feature:python:tp_init", tp_init), "tp_init", "initproc");
+ printSlot(f, getSlot(n, "feature:python:tp_alloc"), "tp_alloc", "allocfunc");
+ printSlot(f, getSlot(), "tp_new", "newfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_free"), "tp_free", "freefunc");
+ printSlot(f, getSlot(n, "feature:python:tp_is_gc"), "tp_is_gc", "inquiry");
+ printSlot(f, getSlot(n, "feature:python:tp_bases"), "tp_bases", "PyObject *");
+ printSlot(f, getSlot(n, "feature:python:tp_mro"), "tp_mro", "PyObject *");
+ printSlot(f, getSlot(n, "feature:python:tp_cache"), "tp_cache", "PyObject *");
+ printSlot(f, getSlot(n, "feature:python:tp_subclasses"), "tp_subclasses", "PyObject *");
+ printSlot(f, getSlot(n, "feature:python:tp_weaklist"), "tp_weaklist", "PyObject *");
+ printSlot(f, getSlot(n, "feature:python:tp_del"), "tp_del", "destructor");
+ printSlot(f, getSlot(n, "feature:python:tp_version_tag"), "tp_version_tag", "int");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03040000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_finalize"), "tp_finalize", "destructor");
+ Printv(f, "#endif\n", NIL);
+ Printv(f, "#if PY_VERSION_HEX >= 0x03080000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_vectorcall"), "tp_vectorcall", "vectorcallfunc");
+ Printv(f, "#endif\n", NIL);
+ Printv(f, "#if (PY_VERSION_HEX >= 0x03080000) && (PY_VERSION_HEX < 0x03090000)\n", NIL);
+ printSlot(f, getSlot(), "tp_print");
+ Printv(f, "#endif\n", NIL);
+
+ Printv(f, "#ifdef COUNT_ALLOCS\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_allocs"), "tp_allocs", "Py_ssize_t");
+ printSlot(f, getSlot(n, "feature:python:tp_frees"), "tp_frees", "Py_ssize_t");
+ printSlot(f, getSlot(n, "feature:python:tp_maxalloc"), "tp_maxalloc", "Py_ssize_t");
+ printSlot(f, getSlot(n, "feature:python:tp_prev"), "tp_prev");
+ printSlot(f, getSlot(n, "feature:python:tp_next"), "tp_next");
+ Printv(f, "#endif\n", NIL);
+ Printf(f, " },\n");
+
+ // PyAsyncMethods as_async
+ Printv(f, "#if PY_VERSION_HEX >= 0x03050000\n", NIL);
+ Printf(f, " {\n");
+ printSlot(f, getSlot(n, "feature:python:am_await"), "am_await", "unaryfunc");
+ printSlot(f, getSlot(n, "feature:python:am_aiter"), "am_aiter", "unaryfunc");
+ printSlot(f, getSlot(n, "feature:python:am_anext"), "am_anext", "unaryfunc");
+ Printf(f, " },\n");
+ Printv(f, "#endif\n", NIL);
+
+ // PyNumberMethods as_number
+ Printf(f, " {\n");
+ printSlot(f, getSlot(n, "feature:python:nb_add"), "nb_add", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_subtract"), "nb_subtract", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_multiply"), "nb_multiply", "binaryfunc");
+ Printv(f, "#if PY_VERSION_HEX < 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_divide"), "nb_divide", "binaryfunc");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_remainder"), "nb_remainder", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_divmod"), "nb_divmod", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_power"), "nb_power", "ternaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_negative"), "nb_negative", "unaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_positive"), "nb_positive", "unaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_absolute"), "nb_absolute", "unaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_nonzero"), "nb_nonzero", "inquiry");
+ printSlot(f, getSlot(n, "feature:python:nb_invert"), "nb_invert", "unaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_lshift"), "nb_lshift", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_rshift"), "nb_rshift", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_and"), "nb_and", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_xor"), "nb_xor", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_or"), "nb_or", "binaryfunc");
+ Printv(f, "#if PY_VERSION_HEX < 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_coerce"), "nb_coerce", "coercion");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_int"), "nb_int", "unaryfunc");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_reserved"), "nb_reserved", "void *");
+ Printv(f, "#else\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_long"), "nb_long", "unaryfunc");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_float"), "nb_float", "unaryfunc");
+ Printv(f, "#if PY_VERSION_HEX < 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_oct"), "nb_oct", "unaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_hex"), "nb_hex", "unaryfunc");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_add"), "nb_inplace_add", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_subtract"), "nb_inplace_subtract", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_multiply"), "nb_inplace_multiply", "binaryfunc");
+ Printv(f, "#if PY_VERSION_HEX < 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_divide"), "nb_inplace_divide", "binaryfunc");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_remainder"), "nb_inplace_remainder", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_power"), "nb_inplace_power", "ternaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_lshift"), "nb_inplace_lshift", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_rshift"), "nb_inplace_rshift", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_and"), "nb_inplace_and", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_xor"), "nb_inplace_xor", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_or"), "nb_inplace_or", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_floor_divide"), "nb_floor_divide", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_divide"), "nb_true_divide", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_floor_divide"), "nb_inplace_floor_divide", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_divide"), "nb_inplace_true_divide", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_index"), "nb_index", "unaryfunc");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03050000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_matrix_multiply"), "nb_matrix_multiply", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_matrix_multiply"), "nb_inplace_matrix_multiply", "binaryfunc");
+ Printv(f, "#endif\n", NIL);
+ Printf(f, " },\n");
+
+ // PyMappingMethods as_mapping;
+ Printf(f, " {\n");
+ printSlot(f, getSlot(n, "feature:python:mp_length"), "mp_length", "lenfunc");
+ printSlot(f, getSlot(n, "feature:python:mp_subscript"), "mp_subscript", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:mp_ass_subscript"), "mp_ass_subscript", "objobjargproc");
+ Printf(f, " },\n");
+
+ // PySequenceMethods as_sequence;
+ Printf(f, " {\n");
+ printSlot(f, getSlot(n, "feature:python:sq_length"), "sq_length", "lenfunc");
+ printSlot(f, getSlot(n, "feature:python:sq_concat"), "sq_concat", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:sq_repeat"), "sq_repeat", "ssizeargfunc");
+ printSlot(f, getSlot(n, "feature:python:sq_item"), "sq_item", "ssizeargfunc");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:was_sq_slice"), "was_sq_slice", "void *");
+ Printv(f, "#else\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:sq_slice"), "sq_slice", "ssizessizeargfunc");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:sq_ass_item"), "sq_ass_item", "ssizeobjargproc");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:was_sq_ass_slice"), "was_sq_ass_slice", "void *");
+ Printv(f, "#else\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:sq_ass_slice"), "sq_ass_slice", "ssizessizeobjargproc");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:sq_contains"), "sq_contains", "objobjproc");
+ printSlot(f, getSlot(n, "feature:python:sq_inplace_concat"), "sq_inplace_concat", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:sq_inplace_repeat"), "sq_inplace_repeat", "ssizeargfunc");
+ Printf(f, " },\n");
+
+ // PyBufferProcs as_buffer;
+ Printf(f, " {\n");
+ Printv(f, "#if PY_VERSION_HEX < 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:bf_getreadbuffer"), "bf_getreadbuffer", "readbufferproc");
+ printSlot(f, getSlot(n, "feature:python:bf_getwritebuffer"), "bf_getwritebuffer", "writebufferproc");
+ printSlot(f, getSlot(n, "feature:python:bf_getsegcount"), "bf_getsegcount", "segcountproc");
+ printSlot(f, getSlot(n, "feature:python:bf_getcharbuffer"), "bf_getcharbuffer", "charbufferproc");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:bf_getbuffer"), "bf_getbuffer", "getbufferproc");
+ printSlot(f, getSlot(n, "feature:python:bf_releasebuffer"), "bf_releasebuffer", "releasebufferproc");
+ Printf(f, " },\n");
+
+ // PyObject *ht_name, *ht_slots, *ht_qualname;
+ printSlot(f, getSlot(n, "feature:python:ht_name"), "ht_name", "PyObject *");
+ printSlot(f, getSlot(n, "feature:python:ht_slots"), "ht_slots", "PyObject *");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03030000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:ht_qualname"), "ht_qualname", "PyObject *");
+
+ // struct _dictkeysobject *ht_cached_keys;
+ printSlot(f, getSlot(n, "feature:python:ht_cached_keys"), "ht_cached_keys");
+ Printv(f, "#endif\n", NIL);
+ Printf(f, "};\n\n");
+
+ String *clientdata = NewString("");
+ Printf(clientdata, "&%s_clientdata", templ);
+ SwigType_remember_mangleddata(pmname, clientdata);
+
+ SwigType *smart = Swig_cparse_smartptr(n);
+ if (smart) {
+ SwigType_add_pointer(smart);
+ String *smart_pmname = SwigType_manglestr(smart);
+ SwigType_remember_mangleddata(smart_pmname, clientdata);
+ Delete(smart_pmname);
+ }
+
+ String *clientdata_klass = NewString("0");
+ if (GetFlag(n, "feature:implicitconv")) {
+ Clear(clientdata_klass);
+ Printf(clientdata_klass, "(PyObject *) &%s_type", templ);
+ }
+
+ Printf(f, "SWIGINTERN SwigPyClientData %s_clientdata = {%s, 0, 0, 0, 0, 0, (PyTypeObject *)&%s_type};\n\n", templ, clientdata_klass, templ);
+
+ Printv(f_init, " if (PyType_Ready(builtin_pytype) < 0) {\n", NIL);
+ Printf(f_init, " PyErr_SetString(PyExc_TypeError, \"Could not create type '%s'.\");\n", symname);
+ Printv(f_init, "#if PY_VERSION_HEX >= 0x03000000\n", NIL);
+ Printv(f_init, " return NULL;\n", NIL);
+ Printv(f_init, "#else\n", NIL);
+ Printv(f_init, " return;\n", NIL);
+ Printv(f_init, "#endif\n", NIL);
+ Printv(f_init, " }\n", NIL);
+ Printv(f_init, " Py_INCREF(builtin_pytype);\n", NIL);
+ Printf(f_init, " PyModule_AddObject(m, \"%s\", (PyObject *)builtin_pytype);\n", symname);
+ Printf(f_init, " SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", symname);
+ Printv(f_init, " d = md;\n", NIL);
+
+ Delete(clientdata);
+ Delete(smart);
+ Delete(rname);
+ Delete(pname);
+ Delete(mname);
+ Delete(pmname);
+ Delete(templ);
+ Delete(tp_flags);
+ Delete(tp_flags_py3);
+ Delete(tp_as_buffer);
+ Delete(tp_as_mapping);
+ Delete(tp_as_sequence);
+ Delete(tp_as_number);
+ Delete(quoted_symname);
+ Delete(quoted_tp_doc_str);
+ Delete(tp_init);
+ Delete(clientdata_klass);
+ Delete(richcompare_func);
+ Delete(getset_name);
+ Delete(methods_name);
+ }
+
+ virtual int classHandler(Node *n) {
+ File *f_shadow_file = f_shadow;
+ Node *base_node = NULL;
+
+ if (shadow) {
+
+ /* Create new strings for building up a wrapper function */
+ have_constructor = 0;
+ have_repr = 0;
+
+ class_name = Getattr(n, "sym:name");
+ real_classname = Getattr(n, "name");
+
+ if (!addSymbol(class_name, n))
+ return SWIG_ERROR;
+
+ if (builtin) {
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist) > 0) {
+ Iterator b = First(baselist);
+ base_node = b.item;
+ }
+ }
+
+ shadow_indent = (String *) tab4;
+
+ /* Handle inheritance */
+ String *base_class = NewString("");
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator b;
+ b = First(baselist);
+ while (b.item) {
+ String *bname = Getattr(b.item, "python:proxy");
+ bool ignore = GetFlag(b.item, "feature:ignore") ? true : false;
+ if (!bname || ignore) {
+ if (!bname && !ignore) {
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(n), Getline(n),
+ "Base class '%s' ignored - unknown module name for base. Either import the appropriate module interface file or specify the name of the module in the %%import directive.\n",
+ SwigType_namestr(Getattr(b.item, "name")));
+ }
+ b = Next(b);
+ continue;
+ }
+ Printv(base_class, bname, NIL);
+ b = Next(b);
+ if (b.item) {
+ Printv(base_class, ", ", NIL);
+ }
+ }
+ }
+
+ if (builtin) {
+ Hash *base_richcompare = NULL;
+ Hash *richcompare = NULL;
+ if (base_node)
+ base_richcompare = Getattr(base_node, "python:richcompare");
+ if (base_richcompare)
+ richcompare = Copy(base_richcompare);
+ else
+ richcompare = NewHash();
+ Setattr(n, "python:richcompare", richcompare);
+ }
+
+ /* dealing with abstract base class */
+ String *abcs = Getattr(n, "feature:python:abc");
+ if (py3 && abcs) {
+ if (Len(base_class)) {
+ Printv(base_class, ", ", NIL);
+ }
+ Printv(base_class, abcs, NIL);
+ }
+
+ if (builtin) {
+ if (have_docstring(n)) {
+ String *ds = cdocstring(n, AUTODOC_CLASS);
+ Setattr(n, "feature:python:tp_doc", ds);
+ Delete(ds);
+ } else {
+ String *name = Getattr(n, "name");
+ String *rname = add_explicit_scope(SwigType_namestr(name));
+ Setattr(n, "feature:python:tp_doc", rname);
+ Delete(rname);
+ }
+ } else {
+ if (!py3) {
+ if (GetFlag(n, "feature:python:nondynamic"))
+ Printv(f_shadow, "@_swig_add_metaclass(_SwigNonDynamicMeta)\n", NIL);
+ }
+ Printv(f_shadow, "class ", class_name, NIL);
+
+ if (Len(base_class)) {
+ Printf(f_shadow, "(%s)", base_class);
+ } else {
+ if (GetFlag(n, "feature:exceptionclass")) {
+ Printf(f_shadow, "(Exception)");
+ } else {
+ Printf(f_shadow, "(object");
+ Printf(f_shadow, py3 && GetFlag(n, "feature:python:nondynamic") ? ", metaclass=_SwigNonDynamicMeta" : "", ")");
+ Printf(f_shadow, ")");
+ }
+ }
+
+ Printf(f_shadow, ":\n");
+
+ // write docstrings if requested
+ if (have_docstring(n)) {
+ String *str = docstring(n, AUTODOC_CLASS, tab4);
+ if (str && Len(str))
+ Printv(f_shadow, tab4, str, "\n\n", NIL);
+ }
+
+ Printv(f_shadow, tab4, "thisown = property(lambda x: x.this.own(), ", "lambda x, v: x.this.own(v), doc=\"The membership flag\")\n", NIL);
+ /* Add static attribute */
+ if (GetFlag(n, "feature:python:nondynamic")) {
+ Printv(f_shadow_file, tab4, "__setattr__ = _swig_setattr_nondynamic_instance_variable(object.__setattr__)\n", NIL);
+ }
+ }
+ }
+
+ /* Emit all of the members */
+
+ in_class = 1;
+ if (builtin)
+ builtin_pre_decl(n);
+
+ /* Override the shadow file so we can capture its methods */
+ f_shadow = NewString("");
+
+ // Set up type check for director class constructor
+ Clear(none_comparison);
+ if (builtin && Swig_directorclass(n)) {
+ String *p_real_classname = Copy(real_classname);
+ SwigType_add_pointer(p_real_classname);
+ String *mangle = SwigType_manglestr(p_real_classname);
+ String *descriptor = NewStringf("SWIGTYPE%s", mangle);
+ Printv(none_comparison, "self->ob_type != ((SwigPyClientData *)(", descriptor, ")->clientdata)->pytype", NIL);
+ Delete(descriptor);
+ Delete(mangle);
+ Delete(p_real_classname);
+ } else {
+ Printv(none_comparison, "$arg != Py_None", NIL);
+ }
+
+ Language::classHandler(n);
+
+ in_class = 0;
+
+ /* Complete the class */
+ if (shadow) {
+ /* Generate a class registration function */
+ // Replace storing a pointer to underlying class with a smart pointer (intended for use with non-intrusive smart pointers)
+ SwigType *smart = Swig_cparse_smartptr(n);
+ SwigType *ct = Copy(smart ? smart : real_classname);
+ SwigType_add_pointer(ct);
+ SwigType *realct = Copy(real_classname);
+ SwigType_add_pointer(realct);
+ SwigType_remember(realct);
+ if (builtin) {
+ Printv(f_wrappers, builtin_closures_code, NIL);
+ Delete(builtin_closures_code);
+ builtin_closures_code = NewString("");
+ Clear(builtin_closures);
+ } else {
+ Printv(f_wrappers, "SWIGINTERN PyObject *", class_name, "_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {\n", NIL);
+ Printv(f_wrappers, " PyObject *obj;\n", NIL);
+ Printv(f_wrappers, " if (!SWIG_Python_UnpackTuple(args, \"swigregister\", 1, 1, &obj)) return NULL;\n", NIL);
+
+ Printv(f_wrappers,
+ " SWIG_TypeNewClientData(SWIGTYPE", SwigType_manglestr(ct), ", SWIG_NewClientData(obj));\n", " return SWIG_Py_Void();\n", "}\n\n", NIL);
+ String *cname = NewStringf("%s_swigregister", class_name);
+ add_method(cname, cname, 0, 0, 1, 1, 1);
+ Delete(cname);
+ }
+ Delete(smart);
+ Delete(ct);
+ Delete(realct);
+ if (!have_constructor) {
+ if (!builtin)
+ Printv(f_shadow_file, "\n", tab4, "def __init__(self, *args, **kwargs):\n", tab8, "raise AttributeError(\"", "No constructor defined",
+ (Getattr(n, "abstracts") ? " - class is abstract" : ""), "\")\n", NIL);
+ } else if (!builtin) {
+
+ Printv(f_wrappers, "SWIGINTERN PyObject *", class_name, "_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {\n", NIL);
+ Printv(f_wrappers, " return SWIG_Python_InitShadowInstance(args);\n", "}\n\n", NIL);
+ String *cname = NewStringf("%s_swiginit", class_name);
+ add_method(cname, cname, 0);
+ Delete(cname);
+ }
+ if (!have_repr && !builtin) {
+ /* Supply a repr method for this class */
+ String *rname = SwigType_namestr(real_classname);
+ Printv(f_shadow_file, tab4, "__repr__ = _swig_repr\n", NIL);
+ Delete(rname);
+ }
+
+ if (builtin)
+ builtin_post_decl(f_builtins, n);
+
+ if (builtin_tp_init) {
+ Delete(builtin_tp_init);
+ builtin_tp_init = 0;
+ }
+
+ if (!builtin) {
+ /* Now emit methods */
+ Printv(f_shadow_file, f_shadow, NIL);
+ Printf(f_shadow_file, "\n");
+ Printf(f_shadow_file, "# Register %s in %s:\n", class_name, module);
+ Printf(f_shadow_file, "%s.%s_swigregister(%s)\n", module, class_name, class_name);
+ }
+
+ shadow_indent = 0;
+ Printf(f_shadow_file, "%s\n", f_shadow_stubs);
+ Clear(f_shadow_stubs);
+ }
+
+ if (builtin) {
+ Clear(class_members);
+ Clear(builtin_getset);
+ Clear(builtin_methods);
+ }
+
+ /* Restore shadow file back to original version */
+ Delete(f_shadow);
+ f_shadow = f_shadow_file;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * functionHandler() - Mainly overloaded for callback handling
+ * ------------------------------------------------------------ */
+
+ virtual int functionHandler(Node *n) {
+ String *pcb = GetFlagAttr(n, "feature:python:callback");
+ if (pcb) {
+ if (Strcmp(pcb, "1") == 0) {
+ SetFlagAttr(n, "feature:callback", "%s_cb_ptr");
+ } else {
+ SetFlagAttr(n, "feature:callback", pcb);
+ }
+ autodoc_l dlevel = autodoc_level(Getattr(n, "feature:autodoc"));
+ if (dlevel != NO_AUTODOC && dlevel > TYPES_AUTODOC) {
+ Setattr(n, "feature:autodoc", "1");
+ }
+ }
+ return Language::functionHandler(n);
+ }
+
+ /* ------------------------------------------------------------
+ * memberfunctionHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int memberfunctionHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ int oldshadow;
+
+ if (builtin)
+ Swig_save("builtin_memberfunc", n, "python:argcount", NIL);
+
+ /* Create the default member function */
+ oldshadow = shadow; /* Disable shadowing when wrapping member functions */
+ if (shadow)
+ shadow = shadow | PYSHADOW_MEMBER;
+ Language::memberfunctionHandler(n);
+ shadow = oldshadow;
+
+ if (builtin && in_class) {
+ // Can't use checkAttribute(n, "access", "public") because
+ // "access" attr isn't set on %extend methods
+ if (!checkAttribute(n, "access", "private") && strncmp(Char(symname), "operator ", 9) && !Getattr(class_members, symname)) {
+ String *fullname = Swig_name_member(NSPACE_TODO, class_name, symname);
+ String *wname = Swig_name_wrapper(fullname);
+ Setattr(class_members, symname, n);
+ int argcount = Getattr(n, "python:argcount") ? atoi(Char(Getattr(n, "python:argcount"))) : 2;
+ String *ds = have_docstring(n) ? cdocstring(n, AUTODOC_METHOD) : NewString("");
+ if (check_kwargs(n)) {
+ // Cast via void(*)(void) to suppress GCC -Wcast-function-type
+ // warning. Python should always call the function correctly, but
+ // the Python C API requires us to store it in function pointer of a
+ // different type.
+ Printf(builtin_methods, " { \"%s\", (PyCFunction)(void(*)(void))%s, METH_VARARGS|METH_KEYWORDS, \"%s\" },\n", symname, wname, ds);
+ } else if (argcount == 0) {
+ Printf(builtin_methods, " { \"%s\", %s, METH_NOARGS, \"%s\" },\n", symname, wname, ds);
+ } else if (argcount == 1) {
+ Printf(builtin_methods, " { \"%s\", %s, METH_O, \"%s\" },\n", symname, wname, ds);
+ } else {
+ Printf(builtin_methods, " { \"%s\", %s, METH_VARARGS, \"%s\" },\n", symname, wname, ds);
+ }
+ Delete(fullname);
+ Delete(wname);
+ Delete(ds);
+ }
+ }
+
+ if (builtin)
+ Swig_restore(n);
+
+ if (!Getattr(n, "sym:nextSibling")) {
+ if (shadow && !builtin) {
+ int fproxy = fastproxy;
+ String *fullname = Swig_name_member(NSPACE_TODO, class_name, symname);
+ if (Strcmp(symname, "__repr__") == 0) {
+ have_repr = 1;
+ }
+ if (Getattr(n, "feature:shadow")) {
+ String *pycode = indent_pythoncode(Getattr(n, "feature:shadow"), tab4, Getfile(n), Getline(n), "%feature(\"shadow\")");
+ String *pyaction = NewStringf("%s.%s", module, fullname);
+ Replaceall(pycode, "$action", pyaction);
+ Delete(pyaction);
+ Printv(f_shadow, pycode, "\n", NIL);
+ Delete(pycode);
+ fproxy = 0;
+ } else {
+ int allow_kwargs = (check_kwargs(n) && !Getattr(n, "sym:overloaded")) ? 1 : 0;
+ String *parms = make_pyParmList(n, true, false, allow_kwargs);
+ String *callParms = make_pyParmList(n, true, true, allow_kwargs);
+ if (!have_addtofunc(n)) {
+ if (!fastproxy || olddefs) {
+ Printv(f_shadow, "\n", tab4, "def ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
+ if (have_docstring(n))
+ Printv(f_shadow, tab8, docstring(n, AUTODOC_METHOD, tab8), "\n", NIL);
+ Printv(f_shadow, tab8, "return ", funcCall(fullname, callParms), "\n", NIL);
+ }
+ } else {
+ Printv(f_shadow, "\n", tab4, "def ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
+ if (have_docstring(n))
+ Printv(f_shadow, tab8, docstring(n, AUTODOC_METHOD, tab8), "\n", NIL);
+ if (have_pythonprepend(n)) {
+ fproxy = 0;
+ Printv(f_shadow, indent_pythoncode(pythonprepend(n), tab8, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL);
+ }
+ if (have_pythonappend(n)) {
+ fproxy = 0;
+ Printv(f_shadow, tab8, "val = ", funcCall(fullname, callParms), "\n", NIL);
+ Printv(f_shadow, indent_pythoncode(pythonappend(n), tab8, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL);
+ Printv(f_shadow, tab8, "return val\n\n", NIL);
+ } else {
+ Printv(f_shadow, tab8, "return ", funcCall(fullname, callParms), "\n\n", NIL);
+ }
+ }
+ }
+ if (fproxy) {
+ Printf(f_shadow, tab4);
+ Printf(f_shadow, "%s = _swig_new_instance_method(%s.%s)\n", symname, module, Swig_name_member(NSPACE_TODO, class_name, symname));
+ }
+ Delete(fullname);
+ }
+ }
+ return SWIG_OK;
+ }
+
+
+ /* ------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ if (builtin && in_class) {
+ Swig_save("builtin_memberconstantHandler", n, "pybuiltin:symname", NIL);
+ Setattr(n, "pybuiltin:symname", symname);
+ }
+ Language::staticmemberfunctionHandler(n);
+ if (builtin && in_class) {
+ Swig_restore(n);
+ }
+
+ if (builtin && in_class) {
+ if ((GetFlagAttr(n, "feature:extend") || checkAttribute(n, "access", "public"))
+ && !Getattr(class_members, symname)) {
+ String *fullname = Swig_name_member(NSPACE_TODO, class_name, symname);
+ String *wname = Swig_name_wrapper(fullname);
+ Setattr(class_members, symname, n);
+ int funpack = fastunpack && !Getattr(n, "sym:overloaded");
+ String *pyflags = NewString("METH_STATIC|");
+ int argcount = Getattr(n, "python:argcount") ? atoi(Char(Getattr(n, "python:argcount"))) : 2;
+ if (funpack && argcount == 0)
+ Append(pyflags, "METH_NOARGS");
+ else if (funpack && argcount == 1)
+ Append(pyflags, "METH_O");
+ else
+ Append(pyflags, "METH_VARARGS");
+ // Cast via void(*)(void) to suppress GCC -Wcast-function-type warning.
+ // Python should always call the function correctly, but the Python C
+ // API requires us to store it in function pointer of a different type.
+ if (have_docstring(n)) {
+ String *ds = cdocstring(n, AUTODOC_STATICFUNC);
+ Printf(builtin_methods, " { \"%s\", (PyCFunction)(void(*)(void))%s, %s, \"%s\" },\n", symname, wname, pyflags, ds);
+ Delete(ds);
+ } else {
+ Printf(builtin_methods, " { \"%s\", (PyCFunction)(void(*)(void))%s, %s, \"\" },\n", symname, wname, pyflags);
+ }
+ Delete(fullname);
+ Delete(wname);
+ Delete(pyflags);
+ }
+ return SWIG_OK;
+ }
+
+ if (Getattr(n, "sym:nextSibling")) {
+ return SWIG_OK;
+ }
+
+ if (shadow) {
+ String *staticfunc_name = NewString(fastproxy ? "_swig_new_static_method" : "staticmethod");
+ bool fast = (fastproxy && !have_addtofunc(n)) || Getattr(n, "feature:callback");
+ if (!fast || olddefs) {
+ int kw = (check_kwargs(n) && !Getattr(n, "sym:overloaded")) ? 1 : 0;
+ String *parms = make_pyParmList(n, false, false, kw);
+ String *callParms = make_pyParmList(n, false, true, kw);
+ Printv(f_shadow, "\n", tab4, "@staticmethod", NIL);
+ Printv(f_shadow, "\n", tab4, "def ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
+ if (have_docstring(n))
+ Printv(f_shadow, tab8, docstring(n, AUTODOC_STATICFUNC, tab8), "\n", NIL);
+ if (have_pythonprepend(n))
+ Printv(f_shadow, indent_pythoncode(pythonprepend(n), tab8, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL);
+ if (have_pythonappend(n)) {
+ Printv(f_shadow, tab8, "val = ", funcCall(Swig_name_member(NSPACE_TODO, class_name, symname), callParms), "\n", NIL);
+ Printv(f_shadow, indent_pythoncode(pythonappend(n), tab8, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL);
+ Printv(f_shadow, tab8, "return val\n", NIL);
+ } else {
+ Printv(f_shadow, tab8, "return ", funcCall(Swig_name_member(NSPACE_TODO, class_name, symname), callParms), "\n", NIL);
+ }
+ }
+
+ // Below may result in a 2nd definition of the method when -olddefs is used. The Python interpreter will use the second definition as it overwrites the first.
+ if (fast) {
+ Printv(f_shadow, tab4, symname, " = ", staticfunc_name, "(", module, ".", Swig_name_member(NSPACE_TODO, class_name, symname),
+ ")\n", NIL);
+ }
+ Delete(staticfunc_name);
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constructorDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int constructorHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ int oldshadow = shadow;
+ int use_director = Swig_directorclass(n);
+
+ /*
+ * If we're wrapping the constructor of a C++ director class, prepend a new parameter
+ * to receive the scripting language object (e.g. 'self')
+ *
+ */
+ Swig_save("python:constructorHandler", n, "parms", NIL);
+ if (use_director) {
+ Parm *parms = Getattr(n, "parms");
+ Parm *self;
+ String *name = NewString("self");
+ String *type = NewString("PyObject");
+ SwigType_add_pointer(type);
+ self = NewParm(type, name, n);
+ Delete(type);
+ Delete(name);
+ Setattr(self, "lname", "O");
+ if (parms)
+ set_nextSibling(self, parms);
+ Setattr(n, "parms", self);
+ Setattr(n, "wrap:self", "1");
+ Setattr(n, "hidden", "1");
+ Delete(self);
+ }
+
+ if (shadow)
+ shadow = shadow | PYSHADOW_MEMBER;
+ Language::constructorHandler(n);
+ shadow = oldshadow;
+
+ Delattr(n, "wrap:self");
+ Swig_restore(n);
+
+ if (!Getattr(n, "sym:nextSibling")) {
+ if (shadow) {
+ int allow_kwargs = (check_kwargs(n) && (!Getattr(n, "sym:overloaded"))) ? 1 : 0;
+ int handled_as_init = 0;
+ if (!have_constructor) {
+ String *nname = Getattr(n, "sym:name");
+ String *sname = Getattr(getCurrentClass(), "sym:name");
+ String *cname = Swig_name_construct(NSPACE_TODO, sname);
+ handled_as_init = (Strcmp(nname, sname) == 0) || (Strcmp(nname, cname) == 0);
+ Delete(cname);
+ }
+
+ String *subfunc = Swig_name_construct(NSPACE_TODO, symname);
+ if (!have_constructor && handled_as_init) {
+ if (!builtin) {
+ if (Getattr(n, "feature:shadow")) {
+ String *pycode = indent_pythoncode(Getattr(n, "feature:shadow"), tab4, Getfile(n), Getline(n), "%feature(\"shadow\")");
+ String *pyaction = NewStringf("%s.%s", module, subfunc);
+ Replaceall(pycode, "$action", pyaction);
+ Delete(pyaction);
+ Printv(f_shadow, pycode, "\n", NIL);
+ Delete(pycode);
+ } else {
+ String *pass_self = NewString("");
+ Node *parent = Swig_methodclass(n);
+ String *classname = Swig_class_name(parent);
+ String *rclassname = Swig_class_name(getCurrentClass());
+ assert(rclassname);
+
+ String *parms = make_pyParmList(n, true, false, allow_kwargs);
+ /* Pass 'self' only if using director */
+ String *callParms = make_pyParmList(n, false, true, allow_kwargs, true);
+
+ if (use_director) {
+ Insert(callParms, 0, "_self, ");
+ Printv(pass_self, tab8, NIL);
+ Printf(pass_self, "if self.__class__ == %s:\n", classname);
+ //Printv(pass_self, tab8, tab4, "args = (None,) + args\n", tab8, "else:\n", tab8, tab4, "args = (self,) + args\n", NIL);
+ Printv(pass_self, tab8, tab4, "_self = None\n", tab8, "else:\n", tab8, tab4, "_self = self\n", NIL);
+ }
+
+ Printv(f_shadow, "\n", tab4, "def __init__(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
+ if (have_docstring(n))
+ Printv(f_shadow, tab8, docstring(n, AUTODOC_CTOR, tab8), "\n", NIL);
+ if (have_pythonprepend(n))
+ Printv(f_shadow, indent_pythoncode(pythonprepend(n), tab8, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL);
+ Printv(f_shadow, pass_self, NIL);
+ Printv(f_shadow, tab8, module, ".", class_name, "_swiginit(self, ", funcCall(subfunc, callParms), ")\n", NIL);
+ if (have_pythonappend(n))
+ Printv(f_shadow, indent_pythoncode(pythonappend(n), tab8, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n\n", NIL);
+ Delete(pass_self);
+ }
+ have_constructor = 1;
+ }
+ } else {
+ /* Hmmm. We seem to be creating a different constructor. We're just going to create a
+ function for it. */
+ if (!builtin) {
+ if (Getattr(n, "feature:shadow")) {
+ String *pycode = indent_pythoncode(Getattr(n, "feature:shadow"), "", Getfile(n), Getline(n), "%feature(\"shadow\")");
+ String *pyaction = NewStringf("%s.%s", module, subfunc);
+ Replaceall(pycode, "$action", pyaction);
+ Delete(pyaction);
+ Printv(f_shadow_stubs, pycode, "\n", NIL);
+ Delete(pycode);
+ } else {
+ String *parms = make_pyParmList(n, false, false, allow_kwargs);
+ String *callParms = make_pyParmList(n, false, true, allow_kwargs);
+
+ Printv(f_shadow_stubs, "\ndef ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
+ if (have_docstring(n))
+ Printv(f_shadow_stubs, tab4, docstring(n, AUTODOC_CTOR, tab4), "\n", NIL);
+ if (have_pythonprepend(n))
+ Printv(f_shadow_stubs, indent_pythoncode(pythonprepend(n), tab4, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL);
+ Printv(f_shadow_stubs, tab4, "val = ", funcCall(subfunc, callParms), "\n", NIL);
+#ifdef USE_THISOWN
+ Printv(f_shadow_stubs, tab4, "val.thisown = 1\n", NIL);
+#endif
+ if (have_pythonappend(n))
+ Printv(f_shadow_stubs, indent_pythoncode(pythonappend(n), tab4, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL);
+ Printv(f_shadow_stubs, tab4, "return val\n", NIL);
+ }
+ } else {
+ Printf(f_shadow_stubs, "%s = %s\n", symname, subfunc);
+ }
+ }
+ Delete(subfunc);
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * destructorHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int destructorHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ int oldshadow = shadow;
+
+ if (builtin && in_class) {
+ Node *cls = Swig_methodclass(n);
+ // Use the destructor for the tp_dealloc slot unless a user overrides it with another method
+ if (!Getattr(cls, "feature:python:tp_dealloc")) {
+ Setattr(n, "feature:python:slot", "tp_dealloc");
+ Setattr(n, "feature:python:slot:functype", "destructor");
+ }
+ }
+
+ if (shadow)
+ shadow = shadow | PYSHADOW_MEMBER;
+ //Setattr(n,"emit:dealloc","1");
+ Language::destructorHandler(n);
+ shadow = oldshadow;
+
+ if (shadow) {
+ if (Getattr(n, "feature:shadow")) {
+ String *pycode = indent_pythoncode(Getattr(n, "feature:shadow"), tab4, Getfile(n), Getline(n), "%feature(\"shadow\")");
+ String *pyaction = NewStringf("%s.%s", module, Swig_name_destroy(NSPACE_TODO, symname));
+ Replaceall(pycode, "$action", pyaction);
+ Delete(pyaction);
+ Printv(f_shadow, pycode, "\n", NIL);
+ Delete(pycode);
+ } else {
+ Printv(f_shadow, tab4, "__swig_destroy__ = ", module, ".", Swig_name_destroy(NSPACE_TODO, symname), "\n", NIL);
+ if (!have_pythonprepend(n) && !have_pythonappend(n)) {
+ return SWIG_OK;
+ }
+ Printv(f_shadow, tab4, "def __del__(self):\n", NIL);
+ if (have_docstring(n))
+ Printv(f_shadow, tab8, docstring(n, AUTODOC_DTOR, tab8), "\n", NIL);
+ if (have_pythonprepend(n))
+ Printv(f_shadow, indent_pythoncode(pythonprepend(n), tab8, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL);
+#ifdef USE_THISOWN
+ Printv(f_shadow, tab8, "try:\n", NIL);
+ Printv(f_shadow, tab8, tab4, "if self.thisown:", module, ".", Swig_name_destroy(NSPACE_TODO, symname), "(self)\n", NIL);
+ Printv(f_shadow, tab8, "except __builtin__.Exception: pass\n", NIL);
+#else
+#endif
+ if (have_pythonappend(n))
+ Printv(f_shadow, indent_pythoncode(pythonappend(n), tab8, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL);
+ Printv(f_shadow, tab8, "pass\n", NIL);
+ Printv(f_shadow, "\n", NIL);
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * membervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int membervariableHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+
+ int oldshadow = shadow;
+ if (shadow)
+ shadow = shadow | PYSHADOW_MEMBER;
+ Language::membervariableHandler(n);
+ shadow = oldshadow;
+
+ if (shadow && !builtin) {
+ String *mname = Swig_name_member(NSPACE_TODO, class_name, symname);
+ String *setname = Swig_name_set(NSPACE_TODO, mname);
+ String *getname = Swig_name_get(NSPACE_TODO, mname);
+ int assignable = is_assignable(n);
+ Printv(f_shadow, tab4, symname, " = property(", module, ".", getname, NIL);
+ if (assignable)
+ Printv(f_shadow, ", ", module, ".", setname, NIL);
+ if (have_docstring(n))
+ Printv(f_shadow, ", doc=", docstring(n, AUTODOC_VAR, tab4), NIL);
+ Printv(f_shadow, ")\n", NIL);
+ Delete(mname);
+ Delete(setname);
+ Delete(getname);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * staticmembervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int staticmembervariableHandler(Node *n) {
+ Swig_save("builtin_staticmembervariableHandler", n, "builtin_symname", NIL);
+ Language::staticmembervariableHandler(n);
+ Swig_restore(n);
+
+ if (GetFlag(n, "wrappedasconstant"))
+ return SWIG_OK;
+
+ String *symname = Getattr(n, "sym:name");
+
+ if (shadow) {
+ if (!builtin && GetFlag(n, "hasconsttype")) {
+ String *mname = Swig_name_member(NSPACE_TODO, class_name, symname);
+ Printf(f_shadow_stubs, "%s.%s = %s.%s.%s\n", class_name, symname, module, global_name, mname);
+ Delete(mname);
+ } else {
+ String *mname = Swig_name_member(NSPACE_TODO, class_name, symname);
+ String *getname = Swig_name_get(NSPACE_TODO, mname);
+ String *wrapgetname = Swig_name_wrapper(getname);
+ String *vargetname = NewStringf("Swig_var_%s", getname);
+ String *setname = Swig_name_set(NSPACE_TODO, mname);
+ String *wrapsetname = Swig_name_wrapper(setname);
+ String *varsetname = NewStringf("Swig_var_%s", setname);
+
+ Wrapper *f = NewWrapper();
+ Printv(f->def, "SWIGINTERN PyObject *", wrapgetname, "(PyObject *SWIGUNUSEDPARM(self), PyObject *SWIGUNUSEDPARM(args)) {", NIL);
+ Printv(f->code, " return ", vargetname, "();\n", NIL);
+ Append(f->code, "}\n");
+ add_method(getname, wrapgetname, 0);
+ Wrapper_print(f, f_wrappers);
+ DelWrapper(f);
+ int assignable = is_assignable(n);
+ if (assignable) {
+ int funpack = fastunpack;
+ Wrapper *f = NewWrapper();
+ Printv(f->def, "SWIGINTERN PyObject *", wrapsetname, "(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {", NIL);
+ Wrapper_add_local(f, "res", "int res");
+ if (!funpack) {
+ Wrapper_add_local(f, "value", "PyObject *value");
+ Append(f->code, "if (!PyArg_ParseTuple(args, \"O:set\", &value)) return NULL;\n");
+ }
+ Printf(f->code, "res = %s(%s);\n", varsetname, funpack ? "args" : "value");
+ Append(f->code, "return !res ? SWIG_Py_Void() : NULL;\n");
+ Append(f->code, "}\n");
+ Wrapper_print(f, f_wrappers);
+ add_method(setname, wrapsetname, 0, 0, funpack, 1, 1);
+ DelWrapper(f);
+ }
+ if (!builtin) {
+ Printv(f_shadow, tab4, symname, " = property(", module, ".", getname, NIL);
+ if (assignable)
+ Printv(f_shadow, ", ", module, ".", setname, NIL);
+ if (have_docstring(n))
+ Printv(f_shadow, ", doc=", docstring(n, AUTODOC_VAR, tab4), NIL);
+ Printv(f_shadow, ")\n", NIL);
+ }
+ String *getter = Getattr(n, "pybuiltin:getter");
+ String *setter = Getattr(n, "pybuiltin:setter");
+ Hash *h = NULL;
+ if (getter || setter) {
+ h = Getattr(builtin_getset, symname);
+ if (!h) {
+ h = NewHash();
+ Setattr(h, "static", "1");
+ Setattr(builtin_getset, symname, h);
+ }
+ }
+ if (getter)
+ Setattr(h, "getter", getter);
+ if (setter)
+ Setattr(h, "setter", setter);
+ if (h)
+ Delete(h);
+ Delete(mname);
+ Delete(getname);
+ Delete(wrapgetname);
+ Delete(vargetname);
+ Delete(setname);
+ Delete(wrapsetname);
+ Delete(varsetname);
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * memberconstantHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int memberconstantHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ if (builtin && in_class) {
+ Swig_save("builtin_memberconstantHandler", n, "pybuiltin:symname", NIL);
+ Setattr(n, "pybuiltin:symname", symname);
+ }
+ int oldshadow = shadow;
+ if (shadow)
+ shadow = shadow | PYSHADOW_MEMBER;
+ Language::memberconstantHandler(n);
+ shadow = oldshadow;
+
+ if (builtin && in_class) {
+ Swig_restore(n);
+ } else if (shadow) {
+ Printv(f_shadow, tab4, symname, " = ", module, ".", Swig_name_member(NSPACE_TODO, class_name, symname), "\n", NIL);
+ if (have_docstring(n))
+ Printv(f_shadow, tab4, docstring(n, AUTODOC_CONST, tab4), "\n", NIL);
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * insertDirective()
+ *
+ * Hook for %insert directive. We're going to look for special %shadow inserts
+ * as a special case so we can do indenting correctly
+ * ------------------------------------------------------------ */
+
+ virtual int insertDirective(Node *n) {
+ String *code = Getattr(n, "code");
+ String *section = Getattr(n, "section");
+
+ if (!ImportMode && (Cmp(section, "python") == 0 || Cmp(section, "shadow") == 0)) {
+ if (shadow) {
+ String *pycode = indent_pythoncode(code, shadow_indent, Getfile(n), Getline(n), "%pythoncode or %insert(\"python\") block");
+ Printv(f_shadow, pycode, NIL);
+ Delete(pycode);
+ }
+ } else if (!ImportMode && (Cmp(section, "pythonbegin") == 0)) {
+ if (shadow) {
+ String *pycode = indent_pythoncode(code, "", Getfile(n), Getline(n), "%pythonbegin or %insert(\"pythonbegin\") block");
+ Printv(f_shadow_begin, pycode, NIL);
+ Delete(pycode);
+ }
+ } else {
+ Language::insertDirective(n);
+ }
+ return SWIG_OK;
+ }
+
+ virtual String *runtimeCode() {
+ String *s = NewString("");
+ String *shead = Swig_include_sys("pyhead.swg");
+ if (!shead) {
+ Printf(stderr, "*** Unable to open 'pyhead.swg'\n");
+ } else {
+ Append(s, shead);
+ Delete(shead);
+ }
+ String *serrors = Swig_include_sys("pyerrors.swg");
+ if (!serrors) {
+ Printf(stderr, "*** Unable to open 'pyerrors.swg'\n");
+ } else {
+ Append(s, serrors);
+ Delete(serrors);
+ }
+ String *sthread = Swig_include_sys("pythreads.swg");
+ if (!sthread) {
+ Printf(stderr, "*** Unable to open 'pythreads.swg'\n");
+ } else {
+ Append(s, sthread);
+ Delete(sthread);
+ }
+ String *sapi = Swig_include_sys("pyapi.swg");
+ if (!sapi) {
+ Printf(stderr, "*** Unable to open 'pyapi.swg'\n");
+ } else {
+ Append(s, sapi);
+ Delete(sapi);
+ }
+ String *srun = Swig_include_sys("pyrun.swg");
+ if (!srun) {
+ Printf(stderr, "*** Unable to open 'pyrun.swg'\n");
+ } else {
+ Append(s, srun);
+ Delete(srun);
+ }
+ return s;
+ }
+
+ virtual String *defaultExternalRuntimeFilename() {
+ return NewString("swigpyrun.h");
+ }
+
+ /*----------------------------------------------------------------------
+ * kwargsSupport()
+ *--------------------------------------------------------------------*/
+
+ bool kwargsSupport() const {
+ return true;
+ }
+};
+
+/* ---------------------------------------------------------------
+ * classDirectorMethod()
+ *
+ * Emit a virtual director method to pass a method call on to the
+ * underlying Python object.
+ *
+ * ** Moved it here due to internal error on gcc-2.96 **
+ * --------------------------------------------------------------- */
+int PYTHON::classDirectorMethods(Node *n) {
+ director_method_index = 0;
+ return Language::classDirectorMethods(n);
+}
+
+
+int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
+ int is_void = 0;
+ int is_pointer = 0;
+ String *decl = Getattr(n, "decl");
+ String *name = Getattr(n, "name");
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *declaration = NewString("");
+ ParmList *l = Getattr(n, "parms");
+ Wrapper *w = NewWrapper();
+ String *tm;
+ String *wrap_args = NewString("");
+ String *returntype = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ String *storage = Getattr(n, "storage");
+ bool pure_virtual = false;
+ int status = SWIG_OK;
+ int idx;
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+
+ if (builtin) {
+ // Rename any wrapped parameters called 'self' as the generated code contains a variable with same name
+ Parm *p;
+ for (p = l; p; p = nextSibling(p)) {
+ String *arg = Getattr(p, "name");
+ if (arg && Cmp(arg, "self") == 0)
+ Delattr(p, "name");
+ }
+ }
+
+ if (Cmp(storage, "virtual") == 0) {
+ if (Cmp(value, "0") == 0) {
+ pure_virtual = true;
+ }
+ }
+
+ /* determine if the method returns a pointer */
+ is_pointer = SwigType_ispointer_return(decl);
+ is_void = (!Cmp(returntype, "void") && !is_pointer);
+
+ /* virtual method definition */
+ String *target;
+ String *pclassname = NewStringf("SwigDirector_%s", classname);
+ String *qualified_name = NewStringf("%s::%s", pclassname, name);
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ /* header declaration */
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Get any exception classes in the throws typemap
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ ParmList *throw_parm_list = 0;
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ Parm *p;
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list)
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+ String *str = SwigType_str(Getattr(p, "type"), 0);
+ Append(w->def, str);
+ Append(declaration, str);
+ Delete(str);
+ }
+ }
+
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+
+ /* declare method return value
+ * if the return value is a reference or const reference, a specialized typemap must
+ * handle it, including declaration of c_result ($result).
+ */
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ }
+ } else {
+ String *cres = SwigType_lstr(returntype, "c_result");
+ Printf(w->code, "%s;\n", cres);
+ Delete(cres);
+ }
+ }
+
+ if (builtin) {
+ Printv(w->code, "PyObject *self = NULL;\n", NIL);
+ Printv(w->code, "(void)self;\n", NIL);
+ }
+
+ if (ignored_method) {
+ if (!pure_virtual) {
+ if (!is_void)
+ Printf(w->code, "return ");
+ String *super_call = Swig_method_call(super, l);
+ Printf(w->code, "%s;\n", super_call);
+ Delete(super_call);
+ } else {
+ Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname),
+ SwigType_namestr(name));
+ }
+ } else {
+ /* attach typemaps to arguments (C/C++ -> Python) */
+ String *arglist = NewString("");
+ String *parse_args = NewString("");
+
+ Swig_director_parms_fixup(l);
+
+ /* remove the wrapper 'w' since it was producing spurious temps */
+ Swig_typemap_attach_parms("in", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ Parm *p;
+ char source[256];
+
+ int outputs = 0;
+ if (!is_void)
+ outputs++;
+
+ /* build argument list and type conversion string */
+ idx = 0;
+ p = l;
+ int use_parse = 0;
+ while (p) {
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ /* old style? caused segfaults without the p!=0 check
+ in the for() condition, and seems dangerous in the
+ while loop as well.
+ while (Getattr(p, "tmap:ignore")) {
+ p = Getattr(p, "tmap:ignore:next");
+ }
+ */
+
+ if (Getattr(p, "tmap:directorargout") != 0)
+ outputs++;
+
+ String *pname = Getattr(p, "name");
+ String *ptype = Getattr(p, "type");
+
+ Putc(',', arglist);
+ if ((tm = Getattr(p, "tmap:directorin")) != 0) {
+ String *parse = Getattr(p, "tmap:directorin:parse");
+ if (!parse) {
+ sprintf(source, "obj%d", idx++);
+ String *input = NewString(source);
+ Setattr(p, "emit:directorinput", input);
+ Replaceall(tm, "$input", input);
+ Delete(input);
+ Replaceall(tm, "$owner", "0");
+ /* Wrapper_add_localv(w, source, "swig::SwigVar_PyObject", source, "= 0", NIL); */
+ Printv(wrap_args, "swig::SwigVar_PyObject ", source, ";\n", NIL);
+
+ Printv(wrap_args, tm, "\n", NIL);
+ Printv(arglist, "(PyObject *)", source, NIL);
+ Putc('O', parse_args);
+ } else {
+ use_parse = 1;
+ Append(parse_args, parse);
+ Setattr(p, "emit:directorinput", pname);
+ Replaceall(tm, "$input", pname);
+ Replaceall(tm, "$owner", "0");
+ if (Len(tm) == 0)
+ Append(tm, pname);
+ Append(arglist, tm);
+ }
+ p = Getattr(p, "tmap:directorin:next");
+ continue;
+ } else if (Cmp(ptype, "void")) {
+ /* special handling for pointers to other C++ director classes.
+ * ideally this would be left to a typemap, but there is currently no
+ * way to selectively apply the dynamic_cast<> to classes that have
+ * directors. in other words, the type "SwigDirector_$1_lname" only exists
+ * for classes with directors. we avoid the problem here by checking
+ * module.wrap::directormap, but it's not clear how to get a typemap to
+ * do something similar. perhaps a new default typemap (in addition
+ * to SWIGTYPE) called DIRECTORTYPE?
+ */
+ if (SwigType_ispointer(ptype) || SwigType_isreference(ptype)) {
+ Node *module = Getattr(parent, "module");
+ Node *target = Swig_directormap(module, ptype);
+ sprintf(source, "obj%d", idx++);
+ String *nonconst = 0;
+ /* strip pointer/reference --- should move to Swig/stype.c */
+ String *nptype = NewString(Char(ptype) + 2);
+ /* name as pointer */
+ String *ppname = Copy(pname);
+ if (SwigType_isreference(ptype)) {
+ Insert(ppname, 0, "&");
+ }
+ /* if necessary, cast away const since Python doesn't support it! */
+ if (SwigType_isconst(nptype)) {
+ nonconst = NewStringf("nc_tmp_%s", pname);
+ String *nonconst_i = NewStringf("= const_cast< %s >(%s)", SwigType_lstr(ptype, 0), ppname);
+ Wrapper_add_localv(w, nonconst, SwigType_lstr(ptype, 0), nonconst, nonconst_i, NIL);
+ Delete(nonconst_i);
+ Swig_warning(WARN_LANG_DISCARD_CONST, input_file, line_number,
+ "Target language argument '%s' discards const in director method %s::%s.\n",
+ SwigType_str(ptype, pname), SwigType_namestr(c_classname), SwigType_namestr(name));
+ } else {
+ nonconst = Copy(ppname);
+ }
+ Delete(nptype);
+ Delete(ppname);
+ String *mangle = SwigType_manglestr(ptype);
+ if (target) {
+ String *director = NewStringf("director_%s", mangle);
+ Wrapper_add_localv(w, director, "Swig::Director *", director, "= 0", NIL);
+ Wrapper_add_localv(w, source, "swig::SwigVar_PyObject", source, "= 0", NIL);
+ Printf(wrap_args, "%s = SWIG_DIRECTOR_CAST(%s);\n", director, nonconst);
+ Printf(wrap_args, "if (!%s) {\n", director);
+ Printf(wrap_args, "%s = SWIG_InternalNewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
+ Append(wrap_args, "} else {\n");
+ Printf(wrap_args, "%s = %s->swig_get_self();\n", source, director);
+ Printf(wrap_args, "Py_INCREF((PyObject *)%s);\n", source);
+ Append(wrap_args, "}\n");
+ Delete(director);
+ Printv(arglist, source, NIL);
+ } else {
+ Wrapper_add_localv(w, source, "swig::SwigVar_PyObject", source, "= 0", NIL);
+ Printf(wrap_args, "%s = SWIG_InternalNewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
+ //Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE_p_%s, 0);\n",
+ // source, nonconst, base);
+ Printv(arglist, source, NIL);
+ }
+ Putc('O', parse_args);
+ Delete(mangle);
+ Delete(nonconst);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
+ "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(ptype, 0),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_NOWRAP;
+ break;
+ }
+ }
+ p = nextSibling(p);
+ }
+
+ /* add the method name as a PyString */
+ String *pyname = Getattr(n, "sym:name");
+
+ int allow_thread = threads_enable(n);
+
+ if (allow_thread) {
+ thread_begin_block(n, w->code);
+ Append(w->code, "{\n");
+ }
+
+ /* wrap complex arguments to PyObjects */
+ Printv(w->code, wrap_args, NIL);
+
+ /* pass the method call on to the Python object */
+ if (dirprot_mode() && !is_public(n)) {
+ Printf(w->code, "swig_set_inner(\"%s\", true);\n", name);
+ }
+
+
+ Append(w->code, "if (!swig_get_self()) {\n");
+ Printf(w->code, " Swig::DirectorException::raise(\"'self' uninitialized, maybe you forgot to call %s.__init__.\");\n", classname);
+ Append(w->code, "}\n");
+ Append(w->code, "#if defined(SWIG_PYTHON_DIRECTOR_VTABLE)\n");
+ Printf(w->code, "const size_t swig_method_index = %d;\n", director_method_index++);
+ Printf(w->code, "const char *const swig_method_name = \"%s\";\n", pyname);
+
+ Append(w->code, "PyObject *method = swig_get_method(swig_method_index, swig_method_name);\n");
+ if (Len(parse_args) > 0) {
+ if (use_parse) {
+ Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallFunction(method, (char *)\"(%s)\" %s);\n", Swig_cresult_name(), parse_args, arglist);
+ } else {
+ Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallFunctionObjArgs(method %s, NULL);\n", Swig_cresult_name(), arglist);
+ }
+ } else {
+ Append(w->code, "swig::SwigVar_PyObject args = PyTuple_New(0);\n");
+ Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_Call(method, (PyObject *) args, NULL);\n", Swig_cresult_name());
+ }
+ Append(w->code, "#else\n");
+ if (Len(parse_args) > 0) {
+ if (use_parse) {
+ Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallMethod(swig_get_self(), (char *)\"%s\", (char *)\"(%s)\" %s);\n", Swig_cresult_name(), pyname, parse_args, arglist);
+ } else {
+ Printf(w->code, "swig::SwigVar_PyObject swig_method_name = SWIG_Python_str_FromChar(\"%s\");\n", pyname);
+ Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name %s, NULL);\n", Swig_cresult_name(), arglist);
+ }
+ } else {
+ Printf(w->code, "swig::SwigVar_PyObject swig_method_name = SWIG_Python_str_FromChar(\"%s\");\n", pyname);
+ Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name, NULL);\n", Swig_cresult_name());
+ }
+ Append(w->code, "#endif\n");
+
+ if (dirprot_mode() && !is_public(n))
+ Printf(w->code, "swig_set_inner(\"%s\", false);\n", name);
+
+ /* exception handling */
+ tm = Swig_typemap_lookup("director:except", n, Swig_cresult_name(), 0);
+ if (!tm) {
+ tm = Getattr(n, "feature:director:except");
+ if (tm)
+ tm = Copy(tm);
+ }
+ Printf(w->code, "if (!%s) {\n", Swig_cresult_name());
+ Append(w->code, " PyObject *error = PyErr_Occurred();\n");
+ if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
+ Replaceall(tm, "$error", "error");
+ Printv(w->code, Str(tm), "\n", NIL);
+ } else {
+ Append(w->code, " if (error) {\n");
+ Printf(w->code, " Swig::DirectorMethodException::raise(\"Error detected when calling '%s.%s'\");\n", classname, pyname);
+ Append(w->code, " }\n");
+ }
+ Append(w->code, "}\n");
+ Delete(tm);
+
+ /*
+ * Python method may return a simple object, or a tuple.
+ * for in/out arguments, we have to extract the appropriate PyObjects from the tuple,
+ * then marshal everything back to C/C++ (return value and output arguments).
+ *
+ */
+
+ /* marshal return value and other outputs (if any) from PyObject to C/C++ type */
+
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+
+ if (outputs > 1) {
+ Wrapper_add_local(w, "output", "PyObject *output");
+ Printf(w->code, "if (!PyTuple_Check(%s)) {\n", Swig_cresult_name());
+ Printf(w->code, " Swig::DirectorTypeMismatchException::raise(\"Python method %s.%sfailed to return a tuple.\");\n", classname, pyname);
+ Append(w->code, "}\n");
+ }
+
+ idx = 0;
+
+ /* marshal return value */
+ if (!is_void) {
+ tm = Swig_typemap_lookup("directorout", n, Swig_cresult_name(), w);
+ if (tm != 0) {
+ if (outputs > 1) {
+ Printf(w->code, "output = PyTuple_GetItem(%s, %d);\n", Swig_cresult_name(), idx++);
+ Replaceall(tm, "$input", "output");
+ } else {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ }
+ char temp[24];
+ sprintf(temp, "%d", idx);
+ Replaceall(tm, "$argnum", temp);
+
+ /* TODO check this */
+ if (Getattr(n, "wrap:disown")) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+ if (Getattr(n, "tmap:directorout:implicitconv")) {
+ Replaceall(tm, "$implicitconv", get_implicitconv_flag(n));
+ }
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, tm, "\n", NIL);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s in director method %s::%s (skipping method).\n", SwigType_str(returntype, 0), SwigType_namestr(c_classname),
+ SwigType_namestr(name));
+ status = SWIG_ERROR;
+ }
+ }
+
+ /* marshal outputs */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout")) != 0) {
+ if (outputs > 1) {
+ Printf(w->code, "output = PyTuple_GetItem(%s, %d);\n", Swig_cresult_name(), idx++);
+ Replaceall(tm, "$result", "output");
+ } else {
+ Replaceall(tm, "$result", Swig_cresult_name());
+ }
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* any existing helper functions to handle this? */
+ if (allow_thread) {
+ Append(w->code, "}\n");
+ thread_end_block(n, w->code);
+ }
+
+ Delete(parse_args);
+ Delete(arglist);
+ Delete(cleanup);
+ Delete(outarg);
+ }
+
+ if (!is_void) {
+ if (!(ignored_method && !pure_virtual)) {
+ String *rettype = SwigType_str(returntype, 0);
+ if (!SwigType_isreference(returntype)) {
+ Printf(w->code, "return (%s) c_result;\n", rettype);
+ } else {
+ Printf(w->code, "return (%s) *c_result;\n", rettype);
+ }
+ Delete(rettype);
+ }
+ }
+
+ Append(w->code, "}\n");
+
+ // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewString("");
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+
+ /* emit the director method */
+ if (status == SWIG_OK) {
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+
+ /* clean up */
+ Delete(wrap_args);
+ Delete(pclassname);
+ DelWrapper(w);
+ return status;
+}
+
+/* -----------------------------------------------------------------------------
+ * swig_python() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_python() {
+ return new PYTHON();
+}
+extern "C" Language *swig_python(void) {
+ return new_swig_python();
+}
diff --git a/contrib/tools/swig/Source/Modules/r.cxx b/contrib/tools/swig/Source/Modules/r.cxx
new file mode 100644
index 00000000000..3e3c23e44ec
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/r.cxx
@@ -0,0 +1,2897 @@
+
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * r.cxx
+ *
+ * R language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+
+static String* replaceInitialDash(const String *name)
+{
+ String *retval;
+ if (!Strncmp(name, "_", 1)) {
+ retval = Copy(name);
+ Insert(retval, 0, "s");
+ } else {
+ retval = Copy(name);
+ }
+ return retval;
+}
+
+static String * getRTypeName(SwigType *t, int *outCount = NULL) {
+ String *b = SwigType_base(t);
+ List *els = SwigType_split(t);
+ int count = 0;
+ int i;
+
+ if(Strncmp(b, "struct ", 7) == 0)
+ Replace(b, "struct ", "", DOH_REPLACE_FIRST);
+
+ for(i = 0; i < Len(els); i++) {
+ String *el = Getitem(els, i);
+ if(Strcmp(el, "p.") == 0 || Strncmp(el, "a(", 2) == 0) {
+ count++;
+ Append(b, "Ref");
+ }
+ }
+ if(outCount)
+ *outCount = count;
+
+ String *tmp = NewString("");
+ char *retName = Char(SwigType_manglestr(t));
+ Insert(tmp, 0, retName);
+ return tmp;
+
+}
+
+/* --------------------------------------------------------------
+ * Tries to get the resolved name, with options of adding
+ * or removing a layer of references. Take care not
+ * to request both
+ * --------------------------------------------------------------*/
+
+static String *getRClassName(String *retType, int deRef=0, int upRef=0) {
+ SwigType *resolved = SwigType_typedef_resolve_all(retType);
+ int ispointer = SwigType_ispointer(resolved);
+ int isreference = SwigType_isreference(resolved);
+ if (upRef) {
+ SwigType_add_pointer(resolved);
+ }
+ if (deRef) {
+ if (ispointer) {
+ SwigType_del_pointer(resolved);
+ }
+ if (isreference) {
+ SwigType_del_reference(resolved);
+ }
+ }
+ String *tmp = NewString("");
+ Insert(tmp, 0, Char(SwigType_manglestr(resolved)));
+ return(tmp);
+}
+
+/* --------------------------------------------------------------
+ * Tries to get the name of the R class corresponding to the given type
+ * e.g. struct A * is ARef, struct A** is ARefRef.
+ * Now handles arrays, i.e. struct A[2]
+ * --------------------------------------------------------------*/
+
+
+static String * getRClassNameCopyStruct(String *retType, int addRef) {
+ String *tmp = NewString("");
+
+ List *l = SwigType_split(retType);
+ int n = Len(l);
+ if(!l || n == 0) {
+#ifdef R_SWIG_VERBOSE
+ Printf(stdout, "SwigType_split return an empty list for %s\n", retType);
+#endif
+ return(tmp);
+ }
+
+
+ String *el = Getitem(l, n-1);
+ char *ptr = Char(el);
+ if(strncmp(ptr, "struct ", 7) == 0)
+ ptr += 7;
+
+ Printf(tmp, "%s", ptr);
+
+ if(addRef) {
+ for(int i = 0; i < n; i++) {
+ if(Strcmp(Getitem(l, i), "p.") == 0 ||
+ Strncmp(Getitem(l, i), "a(", 2) == 0)
+ Printf(tmp, "Ref");
+ }
+ }
+
+ return tmp;
+}
+
+
+/* -------------------------------------------------------------
+ * Write the elements of a list to the File*, one element per line.
+ * If quote is true, surround the element with "element".
+ * This takes care of inserting a tab in front of each line and also
+ * a comma after each element, except the last one.
+ * --------------------------------------------------------------*/
+
+
+static void writeListByLine(List *l, File *out, bool quote = 0) {
+ int i, n = Len(l);
+ for(i = 0; i < n; i++)
+ Printf(out, "%s%s%s%s%s\n", tab8,
+ quote ? "\"" :"",
+ Getitem(l, i),
+ quote ? "\"" :"", i < n-1 ? "," : "");
+}
+
+
+static const char *usage = "\
+R Options (available with -r)\n\
+ -copystruct - Emit R code to copy C structs (on by default)\n\
+ -debug - Output debug\n\
+ -dll <name> - Name of the DLL (without the .dll or .so suffix).\n\
+ Default is the module name.\n\
+ -gc - Aggressive garbage collection\n\
+ -memoryprof - Add memory profile\n\
+ -namespace - Output NAMESPACE file\n\
+ -no-init-code - Turn off the generation of the R_init_<pkgname> code\n\
+ (registration information still generated)\n\
+ -package <name> - Package name for the PACKAGE argument of the R .Call()\n\
+ invocations. Default is the module name.\n\
+";
+
+
+
+/* -------------------------------------------------------------
+ * Display the help for this module on the screen/console.
+ * --------------------------------------------------------------*/
+
+static void showUsage() {
+ fputs(usage, stdout);
+}
+
+static bool expandTypedef(SwigType *t) {
+ if (SwigType_isenum(t)) return false;
+ String *prefix = SwigType_prefix(t);
+ if (Strncmp(prefix, "f", 1)) return false;
+ if (Strncmp(prefix, "p.f", 3)) return false;
+ return true;
+}
+
+
+/* -------------------------------------------------------------
+ * Determine whether we should add a .copy argument to the S function
+ * that wraps/interfaces to the routine that returns the given type.
+ * --------------------------------------------------------------*/
+
+static int addCopyParameter(SwigType *type) {
+ int ok = 0;
+ ok = Strncmp(type, "struct ", 7) == 0 || Strncmp(type, "p.struct ", 9) == 0;
+ if(!ok) {
+ ok = Strncmp(type, "p.", 2);
+ }
+
+ return(ok);
+}
+
+static void replaceRClass(String *tm, SwigType *type) {
+ String *tmp = getRClassName(type, 0, 0);
+ String *tmp_base = getRClassName(type, 1, 0);
+ String *tmp_ref = getRClassName(type, 0, 1);
+ Replaceall(tm, "$R_class", tmp);
+ Replaceall(tm, "$*R_class", tmp_base);
+ Replaceall(tm, "$&R_class", tmp_ref);
+ Delete(tmp); Delete(tmp_base); Delete(tmp_ref);
+}
+
+class R : public Language {
+public:
+ R();
+ void registerClass(Node *n);
+ void main(int argc, char *argv[]);
+ int top(Node *n);
+
+ void dispatchFunction(Node *n);
+ int functionWrapper(Node *n);
+ int constantWrapper(Node *n);
+ int variableWrapper(Node *n);
+
+ int classDeclaration(Node *n);
+ int enumDeclaration(Node *n);
+ String *enumValue(Node *n);
+ virtual int enumvalueDeclaration(Node *n);
+ int membervariableHandler(Node *n);
+
+ int typedefHandler(Node *n);
+
+ static List *Swig_overload_rank(Node *n,
+ bool script_lang_wrapping);
+
+ int memberfunctionHandler(Node *n) {
+ if (debugMode)
+ Printf(stdout, "<memberfunctionHandler> %s %s\n",
+ Getattr(n, "name"),
+ Getattr(n, "type"));
+ member_name = Getattr(n, "sym:name");
+ processing_class_member_function = 1;
+ int status = Language::memberfunctionHandler(n);
+ processing_class_member_function = 0;
+ return status;
+ }
+
+ /* Grab the name of the current class being processed so that we can
+ deal with members of that class. */
+ int classHandler(Node *n){
+ if(!ClassMemberTable)
+ ClassMemberTable = NewHash();
+
+ class_name = Getattr(n, "name");
+ int status = Language::classHandler(n);
+
+ class_name = NULL;
+ return status;
+ }
+
+ // Not used:
+ String *runtimeCode();
+
+protected:
+ int addRegistrationRoutine(String *rname, int nargs);
+ int outputRegistrationRoutines(File *out);
+
+ int outputCommandLineArguments(File *out);
+ int generateCopyRoutines(Node *n);
+ int DumpCode(Node *n);
+
+ int OutputMemberReferenceMethod(String *className, int isSet, List *memberList, List *nameList, List *typeList, File *out);
+ int defineArrayAccessors(SwigType *type);
+
+ void addNamespaceFunction(String *name) {
+ if(!namespaceFunctions)
+ namespaceFunctions = NewList();
+ Append(namespaceFunctions, name);
+ }
+
+ void addNamespaceMethod(String *name) {
+ if(!namespaceMethods)
+ namespaceMethods = NewList();
+ Append(namespaceMethods, name);
+ }
+
+ String* processType(SwigType *t, Node *n, int *nargs = NULL);
+ String *createFunctionPointerHandler(SwigType *t, Node *n, int *nargs);
+ int addFunctionPointerProxy(String *name, Node *n, SwigType *t, String *s_paramTypes) {
+ /*XXX Do we need to put the t in there to get the return type later. */
+ if(!functionPointerProxyTable)
+ functionPointerProxyTable = NewHash();
+
+ Setattr(functionPointerProxyTable, name, n);
+
+ Setattr(SClassDefs, name, name);
+ Printv(s_classes, "setClass('",
+ name,
+ "',\n", tab8,
+ "prototype = list(parameterTypes = c(", s_paramTypes, "),\n",
+ tab8, tab8, tab8,
+ "returnType = '", SwigType_manglestr(t), "'),\n", tab8,
+ "contains = 'CRoutinePointer')\n\n##\n", NIL);
+
+ return SWIG_OK;
+ }
+
+
+ void addSMethodInfo(String *name,
+ String *argType, int nargs);
+ // Simple initialization such as constant strings that can be reused.
+ void init();
+
+
+ void addAccessor(String *memberName, Wrapper *f,
+ String *name, String *methodSetGet);
+
+ static int getFunctionPointerNumArgs(Node *n, SwigType *tt);
+
+ // filtering of class member lists by function type. Used in constructing accessors
+ // are we allowed to use stl style functors to customise this?
+ List* filterMemberList(List *class_member_function_types, List *class_member_other, String *R_MEMBER, bool equal);
+
+protected:
+ bool copyStruct;
+ bool memoryProfile;
+ bool aggressiveGc;
+
+ // Strings into which we cumulate the generated code that is to be written
+ //vto the files.
+ String *enum_values;
+ String *enum_def_calls;
+ String *sfile;
+ String *f_init;
+ String *s_classes;
+ String *f_begin;
+ String *f_runtime;
+ String *f_wrapper;
+ String *s_header;
+ String *f_wrappers;
+ String *s_init;
+ String *s_init_routine;
+ String *s_namespace;
+
+ // State variables that carry information across calls to functionWrapper()
+ // from member accessors and class declarations.
+ String *opaqueClassDeclaration;
+ int processing_variable;
+ int processing_member_access_function;
+ String *member_name;
+ String *class_name;
+
+ String *R_MEMBER_NORMAL;
+ String *R_MEMBER_SET;
+ String *R_MEMBER_GET;
+
+ int processing_class_member_function;
+ // Spread out the lists so that they are simpler to process
+ // by storing the type of the method (i.e. set, get or nothing)
+ // and having separate lists for name, membername and wrapper
+ List *class_member_function_types;
+ List *class_member_function_names;
+ List *class_member_function_membernames;
+ List *class_member_function_wrappernames;
+ /* */
+ Hash *ClassMemberTable;
+ Hash *ClassMethodsTable;
+ Hash *SClassDefs;
+ Hash *SMethodInfo;
+
+ // Information about routines that are generated and to be registered with
+ // R for dynamic lookup.
+ Hash *registrationTable;
+ Hash *functionPointerProxyTable;
+
+ List *namespaceFunctions;
+ List *namespaceMethods;
+ List *namespaceClasses; // Probably can do this from ClassMemberTable.
+
+
+ // Store a copy of the command line.
+ // Need only keep a string that has it formatted.
+ char **Argv;
+ int Argc;
+ bool inCPlusMode;
+
+ // State variables that we remember from the command line settings
+ // potentially that govern the code we generate.
+ String *DllName;
+ String *Rpackage;
+ bool noInitializationCode;
+ bool outputNamespaceInfo;
+
+ String *UnProtectWrapupCode;
+
+ // Static members
+ static bool debugMode;
+};
+
+R::R() :
+ copyStruct(false),
+ memoryProfile(false),
+ aggressiveGc(false),
+ enum_values(0),
+ enum_def_calls(0),
+ sfile(0),
+ f_init(0),
+ s_classes(0),
+ f_begin(0),
+ f_runtime(0),
+ f_wrapper(0),
+ s_header(0),
+ f_wrappers(0),
+ s_init(0),
+ s_init_routine(0),
+ s_namespace(0),
+ opaqueClassDeclaration(0),
+ processing_variable(0),
+ processing_member_access_function(0),
+ member_name(0),
+ class_name(0),
+ R_MEMBER_NORMAL(NewString("normal")),
+ R_MEMBER_SET(NewString("set")),
+ R_MEMBER_GET(NewString("get")),
+ processing_class_member_function(0),
+ class_member_function_types(0),
+ class_member_function_names(0),
+ class_member_function_membernames(0),
+ class_member_function_wrappernames(0),
+ ClassMemberTable(0),
+ ClassMethodsTable(0),
+ SClassDefs(0),
+ SMethodInfo(0),
+ registrationTable(0),
+ functionPointerProxyTable(0),
+ namespaceFunctions(0),
+ namespaceMethods(0),
+ namespaceClasses(0),
+ Argv(0),
+ Argc(0),
+ inCPlusMode(false),
+ DllName(0),
+ Rpackage(0),
+ noInitializationCode(false),
+ outputNamespaceInfo(false),
+ UnProtectWrapupCode(0) {
+}
+
+bool R::debugMode = false;
+
+int R::getFunctionPointerNumArgs(Node *n, SwigType *tt) {
+ (void) tt;
+ n = Getattr(n, "type");
+ if (debugMode)
+ Printf(stdout, "type: %s\n", n);
+
+ ParmList *parms = Getattr(n, "parms");
+ if (debugMode)
+ Printf(stdout, "parms = %p\n", parms);
+ return ParmList_len(parms);
+}
+
+
+void R::addSMethodInfo(String *name, String *argType, int nargs) {
+ (void) argType;
+
+ if(!SMethodInfo)
+ SMethodInfo = NewHash();
+ if (debugMode)
+ Printf(stdout, "[addMethodInfo] %s\n", name);
+
+ Hash *tb = Getattr(SMethodInfo, name);
+
+ if(!tb) {
+ tb = NewHash();
+ Setattr(SMethodInfo, name, tb);
+ }
+
+ String *str = Getattr(tb, "max");
+ int max = -1;
+ if(str)
+ max = atoi(Char(str));
+ if(max < nargs) {
+ if(str) Delete(str);
+ str = NewStringf("%d", max);
+ Setattr(tb, "max", str);
+ }
+}
+
+/* ----------------------------------------
+ * Returns the name of the new routine.
+ * ------------------------------------------ */
+
+String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) {
+ String *funName = SwigType_manglestr(t);
+
+ /* See if we have already processed this one. */
+ if(functionPointerProxyTable && Getattr(functionPointerProxyTable, funName))
+ return funName;
+
+ if (debugMode)
+ Printf(stdout, "<createFunctionPointerHandler> Defining %s\n", t);
+
+ SwigType *rettype = Copy(Getattr(n, "type"));
+ SwigType *funcparams = SwigType_functionpointer_decompose(rettype);
+ String *rtype = SwigType_str(rettype, 0);
+
+ // ParmList *parms = Getattr(n, "parms");
+ // memory leak
+ ParmList *parms = SwigType_function_parms(SwigType_del_pointer(Copy(t)), n);
+
+
+ if (debugMode) {
+ Printf(stdout, "Type: %s\n", t);
+ Printf(stdout, "Return type: %s\n", SwigType_base(t));
+ }
+
+ bool isVoidType = Strcmp(rettype, "void") == 0;
+ if (debugMode)
+ Printf(stdout, "%s is void ? %s (%s)\n", funName, isVoidType ? "yes" : "no", rettype);
+
+ Wrapper *f = NewWrapper();
+
+ /* Go through argument list, attach lnames for arguments */
+ int i = 0;
+ Parm *p = parms;
+ for (i = 0; p; p = nextSibling(p), ++i) {
+ String *arg = Getattr(p, "name");
+ String *lname;
+ if (!arg && Cmp(Getattr(p, "type"), "void")) {
+ lname = NewStringf("arg%d", i+1);
+ Setattr(p, "name", lname);
+ } else
+ lname = arg;
+
+ Setattr(p, "lname", lname);
+ }
+
+ Swig_typemap_attach_parms("out", parms, f);
+ Swig_typemap_attach_parms("scoerceout", parms, f);
+ Swig_typemap_attach_parms("scheck", parms, f);
+
+ Printf(f->def, "%s %s(", rtype, funName);
+
+ emit_parameter_variables(parms, f);
+ emit_return_variable(n, rettype, f);
+ // emit_attach_parmmaps(parms,f);
+
+ /* Using weird name and struct to avoid potential conflicts. */
+ Wrapper_add_local(f, "r_swig_cb_data", "RCallbackFunctionData *r_swig_cb_data = R_SWIG_getCallbackFunctionData()");
+ String *lvar = NewString("r_swig_cb_data");
+
+ Wrapper_add_local(f, "r_tmp", "SEXP r_tmp"); // for use in converting arguments to R objects for call.
+ Wrapper_add_local(f, "r_nprotect", "int r_nprotect = 0"); // for use in converting arguments to R objects for call.
+ Wrapper_add_local(f, "r_vmax", "char * r_vmax= 0"); // for use in converting arguments to R objects for call.
+
+ // Add local for error code in return value. This is not in emit_return_variable because that assumes an out typemap
+ // whereas the type makes are reverse
+ Wrapper_add_local(f, "ecode", "int ecode = 0");
+
+ p = parms;
+ int nargs = ParmList_len(parms);
+ if(numArgs) {
+ *numArgs = nargs;
+ if (debugMode)
+ Printf(stdout, "Setting number of parameters to %d\n", *numArgs);
+ }
+ String *setExprElements = NewString("");
+
+ String *s_paramTypes = NewString("");
+ for(i = 0; p; i++) {
+ SwigType *tt = Getattr(p, "type");
+ SwigType *name = Getattr(p, "name");
+ SwigType *swig_parm_name = NewStringf("swigarg_%s", name);
+ String *tm = Getattr(p, "tmap:out");
+ bool isVoidParm = Strcmp(tt, "void") == 0;
+ if (isVoidParm)
+ Printf(f->def, "%s", SwigType_str(tt, 0));
+ else
+ Printf(f->def, "%s %s", SwigType_str(tt, 0), swig_parm_name);
+ if (tm) {
+ String *lstr = SwigType_lstr(tt, 0);
+ if (SwigType_isreference(tt) || SwigType_isrvalue_reference(tt)) {
+ Printf(f->code, "%s = (%s) &%s;\n", Getattr(p, "lname"), lstr, swig_parm_name);
+ } else if (!isVoidParm) {
+ Printf(f->code, "%s = (%s) %s;\n", Getattr(p, "lname"), lstr, swig_parm_name);
+ }
+ Replaceall(tm, "$1", name);
+ Replaceall(tm, "$result", "r_tmp");
+ if (debugMode) {
+ Printf(stdout, "Calling Replace A: %s\n", Getattr(p,"type"));
+ }
+ replaceRClass(tm, Getattr(p,"type"));
+ Replaceall(tm,"$owner", "0");
+ Delete(lstr);
+ }
+
+ Printf(setExprElements, "%s\n", tm);
+ Printf(setExprElements, "SETCAR(r_swig_cb_data->el, %s);\n", "r_tmp");
+ Printf(setExprElements, "r_swig_cb_data->el = CDR(r_swig_cb_data->el);\n\n");
+
+ Printf(s_paramTypes, "'%s'", SwigType_manglestr(tt));
+
+
+ p = nextSibling(p);
+ if(p) {
+ Printf(f->def, ", ");
+ Printf(s_paramTypes, ", ");
+ }
+ }
+
+ Printf(f->def, ") {\n");
+
+ Printf(f->code, "Rf_protect(%s->expr = Rf_allocVector(LANGSXP, %d));\n", lvar, nargs + 1);
+ Printf(f->code, "r_nprotect++;\n");
+ Printf(f->code, "r_swig_cb_data->el = r_swig_cb_data->expr;\n\n");
+
+ Printf(f->code, "SETCAR(r_swig_cb_data->el, r_swig_cb_data->fun);\n");
+ Printf(f->code, "r_swig_cb_data->el = CDR(r_swig_cb_data->el);\n\n");
+
+ Printf(f->code, "%s\n\n", setExprElements);
+
+ Printv(f->code, "r_swig_cb_data->retValue = R_tryEval(",
+ "r_swig_cb_data->expr,",
+ " R_GlobalEnv,",
+ " &r_swig_cb_data->errorOccurred",
+ ");\n",
+ NIL);
+
+ Printv(f->code, "\n",
+ "if(r_swig_cb_data->errorOccurred) {\n",
+ "R_SWIG_popCallbackFunctionData(1);\n",
+ "Rf_error(\"error in calling R function as a function pointer (",
+ funName,
+ ")\");\n",
+ "}\n",
+ NIL);
+
+
+
+ if(!isVoidType) {
+ /* Need to deal with the return type of the function pointer, not the function pointer itself.
+ So build a new node that has the relevant pieces.
+ XXX Have to be a little more clever so that we can deal with struct A * - the * is getting lost.
+ Is this still true? If so, will a SwigType_push() solve things?
+ */
+ Parm *bbase = NewParmNode(rettype, n);
+ String *returnTM = Swig_typemap_lookup("in", bbase, Swig_cresult_name(), f);
+ if(returnTM) {
+ String *tm = returnTM;
+ Replaceall(tm,"$input", "r_swig_cb_data->retValue");
+ Replaceall(tm,"$target", Swig_cresult_name());
+ replaceRClass(tm, rettype);
+ Replaceall(tm,"$owner", "0");
+ Replaceall(tm,"$disown","0");
+ Printf(f->code, "%s\n", tm);
+ }
+ Delete(bbase);
+ }
+
+ Printv(f->code, "R_SWIG_popCallbackFunctionData(1);\n", NIL);
+ Printv(f->code, "\n", UnProtectWrapupCode, NIL);
+
+ if (SwigType_isreference(rettype)) {
+ Printv(f->code, "return *", Swig_cresult_name(), ";\n", NIL);
+ } else if (SwigType_isrvalue_reference(rettype)) {
+ Printv(f->code, "return std::move(*", Swig_cresult_name(), ");\n", NIL);
+ } else if (!isVoidType) {
+ Printv(f->code, "return ", Swig_cresult_name(), ";\n", NIL);
+ }
+
+ Printv(f->code, "\n}\n", NIL);
+ Replaceall(f->code, "SWIG_exception_fail", "SWIG_exception_noreturn");
+
+ /* To coerce correctly in S, we really want to have an extra/intermediate
+ function that handles the scoerceout.
+ We need to check if any of the argument types have an entry in
+ that map. If none do, the ignore and call the function straight.
+ Otherwise, generate a marshalling function.
+ Need to be able to find it in S. Or use an entirely generic one
+ that evaluates the expressions.
+ Handle errors in the evaluation of the function by restoring
+ the stack, if there is one in use for this function (i.e. no
+ userData).
+ */
+
+ Wrapper_print(f, f_wrapper);
+
+ addFunctionPointerProxy(funName, n, t, s_paramTypes);
+ Delete(s_paramTypes);
+ Delete(rtype);
+ Delete(rettype);
+ Delete(funcparams);
+ DelWrapper(f);
+
+ return funName;
+}
+
+void R::init() {
+ UnProtectWrapupCode =
+ NewStringf("%s", "vmaxset(r_vmax);\nif(r_nprotect) Rf_unprotect(r_nprotect);\n\n");
+
+ SClassDefs = NewHash();
+
+ sfile = NewString("");
+ f_init = NewString("");
+ s_header = NewString("");
+ f_begin = NewString("");
+ f_runtime = NewString("");
+ f_wrapper = NewString("");
+ s_classes = NewString("");
+ s_init = NewString("");
+ s_init_routine = NewString("");
+ enum_def_calls = NewString("");
+}
+
+
+/* -------------------------------------------------------------
+ * Method from Language that is called to start the entire
+ * processing off, i.e. the generation of the code.
+ * It is called after the input has been read and parsed.
+ * Here we open the output streams and generate the code.
+ * ------------------------------------------------------------- */
+int R::top(Node *n) {
+ String *module = Getattr(n, "name");
+
+ if (debugMode) {
+ Printf(stdout, "<Top> %s\n", module);
+ }
+
+ if(!Rpackage)
+ Rpackage = Copy(module);
+ if(!DllName)
+ DllName = Copy(module);
+
+ if(outputNamespaceInfo) {
+ s_namespace = NewString("");
+ Swig_register_filebyname("snamespace", s_namespace);
+ Printf(s_namespace, "useDynLib(%s)\n", DllName);
+ }
+ // Register the naming functions
+ Swig_name_register("wrapper", "R_swig_%f");
+
+ /* Associate the different streams with names so that they can be used in %insert directives by the
+ typemap code. */
+ Swig_register_filebyname("sinit", s_init);
+ Swig_register_filebyname("sinitroutine", s_init_routine);
+
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("header", s_header);
+ Swig_register_filebyname("wrapper", f_wrapper);
+ Swig_register_filebyname("s", sfile);
+ Swig_register_filebyname("sclasses", s_classes);
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n\n#ifndef SWIGR\n#define SWIGR\n#endif\n\n");
+
+
+ Swig_banner_target_lang(s_init, "#");
+ outputCommandLineArguments(s_init);
+
+ Printf(f_wrapper, "#ifdef __cplusplus\n");
+ Printf(f_wrapper, "extern \"C\" {\n");
+ Printf(f_wrapper, "#endif\n\n");
+
+ Language::top(n);
+
+ Printf(f_wrapper, "#ifdef __cplusplus\n");
+ Printf(f_wrapper, "}\n");
+ Printf(f_wrapper, "#endif\n");
+
+ String *type_table = NewString("");
+ SwigType_emit_type_table(f_runtime,f_wrapper);
+ Delete(type_table);
+
+ if(ClassMemberTable) {
+ //XXX OutputClassAccessInfo(ClassMemberTable, sfile);
+ Delete(ClassMemberTable);
+ ClassMemberTable = NULL;
+ }
+
+ Printf(f_init,"}\n");
+ if(registrationTable)
+ outputRegistrationRoutines(f_init);
+
+ /* Now arrange to write the 2 files - .S and .c. */
+
+ DumpCode(n);
+
+ Delete(sfile);
+ Delete(s_classes);
+ Delete(s_init);
+ Delete(f_wrapper);
+ Delete(f_init);
+
+ Delete(s_header);
+ Delete(f_runtime);
+ Delete(f_begin);
+
+ return SWIG_OK;
+}
+
+
+/* -------------------------------------------------------------
+ * Write the generated code to the .S and the .c files.
+ * ------------------------------------------------------------- */
+int R::DumpCode(Node *n) {
+ String *output_filename = NewString("");
+
+
+ /* The name of the file in which we will generate the S code. */
+ Printf(output_filename, "%s%s.R", SWIG_output_directory(), Rpackage);
+
+#ifdef R_SWIG_VERBOSE
+ Printf(stdout, "Writing S code to %s\n", output_filename);
+#endif
+
+ File *scode = NewFile(output_filename, "w", SWIG_output_files());
+ if (!scode) {
+ FileErrorDisplay(output_filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(output_filename);
+
+
+ Printf(scode, "%s\n\n", s_init);
+ Printf(scode, "%s\n\n", s_classes);
+ Printf(scode, "%s\n", sfile);
+ Printf(scode, "%s\n", enum_def_calls);
+
+ Delete(scode);
+ String *outfile = Getattr(n,"outfile");
+ File *runtime = NewFile(outfile,"w", SWIG_output_files());
+ if (!runtime) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ Printf(runtime, "%s", f_begin);
+ Printf(runtime, "%s\n", f_runtime);
+ Printf(runtime, "%s\n", s_header);
+ Printf(runtime, "%s\n", f_wrapper);
+ Printf(runtime, "%s\n", f_init);
+
+ Delete(runtime);
+
+ if(outputNamespaceInfo) {
+ output_filename = NewString("");
+ Printf(output_filename, "%sNAMESPACE", SWIG_output_directory());
+ File *ns = NewFile(output_filename, "w", SWIG_output_files());
+ if (!ns) {
+ FileErrorDisplay(output_filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(output_filename);
+
+ Printf(ns, "%s\n", s_namespace);
+
+ Printf(ns, "\nexport(\n");
+ writeListByLine(namespaceFunctions, ns);
+ Printf(ns, ")\n");
+ Printf(ns, "\nexportMethods(\n");
+ writeListByLine(namespaceMethods, ns, 1);
+ Printf(ns, ")\n");
+ Delete(ns);
+ Delete(s_namespace);
+ }
+
+ return SWIG_OK;
+}
+
+
+List *R::filterMemberList(List *class_member_types,
+ List *class_member_other,
+ String *R_MEMBER, bool equal) {
+ // filters class_member_other based on whether corresponding elements of
+ // class_member_function_types are equal or notequal to R_MEMBER
+ List *CM = NewList();
+ Iterator ftype, other;
+
+ for (ftype = First(class_member_types), other = First(class_member_other);
+ ftype.item;
+ ftype=Next(ftype), other=Next(other)) {
+ // verbose, clean up later if the overall structure works
+ if (equal) {
+ if (ftype.item == R_MEMBER) {
+ Append(CM, other.item);
+ }
+ } else {
+ if (ftype.item != R_MEMBER) {
+ Append(CM, other.item);
+ }
+ }
+ }
+ return(CM);
+}
+
+# if 0
+// not called
+/* -------------------------------------------------------------
+ * We may need to do more.... so this is left as a
+ * stub for the moment.
+ * -------------------------------------------------------------*/
+int R::OutputClassAccessInfo(Hash *tb, File *out) {
+ int n = OutputClassMemberTable(tb, out);
+ OutputClassMethodsTable(out);
+ return n;
+}
+
+/* -------------------------------------------------------------
+ * Currently this just writes the information collected about the
+ * different methods of the C++ classes that have been processed
+ * to the console.
+ * This will be used later to define S4 generics and methods.
+ * --------------------------------------------------------------*/
+
+int R::OutputClassMethodsTable(File *) {
+ Hash *tb = ClassMethodsTable;
+
+ if(!tb)
+ return SWIG_OK;
+
+ List *keys = Keys(tb);
+ String *key;
+ int i, n = Len(keys);
+ if (debugMode) {
+ for(i = 0; i < n ; i++ ) {
+ key = Getitem(keys, i);
+ Printf(stdout, "%d) %s\n", i, key);
+ List *els = Getattr(tb, key);
+ int nels = Len(els);
+ Printf(stdout, "\t");
+ for(int j = 0; j < nels; j+=2) {
+ Printf(stdout, "%s%s", Getitem(els, j), j < nels - 1 ? ", " : "");
+ Printf(stdout, "%s\n", Getitem(els, j+1));
+ }
+ Printf(stdout, "\n");
+ }
+ }
+
+ return SWIG_OK;
+}
+
+
+/* --------------------------------------------------------------
+ * Iterate over the <class name>_set and <>_get
+ * elements and generate the $ and $<- functions
+ * that provide constrained access to the member
+ * fields in these elements.
+
+ * tb - a hash table that is built up in functionWrapper
+ * as we process each membervalueHandler.
+ * The entries are indexed by <class name>_set and
+ * <class_name>_get. Each entry is a List *.
+
+ * out - the stram where the code is to be written. This is the S
+ * code stream as we generate only S code here.
+ * --------------------------------------------------------------*/
+
+int R::OutputClassMemberTable(Hash *tb, File *out) {
+ List *keys = Keys(tb), *el;
+
+ String *key;
+ int i, n = Len(keys);
+ /* Loop over all the <Class>_set and <Class>_get entries in the table. */
+ /* This function checks for names ending in _set - perhaps it should */
+ /* use attributes of some other form, as it potentially clashes with */
+ /* methods ending in _set */
+
+ if(n && outputNamespaceInfo) {
+ Printf(s_namespace, "exportClasses(");
+ }
+ for(i = 0; i < n; i++) {
+ key = Getitem(keys, i);
+ el = Getattr(tb, key);
+
+ String *className = Getitem(el, 0);
+ char *ptr = Char(key);
+ int klen = Len(key);
+ int isSet = 0;
+ if (klen > 4) {
+ ptr = &ptr[klen - 4];
+ isSet = strcmp(ptr, "_set") == 0;
+ }
+
+ if(outputNamespaceInfo)
+ Printf(s_namespace, "\"%s\"%s", className, i < n-1 ? "," : "");
+ }
+ if(n && outputNamespaceInfo) {
+ Printf(s_namespace, ")\n");
+ }
+
+ return n;
+}
+
+// end not used
+#endif
+/* --------------------------------------------------------------
+ * Write the methods for $ or $<- for accessing a member field in an
+ * struct or union (or class).
+ * className - the name of the struct or union (e.g. Bar for struct Bar)
+ * isSet - a logical value indicating whether the method is for
+ * modifying ($<-) or accessing ($) the member field.
+ * el - a list of length 2 * # accessible member elements + 1.
+ * The first element is the name of the class.
+ * The other pairs are member name and the name of the R function to access it.
+ * out - the stream where we write the code.
+ * --------------------------------------------------------------*/
+
+int R::OutputMemberReferenceMethod(String *className, int isSet,
+ List *memberList, List *nameList,
+ List *typeList, File *out) {
+ int numMems = Len(memberList), j;
+ int varaccessor = 0;
+ if (numMems == 0)
+ return SWIG_OK;
+
+ Wrapper *f = NewWrapper(), *attr = NewWrapper();
+
+ Printf(f->def, "function(x, name%s)", isSet ? ", value" : "");
+ Printf(attr->def, "function(x, i, j, ...%s)", isSet ? ", value" : "");
+
+ Printf(f->code, "{\n");
+ Printf(f->code, "%saccessorFuns = list(", tab8);
+
+ Node *itemList = NewHash();
+ bool has_prev = false;
+ for(j = 0; j < numMems; j++) {
+ String *item = Getitem(memberList, j);
+ String *dup = Getitem(nameList, j);
+ String *setgetmethod = Getitem(typeList, j);
+
+ if (setgetmethod == R_MEMBER_GET)
+ varaccessor++;
+
+ if (Getattr(itemList, item))
+ continue;
+ Setattr(itemList, item, "1");
+
+ String *pitem;
+ if (!Strcmp(item, "operator ()")) {
+ pitem = NewString("call");
+ } else if (!Strcmp(item, "operator ->")) {
+ pitem = NewString("deref");
+ } else if (!Strcmp(item, "operator +")) {
+ pitem = NewString("add");
+ } else if (!Strcmp(item, "operator -")) {
+ pitem = NewString("sub");
+ } else {
+ pitem = Copy(item);
+ }
+ if (has_prev)
+ Printf(f->code, ", ");
+ Printf(f->code, "'%s' = %s", pitem, dup);
+ has_prev = true;
+ Delete(pitem);
+ }
+ Delete(itemList);
+ Printf(f->code, ");\n");
+
+ if (!isSet && varaccessor > 0) {
+ Printf(f->code, "%svaccessors = c(", tab8);
+ bool first = true;
+ for(j = 0; j < numMems; j++) {
+ String *item = Getitem(memberList, j);
+ String *setgetmethod = Getitem(typeList, j);
+
+ // Check the type here instead of the name
+ if (setgetmethod == R_MEMBER_GET) {
+ Printf(f->code, "%s'%s'", first ? "" : ", ", item);
+ first = false;
+ }
+ }
+ Printf(f->code, ");\n");
+ }
+
+ Printv(f->code, ";", tab8,
+ "idx = pmatch(name, names(accessorFuns));\n",
+ tab8,
+ "if(is.na(idx)) \n",
+ tab8, tab4, NIL);
+ Printf(f->code, "return(callNextMethod(x, name%s));\n",
+ isSet ? ", value" : "");
+ Printv(f->code, tab8, "f = accessorFuns[[idx]];\n", NIL);
+ if(isSet) {
+ Printv(f->code, tab8, "f(x, value);\n", NIL);
+ Printv(f->code, tab8, "x;\n", NIL); // make certain to return the S value.
+ } else {
+ if (varaccessor) {
+ Printv(f->code, tab8,
+ "if (is.na(match(name, vaccessors))) function(...){f(x, ...)} else f(x);\n", NIL);
+ } else {
+ Printv(f->code, tab8, "function(...){f(x, ...)};\n", NIL);
+ }
+ }
+ Printf(f->code, "}\n");
+
+ String *classname_str = SwigType_namestr(className);
+ Printf(out, "# Start of accessor method for %s\n", classname_str);
+ Printf(out, "setMethod('$%s', '_p%s', ",
+ isSet ? "<-" : "",
+ getRClassName(className));
+ Wrapper_print(f, out);
+ Printf(out, ");\n");
+
+ if(isSet) {
+ Printf(out, "setMethod('[[<-', c('_p%s', 'character'),",
+ getRClassName(className));
+ Insert(f->code, 2, "name = i;\n");
+ Printf(attr->code, "%s", f->code);
+ Wrapper_print(attr, out);
+ Printf(out, ");\n");
+ }
+
+ Printf(out, "# end of accessor method for %s\n", classname_str);
+
+ Delete(classname_str);
+ DelWrapper(attr);
+ DelWrapper(f);
+
+ return SWIG_OK;
+}
+
+/* -------------------------------------------------------------
+ * Called when a enumeration is to be processed.
+ * We want to call the R function defineEnumeration().
+ * tdname is the typedef of the enumeration, i.e. giving its name.
+ * --------------------------------------------------------------*/
+
+int R::enumDeclaration(Node *n) {
+ if (!ImportMode) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ String *symname = Getattr(n, "sym:name");
+
+ // TODO - deal with anonymous enumerations
+ // Previous enum code for R didn't wrap them
+ if (!symname || Getattr(n, "unnamedinstance"))
+ return SWIG_NOWRAP;
+
+ // create mangled name for the enum
+ // This will have content if the %nspace feature is set on
+ // the input file
+ String *nspace = Getattr(n, "sym:nspace"); // NSpace/getNSpace() only works during Language::enumDeclaration call
+ String *ename;
+
+ String *name = Getattr(n, "name");
+ ename = getRClassName(name);
+ if (debugMode) {
+ Node *current_class = getCurrentClass();
+ String *cl = NewString("");
+ if (current_class) {
+ cl = getEnumClassPrefix();
+ }
+ Printf(stdout, "enumDeclaration: %s, %s, %s, %s, %s\n", name, symname, nspace, ename, cl);
+ }
+ Delete(name);
+ // set up a call to create the R enum structure. The list of
+ // individual elements will be built in enum_code
+ enum_values = 0;
+ // Emit each enum item
+ Language::enumDeclaration(n);
+
+ Printf(enum_def_calls, "defineEnumeration(\"%s\",\n .values=c(%s))\n\n", ename, enum_values);
+ Delete(enum_values);
+ Delete(ename);
+ }
+ return SWIG_OK;
+}
+
+/* -------------------------------------------------------------
+* --------------------------------------------------------------*/
+
+int R::enumvalueDeclaration(Node *n) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC)) {
+ Printf(stdout, "evd: Not public\n");
+ return SWIG_NOWRAP;
+ }
+
+ Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
+ String *symname = Getattr(n, "sym:name");
+ String *value = Getattr(n, "value");
+ String *name = Getattr(n, "name");
+ Node *parent = parentNode(n);
+ String *parent_name = Getattr(parent, "name");
+ String *newsymname = 0;
+ String *tmpValue;
+
+ // Strange hack from parent method
+ if (value)
+ tmpValue = NewString(value);
+ else
+ tmpValue = NewString(name);
+ // Note that this is used in enumValue() amongst other places
+ Setattr(n, "value", tmpValue);
+
+ // Deal with enum values that are not int
+ int swigtype = SwigType_type(Getattr(n, "type"));
+ if (swigtype == T_BOOL) {
+ const char *val = Equal(Getattr(n, "enumvalue"), "true") ? "1" : "0";
+ Setattr(n, "enumvalue", val);
+ } else if (swigtype == T_CHAR) {
+ String *val = NewStringf("'%s'", Getattr(n, "enumvalue"));
+ Setattr(n, "enumvalue", val);
+ Delete(val);
+ }
+
+ if (GetFlag(parent, "scopedenum")) {
+ newsymname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
+ symname = newsymname;
+ }
+
+ {
+ // Wrap C/C++ enums with constant integers or use the typesafe enum pattern
+ SwigType *typemap_lookup_type = parent_name ? parent_name : NewString("enum ");
+ if (debugMode) {
+ Printf(stdout, "Setting type: %s\n", Copy(typemap_lookup_type));
+ }
+ Setattr(n, "type", typemap_lookup_type);
+
+ // Simple integer constants
+ // Note these are always generated for anonymous enums, no matter what enum_feature is specified
+ // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later
+
+ String *value = enumValue(n);
+ if (enum_values) {
+ Printf(enum_values, ",\n\"%s\" = %s", name, value);
+ } else {
+ enum_values = NewString("");
+ Printf(enum_values, "\"%s\" = %s", name, value);
+ }
+
+ Delete(value);
+ }
+
+ return SWIG_OK;
+}
+
+
+/* -------------------------------------------------------------
+ * Create accessor functions for variables.
+ * Does not create equivalent wrappers for enumerations,
+ * which are handled differently
+ * --------------------------------------------------------------*/
+
+int R::variableWrapper(Node *n) {
+ String *name = Getattr(n, "sym:name");
+ if (debugMode) {
+ Printf(stdout, "variableWrapper %s\n", n);
+ }
+ processing_variable = 1;
+ Language::variableWrapper(n); // Force the emission of the _set and _get function wrappers.
+ processing_variable = 0;
+
+
+ SwigType *ty = Getattr(n, "type");
+ String *nodeType = nodeType(n);
+ int addCopyParam = addCopyParameter(ty);
+
+ //XXX
+ processType(ty, n);
+
+ if (nodeType && !Strcmp(nodeType, "enumitem")) {
+ /* special wrapper for enums - don't want the R _set, _get functions*/
+ if (debugMode) {
+ Printf(stdout, "variableWrapper enum branch\n");
+ }
+ } else if(!SwigType_isconst(ty)) {
+ Wrapper *f = NewWrapper();
+ Printf(f->def, "%s = \nfunction(value%s)\n{\n",
+ name, addCopyParam ? ", .copy = FALSE" : "");
+ Printv(f->code, "if(missing(value)) {\n",
+ name, "_get(", addCopyParam ? ".copy" : "", ")\n}", NIL);
+ Printv(f->code, " else {\n",
+ name, "_set(value)\n}\n}", NIL);
+
+ Wrapper_print(f, sfile);
+ DelWrapper(f);
+ } else {
+ Printf(sfile, "%s = %s_get\n", name, name);
+ }
+
+ return SWIG_OK;
+}
+
+/* -------------------------------------------------------------
+ * Creates accessor functions for class members.
+
+ * ToDo - this version depends on naming conventions and needs
+ * to be replaced.
+ * --------------------------------------------------------------*/
+
+void R::addAccessor(String *memberName, Wrapper *wrapper, String *name,
+ String *methodSetGet) {
+
+ if (!class_member_function_names) {
+ class_member_function_names = NewList();
+ class_member_function_membernames = NewList();
+ class_member_function_wrappernames = NewList();
+ class_member_function_types = NewList();
+ }
+ Append(class_member_function_types, methodSetGet);
+ Append(class_member_function_names, name);
+ Append(class_member_function_membernames, memberName);
+
+ String *tmp = NewString("");
+ Wrapper_print(wrapper, tmp);
+ Append(class_member_function_wrappernames, tmp);
+ // if we could put the wrapper in directly: Append(l, Copy(sfun));
+ if (debugMode)
+ Printf(stdout, "Adding accessor: %s (%s) => %s\n", memberName, name, tmp);
+}
+
+#define MAX_OVERLOAD 256
+
+struct Overloaded {
+ Node *n; /* Node */
+ int argc; /* Argument count */
+ ParmList *parms; /* Parameters used for overload check */
+ int error; /* Ambiguity error */
+};
+
+
+List * R::Swig_overload_rank(Node *n,
+ bool script_lang_wrapping) {
+ Overloaded nodes[MAX_OVERLOAD];
+ int nnodes = 0;
+ Node *o = Getattr(n,"sym:overloaded");
+
+
+ if (!o) return 0;
+
+ Node *c = o;
+ while (c) {
+ if (Getattr(c,"error")) {
+ c = Getattr(c,"sym:nextSibling");
+ continue;
+ }
+ /* Make a list of all the declarations (methods) that are overloaded with
+ * this one particular method name */
+
+ if (Getattr(c,"wrap:name")) {
+ nodes[nnodes].n = c;
+ nodes[nnodes].parms = Getattr(c,"wrap:parms");
+ nodes[nnodes].argc = emit_num_required(nodes[nnodes].parms);
+ nodes[nnodes].error = 0;
+ nnodes++;
+ }
+ c = Getattr(c,"sym:nextSibling");
+ }
+
+ /* Sort the declarations by required argument count */
+ {
+ int i,j;
+ for (i = 0; i < nnodes; i++) {
+ for (j = i+1; j < nnodes; j++) {
+ if (nodes[i].argc > nodes[j].argc) {
+ Overloaded t = nodes[i];
+ nodes[i] = nodes[j];
+ nodes[j] = t;
+ }
+ }
+ }
+ }
+
+ /* Sort the declarations by argument types */
+ {
+ int i,j;
+ for (i = 0; i < nnodes-1; i++) {
+ if (nodes[i].argc == nodes[i+1].argc) {
+ for (j = i+1; (j < nnodes) && (nodes[j].argc == nodes[i].argc); j++) {
+ Parm *p1 = nodes[i].parms;
+ Parm *p2 = nodes[j].parms;
+ int differ = 0;
+ int num_checked = 0;
+ while (p1 && p2 && (num_checked < nodes[i].argc)) {
+ if (debugMode) {
+ Printf(stdout,"p1 = '%s', p2 = '%s'\n", Getattr(p1,"type"), Getattr(p2,"type"));
+ }
+ if (checkAttribute(p1,"tmap:in:numinputs","0")) {
+ p1 = Getattr(p1,"tmap:in:next");
+ continue;
+ }
+ if (checkAttribute(p2,"tmap:in:numinputs","0")) {
+ p2 = Getattr(p2,"tmap:in:next");
+ continue;
+ }
+ String *t1 = Getattr(p1,"tmap:typecheck:precedence");
+ String *t2 = Getattr(p2,"tmap:typecheck:precedence");
+ if (debugMode) {
+ Printf(stdout,"t1 = '%s', t2 = '%s'\n", t1, t2);
+ }
+ if ((!t1) && (!nodes[i].error)) {
+ Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n",
+ Swig_name_decl(nodes[i].n), SwigType_str(Getattr(p1, "type"), 0));
+ nodes[i].error = 1;
+ } else if ((!t2) && (!nodes[j].error)) {
+ Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n",
+ Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0));
+ nodes[j].error = 1;
+ }
+ if (t1 && t2) {
+ int t1v, t2v;
+ t1v = atoi(Char(t1));
+ t2v = atoi(Char(t2));
+ differ = t1v-t2v;
+ }
+ else if (!t1 && t2) differ = 1;
+ else if (t1 && !t2) differ = -1;
+ else if (!t1 && !t2) differ = -1;
+ num_checked++;
+ if (differ > 0) {
+ Overloaded t = nodes[i];
+ nodes[i] = nodes[j];
+ nodes[j] = t;
+ break;
+ } else if ((differ == 0) && (Strcmp(t1,"0") == 0)) {
+ t1 = Getattr(p1,"ltype");
+ if (!t1) {
+ t1 = SwigType_ltype(Getattr(p1,"type"));
+ if (Getattr(p1,"tmap:typecheck:SWIGTYPE")) {
+ SwigType_add_pointer(t1);
+ }
+ Setattr(p1,"ltype",t1);
+ }
+ t2 = Getattr(p2,"ltype");
+ if (!t2) {
+ t2 = SwigType_ltype(Getattr(p2,"type"));
+ if (Getattr(p2,"tmap:typecheck:SWIGTYPE")) {
+ SwigType_add_pointer(t2);
+ }
+ Setattr(p2,"ltype",t2);
+ }
+
+ /* Need subtype check here. If t2 is a subtype of t1, then we need to change the
+ order */
+
+ if (SwigType_issubtype(t2,t1)) {
+ Overloaded t = nodes[i];
+ nodes[i] = nodes[j];
+ nodes[j] = t;
+ }
+
+ if (Strcmp(t1,t2) != 0) {
+ differ = 1;
+ break;
+ }
+ } else if (differ) {
+ break;
+ }
+ if (Getattr(p1,"tmap:in:next")) {
+ p1 = Getattr(p1,"tmap:in:next");
+ } else {
+ p1 = nextSibling(p1);
+ }
+ if (Getattr(p2,"tmap:in:next")) {
+ p2 = Getattr(p2,"tmap:in:next");
+ } else {
+ p2 = nextSibling(p2);
+ }
+ }
+ if (!differ) {
+ /* See if declarations differ by const only */
+ String *d1 = Getattr(nodes[i].n, "decl");
+ String *d2 = Getattr(nodes[j].n, "decl");
+ if (d1 && d2) {
+ String *dq1 = Copy(d1);
+ String *dq2 = Copy(d2);
+ if (SwigType_isconst(d1)) {
+ Delete(SwigType_pop(dq1));
+ }
+ if (SwigType_isconst(d2)) {
+ Delete(SwigType_pop(dq2));
+ }
+ if (Strcmp(dq1, dq2) == 0) {
+
+ if (SwigType_isconst(d1) && !SwigType_isconst(d2)) {
+ if (script_lang_wrapping) {
+ // Swap nodes so that the const method gets ignored (shadowed by the non-const method)
+ Overloaded t = nodes[i];
+ nodes[i] = nodes[j];
+ nodes[j] = t;
+ }
+ differ = 1;
+ if (!nodes[j].error) {
+ if (script_lang_wrapping) {
+ Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n));
+ } else {
+ if (!Getattr(nodes[j].n, "overload:ignore")) {
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using %s instead.\n", Swig_name_decl(nodes[i].n));
+ }
+ }
+ }
+ nodes[j].error = 1;
+ } else if (!SwigType_isconst(d1) && SwigType_isconst(d2)) {
+ differ = 1;
+ if (!nodes[j].error) {
+ if (script_lang_wrapping) {
+ Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n));
+ } else {
+ if (!Getattr(nodes[j].n, "overload:ignore")) {
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using %s instead.\n", Swig_name_decl(nodes[i].n));
+ }
+ }
+ }
+ nodes[j].error = 1;
+ }
+ }
+ Delete(dq1);
+ Delete(dq2);
+ }
+ }
+ if (!differ) {
+ if (!nodes[j].error) {
+ if (script_lang_wrapping) {
+ Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s effectively ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "as it is shadowed by %s.\n", Swig_name_decl(nodes[i].n));
+ } else {
+ if (!Getattr(nodes[j].n, "overload:ignore")) {
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using %s instead.\n", Swig_name_decl(nodes[i].n));
+ }
+ }
+ nodes[j].error = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ List *result = NewList();
+ {
+ int i;
+ for (i = 0; i < nnodes; i++) {
+ if (nodes[i].error)
+ Setattr(nodes[i].n, "overload:ignore", "1");
+ Append(result,nodes[i].n);
+ // Printf(stdout,"[ %d ] %s\n", i, ParmList_errorstr(nodes[i].parms));
+ // Swig_print_node(nodes[i].n);
+ }
+ }
+ return result;
+}
+
+void R::dispatchFunction(Node *n) {
+ Wrapper *f = NewWrapper();
+ String *symname = Getattr(n, "sym:name");
+ String *nodeType = Getattr(n, "nodeType");
+ bool constructor = (!Cmp(nodeType, "constructor"));
+
+ String *sfname = NewString(symname);
+
+ if (constructor)
+ Replace(sfname, "new_", "", DOH_REPLACE_FIRST);
+
+ Printf(f->def,
+ "`%s` <- function(...) {", sfname);
+ if (debugMode) {
+ Swig_print_node(n);
+ }
+ List *dispatch = Swig_overload_rank(n, true);
+ int nfunc = Len(dispatch);
+ Printv(f->code,
+ "argtypes <- mapply(class, list(...));\n",
+ "argv <- list(...);\n",
+ "argc <- length(argtypes);\n", NIL );
+
+ Printf(f->code, "# dispatch functions %d\n", nfunc);
+ int cur_args = -1;
+ bool first_compare = true;
+ for (int i=0; i < nfunc; i++) {
+ Node *ni = Getitem(dispatch,i);
+ Parm *pi = Getattr(ni,"wrap:parms");
+ int num_arguments = emit_num_arguments(pi);
+
+ String *overname = Getattr(ni,"sym:overname");
+ if (cur_args != num_arguments) {
+ if (cur_args != -1) {
+ Printv(f->code, "} else ", NIL);
+ }
+ Printf(f->code, "if (argc == %d) {", num_arguments);
+ cur_args = num_arguments;
+ first_compare = true;
+ }
+ Parm *p;
+ int j;
+ if (num_arguments > 0) {
+ if (!first_compare) {
+ Printv(f->code, " else ", NIL);
+ } else {
+ first_compare = false;
+ }
+ Printv(f->code, "if (", NIL);
+ for (p =pi, j = 0 ; j < num_arguments ; j++) {
+ if (debugMode) {
+ Swig_print_node(p);
+ }
+ String *tm = Swig_typemap_lookup("rtype", p, "", 0);
+ if(tm) {
+ replaceRClass(tm, Getattr(p, "type"));
+ }
+
+ String *tmcheck = Swig_typemap_lookup("rtypecheck", p, "", 0);
+ if (tmcheck) {
+ String *tmp = NewString("");
+ Printf(tmp, "argv[[%d]]", j+1);
+ Replaceall(tmcheck, "$arg", tmp);
+ Printf(tmp, "argtype[%d]", j+1);
+ Replaceall(tmcheck, "$argtype", tmp);
+ if (tm) {
+ Replaceall(tmcheck, "$rtype", tm);
+ }
+ if (debugMode) {
+ Printf(stdout, "<rtypecheck>%s\n", tmcheck);
+ }
+ Printf(f->code, "%s(%s)",
+ j == 0 ? "" : " && ",
+ tmcheck);
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+ // Below should be migrated into rtypecheck typemaps
+ if (tm) {
+ Printf(f->code, "%s", j == 0 ? "" : " && ");
+ if (Strcmp(tm, "numeric") == 0) {
+ Printf(f->code, "is.numeric(argv[[%d]])", j+1);
+ } else if (Strcmp(tm, "integer") == 0) {
+ Printf(f->code, "(is.integer(argv[[%d]]) || is.numeric(argv[[%d]]))", j+1, j+1);
+ } else if (Strcmp(tm, "character") == 0) {
+ Printf(f->code, "is.character(argv[[%d]])", j+1);
+ } else {
+ if (SwigType_ispointer(Getattr(p, "type")))
+ Printf(f->code, "(extends(argtypes[%d], '%s') || is.null(argv[[%d]]))", j+1, tm, j+1);
+ else
+ Printf(f->code, "extends(argtypes[%d], '%s')", j+1, tm);
+ }
+ }
+ if (!SwigType_ispointer(Getattr(p, "type"))) {
+ Printf(f->code, " && length(argv[[%d]]) == 1", j+1);
+ }
+ p = Getattr(p, "tmap:in:next");
+ }
+ Printf(f->code, ") { f <- %s%s; }\n", sfname, overname);
+ } else {
+ Printf(f->code, "f <- %s%s; ", sfname, overname);
+ }
+ }
+ if (cur_args != -1) {
+ Printf(f->code, "} else {\n"
+ "stop(\"cannot find overloaded function for %s with argtypes (\","
+ "toString(argtypes),\")\");\n"
+ "}", sfname);
+ }
+ Printv(f->code, ";\nf(...)", NIL);
+ Printv(f->code, ";\n}", NIL);
+ Wrapper_print(f, sfile);
+ Printv(sfile, "# Dispatch function\n", NIL);
+ DelWrapper(f);
+}
+
+/*--------------------------------------------------------------
+
+* --------------------------------------------------------------*/
+
+int R::functionWrapper(Node *n) {
+ String *fname = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ String *type = Getattr(n, "type");
+
+ if (debugMode) {
+ Printf(stdout,
+ "<functionWrapper> %s %s %s\n", fname, iname, type);
+ }
+ String *overname = 0;
+ String *nodeType = Getattr(n, "nodeType");
+ bool constructor = (!Cmp(nodeType, "constructor"));
+ bool destructor = (!Cmp(nodeType, "destructor"));
+
+ String *sfname = NewString(iname);
+
+ if (constructor)
+ Replace(sfname, "new_", "", DOH_REPLACE_FIRST);
+
+ if (Getattr(n,"sym:overloaded")) {
+ overname = Getattr(n,"sym:overname");
+ Append(sfname, overname);
+ }
+
+ if (debugMode)
+ Printf(stdout,
+ "<functionWrapper> processing parameters\n");
+
+
+ ParmList *l = Getattr(n, "parms");
+ Parm *p;
+ String *tm;
+
+ p = l;
+ while(p) {
+ SwigType *resultType = Getattr(p, "type");
+ if (expandTypedef(resultType) &&
+ SwigType_istypedef(resultType)) {
+ SwigType *resolved =
+ SwigType_typedef_resolve_all(resultType);
+ if (expandTypedef(resolved)) {
+ if (debugMode) {
+ Printf(stdout, "Setting type: %s\n", resolved);
+ }
+ Setattr(p, "type", Copy(resolved));
+ }
+ }
+ p = nextSibling(p);
+ }
+
+ String *unresolved_return_type =
+ Copy(type);
+ if (expandTypedef(type) &&
+ SwigType_istypedef(type)) {
+ SwigType *resolved =
+ SwigType_typedef_resolve_all(type);
+ if (debugMode)
+ Printf(stdout, "<functionWrapper> resolved %s\n", Copy(unresolved_return_type));
+ if (expandTypedef(resolved)) {
+ type = Copy(resolved);
+ Setattr(n, "type", type);
+ }
+ }
+ if (debugMode)
+ Printf(stdout, "<functionWrapper> unresolved_return_type %s\n", unresolved_return_type);
+ if(processing_member_access_function) {
+ if (debugMode)
+ Printf(stdout, "<functionWrapper memberAccess> '%s' '%s' '%s' '%s'\n", fname, iname, member_name, class_name);
+
+ if(opaqueClassDeclaration)
+ return SWIG_OK;
+
+
+ /* Add the name of this member to a list for this class_name.
+ We will dump all these at the end. */
+
+ bool isSet(GetFlag(n, "memberset"));
+
+ String *tmp = NewString(isSet ? Swig_name_set(NSPACE_TODO, class_name) : Swig_name_get(NSPACE_TODO, class_name));
+
+ List *memList = Getattr(ClassMemberTable, tmp);
+ if(!memList) {
+ memList = NewList();
+ Append(memList, class_name);
+ Setattr(ClassMemberTable, tmp, memList);
+ }
+ Delete(tmp);
+ Append(memList, member_name);
+ Append(memList, iname);
+ }
+
+ int i;
+ int nargs;
+
+ String *wname = Swig_name_wrapper(iname);
+
+ if(overname)
+ Append(wname, overname);
+ Setattr(n,"wrap:name", wname);
+
+ Wrapper *f = NewWrapper();
+ Wrapper *sfun = NewWrapper();
+
+ int isVoidReturnType = (Strcmp(type, "void") == 0);
+ // Need to use the unresolved return type since
+ // typedef resolution removes the const which causes a
+ // mismatch with the function action
+ emit_return_variable(n, unresolved_return_type, f);
+
+ SwigType *rtype = Getattr(n, "type");
+ int addCopyParam = 0;
+
+ if(!isVoidReturnType)
+ addCopyParam = addCopyParameter(rtype);
+
+ if (debugMode)
+ Printf(stdout, "Adding a .copy argument to %s for %s = %s\n",
+ iname, type, addCopyParam ? "yes" : "no");
+
+ Printv(f->def, "SWIGEXPORT SEXP\n", wname, " ( ", NIL);
+
+ Printf(sfun->def, "# Start of %s\n", iname);
+ Printv(sfun->def, "\n`", sfname, "` = function(", NIL);
+
+ if(outputNamespaceInfo) {//XXX Need to be a little more discriminating
+ if (constructor) {
+ String *niname = Copy(iname);
+ Replace(niname, "new_", "", DOH_REPLACE_FIRST);
+ addNamespaceFunction(niname);
+ Delete(niname);
+ } else {
+ addNamespaceFunction(iname);
+ }
+ }
+
+ Swig_typemap_attach_parms("scoercein", l, f);
+ Swig_typemap_attach_parms("scoerceout", l, f);
+ Swig_typemap_attach_parms("scheck", l, f);
+
+ emit_parameter_variables(l, f);
+ emit_attach_parmmaps(l,f);
+ Setattr(n,"wrap:parms",l);
+
+ nargs = emit_num_arguments(l);
+
+ Wrapper_add_local(f, "r_nprotect", "unsigned int r_nprotect = 0");
+ Wrapper_add_localv(f, "r_ans", "SEXP", "r_ans = R_NilValue", NIL);
+ Wrapper_add_localv(f, "r_vmax", "VMAXTYPE", "r_vmax = vmaxget()", NIL);
+
+ String *sargs = NewString("");
+
+
+ String *s_inputTypes = NewString("");
+ String *s_inputMap = NewString("");
+ bool inFirstArg = true;
+ bool inFirstType = true;
+ Parm *curP;
+ for (p =l, i = 0 ; i < nargs ; i++) {
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *tt = Getattr(p, "type");
+ int nargs = -1;
+ String *funcptr_name = processType(tt, p, &nargs);
+
+ // SwigType *tp = Getattr(p, "type");
+ String *name = Getattr(p,"name");
+ String *lname = Getattr(p,"lname");
+
+ // R keyword renaming
+ if (name) {
+ if (Swig_name_warning(p, 0, name, 0)) {
+ name = 0;
+ } else {
+ /* If we have a :: in the parameter name because we are accessing a static member of a class, say, then
+ we need to remove that prefix. */
+ while (Strstr(name, "::")) {
+ //XXX need to free.
+ name = NewStringf("%s", Strchr(name, ':') + 2);
+ if (debugMode)
+ Printf(stdout, "+++ parameter name with :: in it %s\n", name);
+ }
+ }
+ }
+ if (!name || Len(name) == 0)
+ name = NewStringf("s_arg%d", i+1);
+
+ name = replaceInitialDash(name);
+
+ if (!Strncmp(name, "arg", 3)) {
+ name = Copy(name);
+ Insert(name, 0, "s_");
+ }
+
+ if(processing_variable) {
+ name = Copy(name);
+ Insert(name, 0, "s_");
+ }
+
+ if(!Strcmp(name, fname)) {
+ name = Copy(name);
+ Insert(name, 0, "s_");
+ }
+
+ Printf(sargs, "%s, ", name);
+
+ String *tm;
+ if((tm = Getattr(p, "tmap:scoercein"))) {
+ Replaceall(tm, "$input", name);
+ replaceRClass(tm, Getattr(p, "type"));
+
+ if(funcptr_name) {
+ //XXX need to get this to return non-zero
+ if(nargs == -1)
+ nargs = getFunctionPointerNumArgs(p, tt);
+
+ String *snargs = NewStringf("%d", nargs);
+ Printv(sfun->code, "if(is.function(", name, ")) {", "\n",
+ "assert('...' %in% names(formals(", name,
+ ")) || length(formals(", name, ")) >= ", snargs, ");\n} ", NIL);
+ Delete(snargs);
+
+ Printv(sfun->code, "else {\n",
+ "if(is.character(", name, ")) {\n",
+ name, " = getNativeSymbolInfo(", name, ");",
+ "\n};\n",
+ "if(is(", name, ", \"NativeSymbolInfo\")) {\n",
+ name, " = ", name, "$address", ";\n};\n",
+ "if(is(", name, ", \"ExternalReference\")) {\n",
+ name, " = ", name, "@ref;\n}\n",
+ "}; \n",
+ NIL);
+ } else {
+ Printf(sfun->code, "%s\n", tm);
+ }
+ }
+
+ Printv(sfun->def, inFirstArg ? "" : ", ", name, NIL);
+
+ if ((tm = Getattr(p,"tmap:scheck"))) {
+
+ Replaceall(tm,"$target", lname);
+ Replaceall(tm,"$source", name);
+ Replaceall(tm,"$input", name);
+ replaceRClass(tm, Getattr(p, "type"));
+ Printf(sfun->code,"%s\n",tm);
+ }
+
+
+
+ curP = p;
+ if ((tm = Getattr(p,"tmap:in"))) {
+
+ Replaceall(tm,"$target", lname);
+ Replaceall(tm,"$source", name);
+ Replaceall(tm,"$input", name);
+
+ if (Getattr(p,"wrap:disown") || (Getattr(p,"tmap:in:disown"))) {
+ Replaceall(tm,"$disown","SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm,"$disown","0");
+ }
+
+ if(funcptr_name) {
+ /* have us a function pointer */
+ Printf(f->code, "if(TYPEOF(%s) != CLOSXP) {\n", name);
+ Replaceall(tm,"$R_class", "");
+ } else {
+ replaceRClass(tm, Getattr(p, "type"));
+ }
+
+
+ Printf(f->code,"%s\n",tm);
+ if(funcptr_name)
+ Printf(f->code, "} else {\n%s = %s;\nR_SWIG_pushCallbackFunctionData(%s, NULL);\n}\n",
+ lname, funcptr_name, name);
+ Printv(f->def, inFirstArg ? "" : ", ", "SEXP ", name, NIL);
+ if (Len(name) != 0)
+ inFirstArg = false;
+ p = Getattr(p,"tmap:in:next");
+
+ } else {
+ p = nextSibling(p);
+ }
+
+
+ tm = Swig_typemap_lookup("rtype", curP, "", 0);
+ if(tm) {
+ replaceRClass(tm, Getattr(curP, "type"));
+ }
+ Printf(s_inputTypes, "%s'%s'", inFirstType ? "" : ", ", tm);
+ Printf(s_inputMap, "%s%s='%s'", inFirstType ? "" : ", ", name, tm);
+ inFirstType = false;
+
+ if(funcptr_name)
+ Delete(funcptr_name);
+ } /* end of looping over parameters. */
+
+ if(addCopyParam) {
+ Printf(sfun->def, "%s.copy = FALSE", nargs > 0 ? ", " : "");
+ Printf(f->def, "%sSEXP s_swig_copy", nargs > 0 ? ", " : "");
+
+ Printf(sargs, "as.logical(.copy), ");
+ }
+
+ Printv(f->def, ")\n{\n", NIL);
+ Printv(sfun->def, ")\n{\n", NIL);
+
+
+ /* Insert cleanup code */
+ String *cleanup = NewString("");
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+ if (tm && (Len(tm) != 0)) {
+ Printv(cleanup, tm, "\n", NIL);
+ }
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ String *outargs = NewString("");
+ int numOutArgs = isVoidReturnType ? -1 : 0;
+ for(p = l, i = 0; p; i++) {
+ if((tm = Getattr(p, "tmap:argout"))) {
+ // String *lname = Getattr(p, "lname");
+ numOutArgs++;
+ String *pos = NewStringf("%d", numOutArgs);
+ Replaceall(tm,"$source", Getattr(p, "lname"));
+ Replaceall(tm,"$result", "r_ans");
+ Replaceall(tm,"$n", pos); // The position into which to store the answer.
+ Replaceall(tm,"$arg", Getattr(p, "emit:input"));
+ Replaceall(tm,"$input", Getattr(p, "emit:input"));
+ Replaceall(tm,"$owner", "0");
+
+
+ Printf(outargs, "%s\n", tm);
+ p = Getattr(p,"tmap:argout:next");
+ } else
+ p = nextSibling(p);
+ }
+
+ String *actioncode = emit_action(n);
+
+ /* Deal with the explicit return value. */
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ SwigType *retType = Getattr(n, "type");
+
+ Replaceall(tm,"$1", Swig_cresult_name());
+ Replaceall(tm,"$result", "r_ans");
+ if (debugMode){
+ Printf(stdout, "Calling replace D: %s, %s, %s\n", retType, n, tm);
+ }
+ replaceRClass(tm, retType);
+
+ if (GetFlag(n,"feature:new")) {
+ Replaceall(tm, "$owner", "SWIG_POINTER_OWN");
+ } else {
+ Replaceall(tm,"$owner", "0");
+ }
+
+ Printf(f->code, "%s\n", tm);
+
+ } 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), fname);
+ }
+
+
+ if(Len(outargs)) {
+ Wrapper_add_local(f, "R_OutputValues", "SEXP R_OutputValues");
+
+ String *tmp = NewString("");
+ if(!isVoidReturnType)
+ Printf(tmp, "Rf_protect(r_ans);\n");
+
+ Printf(tmp, "Rf_protect(R_OutputValues = Rf_allocVector(VECSXP,%d));\nr_nprotect += %d;\n",
+ numOutArgs + !isVoidReturnType,
+ isVoidReturnType ? 1 : 2);
+
+ if(!isVoidReturnType)
+ Printf(tmp, "SET_VECTOR_ELT(R_OutputValues, 0, r_ans);\n");
+ Printf(tmp, "r_ans = R_OutputValues;\n");
+
+ Insert(outargs, 0, tmp);
+ Delete(tmp);
+
+
+
+ Printv(f->code, outargs, NIL);
+ Delete(outargs);
+
+ }
+
+ /* Output cleanup code */
+ int need_cleanup = Len(cleanup) != 0;
+ if (need_cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+
+ /* Look to see if there is any newfree cleanup code */
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+
+ Printv(f->code, UnProtectWrapupCode, NIL);
+
+ /*If the user gave us something to convert the result in */
+ if ((tm = Swig_typemap_lookup("scoerceout", n, Swig_cresult_name(), sfun))) {
+ Replaceall(tm,"$source","ans");
+ Replaceall(tm,"$result","ans");
+ if (constructor) {
+ Node * parent = Getattr(n, "parentNode");
+ String * smartname = Getattr(parent, "feature:smartptr");
+ if (smartname) {
+ smartname = getRClassName(smartname, 1, 1);
+ Replaceall(tm, "$R_class", smartname);
+ Delete(smartname);
+ }
+ }
+ if (debugMode) {
+ Printf(stdout, "Calling replace B: %s, %s, %s\n", Getattr(n, "type"), Getattr(n, "sym:name"), getNSpace());
+ }
+ replaceRClass(tm, Getattr(n, "type"));
+ Chop(tm);
+ }
+
+
+ Printv(sfun->code, ";", (Len(tm) ? "ans = " : ""), ".Call('", wname,
+ "', ", sargs, "PACKAGE='", Rpackage, "');\n", NIL);
+ if(Len(tm))
+ {
+ Printf(sfun->code, "%s\n\n", tm);
+ if (constructor)
+ {
+ String *finalizer = NewString(iname);
+ Replace(finalizer, "new_", "", DOH_REPLACE_FIRST);
+ Printf(sfun->code, "reg.finalizer(ans@ref, delete_%s);\n", finalizer);
+ }
+ Printf(sfun->code, "ans\n");
+ }
+
+ if (destructor)
+ Printv(f->code, "R_ClearExternalPtr(self);\n", NIL);
+
+ Printv(f->code, "return r_ans;\n", NIL);
+
+ /* Error handling code */
+ Printv(f->code, "fail: SWIGUNUSED;\n", NIL);
+ if (need_cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+ Printv(f->code, " Rf_error(\"%s %s\", SWIG_ErrorType(SWIG_lasterror_code), SWIG_lasterror_msg);\n", NIL);
+ Printv(f->code, " return R_NilValue;\n", NIL);
+ Delete(cleanup);
+
+ Printv(f->code, "}\n", NIL);
+ Printv(sfun->code, "\n}", NIL);
+
+ /* Substitute the function name */
+ Replaceall(f->code,"$symname",iname);
+
+ Wrapper_print(f, f_wrapper);
+ Wrapper_print(sfun, sfile);
+
+ Printf(sfun->code, "\n# End of %s\n", iname);
+ tm = Swig_typemap_lookup("rtype", n, "", 0);
+ if(tm) {
+ SwigType *retType = Getattr(n, "type");
+ if (debugMode) {
+ Printf(stdout, "Calling replace C: %s\n", Copy(retType));
+ }
+ replaceRClass(tm, retType);
+ }
+
+ Printv(sfile, "attr(`", sfname, "`, 'returnType') = '",
+ isVoidReturnType ? "void" : (tm ? tm : ""),
+ "'\n", NIL);
+
+ if(nargs > 0)
+ Printv(sfile, "attr(`", sfname, "`, \"inputTypes\") = c(",
+ s_inputTypes, ")\n", NIL);
+ Printv(sfile, "class(`", sfname, "`) = c(\"SWIGFunction\", class('",
+ sfname, "'))\n\n", NIL);
+
+ if (memoryProfile) {
+ Printv(sfile, "memory.profile()\n", NIL);
+ }
+ if (aggressiveGc) {
+ Printv(sfile, "gc()\n", NIL);
+ }
+
+ // Printv(sfile, "setMethod('", name, "', '", name, "', ", iname, ")\n\n\n");
+
+
+
+ /* If we are dealing with a method in an C++ class, then
+ add the name of the R function and its definition.
+ XXX need to figure out how to store the Wrapper if possible in the hash/list.
+ Would like to be able to do this so that we can potentially insert
+ */
+ if(processing_member_access_function || processing_class_member_function) {
+ String *method_type = R_MEMBER_NORMAL;
+ if (GetFlag(n, "memberset")) {
+ method_type = R_MEMBER_SET;
+ } else if (GetFlag(n, "memberget")) {
+ method_type = R_MEMBER_GET;
+ }
+ addAccessor(member_name, sfun, iname, method_type);
+ }
+
+ if (Getattr(n, "sym:overloaded") &&
+ !Getattr(n, "sym:nextSibling")) {
+ dispatchFunction(n);
+ }
+
+ addRegistrationRoutine(wname, addCopyParam ? nargs +1 : nargs);
+
+ DelWrapper(f);
+ DelWrapper(sfun);
+
+ Delete(sargs);
+ Delete(sfname);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * R::constantWrapper()
+ * ---------------------------------------------------------------------- */
+
+int R::constantWrapper(Node *n) {
+ (void) n;
+ // TODO
+ return SWIG_OK;
+}
+
+/*--------------------------------------------------------------
+ * Add the specified routine name to the collection of
+ * generated routines that are called from R functions.
+ * This is used to register the routines with R for
+ * resolving symbols.
+
+ * rname - the name of the routine
+ * nargs - the number of arguments it expects.
+ * --------------------------------------------------------------*/
+
+int R::addRegistrationRoutine(String *rname, int nargs) {
+ if(!registrationTable)
+ registrationTable = NewHash();
+
+ String *el =
+ NewStringf("{\"%s\", (DL_FUNC) &%s, %d}", rname, rname, nargs);
+
+ Setattr(registrationTable, rname, el);
+
+ return SWIG_OK;
+}
+
+/* -------------------------------------------------------------
+ * Write the registration information to an array and
+ * create the initialization routine for registering
+ * these.
+ * --------------------------------------------------------------*/
+
+int R::outputRegistrationRoutines(File *out) {
+ int i, n;
+ if(!registrationTable)
+ return(0);
+ if(inCPlusMode)
+ Printf(out, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n");
+
+ Printf(out, "#include <R_ext/Rdynload.h>\n\n");
+ if(inCPlusMode)
+ Printf(out, "#ifdef __cplusplus\n}\n#endif\n\n");
+
+ Printf(out, "SWIGINTERN R_CallMethodDef CallEntries[] = {\n");
+
+ List *keys = Keys(registrationTable);
+ n = Len(keys);
+ for(i = 0; i < n; i++)
+ Printf(out, " %s,\n", Getattr(registrationTable, Getitem(keys, i)));
+
+ Printf(out, " {NULL, NULL, 0}\n};\n\n");
+
+ if(!noInitializationCode) {
+ if (inCPlusMode)
+ Printv(out, "extern \"C\" ", NIL);
+ { /* R allows pckage names to have '.' in the name, which is not allowed in C++ var names
+ we simply replace all occurrences of '.' with '_' to construct the var name */
+ String * Rpackage_sane = Copy(Rpackage);
+ Replace(Rpackage_sane, ".", "_", DOH_REPLACE_ANY);
+ Printf(out, "SWIGEXPORT void R_init_%s(DllInfo *dll) {\n", Rpackage_sane);
+ Delete(Rpackage_sane);
+ }
+ Printf(out, "%sR_registerRoutines(dll, NULL, CallEntries, NULL, NULL);\n", tab4);
+ if(Len(s_init_routine)) {
+ Printf(out, "\n%s\n", s_init_routine);
+ }
+ Printf(out, "}\n");
+ }
+
+ return n;
+}
+
+
+
+/* -------------------------------------------------------------
+ * Process a struct, union or class declaration in the source code,
+ * or an anonymous typedef struct
+ * --------------------------------------------------------------*/
+
+//XXX What do we need to do here -
+// Define an S4 class to refer to this.
+
+void R::registerClass(Node *n) {
+ String *name = Getattr(n, "name");
+ String *kind = Getattr(n, "kind");
+
+ if (debugMode)
+ Swig_print_node(n);
+ String *sname = NewStringf("_p%s", SwigType_manglestr(name));
+ if(!Getattr(SClassDefs, sname)) {
+ Setattr(SClassDefs, sname, sname);
+ String *base;
+
+ if(Strcmp(kind, "class") == 0) {
+ base = NewString("");
+ List *l = Getattr(n, "bases");
+ if(Len(l)) {
+ Printf(base, "c(");
+ for(int i = 0; i < Len(l); i++) {
+ registerClass(Getitem(l, i));
+ Printf(base, "'_p%s'%s",
+ SwigType_manglestr(Getattr(Getitem(l, i), "name")),
+ i < Len(l)-1 ? ", " : "");
+ }
+ Printf(base, ")");
+ } else {
+ base = NewString("'C++Reference'");
+ }
+ } else
+ base = NewString("'ExternalReference'");
+
+ Printf(s_classes, "setClass('%s', contains = %s)\n", sname, base);
+ Delete(base);
+ String *smartptr = Getattr(n, "feature:smartptr");
+ if (smartptr) {
+ List *l = Getattr(n, "bases");
+ SwigType *spt = Swig_cparse_type(smartptr);
+ String *smart = SwigType_typedef_resolve_all(spt);
+ String *smart_rname = SwigType_manglestr(smart);
+ Printf(s_classes, "setClass('_p%s', contains = c('%s'", smart_rname, sname);
+ Delete(spt);
+ Delete(smart);
+ Delete(smart_rname);
+ for(int i = 0; i < Len(l); i++) {
+ Node * b = Getitem(l, i);
+ smartptr = Getattr(b, "feature:smartptr");
+ if (smartptr) {
+ spt = Swig_cparse_type(smartptr);
+ smart = SwigType_typedef_resolve_all(spt);
+ smart_rname = SwigType_manglestr(smart);
+ Printf(s_classes, ", '_p%s'", smart_rname);
+ Delete(spt);
+ Delete(smart);
+ Delete(smart_rname);
+ }
+ }
+ Printf(s_classes, "))\n");
+ }
+ }
+}
+
+int R::classDeclaration(Node *n) {
+
+ String *name = Getattr(n, "name");
+ String *kind = Getattr(n, "kind");
+
+ if (debugMode)
+ Swig_print_node(n);
+ registerClass(n);
+
+
+ /* If we have a typedef union { ... } U, then we never get to see the typedef
+ via a regular call to typedefHandler. Instead, */
+ if(Getattr(n, "unnamed") && Getattr(n, "storage") && Strcmp(Getattr(n, "storage"), "typedef") == 0
+ && Getattr(n, "tdname") && Strcmp(Getattr(n, "tdname"), name) == 0) {
+ if (debugMode)
+ Printf(stdout, "Typedef in the class declaration for %s\n", name);
+ // typedefHandler(n);
+ }
+
+ bool opaque = GetFlag(n, "feature:opaque") ? true : false;
+
+ if(opaque)
+ opaqueClassDeclaration = name;
+
+ int status = Language::classDeclaration(n);
+
+ opaqueClassDeclaration = NULL;
+
+
+ if (class_member_function_types) {
+
+ // collect the "set" methods
+ List *class_set_membernames = filterMemberList(class_member_function_types,
+ class_member_function_membernames, R_MEMBER_SET, true);
+ List *class_set_functionnames = filterMemberList(class_member_function_types,
+ class_member_function_names, R_MEMBER_SET, true);
+ // this one isn't used - collecting to keep code simpler
+ List *class_set_functiontypes = filterMemberList(class_member_function_types,
+ class_member_function_types, R_MEMBER_SET, true);
+
+ // collect the others
+ List *class_other_membernames = filterMemberList(class_member_function_types,
+ class_member_function_membernames, R_MEMBER_SET, false);
+ List *class_other_functionnames = filterMemberList(class_member_function_types,
+ class_member_function_names, R_MEMBER_SET, false);
+ List *class_other_functiontypes = filterMemberList(class_member_function_types,
+ class_member_function_types, R_MEMBER_SET, false);
+
+ if (Len(class_other_membernames) > 0) {
+ OutputMemberReferenceMethod(name, 0, class_other_membernames, class_other_functionnames, class_other_functiontypes, sfile);
+ }
+ if (Len(class_set_membernames) > 0) {
+ OutputMemberReferenceMethod(name, 1, class_set_membernames, class_set_functionnames, class_set_functiontypes, sfile);
+ }
+ Delete(class_set_membernames);
+ Delete(class_set_functionnames);
+ Delete(class_set_functiontypes);
+ Delete(class_other_membernames);
+ Delete(class_other_functionnames);
+ Delete(class_other_functiontypes);
+ }
+
+ if (class_member_function_types) {
+ Delete(class_member_function_types);
+ class_member_function_types = NULL;
+ Delete(class_member_function_names);
+ class_member_function_names = NULL;
+ Delete(class_member_function_membernames);
+ class_member_function_membernames = NULL;
+ Delete(class_member_function_wrappernames);
+ class_member_function_wrappernames = NULL;
+ }
+ if (Getattr(n, "has_destructor")) {
+ Printf(sfile, "setMethod('delete', '_p%s', function(obj) {delete%s(obj)})\n", getRClassName(name), getRClassName(name));
+
+ }
+ if(!opaque && !Strcmp(kind, "struct") && copyStruct) {
+
+ String *def =
+ NewStringf("setClass(\"%s\",\n%srepresentation(\n", name, tab4);
+ bool firstItem = true;
+
+ for(Node *c = firstChild(n); c; ) {
+ String *elName;
+ String *tp;
+
+ elName = Getattr(c, "name");
+
+ String *elKind = Getattr(c, "kind");
+ if (!Equal(elKind, "variable")) {
+ c = nextSibling(c);
+ continue;
+ }
+ if (!Len(elName)) {
+ c = nextSibling(c);
+ continue;
+ }
+ tp = Swig_typemap_lookup("rtype", c, "", 0);
+ if(!tp) {
+ c = nextSibling(c);
+ continue;
+ }
+ if (Strstr(tp, "R_class")) {
+ c = nextSibling(c);
+ continue;
+ }
+ if (Strcmp(tp, "character") &&
+ Strstr(Getattr(c, "decl"), "p.")) {
+ c = nextSibling(c);
+ continue;
+ }
+
+ if (!firstItem) {
+ Printf(def, ",\n");
+ }
+ // else
+ //XXX How can we tell if this is already done.
+ // SwigType_push(elType, elDecl);
+
+
+ // returns "" tp = processType(elType, c, NULL);
+ // Printf(stdout, "<classDeclaration> elType %p\n", elType);
+ // tp = getRClassNameCopyStruct(Getattr(c, "type"), 1);
+
+ String *elNameT = replaceInitialDash(elName);
+ Printf(def, "%s%s = \"%s\"", tab8, elNameT, tp);
+ firstItem = false;
+ Delete(tp);
+ Delete(elNameT);
+ c = nextSibling(c);
+ }
+ Printf(def, "),\n%scontains = \"RSWIGStruct\")\n", tab8);
+ Printf(s_classes, "%s\n\n# End class %s\n\n", def, name);
+
+ generateCopyRoutines(n);
+
+ Delete(def);
+ }
+
+ return status;
+}
+
+
+
+/* -------------------------------------------------------------
+ * Create the C routines that copy an S object of the class given
+ * by the given struct definition in Node *n to the C value
+ * and also the routine that goes from the C routine to an object
+ * of this S class.
+ * --------------------------------------------------------------*/
+
+/*XXX
+ Clean up the toCRef - make certain the names are correct for the types, etc.
+ in all cases.
+*/
+
+int R::generateCopyRoutines(Node *n) {
+ Wrapper *copyToR = NewWrapper();
+ Wrapper *copyToC = NewWrapper();
+
+ String *name = Getattr(n, "name");
+ String *tdname = Getattr(n, "tdname");
+ String *kind = Getattr(n, "kind");
+ String *type;
+
+ if(Len(tdname)) {
+ type = Copy(tdname);
+ } else {
+ type = NewStringf("%s %s", kind, name);
+ }
+
+ String *mangledName = SwigType_manglestr(name);
+
+ if (debugMode)
+ Printf(stdout, "generateCopyRoutines: name = %s, %s\n", name, type);
+
+ Printf(copyToR->def, "CopyToR%s = function(value, obj = new(\"%s\"))\n{\n",
+ mangledName, name);
+ Printf(copyToC->def, "CopyToC%s = function(value, obj)\n{\n",
+ mangledName);
+
+ Node *c = firstChild(n);
+
+ for(; c; c = nextSibling(c)) {
+ String *elName = Getattr(c, "name");
+ if (!Len(elName)) {
+ continue;
+ }
+ String *elKind = Getattr(c, "kind");
+ if (!Equal(elKind, "variable")) {
+ continue;
+ }
+
+ String *tp = Swig_typemap_lookup("rtype", c, "", 0);
+ if(!tp) {
+ continue;
+ }
+ if (Strstr(tp, "R_class")) {
+ continue;
+ }
+ if (Strcmp(tp, "character") &&
+ Strstr(Getattr(c, "decl"), "p.")) {
+ continue;
+ }
+
+
+ /* The S functions to get and set the member value. */
+ String *elNameT = replaceInitialDash(elName);
+ Printf(copyToR->code, "obj@%s = value$%s;\n", elNameT, elNameT);
+ Printf(copyToC->code, "obj$%s = value@%s;\n", elNameT, elNameT);
+ Delete(elNameT);
+ }
+ Printf(copyToR->code, "obj;\n}\n\n");
+ String *rclassName = getRClassNameCopyStruct(type, 0); // without the Ref.
+ Printf(sfile, "# Start definition of copy functions & methods for %s\n", rclassName);
+
+ Wrapper_print(copyToR, sfile);
+ Printf(copyToC->code, "obj\n}\n\n");
+ Wrapper_print(copyToC, sfile);
+
+
+ Printf(sfile, "# Start definition of copy methods for %s\n", rclassName);
+ Printf(sfile, "setMethod('copyToR', '_p_%s', CopyToR%s);\n", rclassName,
+ mangledName);
+ Printf(sfile, "setMethod('copyToC', '%s', CopyToC%s);\n\n", rclassName,
+ mangledName);
+
+ Printf(sfile, "# End definition of copy methods for %s\n", rclassName);
+ Printf(sfile, "# End definition of copy functions & methods for %s\n", rclassName);
+
+ String *m = NewStringf("%sCopyToR", name);
+ addNamespaceMethod(m);
+ char *tt = Char(m); tt[Len(m)-1] = 'C';
+ addNamespaceMethod(m);
+ Delete(m);
+ Delete(rclassName);
+ Delete(mangledName);
+ DelWrapper(copyToR);
+ DelWrapper(copyToC);
+
+ return SWIG_OK;
+}
+
+
+
+/* -------------------------------------------------------------
+ * Called when there is a typedef to be invoked.
+ *
+ * XXX Needs to be enhanced or split to handle the case where we have a
+ * typedef within a classDeclaration emission because the struct/union/etc.
+ * is anonymous.
+ * --------------------------------------------------------------*/
+
+int R::typedefHandler(Node *n) {
+ SwigType *tp = Getattr(n, "type");
+ String *type = Getattr(n, "type");
+ if (debugMode)
+ Printf(stdout, "<typedefHandler> %s\n", Getattr(n, "name"));
+
+ processType(tp, n);
+
+ if(Strncmp(type, "struct ", 7) == 0) {
+ String *name = Getattr(n, "name");
+ char *trueName = Char(type);
+ trueName += 7;
+ if (debugMode)
+ Printf(stdout, "<typedefHandler> Defining S class %s\n", trueName);
+ Printf(s_classes, "setClass('_p%s', contains = 'ExternalReference')\n",
+ SwigType_manglestr(name));
+ }
+
+ return Language::typedefHandler(n);
+}
+
+
+
+/* --------------------------------------------------------------
+ * Called when processing a field in a "class", i.e. struct, union or
+ * actual class. We set a state variable so that we can correctly
+ * interpret the resulting functionWrapper() call and understand that
+ * it is for a field element.
+ * --------------------------------------------------------------*/
+
+int R::membervariableHandler(Node *n) {
+ SwigType *t = Getattr(n, "type");
+ processType(t, n, NULL);
+ processing_member_access_function = 1;
+ member_name = Getattr(n,"sym:name");
+ if (debugMode)
+ Printf(stdout, "<membervariableHandler> name = %s, sym:name = %s\n",
+ Getattr(n, "name"), member_name);
+
+ int status(Language::membervariableHandler(n));
+
+ if(!opaqueClassDeclaration && debugMode)
+ Printf(stdout, "<membervariableHandler> %s %s\n", Getattr(n, "name"), Getattr(n, "type"));
+
+ processing_member_access_function = 0;
+ member_name = NULL;
+
+ return status;
+}
+
+
+/*
+ This doesn't seem to get used so leave it out for the moment.
+*/
+String * R::runtimeCode() {
+ String *s = Swig_include_sys("rrun.swg");
+ if (!s) {
+ Printf(stdout, "*** Unable to open 'rrun.swg'\n");
+ s = NewString("");
+ }
+ return s;
+}
+
+
+/* -----------------------------------------------------------------------
+ * Called when SWIG wants to initialize this
+ * We initialize anythin we want here.
+ * Most importantly, tell SWIG where to find the files (e.g. r.swg) for this module.
+ * Use Swig_mark_arg() to tell SWIG that it is understood and not to
+ * throw an error.
+ * --------------------------------------------------------------*/
+
+void R::main(int argc, char *argv[]) {
+ init();
+ Preprocessor_define("SWIGR 1", 0);
+ SWIG_library_directory("r");
+ SWIG_config_file("r.swg");
+ debugMode = false;
+ copyStruct = true;
+ memoryProfile = false;
+ aggressiveGc = false;
+ inCPlusMode = false;
+ outputNamespaceInfo = false;
+ noInitializationCode = false;
+
+ this->Argc = argc;
+ this->Argv = argv;
+
+ allow_overloading();// can we support this?
+
+ for(int i = 0; i < argc; i++) {
+ if(strcmp(argv[i], "-package") == 0) {
+ Swig_mark_arg(i);
+ i++;
+ Swig_mark_arg(i);
+ Rpackage = argv[i];
+ } else if(strcmp(argv[i], "-dll") == 0) {
+ Swig_mark_arg(i);
+ i++;
+ Swig_mark_arg(i);
+ DllName = argv[i];
+ } else if(strcmp(argv[i], "-help") == 0) {
+ showUsage();
+ } else if(strcmp(argv[i], "-namespace") == 0) {
+ outputNamespaceInfo = true;
+ Swig_mark_arg(i);
+ } else if(!strcmp(argv[i], "-no-init-code")) {
+ noInitializationCode = true;
+ Swig_mark_arg(i);
+ } else if(!strcmp(argv[i], "-c++")) {
+ inCPlusMode = true;
+ Swig_mark_arg(i);
+ Printf(s_classes, "setClass('C++Reference', contains = 'ExternalReference')\n");
+ } else if(!strcmp(argv[i], "-debug")) {
+ debugMode = true;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i],"-copystruct")) {
+ copyStruct = true;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i], "-nocopystruct")) {
+ copyStruct = false;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i], "-memoryprof")) {
+ memoryProfile = true;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i], "-nomemoryprof")) {
+ memoryProfile = false;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i], "-aggressivegc")) {
+ aggressiveGc = true;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i], "-noaggressivegc")) {
+ aggressiveGc = false;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-cppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]);
+ Swig_mark_arg(i);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ if (debugMode) {
+ Swig_typemap_search_debug_set();
+ Swig_typemap_used_debug_set();
+ Swig_typemap_register_debug_set();
+ Swig_file_debug_set();
+ }
+ /// copyToR copyToC functions.
+
+ }
+}
+
+/* -----------------------------------------------------------------------
+ * Could make this work for String or File and then just store the resulting string
+ * rather than the collection of arguments and argc.
+ * ----------------------------------------------------------------------- */
+int R::outputCommandLineArguments(File *out)
+{
+ if(Argc < 1 || !Argv || !Argv[0])
+ return(-1);
+
+ Printf(out, "\n## Generated via the command line invocation:\n##\t");
+ for(int i = 0; i < Argc ; i++) {
+ Printf(out, " %s", Argv[i]);
+ }
+ Printf(out, "\n\n\n");
+
+ return Argc;
+}
+
+
+
+/* How SWIG instantiates an object from this module.
+ See swigmain.cxx */
+extern "C"
+Language *swig_r(void) {
+ return new R();
+}
+
+
+
+
+/* -----------------------------------------------------------------------
+ * Needs to be reworked.
+ *----------------------------------------------------------------------- */
+String * R::processType(SwigType *t, Node *n, int *nargs) {
+ //XXX Need to handle typedefs, e.g.
+ // a type which is a typedef to a function pointer.
+
+ SwigType *tmp = Getattr(n, "tdname");
+ if (debugMode)
+ Printf(stdout, "processType %s (tdname = %s)(SwigType = %s)\n", Getattr(n, "name"), tmp, Copy(t));
+
+ SwigType *td = t;
+ if (expandTypedef(t) &&
+ SwigType_istypedef(t)) {
+ SwigType *resolved =
+ SwigType_typedef_resolve_all(t);
+ if (expandTypedef(resolved)) {
+ td = Copy(resolved);
+ }
+ }
+
+ if(!td) {
+ int count = 0;
+ String *b = getRTypeName(t, &count);
+ if(count && b && !Getattr(SClassDefs, b)) {
+ if (debugMode)
+ Printf(stdout, "<processType> Defining class %s\n", b);
+
+ Printf(s_classes, "setClass('%s', contains = 'ExternalReference')\n", b);
+ Setattr(SClassDefs, b, b);
+ }
+
+ }
+
+
+ if(td)
+ t = td;
+
+ if(SwigType_isfunctionpointer(t)) {
+ if (debugMode)
+ Printf(stdout,
+ "<processType> Defining pointer handler %s\n", t);
+
+ String *tmp = createFunctionPointerHandler(t, n, nargs);
+ return tmp;
+ }
+
+ return NULL;
+}
+
+
+/* -----------------------------------------------------------------------
+ * enumValue()
+ * This method will return a string with an enum value to use in from R when
+ * setting up an enum variable
+ * ------------------------------------------------------------------------ */
+
+String *R::enumValue(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ String *value = Getattr(n, "value");
+ String *newsymname = 0;
+
+ Node *parent = parentNode(n);
+ symname = Getattr(n, "sym:name");
+
+ // parent enumtype has namespace mangled in
+ String *etype = Getattr(parent, "enumtype");
+ // we have to directly call the c wrapper function, as the
+ // R wrapper to the enum is designed to be used after the enum
+ // structures have been created on the R side. This means
+ // that we'll need to construct a .Call expression
+
+ // change the type for variableWrapper
+ if (debugMode) {
+ Printf(stdout, "<enumValue> type set: %s\n", etype);
+ }
+
+ Setattr(n, "type", etype);
+
+ if (!getCurrentClass()) {
+ newsymname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
+ // Strange hack to change the name
+ Setattr(n, "name", Getattr(n, "value"));
+ Setattr(n, "sym:name", newsymname);
+ variableWrapper(n);
+ value = Swig_name_get(NSPACE_TODO, newsymname);
+ } else {
+ String *enumClassPrefix = getEnumClassPrefix();
+ newsymname = Swig_name_member(0, enumClassPrefix, symname);
+ Setattr(n, "name", Getattr(n, "value"));
+ Setattr(n, "sym:name", newsymname);
+ variableWrapper(n);
+ value = Swig_name_get(NSPACE_TODO, newsymname);
+ }
+ value = Swig_name_wrapper(value);
+ Replace(value, "_wrap", "R_swig", DOH_REPLACE_FIRST);
+
+ String *valuecall=NewString("");
+ Printv(valuecall, ".Call('", value, "',FALSE, PACKAGE='", Rpackage, "')", NIL);
+ Delete(value);
+ return valuecall;
+}
diff --git a/contrib/tools/swig/Source/Modules/ruby.cxx b/contrib/tools/swig/Source/Modules/ruby.cxx
new file mode 100644
index 00000000000..48b0efab36c
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/ruby.cxx
@@ -0,0 +1,3511 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * ruby.cxx
+ *
+ * Ruby language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+#include <ctype.h>
+#include <string.h>
+#include <limits.h> /* for INT_MAX */
+
+#define SWIG_PROTECTED_TARGET_METHODS 1
+
+class RClass {
+private:
+ String *temp;
+
+public:
+ String *name; /* class name (renamed) */
+ String *cname; /* original C class/struct name */
+ String *mname; /* Mangled name */
+
+ /**
+ * The C variable name used in the SWIG-generated wrapper code to refer to
+ * this class; usually it is of the form "SwigClassXXX.klass", where SwigClassXXX
+ * is a swig_class struct instance and klass is a member of that struct.
+ */
+ String *vname;
+
+ /**
+ * The C variable name used in the SWIG-generated wrapper code to refer to
+ * the module that implements this class's methods (when we're trying to
+ * support C++ multiple inheritance). Usually it is of the form
+ * "SwigClassClassName.mImpl", where SwigClassXXX is a swig_class struct instance
+ * and mImpl is a member of that struct.
+ */
+ String *mImpl;
+
+ String *type;
+ String *prefix;
+ String *init;
+
+
+ int constructor_defined;
+ int destructor_defined;
+
+ RClass() {
+ temp = NewString("");
+ name = NewString("");
+ cname = NewString("");
+ mname = NewString("");
+ vname = NewString("");
+ mImpl = NewString("");
+ type = NewString("");
+ prefix = NewString("");
+ init = NewString("");
+ constructor_defined = 0;
+ destructor_defined = 0;
+ }
+
+ ~RClass() {
+ Delete(name);
+ Delete(cname);
+ Delete(vname);
+ Delete(mImpl);
+ Delete(mname);
+ Delete(type);
+ Delete(prefix);
+ Delete(init);
+ Delete(temp);
+ }
+
+ void set_name(const_String_or_char_ptr cn, const_String_or_char_ptr rn, const_String_or_char_ptr valn) {
+ /* Original C/C++ class (or struct) name */
+ Clear(cname);
+ Append(cname, cn);
+
+ /* Mangled name */
+ Delete(mname);
+ mname = Swig_name_mangle(cname);
+
+ /* Renamed class name */
+ Clear(name);
+ Append(name, valn);
+
+ /* Variable name for the VALUE that refers to the Ruby Class object */
+ Clear(vname);
+ Printf(vname, "SwigClass%s.klass", name);
+
+ /* Variable name for the VALUE that refers to the Ruby Class object */
+ Clear(mImpl);
+ Printf(mImpl, "SwigClass%s.mImpl", name);
+
+ /* Prefix */
+ Clear(prefix);
+ Printv(prefix, (rn ? rn : cn), "_", NIL);
+ }
+
+ char *strip(const_String_or_char_ptr s) {
+ Clear(temp);
+ Append(temp, s);
+ if (Strncmp(s, prefix, Len(prefix)) == 0) {
+ Replaceall(temp, prefix, "");
+ }
+ return Char(temp);
+ }
+};
+
+
+/* flags for the make_autodoc function */
+enum autodoc_t {
+ AUTODOC_CLASS,
+ AUTODOC_CTOR,
+ AUTODOC_DTOR,
+ AUTODOC_STATICFUNC,
+ AUTODOC_FUNC,
+ AUTODOC_METHOD,
+ AUTODOC_GETTER,
+ AUTODOC_SETTER,
+ AUTODOC_NONE
+};
+
+static const char *usage = "\
+Ruby Options (available with -ruby)\n\
+ -autorename - Enable renaming of classes and methods to follow Ruby coding standards\n\
+ -globalmodule - Wrap everything into the global module\n\
+ -initname <name>- Set entry function to Init_<name> (used by `require')\n\
+ -minherit - Attempt to support multiple inheritance\n\
+ -noautorename - Disable renaming of classes and methods (default)\n\
+ -prefix <name> - Set a prefix <name> to be prepended to all names\n\
+";
+
+
+#define RCLASS(hash, name) (RClass*)(Getattr(hash, name) ? Data(Getattr(hash, name)) : 0)
+#define SET_RCLASS(hash, name, klass) Setattr(hash, name, NewVoid(klass, 0))
+
+
+class RUBY:public Language {
+private:
+
+ String *module;
+ String *modvar;
+ String *feature;
+ String *prefix;
+ int current;
+ Hash *classes; /* key=cname val=RClass */
+ RClass *klass; /* Currently processing class */
+ Hash *special_methods; /* Python style special method name table */
+
+ File *f_directors;
+ File *f_directors_h;
+ File *f_directors_helpers;
+ File *f_begin;
+ File *f_runtime;
+ File *f_runtime_h;
+ File *f_header;
+ File *f_wrappers;
+ File *f_init;
+ File *f_initbeforefunc;
+
+ bool useGlobalModule;
+ bool multipleInheritance;
+
+ // Wrap modes
+ enum WrapperMode {
+ NO_CPP,
+ MEMBER_FUNC,
+ CONSTRUCTOR_ALLOCATE,
+ CONSTRUCTOR_INITIALIZE,
+ DESTRUCTOR,
+ MEMBER_VAR,
+ CLASS_CONST,
+ STATIC_FUNC,
+ STATIC_VAR
+ };
+
+ /* ------------------------------------------------------------
+ * autodoc level declarations
+ * ------------------------------------------------------------ */
+
+ enum autodoc_l {
+ NO_AUTODOC = -2, // no autodoc
+ STRING_AUTODOC = -1, // use provided string
+ NAMES_AUTODOC = 0, // only parameter names
+ TYPES_AUTODOC = 1, // parameter names and types
+ EXTEND_AUTODOC = 2, // extended documentation and parameter names
+ EXTEND_TYPES_AUTODOC = 3 // extended documentation and parameter types + names
+ };
+
+ autodoc_t last_mode;
+ String* last_autodoc;
+
+ autodoc_l autodoc_level(String *autodoc) {
+ autodoc_l dlevel = NO_AUTODOC;
+ char *c = Char(autodoc);
+ if (c) {
+ if (isdigit(c[0])) {
+ dlevel = (autodoc_l) atoi(c);
+ } else {
+ if (strcmp(c, "extended") == 0) {
+ dlevel = EXTEND_AUTODOC;
+ } else {
+ dlevel = STRING_AUTODOC;
+ }
+ }
+ }
+ return dlevel;
+ }
+
+
+
+ /* ------------------------------------------------------------
+ * have_docstring()
+ * Check if there is a docstring directive and it has text,
+ * or there is an autodoc flag set
+ * ------------------------------------------------------------ */
+
+ bool have_docstring(Node *n) {
+ String *str = Getattr(n, "feature:docstring");
+ return (str && Len(str) > 0) || (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc"));
+ }
+
+ /* ------------------------------------------------------------
+ * docstring()
+ * Get the docstring text, stripping off {} if necessary,
+ * and enclose in triple double quotes. If autodoc is also
+ * set then it will build a combined docstring.
+ * ------------------------------------------------------------ */
+
+ String *docstring(Node *n, autodoc_t ad_type) {
+
+ String *str = Getattr(n, "feature:docstring");
+ bool have_ds = (str && Len(str) > 0);
+ bool have_auto = (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc"));
+ String *autodoc = NULL;
+ String *doc = NULL;
+
+ if (have_ds) {
+ char *t = Char(str);
+ if (*t == '{') {
+ Delitem(str, 0);
+ Delitem(str, DOH_END);
+ }
+ }
+
+ if (have_auto) {
+ autodoc = make_autodoc(n, ad_type);
+ have_auto = (autodoc && Len(autodoc) > 0);
+ }
+
+ if (have_auto || have_ds)
+ doc = NewString("/*");
+
+ if (have_auto && have_ds) { // Both autodoc and docstring are present
+ Printv(doc, "\n", autodoc, "\n", str, "\n", NIL);
+ } else if (!have_auto && have_ds) { // only docstring
+ Printv(doc, str, NIL);
+ } else if (have_auto && !have_ds) { // only autodoc
+ Printv(doc, "\n", autodoc, "\n", NIL);
+ } else {
+ doc = NewString("");
+ }
+
+ if (have_auto || have_ds)
+ Append(doc, "*/\n");
+
+ // Save the generated strings in the parse tree in case they are used later
+ // by post processing tools
+ Setattr(n, "ruby:docstring", doc);
+ Setattr(n, "ruby:autodoc", autodoc);
+ return doc;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addMissingParameterNames()
+ * For functions that have not had nameless parameters set in the Language class.
+ *
+ * Inputs:
+ * plist - entire parameter list
+ * arg_offset - argument number for first parameter
+ * Side effects:
+ * The "lname" attribute in each parameter in plist will be contain a parameter name
+ * ----------------------------------------------------------------------------- */
+
+ void addMissingParameterNames(Node* n, ParmList *plist, int arg_offset) {
+ Parm *p = plist;
+ int i = arg_offset;
+ while (p) {
+ if (!Getattr(p, "lname")) {
+ String *name = makeParameterName(n, p, i);
+ Setattr(p, "lname", name);
+ Delete(name);
+ }
+ i++;
+ p = nextSibling(p);
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * make_autodocParmList()
+ * Generate the documentation for the function parameters
+ * ------------------------------------------------------------ */
+
+ String *make_autodocParmList(Node *n, bool showTypes) {
+ String *doc = NewString("");
+ String *pdocs = 0;
+ ParmList *plist = CopyParmList(Getattr(n, "parms"));
+ Parm *p;
+ Parm *pnext;
+ int lines = 0;
+ int arg_num = is_wrapping_class() ? 1 : 0;
+ const int maxwidth = 80;
+
+ addMissingParameterNames(n, plist, arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms
+
+ Swig_typemap_attach_parms("in", plist, 0);
+ Swig_typemap_attach_parms("doc", plist, 0);
+
+ if (Strcmp(ParmList_protostr(plist), "void") == 0) {
+ //No parameters actually
+ return doc;
+ }
+
+ for (p = plist; p; p = pnext, arg_num++) {
+
+ String *tm = Getattr(p, "tmap:in");
+ if (tm) {
+ pnext = Getattr(p, "tmap:in:next");
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ continue;
+ }
+ } else {
+ pnext = nextSibling(p);
+ }
+
+ String *name = 0;
+ String *type = 0;
+ String *value = 0;
+ String *pdoc = Getattr(p, "tmap:doc");
+ if (pdoc) {
+ name = Getattr(p, "tmap:doc:name");
+ type = Getattr(p, "tmap:doc:type");
+ value = Getattr(p, "tmap:doc:value");
+ }
+
+ // Note: the generated name should be consistent with that in kwnames[]
+ String *made_name = 0;
+ if (!name) {
+ name = made_name = makeParameterName(n, p, arg_num);
+ }
+
+ type = type ? type : Getattr(p, "type");
+ value = value ? value : Getattr(p, "value");
+
+ if (SwigType_isvarargs(type))
+ break;
+
+ // Skip the 'self' parameter which in ruby is implicit
+ if ( Cmp(name, "self") == 0 )
+ continue;
+
+ // Make __p parameters just p (as used in STL)
+ Replace( name, "__", "", DOH_REPLACE_FIRST );
+
+ if (Len(doc)) {
+ // add a comma to the previous one if any
+ Append(doc, ", ");
+
+ // Do we need to wrap a long line?
+ if ((Len(doc) - lines * maxwidth) > maxwidth) {
+ Printf(doc, "\n%s", tab4);
+ lines += 1;
+ }
+ }
+
+ // Do the param type too?
+ Node *nn = classLookup(Getattr(p, "type"));
+ String *type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
+ if (showTypes)
+ Printf(doc, "%s ", type_str);
+
+ Append(doc, name);
+ if (pdoc) {
+ if (!pdocs)
+ pdocs = NewString("Parameters:\n");
+ Printf(pdocs, " %s.\n", pdoc);
+ }
+
+ if (value) {
+ String *new_value = convertValue(value, Getattr(p, "type"));
+ if (new_value) {
+ value = new_value;
+ } else {
+ Node *lookup = Swig_symbol_clookup(value, 0);
+ if (lookup)
+ value = Getattr(lookup, "sym:name");
+ }
+ Printf(doc, "=%s", value);
+ }
+ Delete(type_str);
+ Delete(made_name);
+ }
+ if (pdocs)
+ Setattr(n, "feature:pdocs", pdocs);
+ Delete(plist);
+ return doc;
+ }
+
+ /* ------------------------------------------------------------
+ * make_autodoc()
+ * Build a docstring for the node, using parameter and other
+ * info in the parse tree. If the value of the autodoc
+ * attribute is "0" then do not include parameter types, if
+ * it is "1" (the default) then do. If it has some other
+ * value then assume it is supplied by the extension writer
+ * and use it directly.
+ * ------------------------------------------------------------ */
+
+ String *make_autodoc(Node *n, autodoc_t ad_type) {
+ int extended = 0;
+ // If the function is overloaded then this function is called
+ // for the last one. Rewind to the first so the docstrings are
+ // in order.
+ while (Getattr(n, "sym:previousSibling"))
+ n = Getattr(n, "sym:previousSibling");
+
+ Node *pn = Swig_methodclass(n);
+ String* super_names = NewString("");
+ String* class_name = Getattr(pn, "sym:name") ;
+
+ if ( !class_name ) {
+ class_name = NewString("");
+ } else {
+ class_name = Copy(class_name);
+ List *baselist = Getattr(pn, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator base = First(baselist);
+ while (base.item && GetFlag(base.item, "feature:ignore")) {
+ base = Next(base);
+ }
+
+ int count = 0;
+ for ( ;base.item; ++count) {
+ if ( count ) Append(super_names, ", ");
+ String *basename = Getattr(base.item, "sym:name");
+
+ String* basenamestr = NewString(basename);
+ Node* parent = parentNode(base.item);
+ while (parent)
+ {
+ String *parent_name = Copy( Getattr(parent, "sym:name") );
+ if ( !parent_name ) {
+ Node* mod = Getattr(parent, "module");
+ if ( mod )
+ parent_name = Copy( Getattr(mod, "name") );
+ if ( parent_name )
+ (Char(parent_name))[0] = (char)toupper((Char(parent_name))[0]);
+ }
+ if ( parent_name ) {
+ Insert(basenamestr, 0, "::");
+ Insert(basenamestr, 0, parent_name);
+ Delete(parent_name);
+ }
+ parent = parentNode(parent);
+ }
+
+ Append(super_names, basenamestr );
+ Delete(basenamestr);
+ base = Next(base);
+ }
+ }
+ }
+ String* full_name;
+ if ( module ) {
+ full_name = NewString(module);
+ if (Len(class_name) > 0)
+ Append(full_name, "::");
+ }
+ else
+ full_name = NewString("");
+ Append(full_name, class_name);
+
+ String* symname = Getattr(n, "sym:name");
+ if ( Getattr( special_methods, symname ) )
+ symname = Getattr( special_methods, symname );
+
+ String* methodName = NewString(full_name);
+ Append(methodName, symname);
+
+
+ // Each overloaded function will try to get documented,
+ // so we keep the name of the last overloaded function and its type.
+ // Documenting just from functionWrapper() is not possible as
+ // sym:name has already been changed to include the class name
+ if ( last_mode == ad_type && Cmp(methodName, last_autodoc) == 0 ) {
+ Delete(full_name);
+ Delete(class_name);
+ Delete(super_names);
+ Delete(methodName);
+ return NewString("");
+ }
+
+
+ last_mode = ad_type;
+ last_autodoc = Copy(methodName);
+
+ String *doc = NewString("");
+ int counter = 0;
+ bool skipAuto = false;
+ Node* on = n;
+ for ( ; n; ++counter ) {
+ String *type_str = NULL;
+ skipAuto = false;
+ bool showTypes = false;
+ String *autodoc = Getattr(n, "feature:autodoc");
+ autodoc_l dlevel = autodoc_level(autodoc);
+ switch (dlevel) {
+ case NO_AUTODOC:
+ break;
+ case NAMES_AUTODOC:
+ showTypes = false;
+ break;
+ case TYPES_AUTODOC:
+ showTypes = true;
+ break;
+ case EXTEND_AUTODOC:
+ extended = 1;
+ showTypes = false;
+ break;
+ case EXTEND_TYPES_AUTODOC:
+ extended = 1;
+ showTypes = true;
+ break;
+ case STRING_AUTODOC:
+ skipAuto = true;
+ break;
+ }
+
+ SwigType *type = Getattr(n, "type");
+
+ if (type) {
+ if (Strcmp(type, "void") == 0) {
+ type_str = NULL;
+ } else {
+ SwigType *qt = SwigType_typedef_resolve_all(type);
+ if (SwigType_isenum(qt)) {
+ type_str = NewString("int");
+ } else {
+ Node *nn = classLookup(type);
+ type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
+ }
+ }
+ }
+
+ if (counter == 0) {
+ switch (ad_type) {
+ case AUTODOC_CLASS:
+ Printf(doc, " Document-class: %s", full_name);
+ if ( Len(super_names) > 0 )
+ Printf( doc, " < %s", super_names);
+ Append(doc, "\n\n");
+ break;
+ case AUTODOC_CTOR:
+ Printf(doc, " Document-method: %s.new\n\n", full_name);
+ break;
+
+ case AUTODOC_DTOR:
+ break;
+
+ case AUTODOC_STATICFUNC:
+ Printf(doc, " Document-method: %s.%s\n\n", full_name, symname);
+ break;
+
+ case AUTODOC_FUNC:
+ case AUTODOC_METHOD:
+ case AUTODOC_GETTER:
+ Printf(doc, " Document-method: %s.%s\n\n", full_name, symname);
+ break;
+ case AUTODOC_SETTER:
+ Printf(doc, " Document-method: %s.%s=\n\n", full_name, symname);
+ break;
+ case AUTODOC_NONE:
+ break;
+ }
+ }
+
+ if (skipAuto) {
+ if ( counter == 0 ) Printf(doc, " call-seq:\n");
+ switch( ad_type )
+ {
+ case AUTODOC_STATICFUNC:
+ case AUTODOC_FUNC:
+ case AUTODOC_METHOD:
+ case AUTODOC_GETTER:
+ {
+ String *paramList = make_autodocParmList(n, showTypes);
+ if (Len(paramList))
+ Printf(doc, " %s(%s)", symname, paramList);
+ else
+ Printf(doc, " %s", symname);
+ if (type_str)
+ Printf(doc, " -> %s", type_str);
+ break;
+ }
+ case AUTODOC_SETTER:
+ {
+ Printf(doc, " %s=(x)", symname);
+ if (type_str)
+ Printf(doc, " -> %s", type_str);
+ break;
+ }
+ default:
+ break;
+ }
+ } else {
+ switch (ad_type) {
+ case AUTODOC_CLASS:
+ {
+ // Only do the autodoc if there isn't a docstring for the class
+ String *str = Getattr(n, "feature:docstring");
+ if (counter == 0 && (str == 0 || Len(str) == 0)) {
+ if (CPlusPlus) {
+ Printf(doc, " Proxy of C++ %s class", full_name);
+ } else {
+ Printf(doc, " Proxy of C %s struct", full_name);
+ }
+ }
+ }
+ break;
+ case AUTODOC_CTOR:
+ if (counter == 0)
+ Printf(doc, " call-seq:\n");
+ if (Strcmp(class_name, symname) == 0) {
+ String *paramList = make_autodocParmList(n, showTypes);
+ if (Len(paramList))
+ Printf(doc, " %s.new(%s)", class_name, paramList);
+ else
+ Printf(doc, " %s.new", class_name);
+ } else {
+ Printf(doc, " %s.new(%s)", class_name, make_autodocParmList(n, showTypes));
+ }
+ break;
+
+ case AUTODOC_DTOR:
+ break;
+
+ case AUTODOC_STATICFUNC:
+ case AUTODOC_FUNC:
+ case AUTODOC_METHOD:
+ case AUTODOC_GETTER:
+ {
+ if (counter == 0)
+ Printf(doc, " call-seq:\n");
+ String *paramList = make_autodocParmList(n, showTypes);
+ if (Len(paramList))
+ Printf(doc, " %s(%s)", symname, paramList);
+ else
+ Printf(doc, " %s", symname);
+ if (type_str)
+ Printf(doc, " -> %s", type_str);
+ break;
+ }
+ case AUTODOC_SETTER:
+ {
+ Printf(doc, " call-seq:\n");
+ Printf(doc, " %s=(x)", symname);
+ if (type_str)
+ Printf(doc, " -> %s", type_str);
+ break;
+ }
+ case AUTODOC_NONE:
+ break;
+ }
+ }
+
+ // if it's overloaded then get the next decl and loop around again
+ n = Getattr(n, "sym:nextSibling");
+ if (n)
+ Append(doc, "\n");
+ Delete(type_str);
+ }
+
+ Printf(doc, "\n\n");
+ if (!skipAuto) {
+ switch (ad_type) {
+ case AUTODOC_CLASS:
+ case AUTODOC_DTOR:
+ break;
+ case AUTODOC_CTOR:
+ Printf(doc, "Class constructor.\n");
+ break;
+ case AUTODOC_STATICFUNC:
+ Printf(doc, "A class method.\n");
+ break;
+ case AUTODOC_FUNC:
+ Printf(doc, "A module function.\n");
+ break;
+ case AUTODOC_METHOD:
+ Printf(doc, "An instance method.\n");
+ break;
+ case AUTODOC_GETTER:
+ Printf(doc, "Get value of attribute.\n");
+ break;
+ case AUTODOC_SETTER:
+ Printf(doc, "Set new value for attribute.\n");
+ break;
+ case AUTODOC_NONE:
+ break;
+ }
+ }
+
+
+ n = on;
+ while ( n ) {
+ String *autodoc = Getattr(n, "feature:autodoc");
+ autodoc_l dlevel = autodoc_level(autodoc);
+
+ switch (dlevel) {
+ case NO_AUTODOC:
+ case NAMES_AUTODOC:
+ case TYPES_AUTODOC:
+ extended = 0;
+ break;
+ case STRING_AUTODOC:
+ extended = 2;
+ Replaceall( autodoc, "$class", class_name );
+ Printv(doc, autodoc, ".", NIL);
+ break;
+ case EXTEND_AUTODOC:
+ case EXTEND_TYPES_AUTODOC:
+ extended = 1;
+ break;
+ }
+
+
+ if (extended) {
+ String *pdocs = Getattr(n, "feature:pdocs");
+ if (pdocs) {
+ Printv(doc, "\n\n", pdocs, NULL);
+ break;
+ }
+ if ( extended == 2 ) break;
+ }
+ n = Getattr(n, "sym:nextSibling");
+ }
+
+ Delete(full_name);
+ Delete(class_name);
+ Delete(super_names);
+ Delete(methodName);
+
+ return doc;
+ }
+
+ /* ------------------------------------------------------------
+ * convertValue()
+ * Check if string v can be a Ruby value literal,
+ * (eg. number or string), or translate it to a Ruby literal.
+ * ------------------------------------------------------------ */
+ String *convertValue(String *v, SwigType *t) {
+ if (v && Len(v) > 0) {
+ char fc = (Char(v))[0];
+ if (('0' <= fc && fc <= '9') || '\'' == fc || '"' == fc) {
+ /* number or string (or maybe NULL pointer) */
+ if (SwigType_ispointer(t) && Strcmp(v, "0") == 0)
+ return NewString("None");
+ else
+ return v;
+ }
+ if (Strcmp(v, "NULL") == 0 || Strcmp(v, "nullptr") == 0)
+ return SwigType_ispointer(t) ? NewString("nil") : NewString("0");
+ if (Strcmp(v, "true") == 0 || Strcmp(v, "TRUE") == 0)
+ return NewString("True");
+ if (Strcmp(v, "false") == 0 || Strcmp(v, "FALSE") == 0)
+ return NewString("False");
+ }
+ return 0;
+ }
+
+public:
+
+ /* ---------------------------------------------------------------------
+ * RUBY()
+ *
+ * Initialize member data
+ * --------------------------------------------------------------------- */
+ RUBY() :
+ module(0),
+ modvar(0),
+ feature(0),
+ prefix(0),
+ current(0),
+ classes(0),
+ klass(0),
+ special_methods(0),
+ f_directors(0),
+ f_directors_h(0),
+ f_directors_helpers(0),
+ f_begin(0),
+ f_runtime(0),
+ f_runtime_h(0),
+ f_header(0),
+ f_wrappers(0),
+ f_init(0),
+ f_initbeforefunc(0),
+ useGlobalModule(false),
+ multipleInheritance(false),
+ last_mode(AUTODOC_NONE),
+ last_autodoc(NewString("")) {
+ current = NO_CPP;
+ director_prot_ctor_code = NewString("");
+ Printv(director_prot_ctor_code,
+ "if ( $comparison ) { /* subclassed */\n",
+ " $director_new \n",
+ "} else {\n", " rb_raise(rb_eRuntimeError,\"accessing abstract class or protected constructor\"); \n", " return Qnil;\n", "}\n", NIL);
+ director_multiple_inheritance = 0;
+ director_language = 1;
+ }
+
+ /* ---------------------------------------------------------------------
+ * main()
+ *
+ * Parse command line options and initializes variables.
+ * --------------------------------------------------------------------- */
+
+ virtual void main(int argc, char *argv[]) {
+
+ int autorename = 0;
+
+ /* Set location of SWIG library */
+ SWIG_library_directory("ruby");
+
+ /* Look for certain command line options */
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-initname") == 0) {
+ if (argv[i + 1]) {
+ char *name = argv[i + 1];
+ feature = NewString(name);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ }
+ else if (strcmp(argv[i], "-feature") == 0) {
+ fprintf( stderr, "Warning: Ruby -feature option is deprecated, "
+ "please use -initname instead.\n");
+ if (argv[i + 1]) {
+ char *name = argv[i + 1];
+ feature = NewString(name);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-globalmodule") == 0) {
+ useGlobalModule = true;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-minherit") == 0) {
+ multipleInheritance = true;
+ director_multiple_inheritance = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-autorename") == 0) {
+ autorename = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-noautorename") == 0) {
+ autorename = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-prefix") == 0) {
+ if (argv[i + 1]) {
+ char *name = argv[i + 1];
+ prefix = NewString(name);
+ 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);
+ } else if (strcmp(argv[i], "-cppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]);
+ Swig_mark_arg(i);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ if (autorename) {
+ /* Turn on the autorename mode */
+ Preprocessor_define((DOH *) "SWIG_RUBY_AUTORENAME", 0);
+ }
+
+ /* Add a symbol to the parser for conditional compilation */
+ Preprocessor_define("SWIGRUBY 1", 0);
+
+ /* Add typemap definitions */
+ SWIG_typemap_lang("ruby");
+ SWIG_config_file("ruby.swg");
+ allow_overloading();
+ }
+
+ /**
+ * Generate initialization code to define the Ruby module(s),
+ * accounting for nested modules as necessary.
+ */
+ void defineRubyModule() {
+ List *modules = Split(module, ':', INT_MAX);
+ if (modules != 0 && Len(modules) > 0) {
+ String *mv = 0;
+ Iterator m;
+ m = First(modules);
+ while (m.item) {
+ if (Len(m.item) > 0) {
+ if (mv != 0) {
+ Printv(f_init, tab4, modvar, " = rb_define_module_under(", modvar, ", \"", m.item, "\");\n", NIL);
+ } else {
+ Printv(f_init, tab4, modvar, " = rb_define_module(\"", m.item, "\");\n", NIL);
+ mv = NewString(modvar);
+ }
+ }
+ m = Next(m);
+ }
+ Delete(mv);
+ Delete(modules);
+ }
+ }
+
+ void registerMagicMethods() {
+
+ special_methods = NewHash();
+
+ /* Python->Ruby style special method name. */
+ /* Basic */
+ Setattr(special_methods, "__repr__", "inspect");
+ Setattr(special_methods, "__str__", "to_s");
+ Setattr(special_methods, "__cmp__", "<=>");
+ Setattr(special_methods, "__hash__", "hash");
+ Setattr(special_methods, "__nonzero__", "nonzero?");
+
+ /* Callable */
+ Setattr(special_methods, "__call__", "call");
+
+ /* Collection */
+ Setattr(special_methods, "__len__", "length");
+ Setattr(special_methods, "__getitem__", "[]");
+ Setattr(special_methods, "__setitem__", "[]=");
+
+ /* Operators */
+ Setattr(special_methods, "__add__", "+");
+ Setattr(special_methods, "__pos__", "+@");
+ Setattr(special_methods, "__sub__", "-");
+ Setattr(special_methods, "__neg__", "-@");
+ Setattr(special_methods, "__mul__", "*");
+ Setattr(special_methods, "__div__", "/");
+ Setattr(special_methods, "__mod__", "%");
+ Setattr(special_methods, "__lshift__", "<<");
+ Setattr(special_methods, "__rshift__", ">>");
+ Setattr(special_methods, "__and__", "&");
+ Setattr(special_methods, "__or__", "|");
+ Setattr(special_methods, "__xor__", "^");
+ Setattr(special_methods, "__invert__", "~");
+ Setattr(special_methods, "__lt__", "<");
+ Setattr(special_methods, "__le__", "<=");
+ Setattr(special_methods, "__gt__", ">");
+ Setattr(special_methods, "__ge__", ">=");
+ Setattr(special_methods, "__eq__", "==");
+
+ /* Other numeric */
+ Setattr(special_methods, "__divmod__", "divmod");
+ Setattr(special_methods, "__pow__", "**");
+ Setattr(special_methods, "__abs__", "abs");
+ Setattr(special_methods, "__int__", "to_i");
+ Setattr(special_methods, "__float__", "to_f");
+ Setattr(special_methods, "__coerce__", "coerce");
+ }
+
+ /* ---------------------------------------------------------------------
+ * top()
+ * --------------------------------------------------------------------- */
+
+ virtual int top(Node *n) {
+
+ String *mod_docstring = NULL;
+
+ /**
+ * See if any Ruby module options have been specified as options
+ * to the %module directive.
+ */
+ Node *swigModule = Getattr(n, "module");
+ if (swigModule) {
+ Node *options = Getattr(swigModule, "options");
+ if (options) {
+ if (Getattr(options, "directors")) {
+ allow_directors();
+ }
+ if (Getattr(options, "dirprot")) {
+ allow_dirprot();
+ }
+ if (Getattr(options, "ruby_globalmodule")) {
+ useGlobalModule = true;
+ }
+ if (Getattr(options, "ruby_minherit")) {
+ multipleInheritance = true;
+ director_multiple_inheritance = 1;
+ }
+ mod_docstring = Getattr(options, "docstring");
+ }
+ }
+
+ /* Set comparison with none for ConstructorToFunction */
+
+
+ setSubclassInstanceCheck(NewStringf("strcmp(rb_obj_classname(self), classname) != 0"));
+ // setSubclassInstanceCheck(NewString("CLASS_OF(self) != cFoo.klass"));
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+ String *outfile_h = Getattr(n, "outfile_h");
+
+ if (!outfile) {
+ Printf(stderr, "Unable to determine outfile\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+ f_directors_h = NewString("");
+ f_directors = NewString("");
+ f_directors_helpers = NewString("");
+ f_initbeforefunc = NewString("");
+
+ if (directorsEnabled()) {
+ if (!outfile_h) {
+ Printf(stderr, "Unable to determine outfile_h\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+ f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
+ if (!f_runtime_h) {
+ FileErrorDisplay(outfile_h);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+ Swig_register_filebyname("director_helpers", f_directors_helpers);
+ Swig_register_filebyname("initbeforefunc", f_initbeforefunc);
+
+ modvar = 0;
+ current = NO_CPP;
+ klass = 0;
+ classes = NewHash();
+
+ registerMagicMethods();
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n\n#ifndef SWIGRUBY\n#define SWIGRUBY\n#endif\n\n");
+
+ if (directorsEnabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+ }
+
+ Printf(f_runtime, "\n");
+
+ /* typedef void *VALUE */
+ SwigType *value = NewSwigType(T_VOID);
+ SwigType_add_pointer(value);
+ SwigType_typedef(value, "VALUE");
+ Delete(value);
+
+ /* Set module name */
+ set_module(Char(Getattr(n, "name")));
+
+ if (directorsEnabled()) {
+ /* Build a version of the module name for use in a C macro name. */
+ String *module_macro = Copy(module);
+ Replaceall(module_macro, "::", "__");
+
+ Swig_banner(f_directors_h);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_macro);
+ Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_macro);
+ Printf(f_directors_h, "namespace Swig {\n");
+ Printf(f_directors_h, " class Director;\n");
+ Printf(f_directors_h, "}\n\n");
+
+ Printf(f_directors_helpers, "/* ---------------------------------------------------\n");
+ Printf(f_directors_helpers, " * C++ director class helpers\n");
+ Printf(f_directors_helpers, " * --------------------------------------------------- */\n\n");
+
+ Printf(f_directors, "\n\n");
+ Printf(f_directors, "/* ---------------------------------------------------\n");
+ Printf(f_directors, " * C++ director class methods\n");
+ Printf(f_directors, " * --------------------------------------------------- */\n\n");
+ if (outfile_h) {
+ String *filename = Swig_file_filename(outfile_h);
+ Printf(f_directors, "#include \"%s\"\n\n", filename);
+ Delete(filename);
+ }
+
+ Delete(module_macro);
+ }
+
+ Printf(f_header, "#define SWIG_init Init_%s\n", feature);
+ Printf(f_header, "#define SWIG_name \"%s\"\n\n", module);
+
+ if (mod_docstring) {
+ if (Len(mod_docstring)) {
+ Printf(f_header, "/*\n Document-module: %s\n\n%s\n*/\n", module, mod_docstring);
+ }
+ Delete(mod_docstring);
+ mod_docstring = NULL;
+ }
+
+ Printf(f_header, "static VALUE %s;\n", modvar);
+
+ /* Start generating the initialization function */
+ String* docs = docstring(n, AUTODOC_CLASS);
+ Printf(f_init, "/*\n%s\n*/", docs );
+ Printv(f_init, "\n", "#ifdef __cplusplus\n", "extern \"C\"\n", "#endif\n", "SWIGEXPORT void Init_", feature, "(void) {\n", "size_t i;\n", "\n", NIL);
+
+ Printv(f_init, tab4, "SWIG_InitRuntime();\n", NIL);
+
+ if (!useGlobalModule)
+ defineRubyModule();
+
+ Printv(f_init, "\n", "SWIG_InitializeModule(0);\n", "for (i = 0; i < swig_module.size; i++) {\n", "SWIG_define_class(swig_module.types[i]);\n", "}\n", NIL);
+ Printf(f_init, "\n");
+
+ /* Initialize code to keep track of objects */
+ Printf(f_init, "SWIG_RubyInitializeTrackings();\n");
+
+ Language::top(n);
+
+ if (directorsEnabled()) {
+ // Insert director runtime into the f_runtime file (make it occur before %header section)
+ Swig_insert_file("director_common.swg", f_runtime);
+ Swig_insert_file("director.swg", f_runtime);
+ }
+
+ /* Finish off our init function */
+ Printf(f_init, "}\n");
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+
+ /* Close all of the files */
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+
+ if (directorsEnabled()) {
+ Dump(f_directors_helpers, f_begin);
+ Dump(f_directors, f_begin);
+ Dump(f_directors_h, f_runtime_h);
+ Printf(f_runtime_h, "\n");
+ Printf(f_runtime_h, "#endif\n");
+ Delete(f_runtime_h);
+ }
+
+ Dump(f_wrappers, f_begin);
+ Dump(f_initbeforefunc, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_initbeforefunc);
+ Delete(f_runtime);
+ Delete(f_begin);
+
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * importDirective()
+ * ----------------------------------------------------------------------------- */
+
+ virtual int importDirective(Node *n) {
+ String *modname = Getattr(n, "module");
+ if (modname) {
+ if (prefix) {
+ Insert(modname, 0, prefix);
+ }
+
+ List *modules = Split(modname, ':', INT_MAX);
+ if (modules && Len(modules) > 0) {
+ modname = NewString("");
+ String *last = NULL;
+ Iterator m = First(modules);
+ while (m.item) {
+ if (Len(m.item) > 0) {
+ if (last) {
+ Append(modname, "/");
+ }
+ Append(modname, m.item);
+ last = m.item;
+ }
+ m = Next(m);
+ }
+ Printf(f_init, "rb_require(\"%s\");\n", modname);
+ Delete(modname);
+ }
+ Delete(modules);
+ }
+ return Language::importDirective(n);
+ }
+
+ /* ---------------------------------------------------------------------
+ * set_module(const char *mod_name)
+ *
+ * Sets the module name. Does nothing if it's already set (so it can
+ * be overridden as a command line option).
+ *---------------------------------------------------------------------- */
+
+ void set_module(const char *s) {
+ String *mod_name = NewString(s);
+ if (module == 0) {
+ /* Start with the empty string */
+ module = NewString("");
+
+ if (prefix) {
+ Insert(mod_name, 0, prefix);
+ }
+
+ /* Account for nested modules */
+ List *modules = Split(mod_name, ':', INT_MAX);
+ if (modules != 0 && Len(modules) > 0) {
+ String *last = 0;
+ Iterator m = First(modules);
+ while (m.item) {
+ if (Len(m.item) > 0) {
+ String *cap = NewString(m.item);
+ (Char(cap))[0] = (char)toupper((Char(cap))[0]);
+ if (last != 0) {
+ Append(module, "::");
+ }
+ Append(module, cap);
+ last = m.item;
+ }
+ m = Next(m);
+ }
+ if (last) {
+ if (feature == 0) {
+ feature = Copy(last);
+ }
+ (Char(last))[0] = (char)toupper((Char(last))[0]);
+ modvar = NewStringf("m%s", last);
+ }
+ }
+ Delete(modules);
+ }
+ Delete(mod_name);
+ }
+
+ /* --------------------------------------------------------------------------
+ * nativeWrapper()
+ * -------------------------------------------------------------------------- */
+ virtual int nativeWrapper(Node *n) {
+ String *funcname = Getattr(n, "wrap:name");
+ Swig_warning(WARN_LANG_NATIVE_UNIMPL, input_file, line_number, "Adding native function %s not supported (ignored).\n", funcname);
+ return SWIG_NOWRAP;
+ }
+
+ /**
+ * Process the comma-separated list of aliases (if any).
+ */
+ void defineAliases(Node *n, const_String_or_char_ptr iname) {
+ String *aliasv = Getattr(n, "feature:alias");
+ if (aliasv) {
+ List *aliases = Split(aliasv, ',', INT_MAX);
+ if (aliases && Len(aliases) > 0) {
+ Iterator alias = First(aliases);
+ while (alias.item) {
+ if (Len(alias.item) > 0) {
+ if (current == NO_CPP) {
+ if (useGlobalModule) {
+ Printv(f_init, tab4, "rb_define_alias(rb_cObject, \"", alias.item, "\", \"", iname, "\");\n", NIL);
+ } else {
+ Printv(f_init, tab4, "rb_define_alias(rb_singleton_class(", modvar, "), \"", alias.item, "\", \"", iname, "\");\n", NIL);
+ }
+ } else if (multipleInheritance) {
+ Printv(klass->init, tab4, "rb_define_alias(", klass->mImpl, ", \"", alias.item, "\", \"", iname, "\");\n", NIL);
+ } else {
+ Printv(klass->init, tab4, "rb_define_alias(", klass->vname, ", \"", alias.item, "\", \"", iname, "\");\n", NIL);
+ }
+ }
+ alias = Next(alias);
+ }
+ }
+ Delete(aliases);
+ }
+ }
+
+ /* ---------------------------------------------------------------------
+ * create_command(Node *n, char *iname)
+ *
+ * Creates a new command from a C function.
+ * iname = Name of function in scripting language
+ *
+ * A note about what "protected" and "private" mean in Ruby:
+ *
+ * A private method is accessible only within the class or its subclasses,
+ * and it is callable only in "function form", with 'self' (implicit or
+ * explicit) as a receiver.
+ *
+ * A protected method is callable only from within its class, but unlike
+ * a private method, it can be called with a receiver other than self, such
+ * as another instance of the same class.
+ * --------------------------------------------------------------------- */
+
+ void create_command(Node *n, const_String_or_char_ptr iname) {
+
+ String *alloc_func = Swig_name_wrapper(iname);
+ String *wname = Swig_name_wrapper(iname);
+ if (CPlusPlus) {
+ Insert(wname, 0, "VALUEFUNC(");
+ Append(wname, ")");
+ }
+ if (current != NO_CPP)
+ iname = klass->strip(iname);
+ if (Getattr(special_methods, iname)) {
+ iname = GetChar(special_methods, iname);
+ }
+
+ String *s = NewString("");
+ String *temp = NewString("");
+
+#ifdef SWIG_PROTECTED_TARGET_METHODS
+ const char *rb_define_method = is_public(n) ? "rb_define_method" : "rb_define_protected_method";
+#else
+ const char *rb_define_method = "rb_define_method";
+#endif
+ switch (current) {
+ case MEMBER_FUNC:
+ {
+ if (multipleInheritance) {
+ Printv(klass->init, tab4, rb_define_method, "(", klass->mImpl, ", \"", iname, "\", ", wname, ", -1);\n", NIL);
+ } else {
+ Printv(klass->init, tab4, rb_define_method, "(", klass->vname, ", \"", iname, "\", ", wname, ", -1);\n", NIL);
+ }
+ }
+ break;
+ case CONSTRUCTOR_ALLOCATE:
+ Printv(s, tab4, "rb_define_alloc_func(", klass->vname, ", ", alloc_func, ");\n", NIL);
+ Replaceall(klass->init, "$allocator", s);
+ break;
+ case CONSTRUCTOR_INITIALIZE:
+ Printv(s, tab4, rb_define_method, "(", klass->vname, ", \"initialize\", ", wname, ", -1);\n", NIL);
+ Replaceall(klass->init, "$initializer", s);
+ break;
+ case MEMBER_VAR:
+ Append(temp, iname);
+ /* Check for _set or _get at the end of the name. */
+ if (Len(temp) > 4) {
+ const char *p = Char(temp) + (Len(temp) - 4);
+ if (strcmp(p, "_set") == 0) {
+ Delslice(temp, Len(temp) - 4, DOH_END);
+ Append(temp, "=");
+ } else if (strcmp(p, "_get") == 0) {
+ Delslice(temp, Len(temp) - 4, DOH_END);
+ }
+ }
+ if (multipleInheritance) {
+ Printv(klass->init, tab4, "rb_define_method(", klass->mImpl, ", \"", temp, "\", ", wname, ", -1);\n", NIL);
+ } else {
+ Printv(klass->init, tab4, "rb_define_method(", klass->vname, ", \"", temp, "\", ", wname, ", -1);\n", NIL);
+ }
+ break;
+ case STATIC_FUNC:
+ Printv(klass->init, tab4, "rb_define_singleton_method(", klass->vname, ", \"", iname, "\", ", wname, ", -1);\n", NIL);
+ break;
+ case NO_CPP:
+ if (!useGlobalModule) {
+ Printv(s, tab4, "rb_define_module_function(", modvar, ", \"", iname, "\", ", wname, ", -1);\n", NIL);
+ Printv(f_init, s, NIL);
+ } else {
+ Printv(s, tab4, "rb_define_global_function(\"", iname, "\", ", wname, ", -1);\n", NIL);
+ Printv(f_init, s, NIL);
+ }
+ break;
+ case DESTRUCTOR:
+ case CLASS_CONST:
+ case STATIC_VAR:
+ default:
+ assert(false); // Should not have gotten here for these types
+ }
+
+ defineAliases(n, iname);
+
+ Delete(temp);
+ Delete(s);
+ Delete(wname);
+ Delete(alloc_func);
+ }
+
+ /* ---------------------------------------------------------------------
+ * applyInputTypemap()
+ *
+ * Look up the appropriate "in" typemap for this parameter (p),
+ * substitute the correct strings for the $target and $input typemap
+ * parameters, and dump the resulting code to the wrapper file.
+ * --------------------------------------------------------------------- */
+
+ Parm *applyInputTypemap(Parm *p, String *ln, String *source, Wrapper *f, String *symname) {
+ String *tm;
+ SwigType *pt = Getattr(p, "type");
+ if ((tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$target", ln);
+ Replaceall(tm, "$source", source);
+ Replaceall(tm, "$input", source);
+ Replaceall(tm, "$symname", symname);
+
+ if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+
+ Setattr(p, "emit:input", Copy(source));
+ Printf(f->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(pt, 0));
+ p = nextSibling(p);
+ }
+ return p;
+ }
+
+ Parm *skipIgnoredArgs(Parm *p) {
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+ return p;
+ }
+
+ /* ---------------------------------------------------------------------
+ * marshalInputArgs()
+ *
+ * Process all of the arguments passed into the scripting language
+ * method and convert them into C/C++ function arguments using the
+ * supplied typemaps.
+ * --------------------------------------------------------------------- */
+
+ void marshalInputArgs(Node *n, ParmList *l, int numarg, int numreq, String *kwargs, bool allow_kwargs, Wrapper *f) {
+ int i;
+ Parm *p;
+ String *tm;
+ String *source;
+ String *target;
+
+ source = NewString("");
+ target = NewString("");
+
+ bool ctor_director = (current == CONSTRUCTOR_INITIALIZE && Swig_directorclass(n));
+
+ /**
+ * The 'start' value indicates which of the C/C++ function arguments
+ * produced here corresponds to the first value in Ruby's argv[] array.
+ * The value of start is either zero or one. If start is zero, then
+ * the first argument (with name arg1) is based on the value of argv[0].
+ * If start is one, then arg1 is based on the value of argv[1].
+ */
+ int start = (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) ? 1 : 0;
+
+ int varargs = emit_isvarargs(l);
+
+ Printf(kwargs, "{ ");
+ for (i = 0, p = l; i < numarg; i++) {
+
+ p = skipIgnoredArgs(p);
+
+ String *pn = Getattr(p, "name");
+ String *ln = Getattr(p, "lname");
+
+ /* Produce string representation of source argument */
+ Clear(source);
+
+ /* First argument is a special case */
+ if (i == 0) {
+ Printv(source, (start == 0) ? "argv[0]" : "self", NIL);
+ } else {
+ Printf(source, "argv[%d]", i - start);
+ }
+
+ /* Produce string representation of target argument */
+ Clear(target);
+ Printf(target, "%s", Char(ln));
+
+ if (i >= (numreq)) { /* Check if parsing an optional argument */
+ Printf(f->code, " if (argc > %d) {\n", i - start);
+ }
+
+ /* Record argument name for keyword argument handling */
+ if (Len(pn)) {
+ Printf(kwargs, "\"%s\",", pn);
+ } else {
+ Printf(kwargs, "\"arg%d\",", i + 1);
+ }
+
+ /* Look for an input typemap */
+ p = applyInputTypemap(p, ln, source, f, Getattr(n, "name"));
+ if (i >= numreq) {
+ Printf(f->code, "}\n");
+ }
+ }
+
+ /* Finish argument marshalling */
+ Printf(kwargs, " NULL }");
+ if (allow_kwargs) {
+// kwarg support not implemented
+// Printv(f->locals, tab4, "const char *kwnames[] = ", kwargs, ";\n", NIL);
+ }
+
+ /* Trailing varargs */
+ if (varargs) {
+ if (p && (tm = Getattr(p, "tmap:in"))) {
+ Clear(source);
+ Printf(source, "argv[%d]", i - start);
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", Copy(source));
+ Printf(f->code, "if (argc > %d) {\n", i - start);
+ Printv(f->code, tm, "\n", NIL);
+ Printf(f->code, "}\n");
+ }
+ }
+
+ Delete(source);
+ Delete(target);
+ }
+
+ /* ---------------------------------------------------------------------
+ * insertConstraintCheckingCode(ParmList *l, Wrapper *f)
+ *
+ * Checks each of the parameters in the parameter list for a "check"
+ * typemap and (if it finds one) inserts the typemapping code into
+ * the function wrapper.
+ * --------------------------------------------------------------------- */
+
+ void insertConstraintCheckingCode(ParmList *l, Wrapper *f) {
+ Parm *p;
+ String *tm;
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ /* ---------------------------------------------------------------------
+ * insertCleanupCode(ParmList *l, String *cleanup)
+ *
+ * Checks each of the parameters in the parameter list for a "freearg"
+ * typemap and (if it finds one) inserts the typemapping code into
+ * the function wrapper.
+ * --------------------------------------------------------------------- */
+
+ void insertCleanupCode(ParmList *l, String *cleanup) {
+ String *tm;
+ for (Parm *p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ if (Len(tm) != 0) {
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+ Printv(cleanup, tm, "\n", NIL);
+ }
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ /* ---------------------------------------------------------------------
+ * insertArgOutputCode(ParmList *l, String *outarg, int& need_result)
+ *
+ * Checks each of the parameters in the parameter list for a "argout"
+ * typemap and (if it finds one) inserts the typemapping code into
+ * the function wrapper.
+ * --------------------------------------------------------------------- */
+
+ void insertArgOutputCode(ParmList *l, String *outarg, int &need_result) {
+ String *tm;
+ for (Parm *p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+ Replaceall(tm, "$target", "vresult");
+ Replaceall(tm, "$result", "vresult");
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+
+ Printv(outarg, tm, "\n", NIL);
+ need_result += 1;
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ /* ---------------------------------------------------------------------
+ * validIdentifier()
+ *
+ * Is this a valid identifier in the scripting language?
+ * Ruby method names can include any combination of letters, numbers
+ * and underscores. A Ruby method name may optionally end with
+ * a question mark ("?"), exclamation point ("!") or equals sign ("=").
+ *
+ * Methods whose names end with question marks are, by convention,
+ * predicate methods that return true or false (e.g. Array#empty?).
+ *
+ * Methods whose names end with exclamation points are, by convention,
+ * called bang methods that modify the instance in place (e.g. Array#sort!).
+ *
+ * Methods whose names end with an equals sign are attribute setters
+ * (e.g. Thread#critical=).
+ * --------------------------------------------------------------------- */
+
+ virtual int validIdentifier(String *s) {
+ char *c = Char(s);
+ while (*c) {
+ if (!(isalnum(*c) || (*c == '_') || (*c == '?') || (*c == '!') || (*c == '=')))
+ return 0;
+ c++;
+ }
+ return 1;
+ }
+
+ /* ---------------------------------------------------------------------
+ * functionWrapper()
+ *
+ * Create a function declaration and register it with the interpreter.
+ * --------------------------------------------------------------------- */
+
+ virtual int functionWrapper(Node *n) {
+
+ String *nodeType;
+ bool destructor;
+
+ String *symname = Copy(Getattr(n, "sym:name"));
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ int director_method = 0;
+ String *tm;
+
+ int need_result = 0;
+
+ /* Ruby needs no destructor wrapper */
+ if (current == DESTRUCTOR)
+ return SWIG_NOWRAP;
+
+ nodeType = Getattr(n, "nodeType");
+ destructor = (!Cmp(nodeType, "destructor"));
+
+ /* If the C++ class constructor is overloaded, we only want to
+ * write out the "new" singleton method once since it is always
+ * the same. (It's the "initialize" method that will handle the
+ * overloading). */
+
+ if (current == CONSTRUCTOR_ALLOCATE && Swig_symbol_isoverloaded(n) && Getattr(n, "sym:nextSibling") != 0)
+ return SWIG_OK;
+
+ String *overname = 0;
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(symname, n))
+ return SWIG_ERROR;
+ }
+
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ String *kwargs = NewString("");
+ Wrapper *f = NewWrapper();
+
+ /* Rename predicate methods */
+ if (GetFlag(n, "feature:predicate")) {
+ Append(symname, "?");
+ }
+
+ /* Rename bang methods */
+ if (GetFlag(n, "feature:bang")) {
+ Append(symname, "!");
+ }
+
+ /* Determine the name of the SWIG wrapper function */
+ String *wname = Swig_name_wrapper(symname);
+ if (overname && current != CONSTRUCTOR_ALLOCATE) {
+ Append(wname, overname);
+ }
+
+ /* Emit arguments */
+ if (current != CONSTRUCTOR_ALLOCATE) {
+ emit_parameter_variables(l, f);
+ }
+
+ /* Attach standard typemaps */
+ if (current != CONSTRUCTOR_ALLOCATE) {
+ emit_attach_parmmaps(l, f);
+ }
+ Setattr(n, "wrap:parms", l);
+
+ /* Get number of arguments */
+ int numarg = emit_num_arguments(l);
+ int numreq = emit_num_required(l);
+ int varargs = emit_isvarargs(l);
+ bool allow_kwargs = GetFlag(n, "feature:kwargs") ? true : false;
+
+ bool ctor_director = (current == CONSTRUCTOR_INITIALIZE && Swig_directorclass(n));
+ int start = (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) ? 1 : 0;
+
+ /* Now write the wrapper function itself */
+ if (current == CONSTRUCTOR_ALLOCATE) {
+ Printv(f->def, "SWIGINTERN VALUE\n", NIL);
+ Printf(f->def, "#ifdef HAVE_RB_DEFINE_ALLOC_FUNC\n");
+ Printv(f->def, wname, "(VALUE self)\n", NIL);
+ Printf(f->def, "#else\n");
+ Printv(f->def, wname, "(int argc, VALUE *argv, VALUE self)\n", NIL);
+ Printf(f->def, "#endif\n");
+ Printv(f->def, "{\n", NIL);
+ } else if (current == CONSTRUCTOR_INITIALIZE) {
+ Printv(f->def, "SWIGINTERN VALUE\n", wname, "(int argc, VALUE *argv, VALUE self) {", NIL);
+ if (!varargs) {
+ Printf(f->code, "if ((argc < %d) || (argc > %d)) ", numreq - start, numarg - start);
+ } else {
+ Printf(f->code, "if (argc < %d) ", numreq - start);
+ }
+ Printf(f->code, "{rb_raise(rb_eArgError, \"wrong # of arguments(%%d for %d)\",argc); SWIG_fail;}\n", numreq - start);
+ } else {
+
+ if ( current == NO_CPP )
+ {
+ String* docs = docstring(n, AUTODOC_FUNC);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+ }
+
+ Printv(f->def, "SWIGINTERN VALUE\n", wname, "(int argc, VALUE *argv, VALUE self) {", NIL);
+ if (!varargs) {
+ Printf(f->code, "if ((argc < %d) || (argc > %d)) ", numreq - start, numarg - start);
+ } else {
+ Printf(f->code, "if (argc < %d) ", numreq - start);
+ }
+ Printf(f->code, "{rb_raise(rb_eArgError, \"wrong # of arguments(%%d for %d)\",argc); SWIG_fail;}\n", numreq - start);
+ }
+
+ /* Now walk the function parameter list and generate code */
+ /* to get arguments */
+ if (current != CONSTRUCTOR_ALLOCATE) {
+ marshalInputArgs(n, l, numarg, numreq, kwargs, allow_kwargs, f);
+ }
+ // FIXME?
+ if (ctor_director) {
+ numarg--;
+ numreq--;
+ }
+
+ /* Insert constraint checking code */
+ insertConstraintCheckingCode(l, f);
+
+ /* Insert cleanup code */
+ insertCleanupCode(l, cleanup);
+
+ /* Insert argument output code */
+ insertArgOutputCode(l, outarg, need_result);
+
+ /* if the object is a director, and the method call originated from its
+ * underlying Ruby object, resolve the call by going up the c++
+ * inheritance chain. otherwise try to resolve the method in Ruby.
+ * without this check an infinite loop is set up between the director and
+ * shadow class method calls.
+ */
+
+ // NOTE: this code should only be inserted if this class is the
+ // base class of a director class. however, in general we haven't
+ // yet analyzed all classes derived from this one to see if they are
+ // directors. furthermore, this class may be used as the base of
+ // a director class defined in a completely different module at a
+ // later time, so this test must be included whether or not directorbase
+ // is true. we do skip this code if directors have not been enabled
+ // at the command line to preserve source-level compatibility with
+ // non-polymorphic swig. also, if this wrapper is for a smart-pointer
+ // method, there is no need to perform the test since the calling object
+ // (the smart-pointer) and the director object (the "pointee") are
+ // distinct.
+
+ director_method = is_member_director(n) && !is_smart_pointer() && !destructor;
+ if (director_method) {
+ Wrapper_add_local(f, "director", "Swig::Director *director = 0");
+ Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n");
+ Wrapper_add_local(f, "upcall", "bool upcall = false");
+ Append(f->code, "upcall = (director && (director->swig_get_self() == self));\n");
+ }
+
+ /* Now write code to make the function call */
+ if (current != CONSTRUCTOR_ALLOCATE) {
+ if (current == CONSTRUCTOR_INITIALIZE) {
+ Node *pn = Swig_methodclass(n);
+ String *symname = Getattr(pn, "sym:name");
+ String *action = Getattr(n, "wrap:action");
+ if (directorsEnabled()) {
+ String *classname = NewStringf("const char *classname SWIGUNUSED = \"%s::%s\"", module, symname);
+ Wrapper_add_local(f, "classname", classname);
+ }
+ if (action) {
+ SwigType *smart = Swig_cparse_smartptr(pn);
+ String *result_name = NewStringf("%s%s", smart ? "smart" : "", Swig_cresult_name());
+ if (smart) {
+ String *result_var = NewStringf("%s *%s = 0", SwigType_namestr(smart), result_name);
+ Wrapper_add_local(f, result_name, result_var);
+ Printf(action, "\n%s = new %s(%s);", result_name, SwigType_namestr(smart), Swig_cresult_name());
+ }
+ Printf(action, "\nDATA_PTR(self) = %s;", result_name);
+ if (GetFlag(pn, "feature:trackobjects")) {
+ Printf(action, "\nSWIG_RubyAddTracking(%s, self);", result_name);
+ }
+ Delete(result_name);
+ Delete(smart);
+ }
+ }
+
+ /* Emit the function call */
+ if (director_method) {
+ Printf(f->code, "try {\n");
+ }
+
+ Setattr(n, "wrap:name", wname);
+
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ if (director_method) {
+ Printf(actioncode, "} catch (Swig::DirectorException& e) {\n");
+ Printf(actioncode, " rb_exc_raise(e.getError());\n");
+ Printf(actioncode, " SWIG_fail;\n");
+ Printf(actioncode, "}\n");
+ }
+
+ /* Return value if necessary */
+ if (SwigType_type(t) != T_VOID && current != CONSTRUCTOR_INITIALIZE) {
+ need_result = 1;
+ if (GetFlag(n, "feature:predicate")) {
+ Printv(actioncode, tab4, "vresult = (", Swig_cresult_name(), " ? Qtrue : Qfalse);\n", NIL);
+ } else {
+ tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode);
+ actioncode = 0;
+ if (tm) {
+ Replaceall(tm, "$result", "vresult");
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Replaceall(tm, "$target", "vresult");
+
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "SWIG_POINTER_OWN");
+ else
+ Replaceall(tm, "$owner", "0");
+
+#if 1
+ // FIXME: this will not try to unwrap directors returned as non-director
+ // base class pointers!
+
+ /* New addition to unwrap director return values so that the original
+ * Ruby object is returned instead.
+ */
+ bool unwrap = false;
+ String *decl = Getattr(n, "decl");
+ int is_pointer = SwigType_ispointer_return(decl);
+ int is_reference = SwigType_isreference_return(decl);
+ if (is_pointer || is_reference) {
+ String *type = Getattr(n, "type");
+ Node *parent = Swig_methodclass(n);
+ Node *modname = Getattr(parent, "module");
+ Node *target = Swig_directormap(modname, type);
+ if (target)
+ unwrap = true;
+ }
+ if (unwrap) {
+ Wrapper_add_local(f, "director", "Swig::Director *director = 0");
+ Printf(f->code, "director = dynamic_cast<Swig::Director *>(%s);\n", Swig_cresult_name());
+ Printf(f->code, "if (director) {\n");
+ Printf(f->code, " vresult = director->swig_get_self();\n");
+ Printf(f->code, "} else {\n");
+ Printf(f->code, "%s\n", tm);
+ Printf(f->code, "}\n");
+ director_method = 0;
+ } else {
+ Printf(f->code, "%s\n", tm);
+ }
+#else
+ Printf(f->code, "%s\n", tm);
+#endif
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s.\n", SwigType_str(t, 0));
+ }
+ }
+ }
+ if (actioncode) {
+ Append(f->code, actioncode);
+ Delete(actioncode);
+ }
+ emit_return_variable(n, t, f);
+ }
+
+ /* Extra code needed for new and initialize methods */
+ if (current == CONSTRUCTOR_ALLOCATE) {
+ Node *pn = Swig_methodclass(n);
+ SwigType *smart = Swig_cparse_smartptr(pn);
+ if (smart)
+ SwigType_add_pointer(smart);
+ String *classtype = smart ? smart : t;
+ need_result = 1;
+ Printf(f->code, "VALUE vresult = SWIG_NewClassInstance(self, SWIGTYPE%s);\n", Char(SwigType_manglestr(classtype)));
+ Printf(f->code, "#ifndef HAVE_RB_DEFINE_ALLOC_FUNC\n");
+ Printf(f->code, "rb_obj_call_init(vresult, argc, argv);\n");
+ Printf(f->code, "#endif\n");
+ Delete(smart);
+ } else if (current == CONSTRUCTOR_INITIALIZE) {
+ need_result = 1;
+ }
+ else
+ {
+ if ( need_result > 1 ) {
+ if ( SwigType_type(t) == T_VOID )
+ Printf(f->code, "vresult = rb_ary_new();\n");
+ else
+ {
+ Printf(f->code, "if (vresult == Qnil) vresult = rb_ary_new();\n");
+ Printf(f->code, "else vresult = SWIG_Ruby_AppendOutput( "
+ "rb_ary_new(), vresult);\n");
+ }
+ }
+ }
+
+ /* Dump argument output code; */
+ Printv(f->code, outarg, NIL);
+
+ /* Dump the argument cleanup code */
+ int need_cleanup = (current != CONSTRUCTOR_ALLOCATE) && (Len(cleanup) != 0);
+ if (need_cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+
+
+ /* Look for any remaining cleanup. This processes the %new directive */
+ if (current != CONSTRUCTOR_ALLOCATE && GetFlag(n, "feature:new")) {
+ tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0);
+ if (tm) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printv(f->code, tm, "\n", NIL);
+ Delete(tm);
+ }
+ }
+
+ /* Special processing on return value. */
+ tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0);
+ if (tm) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printv(f->code, tm, NIL);
+ Delete(tm);
+ }
+
+ if (director_method) {
+ if ((tm = Swig_typemap_lookup("directorfree", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ Replaceall(tm, "$result", "vresult");
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+
+ /* Wrap things up (in a manner of speaking) */
+ if (need_result) {
+ if (current == CONSTRUCTOR_ALLOCATE) {
+ Printv(f->code, tab4, "return vresult;\n", NIL);
+ } else if (current == CONSTRUCTOR_INITIALIZE) {
+ Printv(f->code, tab4, "return self;\n", NIL);
+ Printv(f->code, "fail:\n", NIL);
+ if (need_cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+ Printv(f->code, tab4, "return Qnil;\n", NIL);
+ } else {
+ Wrapper_add_local(f, "vresult", "VALUE vresult = Qnil");
+ Printv(f->code, tab4, "return vresult;\n", NIL);
+ Printv(f->code, "fail:\n", NIL);
+ if (need_cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+ Printv(f->code, tab4, "return Qnil;\n", NIL);
+ }
+ } else {
+ Printv(f->code, tab4, "return Qnil;\n", NIL);
+ Printv(f->code, "fail:\n", NIL);
+ if (need_cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+ Printv(f->code, tab4, "return Qnil;\n", NIL);
+ }
+
+ Printf(f->code, "}\n");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", symname);
+
+ /* Emit the function */
+ Wrapper_print(f, f_wrappers);
+
+ /* Now register the function with the interpreter */
+ if (!Swig_symbol_isoverloaded(n)) {
+ create_command(n, symname);
+ } else {
+ if (current == CONSTRUCTOR_ALLOCATE) {
+ create_command(n, symname);
+ } else {
+ if (!Getattr(n, "sym:nextSibling"))
+ dispatchFunction(n);
+ }
+ }
+
+ Delete(kwargs);
+ Delete(cleanup);
+ Delete(outarg);
+ DelWrapper(f);
+ Delete(symname);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * dispatchFunction()
+ * ------------------------------------------------------------ */
+
+ void dispatchFunction(Node *n) {
+ /* Last node in overloaded chain */
+
+ int maxargs;
+ String *tmp = NewString("");
+ String *dispatch = Swig_overload_dispatch(n, "return %s(nargs, args, self);", &maxargs);
+
+ /* Generate a dispatch wrapper for all overloaded functions */
+
+ Wrapper *f = NewWrapper();
+ String *symname = Getattr(n, "sym:name");
+ String *wname = Swig_name_wrapper(symname);
+
+ Printv(f->def, "SWIGINTERN VALUE ", wname, "(int nargs, VALUE *args, VALUE self) {", NIL);
+
+ Wrapper_add_local(f, "argc", "int argc");
+ bool ctor_director = (current == CONSTRUCTOR_INITIALIZE && Swig_directorclass(n));
+ if (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) {
+ Printf(tmp, "VALUE argv[%d]", maxargs + 1);
+ } else {
+ Printf(tmp, "VALUE argv[%d]", maxargs);
+ }
+ Wrapper_add_local(f, "argv", tmp);
+ Wrapper_add_local(f, "ii", "int ii");
+
+ if (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) {
+ maxargs += 1;
+ Printf(f->code, "argc = nargs + 1;\n");
+ Printf(f->code, "argv[0] = self;\n");
+ Printf(f->code, "if (argc > %d) SWIG_fail;\n", maxargs);
+ Printf(f->code, "for (ii = 1; (ii < argc); ++ii) {\n");
+ Printf(f->code, "argv[ii] = args[ii-1];\n");
+ Printf(f->code, "}\n");
+ } else {
+ Printf(f->code, "argc = nargs;\n");
+ Printf(f->code, "if (argc > %d) SWIG_fail;\n", maxargs);
+ Printf(f->code, "for (ii = 0; (ii < argc); ++ii) {\n");
+ Printf(f->code, "argv[ii] = args[ii];\n");
+ Printf(f->code, "}\n");
+ }
+
+ Replaceall(dispatch, "$args", "nargs, args, self");
+ Printv(f->code, dispatch, "\n", NIL);
+
+
+
+ // Generate prototype list, go to first node
+ Node *sibl = n;
+
+ while (Getattr(sibl, "sym:previousSibling"))
+ sibl = Getattr(sibl, "sym:previousSibling"); // go all the way up
+
+ // Constructors will be treated specially
+ const bool isCtor = (!Cmp(Getattr(sibl, "nodeType"), "constructor"));
+ const bool isMethod = ( Cmp(Getattr(sibl, "ismember"), "1") == 0 &&
+ (!isCtor) );
+
+ // Construct real method name
+ String* methodName = NewString("");
+ if ( isMethod ) {
+ // Sometimes a method node has no parent (SF#3034054).
+ // This value is used in an exception message, so just skip the class
+ // name in this case so at least we don't segfault. This is probably
+ // just working around a problem elsewhere though.
+ Node *parent_node = parentNode(sibl);
+ if (parent_node)
+ Printv( methodName, Getattr(parent_node,"sym:name"), ".", NIL );
+ }
+ Append( methodName, Getattr(sibl,"sym:name" ) );
+ if ( isCtor ) Append( methodName, ".new" );
+
+ // Generate prototype list
+ String *protoTypes = NewString("");
+ do {
+ Append( protoTypes, "\n\" ");
+ if (!isCtor) {
+ SwigType *type = SwigType_str(Getattr(sibl, "type"), NULL);
+ Printv(protoTypes, type, " ", NIL);
+ Delete(type);
+ }
+ Printv(protoTypes, methodName, NIL );
+ Parm* p = Getattr(sibl, "wrap:parms");
+ if (p && (current == MEMBER_FUNC || current == MEMBER_VAR ||
+ ctor_director) )
+ p = nextSibling(p); // skip self
+ Append( protoTypes, "(" );
+ while(p)
+ {
+ Append( protoTypes, SwigType_str(Getattr(p,"type"), Getattr(p,"name")) );
+ if ( ( p = nextSibling(p)) ) Append(protoTypes, ", ");
+ }
+ Append( protoTypes, ")\\n\"" );
+ } while ((sibl = Getattr(sibl, "sym:nextSibling")));
+
+ Append(f->code, "fail:\n");
+ Printf(f->code, "Ruby_Format_OverloadedError( argc, %d, \"%s\", %s);\n",
+ maxargs, methodName, protoTypes);
+ Append(f->code, "\nreturn Qnil;\n");
+
+ Delete(methodName);
+ Delete(protoTypes);
+
+ Printv(f->code, "}\n", NIL);
+ Wrapper_print(f, f_wrappers);
+ create_command(n, Char(symname));
+
+ DelWrapper(f);
+ Delete(dispatch);
+ Delete(tmp);
+ Delete(wname);
+ }
+
+ /* ---------------------------------------------------------------------
+ * variableWrapper()
+ * --------------------------------------------------------------------- */
+
+ virtual int variableWrapper(Node *n) {
+ String* docs = docstring(n, AUTODOC_GETTER);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+
+ char *name = GetChar(n, "name");
+ char *iname = GetChar(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+ String *tm;
+ String *getfname, *setfname;
+ Wrapper *getf, *setf;
+ const int assignable = is_assignable(n);
+
+ // Determine whether virtual global variables shall be used
+ // which have different getter and setter signatures,
+ // see https://docs.ruby-lang.org/en/2.6.0/extension_rdoc.html#label-Global+Variables+Shared+Between+C+and+Ruby
+ const bool use_virtual_var = (current == NO_CPP && useGlobalModule);
+
+ getf = NewWrapper();
+ setf = NewWrapper();
+
+ /* create getter */
+ int addfail = 0;
+ String *getname = Swig_name_get(NSPACE_TODO, iname);
+ getfname = Swig_name_wrapper(getname);
+ Setattr(n, "wrap:name", getfname);
+ Printv(getf->def, "SWIGINTERN VALUE\n", getfname, "(", NIL);
+ Printf(getf->def, (use_virtual_var) ? "ID id, VALUE *data" : "VALUE self");
+ Printf(getf->def, ") {");
+ Wrapper_add_local(getf, "_val", "VALUE _val");
+
+ tm = Swig_typemap_lookup("varout", n, name, 0);
+ if (tm) {
+ Replaceall(tm, "$result", "_val");
+ Replaceall(tm, "$target", "_val");
+ Replaceall(tm, "$source", name);
+ /* Printv(getf->code,tm, NIL); */
+ addfail = emit_action_code(n, getf->code, tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
+ }
+ Printv(getf->code, tab4, "return _val;\n", NIL);
+ if (addfail) {
+ Append(getf->code, "fail:\n");
+ Append(getf->code, " return Qnil;\n");
+ }
+ Append(getf->code, "}\n");
+
+ Wrapper_print(getf, f_wrappers);
+
+ if (!assignable) {
+ setfname = NewString("(rb_gvar_setter_t *)NULL");
+ } else {
+ /* create setter */
+ String* docs = docstring(n, AUTODOC_SETTER);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ String *setname = Swig_name_set(NSPACE_TODO, iname);
+ setfname = Swig_name_wrapper(setname);
+ Setattr(n, "wrap:name", setfname);
+ Printf(setf->def, "SWIGINTERN ");
+ if (use_virtual_var) {
+ Printv(setf->def, "void\n", setfname, "(VALUE _val, ID id, VALUE *data) {", NIL);
+ } else {
+ Printv(setf->def, "VALUE\n", setfname, "(VALUE self, VALUE _val) {", NIL);
+ }
+ tm = Swig_typemap_lookup("varin", n, name, 0);
+ if (tm) {
+ Replaceall(tm, "$input", "_val");
+ Replaceall(tm, "$source", "_val");
+ Replaceall(tm, "$target", name);
+ /* Printv(setf->code,tm,"\n",NIL); */
+ emit_action_code(n, setf->code, tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s\n", SwigType_str(t, 0));
+ }
+ if (use_virtual_var) {
+ Printf(setf->code, "fail:\n");
+ Printv(setf->code, tab4, "return;\n", NIL);
+ } else {
+ Printv(setf->code, tab4, "return _val;\n", NIL);
+ Printf(setf->code, "fail:\n");
+ Printv(setf->code, tab4, "return Qnil;\n", NIL);
+ }
+ Printf(setf->code, "}\n");
+ Wrapper_print(setf, f_wrappers);
+ Delete(setname);
+ }
+
+ /* define accessor methods */
+ Insert(getfname, 0, "VALUEFUNC(");
+ Append(getfname, ")");
+ Insert(setfname, 0, (use_virtual_var) ? "SWIG_RUBY_VOID_ANYARGS_FUNC(" : "VALUEFUNC(");
+ Append(setfname, ")");
+
+ String *s = NewString("");
+ switch (current) {
+ case STATIC_VAR:
+ /* C++ class variable */
+ Printv(s, tab4, "rb_define_singleton_method(", klass->vname, ", \"", klass->strip(iname), "\", ", getfname, ", 0);\n", NIL);
+ if (assignable) {
+ Printv(s, tab4, "rb_define_singleton_method(", klass->vname, ", \"", klass->strip(iname), "=\", ", setfname, ", 1);\n", NIL);
+ }
+ Printv(klass->init, s, NIL);
+ break;
+ default:
+ /* C global variable */
+ /* wrapped in Ruby module attribute */
+ assert(current == NO_CPP);
+ if (!useGlobalModule) {
+ Printv(s, tab4, "rb_define_singleton_method(", modvar, ", \"", iname, "\", ", getfname, ", 0);\n", NIL);
+ if (assignable) {
+ Printv(s, tab4, "rb_define_singleton_method(", modvar, ", \"", iname, "=\", ", setfname, ", 1);\n", NIL);
+ }
+ } else {
+ Printv(s, tab4, "rb_define_virtual_variable(\"$", iname, "\", ", getfname, ", ", setfname, ");\n", NIL);
+ }
+ Printv(f_init, s, NIL);
+ Delete(s);
+ break;
+ }
+ Delete(getname);
+ Delete(getfname);
+ Delete(setfname);
+ DelWrapper(setf);
+ DelWrapper(getf);
+ return SWIG_OK;
+ }
+
+
+ /* ---------------------------------------------------------------------
+ * validate_const_name(char *name)
+ *
+ * Validate constant name.
+ * --------------------------------------------------------------------- */
+
+ char *validate_const_name(char *name, const char *reason) {
+ if (!name || name[0] == '\0')
+ return name;
+
+ if (isupper(name[0]))
+ return name;
+
+ if (islower(name[0])) {
+ name[0] = (char)toupper(name[0]);
+ Swig_warning(WARN_RUBY_WRONG_NAME, input_file, line_number, "Wrong %s name (corrected to `%s')\n", reason, name);
+ return name;
+ }
+
+ Swig_warning(WARN_RUBY_WRONG_NAME, input_file, line_number, "Wrong %s name %s\n", reason, name);
+
+ return name;
+ }
+
+ /* ---------------------------------------------------------------------
+ * constantWrapper()
+ * --------------------------------------------------------------------- */
+
+ virtual int constantWrapper(Node *n) {
+ Swig_require("constantWrapper", n, "*sym:name", "type", "value", NIL);
+
+ char *iname = GetChar(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *rawval = Getattr(n, "rawval");
+ String *value = rawval ? rawval : Getattr(n, "value");
+
+ if (current == CLASS_CONST) {
+ iname = klass->strip(iname);
+ }
+ validate_const_name(iname, "constant");
+ SetChar(n, "sym:name", iname);
+
+ /* Special hook for member pointer */
+ if (SwigType_type(type) == T_MPOINTER) {
+ String *wname = Swig_name_wrapper(iname);
+ Printf(f_header, "static %s = %s;\n", SwigType_str(type, wname), value);
+ value = Char(wname);
+ }
+ String *tm = Swig_typemap_lookup("constant", n, value, 0);
+ if (!tm)
+ tm = Swig_typemap_lookup("constcode", n, value, 0);
+ if (tm) {
+ Replaceall(tm, "$source", value);
+ Replaceall(tm, "$target", iname);
+ Replaceall(tm, "$symname", iname);
+ Replaceall(tm, "$value", value);
+ if (current == CLASS_CONST) {
+ if (multipleInheritance) {
+ Replaceall(tm, "$module", klass->mImpl);
+ Printv(klass->init, tm, "\n", NIL);
+ } else {
+ Replaceall(tm, "$module", klass->vname);
+ Printv(klass->init, tm, "\n", NIL);
+ }
+ } else {
+ if (!useGlobalModule) {
+ Replaceall(tm, "$module", modvar);
+ } else {
+ Replaceall(tm, "$module", "rb_cObject");
+ }
+ Printf(f_init, "%s\n", tm);
+ }
+ } else {
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value %s = %s\n", SwigType_str(type, 0), value);
+ }
+ Swig_restore(n);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * classDeclaration()
+ *
+ * Records information about classes---even classes that might be defined in
+ * other modules referenced by %import.
+ * ----------------------------------------------------------------------------- */
+
+ virtual int classDeclaration(Node *n) {
+ if (!Getattr(n, "feature:onlychildren")) {
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+
+ String *namestr = SwigType_namestr(name);
+ klass = RCLASS(classes, Char(namestr));
+ if (!klass) {
+ klass = new RClass();
+ String *valid_name = NewString(symname ? symname : namestr);
+ validate_const_name(Char(valid_name), "class");
+ klass->set_name(namestr, symname, valid_name);
+ SET_RCLASS(classes, Char(namestr), klass);
+ Delete(valid_name);
+ }
+ Delete(namestr);
+ }
+ return Language::classDeclaration(n);
+ }
+
+ /**
+ * Process the comma-separated list of mixed-in module names (if any).
+ */
+ void includeRubyModules(Node *n) {
+ String *mixin = Getattr(n, "feature:mixin");
+ if (mixin) {
+ List *modules = Split(mixin, ',', INT_MAX);
+ if (modules && Len(modules) > 0) {
+ Iterator mod = First(modules);
+ while (mod.item) {
+ if (Len(mod.item) > 0) {
+ Printf(klass->init, "rb_include_module(%s, rb_eval_string(\"%s\"));\n", klass->vname, mod.item);
+ }
+ mod = Next(mod);
+ }
+ }
+ Delete(modules);
+ }
+ }
+
+ void handleBaseClasses(Node *n) {
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator base = First(baselist);
+ while (base.item && GetFlag(base.item, "feature:ignore")) {
+ base = Next(base);
+ }
+ while (base.item) {
+ String *basename = Getattr(base.item, "name");
+ String *basenamestr = SwigType_namestr(basename);
+ RClass *super = RCLASS(classes, Char(basenamestr));
+ Delete(basenamestr);
+ if (super) {
+ SwigType *btype = NewString(basename);
+ SwigType_add_pointer(btype);
+ SwigType_remember(btype);
+ SwigType *smart = Swig_cparse_smartptr(base.item);
+ if (smart) {
+ SwigType_add_pointer(smart);
+ SwigType_remember(smart);
+ }
+ String *bmangle = SwigType_manglestr(smart ? smart : btype);
+ if (multipleInheritance) {
+ Insert(bmangle, 0, "((swig_class *) SWIGTYPE");
+ Append(bmangle, "->clientdata)->mImpl");
+ Printv(klass->init, "rb_include_module(", klass->mImpl, ", ", bmangle, ");\n", NIL);
+ } else {
+ Insert(bmangle, 0, "((swig_class *) SWIGTYPE");
+ Append(bmangle, "->clientdata)->klass");
+ Replaceall(klass->init, "$super", bmangle);
+ }
+ Delete(bmangle);
+ Delete(smart);
+ Delete(btype);
+ }
+ base = Next(base);
+ while (base.item && GetFlag(base.item, "feature:ignore")) {
+ base = Next(base);
+ }
+ if (!multipleInheritance) {
+ /* Warn about multiple inheritance for additional base class(es) */
+ while (base.item) {
+ if (GetFlag(base.item, "feature:ignore")) {
+ base = Next(base);
+ continue;
+ }
+ String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
+ String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
+ Swig_warning(WARN_RUBY_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Warning for %s, base %s ignored. Multiple inheritance is not supported in Ruby.\n", proxyclassname, baseclassname);
+ base = Next(base);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Check to see if a %markfunc was specified.
+ */
+ void handleMarkFuncDirective(Node *n) {
+ String *markfunc = Getattr(n, "feature:markfunc");
+ if (markfunc) {
+ Printf(klass->init, "SwigClass%s.mark = (void (*)(void *)) %s;\n", klass->name, markfunc);
+ } else {
+ Printf(klass->init, "SwigClass%s.mark = 0;\n", klass->name);
+ }
+ }
+
+ /**
+ * Check to see if a %freefunc was specified.
+ */
+ void handleFreeFuncDirective(Node *n) {
+ String *freefunc = Getattr(n, "feature:freefunc");
+ if (freefunc) {
+ Printf(klass->init, "SwigClass%s.destroy = (void (*)(void *)) %s;\n", klass->name, freefunc);
+ } else {
+ if (klass->destructor_defined) {
+ Printf(klass->init, "SwigClass%s.destroy = (void (*)(void *)) free_%s;\n", klass->name, klass->mname);
+ }
+ }
+ }
+
+ /**
+ * Check to see if tracking is enabled for this class.
+ */
+ void handleTrackDirective(Node *n) {
+ int trackObjects = GetFlag(n, "feature:trackobjects");
+ if (trackObjects) {
+ Printf(klass->init, "SwigClass%s.trackObjects = 1;\n", klass->name);
+ } else {
+ Printf(klass->init, "SwigClass%s.trackObjects = 0;\n", klass->name);
+ }
+ }
+
+ /* ----------------------------------------------------------------------
+ * classHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int classHandler(Node *n) {
+ String* docs = docstring(n, AUTODOC_CLASS);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *namestr = SwigType_namestr(name); // does template expansion
+
+ klass = RCLASS(classes, Char(namestr));
+ assert(klass != 0);
+ Delete(namestr);
+ String *valid_name = NewString(symname);
+ validate_const_name(Char(valid_name), "class");
+
+ Clear(klass->type);
+ Printv(klass->type, Getattr(n, "classtype"), NIL);
+ Printv(f_wrappers, "static swig_class SwigClass", valid_name, ";\n\n", NIL);
+ Printv(klass->init, "\n", tab4, NIL);
+
+ if (!useGlobalModule) {
+ Printv(klass->init, klass->vname, " = rb_define_class_under(", modvar, ", \"", klass->name, "\", $super);\n", NIL);
+ } else {
+ Printv(klass->init, klass->vname, " = rb_define_class(\"", klass->name,
+ "\", $super);\n", NIL);
+ }
+
+ if (multipleInheritance) {
+ Printv(klass->init, klass->mImpl, " = rb_define_module_under(", klass->vname, ", \"Impl\");\n", NIL);
+ }
+
+ SwigType *tt = NewString(name);
+ SwigType_add_pointer(tt);
+ SwigType_remember(tt);
+ SwigType *smart = Swig_cparse_smartptr(n);
+ if (smart) {
+ SwigType_add_pointer(smart);
+ SwigType_remember(smart);
+ }
+ String *tm = SwigType_manglestr(smart ? smart : tt);
+ Printf(klass->init, "SWIG_TypeClientData(SWIGTYPE%s, (void *) &SwigClass%s);\n", tm, valid_name);
+ Delete(tm);
+ Delete(smart);
+ Delete(tt);
+ Delete(valid_name);
+
+ includeRubyModules(n);
+
+ Printv(klass->init, "$allocator", NIL);
+ Printv(klass->init, "$initializer", NIL);
+
+ Language::classHandler(n);
+
+ handleBaseClasses(n);
+ handleMarkFuncDirective(n);
+ handleFreeFuncDirective(n);
+ handleTrackDirective(n);
+
+ if (multipleInheritance) {
+ Printv(klass->init, "rb_include_module(", klass->vname, ", ", klass->mImpl, ");\n", NIL);
+ }
+
+ String *s = NewString("");
+ Printv(s, tab4, "rb_undef_alloc_func(", klass->vname, ");\n", NIL);
+ Replaceall(klass->init, "$allocator", s);
+ Replaceall(klass->init, "$initializer", "");
+
+ if (GetFlag(n, "feature:exceptionclass")) {
+ Replaceall(klass->init, "$super", "rb_eRuntimeError");
+ } else {
+ Replaceall(klass->init, "$super", "rb_cObject");
+ }
+ Delete(s);
+
+ Printv(f_init, klass->init, NIL);
+ klass = 0;
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * memberfunctionHandler()
+ *
+ * Method for adding C++ member function
+ *
+ * By default, we're going to create a function of the form :
+ *
+ * Foo_bar(this,args)
+ *
+ * Where Foo is the classname, bar is the member name and the this pointer
+ * is explicitly attached to the beginning.
+ *
+ * The renaming only applies to the member function part, not the full
+ * classname.
+ *
+ * --------------------------------------------------------------------- */
+
+ virtual int memberfunctionHandler(Node *n) {
+ current = MEMBER_FUNC;
+
+ String* docs = docstring(n, AUTODOC_METHOD);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ Language::memberfunctionHandler(n);
+ current = NO_CPP;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------
+ * constructorHandler()
+ *
+ * Method for adding C++ member constructor
+ * -------------------------------------------------------------------- */
+
+ void set_director_ctor_code(Node *n) {
+ /* director ctor code is specific for each class */
+ Delete(director_prot_ctor_code);
+ director_prot_ctor_code = NewString("");
+ Node *pn = Swig_methodclass(n);
+ String *symname = Getattr(pn, "sym:name");
+ String *name = Copy(symname);
+ char *cname = Char(name);
+ if (cname)
+ cname[0] = (char)toupper(cname[0]);
+ Printv(director_prot_ctor_code,
+ "if ( $comparison ) { /* subclassed */\n",
+ " $director_new \n",
+ "} else {\n", " rb_raise(rb_eNameError,\"accessing abstract class or protected constructor\"); \n", " return Qnil;\n", "}\n", NIL);
+ Delete(director_ctor_code);
+ director_ctor_code = NewString("");
+ Printv(director_ctor_code, "if ( $comparison ) { /* subclassed */\n", " $director_new \n", "} else {\n", " $nondirector_new \n", "}\n", NIL);
+ Delete(name);
+ }
+
+ virtual int constructorHandler(Node *n) {
+ int use_director = Swig_directorclass(n);
+ if (use_director) {
+ set_director_ctor_code(n);
+ }
+
+ /* First wrap the allocate method */
+ current = CONSTRUCTOR_ALLOCATE;
+ Swig_name_register("construct", "%n%c_allocate");
+
+ Language::constructorHandler(n);
+
+ String* docs = docstring(n, AUTODOC_CTOR);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ /*
+ * If we're wrapping the constructor of a C++ director class, prepend a new parameter
+ * to receive the scripting language object (e.g. 'self')
+ *
+ */
+ Swig_save("ruby:constructorHandler", n, "parms", NIL);
+ if (use_director) {
+ Parm *parms = Getattr(n, "parms");
+ Parm *self;
+ String *name = NewString("self");
+ String *type = NewString("VALUE");
+ self = NewParm(type, name, n);
+ Delete(type);
+ Delete(name);
+ Setattr(self, "lname", "Qnil");
+ if (parms)
+ set_nextSibling(self, parms);
+ Setattr(n, "parms", self);
+ Setattr(n, "wrap:self", "1");
+ Delete(self);
+ }
+
+ /* Now do the instance initialize method */
+ current = CONSTRUCTOR_INITIALIZE;
+ Swig_name_register("construct", "new_%n%c");
+ Language::constructorHandler(n);
+
+ /* Restore original parameter list */
+ Delattr(n, "wrap:self");
+ Swig_restore(n);
+
+ /* Done */
+ Swig_name_unregister("construct");
+ current = NO_CPP;
+ klass->constructor_defined = 1;
+ return SWIG_OK;
+ }
+
+ virtual int copyconstructorHandler(Node *n) {
+ int use_director = Swig_directorclass(n);
+ if (use_director) {
+ set_director_ctor_code(n);
+ }
+
+ /* First wrap the allocate method */
+ current = CONSTRUCTOR_ALLOCATE;
+ Swig_name_register("construct", "%n%c_allocate");
+
+ return Language::copyconstructorHandler(n);
+ }
+
+
+ /* ---------------------------------------------------------------------
+ * destructorHandler()
+ * -------------------------------------------------------------------- */
+
+ virtual int destructorHandler(Node *n) {
+
+ /* Do no spit free function if user defined his own for this class */
+ Node *pn = Swig_methodclass(n);
+ String *freefunc = Getattr(pn, "feature:freefunc");
+ if (freefunc) return SWIG_OK;
+
+ current = DESTRUCTOR;
+ Language::destructorHandler(n);
+
+ freefunc = NewString("");
+ String *freebody = NewString("");
+ String *pname0 = Swig_cparm_name(0, 0);
+
+ Printv(freefunc, "free_", klass->mname, NIL);
+ Printv(freebody, "SWIGINTERN void\n", freefunc, "(void *self) {\n", NIL);
+ Printv(freebody, tab4, klass->type, " *", pname0, " = (", klass->type, " *)self;\n", NIL);
+ Printv(freebody, tab4, NIL);
+
+ /* Check to see if object tracking is activated for the class
+ that owns this destructor. */
+ if (GetFlag(pn, "feature:trackobjects")) {
+ Printf(freebody, "SWIG_RubyRemoveTracking(%s);\n", pname0);
+ Printv(freebody, tab4, NIL);
+ }
+
+ if (Extend) {
+ String *wrap = Getattr(n, "wrap:code");
+ if (wrap) {
+ Printv(f_wrappers, wrap, NIL);
+ }
+ /* Printv(freebody, Swig_name_destroy(name), "(", pname0, ")", NIL); */
+ Printv(freebody, Getattr(n, "wrap:action"), "\n", NIL);
+ } else {
+ String *action = Getattr(n, "wrap:action");
+ if (action) {
+ Printv(freebody, action, "\n", NIL);
+ } else {
+ /* In the case swig emits no destroy function. */
+ if (CPlusPlus)
+ Printf(freebody, "delete %s;\n", pname0);
+ else
+ Printf(freebody, "free((char*) %s);\n", pname0);
+ }
+ }
+
+ Printv(freebody, "}\n\n", NIL);
+
+ Printv(f_wrappers, freebody, NIL);
+
+ klass->destructor_defined = 1;
+ current = NO_CPP;
+ Delete(freefunc);
+ Delete(freebody);
+ Delete(pname0);
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------
+ * membervariableHandler()
+ *
+ * This creates a pair of functions to set/get the variable of a member.
+ * -------------------------------------------------------------------- */
+
+ virtual int membervariableHandler(Node *n) {
+ String* docs = docstring(n, AUTODOC_GETTER);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ if (is_assignable(n)) {
+ String* docs = docstring(n, AUTODOC_SETTER);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+ }
+
+ current = MEMBER_VAR;
+ Language::membervariableHandler(n);
+ current = NO_CPP;
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ *
+ * Wrap a static C++ function
+ * ---------------------------------------------------------------------- */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ String* docs = docstring(n, AUTODOC_STATICFUNC);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ current = STATIC_FUNC;
+ Language::staticmemberfunctionHandler(n);
+ current = NO_CPP;
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * memberconstantHandler()
+ *
+ * Create a C++ constant
+ * --------------------------------------------------------------------- */
+
+ virtual int memberconstantHandler(Node *n) {
+ String* docs = docstring(n, AUTODOC_STATICFUNC);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ current = CLASS_CONST;
+ Language::memberconstantHandler(n);
+ current = NO_CPP;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------
+ * staticmembervariableHandler()
+ * --------------------------------------------------------------------- */
+
+ virtual int staticmembervariableHandler(Node *n) {
+ String* docs = docstring(n, AUTODOC_GETTER);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ if (is_assignable(n)) {
+ String* docs = docstring(n, AUTODOC_SETTER);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+ }
+
+ current = STATIC_VAR;
+ Language::staticmembervariableHandler(n);
+ current = NO_CPP;
+ return SWIG_OK;
+ }
+
+ /* C++ director class generation */
+ virtual int classDirector(Node *n) {
+ return Language::classDirector(n);
+ }
+
+ virtual int classDirectorInit(Node *n) {
+ String *declaration;
+ declaration = Swig_director_declaration(n);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "%s\n", declaration);
+ Printf(f_directors_h, "public:\n");
+ Delete(declaration);
+ return Language::classDirectorInit(n);
+ }
+
+ virtual int classDirectorEnd(Node *n) {
+ Printf(f_directors_h, "};\n\n");
+ return Language::classDirectorEnd(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorConstructor()
+ * ------------------------------------------------------------ */
+
+ virtual int classDirectorConstructor(Node *n) {
+ Node *parent = Getattr(n, "parentNode");
+ String *sub = NewString("");
+ String *decl = Getattr(n, "decl");
+ String *supername = Swig_class_name(parent);
+ String *classname = NewString("");
+ Printf(classname, "SwigDirector_%s", supername);
+
+ /* insert self parameter */
+ Parm *p;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms = CopyParmList(superparms);
+ String *type = NewString("VALUE");
+ p = NewParm(type, NewString("self"), n);
+ set_nextSibling(p, parms);
+ parms = p;
+
+ if (!Getattr(n, "defaultargs")) {
+ /* constructor */
+ {
+ Wrapper *w = NewWrapper();
+ String *call;
+ String *basetype = Getattr(parent, "classtype");
+ String *target = Swig_method_decl(0, decl, classname, parms, 0);
+ call = Swig_csuperclass_call(0, basetype, superparms);
+ Printf(w->def, "%s::%s: %s, Swig::Director(self) { }", classname, target, call);
+ Delete(target);
+ Wrapper_print(w, f_directors);
+ Delete(call);
+ DelWrapper(w);
+ }
+
+ /* constructor header */
+ {
+ String *target = Swig_method_decl(0, decl, classname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Delete(sub);
+ Delete(classname);
+ Delete(supername);
+ Delete(parms);
+ return Language::classDirectorConstructor(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDefaultConstructor()
+ * ------------------------------------------------------------ */
+
+ virtual int classDirectorDefaultConstructor(Node *n) {
+ String *classname;
+ Wrapper *w;
+ classname = Swig_class_name(n);
+ w = NewWrapper();
+ Printf(w->def, "SwigDirector_%s::SwigDirector_%s(VALUE self) : Swig::Director(self) { }", classname, classname);
+ Wrapper_print(w, f_directors);
+ DelWrapper(w);
+ Printf(f_directors_h, " SwigDirector_%s(VALUE self);\n", classname);
+ Delete(classname);
+ return Language::classDirectorDefaultConstructor(n);
+ }
+
+ /* ---------------------------------------------------------------
+ * exceptionSafeMethodCall()
+ *
+ * Emit a virtual director method to pass a method call on to the
+ * underlying Ruby instance.
+ *
+ * --------------------------------------------------------------- */
+
+ void exceptionSafeMethodCall(String *className, Node *n, Wrapper *w, int argc, String *args, bool initstack) {
+ Wrapper *body = NewWrapper();
+ Wrapper *rescue = NewWrapper();
+
+ String *methodName = Getattr(n, "sym:name");
+
+ String *bodyName = NewStringf("%s_%s_body", className, methodName);
+ String *rescueName = NewStringf("%s_%s_rescue", className, methodName);
+ String *depthCountName = NewStringf("%s_%s_call_depth", className, methodName);
+
+ // Check for an exception typemap of some kind
+ String *tm = Swig_typemap_lookup("director:except", n, Swig_cresult_name(), 0);
+ if (!tm) {
+ tm = Getattr(n, "feature:director:except");
+ }
+
+ if ((tm != 0) && (Len(tm) > 0) && (Strcmp(tm, "1") != 0)) {
+ // Declare a global to hold the depth count
+ if (!Getattr(n, "sym:nextSibling")) {
+ Printf(body->def, "static int %s = 0;\n", depthCountName);
+
+ // Function body
+ Printf(body->def, "VALUE %s(VALUE data) {\n", bodyName);
+ Wrapper_add_localv(body, "args", "Swig::body_args *", "args", "= reinterpret_cast<Swig::body_args *>(data)", NIL);
+ Wrapper_add_localv(body, Swig_cresult_name(), "VALUE", Swig_cresult_name(), "= Qnil", NIL);
+ Printf(body->code, "%s++;\n", depthCountName);
+ Printv(body->code, Swig_cresult_name(), " = rb_funcall2(args->recv, args->id, args->argc, args->argv);\n", NIL);
+ Printf(body->code, "%s--;\n", depthCountName);
+ Printv(body->code, "return ", Swig_cresult_name(), ";\n", NIL);
+ Printv(body->code, "}", NIL);
+
+ // Exception handler
+ Printf(rescue->def, "VALUE %s(VALUE args, VALUE error) {\n", rescueName);
+ Replaceall(tm, "$error", "error");
+ Printf(rescue->code, "%s--;\n", depthCountName);
+ Printf(rescue->code, "if (%s == 0) ", depthCountName);
+ Printv(rescue->code, Str(tm), "\n", NIL);
+ Printv(rescue->code, "rb_exc_raise(error);\n", NIL);
+ Printv(rescue->code, "return Qnil;\n", NIL);
+ Printv(rescue->code, "}", NIL);
+ }
+
+ // Main code
+ Wrapper_add_localv(w, "args", "Swig::body_args", "args", NIL);
+ Wrapper_add_localv(w, "status", "int", "status", NIL);
+ Printv(w->code, "args.recv = swig_get_self();\n", NIL);
+ Printf(w->code, "args.id = rb_intern(\"%s\");\n", methodName);
+ Printf(w->code, "args.argc = %d;\n", argc);
+ if (argc > 0) {
+ Printf(w->code, "args.argv = new VALUE[%d];\n", argc);
+ for (int i = 0; i < argc; i++) {
+ Printf(w->code, "args.argv[%d] = obj%d;\n", i, i);
+ }
+ } else {
+ Printv(w->code, "args.argv = 0;\n", NIL);
+ }
+ Printf(w->code, "%s = rb_protect(PROTECTFUNC(%s), reinterpret_cast<VALUE>(&args), &status);\n", Swig_cresult_name(), bodyName);
+ if ( initstack ) Printf(w->code, "SWIG_RELEASE_STACK;\n");
+ Printf(w->code, "if (status) {\n");
+ Printf(w->code, "VALUE lastErr = rb_gv_get(\"$!\");\n");
+ Printf(w->code, "%s(reinterpret_cast<VALUE>(&args), lastErr);\n", rescueName);
+ Printf(w->code, "}\n");
+ if (argc > 0) {
+ Printv(w->code, "delete [] args.argv;\n", NIL);
+ }
+ // Dump wrapper code
+ Wrapper_print(body, f_directors_helpers);
+ Wrapper_print(rescue, f_directors_helpers);
+ } else {
+ if (argc > 0) {
+ Printf(w->code, "%s = rb_funcall(swig_get_self(), rb_intern(\"%s\"), %d%s);\n", Swig_cresult_name(), methodName, argc, args);
+ } else {
+ Printf(w->code, "%s = rb_funcall(swig_get_self(), rb_intern(\"%s\"), 0, Qnil);\n", Swig_cresult_name(), methodName);
+ }
+ if ( initstack ) Printf(w->code, "SWIG_RELEASE_STACK;\n");
+ }
+
+ // Clean up
+ Delete(bodyName);
+ Delete(rescueName);
+ Delete(depthCountName);
+ DelWrapper(body);
+ DelWrapper(rescue);
+ }
+
+ virtual int classDirectorMethod(Node *n, Node *parent, String *super) {
+ int is_void = 0;
+ int is_pointer = 0;
+ String *decl = Getattr(n, "decl");
+ String *name = Getattr(n, "name");
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *declaration = NewString("");
+ ParmList *l = Getattr(n, "parms");
+ Wrapper *w = NewWrapper();
+ String *tm;
+ String *wrap_args = NewString("");
+ String *returntype = Getattr(n, "type");
+ Parm *p;
+ String *value = Getattr(n, "value");
+ String *storage = Getattr(n, "storage");
+ bool pure_virtual = false;
+ int status = SWIG_OK;
+ int idx;
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+ bool asvoid = checkAttribute( n, "feature:numoutputs", "0") ? true : false;
+ bool initstack = checkAttribute( n, "feature:initstack", "1") ? true : false;
+
+ if (Cmp(storage, "virtual") == 0) {
+ if (Cmp(value, "0") == 0) {
+ pure_virtual = true;
+ }
+ }
+ String *overnametmp = NewString(Getattr(n, "sym:name"));
+ if (Getattr(n, "sym:overloaded")) {
+ Printf(overnametmp, "::%s", Getattr(n, "sym:overname"));
+ }
+
+ /* determine if the method returns a pointer */
+ is_pointer = SwigType_ispointer_return(decl);
+ is_void = (!Cmp(returntype, "void") && !is_pointer);
+
+ /* virtual method definition */
+ String *target;
+ String *pclassname = NewStringf("SwigDirector_%s", classname);
+ String *qualified_name = NewStringf("%s::%s", pclassname, name);
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ /* header declaration */
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Get any exception classes in the throws typemap
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ ParmList *throw_parm_list = 0;
+
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ Parm *p;
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list)
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+
+ Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0));
+ Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0));
+ }
+ }
+
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+
+ if (initstack && !(ignored_method && !pure_virtual)) {
+ Append(w->def, "\nSWIG_INIT_STACK;\n");
+ }
+
+ /* declare method return value
+ * if the return value is a reference or const reference, a specialized typemap must
+ * handle it, including declaration of c_result ($result).
+ */
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ }
+ } else {
+ String *cres = SwigType_lstr(returntype, "c_result");
+ Printf(w->code, "%s;\n", cres);
+ Delete(cres);
+ }
+ }
+
+ if (ignored_method) {
+ if (!pure_virtual) {
+ if (!is_void)
+ Printf(w->code, "return ");
+ String *super_call = Swig_method_call(super, l);
+ Printf(w->code, "%s;\n", super_call);
+ Delete(super_call);
+ } else {
+ Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname),
+ SwigType_namestr(name));
+ }
+ } else {
+ /* attach typemaps to arguments (C/C++ -> Ruby) */
+ String *arglist = NewString("");
+
+ Swig_director_parms_fixup(l);
+
+ Swig_typemap_attach_parms("in", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ char source[256];
+
+ int outputs = 0;
+ if (!is_void && !asvoid)
+ outputs++;
+
+ /* build argument list and type conversion string */
+ idx = 0; p = l;
+ while ( p ) {
+
+ if (Getattr(p, "tmap:ignore")) {
+ p = Getattr(p, "tmap:ignore:next");
+ continue;
+ }
+
+ if (Getattr(p, "tmap:directorargout") != 0)
+ outputs++;
+
+ if ( checkAttribute( p, "tmap:in:numinputs", "0") ) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ String *parameterName = Getattr(p, "name");
+ String *parameterType = Getattr(p, "type");
+
+ Putc(',', arglist);
+ if ((tm = Getattr(p, "tmap:directorin")) != 0) {
+ sprintf(source, "obj%d", idx++);
+ String *input = NewString(source);
+ Setattr(p, "emit:directorinput", input);
+ Replaceall(tm, "$input", input);
+ Replaceall(tm, "$owner", "0");
+ Delete(input);
+ Printv(wrap_args, tm, "\n", NIL);
+ Wrapper_add_localv(w, source, "VALUE", source, "= Qnil", NIL);
+ Printv(arglist, source, NIL);
+ p = Getattr(p, "tmap:directorin:next");
+ continue;
+ } else if (Cmp(parameterType, "void")) {
+ /**
+ * Special handling for pointers to other C++ director classes.
+ * Ideally this would be left to a typemap, but there is currently no
+ * way to selectively apply the dynamic_cast<> to classes that have
+ * directors. In other words, the type "SwigDirector_$1_lname" only exists
+ * for classes with directors. We avoid the problem here by checking
+ * module.wrap::directormap, but it's not clear how to get a typemap to
+ * do something similar. Perhaps a new default typemap (in addition
+ * to SWIGTYPE) called DIRECTORTYPE?
+ */
+ if (SwigType_ispointer(parameterType) || SwigType_isreference(parameterType)) {
+ Node *modname = Getattr(parent, "module");
+ Node *target = Swig_directormap(modname, parameterType);
+ sprintf(source, "obj%d", idx++);
+ String *nonconst = 0;
+ /* strip pointer/reference --- should move to Swig/stype.c */
+ String *nptype = NewString(Char(parameterType) + 2);
+ /* name as pointer */
+ String *ppname = Copy(parameterName);
+ if (SwigType_isreference(parameterType)) {
+ Insert(ppname, 0, "&");
+ }
+ /* if necessary, cast away const since Ruby doesn't support it! */
+ if (SwigType_isconst(nptype)) {
+ nonconst = NewStringf("nc_tmp_%s", parameterName);
+ String *nonconst_i = NewStringf("= const_cast< %s >(%s)", SwigType_lstr(parameterType, 0), ppname);
+ Wrapper_add_localv(w, nonconst, SwigType_lstr(parameterType, 0), nonconst, nonconst_i, NIL);
+ Delete(nonconst_i);
+ Swig_warning(WARN_LANG_DISCARD_CONST, input_file, line_number,
+ "Target language argument '%s' discards const in director method %s::%s.\n", SwigType_str(parameterType, parameterName),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ } else {
+ nonconst = Copy(ppname);
+ }
+ Delete(nptype);
+ Delete(ppname);
+ String *mangle = SwigType_manglestr(parameterType);
+ if (target) {
+ String *director = NewStringf("director_%s", mangle);
+ Wrapper_add_localv(w, director, "Swig::Director *", director, "= 0", NIL);
+ Wrapper_add_localv(w, source, "VALUE", source, "= Qnil", NIL);
+ Printf(wrap_args, "%s = dynamic_cast<Swig::Director *>(%s);\n", director, nonconst);
+ Printf(wrap_args, "if (!%s) {\n", director);
+ Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
+ Printf(wrap_args, "} else {\n");
+ Printf(wrap_args, "%s = %s->swig_get_self();\n", source, director);
+ Printf(wrap_args, "}\n");
+ Delete(director);
+ Printv(arglist, source, NIL);
+ } else {
+ Wrapper_add_localv(w, source, "VALUE", source, "= Qnil", NIL);
+ Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
+ //Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE_p_%s, 0);\n",
+ // source, nonconst, base);
+ Printv(arglist, source, NIL);
+ }
+ Delete(mangle);
+ Delete(nonconst);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
+ "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(parameterType, 0),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_NOWRAP;
+ break;
+ }
+ }
+ p = nextSibling(p);
+ }
+
+ /* declare Ruby return value */
+ String *value_result = NewStringf("VALUE SWIGUNUSED %s", Swig_cresult_name());
+ Wrapper_add_local(w, Swig_cresult_name(), value_result);
+ Delete(value_result);
+
+ /* wrap complex arguments to VALUEs */
+ Printv(w->code, wrap_args, NIL);
+
+ /* pass the method call on to the Ruby object */
+ exceptionSafeMethodCall(classname, n, w, idx, arglist, initstack);
+
+ /*
+ * Ruby method may return a simple object, or an Array of objects.
+ * For in/out arguments, we have to extract the appropriate VALUEs from the Array,
+ * then marshal everything back to C/C++ (return value and output arguments).
+ */
+
+ /* Marshal return value and other outputs (if any) from VALUE to C/C++ type */
+
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+
+ if (outputs > 1) {
+ Wrapper_add_local(w, "output", "VALUE output");
+ Printf(w->code, "if (TYPE(%s) != T_ARRAY) {\n", Swig_cresult_name());
+ Printf(w->code, "Ruby_DirectorTypeMismatchException(\"Ruby method failed to return an array.\");\n");
+ Printf(w->code, "}\n");
+ }
+
+ idx = 0;
+
+ /* Marshal return value */
+ if (!is_void) {
+ tm = Swig_typemap_lookup("directorout", n, Swig_cresult_name(), w);
+ if (tm != 0) {
+ if (outputs > 1 && !asvoid ) {
+ Printf(w->code, "output = rb_ary_entry(%s, %d);\n", Swig_cresult_name(), idx++);
+ Replaceall(tm, "$input", "output");
+ } else {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ }
+ /* TODO check this */
+ if (Getattr(n, "wrap:disown")) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, tm, "\n", NIL);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s in director method %s::%s (skipping method).\n", SwigType_str(returntype, 0),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_ERROR;
+ }
+ }
+
+ /* Marshal outputs */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout")) != 0) {
+ if (outputs > 1) {
+ Printf(w->code, "output = rb_ary_entry(%s, %d);\n", Swig_cresult_name(), idx++);
+ Replaceall(tm, "$result", "output");
+ } else {
+ Replaceall(tm, "$result", Swig_cresult_name());
+ }
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ Delete(arglist);
+ Delete(cleanup);
+ Delete(outarg);
+ }
+
+ /* any existing helper functions to handle this? */
+ if (!is_void) {
+ if (!(ignored_method && !pure_virtual)) {
+ String *rettype = SwigType_str(returntype, 0);
+ if (!SwigType_isreference(returntype)) {
+ Printf(w->code, "return (%s) c_result;\n", rettype);
+ } else {
+ Printf(w->code, "return (%s) *c_result;\n", rettype);
+ }
+ Delete(rettype);
+ }
+ }
+
+ Printf(w->code, "}\n");
+
+ // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewString("");
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+
+ /* emit the director method */
+ if (status == SWIG_OK) {
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+
+ /* clean up */
+ Delete(wrap_args);
+ Delete(pclassname);
+ DelWrapper(w);
+ return status;
+ }
+
+ virtual int classDirectorConstructors(Node *n) {
+ return Language::classDirectorConstructors(n);
+ }
+
+ virtual int classDirectorMethods(Node *n) {
+ return Language::classDirectorMethods(n);
+ }
+
+ virtual int classDirectorDisown(Node *n) {
+ return Language::classDirectorDisown(n);
+ }
+
+ String *runtimeCode() {
+ String *s = NewString("");
+ String *shead = Swig_include_sys("rubyhead.swg");
+ if (!shead) {
+ Printf(stderr, "*** Unable to open 'rubyhead.swg'\n");
+ } else {
+ Append(s, shead);
+ Delete(shead);
+ }
+ String *serrors = Swig_include_sys("rubyerrors.swg");
+ if (!serrors) {
+ Printf(stderr, "*** Unable to open 'rubyerrors.swg'\n");
+ } else {
+ Append(s, serrors);
+ Delete(serrors);
+ }
+ String *strack = Swig_include_sys("rubytracking.swg");
+ if (!strack) {
+ Printf(stderr, "*** Unable to open 'rubytracking.swg'\n");
+ } else {
+ Append(s, strack);
+ Delete(strack);
+ }
+ String *sapi = Swig_include_sys("rubyapi.swg");
+ if (!sapi) {
+ Printf(stderr, "*** Unable to open 'rubyapi.swg'\n");
+ } else {
+ Append(s, sapi);
+ Delete(sapi);
+ }
+ String *srun = Swig_include_sys("rubyrun.swg");
+ if (!srun) {
+ Printf(stderr, "*** Unable to open 'rubyrun.swg'\n");
+ } else {
+ Append(s, srun);
+ Delete(srun);
+ }
+ return s;
+ }
+
+ String *defaultExternalRuntimeFilename() {
+ return NewString("swigrubyrun.h");
+ }
+
+ /*----------------------------------------------------------------------
+ * kwargsSupport()
+ *--------------------------------------------------------------------*/
+
+ bool kwargsSupport() const {
+ // kwargs support isn't actually implemented, but changing to return false may break something now as it turns on compactdefaultargs
+ return true;
+ }
+}; /* class RUBY */
+
+/* -----------------------------------------------------------------------------
+ * swig_ruby() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_ruby() {
+ return new RUBY();
+}
+extern "C" Language *swig_ruby(void) {
+ return new_swig_ruby();
+}
+
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff --git a/contrib/tools/swig/Source/Modules/scilab.cxx b/contrib/tools/swig/Source/Modules/scilab.cxx
new file mode 100644
index 00000000000..23e45f78757
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/scilab.cxx
@@ -0,0 +1,1156 @@
+/* ----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * scilab.cxx
+ *
+ * Scilab language module for SWIG.
+ * --------------------------------------------------------------------------*/
+
+#include "swigmod.h"
+
+static const int SCILAB_IDENTIFIER_NAME_CHAR_MAX = 24;
+static const int SCILAB_VARIABLE_NAME_CHAR_MAX = SCILAB_IDENTIFIER_NAME_CHAR_MAX - 4;
+
+static const char *usage = (char *) " \
+Scilab options (available with -scilab)\n \
+ -builder - Generate a Scilab builder script\n \
+ -buildercflags <cflags> - Add <cflags> to the builder compiler flags\n \
+ -builderflagscript <file> - Set the Scilab script <file> to use by builder to configure the build flags\n \
+ -builderldflags <ldflags> - Add <ldflags> to the builder linker flags\n \
+ -buildersources <files> - Add the (comma separated) files <files> to the builder sources\n \
+ -builderverbositylevel <level> - Set the builder verbosity level to <level> (default 0: off, 2: high)\n \
+ -gatewayxml <gateway_id> - Generate gateway xml with the given <gateway_id>\n \
+ -targetversion <scilab_major_version> - Generate for Scilab target (major) version (default: 5)\n \
+\n";
+
+
+class SCILAB:public Language {
+protected:
+ /* General objects used for holding the strings */
+ File *beginSection;
+ File *runtimeSection;
+ File *headerSection;
+ File *wrappersSection;
+ File *initSection;
+
+ String *variablesCode;
+
+ int targetVersion;
+
+ bool generateBuilder;
+ File *builderFile;
+ String *builderCode;
+ int builderFunctionCount;
+
+ List *sourceFileList;
+ List *cflags;
+ List *ldflags;
+
+ String *verboseBuildLevel;
+ String *buildFlagsScript;
+
+ String *gatewayHeader;
+ String *gatewayHeaderV5;
+ String *gatewayHeaderV6;
+
+ bool createGatewayXML;
+ File *gatewayXMLFile;
+ String *gatewayXML;
+ String *gatewayID;
+ int primitiveID;
+
+ bool createLoader;
+ File *loaderFile;
+ String *loaderScript;
+public:
+
+ /* ------------------------------------------------------------------------
+ * main()
+ * ----------------------------------------------------------------------*/
+
+ virtual void main(int argc, char *argv[]) {
+ targetVersion = 5;
+
+ generateBuilder = false;
+ sourceFileList = NewList();
+ cflags = NewList();
+ ldflags = NewList();
+ verboseBuildLevel = NULL;
+ buildFlagsScript = NULL;
+
+ gatewayHeader = NULL;
+ gatewayHeaderV5 = NULL;
+ gatewayHeaderV6 = NULL;
+
+ createGatewayXML = false;
+ gatewayXML = NULL;
+ gatewayXMLFile = NULL;
+ gatewayID = NULL;
+
+ createLoader = true;
+ loaderFile = NULL;
+ loaderScript = NULL;
+
+ /* Manage command line arguments */
+ for (int argIndex = 1; argIndex < argc; argIndex++) {
+ if (argv[argIndex] != NULL) {
+ if (strcmp(argv[argIndex], "-help") == 0) {
+ Printf(stdout, "%s\n", usage);
+ } else if (strcmp(argv[argIndex], "-builder") == 0) {
+ Swig_mark_arg(argIndex);
+ generateBuilder = true;
+ createLoader = false;
+ } else if (strcmp(argv[argIndex], "-buildersources") == 0) {
+ if (argv[argIndex + 1] != NULL) {
+ Swig_mark_arg(argIndex);
+ char *sourceFile = strtok(argv[argIndex + 1], ",");
+ while (sourceFile != NULL) {
+ Insert(sourceFileList, Len(sourceFileList), sourceFile);
+ sourceFile = strtok(NULL, ",");
+ }
+ Swig_mark_arg(argIndex + 1);
+ }
+ } else if (strcmp(argv[argIndex], "-buildercflags") == 0) {
+ Swig_mark_arg(argIndex);
+ if (argv[argIndex + 1] != NULL) {
+ Insert(cflags, Len(cflags), argv[argIndex + 1]);
+ Swig_mark_arg(argIndex + 1);
+ }
+ } else if (strcmp(argv[argIndex], "-builderldflags") == 0) {
+ Swig_mark_arg(argIndex);
+ if (argv[argIndex + 1] != NULL) {
+ Insert(ldflags, Len(ldflags), argv[argIndex + 1]);
+ Swig_mark_arg(argIndex + 1);
+ }
+ } else if (strcmp(argv[argIndex], "-builderverbositylevel") == 0) {
+ Swig_mark_arg(argIndex);
+ verboseBuildLevel = NewString(argv[argIndex + 1]);
+ Swig_mark_arg(argIndex + 1);
+ } else if (strcmp(argv[argIndex], "-builderflagscript") == 0) {
+ Swig_mark_arg(argIndex);
+ buildFlagsScript = NewString(argv[argIndex + 1]);
+ Swig_mark_arg(argIndex + 1);
+ } else if (strcmp(argv[argIndex], "-gatewayxml") == 0) {
+ Swig_mark_arg(argIndex);
+ createGatewayXML = true;
+ gatewayID = NewString(argv[argIndex + 1]);
+ Swig_mark_arg(argIndex + 1);
+ } else if (strcmp(argv[argIndex], "-targetversion") == 0) {
+ if (argv[argIndex + 1] != NULL) {
+ Swig_mark_arg(argIndex);
+ targetVersion = atoi(argv[argIndex + 1]);
+ Swig_mark_arg(argIndex + 1);
+ }
+ }
+ }
+ }
+
+ if (verboseBuildLevel == NULL) {
+ verboseBuildLevel = NewString("0");
+ }
+
+ /* Set language-specific subdirectory in SWIG library */
+ SWIG_library_directory("scilab");
+
+ /* Add a symbol to the parser for conditional compilation */
+ Preprocessor_define("SWIGSCILAB 1", 0);
+
+ /* Set scilab configuration file */
+ SWIG_config_file("scilab.swg");
+
+ /* Set typemap for scilab */
+ SWIG_typemap_lang("scilab");
+
+ allow_overloading();
+ }
+
+ /* ------------------------------------------------------------------------
+ * top()
+ * ----------------------------------------------------------------------*/
+
+ virtual int top(Node *node) {
+
+ /* Get the module name */
+ String *gatewayName = Getattr(node, "name");
+
+ // Set library name
+ String *gatewayLibraryName = NewStringf("lib%s", gatewayName);
+
+ /* Get the output file name */
+ String *outputFilename = Getattr(node, "outfile");
+
+ /* Initialize I/O */
+ beginSection = NewFile(outputFilename, "w", SWIG_output_files());
+ if (!beginSection) {
+ FileErrorDisplay(outputFilename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ runtimeSection = NewString("");
+ initSection = NewString("");
+ headerSection = NewString("");
+ wrappersSection = NewString("");
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("begin", beginSection);
+ Swig_register_filebyname("header", headerSection);
+ Swig_register_filebyname("wrapper", wrappersSection);
+ Swig_register_filebyname("runtime", runtimeSection);
+ Swig_register_filebyname("init", initSection);
+
+ /* Output module initialization code */
+ Swig_banner(beginSection);
+
+ Printf(runtimeSection, "\n\n#ifndef SWIGSCILAB\n#define SWIGSCILAB\n#endif\n\n");
+
+ // Gateway header source merged with wrapper source in nobuilder mode
+ if (!generateBuilder)
+ startGatewayHeader(gatewayLibraryName);
+
+ // Create builder file if required
+ if (generateBuilder) {
+ createBuilderFile(outputFilename);
+ }
+
+ // Create gateway XML if required
+ if (createGatewayXML) {
+ createGatewayXMLFile(gatewayName);
+ }
+
+ // Create loader script if required
+ if (createLoader) {
+ createLoaderFile(gatewayLibraryName);
+ }
+
+ // Module initialization function
+ String *gatewayInitFunctionName = NewStringf("%s_Init", gatewayName);
+
+ /* Add initialization function to builder table */
+ addFunctionToScilab(gatewayInitFunctionName, gatewayInitFunctionName);
+
+ // Add helper functions to builder table
+ addHelperFunctions();
+
+ // Open Scilab wrapper variables creation function
+ variablesCode = NewString("");
+ Printf(variablesCode, "int SWIG_CreateScilabVariables(void *_pvApiCtx) {");
+
+ /* Emit code for children */
+ if (CPlusPlus) {
+ Printf(wrappersSection, "extern \"C\" {\n");
+ }
+
+ Language::top(node);
+
+ if (CPlusPlus) {
+ Printf(wrappersSection, "}\n");
+ }
+ // Close Scilab wrapper variables creation function
+ Printf(variablesCode, " return SWIG_OK;\n}\n");
+
+ // Add Builder footer code and save
+ if (generateBuilder) {
+ saveBuilderFile(gatewayName);
+ }
+
+ /* Close the init function and rename with module name */
+ Printf(initSection, "return 0;\n}\n");
+ Replaceall(initSection, "<module>", gatewayName);
+
+ /* Write all to the wrapper file */
+ SwigType_emit_type_table(runtimeSection, wrappersSection); // Declare pointer types, ... (Ex: SWIGTYPE_p_p_double)
+
+ // Gateway header source merged with wrapper source in nobuilder mode
+ if (!generateBuilder) {
+ terminateGatewayHeader(gatewayLibraryName);
+ Printv(initSection, gatewayHeader, NIL);
+ }
+
+ Dump(runtimeSection, beginSection);
+ Dump(headerSection, beginSection);
+ Dump(wrappersSection, beginSection);
+ Dump(variablesCode, beginSection);
+ Wrapper_pretty_print(initSection, beginSection);
+
+ if (createGatewayXML) {
+ saveGatewayXMLFile();
+ }
+
+ if (createLoader) {
+ saveLoaderFile(gatewayLibraryName);
+ }
+
+ /* Cleanup files */
+ Delete(runtimeSection);
+ Delete(headerSection);
+ Delete(wrappersSection);
+ Delete(initSection);
+ Delete(beginSection);
+
+ Delete(sourceFileList);
+ Delete(cflags);
+ Delete(ldflags);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------------------
+ * emitBanner()
+ * ----------------------------------------------------------------------*/
+
+ void emitBanner(File *f) {
+ Printf(f, "// ----------------------------------------------------------------------------\n");
+ Swig_banner_target_lang(f, "// ");
+ Printf(f, "// ----------------------------------------------------------------------------- */\n\n");
+ }
+
+ /* ------------------------------------------------------------------------
+ * functionWrapper()
+ * ----------------------------------------------------------------------*/
+
+ virtual int functionWrapper(Node *node) {
+
+ /* Get some useful attributes of this function */
+ String *functionName = Getattr(node, "sym:name");
+ SwigType *functionReturnType = Getattr(node, "type");
+ ParmList *functionParamsList = Getattr(node, "parms");
+
+ int paramIndex = 0; // Used for loops over ParmsList
+ Parm *param = NULL; // Used for loops over ParamsList
+
+ /* Create the wrapper object */
+ Wrapper *wrapper = NewWrapper();
+
+ /* Create the function wrapper name */
+ String *wrapperName = Swig_name_wrapper(functionName);
+
+ /* Deal with overloading */
+ String *overloadedName = Copy(wrapperName);
+ /* Determine whether the function is overloaded or not */
+ bool isOverloaded = ! !Getattr(node, "sym:overloaded");
+ /* Determine whether the function is the last overloaded */
+ bool isLastOverloaded = isOverloaded && !Getattr(node, "sym:nextSibling");
+
+ if (!isOverloaded && !addSymbol(functionName, node)) {
+ DelWrapper(wrapper);
+ return SWIG_ERROR;
+ }
+
+ if (isOverloaded) {
+ Append(overloadedName, Getattr(node, "sym:overname"));
+ }
+
+ /* Write the wrapper function definition (standard Scilab gateway function prototype) */
+ Printv(wrapper->def, "int ", overloadedName, "(SWIG_GatewayParameters) {", NIL);
+
+ /* Emit all of the local variables for holding arguments */
+ // E.g.: double arg1;
+ emit_parameter_variables(functionParamsList, wrapper);
+
+ /* Attach typemaps to the parameter list */
+ // Add local variables used in typemaps (iRows, iCols, ...)
+ emit_attach_parmmaps(functionParamsList, wrapper);
+ Setattr(node, "wrap:parms", functionParamsList);
+
+ /* Check input/output arguments count */
+ int maxInputArguments = emit_num_arguments(functionParamsList);
+ int minInputArguments = emit_num_required(functionParamsList);
+ int minOutputArguments = 0;
+ int maxOutputArguments = 0;
+
+ if (!emit_isvarargs(functionParamsList)) {
+ Printf(wrapper->code, "SWIG_CheckInputArgument(pvApiCtx, $mininputarguments, $maxinputarguments);\n");
+ }
+ else {
+ Printf(wrapper->code, "SWIG_CheckInputArgumentAtLeast(pvApiCtx, $mininputarguments-1);\n");
+ }
+ Printf(wrapper->code, "SWIG_CheckOutputArgument(pvApiCtx, $minoutputarguments, $maxoutputarguments);\n");
+
+ /* Set context */
+ Printf(wrapper->code, "SWIG_Scilab_SetFuncName(fname);\n");
+ Printf(wrapper->code, "SWIG_Scilab_SetApiContext(pvApiCtx);\n");
+
+ /* Write typemaps(in) */
+
+ for (paramIndex = 0, param = functionParamsList; paramIndex < maxInputArguments; ++paramIndex) {
+ // Ignore parameter if the typemap specifies numinputs=0
+ while (checkAttribute(param, "tmap:in:numinputs", "0")) {
+ param = Getattr(param, "tmap:in:next");
+ }
+
+ SwigType *paramType = Getattr(param, "type");
+ String *paramTypemap = Getattr(param, "tmap:in");
+
+ if (paramTypemap) {
+ // Replace $input by the position on Scilab stack
+ String *source = NewString("");
+ Printf(source, "%d", paramIndex + 1);
+ Setattr(param, "emit:input", source);
+ Replaceall(paramTypemap, "$input", Getattr(param, "emit:input"));
+
+ if (Getattr(param, "wrap:disown") || (Getattr(param, "tmap:in:disown"))) {
+ Replaceall(paramTypemap, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(paramTypemap, "$disown", "0");
+ }
+
+ if (paramIndex >= minInputArguments) { /* Optional input argument management */
+ Printf(wrapper->code, "if (SWIG_NbInputArgument(pvApiCtx) > %d) {\n%s\n}\n", paramIndex, paramTypemap);
+ } else {
+ Printf(wrapper->code, "%s\n", paramTypemap);
+ }
+ param = Getattr(param, "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(paramType, 0));
+ break;
+ }
+ }
+
+ /* TODO write constraints */
+
+ Setattr(node, "wrap:name", overloadedName);
+
+ /* Emit the function call */
+ Swig_director_emit_dynamic_cast(node, wrapper);
+ String *functionActionCode = emit_action(node);
+
+ /* Insert the return variable */
+ emit_return_variable(node, functionReturnType, wrapper);
+
+ /* Return the function value if necessary */
+ String *functionReturnTypemap = Swig_typemap_lookup_out("out", node, Swig_cresult_name(), wrapper, functionActionCode);
+ if (functionReturnTypemap) {
+ // Result is actually the position of output value on stack
+ if (Len(functionReturnTypemap) > 0) {
+ Printf(wrapper->code, "SWIG_Scilab_SetOutputPosition(%d);\n", 1);
+ }
+ Replaceall(functionReturnTypemap, "$result", "1");
+
+ if (GetFlag(node, "feature:new")) {
+ Replaceall(functionReturnTypemap, "$owner", "1");
+ } else {
+ Replaceall(functionReturnTypemap, "$owner", "0");
+ }
+
+ Printf(wrapper->code, "%s\n", functionReturnTypemap);
+
+ /* If the typemap is not empty, the function return one more argument than the typemaps gives */
+ if (Len(functionReturnTypemap) > 0) {
+ minOutputArguments++;
+ maxOutputArguments++;
+ }
+ Delete(functionReturnTypemap);
+
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(functionReturnType, 0),
+ functionName);
+ }
+
+ /* Write typemaps(out) */
+ for (param = functionParamsList; param;) {
+ String *paramTypemap = Getattr(param, "tmap:argout");
+ if (paramTypemap) {
+ minOutputArguments++;
+ maxOutputArguments++;
+ Printf(wrapper->code, "SWIG_Scilab_SetOutputPosition(%d);\n", minOutputArguments);
+ String *result = NewString("");
+ Printf(result, "%d", minOutputArguments);
+ Replaceall(paramTypemap, "$result", result);
+ Printf(wrapper->code, "%s\n", paramTypemap);
+ Delete(paramTypemap);
+ param = Getattr(param, "tmap:argout:next");
+ } else {
+ param = nextSibling(param);
+ }
+ }
+ /* Add cleanup code */
+ for (param = functionParamsList; param;) {
+ String *tm;
+ if ((tm = Getattr(param, "tmap:freearg"))) {
+ if (tm && (Len(tm) != 0)) {
+ Replaceall(tm, "$source", Getattr(param, "lname"));
+ Printf(wrapper->code, "%s\n", tm);
+ }
+ param = Getattr(param, "tmap:freearg:next");
+ } else {
+ param = nextSibling(param);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ String *tm;
+ if ((tm = Swig_typemap_lookup("ret", node, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printf(wrapper->code, "%s\n", tm);
+ Delete(tm);
+ }
+
+ /* Close the function(ok) */
+ Printv(wrapper->code, "return SWIG_OK;\n", NIL);
+ Printv(wrapper->code, "}\n", NIL);
+
+ /* Add the failure cleanup code */
+ /* TODO */
+
+ /* Final substitutions if applicable */
+ Replaceall(wrapper->code, "$symname", functionName);
+
+ /* Set CheckInputArgument and CheckOutputArgument input arguments */
+ /* In Scilab there is always one output even if not defined */
+ if (minOutputArguments == 0) {
+ maxOutputArguments = 1;
+ }
+ String *argnumber = NewString("");
+ Printf(argnumber, "%d", minInputArguments);
+ Replaceall(wrapper->code, "$mininputarguments", argnumber);
+
+ argnumber = NewString("");
+ Printf(argnumber, "%d", maxInputArguments);
+ Replaceall(wrapper->code, "$maxinputarguments", argnumber);
+
+ argnumber = NewString("");
+ Printf(argnumber, "%d", minOutputArguments);
+ Replaceall(wrapper->code, "$minoutputarguments", argnumber);
+
+ argnumber = NewString("");
+ Printf(argnumber, "%d", maxOutputArguments);
+ Replaceall(wrapper->code, "$maxoutputarguments", argnumber);
+
+ /* Dump the function out */
+ Wrapper_print(wrapper, wrappersSection);
+
+ String *scilabFunctionName = checkIdentifierName(functionName, SCILAB_IDENTIFIER_NAME_CHAR_MAX);
+
+ /* Update builder.sce contents */
+ if (isLastOverloaded) {
+ addFunctionToScilab(scilabFunctionName, wrapperName);
+ dispatchFunction(node);
+ }
+
+ if (!isOverloaded) {
+ addFunctionToScilab(scilabFunctionName, wrapperName);
+ }
+
+ /* tidy up */
+ Delete(overloadedName);
+ Delete(wrapperName);
+ DelWrapper(wrapper);
+
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * dispatchFunction()
+ * ----------------------------------------------------------------------- */
+
+ void dispatchFunction(Node *node) {
+ Wrapper *wrapper = NewWrapper();
+
+ String *functionName = Getattr(node, "sym:name");
+ String *wrapperName = Swig_name_wrapper(functionName);
+ int maxargs = 0;
+
+ /* Generate the dispatch function */
+ String *dispatch = Swig_overload_dispatch(node, "return %s(SWIG_GatewayArguments);", &maxargs);
+ String *tmp = NewString("");
+
+ Printv(wrapper->def, "int ", wrapperName, "(SWIG_GatewayParameters) {\n", NIL);
+
+ /* Get the number of the parameters */
+ Wrapper_add_local(wrapper, "argc", "int argc = SWIG_NbInputArgument(pvApiCtx)");
+ Printf(tmp, "int argv[%d] = {", maxargs);
+ for (int j = 0; j < maxargs; ++j) {
+ Printf(tmp, "%s%d", j ? "," : " ", j + 1);
+ }
+ Printf(tmp, "}");
+ Wrapper_add_local(wrapper, "argv", tmp);
+
+ Printf(wrapper->code, "SWIG_Scilab_SetApiContext(pvApiCtx);\n");
+
+ /* Dump the dispatch function */
+ Printv(wrapper->code, dispatch, "\n", NIL);
+ Printf(wrapper->code, "Scierror(999, _(\"No matching function for overload\"));\n");
+ Printf(wrapper->code, "return SWIG_ERROR;\n");
+ Printv(wrapper->code, "}\n", NIL);
+ Wrapper_print(wrapper, wrappersSection);
+
+ Delete(tmp);
+ DelWrapper(wrapper);
+ Delete(dispatch);
+ Delete(wrapperName);
+ }
+
+ /* -----------------------------------------------------------------------
+ * variableWrapper()
+ * ----------------------------------------------------------------------- */
+
+ virtual int variableWrapper(Node *node) {
+
+ /* Get information about variable */
+ String *origVariableName = Getattr(node, "name"); // Ex: Shape::nshapes
+ String *variableName = Getattr(node, "sym:name"); // Ex; Shape_nshapes (can be used for function names, ...)
+
+ // Variable names can have SCILAB_VARIABLE_NAME_CHAR_MAX because of suffixes "_get" or "_set" added to function
+ String *scilabVariableName = checkIdentifierName(variableName, SCILAB_VARIABLE_NAME_CHAR_MAX);
+
+ /* Manage GET function */
+ Wrapper *getFunctionWrapper = NewWrapper();
+ String *getFunctionName = Swig_name_get(NSPACE_TODO, variableName);
+ String *scilabGetFunctionName = Swig_name_get(NSPACE_TODO, scilabVariableName);
+
+ Setattr(node, "wrap:name", getFunctionName);
+ Printv(getFunctionWrapper->def, "int ", getFunctionName, "(SWIG_GatewayParameters) {\n", NIL);
+
+ /* Check the number of input and output */
+ Printf(getFunctionWrapper->def, "SWIG_CheckInputArgument(pvApiCtx, 0, 0);\n");
+ Printf(getFunctionWrapper->def, "SWIG_CheckOutputArgument(pvApiCtx, 1, 1);\n");
+ Printf(getFunctionWrapper->def, "SWIG_Scilab_SetApiContext(pvApiCtx);\n");
+
+ String *varoutTypemap = Swig_typemap_lookup("varout", node, origVariableName, 0);
+ if (varoutTypemap != NULL) {
+ Printf(getFunctionWrapper->code, "SWIG_Scilab_SetOutputPosition(%d);\n", 1);
+ Replaceall(varoutTypemap, "$value", origVariableName);
+ Replaceall(varoutTypemap, "$result", "1");
+ emit_action_code(node, getFunctionWrapper->code, varoutTypemap);
+ Delete(varoutTypemap);
+ }
+ Append(getFunctionWrapper->code, "return SWIG_OK;\n");
+ Append(getFunctionWrapper->code, "}\n");
+ Wrapper_print(getFunctionWrapper, wrappersSection);
+
+ /* Add function to builder table */
+ addFunctionToScilab(scilabGetFunctionName, getFunctionName);
+
+ /* Manage SET function */
+ if (is_assignable(node)) {
+ Wrapper *setFunctionWrapper = NewWrapper();
+ String *setFunctionName = Swig_name_set(NSPACE_TODO, variableName);
+ String *scilabSetFunctionName = Swig_name_set(NSPACE_TODO, scilabVariableName);
+
+ Setattr(node, "wrap:name", setFunctionName);
+ Printv(setFunctionWrapper->def, "int ", setFunctionName, "(SWIG_GatewayParameters) {\n", NIL);
+
+ /* Check the number of input and output */
+ Printf(setFunctionWrapper->def, "SWIG_CheckInputArgument(pvApiCtx, 1, 1);\n");
+ Printf(setFunctionWrapper->def, "SWIG_CheckOutputArgument(pvApiCtx, 1, 1);\n");
+ Printf(setFunctionWrapper->def, "SWIG_Scilab_SetApiContext(pvApiCtx);\n");
+
+ String *varinTypemap = Swig_typemap_lookup("varin", node, origVariableName, 0);
+ if (varinTypemap != NULL) {
+ Replaceall(varinTypemap, "$input", "1");
+ emit_action_code(node, setFunctionWrapper->code, varinTypemap);
+ Delete(varinTypemap);
+ }
+ Append(setFunctionWrapper->code, "return SWIG_OK;\n");
+ Append(setFunctionWrapper->code, "}\n");
+ Wrapper_print(setFunctionWrapper, wrappersSection);
+
+ /* Add function to builder table */
+ addFunctionToScilab(scilabSetFunctionName, setFunctionName);
+
+ DelWrapper(setFunctionWrapper);
+ }
+ DelWrapper(getFunctionWrapper);
+
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * constantWrapper()
+ * ----------------------------------------------------------------------- */
+
+ virtual int constantWrapper(Node *node) {
+
+ /* Get the useful information from the node */
+ String *nodeName = Getattr(node, "name");
+ SwigType *type = Getattr(node, "type");
+ String *constantName = Getattr(node, "sym:name");
+ String *rawValue = Getattr(node, "rawval");
+ String *constantValue = rawValue ? rawValue : Getattr(node, "value");
+ String *constantTypemap = NULL;
+
+ // If feature scilab:const enabled, constants & enums are wrapped to Scilab variables
+ if (GetFlag(node, "feature:scilab:const")) {
+ bool isConstant = ((SwigType_issimple(type)) || (SwigType_type(type) == T_STRING));
+ bool isEnum = (Cmp(nodeType(node), "enumitem") == 0);
+
+ if (isConstant || isEnum) {
+ if (isEnum) {
+ Setattr(node, "type", "double");
+ constantValue = Getattr(node, "value");
+ }
+
+ constantTypemap = Swig_typemap_lookup("scilabconstcode", node, nodeName, 0);
+ if (constantTypemap != NULL) {
+ String *scilabConstantName = checkIdentifierName(constantName, SCILAB_IDENTIFIER_NAME_CHAR_MAX);
+
+ Setattr(node, "wrap:name", constantName);
+ Replaceall(constantTypemap, "$result", scilabConstantName);
+ Replaceall(constantTypemap, "$value", constantValue);
+
+ emit_action_code(node, variablesCode, constantTypemap);
+ Delete(constantTypemap);
+ return SWIG_OK;
+ }
+ }
+ }
+
+ /* Create variables for member pointer constants, not supported by typemaps (like Python wrapper does) */
+ if (SwigType_type(type) == T_MPOINTER) {
+ String *wname = Swig_name_wrapper(constantName);
+ String *str = SwigType_str(type, wname);
+ Printf(headerSection, "static %s = %s;\n", str, constantValue);
+ Delete(str);
+ constantValue = wname;
+ }
+ // Constant names can have SCILAB_VARIABLE_NAME_CHAR_MAX because of suffixes "_get" added to function
+ String *scilabConstantName = checkIdentifierName(constantName, SCILAB_VARIABLE_NAME_CHAR_MAX);
+
+ /* Create GET function to get the constant value */
+ Wrapper *getFunctionWrapper = NewWrapper();
+ String *getFunctionName = Swig_name_get(NSPACE_TODO, constantName);
+ String *scilabGetFunctionName = Swig_name_get(NSPACE_TODO, scilabConstantName);
+ Setattr(node, "wrap:name", getFunctionName);
+ Printv(getFunctionWrapper->def, "int ", getFunctionName, "(SWIG_GatewayParameters) {\n", NIL);
+
+ /* Check the number of input and output */
+ Printf(getFunctionWrapper->def, "SWIG_CheckInputArgument(pvApiCtx, 0, 0);\n");
+ Printf(getFunctionWrapper->def, "SWIG_CheckOutputArgument(pvApiCtx, 1, 1);\n");
+ Printf(getFunctionWrapper->def, "SWIG_Scilab_SetApiContext(pvApiCtx);\n");
+
+ constantTypemap = Swig_typemap_lookup("constcode", node, nodeName, 0);
+ if (constantTypemap != NULL) {
+ Printf(getFunctionWrapper->code, "SWIG_Scilab_SetOutputPosition(%d);\n", 1);
+ Replaceall(constantTypemap, "$value", constantValue);
+ Replaceall(constantTypemap, "$result", "1");
+ emit_action_code(node, getFunctionWrapper->code, constantTypemap);
+ Delete(constantTypemap);
+ }
+
+ /* Dump the wrapper function */
+ Append(getFunctionWrapper->code, "return SWIG_OK;\n");
+ Append(getFunctionWrapper->code, "}\n");
+ Wrapper_print(getFunctionWrapper, wrappersSection);
+
+ /* Add the function to Scilab */
+ addFunctionToScilab(scilabGetFunctionName, getFunctionName);
+
+ DelWrapper(getFunctionWrapper);
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------
+ * enumvalueDeclaration()
+ * --------------------------------------------------------------------- */
+
+ virtual int enumvalueDeclaration(Node *node) {
+ static int iPreviousEnumValue = 0;
+
+ if (GetFlag(node, "feature:scilab:const")) {
+ // Compute the "absolute" value of enum if needed
+ // (most of time enum values are a linked list of relative values)
+ String *enumValue = Getattr(node, "enumvalue");
+ String *enumValueEx = Getattr(node, "enumvalueex");
+
+ // First enum value ?
+ String *firstenumitem = Getattr(node, "firstenumitem");
+ if (firstenumitem) {
+ if (enumValue) {
+ // Value is in 'enumvalue'
+ iPreviousEnumValue = atoi(Char(enumValue));
+ } else if (enumValueEx) {
+ // Or value is in 'enumValueEx'
+ iPreviousEnumValue = atoi(Char(enumValueEx));
+
+ enumValue = NewString("");
+ Printf(enumValue, "%d", iPreviousEnumValue);
+ Setattr(node, "enumvalue", enumValue);
+ }
+ } else if (!enumValue && enumValueEx) {
+ // Value is not specified, set it by incrementing last value
+ enumValue = NewString("");
+ Printf(enumValue, "%d", ++iPreviousEnumValue);
+ Setattr(node, "enumvalue", enumValue);
+ }
+ // Enums in Scilab are mapped to double
+ Setattr(node, "type", "double");
+ }
+
+ return Language::enumvalueDeclaration(node);
+ }
+
+ /* ---------------------------------------------------------------------
+ * membervariableHandler()
+ * --------------------------------------------------------------------- */
+ virtual int membervariableHandler(Node *node) {
+ checkMemberIdentifierName(node, SCILAB_VARIABLE_NAME_CHAR_MAX);
+ return Language::membervariableHandler(node);
+ }
+
+ /* -----------------------------------------------------------------------
+ * checkIdentifierName()
+ * If Scilab target version is lower than 6:
+ * truncates (and displays a warning) too long member identifier names
+ * (applies on members of structs, classes...)
+ * (Scilab 5 identifier names are limited to 24 chars max)
+ * ----------------------------------------------------------------------- */
+
+ String *checkIdentifierName(String *name, int char_size_max) {
+ String *scilabIdentifierName;
+ if (targetVersion <= 5) {
+ if (Len(name) > char_size_max) {
+ scilabIdentifierName = DohNewStringWithSize(name, char_size_max);
+ Swig_warning(WARN_SCILAB_TRUNCATED_NAME, input_file, line_number,
+ "Identifier name '%s' exceeds 24 characters and has been truncated to '%s'.\n", name, scilabIdentifierName);
+ } else
+ scilabIdentifierName = name;
+ } else {
+ scilabIdentifierName = DohNewString(name);
+ }
+ return scilabIdentifierName;
+ }
+
+ /* -----------------------------------------------------------------------
+ * checkMemberIdentifierName()
+ * If Scilab target version is lower than 6:
+ * truncates (and displays a warning) too long member identifier names
+ * (applies on members of structs, classes...)
+ * (Scilab 5 identifier names are limited to 24 chars max)
+ * ----------------------------------------------------------------------- */
+
+ void checkMemberIdentifierName(Node *node, int char_size_max) {
+ if (targetVersion <= 5) {
+ String *memberName = Getattr(node, "sym:name");
+ Node *containerNode = parentNode(node);
+ String *containerName = Getattr(containerNode, "sym:name");
+ int lenContainerName = Len(containerName);
+ int lenMemberName = Len(memberName);
+
+ if (lenContainerName + lenMemberName + 1 > char_size_max) {
+ int lenScilabMemberName = char_size_max - lenContainerName - 1;
+
+ if (lenScilabMemberName > 0) {
+ String *scilabMemberName = DohNewStringWithSize(memberName, lenScilabMemberName);
+ Setattr(node, "sym:name", scilabMemberName);
+ Swig_warning(WARN_SCILAB_TRUNCATED_NAME, input_file, line_number,
+ "Wrapping functions names for member '%s.%s' will exceed 24 characters, "
+ "so member name has been truncated to '%s'.\n", containerName, memberName, scilabMemberName);
+ } else {
+ Swig_error(input_file, line_number,
+ "Wrapping functions names for member '%s.%s' will exceed 24 characters, "
+ "please rename the container of member '%s'.\n", containerName, memberName, containerName);
+ }
+ }
+ }
+ }
+
+ /* -----------------------------------------------------------------------
+ * addHelperFunctions()
+ * ----------------------------------------------------------------------- */
+
+ void addHelperFunctions() {
+ addFunctionToScilab("SWIG_this", "SWIG_this");
+ addFunctionToScilab("SWIG_ptr", "SWIG_ptr");
+ }
+
+ /* -----------------------------------------------------------------------
+ * addFunctionToScilab()
+ * Declare a wrapped function in Scilab (builder, gateway, XML, ...)
+ * ----------------------------------------------------------------------- */
+
+ void addFunctionToScilab(const_String_or_char_ptr scilabFunctionName, const_String_or_char_ptr wrapperFunctionName) {
+ if (!generateBuilder)
+ addFunctionInGatewayHeader(scilabFunctionName, wrapperFunctionName);
+
+ if (generateBuilder) {
+ addFunctionInScriptTable(scilabFunctionName, wrapperFunctionName, builderCode);
+ }
+
+ if (createLoader) {
+ addFunctionInLoader(scilabFunctionName);
+ }
+
+ if (gatewayXMLFile) {
+ Printf(gatewayXML, "<PRIMITIVE gatewayId=\"%s\" primitiveId=\"%d\" primitiveName=\"%s\"/>\n", gatewayID, primitiveID++, scilabFunctionName);
+ }
+ }
+
+
+ /* -----------------------------------------------------------------------
+ * createBuilderCode()
+ * ----------------------------------------------------------------------- */
+
+ void createBuilderFile(String *outputFilename) {
+ String *builderFilename = NewStringf("builder.sce");
+ builderFile = NewFile(builderFilename, "w", SWIG_output_files());
+ if (!builderFile) {
+ FileErrorDisplay(builderFilename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ emitBanner(builderFile);
+
+ builderFunctionCount = 0;
+ builderCode = NewString("");
+ Printf(builderCode, "mode(-1);\n");
+ Printf(builderCode, "lines(0);\n"); /* Useful for automatic tests */
+
+ // Scilab needs to be in the build directory
+ Printf(builderCode, "originaldir = pwd();\n");
+ Printf(builderCode, "builddir = get_absolute_file_path('builder.sce');\n");
+ Printf(builderCode, "cd(builddir);\n");
+
+ Printf(builderCode, "ilib_verbose(%s);\n", verboseBuildLevel);
+
+ Printf(builderCode, "libs = [];\n");
+
+ // Flags from command line arguments
+ Printf(builderCode, "cflags = \"\";\n");
+ for (int i = 0; i < Len(cflags); i++) {
+ String *cflag = Getitem(cflags, i);
+ Printf(builderCode, "cflags = cflags + \" %s\";\n", cflag);
+ }
+
+ if (Len(ldflags) > 0) {
+ for (int i = 0; i < Len(ldflags); i++) {
+ String *ldflag = Getitem(ldflags, i);
+ if (i == 0) {
+ Printf(builderCode, "ldflags = \"%s\";\n", ldflag);
+ } else {
+ Printf(builderCode, "ldflags = ldflags + \" %s\";\n", ldflag);
+ }
+ }
+ } else {
+ Printf(builderCode, "ldflags = \"\";\n");
+ }
+
+ // External script to set flags
+ if (buildFlagsScript) {
+ Printf(builderCode, "exec(\"%s\");\n", buildFlagsScript);
+ Printf(builderCode, "cflags = cflags + getCompilationFlags();\n");
+ Printf(builderCode, "ldflags = ldflags + getLinkFlags();\n");
+ }
+ // Additional sources
+ Insert(sourceFileList, 0, outputFilename);
+ for (int i = 0; i < Len(sourceFileList); i++) {
+ String *sourceFile = Getitem(sourceFileList, i);
+ if (i == 0) {
+ Printf(builderCode, "files = \"%s\";\n", sourceFile);
+ } else {
+ Printf(builderCode, "files($ + 1) = \"%s\";\n", sourceFile);
+ }
+ }
+
+ Printf(builderCode, "table = [");
+ }
+
+ /* -----------------------------------------------------------------------
+ * addFunctionInBuilderCode()
+ * Add a function wrapper in the function table of generated builder script
+ * ----------------------------------------------------------------------- */
+
+ void addFunctionInScriptTable(const_String_or_char_ptr scilabFunctionName, const_String_or_char_ptr wrapperFunctionName, String *scriptCode) {
+ if (++builderFunctionCount % 10 == 0) {
+ Printf(scriptCode, "];\ntable = [table;");
+ }
+ Printf(scriptCode, "\"%s\",\"%s\";", scilabFunctionName, wrapperFunctionName);
+ }
+
+ /* -----------------------------------------------------------------------
+ * saveBuilderFile()
+ * ----------------------------------------------------------------------- */
+
+ void saveBuilderFile(String *gatewayName) {
+ Printf(builderCode, "];\n");
+ Printf(builderCode, "ierr = 0;\n");
+ Printf(builderCode, "if ~isempty(table) then\n");
+ Printf(builderCode, " ierr = execstr(\"ilib_build(''%s'', table, files, libs, [], ldflags, cflags);\", 'errcatch');\n", gatewayName);
+ Printf(builderCode, " if ierr <> 0 then\n");
+ Printf(builderCode, " err_msg = lasterror();\n");
+ Printf(builderCode, " end\n");
+ Printf(builderCode, "end\n");
+ Printf(builderCode, "cd(originaldir);\n");
+ Printf(builderCode, "if ierr <> 0 then\n");
+ Printf(builderCode, " error(ierr, err_msg);\n");
+ Printf(builderCode, "end\n");
+ Printv(builderFile, builderCode, NIL);
+ Delete(builderFile);
+ }
+
+ /* -----------------------------------------------------------------------
+ * createGatewayXMLFile()
+ * This XML file is used by Scilab in the context of internal modules
+ * ----------------------------------------------------------------------- */
+
+ void createGatewayXMLFile(String *gatewayName) {
+ String *gatewayXMLFilename = NewStringf("%s_gateway.xml", gatewayName);
+ gatewayXMLFile = NewFile(gatewayXMLFilename, "w", SWIG_output_files());
+ if (!gatewayXMLFile) {
+ FileErrorDisplay(gatewayXMLFilename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ // Add a slightly modified SWIG banner to the gateway XML ("--modify" is illegal in XML)
+ gatewayXML = NewString("");
+ Printf(gatewayXML, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
+ Printf(gatewayXML, "<!--\n");
+ Printf(gatewayXML, "This file was automatically generated by SWIG (http://www.swig.org).\n");
+ Printf(gatewayXML, "Version %s\n", Swig_package_version());
+ Printf(gatewayXML, "\n");
+ Printf(gatewayXML, "Do not make changes to this file unless you know what you are doing - modify\n");
+ Printf(gatewayXML, "the SWIG interface file instead.\n");
+ Printf(gatewayXML, "-->\n");
+ Printf(gatewayXML, "<GATEWAY name=\"%s\">\n", gatewayName);
+
+ primitiveID = 1;
+ }
+
+ /* -----------------------------------------------------------------------
+ * saveGatewayXMLFile()
+ * ----------------------------------------------------------------------- */
+
+ void saveGatewayXMLFile() {
+ Printf(gatewayXML, "</GATEWAY>\n");
+ Printv(gatewayXMLFile, gatewayXML, NIL);
+ Delete(gatewayXMLFile);
+ }
+
+ /* -----------------------------------------------------------------------
+ * startGatewayHeader()
+ * Start the gateway header
+ * ----------------------------------------------------------------------- */
+ void startGatewayHeader(String *gatewayLibraryName) {
+ gatewayHeader = NewString("");
+ Printf(gatewayHeader, "\n");
+
+ gatewayHeaderV6 = NewString("");
+ Printf(gatewayHeaderV6, "#ifdef __cplusplus\n");
+ Printf(gatewayHeaderV6, "extern \"C\" {\n");
+ Printf(gatewayHeaderV6, "#endif\n");
+ Printf(gatewayHeaderV6, "#include \"c_gateway_prototype.h\"\n");
+ Printf(gatewayHeaderV6, "#include \"addfunction.h\"\n");
+ Printf(gatewayHeaderV6, "#ifdef __cplusplus\n");
+ Printf(gatewayHeaderV6, "}\n");
+ Printf(gatewayHeaderV6, "#endif\n");
+ Printf(gatewayHeaderV6, "\n");
+ Printf(gatewayHeaderV6, "#define MODULE_NAME L\"%s\"\n", gatewayLibraryName);
+ Printf(gatewayHeaderV6, "#ifdef __cplusplus\n");
+ Printf(gatewayHeaderV6, "extern \"C\"\n");
+ Printf(gatewayHeaderV6, "#endif\n");
+ Printf(gatewayHeaderV6, "int %s(wchar_t *pwstFuncName) {\n", gatewayLibraryName);
+ Printf(gatewayHeaderV6, "\n");
+ }
+
+ /* -----------------------------------------------------------------------
+ * addFunctionInGatewayHeader()
+ * Add a function in the gateway header
+ * ----------------------------------------------------------------------- */
+
+ void addFunctionInGatewayHeader(const_String_or_char_ptr scilabFunctionName, const_String_or_char_ptr wrapperFunctionName) {
+ if (gatewayHeaderV5 == NULL) {
+ gatewayHeaderV5 = NewString("");
+ Printf(gatewayHeaderV5, "static GenericTable Tab[] = {\n");
+ } else
+ Printf(gatewayHeaderV5, ",\n");
+ Printf(gatewayHeaderV5, " {(Myinterfun)sci_gateway, (GT)%s, (char *)\"%s\"}", wrapperFunctionName, scilabFunctionName);
+
+ Printf(gatewayHeaderV6, "if (wcscmp(pwstFuncName, L\"%s\") == 0) { addCStackFunction((wchar_t *)L\"%s\", &%s, (wchar_t *)MODULE_NAME); }\n", scilabFunctionName, scilabFunctionName, wrapperFunctionName);
+ }
+
+ /* -----------------------------------------------------------------------
+ * terminateGatewayHeader()
+ * Terminates the gateway header
+ * ----------------------------------------------------------------------- */
+
+ void terminateGatewayHeader(String *gatewayLibraryName) {
+ Printf(gatewayHeaderV5, "};\n");
+ Printf(gatewayHeaderV5, "\n");
+ Printf(gatewayHeaderV5, "#ifdef __cplusplus\n");
+ Printf(gatewayHeaderV5, "extern \"C\" {\n");
+ Printf(gatewayHeaderV5, "#endif\n");
+ Printf(gatewayHeaderV5, "int C2F(%s)() {\n", gatewayLibraryName);
+ Printf(gatewayHeaderV5, " Rhs = Max(0, Rhs);\n");
+ Printf(gatewayHeaderV5, " if (*(Tab[Fin-1].f) != NULL) {\n");
+ Printf(gatewayHeaderV5, " if(pvApiCtx == NULL) {\n");
+ Printf(gatewayHeaderV5, " pvApiCtx = (StrCtx *)MALLOC(sizeof(StrCtx));\n");
+ Printf(gatewayHeaderV5, " }\n");
+ Printf(gatewayHeaderV5, " pvApiCtx->pstName = (char *)Tab[Fin-1].name;\n");
+ Printf(gatewayHeaderV5, " (*(Tab[Fin-1].f))(Tab[Fin-1].name,(GatefuncH)Tab[Fin-1].F);\n");
+ Printf(gatewayHeaderV5, " }\n");
+ Printf(gatewayHeaderV5, " return 0;\n");
+ Printf(gatewayHeaderV5, "}\n");
+ Printf(gatewayHeaderV5, "\n");
+ Printf(gatewayHeaderV5, "#ifdef __cplusplus\n");
+ Printf(gatewayHeaderV5, "}\n");
+ Printf(gatewayHeaderV5, "#endif\n");
+
+ Printf(gatewayHeaderV6, "return 1;\n");
+ Printf(gatewayHeaderV6, "};\n");
+
+ Printf(gatewayHeader, "#if SWIG_SCILAB_VERSION >= 600\n");
+ Printv(gatewayHeader, gatewayHeaderV6, NIL);
+ Printf(gatewayHeader, "#else\n");
+ Printv(gatewayHeader, gatewayHeaderV5, NIL);
+ Printf(gatewayHeader, "#endif\n");
+ }
+
+
+ /* -----------------------------------------------------------------------
+ * createLoaderScriptFile()
+ * Creates the loader script file (loader.sce)
+ * ----------------------------------------------------------------------- */
+
+ void createLoaderFile(String *gatewayLibraryName) {
+ String *loaderFilename = NewString("loader.sce");
+ loaderFile = NewFile(loaderFilename, "w", SWIG_output_files());
+ if (!loaderFile) {
+ FileErrorDisplay(loaderFilename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ emitBanner(loaderFile);
+
+ loaderScript = NewString("");
+ Printf(loaderScript, "%s_path = get_absolute_file_path('loader.sce');\n", gatewayLibraryName);
+ Printf(loaderScript, "[bOK, ilib] = c_link('%s');\n", gatewayLibraryName);
+ Printf(loaderScript, "if bOK then\n");
+ Printf(loaderScript, " ulink(ilib);\n");
+ Printf(loaderScript, "end\n");
+ Printf(loaderScript, "list_functions = [..\n");
+ }
+
+ /* -----------------------------------------------------------------------
+ * addFunctionInLoaderScript()
+ * Add a function in the loader script table
+ * ----------------------------------------------------------------------- */
+
+ void addFunctionInLoader(const_String_or_char_ptr scilabFunctionName) {
+ Printf(loaderScript, " '%s'; ..\n", scilabFunctionName);
+ }
+
+ /* -----------------------------------------------------------------------
+ * saveLoaderScriptFile()
+ * Terminates and saves the loader script
+ * ----------------------------------------------------------------------- */
+
+ void saveLoaderFile(String *gatewayLibraryName) {
+ Printf(loaderScript, "];\n");
+ Printf(loaderScript, "addinter(fullfile(%s_path, '%s' + getdynlibext()), '%s', list_functions);\n",
+ gatewayLibraryName, gatewayLibraryName, gatewayLibraryName);
+ Printf(loaderScript, "clear %s_path;\n", gatewayLibraryName);
+ Printf(loaderScript, "clear bOK;\n");
+ Printf(loaderScript, "clear ilib;\n");
+ Printf(loaderScript, "clear list_functions;\n");
+ Printv(loaderFile, loaderScript, NIL);
+
+ Delete(loaderFile);
+ }
+
+};
+
+extern "C" Language *swig_scilab(void) {
+ return new SCILAB();
+}
diff --git a/contrib/tools/swig/Source/Modules/swigmain.cxx b/contrib/tools/swig/Source/Modules/swigmain.cxx
new file mode 100644
index 00000000000..84ac74294c3
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/swigmain.cxx
@@ -0,0 +1,275 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * swigmain.cxx
+ *
+ * Simplified Wrapper and Interface Generator (SWIG)
+ *
+ * This file is the main entry point to SWIG. It collects the command
+ * line options, registers built-in language modules, and instantiates
+ * a module for code generation. If adding new language modules
+ * to SWIG, you would modify this file.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include <ctype.h>
+
+/* Module factories. These functions are used to instantiate
+ the built-in language modules. If adding a new language
+ module to SWIG, place a similar function here. Make sure
+ the function has "C" linkage. This is required so that modules
+ can be dynamically loaded in future versions. */
+
+extern "C" {
+ Language *swig_csharp(void);
+ Language *swig_d(void);
+ Language *swig_go(void);
+ Language *swig_guile(void);
+ Language *swig_java(void);
+ Language *swig_javascript(void);
+ Language *swig_lua(void);
+ Language *swig_mzscheme(void);
+ Language *swig_ocaml(void);
+ Language *swig_octave(void);
+ Language *swig_perl5(void);
+ Language *swig_php(void);
+ Language *swig_python(void);
+ Language *swig_r(void);
+ Language *swig_ruby(void);
+ Language *swig_scilab(void);
+ Language *swig_tcl(void);
+ Language *swig_xml(void);
+}
+
+/* Association of command line options to language modules.
+ Place an entry for new language modules here, keeping the
+ list sorted alphabetically. */
+
+static TargetLanguageModule modules[] = {
+ {"-allegrocl", NULL, "ALLEGROCL", Disabled},
+ {"-chicken", NULL, "CHICKEN", Disabled},
+ {"-clisp", NULL, "CLISP", Disabled},
+ {"-cffi", NULL, "CFFI", Disabled},
+ {"-csharp", swig_csharp, "C#", Supported},
+ {"-d", swig_d, "D", Supported},
+ {"-go", swig_go, "Go", Supported},
+ {"-guile", swig_guile, "Guile", Supported},
+ {"-java", swig_java, "Java", Supported},
+ {"-javascript", swig_javascript, "Javascript", Supported},
+ {"-lua", swig_lua, "Lua", Supported},
+ {"-modula3", NULL, "Modula 3", Disabled},
+ {"-mzscheme", swig_mzscheme, "MzScheme/Racket", Experimental},
+ {"-ocaml", swig_ocaml, "OCaml", Experimental},
+ {"-octave", swig_octave, "Octave", Supported},
+ {"-perl", swig_perl5, NULL, Supported},
+ {"-perl5", swig_perl5, "Perl 5", Supported},
+ {"-php", swig_php, NULL, Supported},
+ {"-php5", NULL, "PHP 5", Disabled},
+ {"-php7", swig_php, "PHP 7", Supported},
+ {"-pike", NULL, "Pike", Disabled},
+ {"-python", swig_python, "Python", Supported},
+ {"-r", swig_r, "R (aka GNU S)", Supported},
+ {"-ruby", swig_ruby, "Ruby", Supported},
+ {"-scilab", swig_scilab, "Scilab", Supported},
+ {"-sexp", NULL, "Lisp S-Expressions", Disabled},
+ {"-tcl", swig_tcl, NULL, Supported},
+ {"-tcl8", swig_tcl, "Tcl 8", Supported},
+ {"-uffi", NULL, "Common Lisp / UFFI", Disabled},
+ {"-xml", swig_xml, "XML", Supported},
+ {NULL, NULL, NULL, Disabled}
+};
+
+#ifdef MACSWIG
+#include <console.h>
+#include <SIOUX.h>
+#endif
+
+//-----------------------------------------------------------------
+// main()
+//
+// Main program. Initializes the files and starts the parser.
+//-----------------------------------------------------------------
+
+void SWIG_merge_envopt(const char *env, int oargc, char *oargv[], int *nargc, char ***nargv) {
+ if (!env) {
+ *nargc = oargc;
+ *nargv = (char **)malloc(sizeof(char *) * (oargc + 1));
+ memcpy(*nargv, oargv, sizeof(char *) * (oargc + 1));
+ return;
+ }
+
+ int argc = 1;
+ int arge = oargc + 1024;
+ char **argv = (char **) malloc(sizeof(char *) * (arge + 1));
+ char *buffer = (char *) malloc(2048);
+ char *b = buffer;
+ char *be = b + 1023;
+ const char *c = env;
+ while ((b != be) && *c && (argc < arge)) {
+ while (isspace(*c) && *c)
+ ++c;
+ if (*c) {
+ argv[argc] = b;
+ ++argc;
+ }
+ while ((b != be) && *c && !isspace(*c)) {
+ *(b++) = *(c++);
+ }
+ *b++ = 0;
+ }
+
+ argv[0] = oargv[0];
+ for (int i = 1; (i < oargc) && (argc < arge); ++i, ++argc) {
+ argv[argc] = oargv[i];
+ }
+ argv[argc] = NULL;
+
+ *nargc = argc;
+ *nargv = argv;
+}
+
+static void insert_option(int *argc, char ***argv, int index, char const *start, char const *end) {
+ int new_argc = *argc;
+ char **new_argv = *argv;
+ size_t option_len = end - start;
+
+ // Preserve the NULL pointer at argv[argc]
+ new_argv = (char **)realloc(new_argv, (new_argc + 2) * sizeof(char *));
+ memmove(&new_argv[index + 1], &new_argv[index], sizeof(char *) * (new_argc + 1 - index));
+ new_argc++;
+
+ new_argv[index] = (char *)malloc(option_len + 1);
+ memcpy(new_argv[index], start, option_len);
+ new_argv[index][option_len] = '\0';
+
+ *argc = new_argc;
+ *argv = new_argv;
+}
+
+static void merge_options_files(int *argc, char ***argv) {
+ static const int BUFFER_SIZE = 4096;
+ char buffer[BUFFER_SIZE];
+ int i;
+ int insert;
+ char **new_argv = *argv;
+ int new_argc = *argc;
+ FILE *f;
+
+ i = 1;
+ while (i < new_argc) {
+ if (new_argv[i] && new_argv[i][0] == '@' && (f = fopen(&new_argv[i][1], "r"))) {
+ int ci;
+ char *b;
+ char *be = &buffer[BUFFER_SIZE];
+ int quote = 0;
+ bool escape = false;
+
+ new_argc--;
+ memmove(&new_argv[i], &new_argv[i + 1], sizeof(char *) * (new_argc - i));
+ insert = i;
+ b = buffer;
+
+ while ((ci = fgetc(f)) != EOF) {
+ const char c = static_cast<char>(ci);
+ if (escape) {
+ if (b != be) {
+ *b = c;
+ ++b;
+ }
+ escape = false;
+ } else if (c == '\\') {
+ escape = true;
+ } else if (!quote && (c == '\'' || c == '"')) {
+ quote = c;
+ } else if (quote && c == quote) {
+ quote = 0;
+ } else if (isspace(c) && !quote) {
+ if (b != buffer) {
+ insert_option(&new_argc, &new_argv, insert, buffer, b);
+ insert++;
+
+ b = buffer;
+ }
+ } else if (b != be) {
+ *b = c;
+ ++b;
+ }
+ }
+ if (b != buffer)
+ insert_option(&new_argc, &new_argv, insert, buffer, b);
+ fclose(f);
+ } else {
+ ++i;
+ }
+ }
+
+ *argv = new_argv;
+ *argc = new_argc;
+}
+
+int main(int margc, char **margv) {
+ int i;
+ const TargetLanguageModule *language_module = 0;
+
+ int argc;
+ char **argv;
+
+ SWIG_merge_envopt(getenv("SWIG_FEATURES"), margc, margv, &argc, &argv);
+ merge_options_files(&argc, &argv);
+
+#ifdef MACSWIG
+ SIOUXSettings.asktosaveonclose = false;
+ argc = ccommand(&argv);
+#endif
+
+ Swig_init_args(argc, argv);
+
+ /* Get options */
+ for (i = 1; i < argc; i++) {
+ if (argv[i]) {
+ bool is_target_language_module = false;
+ for (int j = 0; modules[j].name; j++) {
+ if (strcmp(modules[j].name, argv[i]) == 0) {
+ language_module = &modules[j];
+ is_target_language_module = true;
+ break;
+ }
+ }
+ if (is_target_language_module) {
+ Swig_mark_arg(i);
+ if (language_module->status == Disabled) {
+ if (language_module->help)
+ Printf(stderr, "Target language option %s (%s) is no longer supported.\n", language_module->name, language_module->help);
+ else
+ Printf(stderr, "Target language option %s is no longer supported.\n", language_module->name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ } else if ((strcmp(argv[i], "-help") == 0) || (strcmp(argv[i], "--help") == 0)) {
+ if (strcmp(argv[i], "--help") == 0)
+ strcpy(argv[i], "-help");
+ Printf(stdout, "Supported Target Language Options\n");
+ for (int j = 0; modules[j].name; j++) {
+ if (modules[j].help && modules[j].status == Supported) {
+ Printf(stdout, " %-15s - Generate %s wrappers\n", modules[j].name, modules[j].help);
+ }
+ }
+ Printf(stdout, "\nExperimental Target Language Options\n");
+ for (int j = 0; modules[j].name; j++) {
+ if (modules[j].help && modules[j].status == Experimental) {
+ Printf(stdout, " %-15s - Generate %s wrappers\n", modules[j].name, modules[j].help);
+ }
+ }
+ // Swig_mark_arg not called as the general -help options also need to be displayed later on
+ }
+ }
+ }
+
+ int res = SWIG_main(argc, argv, language_module);
+
+ return res;
+}
diff --git a/contrib/tools/swig/Source/Modules/swigmod.h b/contrib/tools/swig/Source/Modules/swigmod.h
new file mode 100644
index 00000000000..bfb93d1a705
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/swigmod.h
@@ -0,0 +1,462 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * swigmod.h
+ *
+ * Main header file for SWIG modules.
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_SWIGMOD_H_
+#define SWIG_SWIGMOD_H_
+
+#include "swig.h"
+#include "preprocessor.h"
+#include "swigwarn.h"
+
+#define NOT_VIRTUAL 0
+#define PLAIN_VIRTUAL 1
+#define PURE_VIRTUAL 2
+
+extern String *input_file;
+extern int line_number;
+extern int start_line;
+extern int CPlusPlus; // C++ mode
+extern int Extend; // Extend mode
+extern int Verbose;
+extern int IsVirtual;
+extern int ImportMode;
+extern int NoExcept; // -no_except option
+extern int Abstract; // abstract base class
+extern int SmartPointer; // smart pointer methods being emitted
+extern int SwigRuntime;
+
+/* Overload "argc" and "argv" */
+extern String *argv_template_string;
+extern String *argc_template_string;
+
+/* Miscellaneous stuff */
+
+#define tab2 " "
+#define tab4 " "
+#define tab8 " "
+
+class Dispatcher {
+public:
+
+ Dispatcher ():cplus_mode(PUBLIC) {
+ }
+ virtual ~ Dispatcher () {
+ }
+
+ virtual int emit_one(Node *n);
+ virtual int emit_children(Node *n);
+ virtual int defaultHandler(Node *n);
+
+ /* Top of the parse tree */
+ virtual int top(Node *n) = 0;
+
+ /* SWIG directives */
+
+ virtual int applyDirective(Node *n);
+ virtual int clearDirective(Node *n);
+ virtual int constantDirective(Node *n);
+ virtual int extendDirective(Node *n);
+ virtual int fragmentDirective(Node *n);
+ virtual int importDirective(Node *n);
+ virtual int includeDirective(Node *n);
+ virtual int insertDirective(Node *n);
+ virtual int moduleDirective(Node *n);
+ virtual int nativeDirective(Node *n);
+ virtual int pragmaDirective(Node *n);
+ virtual int typemapDirective(Node *n);
+ virtual int typemapitemDirective(Node *n);
+ virtual int typemapcopyDirective(Node *n);
+ virtual int typesDirective(Node *n);
+
+ /* C/C++ parsing */
+
+ virtual int cDeclaration(Node *n);
+ virtual int externDeclaration(Node *n);
+ virtual int enumDeclaration(Node *n);
+ virtual int enumvalueDeclaration(Node *n);
+ virtual int enumforwardDeclaration(Node *n);
+ virtual int classDeclaration(Node *n);
+ virtual int classforwardDeclaration(Node *n);
+ virtual int constructorDeclaration(Node *n);
+ virtual int destructorDeclaration(Node *n);
+ virtual int accessDeclaration(Node *n);
+ virtual int usingDeclaration(Node *n);
+ virtual int namespaceDeclaration(Node *n);
+ virtual int templateDeclaration(Node *n);
+ virtual int lambdaDeclaration(Node *n);
+
+ enum AccessMode { PUBLIC, PRIVATE, PROTECTED };
+
+protected:
+ AccessMode cplus_mode;
+};
+
+/* ----------------------------------------------------------------------------
+ * class language:
+ *
+ * This class defines the functions that need to be supported by the
+ * scripting language being used. The translator calls these virtual
+ * functions to output different types of code for different languages.
+ * ------------------------------------------------------------------------- */
+
+class Language:public Dispatcher {
+public:
+ Language();
+ virtual ~Language();
+ virtual int emit_one(Node *n);
+
+ String *directorClassName(Node *n);
+
+ /* Parse command line options */
+
+ virtual void main(int argc, char *argv[]);
+
+ /* Top of the parse tree */
+
+ virtual int top(Node *n);
+
+ /* SWIG directives */
+
+
+ virtual int applyDirective(Node *n);
+ virtual int clearDirective(Node *n);
+ virtual int constantDirective(Node *n);
+ virtual int extendDirective(Node *n);
+ virtual int fragmentDirective(Node *n);
+ virtual int importDirective(Node *n);
+ virtual int includeDirective(Node *n);
+ virtual int insertDirective(Node *n);
+ virtual int moduleDirective(Node *n);
+ virtual int nativeDirective(Node *n);
+ virtual int pragmaDirective(Node *n);
+ virtual int typemapDirective(Node *n);
+ virtual int typemapcopyDirective(Node *n);
+ virtual int typesDirective(Node *n);
+
+ /* C/C++ parsing */
+
+ virtual int cDeclaration(Node *n);
+ virtual int externDeclaration(Node *n);
+ virtual int enumDeclaration(Node *n);
+ virtual int enumvalueDeclaration(Node *n);
+ virtual int enumforwardDeclaration(Node *n);
+ virtual int classDeclaration(Node *n);
+ virtual int classforwardDeclaration(Node *n);
+ virtual int constructorDeclaration(Node *n);
+ virtual int destructorDeclaration(Node *n);
+ virtual int accessDeclaration(Node *n);
+ virtual int namespaceDeclaration(Node *n);
+ virtual int usingDeclaration(Node *n);
+
+ /* Function handlers */
+
+ virtual int functionHandler(Node *n);
+ virtual int globalfunctionHandler(Node *n);
+ virtual int memberfunctionHandler(Node *n);
+ virtual int staticmemberfunctionHandler(Node *n);
+ virtual int callbackfunctionHandler(Node *n);
+
+ /* Variable handlers */
+
+ virtual int variableHandler(Node *n);
+ virtual int globalvariableHandler(Node *n);
+ virtual int membervariableHandler(Node *n);
+ virtual int staticmembervariableHandler(Node *n);
+
+ /* C++ handlers */
+
+ virtual int memberconstantHandler(Node *n);
+ virtual int constructorHandler(Node *n);
+ virtual int copyconstructorHandler(Node *n);
+ virtual int destructorHandler(Node *n);
+ virtual int classHandler(Node *n);
+
+ /* Miscellaneous */
+
+ virtual int typedefHandler(Node *n);
+
+ /* Low-level code generation */
+
+ virtual int constantWrapper(Node *n);
+ virtual int variableWrapper(Node *n);
+ virtual int functionWrapper(Node *n);
+ virtual int nativeWrapper(Node *n);
+
+ /* C++ director class generation */
+ virtual int classDirector(Node *n);
+ virtual int classDirectorInit(Node *n);
+ virtual int classDirectorEnd(Node *n);
+ virtual int unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_director, int &virtual_destructor, int protectedbase = 0);
+ virtual int classDirectorConstructor(Node *n);
+ virtual int classDirectorDefaultConstructor(Node *n);
+ virtual int classDirectorMethod(Node *n, Node *parent, String *super);
+ virtual int classDirectorConstructors(Node *n);
+ virtual int classDirectorDestructor(Node *n);
+ virtual int classDirectorMethods(Node *n);
+ virtual int classDirectorDisown(Node *n);
+
+ /* Miscellaneous */
+ virtual int validIdentifier(String *s); /* valid identifier? */
+ virtual int addSymbol(const String *s, const Node *n, const_String_or_char_ptr scope = ""); /* Add symbol */
+ virtual int addInterfaceSymbol(const String *interface_name, Node *n, const_String_or_char_ptr scope = "");
+ virtual void dumpSymbols();
+ virtual Node *symbolLookup(const String *s, const_String_or_char_ptr scope = ""); /* Symbol lookup */
+ virtual Hash* symbolAddScope(const_String_or_char_ptr scope);
+ virtual Hash* symbolScopeLookup(const_String_or_char_ptr scope);
+ virtual Hash* symbolScopePseudoSymbolLookup(const_String_or_char_ptr scope);
+ static Node *classLookup(const SwigType *s); /* Class lookup */
+ static Node *enumLookup(SwigType *s); /* Enum lookup */
+ virtual int abstractClassTest(Node *n); /* Is class really abstract? */
+ virtual int is_assignable(Node *n); /* Is variable assignable? */
+ virtual String *runtimeCode(); /* returns the language specific runtime code */
+ virtual String *defaultExternalRuntimeFilename(); /* the default filename for the external runtime */
+ virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm); /* Language specific special variable substitutions for $typemap() */
+
+ /* Runtime is C++ based, so extern "C" header section */
+ void enable_cplus_runtime_mode();
+
+ /* Returns the cplus_runtime mode */
+ int cplus_runtime_mode();
+
+ /* Allow director related code generation */
+ void allow_directors(int val = 1);
+
+ /* Return true if directors are enabled */
+ int directorsEnabled() const;
+
+ /* Allow director protected members related code generation */
+ void allow_dirprot(int val = 1);
+
+ /* Allow all protected members code generation (for directors) */
+ void allow_allprotected(int val = 0);
+
+ /* Returns the dirprot mode */
+ int dirprot_mode() const;
+
+ /* Check if the non public constructor is needed (for directors) */
+ int need_nonpublic_ctor(Node *n);
+
+ /* Check if the non public member is needed (for directors) */
+ int need_nonpublic_member(Node *n);
+
+ /* Set none comparison string */
+ void setSubclassInstanceCheck(String *s);
+
+ /* Set overload variable templates argc and argv */
+ void setOverloadResolutionTemplates(String *argc, String *argv);
+
+ /* Language instance is a singleton - get instance */
+ static Language* instance();
+
+protected:
+ /* Allow multiple-input typemaps */
+ void allow_multiple_input(int val = 1);
+
+ /* Allow overloaded functions */
+ void allow_overloading(int val = 1);
+
+ /* Wrapping class query */
+ int is_wrapping_class() const;
+
+ /* Return the node for the current class */
+ Node *getCurrentClass() const;
+
+ /* Return C++ mode */
+ int getCPlusMode() const;
+
+ /* Return the namespace for the class/enum - the nspace feature */
+ String *getNSpace() const;
+
+ /* Return the real name of the current class */
+ String *getClassName() const;
+
+ /* Return the classes hash */
+ Hash *getClassHash() const;
+
+ /* Return the current class prefix */
+ String *getClassPrefix() const;
+
+ /* Return the current enum class prefix */
+ String *getEnumClassPrefix() const;
+
+ /* Fully qualified type name to use */
+ String *getClassType() const;
+
+ /* Return true if the current method is part of a smart-pointer */
+ int is_smart_pointer() const;
+
+ /* Return the name to use for the given parameter. */
+ virtual String *makeParameterName(Node *n, Parm *p, int arg_num, bool setter = false) const;
+
+ /* Some language modules require additional wrappers for virtual methods not declared in sub-classes */
+ virtual bool extraDirectorProtectedCPPMethodsRequired() const;
+
+public:
+ enum NestedClassSupport {
+ NCS_None, // Target language does not have an equivalent to nested classes
+ NCS_Full, // Target language does have an equivalent to nested classes and is fully implemented
+ NCS_Unknown // Target language may or may not have an equivalent to nested classes. If it does, it has not been implemented yet.
+ };
+ /* Does target language support nested classes? Default is NCS_Unknown.
+ If NCS_Unknown is returned, then the nested classes will be ignored unless
+ %feature "flatnested" is applied to them, in which case they will appear in global space.
+ If the target language does not support the notion of class
+ nesting, the language module should return NCS_None from this function, and
+ the nested classes will be moved to the global scope (like implicit global %feature "flatnested").
+ */
+ virtual NestedClassSupport nestedClassesSupport() const;
+
+ /* Returns true if the target language supports key word arguments (kwargs) */
+ virtual bool kwargsSupport() const;
+
+protected:
+ /* Identifies if a protected members that are generated when the allprotected option is used.
+ This does not include protected virtual methods as they are turned on with the dirprot option. */
+ bool isNonVirtualProtectedAccess(Node *n) const;
+
+ /* Identify if a wrapped global or member variable n should use the naturalvar feature */
+ int use_naturalvar_mode(Node *n) const;
+
+ /* Director subclass comparison test */
+ String *none_comparison;
+
+ /* Director constructor "template" code */
+ String *director_ctor_code;
+
+ /* Director 'protected' constructor "template" code */
+ String *director_prot_ctor_code;
+
+ /* Director allows multiple inheritance */
+ int director_multiple_inheritance;
+
+ /* Director language module */
+ int director_language;
+
+ /* Used to translate Doxygen comments to target documentation format */
+ class DoxygenTranslator *doxygenTranslator;
+
+private:
+ Hash *symtabs; /* symbol tables */
+ int overloading;
+ int multiinput;
+ int cplus_runtime;
+ int directors;
+ static Language *this_;
+};
+
+extern "C" {
+ void SWIG_typemap_lang(const char *);
+ typedef Language *(*ModuleFactory) (void);
+}
+
+enum Status {Disabled, Experimental, Supported};
+
+struct TargetLanguageModule {
+ const char *name;
+ ModuleFactory fac;
+ const char *help;
+ Status status;
+};
+
+int SWIG_main(int argc, char *argv[], const TargetLanguageModule *tlm);
+void emit_parameter_variables(ParmList *l, Wrapper *f);
+void emit_return_variable(Node *n, SwigType *rt, Wrapper *f);
+void SWIG_config_file(const_String_or_char_ptr );
+const String *SWIG_output_directory();
+void SWIG_config_cppext(const char *ext);
+void Swig_print_xml(Node *obj, String *filename);
+
+/* get the list of generated files */
+List *SWIG_output_files();
+
+void SWIG_library_directory(const char *);
+int emit_num_arguments(ParmList *);
+int emit_num_required(ParmList *);
+int emit_isvarargs(ParmList *p);
+bool emit_isvarargs_function(Node *n);
+void emit_attach_parmmaps(ParmList *, Wrapper *f);
+void emit_mark_varargs(ParmList *l);
+String *emit_action(Node *n);
+int emit_action_code(Node *n, String *wrappercode, String *action);
+void Swig_overload_check(Node *n);
+String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *, const_String_or_char_ptr fmt_fastdispatch = 0);
+String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int *);
+List *Swig_overload_rank(Node *n, bool script_lang_wrapping);
+SwigType *cplus_value_type(SwigType *t);
+
+/* directors.cxx start */
+String *Swig_csuperclass_call(String *base, String *method, ParmList *l);
+String *Swig_class_declaration(Node *n, String *name);
+String *Swig_class_name(Node *n);
+String *Swig_method_call(const_String_or_char_ptr name, ParmList *parms);
+String *Swig_method_decl(SwigType *return_base_type, SwigType *decl, const_String_or_char_ptr id, List *args, int default_args);
+String *Swig_director_declaration(Node *n);
+void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f);
+void Swig_director_parms_fixup(ParmList *parms);
+/* directors.cxx end */
+
+/* Utilities */
+
+int is_public(Node *n);
+int is_private(Node *n);
+int is_protected(Node *n);
+int is_member_director(Node *parentnode, Node *member);
+int is_member_director(Node *member);
+int is_non_virtual_protected_access(Node *n); /* Check if the non-virtual protected members are required (for directors) */
+
+void Wrapper_virtual_elimination_mode_set(int);
+void Wrapper_fast_dispatch_mode_set(int);
+void Wrapper_cast_dispatch_mode_set(int);
+void Wrapper_naturalvar_mode_set(int);
+
+void clean_overloaded(Node *n);
+
+extern "C" {
+ const char *Swig_to_string(DOH *object, int count = -1);
+ const char *Swig_to_string_with_location(DOH *object, int count = -1);
+ void Swig_print(DOH *object, int count = -1);
+ void Swig_print_with_location(DOH *object, int count = -1);
+}
+
+/* Contracts */
+void Swig_contracts(Node *n);
+void Swig_contract_mode_set(int flag);
+int Swig_contract_mode_get();
+
+/* Browser */
+void Swig_browser(Node *n, int);
+void Swig_default_allocators(Node *n);
+void Swig_process_types(Node *n);
+
+/* Nested classes */
+void Swig_nested_process_classes(Node *n);
+void Swig_nested_name_unnamed_c_structs(Node *n);
+
+/* Interface feature */
+void Swig_interface_feature_enable();
+void Swig_interface_propagate_methods(Node *n);
+
+/* Miscellaneous */
+template <class T> class save_value {
+ T _value;
+ T& _value_ptr;
+ save_value(const save_value&);
+ save_value& operator=(const save_value&);
+
+public:
+ save_value(T& value) : _value(value), _value_ptr(value) {}
+ save_value(T& value, T new_val) : _value(value), _value_ptr(value) { value = new_val; }
+ ~save_value() { _value_ptr = _value; }
+};
+
+#endif
diff --git a/contrib/tools/swig/Source/Modules/tcl8.cxx b/contrib/tools/swig/Source/Modules/tcl8.cxx
new file mode 100644
index 00000000000..7a78ede9bc0
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/tcl8.cxx
@@ -0,0 +1,1310 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * tcl8.cxx
+ *
+ * Tcl8 language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+
+static const char *usage = "\
+Tcl 8 Options (available with -tcl8)\n\
+ -itcl - Enable ITcl support\n\
+ -nosafe - Leave out SafeInit module function.\n\
+ -prefix <name> - Set a prefix <name> to be prepended to all names\n\
+ -namespace - Build module into a Tcl 8 namespace\n\
+ -pkgversion - Set package version\n\n";
+
+static String *cmd_tab = 0; /* Table of command names */
+static String *var_tab = 0; /* Table of global variables */
+static String *const_tab = 0; /* Constant table */
+static String *methods_tab = 0; /* Methods table */
+static String *attr_tab = 0; /* Attribute table */
+static String *prefix = 0;
+static String *module = 0;
+static int namespace_option = 0;
+static String *init_name = 0;
+static String *ns_name = 0;
+static int have_constructor;
+static String *constructor_name;
+static int have_destructor;
+static int have_base_classes;
+static String *destructor_action = 0;
+static String *version = (String *) "0.0";
+static String *class_name = 0;
+
+static int have_attributes;
+static int have_methods;
+static int nosafe = 0;
+
+static File *f_header = 0;
+static File *f_wrappers = 0;
+static File *f_init = 0;
+static File *f_begin = 0;
+static File *f_runtime = 0;
+
+
+// Itcl support
+static int itcl = 0;
+static File *f_shadow = 0;
+static File *f_shadow_stubs = 0;
+
+static String *constructor = 0;
+static String *destructor = 0;
+static String *base_classes = 0;
+static String *base_class_init = 0;
+static String *methods = 0;
+static String *imethods = 0;
+static String *attributes = 0;
+static String *attribute_traces = 0;
+static String *iattribute_traces = 0;
+
+
+
+class TCL8:public Language {
+public:
+
+ /* ------------------------------------------------------------
+ * TCL8::main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+
+ SWIG_library_directory("tcl");
+
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-prefix") == 0) {
+ if (argv[i + 1]) {
+ prefix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else
+ Swig_arg_error();
+ } else if (strcmp(argv[i], "-pkgversion") == 0) {
+ if (argv[i + 1]) {
+ version = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ }
+ } else if (strcmp(argv[i], "-namespace") == 0) {
+ namespace_option = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-itcl") == 0) {
+ itcl = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nosafe") == 0) {
+ nosafe = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ } else if (strcmp(argv[i], "-cppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]);
+ Swig_mark_arg(i);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ Preprocessor_define("SWIGTCL 1", 0);
+ // SWIGTCL8 is deprecated, and no longer documented.
+ Preprocessor_define("SWIGTCL8 1", 0);
+ SWIG_typemap_lang("tcl8");
+ SWIG_config_file("tcl8.swg");
+ allow_overloading();
+ }
+
+ /* ------------------------------------------------------------
+ * top()
+ * ------------------------------------------------------------ */
+
+ virtual int top(Node *n) {
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+
+ /* Initialize some variables for the object interface */
+
+ cmd_tab = NewString("");
+ var_tab = NewString("");
+ methods_tab = NewString("");
+ const_tab = NewString("");
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n\n#ifndef SWIGTCL\n#define SWIGTCL\n#endif\n\n");
+
+ /* Set the module name, namespace, and prefix */
+
+ module = NewStringf("%(lower)s", Getattr(n, "name"));
+ init_name = NewStringf("%(title)s_Init", module);
+
+ ns_name = prefix ? Copy(prefix) : Copy(module);
+ if (prefix)
+ Append(prefix, "_");
+
+
+ /* If shadow classing is enabled, we're going to change the module name to "_module" */
+ if (itcl) {
+ String *filen;
+ filen = NewStringf("%s%s.itcl", SWIG_output_directory(), module);
+
+ Insert(module, 0, "_");
+
+ if ((f_shadow = NewFile(filen, "w", SWIG_output_files())) == 0) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ f_shadow_stubs = NewString("");
+
+ Swig_register_filebyname("shadow", f_shadow);
+ Swig_register_filebyname("itcl", f_shadow);
+
+ Swig_banner_target_lang(f_shadow, "#");
+
+ Printv(f_shadow, "\npackage require Itcl\n\n", NIL);
+ Delete(filen);
+ }
+
+ /* Generate some macros used throughout code generation */
+
+ Printf(f_header, "#define SWIG_init %s\n", init_name);
+ Printf(f_header, "#define SWIG_name \"%s\"\n", module);
+ if (namespace_option) {
+ Printf(f_header, "#define SWIG_prefix \"%s::\"\n", ns_name);
+ Printf(f_header, "#define SWIG_namespace \"%s\"\n\n", ns_name);
+ } else {
+ Printf(f_header, "#define SWIG_prefix \"%s\"\n", prefix);
+ }
+ Printf(f_header, "#define SWIG_version \"%s\"\n", version);
+
+ Printf(cmd_tab, "\nstatic swig_command_info swig_commands[] = {\n");
+ Printf(var_tab, "\nstatic swig_var_info swig_variables[] = {\n");
+ Printf(const_tab, "\nstatic swig_const_info swig_constants[] = {\n");
+
+ Printf(f_wrappers, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
+
+ /* Start emitting code */
+ Language::top(n);
+
+ /* Done. Close up the module */
+ Printv(cmd_tab, tab4, "{0, 0, 0}\n", "};\n", NIL);
+ Printv(var_tab, tab4, "{0,0,0,0}\n", "};\n", NIL);
+ Printv(const_tab, tab4, "{0,0,0,0,0,0}\n", "};\n", NIL);
+
+ Printv(f_wrappers, cmd_tab, var_tab, const_tab, NIL);
+
+ /* Dump the pointer equivalency table */
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n}\n#endif\n");
+
+ /* Close the init function and quit */
+ Printf(f_init, "return TCL_OK;\n}\n");
+
+ if (!nosafe) {
+ Printf(f_init, "SWIGEXPORT int %(title)s_SafeInit(Tcl_Interp *interp) {\n", module);
+ Printf(f_init, " return SWIG_init(interp);\n");
+ Printf(f_init, "}\n");
+ }
+
+ if (itcl) {
+ Printv(f_shadow, f_shadow_stubs, "\n", NIL);
+ Delete(f_shadow);
+ }
+
+ /* Close all of the files */
+ Dump(f_runtime, f_begin);
+ Printv(f_begin, f_header, f_wrappers, NIL);
+ Wrapper_pretty_print(f_init, f_begin);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_runtime);
+ Delete(f_begin);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * functionWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int functionWrapper(Node *n) {
+ String *name = Getattr(n, "name"); /* Like to get rid of this */
+ String *iname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ ParmList *parms = Getattr(n, "parms");
+ String *overname = 0;
+
+ Parm *p;
+ int i;
+ String *tm;
+ Wrapper *f;
+ String *incode, *cleanup, *outarg, *argstr, *args;
+ int num_arguments = 0;
+ int num_required = 0;
+ int varargs = 0;
+
+ char source[64];
+
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+ }
+
+ incode = NewString("");
+ cleanup = NewString("");
+ outarg = NewString("");
+ argstr = NewString("\"");
+ args = NewString("");
+
+ f = NewWrapper();
+
+#ifdef SWIG_USE_RESULTOBJ
+ Wrapper_add_local(f, "resultobj", "Tcl_Obj *resultobj = NULL");
+#endif
+
+
+ String *wname = Swig_name_wrapper(iname);
+ if (overname) {
+ Append(wname, overname);
+ }
+ Setattr(n, "wrap:name", wname);
+
+ Printv(f->def, "SWIGINTERN int\n ", wname, "(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {", NIL);
+
+ // Emit all of the local variables for holding arguments.
+ emit_parameter_variables(parms, f);
+
+ /* Attach standard typemaps */
+ emit_attach_parmmaps(parms, f);
+ Setattr(n, "wrap:parms", parms);
+
+ /* Get number of require and total arguments */
+ num_arguments = emit_num_arguments(parms);
+ num_required = emit_num_required(parms);
+ varargs = emit_isvarargs(parms);
+
+ /* Unmarshal parameters */
+
+ for (i = 0, p = parms; i < num_arguments; i++) {
+ /* Skip ignored arguments */
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+
+ /* Produce string representations of the source and target arguments */
+ sprintf(source, "objv[%d]", i + 1);
+
+ if (i == num_required)
+ Putc('|', argstr);
+ if ((tm = Getattr(p, "tmap:in"))) {
+ String *parse = Getattr(p, "tmap:in:parse");
+ if (!parse) {
+ Replaceall(tm, "$target", ln);
+ Replaceall(tm, "$source", source);
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source);
+
+ if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+
+ Putc('o', argstr);
+ Printf(args, ",(void *)0");
+ if (i >= num_required) {
+ Printf(incode, "if (objc > %d) {\n", i + 1);
+ }
+ Printf(incode, "%s\n", tm);
+ if (i >= num_required) {
+ Printf(incode, "}\n");
+ }
+ } else {
+ Printf(argstr, "%s", parse);
+ Printf(args, ",&%s", ln);
+ if (Strcmp(parse, "p") == 0) {
+ SwigType *lt = SwigType_ltype(pt);
+ SwigType_remember(pt);
+ if (Cmp(lt, "p.void") == 0) {
+ Printf(args, ",(void *)0");
+ } else {
+ Printf(args, ",SWIGTYPE%s", SwigType_manglestr(pt));
+ }
+ Delete(lt);
+ }
+ }
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ } else {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
+ }
+ p = nextSibling(p);
+ }
+
+ if (!varargs) {
+ Putc(':', argstr);
+ } else {
+ Putc(';', argstr);
+ /* If variable length arguments we need to emit the in typemap here */
+ if (p && (tm = Getattr(p, "tmap:in"))) {
+ sprintf(source, "objv[%d]", i + 1);
+ Printf(incode, "if (objc > %d) {\n", i);
+ Replaceall(tm, "$input", source);
+ Printv(incode, tm, "\n", NIL);
+ Printf(incode, "}\n");
+ }
+ }
+
+ Printf(argstr, "%s\"", usage_string(Char(iname), type, parms));
+
+ Printv(f->code, "if (SWIG_GetArgs(interp, objc, objv,", argstr, args, ") == TCL_ERROR) SWIG_fail;\n", NIL);
+
+ Printv(f->code, incode, NIL);
+
+ /* Insert constraint checking code */
+ for (p = parms; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ for (i = 0, p = parms; p; i++) {
+ if (!checkAttribute(p, "tmap:in:numinputs", "0")
+ && !Getattr(p, "tmap:in:parse") && (tm = Getattr(p, "tmap:freearg"))) {
+ if (Len(tm) != 0) {
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+ Printv(cleanup, tm, "\n", NIL);
+ }
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert argument output code */
+ for (i = 0, p = parms; p; i++) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+#ifdef SWIG_USE_RESULTOBJ
+ Replaceall(tm, "$target", "resultobj");
+ Replaceall(tm, "$result", "resultobj");
+#else
+ Replaceall(tm, "$target", "(Tcl_GetObjResult(interp))");
+ Replaceall(tm, "$result", "(Tcl_GetObjResult(interp))");
+#endif
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Now write code to make the function call */
+ String *actioncode = emit_action(n);
+
+ /* Need to redo all of this code (eventually) */
+
+ /* Return value if necessary */
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+#ifdef SWIG_USE_RESULTOBJ
+ Replaceall(tm, "$target", "resultobj");
+ Replaceall(tm, "$result", "resultobj");
+#else
+ Replaceall(tm, "$target", "(Tcl_GetObjResult(interp))");
+ Replaceall(tm, "$result", "(Tcl_GetObjResult(interp))");
+#endif
+ if (GetFlag(n, "feature:new")) {
+ Replaceall(tm, "$owner", "SWIG_POINTER_OWN");
+ } else {
+ Replaceall(tm, "$owner", "0");
+ }
+ Printf(f->code, "%s\n", tm);
+ } 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), name);
+ }
+ emit_return_variable(n, type, f);
+
+ /* Dump output argument code */
+ Printv(f->code, outarg, NIL);
+
+ /* Dump the argument cleanup code */
+ Printv(f->code, cleanup, NIL);
+
+ /* Look for any remaining cleanup */
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$source", Swig_cresult_name());
+ Printf(f->code, "%s\n", tm);
+ }
+#ifdef SWIG_USE_RESULTOBJ
+ Printv(f->code, "if (resultobj) Tcl_SetObjResult(interp, resultobj);\n", NIL);
+#endif
+ Printv(f->code, "return TCL_OK;\n", NIL);
+ Printv(f->code, "fail:\n", cleanup, "return TCL_ERROR;\n", NIL);
+ Printv(f->code, "}\n", NIL);
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+ Replaceall(f->code, "$symname", iname);
+
+ /* Dump out the function */
+ Wrapper_print(f, f_wrappers);
+
+ if (!Getattr(n, "sym:overloaded")) {
+ /* Register the function with Tcl */
+ Printv(cmd_tab, tab4, "{ SWIG_prefix \"", iname, "\", (swig_wrapper_func) ", Swig_name_wrapper(iname), ", NULL},\n", NIL);
+ } else {
+ if (!Getattr(n, "sym:nextSibling")) {
+ /* Emit overloading dispatch function */
+
+ int maxargs;
+ String *dispatch = Swig_overload_dispatch(n, "return %s(clientData, interp, objc, argv - 1);", &maxargs);
+
+ /* Generate a dispatch wrapper for all overloaded functions */
+
+ Wrapper *df = NewWrapper();
+ String *dname = Swig_name_wrapper(iname);
+
+ Printv(df->def, "SWIGINTERN int\n", dname, "(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {", NIL);
+ Printf(df->code, "Tcl_Obj *CONST *argv = objv+1;\n");
+ Printf(df->code, "int argc = objc-1;\n");
+ Printv(df->code, dispatch, "\n", NIL);
+ Node *sibl = n;
+ while (Getattr(sibl, "sym:previousSibling"))
+ sibl = Getattr(sibl, "sym:previousSibling"); // go all the way up
+ String *protoTypes = NewString("");
+ do {
+ String *fulldecl = Swig_name_decl(sibl);
+ Printf(protoTypes, "\n\" %s\\n\"", fulldecl);
+ Delete(fulldecl);
+ } while ((sibl = Getattr(sibl, "sym:nextSibling")));
+ Printf(df->code, "Tcl_SetResult(interp,(char *) "
+ "\"Wrong number or type of arguments for overloaded function '%s'.\\n\""
+ "\n\" Possible C/C++ prototypes are:\\n\"%s, TCL_STATIC);\n", iname, protoTypes);
+ Delete(protoTypes);
+ Printf(df->code, "return TCL_ERROR;\n");
+ Printv(df->code, "}\n", NIL);
+ Wrapper_print(df, f_wrappers);
+ Printv(cmd_tab, tab4, "{ SWIG_prefix \"", iname, "\", (swig_wrapper_func) ", dname, ", NULL},\n", NIL);
+ DelWrapper(df);
+ Delete(dispatch);
+ Delete(dname);
+ }
+ }
+
+ Delete(incode);
+ Delete(cleanup);
+ Delete(outarg);
+ Delete(argstr);
+ Delete(args);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * variableWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int variableWrapper(Node *n) {
+
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+
+ String *setname = 0;
+ String *setfname = 0;
+ Wrapper *setf = 0, *getf = 0;
+ int readonly = 0;
+ String *tm;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ /* Create a function for getting a variable */
+ int addfail = 0;
+ getf = NewWrapper();
+ String *getname = Swig_name_get(NSPACE_TODO, iname);
+ String *getfname = Swig_name_wrapper(getname);
+ Setattr(n, "wrap:name", getfname);
+ Printv(getf->def, "SWIGINTERN const char *", getfname, "(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, char *name1, char *name2, int flags) {", NIL);
+ Wrapper_add_local(getf, "value", "Tcl_Obj *value = 0");
+ if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
+ Replaceall(tm, "$source", name);
+ Replaceall(tm, "$target", "value");
+ Replaceall(tm, "$result", "value");
+ /* Printf(getf->code, "%s\n",tm); */
+ addfail = emit_action_code(n, getf->code, tm);
+ Printf(getf->code, "if (value) {\n");
+ Printf(getf->code, "Tcl_SetVar2(interp,name1,name2,Tcl_GetStringFromObj(value,NULL), flags);\n");
+ Printf(getf->code, "Tcl_DecrRefCount(value);\n");
+ Printf(getf->code, "}\n");
+ Printf(getf->code, "return NULL;\n");
+ if (addfail) {
+ Append(getf->code, "fail:\n");
+ Printf(getf->code, "return \"%s\";\n", iname);
+ }
+ Printf(getf->code, "}\n");
+ Wrapper_print(getf, f_wrappers);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
+ DelWrapper(getf);
+ return SWIG_NOWRAP;
+ }
+ DelWrapper(getf);
+
+ /* Try to create a function setting a variable */
+ if (is_assignable(n)) {
+ setf = NewWrapper();
+ setname = Swig_name_set(NSPACE_TODO, iname);
+ setfname = Swig_name_wrapper(setname);
+ Setattr(n, "wrap:name", setfname);
+ if (setf) {
+ Printv(setf->def, "SWIGINTERN const char *", setfname,
+ "(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, char *name1, char *name2 SWIGUNUSED, int flags) {", NIL);
+ Wrapper_add_local(setf, "value", "Tcl_Obj *value = 0");
+ Wrapper_add_local(setf, "name1o", "Tcl_Obj *name1o = 0");
+
+ if ((tm = Swig_typemap_lookup("varin", n, name, 0))) {
+ Replaceall(tm, "$source", "value");
+ Replaceall(tm, "$target", name);
+ Replaceall(tm, "$input", "value");
+ Printf(setf->code, "name1o = Tcl_NewStringObj(name1,-1);\n");
+ Printf(setf->code, "value = Tcl_ObjGetVar2(interp, name1o, 0, flags);\n");
+ Printf(setf->code, "Tcl_DecrRefCount(name1o);\n");
+ Printf(setf->code, "if (!value) SWIG_fail;\n");
+ /* Printf(setf->code,"%s\n", tm); */
+ emit_action_code(n, setf->code, tm);
+ Printf(setf->code, "return NULL;\n");
+ Printf(setf->code, "fail:\n");
+ Printf(setf->code, "return \"%s\";\n", iname);
+ Printf(setf->code, "}\n");
+ Wrapper_print(setf, f_wrappers);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0));
+ readonly = 1;
+ }
+ }
+ DelWrapper(setf);
+ } else {
+ readonly = 1;
+ }
+
+
+ Printv(var_tab, tab4, "{ SWIG_prefix \"", iname, "\", 0, (swig_variable_func) ", getfname, ",", NIL);
+ if (readonly) {
+ static int readonlywrap = 0;
+ if (!readonlywrap) {
+ Wrapper *ro = NewWrapper();
+ Printf(ro->def,
+ "SWIGINTERN const char *swig_readonly(ClientData clientData SWIGUNUSED, Tcl_Interp *interp SWIGUNUSED, char *name1 SWIGUNUSED, char *name2 SWIGUNUSED, int flags SWIGUNUSED) {");
+ Printv(ro->code, "return \"Variable is read-only\";\n", "}\n", NIL);
+ Wrapper_print(ro, f_wrappers);
+ readonlywrap = 1;
+ DelWrapper(ro);
+ }
+ Printf(var_tab, "(swig_variable_func) swig_readonly},\n");
+ } else {
+ Printv(var_tab, "(swig_variable_func) ", setfname, "},\n", NIL);
+ }
+ Delete(getfname);
+ Delete(setfname);
+ Delete(setname);
+ Delete(getname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ String *nsname = !namespace_option ? Copy(iname) : NewStringf("%s::%s", ns_name, iname);
+ SwigType *type = Getattr(n, "type");
+ String *rawval = Getattr(n, "rawval");
+ String *value = rawval ? rawval : Getattr(n, "value");
+ String *tm;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+ if (namespace_option)
+ Setattr(n, "sym:name", nsname);
+
+ /* Special hook for member pointer */
+ if (SwigType_type(type) == T_MPOINTER) {
+ String *wname = Swig_name_wrapper(iname);
+ Printf(f_wrappers, "static %s = %s;\n", SwigType_str(type, wname), value);
+ value = Char(wname);
+ }
+
+ if ((tm = Swig_typemap_lookup("consttab", n, name, 0))) {
+ Replaceall(tm, "$source", value);
+ Replaceall(tm, "$target", name);
+ Replaceall(tm, "$value", value);
+ Replaceall(tm, "$nsname", nsname);
+ Printf(const_tab, "%s,\n", tm);
+ } else if ((tm = Swig_typemap_lookup("constcode", n, name, 0))) {
+ Replaceall(tm, "$source", value);
+ Replaceall(tm, "$target", name);
+ Replaceall(tm, "$value", value);
+ Replaceall(tm, "$nsname", nsname);
+ Printf(f_init, "%s\n", tm);
+ } else {
+ Delete(nsname);
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
+ return SWIG_NOWRAP;
+ }
+ Delete(nsname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * nativeWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int nativeWrapper(Node *n) {
+ String *name = Getattr(n, "sym:name");
+ String *funcname = Getattr(n, "wrap:name");
+ if (!addSymbol(funcname, n))
+ return SWIG_ERROR;
+
+ Printf(f_init, "\t Tcl_CreateObjCommand(interp, SWIG_prefix \"%s\", (swig_wrapper_func) %s, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);\n", name,
+ funcname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int classHandler(Node *n) {
+ static Hash *emitted = NewHash();
+ String *mangled_classname = 0;
+ String *real_classname = 0;
+
+ have_constructor = 0;
+ have_destructor = 0;
+ destructor_action = 0;
+ constructor_name = 0;
+
+ if (itcl) {
+ constructor = NewString("");
+ destructor = NewString("");
+ base_classes = NewString("");
+ base_class_init = NewString("");
+ methods = NewString("");
+ imethods = NewString("");
+ attributes = NewString("");
+ attribute_traces = NewString("");
+ iattribute_traces = NewString("");
+
+ have_base_classes = 0;
+ have_methods = 0;
+ have_attributes = 0;
+ }
+
+ class_name = Getattr(n, "sym:name");
+ if (!addSymbol(class_name, n))
+ return SWIG_ERROR;
+
+ real_classname = Getattr(n, "name");
+ mangled_classname = Swig_name_mangle(real_classname);
+
+ if (Getattr(emitted, mangled_classname))
+ return SWIG_NOWRAP;
+ Setattr(emitted, mangled_classname, "1");
+
+ attr_tab = NewString("");
+ Printf(attr_tab, "static swig_attribute swig_");
+ Printv(attr_tab, mangled_classname, "_attributes[] = {\n", NIL);
+
+ methods_tab = NewStringf("");
+ Printf(methods_tab, "static swig_method swig_");
+ Printv(methods_tab, mangled_classname, "_methods[] = {\n", NIL);
+
+ /* Generate normal wrappers */
+ Language::classHandler(n);
+
+ SwigType *t = Copy(Getattr(n, "name"));
+ SwigType_add_pointer(t);
+
+ // Catch all: eg. a class with only static functions and/or variables will not have 'remembered'
+ // SwigType_remember(t);
+ String *wrap_class = NewStringf("&_wrap_class_%s", mangled_classname);
+ SwigType_remember_clientdata(t, wrap_class);
+
+ String *rt = Copy(getClassType());
+ SwigType_add_pointer(rt);
+
+ // Register the class structure with the type checker
+ /* Printf(f_init,"SWIG_TypeClientData(SWIGTYPE%s, (void *) &_wrap_class_%s);\n", SwigType_manglestr(t), mangled_classname); */
+ if (have_destructor) {
+ Printv(f_wrappers, "SWIGINTERN void swig_delete_", class_name, "(void *obj) {\n", NIL);
+ if (destructor_action) {
+ Printv(f_wrappers, SwigType_str(rt, "arg1"), " = (", SwigType_str(rt, 0), ") obj;\n", NIL);
+ Printv(f_wrappers, destructor_action, "\n", NIL);
+ } else {
+ if (CPlusPlus) {
+ Printv(f_wrappers, " delete (", SwigType_str(rt, 0), ") obj;\n", NIL);
+ } else {
+ Printv(f_wrappers, " free((char *) obj);\n", NIL);
+ }
+ }
+ Printf(f_wrappers, "}\n");
+ }
+
+ Printf(methods_tab, " {0,0}\n};\n");
+ Printv(f_wrappers, methods_tab, NIL);
+
+ Printf(attr_tab, " {0,0,0}\n};\n");
+ Printv(f_wrappers, attr_tab, NIL);
+
+ /* Handle inheritance */
+
+ String *base_class = NewString("");
+ String *base_class_names = NewString("");
+
+ if (itcl) {
+ base_classes = NewString("");
+ }
+
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator b;
+ int index = 0;
+ b = First(baselist);
+ while (b.item) {
+ String *bname = Getattr(b.item, "name");
+ if ((!bname) || GetFlag(b.item, "feature:ignore") || (!Getattr(b.item, "module"))) {
+ b = Next(b);
+ continue;
+ }
+ if (itcl) {
+ have_base_classes = 1;
+ Printv(base_classes, bname, " ", NIL);
+ Printv(base_class_init, " ", bname, "Ptr::constructor $ptr\n", NIL);
+ }
+ String *bmangle = Swig_name_mangle(bname);
+ // Printv(f_wrappers,"extern swig_class _wrap_class_", bmangle, ";\n", NIL);
+ // Printf(base_class,"&_wrap_class_%s",bmangle);
+ Printf(base_class, "0");
+ Printf(base_class_names, "\"%s *\",", SwigType_namestr(bname));
+ /* Put code to register base classes in init function */
+
+ //Printf(f_init,"/* Register base : %s */\n", bmangle);
+ //Printf(f_init,"swig_%s_bases[%d] = (swig_class *) SWIG_TypeQuery(\"%s *\")->clientdata;\n", mangled_classname, index, SwigType_namestr(bname));
+ b = Next(b);
+ index++;
+ Putc(',', base_class);
+ Delete(bmangle);
+ }
+ }
+
+ if (itcl) {
+ String *ptrclass = NewString("");
+
+ // First, build the pointer base class
+ Printv(ptrclass, "itcl::class ", class_name, "Ptr {\n", NIL);
+ if (have_base_classes)
+ Printv(ptrclass, " inherit ", base_classes, "\n", NIL);
+
+ // Define protected variables for SWIG object pointer
+ Printv(ptrclass, " protected variable swigobj\n", " protected variable thisown\n", NIL);
+
+ // Define public variables
+ if (have_attributes) {
+ Printv(ptrclass, attributes, NIL);
+
+ // base class swig_getset was being called for complex inheritance trees
+ if (namespace_option) {
+
+ Printv(ptrclass, " protected method ", class_name, "_swig_getset {var name1 name2 op} {\n", NIL);
+
+ Printv(ptrclass,
+ " switch -exact -- $op {\n",
+ " r {set $var [", ns_name, "::", class_name, "_[set var]_get $swigobj]}\n",
+ " w {", ns_name, "::", class_name, "_${var}_set $swigobj [set $var]}\n", " }\n", " }\n", NIL);
+ } else {
+ Printv(ptrclass,
+ " protected method ", class_name, "_swig_getset {var name1 name2 op} {\n",
+ " switch -exact -- $op {\n",
+ " r {set $var [", class_name, "_[set var]_get $swigobj]}\n",
+ " w {", class_name, "_${var}_set $swigobj [set $var]}\n", " }\n", " }\n", NIL);
+ }
+ }
+ // Add the constructor, which may include
+ // calls to base class class constructors
+
+ Printv(ptrclass, " constructor { ptr } {\n", NIL);
+ if (have_base_classes) {
+ Printv(ptrclass, base_class_init, NIL);
+ Printv(ptrclass, " } {\n", NIL);
+ }
+
+ Printv(ptrclass, " set swigobj $ptr\n", " set thisown 0\n", NIL);
+
+ if (have_attributes) {
+ Printv(ptrclass, attribute_traces, NIL);
+ }
+ Printv(ptrclass, " }\n", NIL);
+
+
+ // Add destructor
+ Printv(ptrclass, " destructor {\n",
+ " set d_func delete_", class_name, "\n",
+ " if { $thisown && ([info command $d_func] != \"\") } {\n" " $d_func $swigobj\n", " }\n", " }\n", NIL);
+
+ // Add methods
+ if (have_methods) {
+ Printv(ptrclass, imethods, NIL);
+ };
+
+ // Close out the pointer class
+ Printv(ptrclass, "}\n\n", NIL);
+ Printv(f_shadow, ptrclass, NIL);
+ // pointer class end
+
+
+ // Create the "real" class.
+ Printv(f_shadow, "itcl::class ", class_name, " {\n", NIL);
+ Printv(f_shadow, " inherit ", class_name, "Ptr\n", NIL);
+
+ // If we have a constructor, then use it.
+ // If not, then we must have an abstract class without
+ // any constructor. So we create a class constructor
+ // which will fail for this class (but not for inherited
+ // classes). Note that the constructor must fail before
+ // calling the ptrclass constructor.
+
+ if (have_constructor) {
+ Printv(f_shadow, constructor, NIL);
+ } else {
+ Printv(f_shadow, " constructor { } {\n", NIL);
+ Printv(f_shadow, " # This constructor will fail if called directly\n", NIL);
+ Printv(f_shadow, " if { [info class] == \"::", class_name, "\" } {\n", NIL);
+ Printv(f_shadow, " error \"No constructor for class ", class_name, (Getattr(n, "abstracts") ? " - class is abstract" : ""), "\"\n", NIL);
+ Printv(f_shadow, " }\n", NIL);
+ Printv(f_shadow, " }\n", NIL);
+ }
+
+ Printv(f_shadow, "}\n\n", NIL);
+ }
+
+ Printv(f_wrappers, "static swig_class *swig_", mangled_classname, "_bases[] = {", base_class, "0};\n", NIL);
+ Printv(f_wrappers, "static const char * swig_", mangled_classname, "_base_names[] = {", base_class_names, "0};\n", NIL);
+ Delete(base_class);
+ Delete(base_class_names);
+
+ Printv(f_wrappers, "static swig_class _wrap_class_", mangled_classname, " = { \"", class_name, "\", &SWIGTYPE", SwigType_manglestr(t), ",", NIL);
+
+ if (have_constructor) {
+ Printf(f_wrappers, "%s", Swig_name_wrapper(Swig_name_construct(NSPACE_TODO, constructor_name)));
+ Delete(constructor_name);
+ constructor_name = 0;
+ } else {
+ Printf(f_wrappers, "0");
+ }
+ if (have_destructor) {
+ Printv(f_wrappers, ", swig_delete_", class_name, NIL);
+ } else {
+ Printf(f_wrappers, ",0");
+ }
+ Printv(f_wrappers, ", swig_", mangled_classname, "_methods, swig_", mangled_classname, "_attributes, swig_", mangled_classname, "_bases,",
+ "swig_", mangled_classname, "_base_names, &swig_module, SWIG_TCL_HASHTABLE_INIT };\n", NIL);
+
+ if (!itcl) {
+ Printv(cmd_tab, tab4, "{ SWIG_prefix \"", class_name, "\", (swig_wrapper_func) SWIG_ObjectConstructor, (ClientData)&_wrap_class_", mangled_classname,
+ "},\n", NIL);
+ };
+
+ Delete(t);
+ Delete(mangled_classname);
+ return SWIG_OK;
+ }
+
+
+ /* ------------------------------------------------------------
+ * memberfunctionHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int memberfunctionHandler(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = GetChar(n, "sym:name");
+
+ String *realname, *rname;
+
+ Language::memberfunctionHandler(n);
+
+ realname = iname ? iname : name;
+ rname = Swig_name_wrapper(Swig_name_member(NSPACE_TODO, class_name, realname));
+ if (!Getattr(n, "sym:nextSibling")) {
+ Printv(methods_tab, tab4, "{\"", realname, "\", ", rname, "}, \n", NIL);
+ }
+
+ if (itcl) {
+ ParmList *l = Getattr(n, "parms");
+ Parm *p = 0;
+ String *pname = NewString("");
+
+ // Add this member to our class handler function
+ Printv(imethods, tab2, "method ", realname, " [list ", NIL);
+
+ int pnum = 0;
+ for (p = l; p; p = nextSibling(p)) {
+
+ String *pn = Getattr(p, "name");
+ String *dv = Getattr(p, "value");
+ SwigType *pt = Getattr(p, "type");
+
+ Printv(pname, ",(", pt, ")", NIL);
+ Clear(pname);
+
+ /* Only print an argument if not void */
+ if (Cmp(pt, "void") != 0) {
+ if (Len(pn) > 0) {
+ Printv(pname, pn, NIL);
+ } else {
+ Printf(pname, "p%d", pnum);
+ }
+
+ if (Len(dv) > 0) {
+ String *defval = NewString(dv);
+ if (namespace_option) {
+ Insert(defval, 0, "::");
+ Insert(defval, 0, ns_name);
+ }
+ if (Strncmp(dv, "(", 1) == 0) {
+ Insert(defval, 0, "$");
+ Replaceall(defval, "(", "");
+ Replaceall(defval, ")", "");
+ }
+ Printv(imethods, "[list ", pname, " ", defval, "] ", NIL);
+ } else {
+ Printv(imethods, pname, " ", NIL);
+ }
+ }
+ ++pnum;
+ }
+ Printv(imethods, "] ", NIL);
+
+ if (namespace_option) {
+ Printv(imethods, "{ ", ns_name, "::", class_name, "_", realname, " $swigobj", NIL);
+ } else {
+ Printv(imethods, "{ ", class_name, "_", realname, " $swigobj", NIL);
+ };
+
+ pnum = 0;
+ for (p = l; p; p = nextSibling(p)) {
+
+ String *pn = Getattr(p, "name");
+ SwigType *pt = Getattr(p, "type");
+ Clear(pname);
+
+ /* Only print an argument if not void */
+ if (Cmp(pt, "void") != 0) {
+ if (Len(pn) > 0) {
+ Printv(pname, pn, NIL);
+ } else {
+ Printf(pname, "p%d", pnum);
+ }
+ Printv(imethods, " $", pname, NIL);
+ }
+ ++pnum;
+ }
+ Printv(imethods, " }\n", NIL);
+ have_methods = 1;
+ }
+
+ Delete(rname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * membervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int membervariableHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ String *rname;
+
+ Language::membervariableHandler(n);
+ Printv(attr_tab, tab4, "{ \"-", symname, "\",", NIL);
+ rname = Swig_name_wrapper(Swig_name_get(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname)));
+ Printv(attr_tab, rname, ", ", NIL);
+ Delete(rname);
+ if (!GetFlag(n, "feature:immutable")) {
+ rname = Swig_name_wrapper(Swig_name_set(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname)));
+ Printv(attr_tab, rname, "},\n", NIL);
+ Delete(rname);
+ } else {
+ Printf(attr_tab, "0 },\n");
+ }
+
+ if (itcl) {
+ Printv(attributes, " public variable ", symname, "\n", NIL);
+
+ Printv(attribute_traces, " trace variable ", symname, " rw [list ", class_name, "_swig_getset ", symname, "]\n", NIL);
+ Printv(attribute_traces, " set ", symname, "\n", NIL);
+
+ have_attributes = 1;
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constructorHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int constructorHandler(Node *n) {
+ Language::constructorHandler(n);
+
+ if (itcl) {
+ String *name = Getattr(n, "name");
+ String *iname = GetChar(n, "sym:name");
+
+ String *realname;
+
+ ParmList *l = Getattr(n, "parms");
+ Parm *p = 0;
+
+ String *pname = NewString("");
+
+ realname = iname ? iname : name;
+
+ if (!have_constructor) {
+ // Add this member to our class handler function
+ Printf(constructor, " constructor { ");
+
+ // Add parameter list
+ int pnum = 0;
+ for (p = l; p; p = nextSibling(p)) {
+
+ SwigType *pt = Getattr(p, "type");
+ String *pn = Getattr(p, "name");
+ String *dv = Getattr(p, "value");
+ Clear(pname);
+
+ /* Only print an argument if not void */
+ if (Cmp(pt, "void") != 0) {
+ if (Len(pn) > 0) {
+ Printv(pname, pn, NIL);
+ } else {
+ Printf(pname, "p%d", pnum);
+ }
+
+ if (Len(dv) > 0) {
+ Printv(constructor, "{", pname, " {", dv, "} } ", NIL);
+ } else {
+ Printv(constructor, pname, " ", NIL);
+ }
+ }
+ ++pnum;
+ }
+ Printf(constructor, "} { \n");
+
+ // [BRE] 08/17/00 Added test to see if we are instantiating this object
+ // type, or, if this constructor is being called as part of the itcl
+ // inheritance hierarchy.
+ // In the former case, we need to call the C++ constructor, in the
+ // latter we don't, or we end up with two C++ objects.
+ // Check to see if we are instantiating a 'realname' or something
+ // derived from it.
+ //
+ Printv(constructor, " if { [string equal -nocase \"", realname, "\" \"[namespace tail [info class]]\" ] } {\n", NIL);
+
+ // Call to constructor wrapper and parent Ptr class
+ // [BRE] add -namespace/-prefix support
+
+ if (namespace_option) {
+ Printv(constructor, " ", realname, "Ptr::constructor [", ns_name, "::new_", realname, NIL);
+ } else {
+ Printv(constructor, " ", realname, "Ptr::constructor [new_", realname, NIL);
+ }
+
+ pnum = 0;
+ for (p = l; p; p = nextSibling(p)) {
+
+ SwigType *pt = Getattr(p, "type");
+ String *pn = Getattr(p, "name");
+ Clear(pname);
+
+ /* Only print an argument if not void */
+ if (Cmp(pt, "void") != 0) {
+ if (Len(pn) > 0) {
+ Printv(pname, pn, NIL);
+ } else {
+ Printf(pname, "p%d", pnum);
+ }
+ Printv(constructor, " $", pname, NIL);
+ }
+ ++pnum;
+ }
+
+ Printv(constructor, "]\n", " }\n", " } {\n", " set thisown 1\n", " }\n", NIL);
+ }
+ }
+
+ if (!have_constructor)
+ constructor_name = NewString(Getattr(n, "sym:name"));
+ have_constructor = 1;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * destructorHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int destructorHandler(Node *n) {
+ Language::destructorHandler(n);
+ have_destructor = 1;
+ destructor_action = Getattr(n, "wrap:action");
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * validIdentifier()
+ * ------------------------------------------------------------ */
+
+ virtual int validIdentifier(String *s) {
+ if (Strchr(s, ' '))
+ return 0;
+ return 1;
+ }
+
+ /* ------------------------------------------------------------
+ * usage_string()
+ * ------------------------------------------------------------ */
+
+ char *usage_string(char *iname, SwigType *, ParmList *l) {
+ static String *temp = 0;
+ Parm *p;
+ int i, numopt, pcount;
+
+ if (!temp)
+ temp = NewString("");
+ Clear(temp);
+ if (namespace_option) {
+ Printf(temp, "%s::%s ", ns_name, iname);
+ } else {
+ Printf(temp, "%s ", iname);
+ }
+ /* Now go through and print parameters */
+ i = 0;
+ pcount = emit_num_arguments(l);
+ numopt = pcount - emit_num_required(l);
+ for (p = l; p; p = nextSibling(p)) {
+
+ SwigType *pt = Getattr(p, "type");
+ String *pn = Getattr(p, "name");
+ /* Only print an argument if not ignored */
+ if (!checkAttribute(p, "tmap:in:numinputs", "0")) {
+ if (i >= (pcount - numopt))
+ Putc('?', temp);
+ if (Len(pn) > 0) {
+ Printf(temp, "%s", pn);
+ } else {
+ Printf(temp, "%s", SwigType_str(pt, 0));
+ }
+ if (i >= (pcount - numopt))
+ Putc('?', temp);
+ Putc(' ', temp);
+ i++;
+ }
+ }
+ return Char(temp);
+ }
+
+ String *runtimeCode() {
+ String *s = NewString("");
+ String *serrors = Swig_include_sys("tclerrors.swg");
+ if (!serrors) {
+ Printf(stderr, "*** Unable to open 'tclerrors.swg'\n");
+ } else {
+ Append(s, serrors);
+ Delete(serrors);
+ }
+ String *sapi = Swig_include_sys("tclapi.swg");
+ if (!sapi) {
+ Printf(stderr, "*** Unable to open 'tclapi.swg'\n");
+ } else {
+ Append(s, sapi);
+ Delete(sapi);
+ }
+ String *srun = Swig_include_sys("tclrun.swg");
+ if (!srun) {
+ Printf(stderr, "*** Unable to open 'tclrun.swg'\n");
+ } else {
+ Append(s, srun);
+ Delete(srun);
+ }
+
+ return s;
+ }
+
+ String *defaultExternalRuntimeFilename() {
+ return NewString("swigtclrun.h");
+ }
+};
+
+/* ----------------------------------------------------------------------
+ * swig_tcl() - Instantiate module
+ * ---------------------------------------------------------------------- */
+
+static Language *new_swig_tcl() {
+ return new TCL8();
+}
+extern "C" Language *swig_tcl(void) {
+ return new_swig_tcl();
+}
diff --git a/contrib/tools/swig/Source/Modules/typepass.cxx b/contrib/tools/swig/Source/Modules/typepass.cxx
new file mode 100644
index 00000000000..dc84cf94ae6
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/typepass.cxx
@@ -0,0 +1,1303 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * typepass.cxx
+ *
+ * This module builds all of the internal type information by collecting
+ * typedef declarations as well as registering classes, structures, and unions.
+ * This information is needed to correctly handle shadow classes and other
+ * advanced features. This phase of compilation is also used to perform
+ * type-expansion. All types are fully qualified with namespace prefixes
+ * and other information needed for compilation.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+
+struct normal_node {
+ Symtab *symtab;
+ Hash *typescope;
+ List *normallist;
+ normal_node *next;
+};
+
+static normal_node *patch_list = 0;
+
+/* Singleton class - all non-static methods in this class are private */
+class TypePass:private Dispatcher {
+ Node *inclass;
+ Node *module;
+ int importmode;
+ String *nsname;
+ String *nssymname;
+ Hash *classhash;
+ List *normalize;
+
+ TypePass() :
+ inclass(0),
+ module(0),
+ importmode(0),
+ nsname(0),
+ nssymname(0),
+ classhash(0),
+ normalize(0) {
+ }
+
+ /* Normalize a type. Replaces type with fully qualified version */
+ void normalize_type(SwigType *ty) {
+ SwigType *qty;
+ if (CPlusPlus) {
+ Replaceall(ty, "struct ", "");
+ Replaceall(ty, "union ", "");
+ Replaceall(ty, "class ", "");
+ }
+
+ qty = SwigType_typedef_qualified(ty);
+ /* Printf(stdout,"%s --> %s\n", ty, qty); */
+ Clear(ty);
+ Append(ty, qty);
+ Delete(qty);
+ }
+
+ /* Normalize a parameter list */
+
+ void normalize_parms(ParmList *p) {
+ while (p) {
+ SwigType *ty = Getattr(p, "type");
+ normalize_type(ty);
+ /* This is a check for a function type */
+ {
+ SwigType *qty = SwigType_typedef_resolve_all(ty);
+ if (SwigType_isfunction(qty)) {
+ SwigType_add_pointer(ty);
+ }
+ Delete(qty);
+ }
+
+ String *value = Getattr(p, "value");
+ if (value) {
+ Node *n = Swig_symbol_clookup(value, 0);
+ if (n) {
+ String *q = Swig_symbol_qualified(n);
+ if (q && Len(q)) {
+ String *vb = Swig_scopename_last(value);
+ Clear(value);
+ Printf(value, "%s::%s", SwigType_namestr(q), vb);
+ Delete(q);
+ }
+ }
+ }
+ if (value && SwigType_istemplate(value)) {
+ String *nv = SwigType_namestr(value);
+ Setattr(p, "value", nv);
+ }
+ p = nextSibling(p);
+ }
+ }
+
+ void normalize_later(ParmList *p) {
+ while (p) {
+ SwigType *ty = Getattr(p, "type");
+ Append(normalize, ty);
+ p = nextSibling(p);
+ }
+ }
+
+ /* Walk through entries in normalize list and patch them up */
+ void normalize_list() {
+ Hash *currentsym = Swig_symbol_current();
+
+ normal_node *nn = patch_list;
+ normal_node *np;
+ while (nn) {
+ Swig_symbol_setscope(nn->symtab);
+ SwigType_set_scope(nn->typescope);
+ Iterator t;
+ for (t = First(nn->normallist); t.item; t = Next(t)) {
+ normalize_type(t.item);
+ }
+ Delete(nn->normallist);
+ np = nn->next;
+ delete(nn);
+ nn = np;
+ }
+ Swig_symbol_setscope(currentsym);
+ }
+
+ /* generate C++ inheritance type-relationships */
+ void cplus_inherit_types_impl(Node *first, Node *cls, String *clsname, const char *bases, const char *baselist, int ispublic, String *cast = 0) {
+
+ if (first == cls)
+ return; /* The Marcelo check */
+ if (!cls)
+ cls = first;
+ List *alist = 0;
+ List *ilist = Getattr(cls, bases);
+ if (!ilist) {
+ List *nlist = Getattr(cls, baselist);
+ if (nlist) {
+ int len = Len(nlist);
+ int i;
+ for (i = 0; i < len; i++) {
+ Node *bcls = 0;
+ int clsforward = 0;
+ String *bname = Getitem(nlist, i);
+ String *sname = bname;
+ String *tname = 0;
+
+ /* Try to locate the base class. We look in the symbol table and we chase
+ typedef declarations to get to the base class if necessary */
+ Symtab *st = Getattr(cls, "sym:symtab");
+
+ if (SwigType_istemplate(bname)) {
+ tname = SwigType_typedef_resolve_all(bname);
+ sname = tname;
+ }
+ while (1) {
+ String *qsname = SwigType_typedef_qualified(sname);
+ bcls = Swig_symbol_clookup(qsname, st);
+ Delete(qsname);
+ if (bcls) {
+ if (Strcmp(nodeType(bcls), "class") != 0) {
+ /* Not a class. The symbol could be a typedef. */
+ if (checkAttribute(bcls, "storage", "typedef")) {
+ SwigType *decl = Getattr(bcls, "decl");
+ if (!decl || !(Len(decl))) {
+ sname = Getattr(bcls, "type");
+ st = Getattr(bcls, "sym:symtab");
+ if (SwigType_istemplate(sname)) {
+ if (tname)
+ Delete(tname);
+ tname = SwigType_typedef_resolve_all(sname);
+ sname = tname;
+ }
+ continue;
+ }
+ // A case when both outer and nested classes inherit from the same parent. Constructor may be found instead of the class itself.
+ } else if (GetFlag(cls, "nested") && checkAttribute(bcls, "nodeType", "constructor")) {
+ bcls = Getattr(bcls, "parentNode");
+ if (Getattr(bcls, "typepass:visit")) {
+ if (!Getattr(bcls, "feature:onlychildren")) {
+ if (!ilist)
+ ilist = alist = NewList();
+ Append(ilist, bcls);
+ } else {
+ if (!GetFlag(bcls, "feature:ignore")) {
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname));
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname));
+ }
+ }
+ }
+ break;
+ }
+ if (Strcmp(nodeType(bcls), "classforward") != 0) {
+ Swig_error(Getfile(bname), Getline(bname), "'%s' is not a valid base class.\n", SwigType_namestr(bname));
+ Swig_error(Getfile(bcls), Getline(bcls), "See definition of '%s'.\n", SwigType_namestr(bname));
+ } else {
+ Swig_warning(WARN_TYPE_INCOMPLETE, Getfile(bname), Getline(bname), "Base class '%s' is incomplete.\n", SwigType_namestr(bname));
+ Swig_warning(WARN_TYPE_INCOMPLETE, Getfile(bcls), Getline(bcls), "Only forward declaration '%s' was found.\n", SwigType_namestr(bname));
+ clsforward = 1;
+ }
+ bcls = 0;
+ } else {
+ if (Getattr(bcls, "typepass:visit")) {
+ if (!Getattr(bcls, "feature:onlychildren")) {
+ if (!ilist)
+ ilist = alist = NewList();
+ Append(ilist, bcls);
+ } else {
+ if (!GetFlag(bcls, "feature:ignore")) {
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname));
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname));
+ }
+ }
+ } else {
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' undefined.\n", SwigType_namestr(bname));
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "'%s' must be defined before it is used as a base class.\n", SwigType_namestr(bname));
+ }
+ }
+ }
+ break;
+ }
+
+ if (tname)
+ Delete(tname);
+ if (!bcls) {
+ if (!clsforward && !GetFlag(cls, "feature:ignore")) {
+ if (ispublic && !Getmeta(bname, "already_warned")) {
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Nothing known about base class '%s'. Ignored.\n", SwigType_namestr(bname));
+ if (Strchr(bname, '<')) {
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Maybe you forgot to instantiate '%s' using %%template.\n", SwigType_namestr(bname));
+ }
+ Setmeta(bname, "already_warned", "1");
+ }
+ }
+ SwigType_inherit(clsname, bname, cast, 0);
+ }
+ }
+ }
+ if (ilist) {
+ Setattr(cls, bases, ilist);
+ }
+ }
+ if (alist)
+ Delete(alist);
+
+ if (!ilist)
+ return;
+ int len = Len(ilist);
+ int i;
+ for (i = 0; i < len; i++) {
+ Node *n = Getitem(ilist, i);
+ String *bname = Getattr(n, "name");
+ Node *bclass = n; /* Getattr(n,"class"); */
+ Hash *scopes = Getattr(bclass, "typescope");
+ SwigType_inherit(clsname, bname, cast, 0);
+ if (ispublic && !GetFlag(bclass, "feature:ignore")) {
+ String *smartptr = Getattr(first, "feature:smartptr");
+ if (smartptr) {
+ SwigType *smart = Swig_cparse_smartptr(first);
+ if (smart) {
+ /* Record a (fake) inheritance relationship between smart pointer
+ and smart pointer to base class, so that smart pointer upcasts
+ are automatically generated. */
+ SwigType *bsmart = Copy(smart);
+
+ // TODO: SwigType_typedef_resolve_all on a String instead of SwigType is incorrect for templates
+ SwigType *rclsname = SwigType_typedef_resolve_all(clsname);
+ SwigType *rbname = SwigType_typedef_resolve_all(bname);
+ int replace_count = Replaceall(bsmart, rclsname, rbname);
+ if (replace_count == 0) {
+ // If no replacement made, it will be because rclsname is fully resolved, but the
+ // type in the smartptr feature used a typedef or not fully resolved name.
+ String *firstname = Getattr(first, "name");
+ Replaceall(bsmart, firstname, rbname);
+ }
+ // The code above currently creates a smartptr of the base class by substitution, replacing Derived
+ // with Base resulting in something like: 'smartptr< Derived >' from 'smartptr< Base >'. Instead
+ // the feature:smartptr should be used as it also contains 'smartptr< Base >' as specified by the user.
+ // A similar fix should also be done in upcastsCode in java.cxx, csharp.cxx and writeClassUpcast in d.cxx.
+ // Printf(stdout, "smartcomparison %s <=> %s\n", SwigType_namestr(bsmart), Getattr(bclass, "feature:smartptr"));
+
+ Delete(rclsname);
+ Delete(rbname);
+ String *smartnamestr = SwigType_namestr(smart);
+ String *bsmartnamestr = SwigType_namestr(bsmart);
+ /* construct casting code */
+ String *convcode = NewStringf("\n *newmemory = SWIG_CAST_NEW_MEMORY;\n return (void *) new %s(*(%s *)$from);\n", bsmartnamestr, smartnamestr);
+ Delete(bsmartnamestr);
+ Delete(smartnamestr);
+ /* setup inheritance relationship between smart pointer templates */
+ SwigType_inherit(smart, bsmart, 0, convcode);
+ if (!GetFlag(bclass, "feature:smartptr"))
+ Swig_warning(WARN_LANG_SMARTPTR_MISSING, Getfile(first), Getline(first), "Base class '%s' of '%s' is not similarly marked as a smart pointer.\n", SwigType_namestr(Getattr(bclass, "name")), SwigType_namestr(Getattr(first, "name")));
+ Delete(convcode);
+ Delete(bsmart);
+ }
+ Delete(smart);
+ } else {
+ if (GetFlag(bclass, "feature:smartptr"))
+ Swig_warning(WARN_LANG_SMARTPTR_MISSING, Getfile(first), Getline(first), "Derived class '%s' of '%s' is not similarly marked as a smart pointer.\n", SwigType_namestr(Getattr(first, "name")), SwigType_namestr(Getattr(bclass, "name")));
+ }
+ }
+ if (!importmode) {
+ String *btype = Copy(bname);
+ SwigType_add_pointer(btype);
+ SwigType_remember(btype);
+ Delete(btype);
+ }
+ if (scopes) {
+ SwigType_inherit_scope(scopes);
+ }
+ /* Set up inheritance in the symbol table */
+ Symtab *st = Getattr(cls, "symtab");
+ Symtab *bst = Getattr(bclass, "symtab");
+ if (st == bst) {
+ Swig_warning(WARN_PARSE_REC_INHERITANCE, Getfile(cls), Getline(cls), "Recursive scope inheritance of '%s'.\n", SwigType_namestr(Getattr(cls, "name")));
+ continue;
+ }
+ Symtab *s = Swig_symbol_current();
+ Swig_symbol_setscope(st);
+ Swig_symbol_inherit(bst);
+ Swig_symbol_setscope(s);
+
+ /* Recursively hit base classes */
+ String *namestr = SwigType_namestr(Getattr(bclass, "name"));
+ String *newcast = NewStringf("(%s *)%s", namestr, cast);
+ Delete(namestr);
+ cplus_inherit_types_impl(first, bclass, clsname, bases, baselist, ispublic, newcast);
+ Delete(newcast);
+ }
+ }
+
+ void append_list(List *lb, List *la) {
+ if (la && lb) {
+ for (Iterator bi = First(la); bi.item; bi = Next(bi)) {
+ Append(lb, bi.item);
+ }
+ }
+ }
+
+ void cplus_inherit_types(Node *first, Node *cls, String *clsname, String *cast = 0) {
+ cplus_inherit_types_impl(first, cls, clsname, "bases", "baselist", 1, cast);
+ cplus_inherit_types_impl(first, cls, clsname, "protectedbases", "protectedbaselist", 0, cast);
+ cplus_inherit_types_impl(first, cls, clsname, "privatebases", "privatebaselist", 0, cast);
+
+ if (!cls)
+ cls = first;
+
+ List *allbases = NewList();
+ append_list(allbases, Getattr(cls, "bases"));
+ append_list(allbases, Getattr(cls, "protectedbases"));
+ append_list(allbases, Getattr(cls, "privatebases"));
+ if (Len(allbases)) {
+ Setattr(cls, "allbases", allbases);
+ }
+ Delete(allbases);
+ }
+
+ /* ------------------------------------------------------------
+ * top()
+ * ------------------------------------------------------------ */
+
+ virtual int top(Node *n) {
+ importmode = 0;
+ module = Getattr(n, "module");
+ inclass = 0;
+ normalize = 0;
+ nsname = 0;
+ nssymname = 0;
+ classhash = Getattr(n, "classes");
+ emit_children(n);
+ normalize_list();
+ SwigType_set_scope(0);
+ return SWIG_OK;
+ }
+
+
+ /* ------------------------------------------------------------
+ * moduleDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int moduleDirective(Node *n) {
+ if (!module) {
+ module = n;
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * importDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int importDirective(Node *n) {
+ String *oldmodule = module;
+ int oldimport = importmode;
+ importmode = 1;
+ module = 0;
+ emit_children(n);
+ importmode = oldimport;
+ module = oldmodule;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * includeDirective()
+ * externDirective()
+ * extendDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int includeDirective(Node *n) {
+ return emit_children(n);
+ }
+ virtual int externDeclaration(Node *n) {
+ return emit_children(n);
+ }
+ virtual int extendDirective(Node *n) {
+ return emit_children(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int classDeclaration(Node *n) {
+ String *name = Getattr(n, "name");
+ String *tdname = Getattr(n, "tdname");
+ String *unnamed = Getattr(n, "unnamed");
+ String *storage = Getattr(n, "storage");
+ String *kind = Getattr(n, "kind");
+ save_value<Node*> oldinclass(inclass);
+ List *olist = normalize;
+ Symtab *symtab;
+ String *nname = 0;
+ String *fname = 0;
+ String *scopename = 0;
+ String *template_default_expanded = 0;
+
+ normalize = NewList();
+
+ if (name) {
+ if (SwigType_istemplate(name)) {
+ // We need to fully resolve the name and expand default template parameters to make templates work correctly */
+ Node *cn;
+ SwigType *resolved_name = SwigType_typedef_resolve_all(name);
+ SwigType *deftype_name = Swig_symbol_template_deftype(resolved_name, 0);
+ fname = Copy(resolved_name);
+ if (!Equal(resolved_name, deftype_name))
+ template_default_expanded = Copy(deftype_name);
+ if (!Equal(fname, name) && (cn = Swig_symbol_clookup_local(fname, 0))) {
+ if ((n == cn)
+ || (Strcmp(nodeType(cn), "template") == 0)
+ || (Getattr(cn, "feature:onlychildren") != 0)
+ || (Getattr(n, "feature:onlychildren") != 0)) {
+ Swig_symbol_cadd(fname, n);
+ if (template_default_expanded)
+ Swig_symbol_cadd(template_default_expanded, n);
+ SwigType_typedef_class(fname);
+ scopename = Copy(fname);
+ } else {
+ Swig_warning(WARN_TYPE_REDEFINED, Getfile(n), Getline(n), "Template '%s' was already wrapped,\n", SwigType_namestr(name));
+ Swig_warning(WARN_TYPE_REDEFINED, Getfile(cn), Getline(cn), "previous wrap of '%s'.\n", SwigType_namestr(Getattr(cn, "name")));
+ scopename = 0;
+ }
+ } else {
+ Swig_symbol_cadd(fname, n);
+ SwigType_typedef_class(fname);
+ scopename = Copy(fname);
+ }
+ Delete(deftype_name);
+ Delete(resolved_name);
+ } else {
+ if ((CPlusPlus) || (unnamed)) {
+ SwigType_typedef_class(name);
+ } else {
+ SwigType_typedef_class(NewStringf("%s %s", kind, name));
+ }
+ scopename = Copy(name);
+ }
+ } else {
+ scopename = 0;
+ }
+
+ Setattr(n, "typepass:visit", "1");
+
+ /* Need to set up a typedef if unnamed */
+ if (unnamed && tdname && (Cmp(storage, "typedef") == 0)) {
+ SwigType_typedef(unnamed, tdname);
+ }
+ // name of the outer class should already be patched to contain its outer classes names, but not to contain namespaces
+ // namespace name (if present) is added after processing child nodes
+ if (Getattr(n, "nested:outer") && name) {
+ String *outerName = Getattr(Getattr(n, "nested:outer"), "name");
+ name = NewStringf("%s::%s", outerName, name);
+ Setattr(n, "name", name);
+ if (tdname) {
+ tdname = NewStringf("%s::%s", outerName, tdname);
+ Setattr(n, "tdname", tdname);
+ }
+ }
+
+ if (nsname && name) {
+ nname = NewStringf("%s::%s", nsname, name);
+ String *tdname = Getattr(n, "tdname");
+ if (tdname) {
+ tdname = NewStringf("%s::%s", nsname, tdname);
+ Setattr(n, "tdname", tdname);
+ }
+ }
+ if (nssymname) {
+ if (GetFlag(n, "feature:nspace"))
+ Setattr(n, "sym:nspace", nssymname);
+ }
+ SwigType_new_scope(scopename);
+ SwigType_attach_symtab(Getattr(n, "symtab"));
+
+ /* Inherit type definitions into the class */
+ if (name && !(GetFlag(n, "nested") && !checkAttribute(n, "access", "public") &&
+ (GetFlag(n, "feature:flatnested") || Language::instance()->nestedClassesSupport() == Language::NCS_None))) {
+ cplus_inherit_types(n, 0, nname ? nname : (fname ? fname : name));
+ }
+
+ inclass = n;
+ symtab = Swig_symbol_setscope(Getattr(n, "symtab"));
+ emit_children(n);
+ Swig_symbol_setscope(symtab);
+
+ Hash *ts = SwigType_pop_scope();
+ Setattr(n, "typescope", ts);
+ Delete(ts);
+ Setattr(n, "module", module);
+
+ // When a fully qualified templated type with default parameters is used in the parsed code,
+ // the following additional symbols and scopes are needed for successful lookups
+ if (template_default_expanded) {
+ Swig_symbol_alias(template_default_expanded, Getattr(n, "symtab"));
+ SwigType_scope_alias(template_default_expanded, Getattr(n, "typescope"));
+ }
+
+ /* Normalize deferred types */
+ {
+ normal_node *nn = new normal_node();
+ nn->normallist = normalize;
+ nn->symtab = Getattr(n, "symtab");
+ nn->next = patch_list;
+ nn->typescope = Getattr(n, "typescope");
+ patch_list = nn;
+ }
+
+ normalize = olist;
+
+ /* If in a namespace, patch the class name */
+ if (nname) {
+ Setattr(n, "name", nname);
+ Delete(nname);
+ }
+ Delete(fname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * templateDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int templateDeclaration(Node *n) {
+ String *name = Getattr(n, "name");
+ String *ttype = Getattr(n, "templatetype");
+ if (Strcmp(ttype, "class") == 0) {
+ String *rname = SwigType_typedef_resolve_all(name);
+ SwigType_typedef_class(rname);
+ Delete(rname);
+ } else if (Strcmp(ttype, "classforward") == 0) {
+ String *rname = SwigType_typedef_resolve_all(name);
+ SwigType_typedef_class(rname);
+ Delete(rname);
+ /* SwigType_typedef_class(name); */
+ } else if (Strcmp(ttype, "cdecl") == 0) {
+ String *rname = SwigType_typedef_resolve_all(name);
+ SwigType_typedef_class(rname);
+ Delete(rname);
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * lambdaDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int lambdaDeclaration(Node *) {
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classforwardDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int classforwardDeclaration(Node *n) {
+
+ /* Can't do inside a C struct because it breaks C nested structure wrapping */
+ if ((!inclass) || (CPlusPlus)) {
+ String *name = Getattr(n, "name");
+ SwigType_typedef_class(name);
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * namespaceDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int namespaceDeclaration(Node *n) {
+ Symtab *symtab;
+ String *name = Getattr(n, "name");
+ String *alias = Getattr(n, "alias");
+ List *olist = normalize;
+ normalize = NewList();
+ if (alias) {
+ Typetab *ts = Getattr(n, "typescope");
+ if (!ts) {
+ /* Create an empty scope for the alias */
+ Node *ns = Getattr(n, "namespace");
+ SwigType_scope_alias(name, Getattr(ns, "typescope"));
+ ts = Getattr(ns, "typescope");
+ Setattr(n, "typescope", ts);
+ }
+ /* Namespace alias */
+ return SWIG_OK;
+ } else {
+ if (name) {
+ Node *nn = Swig_symbol_clookup(name, n);
+ Hash *ts = 0;
+ if (nn)
+ ts = Getattr(nn, "typescope");
+ if (!ts) {
+ SwigType_new_scope(name);
+ SwigType_attach_symtab(Getattr(n, "symtab"));
+ } else {
+ SwigType_set_scope(ts);
+ }
+ }
+ String *oldnsname = nsname;
+ String *oldnssymname = nssymname;
+ nsname = Swig_symbol_qualified(Getattr(n, "symtab"));
+ nssymname = Swig_symbol_qualified_language_scopename(Getattr(n, "symtab"));
+ symtab = Swig_symbol_setscope(Getattr(n, "symtab"));
+ emit_children(n);
+ Swig_symbol_setscope(symtab);
+
+ if (name) {
+ Hash *ts = SwigType_pop_scope();
+ Setattr(n, "typescope", ts);
+ Delete(ts);
+ }
+
+ /* Normalize deferred types */
+ {
+ normal_node *nn = new normal_node();
+ nn->normallist = normalize;
+ nn->symtab = Getattr(n, "symtab");
+ nn->next = patch_list;
+ nn->typescope = Getattr(n, "typescope");
+ patch_list = nn;
+ }
+ normalize = olist;
+
+ Delete(nssymname);
+ nssymname = oldnssymname;
+ Delete(nsname);
+ nsname = oldnsname;
+ return SWIG_OK;
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * cDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int cDeclaration(Node *n) {
+ if (NoExcept) {
+ Delattr(n, "throws");
+ }
+
+ /* Normalize types. */
+ SwigType *ty = Getattr(n, "type");
+ if (!ty) {
+ return SWIG_OK;
+ }
+ normalize_type(ty);
+ SwigType *decl = Getattr(n, "decl");
+ if (decl) {
+ normalize_type(decl);
+ }
+ normalize_parms(Getattr(n, "parms"));
+ normalize_parms(Getattr(n, "throws"));
+ if (GetFlag(n, "conversion_operator")) {
+ /* The call to the operator in the generated wrapper must be fully qualified in order to compile */
+ SwigType *name = Getattr(n, "name");
+ SwigType *qualifiedname = Swig_symbol_string_qualify(name, 0);
+ Clear(name);
+ Append(name, qualifiedname);
+ Delete(qualifiedname);
+ }
+
+ if (checkAttribute(n, "storage", "typedef")) {
+ String *name = Getattr(n, "name");
+ ty = Getattr(n, "type");
+ decl = Getattr(n, "decl");
+ SwigType *t = Copy(ty);
+ {
+ /* If the typename is qualified, make sure the scopename is fully qualified when making a typedef */
+ if (Swig_scopename_check(t) && strncmp(Char(t), "::", 2)) {
+ String *base, *prefix, *qprefix;
+ base = Swig_scopename_last(t);
+ prefix = Swig_scopename_prefix(t);
+ qprefix = SwigType_typedef_qualified(prefix);
+ Delete(t);
+ t = NewStringf("%s::%s", qprefix, base);
+ Delete(base);
+ Delete(prefix);
+ Delete(qprefix);
+ }
+ }
+ SwigType_push(t, decl);
+ if (CPlusPlus) {
+ Replaceall(t, "struct ", "");
+ Replaceall(t, "union ", "");
+ Replaceall(t, "class ", "");
+ }
+ SwigType_typedef(t, name);
+ }
+ /* If namespaces are active. We need to patch the name with a namespace prefix */
+ if (nsname && !inclass) {
+ String *name = Getattr(n, "name");
+ if (name) {
+ String *nname = NewStringf("%s::%s", nsname, name);
+ Setattr(n, "name", nname);
+ Delete(nname);
+ }
+ }
+ clean_overloaded(n);
+ return SWIG_OK;
+ }
+
+
+ /* ------------------------------------------------------------
+ * constructorDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int constructorDeclaration(Node *n) {
+ if (NoExcept) {
+ Delattr(n, "throws");
+ }
+
+ normalize_parms(Getattr(n, "parms"));
+ normalize_parms(Getattr(n, "throws"));
+
+ clean_overloaded(n);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * destructorDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int destructorDeclaration(Node *) {
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constantDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int constantDirective(Node *n) {
+ SwigType *ty = Getattr(n, "type");
+ if (ty) {
+ Setattr(n, "type", SwigType_typedef_qualified(ty));
+ }
+ return SWIG_OK;
+ }
+
+
+ /* ------------------------------------------------------------
+ * enumDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int enumDeclaration(Node *n) {
+ String *name = Getattr(n, "name");
+
+ if (name) {
+ String *scope = 0;
+
+ // Add a typedef to the type table so that we can use 'enum Name' as well as just 'Name'
+ if (nsname || inclass) {
+
+ // But first correct the name and tdname to contain the fully qualified scopename
+ if (nsname && inclass) {
+ scope = NewStringf("%s::%s", nsname, Getattr(inclass, "name"));
+ } else if (nsname) {
+ scope = NewStringf("%s", nsname);
+ } else if (inclass) {
+ scope = NewStringf("%s", Getattr(inclass, "name"));
+ }
+
+ String *nname = NewStringf("%s::%s", scope, name);
+ Setattr(n, "name", nname);
+
+ String *tdname = Getattr(n, "tdname");
+ if (tdname) {
+ tdname = NewStringf("%s::%s", scope, tdname);
+ Setattr(n, "tdname", tdname);
+ }
+
+ SwigType *t = NewStringf("enum %s", nname);
+ SwigType_typedef(t, name);
+ } else {
+ SwigType *t = NewStringf("enum %s", name);
+ SwigType_typedef(t, name);
+ }
+ Delete(scope);
+ }
+
+ String *tdname = Getattr(n, "tdname");
+ String *unnamed = Getattr(n, "unnamed");
+ String *storage = Getattr(n, "storage");
+
+ // Construct enumtype - for declaring an enum of this type with SwigType_ltype() etc
+ String *enumtype = 0;
+ if (unnamed && tdname && (Cmp(storage, "typedef") == 0)) {
+ enumtype = Copy(Getattr(n, "tdname"));
+ } else if (name) {
+ enumtype = NewStringf("%s%s", CPlusPlus ? "" : "enum ", Getattr(n, "name"));
+ } else {
+ // anonymous enums
+ enumtype = Copy(Getattr(n, "type"));
+ }
+ Setattr(n, "enumtype", enumtype);
+
+ if (nssymname) {
+ if (GetFlag(n, "feature:nspace"))
+ Setattr(n, "sym:nspace", nssymname);
+ }
+
+ // This block of code is for dealing with %ignore on an enum item where the target language
+ // attempts to use the C enum value in the target language itself and expects the previous enum value
+ // to be one more than the previous value... the previous enum item might not exist if it is ignored!
+ // - It sets the first non-ignored enum item with the "firstenumitem" attribute.
+ // - It adds an enumvalue attribute if the previous enum item is ignored
+ {
+ Node *c;
+ int count = 0;
+ String *previous = 0;
+ bool previous_ignored = false;
+ bool firstenumitem = false;
+ for (c = firstChild(n); c; c = nextSibling(c)) {
+ assert(strcmp(Char(nodeType(c)), "enumitem") == 0);
+
+ bool reset;
+ String *enumvalue = Getattr(c, "enumvalue");
+ if (GetFlag(c, "feature:ignore") || !Getattr(c, "sym:name")) {
+ reset = enumvalue ? true : false;
+ previous_ignored = true;
+ } else {
+ if (!enumvalue && previous_ignored) {
+ if (previous)
+ Setattr(c, "enumvalue", NewStringf("(%s) + %d", previous, count+1));
+ else
+ Setattr(c, "enumvalue", NewStringf("%d", count));
+ SetFlag(c, "virtenumvalue"); // identify enumvalue as virtual, ie not from the parsed source
+ }
+ if (!firstenumitem) {
+ SetFlag(c, "firstenumitem");
+ firstenumitem = true;
+ }
+ reset = true;
+ previous_ignored = false;
+ }
+ if (reset) {
+ previous = enumvalue ? enumvalue : Getattr(c, "name");
+ count = 0;
+ } else {
+ count++;
+ }
+ }
+ }
+
+ emit_children(n);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * enumvalueDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int enumvalueDeclaration(Node *n) {
+ String *name = Getattr(n, "name");
+ String *value = Getattr(n, "value");
+ String *scopedenum = Getattr(parentNode(n), "scopedenum");
+ if (!value)
+ value = name;
+ if (Strcmp(value, name) == 0) {
+ String *new_value;
+ if ((nsname || inclass || scopedenum) && cparse_cplusplus) {
+ new_value = NewStringf("%s::%s", SwigType_namestr(Swig_symbol_qualified(n)), value);
+ } else {
+ new_value = NewString(value);
+ }
+ if ((nsname || inclass || scopedenum) && !cparse_cplusplus) {
+ String *cppvalue = NewStringf("%s::%s", SwigType_namestr(Swig_symbol_qualified(n)), value);
+ Setattr(n, "cppvalue", cppvalue); /* for target languages that always generate C++ code even when wrapping C code */
+ }
+ Setattr(n, "value", new_value);
+ Delete(new_value);
+ }
+ Node *next = nextSibling(n);
+
+ // Make up an enumvalue if one was not specified in the parsed code (not designed to be used on enum items and %ignore - enumvalue will be set instead)
+ if (!GetFlag(n, "feature:ignore")) {
+ if (Getattr(n, "_last") && !Getattr(n, "enumvalue")) { // Only the first enum item has _last set (Note: first non-ignored enum item has firstenumitem set)
+ Setattr(n, "enumvalueex", "0");
+ }
+ if (next && !Getattr(next, "enumvalue")) {
+ Setattr(next, "enumvalueex", NewStringf("%s + 1", Getattr(n, "sym:name")));
+ }
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * enumforwardDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int enumforwardDeclaration(Node *n) {
+
+ // Use enumDeclaration() to do all the hard work.
+ // Note that no children can be emitted in a forward declaration as there aren't any.
+ int result = enumDeclaration(n);
+ if (result == SWIG_OK) {
+ // Detect when the real enum matching the forward enum declaration has not been parsed/declared
+ SwigType *ty = SwigType_typedef_resolve_all(Getattr(n, "type"));
+ Replaceall(ty, "enum ", "");
+ Node *nn = Swig_symbol_clookup(ty, 0);
+
+ String *nodetype = nn ? nodeType(nn) : 0;
+ if (nodetype) {
+ if (Equal(nodetype, "enumforward")) {
+ SetFlag(nn, "enumMissing");
+ } // if a real enum was declared this would be an "enum" node type
+ }
+ Delete(ty);
+ }
+ return result;
+ }
+
+#ifdef DEBUG_OVERLOADED
+ static void show_overloaded(Node *n) {
+ Node *c = Getattr(n, "sym:overloaded");
+ Node *checkoverloaded = c;
+ Printf(stdout, "-------------------- overloaded start %s sym:overloaded():%p -------------------------------\n", Getattr(n, "name"), c);
+ while (c) {
+ if (Getattr(c, "error")) {
+ c = Getattr(c, "sym:nextSibling");
+ continue;
+ }
+ if (Getattr(c, "sym:overloaded") != checkoverloaded) {
+ Printf(stdout, "sym:overloaded error c:%p checkoverloaded:%p\n", c, checkoverloaded);
+ Swig_print_node(c);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ String *decl = Strcmp(nodeType(c), "using") == 0 ? NewString("------") : Getattr(c, "decl");
+ Printf(stdout, " show_overloaded %s::%s(%s) [%s] nodeType:%s\n", parentNode(c) ? Getattr(parentNode(c), "name") : "NOPARENT", Getattr(c, "name"), decl, Getattr(c, "sym:overname"), nodeType(c));
+ if (!Getattr(c, "sym:overloaded")) {
+ Printf(stdout, "sym:overloaded error.....%p\n", c);
+ Swig_print_node(c);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ c = Getattr(c, "sym:nextSibling");
+ }
+ Printf(stdout, "-------------------- overloaded end %s -------------------------------\n", Getattr(n, "name"));
+ }
+#endif
+
+ /* ------------------------------------------------------------
+ * usingDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int usingDeclaration(Node *n) {
+ if (Getattr(n, "namespace")) {
+ /* using namespace id */
+
+ /* For a namespace import. We set up inheritance in the type system */
+ Node *ns = Getattr(n, "node");
+ if (ns) {
+ Typetab *ts = Getattr(ns, "typescope");
+ if (ts) {
+ SwigType_using_scope(ts);
+ }
+ }
+ return SWIG_OK;
+ } else {
+ Node *ns;
+ /* using id */
+ Symtab *stab = Getattr(n, "sym:symtab");
+ if (stab) {
+ String *uname = Getattr(n, "uname");
+ ns = Swig_symbol_clookup(uname, stab);
+ if (!ns && SwigType_istemplate(uname)) {
+ String *tmp = Swig_symbol_template_deftype(uname, 0);
+ if (!Equal(tmp, uname)) {
+ ns = Swig_symbol_clookup(tmp, stab);
+ }
+ Delete(tmp);
+ }
+ } else {
+ ns = 0;
+ }
+ if (!ns) {
+ if (is_public(n)) {
+ Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(n), Getline(n), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(n, "uname")));
+ }
+ } else {
+ /* Only a single symbol is being used. There are only a few symbols that
+ we actually care about. These are typedef, class declarations, and enum */
+ String *ntype = nodeType(ns);
+ if (Strcmp(ntype, "cdecl") == 0) {
+ if (checkAttribute(ns, "storage", "typedef")) {
+ /* A typedef declaration */
+ String *uname = Getattr(n, "uname");
+ SwigType_typedef_using(uname);
+ } else {
+ /* A normal C declaration. */
+ if ((inclass) && (!GetFlag(n, "feature:ignore")) && (Getattr(n, "sym:name"))) {
+ Node *c = ns;
+ Node *unodes = 0, *last_unodes = 0;
+ int ccount = 0;
+ String *symname = Getattr(n, "sym:name");
+ while (c) {
+ if (Strcmp(nodeType(c), "cdecl") == 0) {
+ if (!(Swig_storage_isstatic(c)
+ || checkAttribute(c, "storage", "typedef")
+ || checkAttribute(c, "storage", "friend")
+ || (Getattr(c, "feature:extend") && !Getattr(c, "code"))
+ || GetFlag(c, "feature:ignore"))) {
+
+ /* Don't generate a method if the method is overridden in this class,
+ * for example don't generate another m(bool) should there be a Base::m(bool) :
+ * struct Derived : Base {
+ * void m(bool);
+ * using Base::m;
+ * };
+ */
+ String *csymname = Getattr(c, "sym:name");
+ if (!csymname || (Strcmp(csymname, symname) == 0)) {
+ {
+ String *decl = Getattr(c, "decl");
+ Node *over = Getattr(n, "sym:overloaded");
+ int match = 0;
+ while (over) {
+ String *odecl = Getattr(over, "decl");
+ if (Cmp(decl, odecl) == 0) {
+ match = 1;
+ break;
+ }
+ over = Getattr(over, "sym:nextSibling");
+ }
+ if (match) {
+ c = Getattr(c, "csym:nextSibling");
+ continue;
+ }
+ }
+ Node *nn = copyNode(c);
+ Delattr(nn, "access"); // access might be different from the method in the base class
+ Setattr(nn, "access", Getattr(n, "access"));
+ if (!Getattr(nn, "sym:name"))
+ Setattr(nn, "sym:name", symname);
+
+ if (!GetFlag(nn, "feature:ignore")) {
+ ParmList *parms = CopyParmList(Getattr(c, "parms"));
+ int is_pointer = SwigType_ispointer_return(Getattr(nn, "decl"));
+ int is_void = checkAttribute(nn, "type", "void") && !is_pointer;
+ Setattr(nn, "parms", parms);
+ Delete(parms);
+ if (Getattr(n, "feature:extend")) {
+ String *ucode = is_void ? NewStringf("{ self->%s(", Getattr(n, "uname")) : NewStringf("{ return self->%s(", Getattr(n, "uname"));
+
+ for (ParmList *p = parms; p;) {
+ Append(ucode, Getattr(p, "name"));
+ p = nextSibling(p);
+ if (p)
+ Append(ucode, ",");
+ }
+ Append(ucode, "); }");
+ Setattr(nn, "code", ucode);
+ Delete(ucode);
+ }
+ ParmList *throw_parm_list = Getattr(c, "throws");
+ if (throw_parm_list)
+ Setattr(nn, "throws", CopyParmList(throw_parm_list));
+ ccount++;
+ if (!last_unodes) {
+ last_unodes = nn;
+ unodes = nn;
+ } else {
+ Setattr(nn, "previousSibling", last_unodes);
+ Setattr(last_unodes, "nextSibling", nn);
+ Setattr(nn, "sym:previousSibling", last_unodes);
+ Setattr(last_unodes, "sym:nextSibling", nn);
+ Setattr(nn, "sym:overloaded", unodes);
+ Setattr(unodes, "sym:overloaded", unodes);
+ last_unodes = nn;
+ }
+ } else {
+ Delete(nn);
+ }
+ }
+ }
+ }
+ c = Getattr(c, "csym:nextSibling");
+ }
+ if (unodes) {
+ set_firstChild(n, unodes);
+ if (ccount > 1) {
+ if (!Getattr(n, "sym:overloaded")) {
+ Setattr(n, "sym:overloaded", n);
+ Setattr(n, "sym:overname", "_SWIG_0");
+ }
+ }
+ }
+
+ /* Hack the parse tree symbol table for overloaded methods. Replace the "using" node with the
+ * list of overloaded methods we have just added in as child nodes to the "using" node.
+ * The node will still exist, it is just the symbol table linked list of overloaded methods
+ * which is hacked. */
+ if (Getattr(n, "sym:overloaded")) {
+ int cnt = 0;
+#ifdef DEBUG_OVERLOADED
+ Node *debugnode = n;
+ show_overloaded(n);
+#endif
+ if (!firstChild(n)) {
+ // Remove from overloaded list ('using' node does not actually end up adding in any methods)
+ Node *ps = Getattr(n, "sym:previousSibling");
+ Node *ns = Getattr(n, "sym:nextSibling");
+ if (ps) {
+ Setattr(ps, "sym:nextSibling", ns);
+ }
+ if (ns) {
+ Setattr(ns, "sym:previousSibling", ps);
+ }
+ } else {
+ // The 'using' node results in methods being added in - slot in the these methods here
+ Node *ps = Getattr(n, "sym:previousSibling");
+ Node *ns = Getattr(n, "sym:nextSibling");
+ Node *fc = firstChild(n);
+ Node *pp = fc;
+
+ Node *firstoverloaded = Getattr(n, "sym:overloaded");
+ if (firstoverloaded == n) {
+ // This 'using' node we are cutting out was the first node in the overloaded list.
+ // Change the first node in the list to its first sibling
+ Delattr(firstoverloaded, "sym:overloaded");
+ Node *nnn = Getattr(firstoverloaded, "sym:nextSibling");
+ firstoverloaded = fc;
+ while (nnn) {
+ Setattr(nnn, "sym:overloaded", firstoverloaded);
+ nnn = Getattr(nnn, "sym:nextSibling");
+ }
+ }
+ while (pp) {
+ Node *ppn = Getattr(pp, "sym:nextSibling");
+ Setattr(pp, "sym:overloaded", firstoverloaded);
+ Setattr(pp, "sym:overname", NewStringf("%s_%d", Getattr(n, "sym:overname"), cnt++));
+ if (ppn)
+ pp = ppn;
+ else
+ break;
+ }
+ if (ps) {
+ Setattr(ps, "sym:nextSibling", fc);
+ Setattr(fc, "sym:previousSibling", ps);
+ }
+ if (ns) {
+ Setattr(ns, "sym:previousSibling", pp);
+ Setattr(pp, "sym:nextSibling", ns);
+ }
+#ifdef DEBUG_OVERLOADED
+ debugnode = firstoverloaded;
+#endif
+ }
+ Delattr(n, "sym:previousSibling");
+ Delattr(n, "sym:nextSibling");
+ Delattr(n, "sym:overloaded");
+ Delattr(n, "sym:overname");
+#ifdef DEBUG_OVERLOADED
+ show_overloaded(debugnode);
+#endif
+ clean_overloaded(n); // Needed?
+ }
+ }
+ }
+ } else if ((Strcmp(ntype, "class") == 0) || ((Strcmp(ntype, "classforward") == 0))) {
+ /* We install the using class name as kind of a typedef back to the original class */
+ String *uname = Getattr(n, "uname");
+ /* Import into current type scope */
+ SwigType_typedef_using(uname);
+ } else if (Strcmp(ntype, "enum") == 0) {
+ SwigType_typedef_using(Getattr(n, "uname"));
+ } else if (Strcmp(ntype, "template") == 0) {
+ SwigType_typedef_using(Getattr(n, "uname"));
+ }
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * typemapDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int typemapDirective(Node *n) {
+ if (inclass || nsname) {
+ Node *items = firstChild(n);
+ while (items) {
+ Parm *pattern = Getattr(items, "pattern");
+ Parm *parms = Getattr(items, "parms");
+ normalize_later(pattern);
+ normalize_later(parms);
+ items = nextSibling(items);
+ }
+ }
+ return SWIG_OK;
+ }
+
+
+ /* ------------------------------------------------------------
+ * typemapcopyDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int typemapcopyDirective(Node *n) {
+ if (inclass || nsname) {
+ Node *items = firstChild(n);
+ ParmList *pattern = Getattr(n, "pattern");
+ normalize_later(pattern);
+ while (items) {
+ ParmList *npattern = Getattr(items, "pattern");
+ normalize_later(npattern);
+ items = nextSibling(items);
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * applyDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int applyDirective(Node *n) {
+ if (inclass || nsname) {
+ ParmList *pattern = Getattr(n, "pattern");
+ normalize_later(pattern);
+ Node *items = firstChild(n);
+ while (items) {
+ Parm *apattern = Getattr(items, "pattern");
+ normalize_later(apattern);
+ items = nextSibling(items);
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * clearDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int clearDirective(Node *n) {
+ if (inclass || nsname) {
+ Node *p;
+ for (p = firstChild(n); p; p = nextSibling(p)) {
+ ParmList *pattern = Getattr(p, "pattern");
+ normalize_later(pattern);
+ }
+ }
+ return SWIG_OK;
+ }
+
+public:
+ static void pass(Node *n) {
+ TypePass t;
+ t.top(n);
+ }
+};
+
+void Swig_process_types(Node *n) {
+ if (!n)
+ return;
+ TypePass::pass(n);
+}
+
diff --git a/contrib/tools/swig/Source/Modules/utils.cxx b/contrib/tools/swig/Source/Modules/utils.cxx
new file mode 100644
index 00000000000..2964ed3a66a
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/utils.cxx
@@ -0,0 +1,218 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * utils.cxx
+ *
+ * Various utility functions.
+ * ----------------------------------------------------------------------------- */
+
+#include <swigmod.h>
+
+int is_public(Node *n) {
+ String *access = Getattr(n, "access");
+ return !access || !Cmp(access, "public");
+}
+
+int is_private(Node *n) {
+ String *access = Getattr(n, "access");
+ return access && !Cmp(access, "private");
+}
+
+int is_protected(Node *n) {
+ String *access = Getattr(n, "access");
+ return access && !Cmp(access, "protected");
+}
+
+static int is_member_director_helper(Node *parentnode, Node *member) {
+ int parent_nodirector = GetFlag(parentnode, "feature:nodirector");
+ if (parent_nodirector)
+ return 0;
+ int parent_director = Swig_director_mode() && GetFlag(parentnode, "feature:director");
+ int cdecl_director = parent_director || GetFlag(member, "feature:director");
+ int cdecl_nodirector = GetFlag(member, "feature:nodirector");
+ return cdecl_director && !cdecl_nodirector && !GetFlag(member, "feature:extend");
+}
+
+int is_member_director(Node *parentnode, Node *member) {
+ if (parentnode && checkAttribute(member, "storage", "virtual")) {
+ return is_member_director_helper(parentnode, member);
+ } else {
+ return 0;
+ }
+}
+
+int is_member_director(Node *member) {
+ return is_member_director(Getattr(member, "parentNode"), member);
+}
+
+// Identifies the additional protected members that are generated when the allprotected option is used.
+// This does not include protected virtual methods as they are turned on with the dirprot option.
+int is_non_virtual_protected_access(Node *n) {
+ int result = 0;
+ if (Swig_director_mode() && Swig_director_protected_mode() && Swig_all_protected_mode() && is_protected(n) && !checkAttribute(n, "storage", "virtual")) {
+ Node *parentNode = Getattr(n, "parentNode");
+ // When vtable is empty, the director class does not get emitted, so a check for an empty vtable should be done.
+ // However, vtable is set in Language and so is not yet set when methods in Typepass call clean_overloaded()
+ // which calls is_non_virtual_protected_access. So commented out below.
+ // Moving the director vtable creation into Typepass should solve this problem.
+ if (is_member_director_helper(parentNode, n) /* && Getattr(parentNode, "vtable")*/)
+ result = 1;
+ }
+ return result;
+}
+
+/* Clean overloaded list. Removes templates, ignored, and errors */
+
+void clean_overloaded(Node *n) {
+ Node *nn = Getattr(n, "sym:overloaded");
+ Node *first = 0;
+ while (nn) {
+ String *ntype = nodeType(nn);
+ if ((GetFlag(nn, "feature:ignore")) ||
+ (Getattr(nn, "error")) ||
+ (Strcmp(ntype, "template") == 0) ||
+ ((Strcmp(ntype, "cdecl") == 0) && is_protected(nn) && !is_member_director(nn) && !is_non_virtual_protected_access(n))) {
+ /* Remove from overloaded list */
+ Node *ps = Getattr(nn, "sym:previousSibling");
+ Node *ns = Getattr(nn, "sym:nextSibling");
+ if (ps) {
+ Setattr(ps, "sym:nextSibling", ns);
+ }
+ if (ns) {
+ Setattr(ns, "sym:previousSibling", ps);
+ }
+ Delattr(nn, "sym:previousSibling");
+ Delattr(nn, "sym:nextSibling");
+ Delattr(nn, "sym:overloaded");
+ nn = ns;
+ continue;
+ } else {
+ if (!first)
+ first = nn;
+ Setattr(nn, "sym:overloaded", first);
+ }
+ nn = Getattr(nn, "sym:nextSibling");
+ }
+ if (!first || (first && !Getattr(first, "sym:nextSibling"))) {
+ if (Getattr(n, "sym:overloaded"))
+ Delattr(n, "sym:overloaded");
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_set_max_hash_expand()
+ *
+ * Controls how many Hash objects are displayed when displaying nested Hash objects.
+ * Makes DohSetMaxHashExpand an externally callable function (for debugger).
+ * ----------------------------------------------------------------------------- */
+
+void Swig_set_max_hash_expand(int count) {
+ SetMaxHashExpand(count);
+}
+
+extern "C" {
+
+/* -----------------------------------------------------------------------------
+ * Swig_get_max_hash_expand()
+ *
+ * Returns how many Hash objects are displayed when displaying nested Hash objects.
+ * Makes DohGetMaxHashExpand an externally callable function (for debugger).
+ * ----------------------------------------------------------------------------- */
+
+int Swig_get_max_hash_expand() {
+ return GetMaxHashExpand();
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_to_doh_string()
+ *
+ * DOH version of Swig_to_string()
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_to_doh_string(DOH *object, int count) {
+ int old_count = Swig_get_max_hash_expand();
+ if (count >= 0)
+ Swig_set_max_hash_expand(count);
+
+ String *debug_string = object ? NewStringf("%s", object) : NewString("NULL");
+
+ Swig_set_max_hash_expand(old_count);
+ return debug_string;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_to_doh_string_with_location()
+ *
+ * DOH version of Swig_to_string_with_location()
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_to_doh_string_with_location(DOH *object, int count) {
+ int old_count = Swig_get_max_hash_expand();
+ if (count >= 0)
+ Swig_set_max_hash_expand(count);
+
+ String *debug_string = Swig_stringify_with_location(object);
+
+ Swig_set_max_hash_expand(old_count);
+ return debug_string;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_to_string()
+ *
+ * Swig debug - return C string representation of any DOH type.
+ * Nested Hash types expand count is value of Swig_get_max_hash_expand when count<0
+ * Note: leaks memory.
+ * ----------------------------------------------------------------------------- */
+
+const char *Swig_to_string(DOH *object, int count) {
+ return Char(Swig_to_doh_string(object, count));
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_to_string_with_location()
+ *
+ * Swig debug - return C string representation of any DOH type, within [] brackets
+ * for Hash and List types, prefixed by line and file information.
+ * Nested Hash types expand count is value of Swig_get_max_hash_expand when count<0
+ * Note: leaks memory.
+ * ----------------------------------------------------------------------------- */
+
+const char *Swig_to_string_with_location(DOH *object, int count) {
+ return Char(Swig_to_doh_string_with_location(object, count));
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_print()
+ *
+ * Swig debug - display string representation of any DOH type.
+ * Nested Hash types expand count is value of Swig_get_max_hash_expand when count<0
+ * ----------------------------------------------------------------------------- */
+
+void Swig_print(DOH *object, int count) {
+ String *output = Swig_to_doh_string(object, count);
+ Printf(stdout, "%s\n", output);
+ Delete(output);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_to_string_with_location()
+ *
+ * Swig debug - display string representation of any DOH type, within [] brackets
+ * for Hash and List types, prefixed by line and file information.
+ * Nested Hash types expand count is value of Swig_get_max_hash_expand when count<0
+ * ----------------------------------------------------------------------------- */
+
+void Swig_print_with_location(DOH *object, int count) {
+ String *output = Swig_to_doh_string_with_location(object, count);
+ Printf(stdout, "%s\n", output);
+ Delete(output);
+}
+
+} // extern "C"
+
diff --git a/contrib/tools/swig/Source/Modules/xml.cxx b/contrib/tools/swig/Source/Modules/xml.cxx
new file mode 100644
index 00000000000..5f090561a89
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/xml.cxx
@@ -0,0 +1,326 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * xml.cxx
+ *
+ * An Xml parse tree generator.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+
+static const char *usage = "\
+XML Options (available with -xml)\n\
+ -xmllang <lang> - Typedef language\n\
+ -xmllite - More lightweight version of XML\n\
+ ------\n\
+ deprecated (use -o): -xml <output.xml> - Use <output.xml> as output file (extension .xml mandatory)\n";
+
+static File *out = 0;
+static int xmllite = 0;
+
+
+class XML:public Language {
+public:
+
+ int indent_level;
+ long id;
+
+ XML() :indent_level(0) , id(0) {
+ }
+
+ virtual ~ XML() {
+ }
+
+ virtual void main(int argc, char *argv[]) {
+ SWIG_typemap_lang("xml");
+ for (int iX = 0; iX < argc; iX++) {
+ if (strcmp(argv[iX], "-xml") == 0) {
+ char *extension = 0;
+ if (iX + 1 >= argc)
+ continue;
+ extension = argv[iX + 1] + strlen(argv[iX + 1]) - 4;
+ if (strcmp(extension, ".xml"))
+ continue;
+ iX++;
+ Swig_mark_arg(iX);
+ String *outfile = NewString(argv[iX]);
+ out = NewFile(outfile, "w", SWIG_output_files());
+ if (!out) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ continue;
+ }
+ if (strcmp(argv[iX], "-xmllang") == 0) {
+ Swig_mark_arg(iX);
+ iX++;
+ SWIG_typemap_lang(argv[iX]);
+ Swig_mark_arg(iX);
+ continue;
+ }
+ if (strcmp(argv[iX], "-help") == 0) {
+ fputs(usage, stdout);
+ }
+ if (strcmp(argv[iX], "-xmllite") == 0) {
+ Swig_mark_arg(iX);
+ xmllite = 1;
+ }
+ }
+
+ // Add a symbol to the parser for conditional compilation
+ Preprocessor_define("SWIGXML 1", 0);
+ }
+
+ /* Top of the parse tree */
+
+ virtual int top(Node *n) {
+ if (out == 0) {
+ String *outfile = Getattr(n, "outfile");
+ String *ext = Swig_file_extension(outfile);
+ // If there's an extension, ext will include the ".".
+ Delslice(outfile, Len(outfile) - Len(ext), DOH_END);
+ Delete(ext);
+ Append(outfile, ".xml");
+ out = NewFile(outfile, "w", SWIG_output_files());
+ if (!out) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+ Printf(out, "<?xml version=\"1.0\" ?> \n");
+ Xml_print_tree(n);
+ return SWIG_OK;
+ }
+
+ void print_indent(int l) {
+ int i;
+ for (i = 0; i < indent_level; i++) {
+ Printf(out, " ");
+ }
+ if (l) {
+ Printf(out, " ");
+ }
+ }
+
+ void Xml_print_tree(DOH *obj) {
+ while (obj) {
+ Xml_print_node(obj);
+ obj = nextSibling(obj);
+ }
+ }
+
+ void Xml_print_attributes(Node *obj) {
+ String *k;
+ indent_level += 4;
+ print_indent(0);
+ Printf(out, "<attributelist id=\"%ld\" addr=\"%p\" >\n", ++id, obj);
+ indent_level += 4;
+ Iterator ki;
+ ki = First(obj);
+ while (ki.key) {
+ k = ki.key;
+ if ((Cmp(k, "nodeType") == 0)
+ || (Cmp(k, "firstChild") == 0)
+ || (Cmp(k, "lastChild") == 0)
+ || (Cmp(k, "parentNode") == 0)
+ || (Cmp(k, "nextSibling") == 0)
+ || (Cmp(k, "previousSibling") == 0)
+ || (*(Char(k)) == '$')) {
+ /* Do nothing */
+ } else if (Cmp(k, "module") == 0) {
+ Xml_print_module(Getattr(obj, k));
+ } else if (Cmp(k, "baselist") == 0) {
+ Xml_print_baselist(Getattr(obj, k));
+ } else if (!xmllite && Cmp(k, "typescope") == 0) {
+ Xml_print_typescope(Getattr(obj, k));
+ } else if (!xmllite && Cmp(k, "typetab") == 0) {
+ Xml_print_typetab(Getattr(obj, k));
+ } else if (Cmp(k, "kwargs") == 0) {
+ Xml_print_kwargs(Getattr(obj, k));
+ } else if (Cmp(k, "parms") == 0 || Cmp(k, "pattern") == 0) {
+ Xml_print_parmlist(Getattr(obj, k));
+ } else if (Cmp(k, "catchlist") == 0 || Cmp(k, "templateparms") == 0) {
+ Xml_print_parmlist(Getattr(obj, k), Char(k));
+ } else {
+ DOH *o;
+ print_indent(0);
+ if (DohIsString(Getattr(obj, k))) {
+ String *ck = NewString(k);
+ o = Str(Getattr(obj, k));
+ Replaceall(ck, ":", "_");
+ Replaceall(ck, "<", "&lt;");
+ /* Do first to avoid aliasing errors. */
+ Replaceall(o, "&", "&amp;");
+ Replaceall(o, "<", "&lt;");
+ Replaceall(o, "\"", "&quot;");
+ Replaceall(o, "\\", "\\\\");
+ Replaceall(o, "\n", "&#10;");
+ Printf(out, "<attribute name=\"%s\" value=\"%s\" id=\"%ld\" addr=\"%p\" />\n", ck, o, ++id, o);
+ Delete(o);
+ Delete(ck);
+ } else {
+ o = Getattr(obj, k);
+ String *ck = NewString(k);
+ Replaceall(ck, ":", "_");
+ Printf(out, "<attribute name=\"%s\" value=\"%p\" id=\"%ld\" addr=\"%p\" />\n", ck, o, ++id, o);
+ Delete(ck);
+ }
+ }
+ ki = Next(ki);
+ }
+ indent_level -= 4;
+ print_indent(0);
+ Printf(out, "</attributelist >\n");
+ indent_level -= 4;
+ }
+
+ void Xml_print_node(Node *obj) {
+ Node *cobj;
+
+ print_indent(0);
+ Printf(out, "<%s id=\"%ld\" addr=\"%p\" >\n", nodeType(obj), ++id, obj);
+ Xml_print_attributes(obj);
+ cobj = firstChild(obj);
+ if (cobj) {
+ indent_level += 4;
+ Printf(out, "\n");
+ Xml_print_tree(cobj);
+ indent_level -= 4;
+ } else {
+ print_indent(1);
+ Printf(out, "\n");
+ }
+ print_indent(0);
+ Printf(out, "</%s >\n", nodeType(obj));
+ }
+
+
+ void Xml_print_parmlist(ParmList *p, const char* markup = "parmlist") {
+
+ print_indent(0);
+ Printf(out, "<%s id=\"%ld\" addr=\"%p\" >\n", markup, ++id, p);
+ indent_level += 4;
+ while (p) {
+ print_indent(0);
+ Printf(out, "<parm id=\"%ld\">\n", ++id);
+ Xml_print_attributes(p);
+ print_indent(0);
+ Printf(out, "</parm >\n");
+ p = nextSibling(p);
+ }
+ indent_level -= 4;
+ print_indent(0);
+ Printf(out, "</%s >\n", markup);
+ }
+
+ void Xml_print_baselist(List *p) {
+
+ print_indent(0);
+ Printf(out, "<baselist id=\"%ld\" addr=\"%p\" >\n", ++id, p);
+ indent_level += 4;
+ Iterator s;
+ for (s = First(p); s.item; s = Next(s)) {
+ print_indent(0);
+ String *item_name = Xml_escape_string(s.item);
+ Printf(out, "<base name=\"%s\" id=\"%ld\" addr=\"%p\" />\n", item_name, ++id, s.item);
+ Delete(item_name);
+ }
+ indent_level -= 4;
+ print_indent(0);
+ Printf(out, "</baselist >\n");
+ }
+
+ String *Xml_escape_string(String *str) {
+ String *escaped_str = 0;
+ if (str) {
+ escaped_str = NewString(str);
+ Replaceall(escaped_str, "&", "&amp;");
+ Replaceall(escaped_str, "<", "&lt;");
+ Replaceall(escaped_str, "\"", "&quot;");
+ Replaceall(escaped_str, "\\", "\\\\");
+ Replaceall(escaped_str, "\n", "&#10;");
+ }
+ return escaped_str;
+ }
+
+ void Xml_print_module(Node *p) {
+
+ print_indent(0);
+ Printf(out, "<attribute name=\"module\" value=\"%s\" id=\"%ld\" addr=\"%p\" />\n", Getattr(p, "name"), ++id, p);
+ }
+
+ void Xml_print_kwargs(Hash *p) {
+ Xml_print_hash(p, "kwargs");
+ }
+
+ void Xml_print_typescope(Hash *p) {
+
+ Xml_print_hash(p, "typescope");
+ }
+
+ void Xml_print_typetab(Hash *p) {
+
+ Xml_print_hash(p, "typetab");
+ }
+
+
+ void Xml_print_hash(Hash *p, const char *markup) {
+
+ print_indent(0);
+ Printf(out, "<%s id=\"%ld\" addr=\"%p\" >\n", markup, ++id, p);
+ Xml_print_attributes(p);
+ indent_level += 4;
+ Iterator n = First(p);
+ while (n.key) {
+ print_indent(0);
+ Printf(out, "<%ssitem id=\"%ld\" addr=\"%p\" >\n", markup, ++id, n.item);
+ Xml_print_attributes(n.item);
+ print_indent(0);
+ Printf(out, "</%ssitem >\n", markup);
+ n = Next(n);
+ }
+ indent_level -= 4;
+ print_indent(0);
+ Printf(out, "</%s >\n", markup);
+ }
+
+};
+
+/* -----------------------------------------------------------------------------
+ * Swig_print_xml
+ *
+ * Dump an XML version of the parse tree. This is different from using the -xml
+ * language module normally as it allows the real language module to process the
+ * tree first, possibly stuffing in new attributes, so the XML that is output ends
+ * up being a post-processing version of the tree.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_print_xml(DOH *obj, String *filename) {
+ XML xml;
+ xmllite = 1;
+
+ if (!filename) {
+ out = stdout;
+ } else {
+ out = NewFile(filename, "w", SWIG_output_files());
+ if (!out) {
+ FileErrorDisplay(filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+
+ Printf(out, "<?xml version=\"1.0\" ?> \n");
+ xml.Xml_print_tree(obj);
+}
+
+static Language *new_swig_xml() {
+ return new XML();
+}
+extern "C" Language *swig_xml(void) {
+ return new_swig_xml();
+}