summaryrefslogtreecommitdiff
path: root/Source/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Modules')
-rw-r--r--Source/Modules/README9
-rw-r--r--Source/Modules/allegrocl.cxx3222
-rw-r--r--Source/Modules/allocate.cxx955
-rw-r--r--Source/Modules/browser.cxx413
-rw-r--r--Source/Modules/cffi.cxx1081
-rw-r--r--Source/Modules/chicken.cxx1552
-rw-r--r--Source/Modules/clisp.cxx509
-rw-r--r--Source/Modules/contract.cxx354
-rw-r--r--Source/Modules/csharp.cxx3960
-rw-r--r--Source/Modules/directors.cxx288
-rw-r--r--Source/Modules/emit.cxx512
-rw-r--r--Source/Modules/guile.cxx1759
-rw-r--r--Source/Modules/java.cxx4166
-rw-r--r--Source/Modules/lang.cxx3431
-rw-r--r--Source/Modules/lua.cxx1226
-rw-r--r--Source/Modules/main.cxx1251
-rw-r--r--Source/Modules/modula3.cxx3987
-rw-r--r--Source/Modules/module.cxx57
-rw-r--r--Source/Modules/mzscheme.cxx834
-rw-r--r--Source/Modules/ocaml.cxx1866
-rw-r--r--Source/Modules/octave.cxx1425
-rw-r--r--Source/Modules/overload.cxx792
-rw-r--r--Source/Modules/perl5.cxx1768
-rw-r--r--Source/Modules/php.cxx2739
-rw-r--r--Source/Modules/pike.cxx903
-rw-r--r--Source/Modules/python.cxx4067
-rw-r--r--Source/Modules/r.cxx2745
-rw-r--r--Source/Modules/ruby.cxx3427
-rw-r--r--Source/Modules/s-exp.cxx394
-rw-r--r--Source/Modules/swigmain.cxx202
-rw-r--r--Source/Modules/swigmod.h391
-rw-r--r--Source/Modules/tcl8.cxx1306
-rw-r--r--Source/Modules/typepass.cxx1164
-rw-r--r--Source/Modules/uffi.cxx398
-rw-r--r--Source/Modules/utils.cxx98
-rw-r--r--Source/Modules/xml.cxx320
36 files changed, 53571 insertions, 0 deletions
diff --git a/Source/Modules/README b/Source/Modules/README
new file mode 100644
index 0000000..058779d
--- /dev/null
+++ b/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/Source/Modules/allegrocl.cxx b/Source/Modules/allegrocl.cxx
new file mode 100644
index 0000000..d40538d
--- /dev/null
+++ b/Source/Modules/allegrocl.cxx
@@ -0,0 +1,3222 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * allegrocl.cxx
+ *
+ * ALLEGROCL language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_allegrocl_cxx[] = "$Id: allegrocl.cxx 11471 2009-07-29 20:52:29Z wsfulton $";
+
+#include "swigmod.h"
+#include "cparse.h"
+#include <ctype.h>
+
+// #define ALLEGROCL_DEBUG
+// #define ALLEGROCL_WRAP_DEBUG
+// #define ALLEGROCL_TYPE_DEBUG
+// #define ALLEGROCL_CLASS_DEBUG
+
+static File *f_cl = 0;
+String *f_clhead = NewString("");
+String *f_clwrap = NewString("(swig-in-package ())\n\n");
+static File *f_begin;
+static File *f_runtime;
+static File *f_cxx_header = 0;
+static File *f_cxx_wrapper = 0;
+
+static String *module_name = 0;
+static String *swig_package = 0;
+
+const char *identifier_converter = "identifier-convert-null";
+
+static bool CWrap = true; // generate wrapper file for C code by default. most correct.
+static bool Generate_Wrapper = false;
+static bool unique_swig_package = false;
+
+static SwigType *fwdref_ffi_type = NewString("__SWIGACL_FwdReference");
+
+static String *current_namespace = NewString("");
+static String *current_package = NewString("");
+static Hash *defined_namespace_packages = NewHash();
+static Node *in_class = 0;
+
+static Node *first_linked_type = 0;
+static Hash *defined_foreign_types = NewHash();
+static Hash *defined_foreign_ltypes = NewHash();
+
+static String *anon_type_name = NewString("anontype");
+static int anon_type_count = 0;
+
+// stub
+String *convert_literal(String *num_param, String *type, bool try_to_split = true);
+
+class ALLEGROCL:public Language {
+public:
+ virtual void main(int argc, char *argv[]);
+ virtual int top(Node *n);
+ virtual int functionWrapper(Node *n);
+ virtual int namespaceDeclaration(Node *n);
+ virtual int constructorHandler(Node *n);
+ virtual int destructorHandler(Node *n);
+ virtual int globalvariableHandler(Node *n);
+ virtual int variableWrapper(Node *n);
+ virtual int constantWrapper(Node *n);
+ virtual int memberfunctionHandler(Node *n);
+ virtual int membervariableHandler(Node *n);
+ virtual int classHandler(Node *n);
+ virtual int emit_one(Node *n);
+ virtual int enumDeclaration(Node *n);
+ virtual int enumvalueDeclaration(Node *n);
+ virtual int typedefHandler(Node *n);
+ virtual int classforwardDeclaration(Node *n);
+ virtual int templateDeclaration(Node *n);
+ virtual int validIdentifier(String *s);
+private:
+ int emit_defun(Node *n, File *f_cl);
+ int emit_dispatch_defun(Node *n);
+ int emit_buffered_defuns(Node *n);
+ int cClassHandler(Node *n);
+ int cppClassHandler(Node *n);
+};
+static ALLEGROCL *allegrocl = 0;
+
+static String *trim(String *str) {
+ char *c = Char(str);
+ while (*c != '\0' && isspace((int) *c))
+ ++c;
+ String *result = NewString(c);
+ Chop(result);
+ return result;
+}
+
+int is_integer(String *s) {
+ char *c = Char(s);
+ if (c[0] == '#' && (c[1] == 'x' || c[1] == 'o'))
+ c += 2;
+
+ while (*c) {
+ if (!isdigit(*c))
+ return 0;
+ c++;
+ }
+ return 1;
+}
+
+String *class_from_class_or_class_ref(String *type) {
+ SwigType *stripped = SwigType_strip_qualifiers(type);
+ if (SwigType_isclass(stripped))
+ return stripped;
+
+ if (SwigType_ispointer(stripped) || SwigType_isreference(stripped)) {
+ // Printf(stderr,"It is a pointer/reference. Is it a class?\n");
+ SwigType_pop(stripped);
+ if (SwigType_isclass(stripped)) {
+ return stripped;
+ }
+ }
+ return 0;
+}
+
+String *lookup_defined_foreign_type(String *k) {
+
+#ifdef ALLEGROCL_TYPE_DEBUG
+ Printf(stderr, "Looking up defined type '%s'.\n Found: '%s'\n", k, Getattr(defined_foreign_types, k));
+#endif
+
+ return Getattr(defined_foreign_types, k);
+}
+
+String *listify_namespace(String *namespaze) {
+ if (Len(namespaze) == 0)
+ return NewString("()");
+ String *result = NewStringf("(\"%s\")", namespaze);
+ Replaceall(result, "::", "\" \"");
+ return result;
+}
+
+String *namespaced_name(Node *n, String *ns = current_namespace) {
+
+ return NewStringf("%s%s%s", ns, (Len(ns) != 0) ? "::" : "", Getattr(n, "sym:name"));
+}
+
+// "Namespace::Nested::Class2::Baz" -> "Baz"
+static String *strip_namespaces(String *str) {
+ char *result = Char(str);
+ String *stripped_one;
+ while ((stripped_one = Strstr(result, "::")))
+ result = Char(stripped_one) + 2;
+ return NewString(result);
+}
+
+static String *namespace_of(String *str) {
+ char *p = Char(str);
+ char *start = Char(str);
+ char *result = 0;
+ String *stripped_one;
+
+ while ((stripped_one = Strstr(p, "::"))) {
+ p = Char(stripped_one) + 2;
+ }
+ if (p > start) {
+ int len = p - start - 1;
+ result = (char *) malloc(len);
+ strncpy(result, start, len - 1);
+ result[len - 1] = 0;
+ }
+ return Char(result);
+}
+
+void add_linked_type(Node *n) {
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "Adding linked node of type: %s(%s) %s(%x)\n\n", nodeType(n), Getattr(n, "storage"), Getattr(n, "name"), n);
+ // Swig_print_node(n);
+#endif
+ if (!first_linked_type) {
+ first_linked_type = n;
+ Setattr(n, "allegrocl:last_linked_type", n);
+ } else {
+ Node *t = Getattr(first_linked_type, "allegrocl:last_linked_type");
+ Setattr(t, "allegrocl:next_linked_type", n);
+ Setattr(first_linked_type, "allegrocl:last_linked_type", n);
+ }
+}
+
+void replace_linked_type(Node *old, Node *new_node) {
+ Node *prev = Getattr(old, "allegrocl:prev_linked_type");
+
+ Setattr(new_node, "allegrocl:next_linked_type", Getattr(old, "allegrocl:next_linked_type"));
+ if (prev)
+ Setattr(prev, "allegrocl:next_linked_type", new_node);
+ Delattr(old, "allegrocl:next_linked_type");
+ Delattr(old, "allegrocl:prev_linked_type");
+
+ // check if we're replacing the first link.
+ if (first_linked_type == old) {
+ first_linked_type = new_node;
+ Setattr(first_linked_type, "allegrocl:last_linked_type", Getattr(old, "allegrocl:last_linked_type"));
+ }
+ // check if we're replacing the last link.
+ if (Getattr(first_linked_type, "allegrocl:last_linked_type") == old)
+ Setattr(first_linked_type, "allegrocl:last_linked_type", new_node);
+}
+
+void insert_linked_type_at(Node *old, Node *new_node, int before = 1) {
+ Node *p = 0;
+
+ if (!first_linked_type) {
+ add_linked_type(new_node);
+ return;
+ }
+
+ if (!before) {
+ Setattr(new_node, "allegrocl:next_linked_type", Getattr(old, "allegrocl:next_linked_type"));
+ Setattr(old, "allegrocl:next_linked_type", new_node);
+ if (Getattr(first_linked_type, "allegrocl:last_linked_type") == old)
+ Setattr(first_linked_type, "allegrocl:last_linked_type", new_node);
+ } else {
+ Node *c = first_linked_type;
+ while (c) {
+ if (c == old) {
+ break;
+ } else {
+ p = c;
+ c = Getattr(c, "allegrocl:next_linked_type");
+ }
+ }
+ if (c == old) {
+ Setattr(new_node, "allegrocl:next_linked_type", c);
+ if (first_linked_type == c) {
+ first_linked_type = new_node;
+ Setattr(first_linked_type, "allegrocl:last_linked_type", Getattr(c, "allegrocl:last_linked_type"));
+ Delattr(c, "allegrocl:last_linked_type");
+ }
+ if (p)
+ Setattr(p, "allegrocl:next_linked_type", new_node);
+ }
+ }
+}
+
+Node *find_linked_type_by_name(String *name) {
+ Node *p = 0;
+ Node *c = first_linked_type;
+
+ // Printf(stderr,"in find_linked_type_by_name '%s'...", name);
+ while (c) {
+ String *key = Getattr(c, "name");
+ if (!Strcmp(key, name)) {
+ break;
+ } else {
+ p = c;
+ c = Getattr(c, "allegrocl:next_linked_type");
+ }
+ }
+ // Printf(stderr,"exit find_linked_type_by_name.\n");
+
+ if (p && c)
+ Setattr(c, "allegrocl:prev_linked_type", p);
+ // Printf(stderr,"find_linked_type_by_name: DONE\n");
+ return c;
+}
+
+Node *get_primary_synonym_of(Node *n) {
+ Node *p = Getattr(n, "allegrocl:synonym-of");
+ Node *prim = n;
+
+ // Printf(stderr, "getting primary synonym of %x\n", n);
+ while (p) {
+ // Printf(stderr, " found one! %x\n", p);
+ prim = p;
+ p = Getattr(p, "allegrocl:synonym-of");
+ }
+ // Printf(stderr,"get_primary_syn: DONE. returning %s(%x)\n", Getattr(prim,"name"),prim);
+ return prim;
+}
+
+void add_forward_referenced_type(Node *n, int overwrite = 0) {
+ String *k = Getattr(n, "name");
+ String *name = Getattr(n, "sym:name");
+ String *ns = listify_namespace(current_namespace);
+
+ String *val = Getattr(defined_foreign_types, k);
+
+ if (!val || overwrite) {
+#ifdef ALLEGROCL_TYPE_DEBUG
+ Printf(stderr, "Adding forward reference for %s (overwrite=%d)\n", k, overwrite);
+#endif
+ Setattr(defined_foreign_types, Copy(k), NewString("forward-reference"));
+
+ String *mangled_lname_gen = NewStringf("#.(swig-insert-id \"%s\" %s :type :class)", name, ns);
+
+ Setattr(defined_foreign_ltypes, Copy(k), mangled_lname_gen);
+ // Printf(f_cl, ";; forward reference stub\n"
+ // "(swig-def-foreign-class \"%s\" (ff:foreign-pointer) (:class ))\n\n"
+ // , name);
+
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "Linking forward reference type = %s(%x)\n", k, n);
+#endif
+ add_linked_type(n);
+ }
+}
+
+void add_defined_foreign_type(Node *n, int overwrite = 0, String *k = 0,
+ String *name = 0, String *ns = current_namespace) {
+
+ String *val;
+ String *ns_list = listify_namespace(ns);
+ String *templated = n ? Getattr(n, "template") : 0;
+ String *cDeclName = n ? Getattr(n, "classDeclaration:name") : 0;
+
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "IN A-D-F-T. (n=%x, ow=%d, k=%s, name=%s, ns=%s\n", n, overwrite, k, name, ns);
+ Printf(stderr, " templated = '%x', classDecl = '%x'\n", templated, cDeclName);
+#endif
+ if (n) {
+ if (!name)
+ name = Getattr(n, "sym:name");
+ if (!name)
+ name = strip_namespaces(Getattr(n, "name"));
+ if (templated) {
+ k = namespaced_name(n);
+ } else {
+ String *kind_of_type = Getattr(n, "kind");
+
+ /*
+ For typedefs of the form:
+
+ typedef struct __xxx { ... } xxx;
+
+ behavior differs between C mode and C++ mode.
+
+ C Mode:
+ add_defined_foreign_type will be called once via classHandler
+ to define the type for 'struct __xxx' and add the mapping from
+ 'struct __xxx' -> 'xxx'
+
+ It will also be called once via typedefHandler to add the
+ mapping 'xxx' -> 'xxx'
+
+ C++ Mode:
+ add_defined_foreign_type will be called once via classHandler
+ to define the type for 'xxx'. it also adds the mapping from
+ 'xxx' -> 'xxx' and also for 'struct xxx' -> 'xxx'
+
+ In typedefHandler, we again try to add the mapping from
+ 'xxx' -> 'xxx', which already exists. This second mapping
+ is ignored.
+
+ Both modes:
+
+ All references to this typedef'd struct will appear in
+ generated lisp code as an objectd of type 'xxx'. For
+ non-typedef'd structs, the classHand mapping will be
+
+ struct __xxx -> (swig-insert-id "__xxx")
+ */
+ // Swig_print_node(n);
+ String *unnamed = Getattr(n, "unnamed");
+ if (kind_of_type && (!Strcmp(kind_of_type, "struct")
+ || !Strcmp(kind_of_type, "union")) && cDeclName && !unnamed) {
+ k = NewStringf("%s %s", kind_of_type, cDeclName);
+ } else {
+ if (!Strcmp(nodeType(n), "enum") && unnamed) {
+ name = NewStringf("%s%d", anon_type_name, anon_type_count++);
+ k = NewStringf("enum %s", name);
+ Setattr(n, "allegrocl:name", name);
+
+ } else {
+ k = k ? k : Getattr(n, "name");
+ }
+ }
+ }
+ // Swig_print_node(n);
+ }
+
+ if (SwigType_istemplate(name)) {
+ String *temp = strip_namespaces(SwigType_templateprefix(name));
+ name = NewStringf("%s%s%s", temp, SwigType_templateargs(name), SwigType_templatesuffix(name));
+ }
+
+ val = lookup_defined_foreign_type(k);
+
+ int is_fwd_ref = 0;
+ if (val)
+ is_fwd_ref = !Strcmp(val, "forward-reference");
+
+ if (!val || overwrite || is_fwd_ref) {
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "Adding defined type '%s' = '%s' '%s' (overwrite=%d, in-class=%d)\n", k, ns, name, overwrite, in_class);
+#endif
+ String *mangled_name_gen = NewStringf("#.(swig-insert-id \"%s\" %s :type :type)", name, ns_list);
+ String *mangled_lname_gen = NewStringf("#.(swig-insert-id \"%s\" %s :type :class)", name, ns_list);
+
+ Setattr(defined_foreign_types, Copy(k), Copy(mangled_name_gen));
+ Setattr(defined_foreign_ltypes, Copy(k), Copy(mangled_lname_gen));
+
+ if (CPlusPlus) {
+ bool cpp_struct = Strstr(k, "struct ") ? true : false;
+ bool cpp_union = Strstr(k, "union ") ? true : false;
+
+ String *cpp_type = 0;
+ if (cpp_struct) {
+ cpp_type = Copy(k);
+ Replaceall(cpp_type, "struct ", "");
+ } else if (cpp_union) {
+ cpp_type = Copy(k);
+ Replaceall(cpp_type, "union ", "");
+ }
+
+ if (cpp_struct || cpp_union) {
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, " Also adding defined type '%s' = '%s' '%s' (overwrite=%d)\n", cpp_type, ns, name, overwrite);
+#endif
+ Setattr(defined_foreign_types, Copy(cpp_type), Copy(mangled_name_gen));
+ Setattr(defined_foreign_ltypes, Copy(cpp_type), Copy(mangled_lname_gen));
+ }
+ }
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "looking to add %s/%s(%x) to linked_type_list...\n", k, name, n);
+#endif
+ if (is_fwd_ref) {
+ // Printf(stderr,"*** 1\n");
+ add_linked_type(n);
+ } else {
+ // Printf(stderr,"*** 1-a\n");
+ if (SwigType_istemplate(k)) {
+ SwigType *resolved = SwigType_typedef_resolve_all(k);
+ // Printf(stderr,"*** 1-b\n");
+ Node *match = find_linked_type_by_name(resolved);
+ Node *new_node = 0;
+ // Printf(stderr, "*** temp-1\n");
+ if (n) {
+ new_node = n;
+ } else {
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "Creating a new templateInst:\n");
+ Printf(stderr, " name = %s\n", resolved);
+ Printf(stderr, " sym:name = %s\n", name);
+ Printf(stderr, " real-name = %s\n", k);
+ Printf(stderr, " type = %s\n", resolved);
+ Printf(stderr, " ns = %s\n\n", ns);
+#endif
+ new_node = NewHash();
+ Setattr(new_node, "nodeType", "templateInst");
+ Setattr(new_node, "name", Copy(resolved));
+ Setattr(new_node, "sym:name", Copy(name));
+ Setattr(new_node, "real-name", Copy(k));
+ Setattr(new_node, "type", Copy(resolved));
+ Setattr(new_node, "allegrocl:namespace", ns);
+ Setattr(new_node, "allegrocl:package", ns);
+ }
+
+ if (!match) {
+ if (!Strcmp(nodeType(new_node), "templateInst") && in_class) {
+ /* this is an implicit template instantiation found while
+ walking a class. need to insert this into the
+ linked_type list before the current class definition */
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "trying to insert a templateInst before a class\n");
+#endif
+ insert_linked_type_at(in_class, new_node);
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "DID IT!\n");
+#endif
+ } else {
+ // Printf(stderr,"*** 3\n");
+ add_linked_type(new_node);
+ }
+ Setattr(new_node, "allegrocl:synonym:is-primary", "1");
+ } else {
+ // a synonym type was found (held in variable 'match')
+ // Printf(stderr, "setting primary synonym of %x to %x\n", new_node, match);
+ if (new_node == match)
+ Printf(stderr, "Hey-4 * - '%s' is a synonym of iteself!\n", Getattr(new_node, "name"));
+ Setattr(new_node, "allegrocl:synonym-of", match);
+ // Printf(stderr,"*** 4\n");
+ add_linked_type(new_node);
+ }
+ } else {
+ Node *match;
+
+ if (!Strcmp(nodeType(n), "cdecl") && !Strcmp(Getattr(n, "storage"), "typedef")) {
+ SwigType *type = SwigType_strip_qualifiers(Getattr(n, "type"));
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "Examining typedef '%s' for class references. (%d)\n", type, SwigType_isclass(type));
+#endif
+ if (SwigType_isclass(type)) {
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "Found typedef of a class '%s'\n", type);
+#endif
+ /*
+ For the following parsed expression:
+
+ typedef struct __xxx { ... } xxx;
+
+ if n is of kind "class" (defining the class 'struct __xxx'
+ then we add n to the linked type list.
+
+ if n is "cdecl" node of storage "typedef" (to note
+ that xxx is equivalent to 'struct __xxx' then we don't
+ want to add this node to the linked type list.
+ */
+ String *defined_type = lookup_defined_foreign_type(type);
+ String *defined_key_type = lookup_defined_foreign_type(k);
+
+ if ((Strstr(type, "struct ") || Strstr(type, "union "))
+ && defined_type && !Strcmp(defined_type, defined_key_type)) {
+ // mark as a synonym but don't add to linked_type list
+ // Printf(stderr,"*** 4.8\n");
+ Setattr(n, "allegrocl:synonym", "1");
+ } else {
+ SwigType *lookup_type = SwigType_istemplate(type) ? SwigType_typedef_resolve_all(type) : Copy(type);
+ match = find_linked_type_by_name(lookup_type);
+ if (match) {
+ Setattr(n, "allegrocl:synonym", "1");
+ Setattr(n, "allegrocl:synonym-of", match);
+ Setattr(n, "real-name", Copy(lookup_type));
+
+ // Printf(stderr, "*** pre-5: found match of '%s'(%x)\n", Getattr(match,"name"),match);
+ // if(n == match) Printf(stderr, "Hey-5 *** setting synonym of %x to %x\n", n, match);
+ // Printf(stderr,"*** 5\n");
+ add_linked_type(n);
+ } else {
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "Creating classfoward node for struct stub in typedef.\n");
+#endif
+ Node *new_node = NewHash();
+ String *symname = Copy(type);
+ Replaceall(symname, "struct ", "");
+ Setattr(new_node, "nodeType", "classforward");
+ Setattr(new_node, "name", Copy(type));
+ Setattr(new_node, "sym:name", symname);
+ Setattr(new_node, "allegrocl:namespace", ns);
+ Setattr(new_node, "allegrocl:package", ns);
+
+ String *mangled_new_name = NewStringf("#.(swig-insert-id \"%s\" %s)", symname, ns_list);
+ String *mangled_new_lname = NewStringf("#.(swig-insert-id \"%s\" %s :type :class)", symname, ns_list);
+ Setattr(defined_foreign_types, Copy(symname), Copy(mangled_new_name));
+ Setattr(defined_foreign_ltypes, Copy(symname), Copy(mangled_new_lname));
+
+ // Printf(stderr,"Weird! Can't find the type!\n");
+ add_forward_referenced_type(new_node);
+ add_linked_type(new_node);
+
+ Setattr(n, "allegrocl:synonym", "1");
+ Setattr(n, "allegrocl:synonym-of", new_node);
+
+ add_linked_type(n);
+ }
+ Delete(lookup_type);
+ }
+ } else {
+ // check if it's a pointer or reference to a class.
+ // Printf(stderr,"Checking if '%s' is a p. or r. to a class\n", type);
+ String *class_ref = class_from_class_or_class_ref(type);
+ if (class_ref) {
+ match = find_linked_type_by_name(class_ref);
+ Setattr(n, "allegrocl:synonym", "1");
+ Setattr(n, "allegrocl:synonym-of", match);
+ add_linked_type(n);
+ }
+ }
+ Delete(type);
+ // synonym types have already been added.
+ // Printf(stderr,"*** 10\n");
+ if (!Getattr(n, "allegrocl:synonym"))
+ add_linked_type(n);
+ } else if (Getattr(n, "template")) {
+ // Printf(stderr, "this is a class template node(%s)\n", nodeType(n));
+ String *resolved = SwigType_typedef_resolve_all(Getattr(n, "name"));
+
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, " looking up %s for linked type match with %s...\n", Getattr(n, "sym:name"), resolved);
+#endif
+ match = find_linked_type_by_name(resolved);
+ if (!match) {
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "found no implicit instantiation of %%template node %s(%x)\n", Getattr(n, "name"), n);
+#endif
+ add_linked_type(n);
+ } else {
+ Node *primary = get_primary_synonym_of(match);
+
+ Setattr(n, "allegrocl:synonym:is-primary", "1");
+ Delattr(primary, "allegrocl:synonym:is-primary");
+ if (n == match)
+ Printf(stderr, "Hey-7 * setting synonym of %x to %x\n (match = %x)", primary, n, match);
+ Setattr(primary, "allegrocl:synonym-of", n);
+ // Printf(stderr,"*** 7\n");
+ add_linked_type(n);
+ }
+ } else {
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "linking type '%s'(%x)\n", k, n);
+#endif
+ // Printf(stderr,"*** 8\n");
+ add_linked_type(n);
+ }
+ }
+ }
+ Delete(mangled_name_gen);
+ Delete(mangled_lname_gen);
+ } else {
+ if (!CPlusPlus || Strcmp(Getattr(n,"kind"),"typedef")) {
+ Swig_warning(WARN_TYPE_REDEFINED, Getfile(n), Getline(n),
+ "Attempting to store a foreign type that exists: %s (%s)\n",
+ k, val);
+ }
+ }
+
+ Delete(ns_list);
+
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "OUT A-D-F-T\n");
+#endif
+}
+
+void note_implicit_template_instantiation(SwigType *t) {
+ // the namespace of the implicit instantiation is not necessarily
+ // current_namespace. Attempt to cull this from the type.
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "culling namespace of '%s' from '%s'\n", t, SwigType_templateprefix(t));
+#endif
+ String *implicit_ns = namespace_of(SwigType_templateprefix(t));
+ add_defined_foreign_type(0, 0, t, t, implicit_ns ? implicit_ns : current_namespace);
+}
+
+String *get_ffi_type(Node *n, SwigType *ty, const_String_or_char_ptr name) {
+ /* lookup defined foreign type.
+ if it exists, it will return a form suitable for placing
+ into lisp code to generate the def-foreign-type name */
+
+#ifdef ALLEGROCL_TYPE_DEBUG
+ Printf(stderr, "inside g_f_t: looking up '%s' '%s'\n", ty, name);
+#endif
+
+ String *found_type = lookup_defined_foreign_type(ty);
+
+ if (found_type) {
+#ifdef ALLEGROCL_TYPE_DEBUG
+ Printf(stderr, "found_type '%s'\n", found_type);
+#endif
+ return (Strcmp(found_type, "forward-reference") ? Copy(found_type) : get_ffi_type(n, fwdref_ffi_type, ""));
+ } else {
+ Node *node = NewHash();
+ Setattr(node, "type", ty);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *tm = Swig_typemap_lookup("ffitype", node, name, 0);
+ Delete(node);
+
+ if (tm) {
+#ifdef ALLEGROCL_TYPE_DEBUG
+ Printf(stderr, "g-f-t: found ffitype typemap '%s'\n", tm);
+#endif
+ return NewString(tm);
+ }
+
+ if (SwigType_istemplate(ty)) {
+ note_implicit_template_instantiation(ty);
+ return Copy(lookup_defined_foreign_type(ty));
+ }
+ }
+ return 0;
+}
+
+String *lookup_defined_foreign_ltype(String *l) {
+
+#ifdef ALLEGROCL_TYPE_DEBUG
+ Printf(stderr, "Looking up defined ltype '%s'.\n Found: '%s'\n", l, Getattr(defined_foreign_ltypes, l));
+#endif
+ return Getattr(defined_foreign_ltypes, l);
+}
+
+/* walk type and return string containing lisp version.
+ recursive. */
+String *internal_compose_foreign_type(Node *n, SwigType *ty) {
+
+ SwigType *tok;
+ String *ffiType = NewString("");
+
+ // for a function type, need to walk the parm list.
+ while (Len(ty) != 0) {
+ tok = SwigType_pop(ty);
+
+ if (SwigType_isfunction(tok)) {
+ // Generate Function wrapper
+ Printf(ffiType, "(:function ");
+ // walk parm list
+ List *pl = SwigType_parmlist(tok);
+
+ Printf(ffiType, "("); // start parm list
+ for (Iterator i = First(pl); i.item; i = Next(i)) {
+ SwigType *f_arg = SwigType_strip_qualifiers(i.item);
+ Printf(ffiType, "%s ", internal_compose_foreign_type(n, f_arg));
+ Delete(f_arg);
+ }
+ Printf(ffiType, ")"); // end parm list.
+
+ // do function return type.
+ Printf(ffiType, " %s)", internal_compose_foreign_type(n, ty));
+ break;
+ } else if (SwigType_ispointer(tok) || SwigType_isreference(tok)) {
+ Printf(ffiType, "(* %s)", internal_compose_foreign_type(n, ty));
+ } else if (SwigType_isarray(tok)) {
+ Printf(ffiType, "(:array %s", internal_compose_foreign_type(n, ty));
+ String *atype = NewString("int");
+ String *dim = convert_literal(SwigType_array_getdim(tok, 0), atype);
+ Delete(atype);
+ if (is_integer(dim)) {
+ Printf(ffiType, " %s)", dim);
+ } else {
+ Printf(ffiType, " #| %s |#)", SwigType_array_getdim(tok, 0));
+ }
+ } else if (SwigType_ismemberpointer(tok)) {
+ // temp
+ Printf(ffiType, "(* %s)", internal_compose_foreign_type(n, ty));
+ } else {
+ String *res = get_ffi_type(n, tok, "");
+ if (res) {
+ Printf(ffiType, "%s", res);
+ } else {
+ SwigType *resolved_type = SwigType_typedef_resolve(tok);
+ if (resolved_type) {
+ res = get_ffi_type(n, resolved_type, "");
+ if (res) {
+ } else {
+ res = internal_compose_foreign_type(n, resolved_type);
+ }
+ if (res)
+ Printf(ffiType, "%s", res);
+ }
+
+ if (!res) {
+ String *is_struct = 0;
+ String *tok_remove_text = 0;
+ String *tok_name = Copy(tok);
+ String *tok_key = SwigType_str(tok,0);
+ if ((is_struct = Strstr(tok_key, "struct ")) || Strstr(tok_key, "union ")) {
+ tok_remove_text = NewString(is_struct ? "struct " : "union ");
+ }
+
+ /* be more permissive of opaque types. This is the swig way.
+ compiles will notice if these types are ultimately not
+ present. */
+
+ if(tok_remove_text) {
+ Replaceall(tok_name,tok_remove_text,"");
+ }
+ tok_name = strip_namespaces(tok_name);
+ Delete(tok_remove_text);
+ // Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(tok), Getline(tok), "Unable to find definition of '%s', assuming forward reference.\n", tok);
+
+#ifdef ALLEGROCL_TYPE_DEBUG
+ Printf(stderr, "i-c-f-t: adding forward reference for unknown type '%s'. mapping: %s -> %s\n", tok, tok_key, tok_name);
+#endif
+ Node *nn = NewHash();
+ Setattr(nn,"nodeType","classforward");
+ Setattr(nn,"kind","class");
+ Setattr(nn,"sym:name",tok_name);
+ Setattr(nn,"name",tok_key);
+ Setattr(nn,"allegrocl:package",current_namespace);
+
+ add_forward_referenced_type(nn, 0);
+ // tok_name is dangling here, unused. ouch. why?
+ Printf(ffiType, "%s", get_ffi_type(n, tok, ""), tok_name);
+ }
+ }
+ }
+ }
+ return ffiType;
+}
+
+String *compose_foreign_type(Node *n, SwigType *ty, String * /*id*/ = 0) {
+
+#ifdef ALLEGROCL_TYPE_DEBUG
+ Printf(stderr, "compose_foreign_type: ENTER (%s)...\n ", ty);
+ // Printf(stderr, "compose_foreign_type: ENTER (%s)(%s)...\n ", ty, (id ? id : 0));
+ /* String *id_ref = SwigType_str(ty, id);
+ Printf(stderr, "looking up typemap for %s, found '%s'(%x)\n",
+ id_ref, lookup_res ? Getattr(lookup_res, "code") : 0, lookup_res);
+ if (lookup_res) Swig_print_node(lookup_res);
+ */
+#endif
+
+ /* should we allow named lookups in the typemap here? YES! */
+ /* unnamed lookups should be found in get_ffi_type, called
+ by internal_compose_foreign_type(), below. */
+
+ /* I'm reverting to 'no' for the question above. I can no longer
+ remember why I needed it. If a user needed it, I'll find out
+ as soon as they upgrade. Sigh. -mutandiz 9/16/2008. */
+
+/*
+ if(id && lookup_res) {
+#ifdef ALLEGROCL_TYPE_DEBUG
+ Printf(stderr, "compose_foreign_type: EXIT-1 (%s)\n ", Getattr(lookup_res, "code"));
+#endif
+ return NewString(Getattr(lookup_res, "code"));
+ }
+*/
+
+ SwigType *temp = SwigType_strip_qualifiers(ty);
+ String *res = internal_compose_foreign_type(n, temp);
+ Delete(temp);
+
+#ifdef ALLEGROCL_TYPE_DEBUG
+ Printf(stderr, "compose_foreign_type: EXIT (%s)\n ", res);
+#endif
+
+ return res;
+}
+
+void update_package_if_needed(Node *n, File *f = f_clwrap) {
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "update_package: ENTER... \n");
+ Printf(stderr, " current_package = '%s'\n", current_package);
+ Printf(stderr, " node_package = '%s'\n", Getattr(n, "allegrocl:package"));
+ Printf(stderr, " node(%x) = '%s'\n", n, Getattr(n, "name"));
+#endif
+ String *node_package = Getattr(n, "allegrocl:package");
+ if (Strcmp(current_package, node_package)) {
+ String *lispy_package = listify_namespace(node_package);
+
+ Delete(current_package);
+ current_package = Copy(node_package);
+ Printf(f, "\n(swig-in-package %s)\n", lispy_package);
+ Delete(lispy_package);
+ }
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "update_package: EXIT.\n");
+#endif
+}
+
+static String *mangle_name(Node *n, char const *prefix = "ACL", String *ns = current_namespace) {
+ String *suffix = Getattr(n, "sym:overname");
+ String *pre_mangled_name = NewStringf("%s_%s__%s%s", prefix, ns, Getattr(n, "sym:name"), suffix);
+ String *mangled_name = Swig_name_mangle(pre_mangled_name);
+ Delete(pre_mangled_name);
+ return mangled_name;
+}
+
+/* utilities */
+
+/* remove a pointer from ffitype. non-destructive.
+ (* :char) ==> :char
+ (* (:array :int 30)) ==> (:array :int 30) */
+String *dereference_ffitype(String *ffitype) {
+ char *start;
+ char *temp = Char(ffitype);
+ String *reduced_type = 0;
+
+ if(temp && temp[0] == '(' && temp[1] == '*') {
+ temp += 2;
+
+ // walk past start of pointer references
+ while(*temp == ' ') temp++;
+ start = temp;
+ // temp = Char(reduced_type);
+ reduced_type = NewString(start);
+ temp = Char(reduced_type);
+ // walk to end of string. remove closing paren
+ while(*temp != '\0') temp++;
+ *(--temp) = '\0';
+ }
+
+ return reduced_type ? reduced_type : Copy(ffitype);
+}
+
+/* returns new string w/ parens stripped */
+String *strip_parens(String *string) {
+ string = Copy(string);
+ Replaceall(string, "(", "");
+ Replaceall(string, ")", "");
+ return string;
+}
+
+int ALLEGROCL::validIdentifier(String *s) {
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "validIdentifier %s\n", s);
+#endif
+
+ char *c = Char(s);
+
+ bool got_dot = false;
+ bool only_dots = true;
+
+ /* Check that s is a valid common lisp symbol. There's a lot of leeway here.
+ A common lisp symbol is essentially any token that's not a number and
+ does not consist of only dots.
+
+ We are expressly not allowing spaces in identifiers here, but spaces
+ could be added via the identifier converter. */
+ while (*c) {
+ if (*c == '.') {
+ got_dot = true;
+ } else {
+ only_dots = false;
+ }
+ if (!isgraph(*c))
+ return 0;
+ c++;
+ }
+
+ return (got_dot && only_dots) ? 0 : 1;
+}
+
+String *infix_to_prefix(String *val, char split_op, const String *op, String *type) {
+ List *ored = Split(val, split_op, -1);
+
+ // some float hackery
+ if (((split_op == '+') || (split_op == '-')) && Len(ored) == 2 &&
+ (SwigType_type(type) == T_FLOAT || SwigType_type(type) == T_DOUBLE || SwigType_type(type) == T_LONGDOUBLE)) {
+ // check that we're not splitting a float
+ String *possible_result = convert_literal(val, type, false);
+ if (possible_result)
+ return possible_result;
+
+ }
+ // try parsing the split results. if any part fails, kick out.
+ bool part_failed = false;
+ if (Len(ored) > 1) {
+ String *result = NewStringf("(%s", op);
+ for (Iterator i = First(ored); i.item; i = Next(i)) {
+ String *converted = convert_literal(i.item, type);
+ if (converted) {
+ Printf(result, " %s", converted);
+ Delete(converted);
+ } else {
+ part_failed = true;
+ break;
+ }
+ }
+ Printf(result, ")");
+ Delete(ored);
+ return part_failed ? 0 : result;
+ }
+ Delete(ored);
+ return 0;
+}
+
+/* To be called by code generating the lisp interface
+ Will return a containing the literal based on type.
+ Will return null if there are problems.
+
+ try_to_split defaults to true (see stub above).
+ */
+String *convert_literal(String *literal, String *type, bool try_to_split) {
+ String *num_param = Copy(literal);
+ String *trimmed = trim(num_param);
+ String *num = strip_parens(trimmed), *res = 0;
+ char *s = Char(num);
+
+ String *ns = listify_namespace(current_namespace);
+
+ // very basic parsing of infix expressions.
+ if (try_to_split && SwigType_type(type) != T_STRING) {
+ if ((res = infix_to_prefix(num, '|', "logior", type)))
+ return res;
+ if ((res = infix_to_prefix(num, '&', "logand", type)))
+ return res;
+ if ((res = infix_to_prefix(num, '^', "logxor", type)))
+ return res;
+ if ((res = infix_to_prefix(num, '*', "*", type)))
+ return res;
+ if ((res = infix_to_prefix(num, '/', "/", type)))
+ return res;
+ if ((res = infix_to_prefix(num, '+', "+", type)))
+ return res;
+ if ((res = infix_to_prefix(num, '-', "-", type)))
+ return res;
+ // if ((res = infix_to_prefix(num, '~', "lognot", type))) return res;
+ // if( (res = infix_to_prefix(num, '<<', "ash", type)) ) return res;
+ }
+
+ // unary complement...
+ if (s[0] == '~' && Len(num) >= 2) {
+ String *id = NewString(++s);
+ String *id_conv = convert_literal(id, type, false);
+ Delete(id);
+ if (id_conv)
+ return NewStringf("(lognot %s)", id_conv);
+ s--;
+ }
+
+ if (SwigType_type(type) == T_FLOAT || SwigType_type(type) == T_DOUBLE || SwigType_type(type) == T_LONGDOUBLE) {
+ // Use CL syntax for float literals
+ String *oldnum = Copy(num);
+
+ // careful. may be a float identifier or float constant.
+ char *num_start = Char(num);
+ char *num_end = num_start + strlen(num_start) - 1;
+
+ bool is_literal = isdigit(*num_start) || (*num_start == '.');
+
+ String *lisp_exp = 0;
+ if (is_literal) {
+ if (*num_end == 'f' || *num_end == 'F') {
+ lisp_exp = NewString("f");
+ } else {
+ lisp_exp = NewString("d");
+ }
+
+ if (*num_end == 'l' || *num_end == 'L' || *num_end == 'f' || *num_end == 'F') {
+ *num_end = '\0';
+ num_end--;
+ }
+
+ int exponents = Replaceall(num, "e", lisp_exp) + Replaceall(num, "E", lisp_exp);
+
+ if (!exponents)
+ Printf(num, "%s0", lisp_exp);
+
+ if (exponents > 1 || (exponents + Replaceall(num, ".", ".") == 0)) {
+ // Printf(stderr, "Can't parse '%s' as type '%s'.\n", oldnum, type);
+ Delete(num);
+ num = 0;
+ }
+ Delete(lisp_exp);
+ } else {
+ String *id = NewStringf("#.(swig-insert-id \"%s\" %s :type :constant)",
+ num, ns);
+ Delete(num);
+ num = id;
+ }
+
+ Delete(oldnum);
+ Delete(trimmed);
+ Delete(ns);
+ return num;
+ } else if (SwigType_type(type) == T_CHAR) {
+ /* Use CL syntax for character literals */
+ Delete(num);
+ Delete(trimmed);
+ return NewStringf("#\\%s", num_param);
+ } else if (SwigType_type(type) == T_STRING) {
+ /* Use CL syntax for string literals */
+ Delete(num);
+ Delete(trimmed);
+ return NewStringf("\"%s\"", num_param);
+ } else if (Len(num) >= 1 && (isdigit(s[0]) || s[0] == '+' || s[0] == '-')) {
+ /* use CL syntax for numbers */
+ String *oldnum = Copy(num);
+ int usuffixes = Replaceall(num, "u", "") + Replaceall(num, "U", "");
+ int lsuffixes = Replaceall(num, "l", "") + Replaceall(num, "L", "");
+ if (usuffixes > 1 || lsuffixes > 1) {
+ Printf(stderr, "Weird!! number %s looks invalid.\n", oldnum);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ s = Char(num);
+ if (s[0] == '0' && Len(num) >= 2) {
+ /*octal or hex */
+ res = NewStringf("#%c%s", tolower(s[1]) == 'x' ? 'x' : 'o', s + 2);
+ Delete(num);
+ } else {
+ res = num;
+ }
+ Delete(oldnum);
+ Delete(trimmed);
+ return res;
+ } else if (allegrocl->validIdentifier(num)) {
+ /* convert C/C++ identifiers to CL symbols */
+ res = NewStringf("#.(swig-insert-id \"%s\" %s :type :constant)", num, ns);
+ Delete(num);
+ Delete(trimmed);
+ Delete(ns);
+ return res;
+ } else {
+ Delete(trimmed);
+ return num;
+ }
+}
+
+
+void emit_stub_class(Node *n) {
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_stub_class: ENTER... '%s'(%x)\n", Getattr(n, "sym:name"), n);
+#endif
+
+
+ String *name = Getattr(n, "sym:name");
+
+ if (Getattr(n, "allegrocl:synonym:already-been-stubbed"))
+ return;
+
+ if (SwigType_istemplate(name)) {
+ String *temp = strip_namespaces(SwigType_templateprefix(name));
+ name = NewStringf("%s%s%s", temp, SwigType_templateargs(name), SwigType_templatesuffix(name));
+
+ Delete(temp);
+ } else {
+ name = strip_namespaces(name);
+ }
+
+ // Printf(f_clhead, ";; from emit-stub-class\n");
+ update_package_if_needed(n, f_clhead);
+ Printf(f_clhead, ";; class template stub.\n");
+ Printf(f_clhead, "(swig-def-foreign-stub \"%s\")\n", name);
+
+ Setattr(n, "allegrocl:synonym:already-been-stubbed", "1");
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_stub_class: EXIT\n");
+#endif
+}
+
+void emit_synonym(Node *synonym) {
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_synonym: ENTER... \n");
+#endif
+
+ // Printf(stderr,"in emit_synonym for %s(%x)\n", Getattr(synonym,"name"),synonym);
+ int is_tempInst = !Strcmp(nodeType(synonym), "templateInst");
+ String *synonym_type;
+
+ Node *of = get_primary_synonym_of(synonym);
+
+ if (is_tempInst) {
+ // Printf(stderr, "*** using real-name '%s'\n", Getattr(synonym,"real-name"));
+ synonym_type = Getattr(synonym, "real-name");
+ } else {
+ // Printf(stderr, "*** using name '%s'\n", Getattr(synonym,"name"));
+ synonym_type = Getattr(synonym, "name");
+ }
+
+ String *synonym_ns = listify_namespace(Getattr(synonym, "allegrocl:namespace"));
+ String *syn_ltype, *syn_type, *of_ltype;
+ // String *of_cdeclname = Getattr(of,"allegrocl:classDeclarationName");
+ String *of_ns = Getattr(of, "allegrocl:namespace");
+ String *of_ns_list = listify_namespace(of_ns);
+ // String *of_name = of_cdeclname ? NewStringf("struct %s", Getattr(of,"name")) : NewStringf("%s::%s", of_ns, Getattr(of,"sym:name"));
+ // String *of_name = NewStringf("%s::%s", of_ns, Getattr(of,"sym:name"));
+ String *of_name = namespaced_name(of, of_ns);
+
+ if (CPlusPlus && !Strcmp(nodeType(synonym), "cdecl")) {
+ syn_ltype = NewStringf("#.(swig-insert-id \"%s\" %s :type :class)",
+ strip_namespaces(Getattr(synonym, "real-name")), synonym_ns);
+ syn_type = NewStringf("#.(swig-insert-id \"%s\" %s :type :type)",
+ strip_namespaces(Getattr(synonym, "real-name")), synonym_ns);
+ } else {
+ syn_ltype = lookup_defined_foreign_ltype(synonym_type);
+ syn_type = lookup_defined_foreign_type(synonym_type);
+ }
+
+ of_ltype = lookup_defined_foreign_ltype(of_name);
+
+ // Printf(stderr,";; from emit-synonym syn='%s' of_ltype='%s'\n", syn_ltype, of_ltype);
+ if( of_ltype )
+ Printf(f_clhead, "(swig-def-synonym-type %s\n %s\n %s)\n", syn_ltype, of_ltype, syn_type);
+
+ Delete(synonym_ns);
+ Delete(of_ns_list);
+ Delete(of_name);
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_synonym: EXIT\n");
+#endif
+}
+
+void emit_full_class(Node *n) {
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_full_class: ENTER... \n");
+#endif
+
+ String *name = Getattr(n, "sym:name");
+ String *kind = Getattr(n, "kind");
+
+ // Printf(stderr,"in emit_full_class: '%s'(%x).", Getattr(n,"name"),n);
+ if (Getattr(n, "allegrocl:synonym-of")) {
+ // Printf(stderr,"but it's a synonym of something.\n");
+ update_package_if_needed(n, f_clhead);
+ emit_synonym(n);
+ return;
+ }
+ // collect superclasses
+ String *bases = Getattr(n, "bases");
+ String *supers = NewString("(");
+ if (bases) {
+ int first = 1;
+ for (Iterator i = First(bases); i.item; i = Next(i)) {
+ if (!first)
+ Printf(supers, " ");
+ String *s = lookup_defined_foreign_ltype(Getattr(i.item, "name"));
+ // String *name = Getattr(i.item,"name");
+ if (s) {
+ Printf(supers, "%s", s);
+ } else {
+#ifdef ALLEGROCL_TYPE_DEBUG
+ Printf(stderr, "emit_templ_inst: did not find ltype for base class %s (%s)", Getattr(i.item, "name"), Getattr(n, "allegrocl:namespace"));
+#endif
+ }
+ }
+ } else {
+ Printf(supers, "ff:foreign-pointer");
+ }
+
+ Printf(supers, ")");
+
+ // Walk children to generate type definition.
+ String *slotdefs = NewString(" ");
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, " walking children...\n");
+#endif
+
+ Node *c;
+ for (c = firstChild(n); c; c = nextSibling(c)) {
+ String *storage_type = Getattr(c, "storage");
+ if ((!Strcmp(nodeType(c), "cdecl") && (!storage_type || Strcmp(storage_type, "typedef")))) {
+ String *access = Getattr(c, "access");
+
+ // hack. why would decl have a value of "variableHandler" and now "0"?
+ String *childDecl = Getattr(c, "decl");
+ // Printf(stderr,"childDecl = '%s' (%s)\n", childDecl, Getattr(c,"view"));
+ if (!Strcmp(childDecl, "0"))
+ childDecl = NewString("");
+
+ SwigType *childType;
+ String *cname;
+
+ // don't include types for private slots (yet). spr33959.
+ if(access && Strcmp(access,"public")) {
+ childType = NewStringf("int");
+ cname = NewString("nil");
+ } else {
+ childType = NewStringf("%s%s", childDecl, Getattr(c, "type"));
+ cname = Copy(Getattr(c, "name"));
+ }
+
+ if (!SwigType_isfunction(childType)) {
+ // Printf(slotdefs, ";;; member functions don't appear as slots.\n ");
+ // Printf(slotdefs, ";; ");
+ String *ns = listify_namespace(Getattr(n, "allegrocl:package"));
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "slot name = '%s' ns = '%s' class-of '%s' and type = '%s'\n", cname, ns, name, childType);
+#endif
+ Printf(slotdefs, "(#.(swig-insert-id \"%s\" %s :type :slot :class \"%s\") %s)", cname, ns, name, compose_foreign_type(n, childType));
+ Delete(ns);
+ if (access && Strcmp(access, "public"))
+ Printf(slotdefs, " ;; %s member", access);
+
+ Printf(slotdefs, "\n ");
+ }
+ Delete(childType);
+ Delete(cname);
+ }
+ }
+
+ String *ns_list = listify_namespace(Getattr(n, "allegrocl:namespace"));
+ update_package_if_needed(n, f_clhead);
+ Printf(f_clhead, "(swig-def-foreign-class \"%s\"\n %s\n (:%s\n%s))\n\n", name, supers, kind, slotdefs);
+
+ Delete(supers);
+ Delete(ns_list);
+
+ Setattr(n, "allegrocl:synonym:already-been-stubbed", "1");
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_full_class: EXIT\n");
+#endif
+
+}
+
+void emit_class(Node *n) {
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_class: ENTER... '%s'(%x)\n", Getattr(n, "sym:name"), n);
+#endif
+
+ int is_tempInst = !Strcmp(nodeType(n), "templateInst");
+
+ String *ns_list = listify_namespace(Getattr(n, "allegrocl:namespace"));
+ String *name = Getattr(n, is_tempInst ? "real-name" : "name");
+
+ if (SwigType_istemplate(name)) {
+ String *temp = strip_namespaces(SwigType_templateprefix(name));
+ name = NewStringf("%s%s%s", temp, SwigType_templateargs(name), SwigType_templatesuffix(name));
+
+ Delete(temp);
+ } else {
+ name = strip_namespaces(name);
+ }
+
+ if (Getattr(n, "allegrocl:synonym:is-primary")) {
+ // Printf(stderr," is primary... ");
+ if (is_tempInst) {
+ emit_stub_class(n);
+ } else {
+ emit_full_class(n);
+ }
+ } else {
+ // Node *primary = Getattr(n,"allegrocl:synonym-of");
+ Node *primary = get_primary_synonym_of(n);
+ if (primary && (primary != n)) {
+ // Printf(stderr," emitting synonym... ");
+ emit_stub_class(primary);
+ update_package_if_needed(n, f_clhead);
+ emit_synonym(n);
+ } else {
+ emit_full_class(n);
+ }
+ }
+ // Printf(stderr,"DONE\n");
+ Delete(name);
+ Delete(ns_list);
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_class: EXIT\n");
+#endif
+}
+
+void emit_typedef(Node *n) {
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_typedef: ENTER... \n");
+#endif
+
+ String *name;
+ String *sym_name = Getattr(n, "sym:name");
+ String *type = NewStringf("%s%s", Getattr(n, "decl"), Getattr(n, "type"));
+ String *lisp_type = compose_foreign_type(n, type);
+ Delete(type);
+ Node *in_class = Getattr(n, "allegrocl:typedef:in-class");
+
+ // Printf(stderr,"in emit_typedef: '%s'(%x).",Getattr(n,"name"),n);
+ if (Getattr(n, "allegrocl:synonym-of")) {
+ // Printf(stderr," but it's a synonym of something.\n");
+ emit_synonym(n);
+ return;
+ }
+
+ if (in_class) {
+ String *class_name = Getattr(in_class, "name");
+ if (SwigType_istemplate(class_name)) {
+ String *temp = strip_namespaces(SwigType_templateprefix(class_name));
+ class_name = NewStringf("%s%s%s", temp, SwigType_templateargs(class_name), SwigType_templatesuffix(class_name));
+ Delete(temp);
+ }
+
+ name = NewStringf("%s__%s", class_name, sym_name);
+ Setattr(n, "allegrocl:in-class", in_class);
+ } else {
+ name = sym_name ? Copy(sym_name) : Copy(Getattr(n, "name"));
+ }
+
+ // leave these in for now. might want to change these to def-foreign-class at some point.
+// Printf(f_clhead, ";; %s\n", SwigType_typedef_resolve_all(lisp_type));
+ Printf(f_clhead, "(swig-def-foreign-type \"%s\"\n %s)\n", name, lisp_type);
+
+ Delete(name);
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_typedef: EXIT\n");
+#endif
+}
+
+void emit_enum_type_no_wrap(Node *n) {
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_enum_type_no_wrap: ENTER... \n");
+#endif
+
+ String *unnamed = Getattr(n, "unnamed");
+ String *name;
+ // SwigType *enumtype;
+
+ name = unnamed ? Getattr(n, "allegrocl:name") : Getattr(n, "sym:name");
+ SwigType *tmp = NewStringf("enum %s", unnamed ? unnamed : name);
+
+ Node *node = NewHash();
+ Setattr(node, "type", tmp);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *enumtype = Swig_typemap_lookup("ffitype", node, "", 0);
+ Delete(node);
+
+ Delete(tmp);
+
+ if (name) {
+ String *ns = listify_namespace(current_namespace);
+
+ Printf(f_clhead, "(swig-def-foreign-type \"%s\" %s)\n", name, enumtype);
+ Delete(ns);
+
+ // walk children.
+ Node *c;
+ for (c = firstChild(n); c; c = nextSibling(c)) {
+ if (!Getattr(c, "error")) {
+ String *val = Getattr(c, "enumvalue");
+ if (!val)
+ val = Getattr(c, "enumvalueex");
+ String *converted_val = convert_literal(val, Getattr(c, "type"));
+ String *valname = Getattr(c, "sym:name");
+
+ if (converted_val) {
+ Printf(f_clhead, "(swig-defconstant \"%s\" %s)\n", valname, converted_val);
+ Delete(converted_val);
+ } else {
+ Swig_warning(WARN_LANG_DISCARD_CONST, Getfile(n), Getline(n), "Unable to parse enum value '%s'. Setting to NIL\n", val);
+ Printf(f_clhead, "(swig-defconstant \"%s\" nil #| %s |#)\n", valname, val);
+ }
+ }
+ }
+ }
+ Printf(f_clhead, "\n");
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_enum_type_no_wrap: EXIT\n");
+#endif
+
+}
+
+void emit_enum_type(Node *n) {
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_enum_type: ENTER... \n");
+#endif
+
+ if (!Generate_Wrapper) {
+ emit_enum_type_no_wrap(n);
+ return;
+ }
+
+ String *unnamed = Getattr(n, "unnamed");
+ String *name;
+ // SwigType *enumtype;
+
+ name = unnamed ? Getattr(n, "allegrocl:name") : Getattr(n, "sym:name");
+ SwigType *tmp = NewStringf("enum %s", unnamed ? unnamed : name);
+
+ Node *node = NewHash();
+ Setattr(node, "type", tmp);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *enumtype = Swig_typemap_lookup("ffitype", node, "", 0);
+ Delete(node);
+
+ Delete(tmp);
+
+ if (name) {
+ String *ns = listify_namespace(current_namespace);
+
+ Printf(f_clhead, "(swig-def-foreign-type \"%s\" %s)\n", name, enumtype);
+ Delete(ns);
+
+ // walk children.
+ Node *c;
+ for(c = firstChild(n); c; c=nextSibling(c)) {
+ String *mangled_name = mangle_name(c, "ACL_ENUM", Getattr(c,"allegrocl:package"));
+ Printf(f_clhead, "(swig-defvar \"%s\" \"%s\" :type :constant :ftype :signed-long)\n", Getattr(c, "sym:name"), mangled_name);
+ Delete(mangled_name);
+ }
+ }
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_enum_type: EXIT\n");
+#endif
+
+}
+
+void emit_default_linked_type(Node *n) {
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_default_linked_type: ENTER... \n");
+#endif
+
+ // catchall for non class types.
+ if (!Strcmp(nodeType(n), "classforward")) {
+ Printf(f_clhead, ";; forward referenced stub.\n");
+ Printf(f_clhead, "(swig-def-foreign-class \"%s\" (ff:foreign-pointer) (:class ))\n\n", Getattr(n, "sym:name"));
+ } else if (!Strcmp(nodeType(n), "enum")) {
+ emit_enum_type(n);
+ } else {
+ Printf(stderr, "Don't know how to emit node type '%s' named '%s'\n", nodeType(n), Getattr(n, "name"));
+ }
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_default_linked_type: EXIT\n");
+#endif
+
+}
+
+void dump_linked_types(File *f) {
+ Node *n = first_linked_type;
+ int i = 0;
+ while (n) {
+ Printf(f, "%d: (%x) node '%s' name '%s'\n", i++, n, nodeType(n), Getattr(n, "sym:name"));
+
+ Node *t = Getattr(n, "allegrocl:synonym-of");
+ if (t)
+ Printf(f, " synonym-of %s(%x)\n", Getattr(t, "name"), t);
+ n = Getattr(n, "allegrocl:next_linked_type");
+ }
+}
+
+void emit_linked_types() {
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_linked_types: ENTER... ");
+#endif
+
+ Node *n = first_linked_type;
+
+ while (n) {
+ String *node_type = nodeType(n);
+
+ // Printf(stderr,"emitting node %s(%x) of type %s.", Getattr(n,"name"),n, nodeType(n));
+ if (!Strcmp(node_type, "class") || !Strcmp(node_type, "templateInst")) {
+ // may need to emit a stub, so it will update the package itself.
+ // Printf(stderr," Passing to emit_class.");
+ emit_class(n);
+ } else if (!Strcmp(nodeType(n), "cdecl")) {
+ // Printf(stderr," Passing to emit_typedef.");
+ update_package_if_needed(n, f_clhead);
+ emit_typedef(n);
+ } else {
+ // Printf(stderr," Passing to default_emitter.");
+ update_package_if_needed(n, f_clhead);
+ emit_default_linked_type(n);
+ }
+
+ n = Getattr(n, "allegrocl:next_linked_type");
+ // Printf(stderr,"returned.\n");
+ }
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_linked_types: EXIT\n");
+#endif
+}
+
+extern "C" Language *swig_allegrocl(void) {
+ return (allegrocl = new ALLEGROCL());
+}
+
+void ALLEGROCL::main(int argc, char *argv[]) {
+ int i;
+
+ Preprocessor_define("SWIGALLEGROCL 1", 0);
+ SWIG_library_directory("allegrocl");
+ SWIG_config_file("allegrocl.swg");
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-identifier-converter")) {
+ char *conv = argv[i + 1];
+
+ if (!conv)
+ Swig_arg_error();
+
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+
+ /* check for built-ins */
+ if (!strcmp(conv, "lispify")) {
+ identifier_converter = "identifier-convert-lispify";
+ } else if (!strcmp(conv, "null")) {
+ identifier_converter = "identifier-convert-null";
+ } else {
+ /* Must be user defined */
+ char *idconv = new char[strlen(conv) + 1];
+ strcpy(idconv, conv);
+ identifier_converter = idconv;
+ }
+ } else if (!strcmp(argv[i], "-cwrap")) {
+ CWrap = true;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i], "-nocwrap")) {
+ CWrap = false;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i], "-isolate")) {
+ unique_swig_package = true;
+ Swig_mark_arg(i);
+ }
+
+ if (!strcmp(argv[i], "-help")) {
+ fprintf(stdout, "Allegro CL Options (available with -allegrocl)\n");
+ fprintf(stdout,
+ " -identifier-converter <type or funcname>\n"
+ "\tSpecifies the type of conversion to do on C identifiers to convert\n"
+ "\tthem to symbols. There are two built-in converters: 'null' and\n"
+ "\t 'lispify'. The default is 'null'. If you supply a name other\n"
+ "\tthan one of the built-ins, then a function by that name will be\n"
+ "\tcalled to convert identifiers to symbols.\n"
+ "\n"
+ " -[no]cwrap\n"
+ "\tTurn on or turn off generation of an intermediate C file when\n" "\tcreating a C interface. By default this is only done for C++ code.\n"
+ " -isolate\n"
+ "Define all SWIG helper functions in a package unique to this module. Avoids redefinition warnings when loading multiple SWIGged modules\n"
+ "into the same running Allegro CL image.\n");
+
+ }
+
+ }
+
+ allow_overloading();
+}
+
+int ALLEGROCL::top(Node *n) {
+ module_name = Getattr(n, "name");
+ String *cxx_filename = Getattr(n, "outfile");
+ String *cl_filename = NewString("");
+
+ swig_package = unique_swig_package ? NewStringf("swig.%s", module_name) : NewString("swig");
+
+ Printf(cl_filename, "%s%s.cl", SWIG_output_directory(), module_name);
+
+ f_cl = NewFile(cl_filename, "w", SWIG_output_files());
+ if (!f_cl) {
+ Printf(stderr, "Unable to open %s for writing\n", cl_filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ Generate_Wrapper = CPlusPlus || CWrap;
+
+ if (Generate_Wrapper) {
+ f_begin = NewFile(cxx_filename, "w", SWIG_output_files());
+ if (!f_begin) {
+ Close(f_cl);
+ Delete(f_cl);
+ Printf(stderr, "Unable to open %s for writing\n", cxx_filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ } else
+ f_begin = NewString("");
+
+ f_runtime = NewString("");
+ f_cxx_header = f_runtime;
+ f_cxx_wrapper = NewString("");
+
+ Swig_register_filebyname("header", f_cxx_header);
+ Swig_register_filebyname("wrapper", f_cxx_wrapper);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("lisp", f_clwrap);
+ Swig_register_filebyname("lisphead", f_cl);
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n");
+ Printf(f_runtime, "#define SWIGALLEGROCL\n");
+ Printf(f_runtime, "\n");
+
+ Swig_banner_target_lang(f_cl, ";;");
+
+ Printf(f_cl, "\n"
+ "(defpackage :%s\n"
+ " (:use :common-lisp :ff :excl)\n"
+ " (:export #:*swig-identifier-converter* #:*swig-module-name*\n"
+ " #:*void* #:*swig-export-list*))\n"
+ "(in-package :%s)\n\n"
+ "(eval-when (:compile-toplevel :load-toplevel :execute)\n"
+ " (defparameter *swig-identifier-converter* '%s)\n"
+ " (defparameter *swig-module-name* :%s))\n\n", swig_package, swig_package, identifier_converter, module_name);
+ Printf(f_cl, "(defpackage :%s\n" " (:use :common-lisp :%s :ff :excl))\n\n", module_name, swig_package);
+
+ Printf(f_clhead, "(in-package :%s)\n", module_name);
+
+ // Swig_print_tree(n);
+
+ Language::top(n);
+
+ // SwigType_emit_type_table(f_runtime,f_cxx_wrapper);
+
+ // Swig_print_tree(n);
+#ifdef ALLEGROCL_TYPE_DEBUG
+ dump_linked_types(stderr);
+#endif
+ emit_linked_types();
+
+ Printf(f_clwrap, "\n(cl::in-package :%s)\n", swig_package);
+ Printf(f_clwrap, "\n(macrolet ((swig-do-export ()\n");
+ Printf(f_clwrap, " `(dolist (s ',*swig-export-list*)\n");
+ Printf(f_clwrap, " (apply #'export s))))\n");
+ Printf(f_clwrap, " (swig-do-export))\n");
+ Printf(f_clwrap, "\n(setq *swig-export-list* nil)\n");
+
+ Printf(f_cl, "%s\n", f_clhead);
+ Printf(f_cl, "%s\n", f_clwrap);
+
+ Close(f_cl);
+ Delete(f_cl); // Delete the handle, not the file
+ Delete(f_clhead);
+ Delete(f_clwrap);
+
+ Dump(f_runtime, f_begin);
+ Printf(f_begin, "%s\n", f_cxx_wrapper);
+
+ Close(f_begin);
+ Delete(f_runtime);
+ Delete(f_begin);
+ Delete(f_cxx_wrapper);
+
+ // Swig_print_tree(n);
+
+ return SWIG_OK;
+}
+
+/* very shamelessly 'borrowed' from overload.cxx, which
+ keeps the below Swig_overload_rank() code to itself.
+ We don't need a dispatch function in the C++ wrapper
+ code; we want it over on the lisp side. */
+
+#define MAX_OVERLOAD 256
+
+/* 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 */
+};
+
+/* -----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------- */
+
+static 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")) {
+ 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)) {
+ // 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 (no type checking rule 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 (no type checking rule 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 %s(%s) const ignored. Non-const method at %s:%d used.\n",
+ Getattr(nodes[j].n, "name"), ParmList_errorstr(nodes[j].parms), Getfile(nodes[i].n), Getline(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(%s) ignored. Method %s(%s) const at %s:%d used.\n",
+ Getattr(nodes[j].n, "name"), ParmList_errorstr(nodes[j].parms),
+ Getattr(nodes[i].n, "name"), ParmList_errorstr(nodes[i].parms), Getfile(nodes[i].n), Getline(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 %s(%s) const ignored. Non-const method at %s:%d used.\n",
+ Getattr(nodes[j].n, "name"), ParmList_errorstr(nodes[j].parms), Getfile(nodes[i].n), Getline(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(%s) const ignored. Method %s(%s) at %s:%d used.\n",
+ Getattr(nodes[j].n, "name"), ParmList_errorstr(nodes[j].parms),
+ Getattr(nodes[i].n, "name"), ParmList_errorstr(nodes[i].parms), Getfile(nodes[i].n), Getline(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 is shadowed by %s at %s:%d.\n",
+ Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n),
+ Getfile(nodes[i].n), Getline(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. Method %s at %s:%d used.\n",
+ Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n),
+ Getfile(nodes[i].n), Getline(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;
+}
+
+/* end shameless borrowing */
+
+int any_varargs(ParmList *pl) {
+ Parm *p;
+
+ for (p = pl; p; p = nextSibling(p)) {
+ if (SwigType_isvarargs(Getattr(p, "type")))
+ return 1;
+ }
+
+ return 0;
+}
+
+String *get_lisp_type(Node *n, SwigType *ty, const_String_or_char_ptr name) {
+ Node *node = NewHash();
+ Setattr(node, "type", ty);
+ Setattr(node, "name", name);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *tm = Swig_typemap_lookup("lisptype", node, "", 0);
+ Delete(node);
+
+ return tm ? NewString(tm) : NewString("");
+}
+
+Node *parent_node_skipping_extends(Node *n) {
+ Node *result = n;
+ do {
+ result = parentNode(result);
+ }
+ while (Cmp("extend", nodeType(result)) == 0);
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * emit_num_lin_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_lin_arguments(ParmList *parms) {
+ Parm *p = parms;
+ int nargs = 0;
+
+ while (p) {
+ // Printf(stderr,"enla: '%s' lin='%x'\n", Getattr(p,"name"), Getattr(p,"tmap:lin"));
+ if (Getattr(p, "tmap:lin")) {
+ nargs += GetInt(p, "tmap:lin:numinputs");
+ p = Getattr(p, "tmap:lin: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;
+}
+
+String *id_converter_type(SwigType const *type) {
+ SwigType *t = Copy(type);
+ String *result = 0;
+
+ if (SwigType_ispointer(t)) {
+ SwigType_pop(t);
+ String *pointee = id_converter_type(t);
+ result = NewStringf("(:* %s)", pointee);
+ Delete(pointee);
+ } else if (SwigType_ismemberpointer(t)) {
+ String *klass = SwigType_parm(t);
+ SwigType_pop(t);
+ String *member = id_converter_type(t);
+ result = NewStringf("(:member \"%s\" %s)", klass, member);
+ Delete(klass);
+ Delete(member);
+ } else if (SwigType_isreference(t)) {
+ SwigType_pop(t);
+ String *referencee = id_converter_type(t);
+ result = NewStringf("(:& %s)", referencee);
+ Delete(referencee);
+ } else if (SwigType_isarray(t)) {
+ String *size = SwigType_parm(t);
+ SwigType_pop(t);
+ String *element_type = id_converter_type(t);
+ result = NewStringf("(:array %s \"%s\")", element_type, size);
+ Delete(size);
+ Delete(element_type);
+ } else if (SwigType_isfunction(t)) {
+ result = NewString("(:function (");
+ String *parmlist_str = SwigType_parm(t);
+ List *parms = SwigType_parmlist(parmlist_str);
+
+ for (Iterator i = First(parms); i.item;) {
+ String *parm = id_converter_type((SwigType *) i.item);
+ Printf(result, "%s", parm);
+ i = Next(i);
+ if (i.item)
+ Printf(result, " ");
+ Delete(parm);
+ }
+ SwigType_pop(t);
+ String *ret = id_converter_type(t);
+ Printf(result, ") %s)", ret);
+
+ Delete(parmlist_str);
+ Delete(parms);
+ Delete(ret);
+ } else if (SwigType_isqualifier(t)) {
+ result = NewString("(:qualified (");
+ String *qualifiers_str = Copy(SwigType_parm(t)); // ?!
+ // Replaceall below SEGVs if we don't put the Copy here...
+ SwigType_pop(t);
+ String *qualifiee = id_converter_type(t);
+
+ Replaceall(qualifiers_str, " ", " :");
+ if (Len(qualifiers_str) > 0)
+ Printf(result, ":");
+ Printf(result, "%s) %s)", qualifiers_str, qualifiee);
+
+ Delete(qualifiers_str);
+ Delete(qualifiee);
+ } else if (SwigType_istemplate(t)) {
+ result = NewStringf("(:template \"%s\")", t);
+ } else { /* if (SwigType_issimple(t)) */
+
+ if (Strstr(Char(t), "::")) {
+ result = listify_namespace(t);
+ } else {
+ result = NewStringf("\"%s\"", t);
+ }
+ }
+
+ Delete(t);
+ return result;
+}
+
+static ParmList *parmlist_with_names(ParmList *pl) {
+ ParmList *pl2 = CopyParmList(pl);
+ for (Parm *p = pl, *p2 = pl2; p2; p = nextSibling(p), p2 = nextSibling(p2)) {
+ if (!Getattr(p2, "name"))
+ Setattr(p2, "name", Getattr(p2, "lname"));
+ Setattr(p2, "name", strip_namespaces(Getattr(p2, "name")));
+ Setattr(p2, "tmap:ctype", Getattr(p, "tmap:ctype"));
+
+ String *temp = Getattr(p, "tmap:lin");
+ if (temp) {
+ Setattr(p2, "tmap:lin", temp);
+ Setattr(p2, "tmap:lin:next", Getattr(p, "tmap:lin:next"));
+ }
+ }
+ return pl2;
+}
+
+static String *parmlist_str_id_converter(ParmList *pl) {
+ String *result = NewString("");
+ for (Parm *p = pl; p;) {
+ String *lispy_type = id_converter_type(Getattr(p, "type"));
+ Printf(result, "(\"%s\" %s)", Getattr(p, "name"), lispy_type);
+ Delete(lispy_type);
+ if ((p = nextSibling(p)))
+ Printf(result, " ");
+ }
+ return result;
+}
+
+String *collect_others_args(Node *overload) {
+ String *overloaded_from = Getattr(overload, "sym:overloaded");
+ String *others_args = NewString("");
+ int first_overload = 1;
+
+ for (Node *overload2 = overloaded_from; overload2; overload2 = Getattr(overload2, "sym:nextSibling")) {
+ if (overload2 == overload || GetInt(overload2, "overload:ignore"))
+ continue;
+
+ ParmList *opl = parmlist_with_names(Getattr(overload2, "wrap:parms"));
+ String *args = parmlist_str_id_converter(opl);
+ if (!first_overload)
+ Printf(others_args, "\n ");
+ Printf(others_args, "(%s)", args);
+ Delete(args);
+ Delete(opl);
+ first_overload = 0;
+ }
+ return others_args;
+}
+
+struct IDargs {
+ String *name;
+ String *type;
+ String *klass;
+ String *arity;
+
+ IDargs():name(0), type(0), klass(0), arity(0) {
+ }
+
+ String *full_quoted_str() {
+ String *result = no_others_quoted_str();
+ if (arity)
+ Printf(result, " :arity %s", arity);
+ return result;
+ }
+
+ String *no_others_quoted_str() {
+ String *result = NewString("");
+ Printf(result, "\"%s\" :type :%s", name, type);
+ if (klass)
+ Printf(result, " :class \"%s\"", klass);
+ return result;
+ }
+
+ String *noname_str() {
+ String *result = NewString("");
+ Printf(result, " :type :%s", type);
+ if (klass)
+ Printf(result, " :class \"%s\"", klass);
+ if (arity)
+ Printf(result, " :arity %s", arity);
+ return result;
+ }
+};
+IDargs *id_converter_arguments(Node *n) {
+ IDargs *result = (IDargs *) GetVoid(n, "allegrocl:id-converter-args");
+ if (!result)
+ result = new IDargs;
+
+ // Base name
+ if (!result->name) {
+ result->name = Getattr(n, "allegrocl:old-sym:name");
+ if (!result->name)
+ result->name = Getattr(n, "sym:name");
+ result->name = Copy(result->name);
+ }
+ // :type
+ if (result->type)
+ Delete(result->type);
+ if (!Getattr(n, "allegrocl:kind"))
+ Setattr(n, "allegrocl:kind", "function");
+ if (Strstr(Getattr(n, "name"), "operator "))
+ Replaceall(Getattr(n, "allegrocl:kind"), "function", "operator");
+ if (Strstr(Getattr(n, "allegrocl:kind"), "variable")) {
+ int name_end = Len(Getattr(n, "sym:name")) - 4;
+ char *str = Char(Getattr(n, "sym:name"));
+ String *get_set = NewString(str + name_end + 1);
+ result->type = Copy(Getattr(n, "allegrocl:kind"));
+ Replaceall(result->type, "variable", "");
+ Printf(result->type, "%ster", get_set);
+ Delete(get_set);
+ } else {
+ result->type = Copy(Getattr(n, "allegrocl:kind"));
+ }
+
+ // :class
+ if (Strstr(result->type, "member ")) {
+ Replaceall(result->type, "member ", "");
+ if (!result->klass)
+ result->klass = Copy(Getattr(parent_node_skipping_extends(n), "sym:name"));
+ }
+ // :arity
+ if (Getattr(n, "sym:overloaded")) {
+ if (result->arity)
+ Delete(result->arity);
+ result->arity = NewStringf("%d",
+ // emit_num_arguments(Getattr(n, "wrap:parms")));
+ emit_num_lin_arguments(Getattr(n, "wrap:parms")));
+ // Printf(stderr, "got arity of '%s' node '%s' '%x'\n", result->arity, Getattr(n,"name"), Getattr(n,"wrap:parms"));
+ }
+
+ SetVoid(n, "allegrocl:id-converter-args", result);
+ return result;
+}
+
+int ALLEGROCL::emit_buffered_defuns(Node *n) {
+
+ Node *overloaded_from = Getattr(n, "sym:overloaded");
+
+ String *wrap;
+
+ if (!overloaded_from) {
+ wrap = Getattr(n, "allegrocl:lisp-wrap");
+
+ Printf(f_clwrap, "%s\n", wrap);
+ Delattr(n, "allegrocl:lisp-wrap");
+ Delete(wrap);
+ } else {
+ for (Node *overload = overloaded_from; overload; overload = Getattr(overload, "sym:nextSibling")) {
+ String *others_args = collect_others_args(overload);
+ wrap = Getattr(overload, "allegrocl:lisp-wrap");
+
+ Replaceall(wrap, "@@OTHERS-ARGS-GO-HERE@@", others_args);
+// IDargs* id_args = id_converter_arguments(overload);
+// Replaceall(id_args->others_args, "@@OTHERS-ARGS-GO-HERE@@", others_args);
+
+ if (!GetInt(overload, "overload:ignore"))
+ Printf(f_clwrap, "%s", wrap);
+
+ Delattr(overload, "allegrocl:lisp-wrap");
+ Delete(wrap);
+ }
+ }
+ return SWIG_OK;
+}
+
+String *dispatching_type(Node *n, Parm *p) {
+ String *result = 0;
+
+ String *parsed = Getattr(p, "type"); //Swig_cparse_type(Getattr(p,"tmap:ctype"));
+ String *cl_t = SwigType_typedef_resolve_all(parsed);
+
+ Node *node = NewHash();
+ Setattr(node, "type", parsed);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *tm = Swig_typemap_lookup("lispclass", node, Getattr(p, "name"), 0);
+ Delete(node);
+
+ if (tm) {
+ result = Copy(tm);
+ } else {
+ String *lookup_type = class_from_class_or_class_ref(parsed);
+ if (lookup_type)
+ result = lookup_defined_foreign_ltype(lookup_type);
+ }
+
+ // if (!result && SwigType_ispointer(cl_t)) {
+ // SwigType_pop(cl_t);
+ // result = lookup_defined_foreign_ltype(cl_t);
+ // }
+
+ if (!result)
+ result = NewStringf("ff:foreign-pointer");
+
+ // Delete(parsed);
+ Delete(cl_t);
+ return result;
+}
+
+int ALLEGROCL::emit_dispatch_defun(Node *n) {
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_dispatch_defun: ENTER... ");
+#endif
+ List *overloads = Swig_overload_rank(n, true);
+
+ String *id_args = id_converter_arguments(n)->no_others_quoted_str();
+ Printf(f_clwrap, "(swig-dispatcher (%s :arities (", id_args);
+
+ int last_arity = -1;
+ for (Iterator i = First(overloads); i.item; i = Next(i)) {
+ int arity = emit_num_lin_arguments(Getattr(i.item, "wrap:parms"));
+ if (arity == last_arity)
+ continue;
+
+ Printf(f_clwrap, "%s%d", last_arity == -1 ? "" : " ", arity);
+
+ last_arity = arity;
+ }
+ Printf(f_clwrap, ")))\n");
+
+ Delete(id_args);
+ Delete(overloads);
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_dispatch_defun: EXIT\n");
+#endif
+
+ return SWIG_OK;
+}
+
+int ALLEGROCL::emit_defun(Node *n, File *fcl) {
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_defun: ENTER... ");
+#endif
+
+#ifdef ALLEGROCL_DEBUG
+ int auto_generated = Cmp(Getattr(n, "view"), "globalfunctionHandler");
+ Printf(stderr, "%s%sfunction %s%s%s\n", auto_generated ? "> " : "", Getattr(n, "sym:overloaded")
+ ? "overloaded " : "", current_namespace, (current_namespace) > 0 ? "::" : "", Getattr(n, "sym:name"));
+ Printf(stderr, " (view: %s)\n", Getattr(n, "view"));
+#endif
+
+ String *funcname = Getattr(n, "allegrocl:old-sym:name");
+ if (!funcname)
+ funcname = Getattr(n, "sym:name");
+ String *mangled_name = Getattr(n, "wrap:name");
+ ParmList *pl = parmlist_with_names(Getattr(n, "wrap:parms"));
+
+ // attach typemap info.
+ Wrapper *wrap = NewWrapper();
+ Swig_typemap_attach_parms("lin", pl, wrap);
+ // Swig_typemap_attach_parms("ffitype", pl, wrap);
+ Swig_typemap_lookup("lout", n, "result", 0);
+
+ SwigType *result_type = Swig_cparse_type(Getattr(n, "tmap:ctype"));
+ // prime the pump, with support for OUTPUT, INOUT typemaps.
+ Printf(wrap->code,
+ "(cl::let ((ACL_ffresult %s:*void*)\n ACL_result)\n $body\n (cl::if (cl::eq ACL_ffresult %s:*void*)\n (cl::values-list ACL_result)\n (cl::values-list (cl::cons ACL_ffresult ACL_result))))",
+ swig_package, swig_package);
+
+ Parm *p;
+ int largnum = 0, argnum = 0, first = 1;
+ // int varargs=0;
+ if (Generate_Wrapper) {
+ String *extra_parms = id_converter_arguments(n)->noname_str();
+ if (Getattr(n, "sym:overloaded"))
+ Printf(fcl, "(swig-defmethod (\"%s\" \"%s\"%s)\n", funcname, mangled_name, extra_parms);
+ else
+ Printf(fcl, "(swig-defun (\"%s\" \"%s\"%s)\n", funcname, mangled_name, extra_parms);
+ Delete(extra_parms);
+ }
+ // Just C
+ else {
+ Printf(fcl, "(swig-defun (\"%s\" \"%s\")\n", funcname, Generate_Wrapper ? mangled_name : funcname);
+ }
+
+ //////////////////////////////////////
+ // Lisp foreign call parameter list //
+ //////////////////////////////////////
+ Printf(fcl, " (");
+
+ /* Special cases */
+
+ if (ParmList_len(pl) == 0) {
+ Printf(fcl, ":void");
+/* } else if (any_varargs(pl)) {
+ Printf(fcl, "#| varargs |#");
+ varargs=1; */
+ } else {
+ String *largs = NewString("");
+
+ for (p = pl; p; p = nextSibling(p), argnum++, largnum++) {
+ // SwigType *argtype=Getattr(p, "type");
+ SwigType *argtype = Swig_cparse_type(Getattr(p, "tmap:ctype"));
+ SwigType *parmtype = Getattr(p,"type");
+
+ if (!first) {
+ Printf(fcl, "\n ");
+ }
+
+ /* by default, skip varargs */
+ if (!SwigType_isvarargs(parmtype)) {
+ String *argname = NewStringf("PARM%d_%s", largnum, Getattr(p, "name"));
+
+ // Printf(stderr,"%s\n", Getattr(p,"tmap:lin"));
+ String *ffitype = compose_foreign_type(n, argtype, Getattr(p,"name"));
+ String *deref_ffitype = dereference_ffitype(ffitype);
+ String *lisptype = get_lisp_type(n, parmtype, Getattr(p, "name"));
+
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "lisptype of '%s' '%s' = '%s'\n", parmtype,
+ Getattr(p, "name"), lisptype);
+#endif
+
+ // while we're walking the parameters, generating LIN
+ // wrapper code...
+ Setattr(p, "lname", NewStringf("SWIG_arg%d", largnum));
+
+ String *parm_code = Getattr(p, "tmap:lin");
+ if (parm_code) {
+ String *lname = Getattr(p, "lname");
+
+ Printf(largs, " %s", lname);
+ Replaceall(parm_code, "$in_fftype", ffitype); // must come before $in
+ Replaceall(parm_code, "$in", argname);
+ Replaceall(parm_code, "$out", lname);
+ Replaceall(parm_code, "$*in_fftype", deref_ffitype);
+ Replaceall(wrap->code, "$body", parm_code);
+ }
+
+ String *dispatchtype = Getattr(n, "sym:overloaded") ? dispatching_type(n, p) : NewString("");
+
+ // if this parameter has been removed from the C/++ wrapper
+ // it shouldn't be in the lisp wrapper either.
+ if (!checkAttribute(p, "tmap:in:numinputs", "0")) {
+ Printf(fcl, "(%s %s %s %s %s)",
+ // parms in the ff wrapper, but not in the lisp wrapper.
+ (checkAttribute(p, "tmap:lin:numinputs", "0") ? ":p-" : ":p+"), argname, dispatchtype, ffitype, lisptype);
+
+ first = 0;
+ }
+
+ Delete(argname);
+ Delete(ffitype);
+ Delete(deref_ffitype);
+ Delete(lisptype);
+ }
+ }
+
+ Printf(wrap->locals, "%s", largs);
+ }
+
+ String *lout = Getattr(n, "tmap:lout");
+ Replaceall(lout, "$owner", GetFlag(n, "feature:new") ? "t" : "nil");
+
+ Replaceall(wrap->code, "$body", lout);
+ // $lclass handling.
+ String *lclass = (String *) 0;
+ SwigType *parsed = Swig_cparse_type(Getattr(n, "tmap:ctype"));
+ // SwigType *cl_t = SwigType_typedef_resolve_all(parsed);
+ SwigType *cl_t = class_from_class_or_class_ref(parsed);
+ String *out_ffitype = compose_foreign_type(n, parsed);
+ String *deref_out_ffitype;
+ String *out_temp = Copy(parsed);
+
+ if (SwigType_ispointer(out_temp)) {
+ SwigType_pop(out_temp);
+ deref_out_ffitype = compose_foreign_type(n, out_temp);
+ } else {
+ deref_out_ffitype = Copy(out_ffitype);
+ }
+
+ Delete(out_temp);
+
+ Delete(parsed);
+
+ int isPtrReturn = 0;
+
+ if (cl_t) {
+ lclass = lookup_defined_foreign_ltype(cl_t);
+ isPtrReturn = 1;
+ }
+
+ int ff_foreign_ptr = 0;
+ if (!lclass) {
+ ff_foreign_ptr = 1;
+ lclass = NewStringf("ff:foreign-pointer");
+ }
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "for output wrapping %s: type=%s, ctype=%s\n", Getattr(n, "name"),
+ Getattr(n, "type"), Swig_cparse_type(Getattr(n, "tmap:ctype")));
+#endif
+
+ if (lclass)
+ Replaceall(wrap->code, "$lclass", lclass);
+ if (out_ffitype)
+ Replaceall(wrap->code, "$out_fftype", out_ffitype);
+ if (deref_out_ffitype)
+ Replaceall(wrap->code, "$*out_fftype", deref_out_ffitype);
+ // if(Replaceall(wrap->code,"$lclass", lclass) && !isPtrReturn) {
+ // Swig_warning(WARN_LANG_RETURN_TYPE,Getfile(n), Getline(n),
+ // "While Wrapping %s, replaced a $lclass reference when return type is non-pointer %s!\n",
+ // Getattr(n,"name"), cl_t);
+ // }
+
+ Replaceall(wrap->code, "$body", NewStringf("(swig-ff-call%s)", wrap->locals));
+// Replaceall(wrap->code,"$body",
+// (!Strcmp(result_type,"void") ?
+// NewStringf("(swig-ff-call%s)", wrap->locals) :
+// NewStringf("(push (swig-ff-call%s) ACL_result)", wrap->locals)));
+ String *ldestructor = Copy(lclass);
+ if (ff_foreign_ptr)
+ Replaceall(ldestructor, ldestructor, "identity");
+ else
+ Replaceall(ldestructor, ":type :class", ":type :destructor");
+ Replaceall(wrap->code, "$ldestructor", ldestructor);
+ Delete(ldestructor);
+
+ Printf(fcl, ")\n"); /* finish arg list */
+
+ /////////////////////////////////////////////////////
+ // Lisp foreign call return type and optimizations //
+ /////////////////////////////////////////////////////
+ Printf(fcl, " (:returning (%s %s)", compose_foreign_type(n, result_type), get_lisp_type(n, Getattr(n, "type"), "result"));
+
+ for (Iterator option = First(n); option.item; option = Next(option)) {
+ if (Strncmp("feature:ffargs:", option.key, 15))
+ continue;
+ String *option_val = option.item;
+ String *option_name = NewString(Char(option.key) + 14);
+ Replaceall(option_name, "_", "-");
+
+ // TODO: varargs vs call-direct ?
+ Printf(fcl, "\n %s %s", option_name, option_val);
+
+ Delete(option_name);
+ }
+
+ Printf(fcl, ")\n %s)\n\n", wrap->code);
+ // Wrapper_print(wrap, stderr);
+
+ Delete(result_type);
+ Delete(mangled_name);
+ Delete(pl);
+ DelWrapper(wrap);
+
+#ifdef ALLEGROCL_WRAP_DEBUG
+ Printf(stderr, "emit_defun: EXIT\n");
+#endif
+
+ return SWIG_OK;
+}
+
+int ALLEGROCL::functionWrapper(Node *n) {
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "functionWrapper %s\n", Getattr(n,"name"));
+ Swig_print_node(n);
+#endif
+
+
+ ParmList *parms = CopyParmList(Getattr(n, "parms"));
+ Wrapper *f = NewWrapper();
+ SwigType *t = Getattr(n, "type");
+ String *name = Getattr(n, "name");
+
+ String *raw_return_type = Swig_typemap_lookup("ctype", n, "", 0);
+ SwigType *return_type = Swig_cparse_type(raw_return_type);
+ SwigType *resolved = SwigType_typedef_resolve_all(return_type);
+ int is_void_return = (Cmp(resolved, "void") == 0);
+
+ Delete(resolved);
+
+ if (!is_void_return) {
+ String *lresult_init =
+ NewStringf("= (%s)0",
+ SwigType_str(SwigType_strip_qualifiers(return_type),0));
+ Wrapper_add_localv(f, "lresult",
+ SwigType_lstr(SwigType_ltype(return_type), "lresult"),
+ lresult_init, NIL);
+ Delete(lresult_init);
+ }
+ // Emit all of the local variables for holding arguments.
+ emit_parameter_variables(parms, f);
+
+ // Attach the standard typemaps
+ Swig_typemap_attach_parms("ctype", parms, f);
+ Swig_typemap_attach_parms("lin", parms, f);
+ emit_attach_parmmaps(parms, f);
+
+ String *mangled = mangle_name(n);
+ Node *overloaded = Getattr(n, "sym:overloaded");
+
+ // Parameter overloading
+ Setattr(n, "wrap:parms", parms);
+ Setattr(n, "wrap:name", mangled);
+
+ if (overloaded) {
+ // emit warnings when overloading is impossible on the lisp side.
+ // basically Swig_overload_check(n), but with script_lang_wrapping
+ // set to true.
+ Delete(Swig_overload_rank(n, true));
+ if (Getattr(n, "overload:ignore")) {
+ // if we're the last overload, make sure to force the emit
+ // of the rest of the overloads before we leave.
+ Printf(stderr, "ignored overload %s(%x)\n", name, Getattr(n, "sym:nextSibling"));
+ if (!Getattr(n, "sym:nextSibling")) {
+ update_package_if_needed(n);
+ emit_buffered_defuns(n);
+ emit_dispatch_defun(n);
+ }
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+ }
+ // Get number of required and total arguments
+ int num_arguments = emit_num_arguments(parms);
+ int gencomma = 0;
+
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "Walking parameters for %s '%s'\n", Getattr(n, "allegrocl:kind"), name);
+#endif
+ // Now walk the function parameter list and generate code to get arguments
+ String *name_and_parms = NewStringf("%s (", mangled);
+ int i;
+ Parm *p;
+ for (i = 0, p = parms; i < num_arguments; i++) {
+
+ while (p && checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ if (!p)
+ break;
+
+ SwigType *c_parm_type = Swig_cparse_type(Getattr(p, "tmap:ctype"));
+ String *arg = NewStringf("l%s", Getattr(p, "lname"));
+
+ // Emit parameter declaration
+ if (gencomma)
+ Printf(name_and_parms, ", ");
+ String *parm_decl = SwigType_str(c_parm_type, arg);
+ Printf(name_and_parms, "%s", parm_decl);
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, " param: %s\n", parm_decl);
+#endif
+ Delete(parm_decl);
+ gencomma = 1;
+
+ // Emit parameter conversion code
+ String *parm_code = Getattr(p, "tmap:in");
+ //if (!parm_code) {
+ // Swig_warning(...);
+ // p = nextSibling(p);
+ /*} else */ {
+ // canThrow(n, "in", p);
+ Replaceall(parm_code, "$input", arg);
+ Setattr(p, "emit:input", arg);
+ Printf(f->code, "%s\n", parm_code);
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Delete(arg);
+ }
+ Printf(name_and_parms, ")");
+
+ // Emit the function definition
+ String *signature = SwigType_str(return_type, name_and_parms);
+ Printf(f->def, "EXPORT %s {", signature);
+ if (CPlusPlus)
+ Printf(f->code, " try {\n");
+
+ String *actioncode = emit_action(n);
+
+ String *tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode);
+ if (!is_void_return && tm) {
+ if (tm) {
+ Replaceall(tm, "$result", "lresult");
+ Printf(f->code, "%s\n", tm);
+ Printf(f->code, " return lresult;\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(t, 0), name);
+ }
+ }
+
+ emit_return_variable(n, t, f);
+
+ if (CPlusPlus) {
+ Printf(f->code, " } catch (...) {\n");
+ if (!is_void_return)
+ Printf(f->code, " return (%s)0;\n",
+ SwigType_str(SwigType_strip_qualifiers(return_type),0));
+ Printf(f->code, " }\n");
+ }
+ Printf(f->code, "}\n");
+
+ /* print this when in C mode? make this a command-line arg? */
+ if (Generate_Wrapper)
+ Wrapper_print(f, f_cxx_wrapper);
+
+ String *f_buffer = NewString("");
+
+ emit_defun(n, f_buffer);
+ Setattr(n, "allegrocl:lisp-wrap", f_buffer);
+
+ if (!overloaded || !Getattr(n, "sym:nextSibling")) {
+ update_package_if_needed(n);
+ emit_buffered_defuns(n);
+ // this is the last overload.
+ if (overloaded) {
+ emit_dispatch_defun(n);
+ }
+ }
+
+ DelWrapper(f);
+
+ return SWIG_OK;
+}
+
+int ALLEGROCL::namespaceDeclaration(Node *n) {
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "namespaceDecl: '%s'(0x%x) (fc=0x%x)\n", Getattr(n, "sym:name"), n, firstChild(n));
+#endif
+
+ /* don't wrap a namespace with no contents. package bloat.
+ also, test-suite/namespace_class.i claims an unnamed namespace
+ is 'private' and should not be wrapped. Complying...
+ */
+ if (Getattr(n,"unnamed") || !firstChild(n))
+ return SWIG_OK;
+
+ String *name = Getattr(n, "sym:name");
+
+ String *old_namespace = current_namespace;
+ if (Cmp(current_namespace, "") == 0)
+ current_namespace = NewStringf("%s", name);
+ else
+ current_namespace = NewStringf("%s::%s", current_namespace, name);
+
+ if (!GetInt(defined_namespace_packages, current_namespace)) {
+ SetInt(defined_namespace_packages, current_namespace, 1);
+ String *lispy_namespace = listify_namespace(current_namespace);
+ Printf(f_clhead, "(swig-defpackage %s)\n", lispy_namespace);
+ Delete(lispy_namespace);
+ }
+
+ emit_children(n);
+
+ Delete(current_namespace);
+ current_namespace = old_namespace;
+ return SWIG_OK;
+}
+
+int ALLEGROCL::constructorHandler(Node *n) {
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "constructorHandler %s\n", Getattr(n, "name"));
+#endif
+ // Swig_print_node(n);
+ Setattr(n, "allegrocl:kind", "constructor");
+ Setattr(n, "allegrocl:old-sym:name", Getattr(n, "sym:name"));
+
+ // Let SWIG generate a global forwarding function.
+ return Language::constructorHandler(n);
+}
+
+int ALLEGROCL::destructorHandler(Node *n) {
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "destructorHandler %s\n", Getattr(n, "name"));
+#endif
+
+ Setattr(n, "allegrocl:kind", "destructor");
+ Setattr(n, "allegrocl:old-sym:name", Getattr(n, "sym:name"));
+
+ // Let SWIG generate a global forwarding function.
+ return Language::destructorHandler(n);
+}
+
+int ALLEGROCL::constantWrapper(Node *n) {
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "constantWrapper %s\n", Getattr(n, "name"));
+#endif
+
+ if (Generate_Wrapper) {
+ // Setattr(n,"wrap:name",mangle_name(n, "ACLPP"));
+ String *const_type = Getattr(n, "type");
+
+ String *const_val = 0;
+ String *raw_const = Getattr(n, "value");
+
+ if (SwigType_type(const_type) == T_STRING) {
+ const_val = NewStringf("\"%s\"", raw_const);
+ } else if (SwigType_type(const_type) == T_CHAR) {
+ const_val = NewStringf("'%s'", raw_const);
+ } else {
+ const_val = Copy(raw_const);
+ }
+
+ SwigType_add_qualifier(const_type, "const");
+
+ String *ppcname = NewStringf("ACLppc_%s", Getattr(n, "sym:name"));
+ // Printf(f_runtime, "static const %s = %s;\n", SwigType_lstr(const_type, ppcname), const_val);
+ Printf(f_runtime, "static %s = %s;\n", SwigType_lstr(const_type, ppcname), const_val);
+
+ Setattr(n, "name", ppcname);
+ SetFlag(n, "feature:immutable");
+
+ Delete(const_val);
+ return variableWrapper(n);
+ }
+
+ String *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ String *converted_value = convert_literal(value, type);
+ String *name = Getattr(n, "sym:name");
+
+ Setattr(n, "allegrocl:kind", "constant");
+ Setattr(n, "allegrocl:old-sym:name", Getattr(n, "sym:name"));
+
+#if 0
+ Printf(stdout, "constant %s is of type %s. value: %s\n", name, type, converted_value);
+#endif
+
+ if (converted_value) {
+ Printf(f_clwrap, "(swig-defconstant \"%s\" %s)\n", name, converted_value);
+ } else {
+ Swig_warning(WARN_LANG_DISCARD_CONST, Getfile(n), Getline(n), "Unable to parse constant value '%s'. Setting to NIL\n", value);
+ Printf(f_clwrap, "(swig-defconstant \"%s\" nil #| %s |#)\n", name, value);
+ }
+
+ Delete(converted_value);
+
+ return SWIG_OK;
+}
+
+int ALLEGROCL::globalvariableHandler(Node *n) {
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "globalvariableHandler %s\n", Getattr(n, "name"));
+#endif
+
+ if (Generate_Wrapper)
+ return Language::globalvariableHandler(n);
+
+ // String *name = Getattr(n, "name");
+ SwigType *type = Getattr(n, "type");
+ SwigType *ctype;
+ SwigType *rtype = SwigType_typedef_resolve_all(type);
+
+ int pointer_added = 0;
+
+ if (SwigType_isclass(rtype)) {
+ SwigType_add_pointer(type);
+ SwigType_add_pointer(rtype);
+ pointer_added = 1;
+ }
+
+ ctype = SwigType_str(type, 0);
+ // EXPORT <SwigType_str> <mangled_name>;
+ // <SwigType_str> <mangled_name> = <name>;
+ // Printf(f_runtime, "EXPORT %s %s;\n%s %s = %s%s;\n", ctype, mangled_name,
+ // ctype, mangled_name, (pointer_added ? "&" : ""), name);
+
+ Printf(f_clwrap, "(swig-defvar \"%s\" \"%s\" :type %s)\n",
+ Getattr(n, "sym:name"), Getattr(n, "sym:name"), ((SwigType_isconst(type)) ? ":constant" : ":variable"));
+
+ return SWIG_OK;
+}
+
+int ALLEGROCL::variableWrapper(Node *n) {
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "variableWrapper %s\n", Getattr(n, "name"));
+#endif
+ Setattr(n, "allegrocl:kind", "variable");
+ Setattr(n, "allegrocl:old-sym:name", Getattr(n, "sym:name"));
+
+ // Let SWIG generate a get/set function pair.
+ if (Generate_Wrapper)
+ return Language::variableWrapper(n);
+
+ String *name = Getattr(n, "name");
+ SwigType *type = Getattr(n, "type");
+ SwigType *ctype;
+ SwigType *rtype = SwigType_typedef_resolve_all(type);
+
+ String *mangled_name = mangle_name(n);
+
+ int pointer_added = 0;
+
+ if (SwigType_isclass(rtype)) {
+ SwigType_add_pointer(type);
+ SwigType_add_pointer(rtype);
+ pointer_added = 1;
+ }
+
+ ctype = SwigType_str(type, 0);
+
+ // EXPORT <SwigType_str> <mangled_name>;
+ // <SwigType_str> <mangled_name> = <name>;
+ Printf(f_runtime, "EXPORT %s %s;\n%s %s = %s%s;\n", ctype, mangled_name, ctype, mangled_name, (pointer_added ? "&" : ""), name);
+
+ Printf(f_cl, "(swig-defvar \"%s\" :type %s)\n", mangled_name, ((SwigType_isconst(type)) ? ":constant" : ":variable"));
+
+ Printf(stderr,"***\n");
+ Delete(mangled_name);
+
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "DONE variable %s\n", Getattr(n, "name"));
+#endif
+
+ return SWIG_OK;
+}
+
+int ALLEGROCL::memberfunctionHandler(Node *n) {
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "memberfunctionHandler %s::%s\n", Getattr(parent_node_skipping_extends(n), "name"), Getattr(n, "name"));
+#endif
+ Setattr(n, "allegrocl:kind", "member function");
+ Setattr(n, "allegrocl:old-sym:name", Getattr(n, "sym:name"));
+
+ // Let SWIG generate a global forwarding function.
+ return Language::memberfunctionHandler(n);
+}
+
+int ALLEGROCL::membervariableHandler(Node *n) {
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "membervariableHandler %s::%s\n", Getattr(parent_node_skipping_extends(n), "name"), Getattr(n, "name"));
+#endif
+ Setattr(n, "allegrocl:kind", "member variable");
+ Setattr(n, "allegrocl:old-sym:name", Getattr(n, "sym:name"));
+
+ // Let SWIG generate a get/set function pair.
+ return Language::membervariableHandler(n);
+}
+
+int ALLEGROCL::typedefHandler(Node *n) {
+#ifdef ALLEGROCL_TYPE_DEBUG
+ Printf(stderr, "In typedefHandler\n");
+#endif
+
+ SwigType *typedef_type = Getattr(n,"type");
+ // has the side-effect of noting any implicit
+ // template instantiations in type.
+ String *ff_type = compose_foreign_type(n, typedef_type);
+
+ String *sym_name = Getattr(n, "sym:name");
+
+ String *name;
+ String *type_ref;
+
+ if (in_class) {
+#ifdef ALLEGROCL_TYPE_DEBUG
+ Printf(stderr, " typedef in class '%s'(%x)\n", Getattr(in_class, "sym:name"), in_class);
+#endif
+ Setattr(n, "allegrocl:typedef:in-class", in_class);
+
+ String *class_name = Getattr(in_class, "name");
+ name = NewStringf("%s__%s", class_name, sym_name);
+ type_ref = NewStringf("%s::%s", class_name, sym_name);
+ Setattr(n, "allegrocl:in-class", in_class);
+ } else {
+ name = Copy(sym_name);
+ type_ref = Copy(Getattr(n, "name"));
+ }
+
+ Setattr(n, "allegrocl:namespace", current_namespace);
+
+ String *lookup = lookup_defined_foreign_type(typedef_type);
+
+#ifdef ALLEGROCL_TYPE_DEBUG
+ Printf(stderr, "** lookup='%s'(%x), typedef_type='%s', strcmp = '%d' strstr = '%d'\n", lookup, lookup, typedef_type, Strcmp(typedef_type,"void"), Strstr(ff_type,"__SWIGACL_FwdReference"));
+#endif
+
+ if(lookup || (!lookup && Strcmp(typedef_type,"void")) ||
+ (!lookup && Strstr(ff_type,"__SWIGACL_FwdReference"))) {
+ add_defined_foreign_type(n, 0, type_ref, name);
+ } else {
+ add_forward_referenced_type(n);
+ }
+
+#ifdef ALLEGROCL_TYPE_DEBUG
+ Printf(stderr, "Out typedefHandler\n");
+#endif
+
+ Delete(ff_type);
+
+ return SWIG_OK;
+}
+
+// forward referenced classes are added specially to defined_foreign_types
+int ALLEGROCL::classforwardDeclaration(Node *n) {
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "classforwardDeclaration %s\n", Getattr(n, "name"));
+#endif
+
+ add_forward_referenced_type(n);
+ return SWIG_OK;
+}
+
+int ALLEGROCL::classHandler(Node *n) {
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "classHandler %s::%s\n", current_namespace, Getattr(n, "sym:name"));
+#endif
+
+ int result;
+
+ if (Generate_Wrapper)
+ result = cppClassHandler(n);
+ else
+ result = cClassHandler(n);
+
+ return result;
+}
+
+int ALLEGROCL::cClassHandler(Node *n) {
+#ifdef ALLEGROCL_TYPE_DEBUG
+ Printf(stderr, "In cClassHandler\n");
+#endif
+ // String *cDeclName = Getattr(n,"classDeclaration:name");
+ // String *name= Getattr(n, "sym:name");
+ // String *kind = Getattr(n,"kind");
+ // Node *c;
+
+ /* Add this structure to the known lisp types */
+ // Printf(stderr, "Adding %s foreign type\n", name);
+ String *ns = listify_namespace(current_namespace);
+
+ add_defined_foreign_type(n);
+
+ Delete(ns);
+
+#ifdef ALLEGROCL_TYPE_DEBUG
+ Printf(stderr, "Out cClassHandler\n");
+#endif
+
+ return SWIG_OK;
+}
+
+int ALLEGROCL::cppClassHandler(Node *n) {
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "cppClassHandler %s\n", Getattr(n, "name"));
+#endif
+
+ // String *name=Getattr(n, "sym:name");
+ // String *kind = Getattr(n,"kind");
+
+ /* Template instantiation.
+ Careful.
+ SWIG does not create instantiations of templated classes whenever
+ it sees a templated class reference (say, as a return type, or
+ in a parameter list).
+
+ The %template directive results in a templated class instantiation
+ that will actually be seen by <LANG> :: classHandler().
+
+ In this case, we don't want to error if the type already exists;
+ the point is to force the creation of wrappers for the templated
+ class.
+ */
+ String *templated = Getattr(n, "template");
+ String *t_name;
+ // String *ns = listify_namespace(current_namespace);
+
+ if (templated) {
+ t_name = namespaced_name(n);
+ } else {
+ t_name = Getattr(n, "name");
+ }
+
+ Setattr(n, "allegrocl:namespace", current_namespace);
+
+ /* Add this structure to the known lisp types.
+ Class may contain references to the type currently being
+ defined */
+ if (!templated || !lookup_defined_foreign_type(t_name)) {
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "Adding %s foreign type\n", Getattr(n, "sym:name"));
+#endif
+ add_defined_foreign_type(n);
+ } else {
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "cppClassHand: type %s already exists. Assuming %%template instantiation for wrapping purposes.\n", Getattr(n, "sym:name"));
+#endif
+ add_defined_foreign_type(n, 1);
+ }
+
+ // Generate slot accessors, constructor, and destructor.
+ Node *prev_class = in_class;
+ in_class = n;
+
+ Node *c;
+ // walk all member variables.
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, " MANUALLY walking class members... \n");
+#endif
+ for (c = firstChild(n); c; c = nextSibling(c)) {
+ // ping the types of all children--even protected and private
+ // so their types can be added to the linked_type_list.
+ SwigType *childType = NewStringf("%s%s", Getattr(c, "decl"),
+ Getattr(c, "type"));
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, "looking at child '%x' of type '%s'\n", c, childType);
+#endif
+ if (!SwigType_isfunction(childType))
+ Delete(compose_foreign_type(n, childType));
+
+ Delete(childType);
+ }
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, " MANUAL walk DONE.\n");
+#endif
+
+ // this will walk all necessary methods.
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, " LANGUAGE walk of children...\n");
+#endif
+ Language::classHandler(n);
+#ifdef ALLEGROCL_CLASS_DEBUG
+ Printf(stderr, " LANGUAGE walk DONE\n");
+#endif
+ in_class = prev_class;
+
+ return SWIG_OK;
+}
+
+int ALLEGROCL::emit_one(Node *n) {
+ // When the current package does not correspond with the current
+ // namespace we need to generate an IN-PACKAGE form, unless the
+ // current node is another namespace node.
+ if (Cmp(nodeType(n), "namespace") != 0 && Cmp(current_package, current_namespace) != 0) {
+ String *lispy_namespace = listify_namespace(current_namespace);
+ Printf(f_clwrap, "(swig-in-package %s)\n", lispy_namespace);
+ Delete(lispy_namespace);
+ Delete(current_package);
+ current_package = NewStringf("%s", current_namespace);
+ }
+
+ Setattr(n, "allegrocl:package", current_package);
+
+ return Language::emit_one(n);
+}
+
+int ALLEGROCL::enumDeclaration(Node *n) {
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "enumDeclaration %s\n", Getattr(n, "name"));
+#endif
+
+ if (Getattr(n, "sym:name")) {
+ add_defined_foreign_type(n);
+ }
+ Node *c;
+ for (c = firstChild(n); c; c = nextSibling(c)) {
+ ALLEGROCL::enumvalueDeclaration(c);
+ // since we walk our own children, we need to add
+ // the current package ourselves.
+ Setattr(c, "allegrocl:package", current_package);
+ }
+ return SWIG_OK;
+}
+
+
+int ALLEGROCL::enumvalueDeclaration(Node *n) {
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "enumvalueDeclaration %s\n", Getattr(n, "name"));
+#endif
+ /* print this when in C mode? make this a command-line arg? */
+ if (Generate_Wrapper) {
+ SwigType *enum_type = Copy(Getattr(n,"type"));
+ String *mangled_name =
+ mangle_name(n, "ACL_ENUM",
+ in_class ? Getattr(in_class,"name") :
+ current_namespace);
+
+ SwigType_add_qualifier(enum_type,"const");
+
+ String *enum_decl = SwigType_str(enum_type, mangled_name);
+ Printf(f_cxx_wrapper, "EXPORT %s;\n", enum_decl);
+ Printf(f_cxx_wrapper, "%s = %s;\n", enum_decl, Getattr(n, "value"));
+
+ Delete(mangled_name);
+ Delete(enum_type);
+ Delete(enum_decl);
+ }
+ return SWIG_OK;
+}
+
+int ALLEGROCL::templateDeclaration(Node *n) {
+#ifdef ALLEGROCL_DEBUG
+ Printf(stderr, "templateDeclaration %s\n", Getattr(n, "name"));
+#endif
+
+ String *type = Getattr(n, "templatetype");
+
+ // Printf(stderr, "tempDecl: %s %s\n", Getattr(n,"name"),
+ // type);
+ // Swig_print_node(n);
+
+ if (!Strcmp(type, "cdecl")) {
+ SwigType *ty = NewStringf("%s%s", Getattr(n, "decl"),
+ Getattr(n, "type"));
+ Delete(ty);
+ }
+
+ Delete(type);
+
+ return SWIG_OK;
+}
diff --git a/Source/Modules/allocate.cxx b/Source/Modules/allocate.cxx
new file mode 100644
index 0000000..b52578b
--- /dev/null
+++ b/Source/Modules/allocate.cxx
@@ -0,0 +1,955 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * 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.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_allocate_cxx[] = "$Id: allocate.cxx 11583 2009-08-15 23:22:20Z wsfulton $";
+
+#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 (!Getattr(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 (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)
+ 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 *abstract = Getattr(base, "abstract");
+ if (abstract) {
+ int dabstract = 0;
+ int len = Len(abstract);
+ for (int i = 0; i < len; i++) {
+ Node *nn = Getitem(abstract, i);
+ String *name = Getattr(nn, "name");
+ if (!name)
+ continue;
+ String *base_decl = Getattr(nn, "decl");
+ if (base_decl)
+ base_decl = SwigType_typedef_resolve_all(base_decl);
+ if (Strchr(name, '~'))
+ continue; /* Don't care about destructors */
+
+ 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 *nabstract = Getattr(n, "abstract");
+ if (!nabstract) {
+ nabstract = NewList();
+ Setattr(n, "abstract", nabstract);
+ Delete(nabstract);
+ }
+ Append(nabstract, nn);
+ if (!Getattr(n, "abstract:firstnode")) {
+ Setattr(n, "abstract: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);
+ String *kind = Getattr(cls, "kind");
+ int mode = PUBLIC;
+ if (kind && (Strcmp(kind, "class") == 0))
+ mode = PRIVATE;
+
+ 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 ((!symname || (!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, "classname", 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");
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (Strcmp(nodeType(c), "access") == 0) {
+ kind = Getattr(c, "kind");
+ if (Strcmp(kind, "public") == 0)
+ mode = PUBLIC;
+ else
+ mode = PRIVATE;
+ }
+ 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 constructued 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);
+ 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"));
+
+ 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, "abstract") && 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, "abstract: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, "abstract")) {
+ List *abstract = NewList();
+ Append(abstract, na);
+ Setattr(n, "abstract", abstract);
+ Delete(abstract);
+ }
+ }
+ }
+ }
+ }
+
+ 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, "abstract")) {
+ 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, "abstract")) {
+ 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. We need to check a few things here too */
+ 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 destructor was defined. We need to check a few things here too */
+ 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 default destructor, 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 destructor was defined. We need to check a few things here too */
+ 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 default destructor, 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((char *) "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"));
+ }
+ }
+ }
+ }
+
+ /* Only care about default behavior. Remove temporary values */
+ Setattr(n, "allocate:visit", "1");
+ inclass = 0;
+ 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 (checkAttribute(n, "storage", "static")) {
+ 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 */
+ Setattr(inclass, "allocate:has_assign", "1");
+ Setattr(inclass, "allocate:noassign", "1");
+ } else if (Strcmp(name, "operator new") == 0) {
+ /* Look for a private new operator */
+ Setattr(inclass, "allocate:has_new", "1");
+ Setattr(inclass, "allocate:nonew", "1");
+ }
+ } else {
+ if (Strcmp(name, "operator =") == 0) {
+ Setattr(inclass, "allocate:has_assign", "1");
+ } else if (Strcmp(name, "operator new") == 0) {
+ Setattr(inclass, "allocate:has_new", "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 = 1;
+ Setattr(inclass, "allocate:smartpointerconst", "1");
+ }
+ List *methods = smart_pointer_methods(sc, 0, isconst);
+ Setattr(inclass, "allocate:smartpointer", methods);
+ Setattr(inclass, "allocate:smartpointerbase", base);
+ } 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((char *) "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");
+ }
+ }
+ return SWIG_OK;
+ }
+};
+
+void Swig_default_allocators(Node *n) {
+ if (!n)
+ return;
+ Allocate *a = new Allocate;
+ a->top(n);
+ delete a;
+}
diff --git a/Source/Modules/browser.cxx b/Source/Modules/browser.cxx
new file mode 100644
index 0000000..dd1679a
--- /dev/null
+++ b/Source/Modules/browser.cxx
@@ -0,0 +1,413 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * browser.cxx
+ *
+ * A web-base parse tree browser using SWILL. This is an optional
+ * feature that's normally disabled.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_browser_cxx[] = "$Id: browser.cxx 10003 2007-10-17 21:42:11Z wsfulton $";
+
+#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%x\"></a>[<a href=\"hide.html?node=0x%x&hn=0x%x#n%x\">-</a>] ", n, t, n, n);
+ } else {
+ Printf(out, "<a name=\"n%x\"></a>[<a href=\"show.html?node=0x%x&hn=0x%x#n%x\">+</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=0x%x\">?</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=0x%x\">?</a> %-12s - \"%(escape)-0.70s%s\"\n", Getattr(obj, k), k, o, trunc);
+ Delete(o);
+ } else {
+ Printf(os, "<a href=\"data.html?n=0x%x\">?</a> %-12s - 0x%x\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=0x%x\">%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 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=0x%x\">Top</a> ]", tree_top);
+ if (n != tree_top) {
+ Printf(f, " [ <a href=\"index.html?node=0x%x\">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=0x%x\">?</a> %-12s - \"%(escape)-0.70s%s\"\n", Getattr(obj, k), k, o, trunc);
+ Delete(o);
+ } else {
+ Printf(os, " <a href=\"data.html?n=0x%x\">?</a> %-12s - 0x%x\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=0x%x\">?</a> [%d] - \"%(escape)-0.70s%s\"\n", o, i, s, trunc);
+ Delete(s);
+ } else {
+ Printf(os, " <a href=\"data.html?n=0x%x\">?</a> [%d] - 0x%x\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=0x%x\">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=0x%x\">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=\"0x%x\">\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=0x%x\">%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/Source/Modules/cffi.cxx b/Source/Modules/cffi.cxx
new file mode 100644
index 0000000..053bab7
--- /dev/null
+++ b/Source/Modules/cffi.cxx
@@ -0,0 +1,1081 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * cffi.cxx
+ *
+ * cffi language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_cffi_cxx[] = "$Id: cffi.cxx 11380 2009-07-08 12:17:45Z wsfulton $";
+
+#include "swigmod.h"
+#include "cparse.h"
+#include <ctype.h>
+
+//#define CFFI_DEBUG
+//#define CFFI_WRAP_DEBUG
+
+class CFFI:public Language {
+public:
+ String *f_cl;
+ String *f_clhead;
+ String *f_clwrap;
+ bool CWrap; // generate wrapper file for C code?
+ File *f_begin;
+ File *f_runtime;
+ File *f_cxx_header;
+ File *f_cxx_wrapper;
+ File *f_clos;
+
+ String *module;
+ virtual void main(int argc, char *argv[]);
+ virtual int top(Node *n);
+ virtual int functionWrapper(Node *n);
+ virtual int variableWrapper(Node *n);
+ virtual int constantWrapper(Node *n);
+ // virtual int classDeclaration(Node *n);
+ virtual int enumDeclaration(Node *n);
+ virtual int typedefHandler(Node *n);
+
+ //c++ specific code
+ virtual int constructorHandler(Node *n);
+ virtual int destructorHandler(Node *n);
+ virtual int memberfunctionHandler(Node *n);
+ virtual int membervariableHandler(Node *n);
+ virtual int classHandler(Node *n);
+
+private:
+ void emit_defun(Node *n, String *name);
+ void emit_defmethod(Node *n);
+ void emit_initialize_instance(Node *n);
+ void emit_getter(Node *n);
+ void emit_setter(Node *n);
+ void emit_class(Node *n);
+ void emit_struct_union(Node *n, bool un);
+ void emit_export(Node *n, String *name);
+ void emit_inline(Node *n, String *name);
+ String *lispy_name(char *name);
+ String *lispify_name(Node *n, String *ty, const char *flag, bool kw = false);
+ String *convert_literal(String *num_param, String *type, bool try_to_split = true);
+ String *infix_to_prefix(String *val, char split_op, const String *op, String *type);
+ String *strip_parens(String *string);
+ String *trim(String *string);
+ int generate_typedef_flag;
+ bool no_swig_lisp;
+};
+
+void CFFI::main(int argc, char *argv[]) {
+ int i;
+
+ Preprocessor_define("SWIGCFFI 1", 0);
+ SWIG_library_directory("cffi");
+ SWIG_config_file("cffi.swg");
+ generate_typedef_flag = 0;
+ no_swig_lisp = false;
+ CWrap = false;
+ for (i = 1; i < argc; i++) {
+ if (!Strcmp(argv[i], "-help")) {
+ Printf(stdout, "cffi Options (available with -cffi)\n");
+ Printf(stdout,
+ " -generate-typedef\n"
+ "\tIf this option is given then defctype will be used to generate\n"
+ "\tshortcuts according to the typedefs in the input.\n"
+ " -[no]cwrap\n"
+ "\tTurn on or turn off generation of an intermediate C file when\n"
+ "\tcreating a C interface. By default this is only done for C++ code.\n"
+ " -[no]swig-lisp\n"
+ "\tTurns on or off generation of code for helper lisp macro, functions,\n"
+ "\tetc. which SWIG uses while generating wrappers. These macros, functions\n" "\tmay still be used by generated wrapper code.\n");
+ } else if (!strcmp(argv[i], "-cwrap")) {
+ CWrap = true;
+ Swig_mark_arg(i);
+ } else if ((Strcmp(argv[i], "-generate-typedef") == 0)) {
+ generate_typedef_flag = 1;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i], "-nocwrap")) {
+ CWrap = false;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i], "-swig-lisp")) {
+ no_swig_lisp = false;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i], "-noswig-lisp")) {
+ no_swig_lisp = true;
+ Swig_mark_arg(i);
+ }
+
+ }
+ f_clhead = NewString("");
+ f_clwrap = NewString("");
+ f_cl = NewString("");
+
+ allow_overloading();
+}
+
+int CFFI::top(Node *n) {
+ File *f_null = NewString("");
+ module = Getattr(n, "name");
+
+ String *cxx_filename = Getattr(n, "outfile");
+ String *lisp_filename = NewString("");
+
+ Printf(lisp_filename, "%s%s.lisp", SWIG_output_directory(), module);
+
+ File *f_lisp = NewFile(lisp_filename, "w", SWIG_output_files());
+ if (!f_lisp) {
+ FileErrorDisplay(lisp_filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ if (CPlusPlus || CWrap) {
+ f_begin = NewFile(cxx_filename, "w", SWIG_output_files());
+ if (!f_begin) {
+ Close(f_lisp);
+ Delete(f_lisp);
+ Printf(stderr, "Unable to open %s for writing\n", cxx_filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ String *clos_filename = NewString("");
+ Printf(clos_filename, "%s%s-clos.lisp", SWIG_output_directory(), module);
+ f_clos = NewFile(clos_filename, "w", SWIG_output_files());
+ if (!f_clos) {
+ Close(f_lisp);
+ Delete(f_lisp);
+ Printf(stderr, "Unable to open %s for writing\n", cxx_filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ } else {
+ f_begin = NewString("");
+ f_clos = NewString("");
+ }
+
+ f_runtime = NewString("");
+ f_cxx_header = f_runtime;
+ f_cxx_wrapper = NewString("");
+
+ Swig_register_filebyname("header", f_cxx_header);
+ Swig_register_filebyname("wrapper", f_cxx_wrapper);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("lisphead", f_clhead);
+ if (!no_swig_lisp)
+ Swig_register_filebyname("swiglisp", f_cl);
+ else
+ Swig_register_filebyname("swiglisp", f_null);
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n");
+ Printf(f_runtime, "#define SWIGCFFI\n");
+ Printf(f_runtime, "\n");
+
+ Swig_banner_target_lang(f_lisp, ";;;");
+
+ Language::top(n);
+ Printf(f_lisp, "%s\n", f_clhead);
+ Printf(f_lisp, "%s\n", f_cl);
+ Printf(f_lisp, "%s\n", f_clwrap);
+
+ Close(f_lisp);
+ Delete(f_lisp); // Deletes the handle, not the file
+ Delete(f_cl);
+ Delete(f_clhead);
+ Delete(f_clwrap);
+ Dump(f_runtime, f_begin);
+ Close(f_begin);
+ Delete(f_runtime);
+ Delete(f_begin);
+ Delete(f_cxx_wrapper);
+ Delete(f_null);
+
+ return SWIG_OK;
+}
+
+int CFFI::classHandler(Node *n) {
+#ifdef CFFI_DEBUG
+ Printf(stderr, "class %s::%s\n", "some namespace", //current_namespace,
+ Getattr(n, "sym:name"));
+#endif
+ String *name = Getattr(n, "sym:name");
+ String *kind = Getattr(n, "kind");
+
+ // maybe just remove this check and get rid of the else clause below.
+ if (Strcmp(kind, "struct") == 0) {
+ emit_struct_union(n, false);
+ return SWIG_OK;
+ } else if (Strcmp(kind, "union") == 0) {
+ emit_struct_union(n, true);
+ return SWIG_OK;
+ } else if (Strcmp(kind, "class") == 0) {
+ emit_class(n);
+ Language::classHandler(n);
+ } else {
+ Printf(stderr, "Don't know how to deal with %s kind of class yet.\n", kind);
+ Printf(stderr, " (name: %s)\n", name);
+ SWIG_exit(EXIT_FAILURE);
+ return SWIG_OK;
+ }
+
+ return SWIG_OK;
+}
+
+int CFFI::constructorHandler(Node *n) {
+#ifdef CFFI_DEBUG
+ Printf(stderr, "constructor %s\n", Getattr(n, "name"));
+ Printf(stderr, "constructor %s\n and %s and %s", Getattr(n, "kind"), Getattr(n, "sym:name"), Getattr(n, "allegrocl:old-sym:name"));
+#endif
+ Setattr(n, "cffi:constructorfunction", "1");
+ // Let SWIG generate a global forwarding function.
+ return Language::constructorHandler(n);
+}
+
+int CFFI::destructorHandler(Node *n) {
+#ifdef CFFI_DEBUG
+ Printf(stderr, "destructor %s\n", Getattr(n, "name"));
+#endif
+
+ // Let SWIG generate a global forwarding function.
+ return Language::destructorHandler(n);
+}
+
+void CFFI::emit_defmethod(Node *n) {
+ String *args_placeholder = NewStringf("");
+ String *args_call = NewStringf("");
+
+ ParmList *pl = Getattr(n, "parms");
+ int argnum = 0;
+ Node *parent = getCurrentClass();
+ bool first = 0;
+
+ for (Parm *p = pl; p; p = nextSibling(p), argnum++) {
+ String *argname = Getattr(p, "name");
+ String *ffitype = Swig_typemap_lookup("lispclass", p, "", 0);
+
+ int tempargname = 0;
+
+ if(!first)
+ first = true;
+ else
+ Printf(args_placeholder, " ");
+
+ if (!argname) {
+ argname = NewStringf("arg%d", argnum);
+ tempargname = 1;
+ } else if (Strcmp(argname, "t") == 0 || Strcmp(argname, "T") == 0) {
+ argname = NewStringf("t-arg%d", argnum);
+ tempargname = 1;
+ }
+ if (Len(ffitype) > 0)
+ Printf(args_placeholder, "(%s %s)", argname, ffitype);
+ else
+ Printf(args_placeholder, "%s", argname);
+
+ if (ffitype && Strcmp(ffitype, lispify_name(parent, lispy_name(Char(Getattr(parent, "sym:name"))), "'classname")) == 0)
+ Printf(args_call, " (ff-pointer %s)", argname);
+ else
+ Printf(args_call, " %s", argname);
+
+ Delete(ffitype);
+
+ if (tempargname)
+ Delete(argname);
+ }
+
+ String *method_name = Getattr(n, "name");
+ int x = Replace(method_name, "operator ", "", DOH_REPLACE_FIRST); //
+
+ if (x == 1)
+ Printf(f_clos, "(cl:shadow \"%s\")\n", method_name);
+
+ Printf(f_clos, "(cl:defmethod %s (%s)\n (%s%s))\n\n",
+ lispify_name(n, lispy_name(Char(method_name)), "'method"), args_placeholder,
+ lispify_name(n, Getattr(n, "sym:name"), "'function"), args_call);
+
+}
+
+void CFFI::emit_initialize_instance(Node *n) {
+ String *args_placeholder = NewStringf("");
+ String *args_call = NewStringf("");
+
+ ParmList *pl = Getattr(n, "parms");
+ int argnum = 0;
+ Node *parent = getCurrentClass();
+
+ for (Parm *p = pl; p; p = nextSibling(p), argnum++) {
+ String *argname = Getattr(p, "name");
+ String *ffitype = Swig_typemap_lookup("lispclass", p, "", 0);
+
+ int tempargname = 0;
+ if (!argname) {
+ argname = NewStringf("arg%d", argnum);
+ tempargname = 1;
+ } else if (Strcmp(argname, "t") == 0 || Strcmp(argname, "T") == 0) {
+ argname = NewStringf("t-arg%d", argnum);
+ tempargname = 1;
+ }
+ if (Len(ffitype) > 0)
+ Printf(args_placeholder, " (%s %s)", argname, ffitype);
+ else
+ Printf(args_placeholder, " %s", argname);
+
+ if (Strcmp(ffitype, lispify_name(parent, lispy_name(Char(Getattr(parent, "sym:name"))), "'classname")) == 0)
+ Printf(args_call, " (ff-pointer %s)", argname);
+ else
+ Printf(args_call, " %s", argname);
+
+ Delete(ffitype);
+
+ if (tempargname)
+ Delete(argname);
+ }
+
+ Printf(f_clos, "(cl:defmethod initialize-instance :after ((obj %s) &key%s)\n (setf (slot-value obj 'ff-pointer) (%s%s)))\n\n",
+ lispify_name(parent, lispy_name(Char(Getattr(parent, "sym:name"))), "'class"), args_placeholder,
+ lispify_name(n, Getattr(n, "sym:name"), "'function"), args_call);
+
+}
+
+void CFFI::emit_setter(Node *n) {
+ Node *parent = getCurrentClass();
+ Printf(f_clos, "(cl:defmethod (cl:setf %s) (arg0 (obj %s))\n (%s (ff-pointer obj) arg0))\n\n",
+ lispify_name(n, Getattr(n, "name"), "'method"),
+ lispify_name(parent, lispy_name(Char(Getattr(parent, "sym:name"))), "'class"), lispify_name(n, Getattr(n, "sym:name"), "'function"));
+}
+
+
+void CFFI::emit_getter(Node *n) {
+ Node *parent = getCurrentClass();
+ Printf(f_clos, "(cl:defmethod %s ((obj %s))\n (%s (ff-pointer obj)))\n\n",
+ lispify_name(n, Getattr(n, "name"), "'method"),
+ lispify_name(parent, lispy_name(Char(Getattr(parent, "sym:name"))), "'class"), lispify_name(n, Getattr(n, "sym:name"), "'function"));
+}
+
+int CFFI::memberfunctionHandler(Node *n) {
+ // Let SWIG generate a global forwarding function.
+ Setattr(n, "cffi:memberfunction", "1");
+ return Language::memberfunctionHandler(n);
+}
+
+int CFFI::membervariableHandler(Node *n) {
+ // Let SWIG generate a get/set function pair.
+ Setattr(n, "cffi:membervariable", "1");
+ return Language::membervariableHandler(n);
+}
+
+int CFFI::functionWrapper(Node *n) {
+
+ ParmList *parms = Getattr(n, "parms");
+ String *iname = Getattr(n, "sym:name");
+ Wrapper *f = NewWrapper();
+
+ String *raw_return_type = Swig_typemap_lookup("ctype", n, "", 0);
+ SwigType *return_type = Swig_cparse_type(raw_return_type);
+ SwigType *resolved = SwigType_typedef_resolve_all(return_type);
+ int is_void_return = (Cmp(resolved, "void") == 0);
+ Delete(resolved);
+
+ if (!is_void_return) {
+ String *lresult_init = NewStringf("lresult = (%s)0", raw_return_type);
+ Wrapper_add_localv(f, "lresult", raw_return_type, lresult_init, NIL);
+ Delete(lresult_init);
+ }
+
+ String *overname = 0;
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n)) {
+ DelWrapper(f);
+ return SWIG_ERROR;
+ }
+ }
+
+ String *wname = Swig_name_wrapper(iname);
+ if (overname) {
+ Append(wname, overname);
+ }
+ Setattr(n, "wrap:name", wname);
+
+ // Emit all of the local variables for holding arguments.
+ emit_parameter_variables(parms, f);
+
+ // Attach the standard typemaps
+ Swig_typemap_attach_parms("ctype", parms, f);
+ emit_attach_parmmaps(parms, f);
+
+ int num_arguments = emit_num_arguments(parms);
+ String *name_and_parms = NewStringf("%s (", wname);
+ int i;
+ Parm *p;
+ int gencomma = 0;
+
+#ifdef CFFI_DEBUG
+ Printf(stderr, "function - %s - %d\n", Getattr(n, "name"), num_arguments);
+#endif
+
+ for (i = 0, p = parms; i < num_arguments; i++) {
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *c_parm_type = Swig_cparse_type(Getattr(p, "tmap:ctype"));
+ String *arg = NewStringf("l%s", Getattr(p, "lname"));
+
+ // Emit parameter declaration
+ if (gencomma)
+ Printf(name_and_parms, ", ");
+ String *parm_decl = SwigType_str(c_parm_type, arg);
+ Printf(name_and_parms, "%s", parm_decl);
+#ifdef CFFI_DEBUG
+ Printf(stderr, " param: %s\n", parm_decl);
+#endif
+ Delete(parm_decl);
+ gencomma = 1;
+
+ // Emit parameter conversion code
+ String *parm_code = Getattr(p, "tmap:in");
+ {
+ Replaceall(parm_code, "$input", arg);
+ Setattr(p, "emit:input", arg);
+ Printf(f->code, "%s\n", parm_code);
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Delete(arg);
+ }
+ Printf(name_and_parms, ")");
+
+ // Emit the function definition
+ String *signature = SwigType_str(return_type, name_and_parms);
+ Printf(f->def, "EXPORT %s {", signature);
+ Printf(f->code, " try {\n");
+
+ String *actioncode = emit_action(n);
+
+ String *result_convert = Swig_typemap_lookup_out("out", n, "result", f, actioncode);
+ Replaceall(result_convert, "$result", "lresult");
+ Printf(f->code, "%s\n", result_convert);
+ if(!is_void_return) Printf(f->code, " return lresult;\n");
+ Delete(result_convert);
+ emit_return_variable(n, Getattr(n, "type"), f);
+
+ Printf(f->code, " } catch (...) {\n");
+ if (!is_void_return)
+ Printf(f->code, " return (%s)0;\n", raw_return_type);
+ Printf(f->code, " }\n");
+ Printf(f->code, "}\n");
+
+ if (CPlusPlus)
+ Wrapper_print(f, f_runtime);
+
+ if (CPlusPlus) {
+ emit_defun(n, wname);
+ if (Getattr(n, "cffi:memberfunction"))
+ emit_defmethod(n);
+ else if (Getattr(n, "cffi:membervariable")) {
+ if (Getattr(n, "memberget"))
+ emit_getter(n);
+ else if (Getattr(n, "memberset"))
+ emit_setter(n);
+ }
+ else if (Getattr(n, "cffi:constructorfunction")) {
+ emit_initialize_instance(n);
+ }
+ } else
+ emit_defun(n, iname);
+
+ // if (!overloaded || !Getattr(n, "sym:nextSibling")) {
+ // update_package_if_needed(n);
+ // emit_buffered_defuns(n);
+ // // this is the last overload.
+ // if (overloaded) {
+ // emit_dispatch_defun(n);
+ // }
+ // }
+
+ Delete(wname);
+ DelWrapper(f);
+
+ return SWIG_OK;
+}
+
+
+void CFFI::emit_defun(Node *n, String *name) {
+
+ // String *storage=Getattr(n,"storage");
+ // if(!storage || (Strcmp(storage,"extern") && Strcmp(storage,"externc")))
+ // return SWIG_OK;
+
+ String *func_name = Getattr(n, "sym:name");
+
+ ParmList *pl = Getattr(n, "parms");
+
+ int argnum = 0;
+
+ func_name = lispify_name(n, func_name, "'function");
+
+ emit_inline(n, func_name);
+
+ Printf(f_cl, "\n(cffi:defcfun (\"%s\" %s)", name, func_name);
+ String *ffitype = Swig_typemap_lookup("cout", n, ":pointer", 0);
+
+ Printf(f_cl, " %s", ffitype);
+ Delete(ffitype);
+
+ for (Parm *p = pl; p; p = nextSibling(p), argnum++) {
+
+ if (SwigType_isvarargs(Getattr(p, "type"))) {
+ Printf(f_cl, "\n %s", NewString("&rest"));
+ continue;
+ }
+
+ String *argname = Getattr(p, "name");
+
+ ffitype = Swig_typemap_lookup("cin", p, "", 0);
+
+ int tempargname = 0;
+ if (!argname) {
+
+ argname = NewStringf("arg%d", argnum);
+ tempargname = 1;
+ } else if (Strcmp(argname, "t") == 0 || Strcmp(argname, "T") == 0) {
+ argname = NewStringf("t_arg%d", argnum);
+ tempargname = 1;
+ }
+
+ Printf(f_cl, "\n (%s %s)", argname, ffitype);
+
+ Delete(ffitype);
+
+ if (tempargname)
+ Delete(argname);
+ }
+ Printf(f_cl, ")\n"); /* finish arg list */
+
+ emit_export(n, func_name);
+}
+
+
+int CFFI::constantWrapper(Node *n) {
+ String *type = Getattr(n, "type");
+ String *converted_value = convert_literal(Getattr(n, "value"), type);
+ String *name = lispify_name(n, Getattr(n, "sym:name"), "'constant");
+
+ if (Strcmp(name, "t") == 0 || Strcmp(name, "T") == 0)
+ name = NewStringf("t_var");
+
+ Printf(f_cl, "\n(cl:defconstant %s %s)\n", name, converted_value);
+ Delete(converted_value);
+
+ emit_export(n, name);
+ return SWIG_OK;
+}
+
+int CFFI::variableWrapper(Node *n) {
+ // String *storage=Getattr(n,"storage");
+ // Printf(stdout,"\"%s\" %s)\n",storage,Getattr(n, "sym:name"));
+
+ // if(!storage || (Strcmp(storage,"extern") && Strcmp(storage,"externc")))
+ // return SWIG_OK;
+
+ String *var_name = Getattr(n, "sym:name");
+ String *lisp_type = Swig_typemap_lookup("cin", n, "", 0);
+ String *lisp_name = lispify_name(n, var_name, "'variable");
+
+ if (Strcmp(lisp_name, "t") == 0 || Strcmp(lisp_name, "T") == 0)
+ lisp_name = NewStringf("t_var");
+
+ Printf(f_cl, "\n(cffi:defcvar (\"%s\" %s)\n %s)\n", var_name, lisp_name, lisp_type);
+
+ Delete(lisp_type);
+
+ emit_export(n, lisp_name);
+ return SWIG_OK;
+}
+
+int CFFI::typedefHandler(Node *n) {
+ if (generate_typedef_flag && strncmp(Char(Getattr(n, "type")), "enum", 4)) {
+ String *lisp_name = lispify_name(n, Getattr(n, "name"), "'typename");
+ Printf(f_cl, "\n(cffi:defctype %s %s)\n", lisp_name, Swig_typemap_lookup("cin", n, "", 0));
+ emit_export(n, lisp_name);
+ }
+ return Language::typedefHandler(n);
+}
+
+int CFFI::enumDeclaration(Node *n) {
+ String *name = Getattr(n, "sym:name");
+ bool slot_name_keywords;
+ String *lisp_name = 0;
+ if (name && Len(name) != 0) {
+ lisp_name = lispify_name(n, name, "'enumname");
+ if (GetFlag(n, "feature:bitfield")) {
+ Printf(f_cl, "\n(cffi:defbitfield %s", lisp_name);
+ } else {
+ Printf(f_cl, "\n(cffi:defcenum %s", lisp_name);
+ }
+ slot_name_keywords = true;
+
+ //Registering the enum name to the cin and cout typemaps
+ Parm *pattern = NewParm(name, NULL);
+ Swig_typemap_register("cin", pattern, lisp_name, NULL, NULL);
+ Swig_typemap_register("cout", pattern, lisp_name, NULL, NULL);
+ Delete(pattern);
+ //Registering with the kind, i.e., enum
+ pattern = NewParm(NewStringf("enum %s", name), NULL);
+ Swig_typemap_register("cin", pattern, lisp_name, NULL, NULL);
+ Swig_typemap_register("cout", pattern, lisp_name, NULL, NULL);
+ Delete(pattern);
+
+ } else {
+ Printf(f_cl, "\n(defanonenum %s", name);
+ slot_name_keywords = false;
+ }
+
+ for (Node *c = firstChild(n); c; c = nextSibling(c)) {
+
+ String *slot_name = lispify_name(c, Getattr(c, "name"), "'enumvalue", slot_name_keywords);
+ String *value = Getattr(c, "enumvalue");
+
+ if (!value || GetFlag(n, "feature:bitfield:ignore_values"))
+ Printf(f_cl, "\n\t%s", slot_name);
+ else {
+ String *type = Getattr(c, "type");
+ String *converted_value = convert_literal(value, type);
+ Printf(f_cl, "\n\t(%s #.%s)", slot_name, converted_value);
+ Delete(converted_value);
+ }
+ Delete(value);
+ }
+
+ Printf(f_cl, ")\n");
+
+ // No need to export keywords
+ if (lisp_name && Len(lisp_name) != 0) {
+ emit_export(n, lisp_name);
+ } else {
+ for (Node *c = firstChild(n); c; c = nextSibling(c))
+ emit_export(c, lispify_name(c, Getattr(c, "name"), "'enumvalue"));
+ }
+
+ return SWIG_OK;
+}
+void CFFI::emit_class(Node *n) {
+
+#ifdef CFFI_WRAP_DEBUG
+ Printf(stderr, "emit_class: ENTER... '%s'(%x)\n", Getattr(n, "sym:name"), n);
+#endif
+
+ String *name = Getattr(n, "sym:name");
+ String *lisp_name = lispify_name(n, lispy_name(Char(name)), "'classname");
+
+ String *bases = Getattr(n, "bases");
+ String *supers = NewString("(");
+ if (bases) {
+ int first = 1;
+ for (Iterator i = First(bases); i.item; i = Next(i)) {
+ if (!first)
+ Printf(supers, " ");
+ String *s = Getattr(i.item, "name");
+ Printf(supers, "%s", lispify_name(i.item, s, "'classname"));
+ }
+ } else {
+ // Printf(supers,"ff:foreign-pointer");
+ }
+
+ Printf(supers, ")");
+ Printf(f_clos, "\n(cl:defclass %s%s", lisp_name, supers);
+ Printf(f_clos, "\n ((ff-pointer :reader ff-pointer)))\n\n");
+
+ Parm *pattern = NewParm(Getattr(n, "name"), NULL);
+
+ Swig_typemap_register("lispclass", pattern, lisp_name, NULL, NULL);
+ SwigType_add_pointer(Getattr(pattern, "type"));
+ Swig_typemap_register("lispclass", pattern, lisp_name, NULL, NULL);
+ SwigType_add_qualifier(Getattr(pattern, "type"), "const");
+ Swig_typemap_register("lispclass", pattern, lisp_name, NULL, NULL);
+ SwigType_del_pointer(Getattr(pattern, "type"));
+ SwigType_add_reference(Getattr(pattern, "type"));
+ Swig_typemap_register("lispclass", pattern, lisp_name, NULL, NULL);
+
+#ifdef CFFI_WRAP_DEBUG
+ Printf(stderr, " pattern %s name %s .. ... %s .\n", pattern, lisp_name);
+#endif
+
+ Delete(pattern);
+
+ // Walk children to generate type definition.
+ String *slotdefs = NewString(" ");
+
+#ifdef CFFI_WRAP_DEBUG
+ Printf(stderr, " walking children...\n");
+#endif
+
+ Node *c;
+ for (c = firstChild(n); c; c = nextSibling(c)) {
+ String *storage_type = Getattr(c, "storage");
+ if ((!Strcmp(nodeType(c), "cdecl") && (!storage_type || Strcmp(storage_type, "typedef")))) {
+ String *access = Getattr(c, "access");
+
+ // hack. why would decl have a value of "variableHandler" and now "0"?
+ String *childDecl = Getattr(c, "decl");
+ // Printf(stderr,"childDecl = '%s' (%s)\n", childDecl, Getattr(c,"view"));
+ if (!Strcmp(childDecl, "0"))
+ childDecl = NewString("");
+
+ SwigType *childType = NewStringf("%s%s", childDecl,
+ Getattr(c, "type"));
+ String *cname = (access && Strcmp(access, "public")) ? NewString("nil") : Copy(Getattr(c, "name"));
+
+ if (!SwigType_isfunction(childType)) {
+ // Printf(slotdefs, ";;; member functions don't appear as slots.\n ");
+ // Printf(slotdefs, ";; ");
+ // String *ns = listify_namespace(Getattr(n, "cffi:package"));
+ String *ns = NewString("");
+#ifdef CFFI_WRAP_DEBUG
+ Printf(stderr, "slot name = '%s' ns = '%s' class-of '%s' and type = '%s'\n", cname, ns, name, childType);
+#endif
+ Printf(slotdefs, "(#.(swig-insert-id \"%s\" %s :type :slot :class \"%s\") %s)", cname, ns, name, childType); //compose_foreign_type(childType)
+ Delete(ns);
+ if (access && Strcmp(access, "public"))
+ Printf(slotdefs, " ;; %s member", access);
+
+ Printf(slotdefs, "\n ");
+ }
+ Delete(childType);
+ Delete(cname);
+ }
+ }
+
+
+ // String *ns_list = listify_namespace(Getattr(n,"cffi:namespace"));
+ // update_package_if_needed(n,f_clhead);
+ // Printf(f_clos,
+ // "(swig-def-foreign-class \"%s\"\n %s\n (:%s\n%s))\n\n",
+ // name, supers, kind, slotdefs);
+
+ Delete(supers);
+ // Delete(ns_list);
+
+ // Parm *pattern = NewParm(name,NULL);
+ // Swig_typemap_register("cin",pattern,lisp_name,NULL,NULL);
+ //Swig_typemap_register("cout",pattern,lisp_name,NULL,NULL);
+ //Delete(pattern);
+
+#ifdef CFFI_WRAP_DEBUG
+ Printf(stderr, "emit_class: EXIT\n");
+#endif
+}
+
+// Includes structs
+void CFFI::emit_struct_union(Node *n, bool un = false) {
+#ifdef CFFI_DEBUG
+ Printf(stderr, "struct/union %s\n", Getattr(n, "name"));
+ Printf(stderr, "struct/union %s\n and %s", Getattr(n, "kind"), Getattr(n, "sym:name"));
+#endif
+
+ String *name = Getattr(n, "sym:name");
+ String *kind = Getattr(n, "kind");
+
+ if (Strcmp(kind, "struct") != 0 && Strcmp(kind, "union") != 0) {
+ Printf(stderr, "Don't know how to deal with %s kind of class yet.\n", kind);
+ Printf(stderr, " (name: %s)\n", name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ String *lisp_name = lispify_name(n, name, "'classname");
+
+ //Register the struct/union name to the cin and cout typemaps
+
+ Parm *pattern = NewParm(name, NULL);
+ Swig_typemap_register("cin", pattern, lisp_name, NULL, NULL);
+ Swig_typemap_register("cout", pattern, lisp_name, NULL, NULL);
+ Delete(pattern);
+ //Registering with the kind, i.e., struct or union
+ pattern = NewParm(NewStringf("%s %s", kind, name), NULL);
+ Swig_typemap_register("cin", pattern, lisp_name, NULL, NULL);
+ Swig_typemap_register("cout", pattern, lisp_name, NULL, NULL);
+ Delete(pattern);
+
+ if (un) {
+ Printf(f_cl, "\n(cffi:defcunion %s", lisp_name);
+ } else
+ Printf(f_cl, "\n(cffi:defcstruct %s", lisp_name);
+
+
+ for (Node *c = firstChild(n); c; c = nextSibling(c)) {
+#ifdef CFFI_DEBUG
+ Printf(stderr, "struct/union %s\n", Getattr(c, "name"));
+ Printf(stderr, "struct/union %s and %s \n", Getattr(c, "kind"), Getattr(c, "sym:name"));
+#endif
+
+ if (Strcmp(nodeType(c), "cdecl")) {
+ //C declaration ignore
+ // Printf(stderr, "Structure %s has a slot that we can't deal with.\n",
+ // name);
+ // Printf(stderr, "nodeType: %s, name: %s, type: %s\n",
+ // nodeType(c),
+ // Getattr(c, "name"),
+ // Getattr(c, "type"));
+ // SWIG_exit(EXIT_FAILURE);
+ } else {
+ SwigType *childType = NewStringf("%s%s", Getattr(c, "decl"), Getattr(c, "type"));
+
+ Node *node = NewHash();
+ Setattr(node, "type", childType);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *tm = Swig_typemap_lookup("cin", node, "", 0);
+
+ String *typespec = tm ? NewString(tm) : NewString("");
+
+ String *slot_name = lispify_name(c, Getattr(c, "sym:name"), "'slotname");
+ if (Strcmp(slot_name, "t") == 0 || Strcmp(slot_name, "T") == 0)
+ slot_name = NewStringf("t_var");
+
+ Printf(f_cl, "\n\t(%s %s)", slot_name, typespec);
+
+ Delete(node);
+ Delete(childType);
+ Delete(typespec);
+ }
+ }
+
+ Printf(f_cl, ")\n");
+
+ emit_export(n, lisp_name);
+ for (Node *child = firstChild(n); child; child = nextSibling(child)) {
+ if (!Strcmp(nodeType(child), "cdecl")) {
+ emit_export(child, lispify_name(child, Getattr(child, "sym:name"), "'slotname"));
+ }
+ }
+
+ /* Add this structure to the known lisp types */
+ //Printf(stdout, "Adding %s foreign type\n", name);
+ // add_defined_foreign_type(name);
+
+}
+
+void CFFI::emit_export(Node *n, String *name) {
+ if (GetInt(n, "feature:export"))
+ Printf(f_cl, "\n(cl:export '%s)\n", name);
+}
+
+void CFFI::emit_inline(Node *n, String *name) {
+ if (GetInt(n, "feature:inline"))
+ Printf(f_cl, "\n(cl:declaim (cl:inline %s))\n", name);
+}
+
+String *CFFI::lispify_name(Node *n, String *ty, const char *flag, bool kw) {
+ String *intern_func = Getattr(n, "feature:intern_function");
+ if (intern_func) {
+ if (Strcmp(intern_func, "1") == 0)
+ intern_func = NewStringf("swig-lispify");
+ return NewStringf("#.(%s \"%s\" %s%s)", intern_func, ty, flag, kw ? " :keyword" : "");
+ } else if (kw)
+ return NewStringf(":%s", ty);
+ else
+ return ty;
+}
+
+/* utilities */
+/* returns new string w/ parens stripped */
+String *CFFI::strip_parens(String *string) {
+ char *s = Char(string), *p;
+ int len = Len(string);
+ String *res;
+
+ if (len == 0 || s[0] != '(' || s[len - 1] != ')') {
+ return NewString(string);
+ }
+
+ p = (char *) malloc(len - 2 + 1);
+ if (!p) {
+ Printf(stderr, "Malloc failed\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ strncpy(p, s + 1, len - 1);
+ p[len - 2] = 0; /* null terminate */
+
+ res = NewString(p);
+ free(p);
+
+ return res;
+}
+
+String *CFFI::trim(String *str) {
+ char *c = Char(str);
+ while (*c != '\0' && isspace((int) *c))
+ ++c;
+ String *result = NewString(c);
+ Chop(result);
+ return result;
+}
+
+String *CFFI::infix_to_prefix(String *val, char split_op, const String *op, String *type) {
+ List *ored = Split(val, split_op, -1);
+
+ // some float hackery
+ //i don't understand it, if you do then please explain
+ // if ( ((split_op == '+') || (split_op == '-')) && Len(ored) == 2 &&
+ // (SwigType_type(type) == T_FLOAT || SwigType_type(type) == T_DOUBLE ||
+ // SwigType_type(type) == T_LONGDOUBLE) ) {
+ // // check that we're not splitting a float
+ // String *possible_result = convert_literal(val, type, false);
+ // if (possible_result) return possible_result;
+
+ // }
+
+ // try parsing the split results. if any part fails, kick out.
+ bool part_failed = false;
+ if (Len(ored) > 1) {
+ String *result = NewStringf("(%s", op);
+ for (Iterator i = First(ored); i.item; i = Next(i)) {
+ String *converted = convert_literal(i.item, type);
+ if (converted) {
+ Printf(result, " %s", converted);
+ Delete(converted);
+ } else {
+ part_failed = true;
+ break;
+ }
+ }
+ Printf(result, ")");
+ Delete(ored);
+ return part_failed ? 0 : result;
+ } else {
+ Delete(ored);
+ }
+ return 0;
+}
+
+/* To be called by code generating the lisp interface
+ Will return a String containing the literal based on type.
+ Will return null if there are problems.
+
+ try_to_split defaults to true (see stub above).
+*/
+String *CFFI::convert_literal(String *literal, String *type, bool try_to_split) {
+ String *num_param = Copy(literal);
+ String *trimmed = trim(num_param);
+ String *num = strip_parens(trimmed), *res = 0;
+ Delete(trimmed);
+ char *s = Char(num);
+
+ // very basic parsing of infix expressions.
+ if (try_to_split) {
+ if ((res = infix_to_prefix(num, '|', "cl:logior", type)))
+ return res;
+ if ((res = infix_to_prefix(num, '&', "cl:logand", type)))
+ return res;
+ if ((res = infix_to_prefix(num, '^', "cl:logxor", type)))
+ return res;
+ if ((res = infix_to_prefix(num, '*', "cl:*", type)))
+ return res;
+ if ((res = infix_to_prefix(num, '/', "cl:/", type)))
+ return res;
+ if ((res = infix_to_prefix(num, '+', "cl:+", type)))
+ return res;
+ if ((res = infix_to_prefix(num, '-', "cl:-", type)))
+ return res;
+ }
+
+ if (SwigType_type(type) == T_FLOAT || SwigType_type(type) == T_DOUBLE || SwigType_type(type) == T_LONGDOUBLE) {
+ // Use CL syntax for float literals
+
+ // careful. may be a float identifier or float constant.
+ char *num_start = Char(num);
+ char *num_end = num_start + strlen(num_start) - 1;
+
+ bool is_literal = isdigit(*num_start) || (*num_start == '.') || (*num_start == '+') || (*num_start == '-');
+
+ String *lisp_exp = 0;
+ if (is_literal) {
+ if (*num_end == 'f' || *num_end == 'F') {
+ lisp_exp = NewString("f");
+ } else {
+ lisp_exp = NewString("d");
+ }
+
+ if (*num_end == 'l' || *num_end == 'L' || *num_end == 'f' || *num_end == 'F') {
+ *num_end = '\0';
+ num_end--;
+ }
+
+ int exponents = Replaceall(num, "e", lisp_exp) + Replaceall(num, "E", lisp_exp);
+
+ if (!exponents)
+ Printf(num, "%s0", lisp_exp);
+
+ if (exponents > 1 || (exponents + Replaceall(num, ".", ".") == 0)) {
+ Delete(num);
+ num = 0;
+ }
+ }
+ return num;
+ } else if (SwigType_type(type) == T_CHAR) {
+ /* Use CL syntax for character literals */
+ String* result = NewStringf("#\\%c", s[2]);
+ Delete(num);
+ // Printf(stderr, "%s %c %d", s, s[2], s);
+ return result;
+ } else if (SwigType_type(type) == T_STRING) {
+ /* Use CL syntax for string literals */
+ String* result = NewStringf("\"%s\"", num_param);
+ Delete(num);
+ return result;
+ } else if (SwigType_type(type) == T_INT || SwigType_type(type) == T_UINT) {
+ // Printf(stderr, "Is a T_INT or T_UINT %s, before replaceall\n", s);
+ Replaceall(num, "u", "");
+ Replaceall(num, "U", "");
+ Replaceall(num, "l", "");
+ Replaceall(num, "L", "");
+
+ int i, j;
+ if (sscanf(s, "%d >> %d", &i, &j) == 2) {
+ String* result = NewStringf("(cl:ash %d -%d)", i, j);
+ Delete(num);
+ return result;
+ } else if (sscanf(s, "%d << %d", &i, &j) == 2) {
+ String* result = NewStringf("(cl:ash %d %d)", i, j);
+ Delete(num);
+ return result;
+ }
+ }
+
+ if (Len(num) >= 2 && s[0] == '0') { /* octal or hex */
+ if (s[1] == 'x'){
+ DohReplace(num,"0","#",DOH_REPLACE_FIRST);
+ }
+ else{
+ DohReplace(num,"0","#o",DOH_REPLACE_FIRST);
+ }
+ }
+ return num;
+}
+
+//less flexible as it does the conversion in C, the lispify name does the conversion in lisp
+String *CFFI::lispy_name(char *name) {
+ bool helper = false;
+ String *new_name = NewString("");
+ for (unsigned int i = 0; i < strlen(name); i++) {
+ if (name[i] == '_' || name[i] == '-') {
+ Printf(new_name, "%c", '-');
+ helper = false;
+ } else if (name[i] >= 'A' && name[i] <= 'Z') {
+ if (helper)
+ Printf(new_name, "%c", '-');
+ Printf(new_name, "%c", ('a' + (name[i] - 'A')));
+ helper = false;
+ } else {
+ helper = true;
+ Printf(new_name, "%c", name[i]);
+ }
+ }
+ return new_name;
+}
+
+extern "C" Language *swig_cffi(void) {
+ return new CFFI();
+}
diff --git a/Source/Modules/chicken.cxx b/Source/Modules/chicken.cxx
new file mode 100644
index 0000000..3bf6602
--- /dev/null
+++ b/Source/Modules/chicken.cxx
@@ -0,0 +1,1552 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * chicken.cxx
+ *
+ * CHICKEN language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_chicken_cxx[] = "$Id: chicken.cxx 11133 2009-02-20 07:52:24Z wsfulton $";
+
+#include "swigmod.h"
+
+#include <ctype.h>
+
+static const char *chicken_usage = (char *) "\
+\
+CHICKEN Options (available with -chicken)\n\
+ -proxy - Export TinyCLOS class definitions\n\
+ -closprefix <prefix> - Prepend <prefix> to all clos identifiers\n\
+ -useclassprefix - Prepend the class name to all clos identifiers\n\
+ -unhideprimitive - Unhide the primitive: symbols\n\
+ -nounit - Do not (declare (unit ...)) in scheme file\n\
+ -noclosuses - Do not (declare (uses ...)) in scheme file\n\
+ -nocollection - Do not register pointers with chicken garbage\n\
+ collector and export destructors\n\
+\n";
+
+static char *module = 0;
+static char *chicken_path = (char *) "chicken";
+static int num_methods = 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;
+static String *chickentext = 0;
+static String *closprefix = 0;
+static String *swigtype_ptr = 0;
+
+
+static String *f_sym_size = 0;
+
+/* some options */
+static int declare_unit = 1;
+static int no_collection = 0;
+static int clos_uses = 1;
+
+/* C++ Support + Clos Classes */
+static int clos = 0;
+static String *c_class_name = 0;
+static String *class_name = 0;
+static String *short_class_name = 0;
+
+static int in_class = 0;
+static int have_constructor = 0;
+static bool exporting_destructor = false;
+static bool exporting_constructor = false;
+static String *constructor_name = 0;
+static String *member_name = 0;
+
+/* sections of the .scm code */
+static String *scm_const_defs = 0;
+static String *clos_class_defines = 0;
+static String *clos_methods = 0;
+
+/* Some clos options */
+static int useclassprefix = 0;
+static String *clossymnameprefix = 0;
+static int hide_primitive = 1;
+static Hash *primitive_names = 0;
+
+/* Used for overloading constructors */
+static int has_constructor_args = 0;
+static List *constructor_arg_types = 0;
+static String *constructor_dispatch = 0;
+
+static Hash *overload_parameter_lists = 0;
+
+class CHICKEN:public Language {
+public:
+
+ virtual void main(int argc, char *argv[]);
+ virtual int top(Node *n);
+ virtual int functionWrapper(Node *n);
+ virtual int variableWrapper(Node *n);
+ virtual int constantWrapper(Node *n);
+ virtual int classHandler(Node *n);
+ virtual int memberfunctionHandler(Node *n);
+ virtual int membervariableHandler(Node *n);
+ virtual int constructorHandler(Node *n);
+ virtual int destructorHandler(Node *n);
+ virtual int validIdentifier(String *s);
+ virtual int staticmembervariableHandler(Node *n);
+ virtual int staticmemberfunctionHandler(Node *n);
+ virtual int importDirective(Node *n);
+
+protected:
+ void addMethod(String *scheme_name, String *function);
+ /* Return true iff T is a pointer type */
+ int isPointer(SwigType *t);
+ void dispatchFunction(Node *n);
+
+ String *chickenNameMapping(String *, const_String_or_char_ptr );
+ String *chickenPrimitiveName(String *);
+
+ String *runtimeCode();
+ String *defaultExternalRuntimeFilename();
+ String *buildClosFunctionCall(List *types, const_String_or_char_ptr closname, const_String_or_char_ptr funcname);
+};
+
+/* -----------------------------------------------------------------------
+ * swig_chicken() - Instantiate module
+ * ----------------------------------------------------------------------- */
+
+static Language *new_swig_chicken() {
+ return new CHICKEN();
+}
+
+extern "C" {
+ Language *swig_chicken(void) {
+ return new_swig_chicken();
+ }
+}
+
+void CHICKEN::main(int argc, char *argv[]) {
+ int i;
+
+ SWIG_library_directory(chicken_path);
+
+ // Look for certain command line options
+ for (i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-help") == 0) {
+ fputs(chicken_usage, stdout);
+ SWIG_exit(0);
+ } else if (strcmp(argv[i], "-proxy") == 0) {
+ clos = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-closprefix") == 0) {
+ if (argv[i + 1]) {
+ clossymnameprefix = 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], "-unhideprimitive") == 0) {
+ hide_primitive = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nounit") == 0) {
+ declare_unit = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-noclosuses") == 0) {
+ clos_uses = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocollection") == 0) {
+ no_collection = 1;
+ Swig_mark_arg(i);
+ }
+ }
+ }
+
+ if (!clos)
+ hide_primitive = 0;
+
+ // Add a symbol for this module
+ Preprocessor_define("SWIGCHICKEN 1", 0);
+
+ // Set name of typemaps
+
+ SWIG_typemap_lang("chicken");
+
+ // Read in default typemaps */
+ SWIG_config_file("chicken.swg");
+ allow_overloading();
+}
+
+int CHICKEN::top(Node *n) {
+ String *chicken_filename = NewString("");
+ File *f_scm;
+ String *scmmodule;
+
+ /* 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("");
+ chickentext = NewString("");
+ closprefix = NewString("");
+ f_sym_size = NewString("");
+ primitive_names = NewHash();
+ overload_parameter_lists = NewHash();
+
+ /* 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("chicken", chickentext);
+ Swig_register_filebyname("closprefix", closprefix);
+
+ clos_class_defines = NewString("");
+ clos_methods = NewString("");
+ scm_const_defs = NewString("");
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n");
+ Printf(f_runtime, "#define SWIGCHICKEN\n");
+
+ if (no_collection)
+ Printf(f_runtime, "#define SWIG_CHICKEN_NO_COLLECTION 1\n");
+
+ Printf(f_runtime, "\n");
+
+ /* Set module name */
+ module = Swig_copy_string(Char(Getattr(n, "name")));
+ scmmodule = NewString(module);
+ Replaceall(scmmodule, "_", "-");
+
+ Printf(f_header, "#define SWIG_init swig_%s_init\n", module);
+ Printf(f_header, "#define SWIG_name \"%s\"\n", scmmodule);
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n");
+ Printf(f_wrappers, "extern \"C\" {\n");
+ Printf(f_wrappers, "#endif\n\n");
+
+ Language::top(n);
+
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n");
+ Printf(f_wrappers, "}\n");
+ Printf(f_wrappers, "#endif\n");
+
+ Printf(f_init, "C_kontinue (continuation, ret);\n");
+ Printf(f_init, "}\n\n");
+
+ Printf(f_init, "#ifdef __cplusplus\n");
+ Printf(f_init, "}\n");
+ Printf(f_init, "#endif\n");
+
+ Printf(chicken_filename, "%s%s.scm", SWIG_output_directory(), module);
+ if ((f_scm = NewFile(chicken_filename, "w", SWIG_output_files())) == 0) {
+ FileErrorDisplay(chicken_filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ Swig_banner_target_lang(f_scm, ";;");
+ Printf(f_scm, "\n");
+
+ if (declare_unit)
+ Printv(f_scm, "(declare (unit ", scmmodule, "))\n\n", NIL);
+ Printv(f_scm, "(declare \n",
+ tab4, "(hide swig-init swig-init-return)\n",
+ tab4, "(foreign-declare \"C_extern void swig_", module, "_init(C_word,C_word,C_word) C_noret;\"))\n", NIL);
+ Printv(f_scm, "(define swig-init (##core#primitive \"swig_", module, "_init\"))\n", NIL);
+ Printv(f_scm, "(define swig-init-return (swig-init))\n\n", NIL);
+
+ if (clos) {
+ //Printf (f_scm, "(declare (uses tinyclos))\n");
+ //New chicken versions have tinyclos as an egg
+ Printf(f_scm, "(require-extension tinyclos)\n");
+ Replaceall(closprefix, "$module", scmmodule);
+ Printf(f_scm, "%s\n", closprefix);
+ Printf(f_scm, "%s\n", clos_class_defines);
+ Printf(f_scm, "%s\n", clos_methods);
+ } else {
+ Printf(f_scm, "%s\n", scm_const_defs);
+ }
+
+ Printf(f_scm, "%s\n", chickentext);
+
+
+ Close(f_scm);
+ Delete(f_scm);
+
+ char buftmp[20];
+ sprintf(buftmp, "%d", num_methods);
+ Replaceall(f_init, "$nummethods", buftmp);
+ Replaceall(f_init, "$symsize", f_sym_size);
+
+ if (hide_primitive)
+ Replaceall(f_init, "$veclength", buftmp);
+ else
+ Replaceall(f_init, "$veclength", "0");
+
+ Delete(chicken_filename);
+ Delete(chickentext);
+ Delete(closprefix);
+ Delete(overload_parameter_lists);
+
+ Delete(clos_class_defines);
+ Delete(clos_methods);
+ Delete(scm_const_defs);
+
+ /* Close all of the files */
+ Delete(primitive_names);
+ Delete(scmmodule);
+ 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_sym_size);
+ Delete(f_init);
+ Close(f_begin);
+ Delete(f_runtime);
+ Delete(f_begin);
+ return SWIG_OK;
+}
+
+int CHICKEN::functionWrapper(Node *n) {
+
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *d = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+
+ Parm *p;
+ int i;
+ String *wname;
+ Wrapper *f;
+ String *mangle = NewString("");
+ String *get_pointers;
+ String *cleanup;
+ String *argout;
+ String *tm;
+ String *overname = 0;
+ String *declfunc = 0;
+ String *scmname;
+ bool any_specialized_arg = false;
+ List *function_arg_types = NewList();
+
+ int num_required;
+ int num_arguments;
+ int have_argout;
+
+ Printf(mangle, "\"%s\"", SwigType_manglestr(d));
+
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+ }
+
+ f = NewWrapper();
+ wname = NewString("");
+ get_pointers = NewString("");
+ cleanup = NewString("");
+ argout = NewString("");
+ declfunc = NewString("");
+ scmname = NewString(iname);
+ Replaceall(scmname, "_", "-");
+
+ /* Local vars */
+ Wrapper_add_local(f, "resultobj", "C_word resultobj");
+
+ /* 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 */
+ num_arguments = emit_num_arguments(l);
+ num_required = emit_num_required(l);
+
+ Append(wname, Swig_name_wrapper(iname));
+ if (overname) {
+ Append(wname, overname);
+ }
+ // Check for interrupts
+ Printv(f->code, "C_trace(\"", scmname, "\");\n", NIL);
+
+ Printv(f->def, "static ", "void ", wname, " (C_word argc, C_word closure, C_word continuation", NIL);
+ Printv(declfunc, "void ", wname, "(C_word,C_word,C_word", NIL);
+
+ /* Generate code for argument marshalling */
+ 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");
+
+ Printf(f->def, ", C_word scm%d", i + 1);
+ Printf(declfunc, ",C_word");
+
+ /* Look for an input typemap */
+ if ((tm = Getattr(p, "tmap:in"))) {
+ String *parse = Getattr(p, "tmap:in:parse");
+ if (!parse) {
+ String *source = NewStringf("scm%d", i + 1);
+ 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 (i >= num_required)
+ Printf(get_pointers, "if (argc-2>%i && (%s)) {\n", i, source);
+ Printv(get_pointers, tm, "\n", NIL);
+ if (i >= num_required)
+ Printv(get_pointers, "}\n", NIL);
+
+ if (clos) {
+ if (i < num_required) {
+ if (strcmp("void", Char(pt)) != 0) {
+ Node *class_node = 0;
+ String *clos_code = Getattr(p, "tmap:in:closcode");
+ class_node = classLookup(pt);
+ if (clos_code && class_node) {
+ String *class_name = NewStringf("<%s>", Getattr(class_node, "sym:name"));
+ Replaceall(class_name, "_", "-");
+ Append(function_arg_types, class_name);
+ Append(function_arg_types, Copy(clos_code));
+ any_specialized_arg = true;
+ Delete(class_name);
+ } else {
+ Append(function_arg_types, "<top>");
+ Append(function_arg_types, "$input");
+ }
+ }
+ }
+ }
+ Delete(source);
+ }
+
+ 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 */
+
+ Printf(f->def, ") {");
+ Printf(declfunc, ")");
+
+ if (num_required != num_arguments) {
+ Append(function_arg_types, "^^##optional$$");
+ }
+
+ /* First check the number of arguments is correct */
+ if (num_arguments != num_required)
+ Printf(f->code, "if (argc-2<%i || argc-2>%i) C_bad_argc(argc,%i);\n", num_required, num_arguments, num_required + 2);
+ else
+ Printf(f->code, "if (argc!=%i) C_bad_argc(argc,%i);\n", num_arguments + 2, num_arguments + 2);
+
+ /* Now piece together the first part of the wrapper function */
+ Printv(f->code, get_pointers, 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 ((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 */
+ have_argout = 0;
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+
+ if (!have_argout) {
+ have_argout = 1;
+ // Print initial argument output code
+ Printf(argout, "SWIG_Chicken_SetupArgout\n");
+ }
+
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+ Replaceall(tm, "$target", "resultobj");
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printf(argout, "%s", tm);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ Setattr(n, "wrap:name", wname);
+
+ /* Emit the function call */
+ String *actioncode = emit_action(n);
+
+ /* Return the function value */
+ if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
+ Replaceall(tm, "$source", "result");
+ Replaceall(tm, "$target", "resultobj");
+ Replaceall(tm, "$result", "resultobj");
+ if (GetFlag(n, "feature:new")) {
+ Replaceall(tm, "$owner", "1");
+ } else {
+ Replaceall(tm, "$owner", "0");
+ }
+
+ Printf(f->code, "%s", tm);
+
+ if (have_argout)
+ Printf(f->code, "\nSWIG_APPEND_VALUE(resultobj);\n");
+
+ } 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);
+
+ /* Insert the argumetn output code */
+ Printv(f->code, argout, 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, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ Printf(f->code, "%s\n", tm);
+ }
+
+
+ if (have_argout) {
+ Printf(f->code, "C_kontinue(continuation,C_SCHEME_END_OF_LIST);\n");
+ } else {
+ if (exporting_constructor && clos && hide_primitive) {
+ /* Don't return a proxy, the wrapped CLOS class is the proxy */
+ Printf(f->code, "C_kontinue(continuation,resultobj);\n");
+ } else {
+ // make the continuation the proxy creation function, if one exists
+ Printv(f->code, "{\n",
+ "C_word func;\n",
+ "SWIG_Chicken_FindCreateProxy(func, resultobj)\n",
+ "if (C_swig_is_closurep(func))\n",
+ " ((C_proc4)(void *)C_block_item(func, 0))(4,func,continuation,resultobj,C_SCHEME_FALSE);\n",
+ "else\n", " C_kontinue(continuation, resultobj);\n", "}\n", NIL);
+ }
+ }
+
+ /* Error handling code */
+#ifdef USE_FAIL
+ Printf(f->code, "fail:\n");
+ Printv(f->code, cleanup, NIL);
+ Printf(f->code, "swig_panic (\"failure in " "'$symname' SWIG function wrapper\");\n");
+#endif
+ 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", "resultobj");
+
+ /* Dump the function out */
+ Printv(f_wrappers, "static ", declfunc, " C_noret;\n", NIL);
+ Wrapper_print(f, f_wrappers);
+
+ /* Now register the function with the interpreter. */
+ if (!Getattr(n, "sym:overloaded")) {
+ if (exporting_destructor && !no_collection) {
+ Printf(f_init, "((swig_chicken_clientdata *)(SWIGTYPE%s->clientdata))->destroy = (swig_chicken_destructor) %s;\n", swigtype_ptr, wname);
+ } else {
+ addMethod(scmname, wname);
+ }
+
+ /* Only export if we are not in a class, or if in a class memberfunction */
+ if (!in_class || member_name) {
+ String *method_def;
+ String *clos_name;
+ if (in_class)
+ clos_name = NewString(member_name);
+ else
+ clos_name = chickenNameMapping(scmname, (char *) "");
+
+ if (!any_specialized_arg) {
+ method_def = NewString("");
+ Printv(method_def, "(define ", clos_name, " ", chickenPrimitiveName(scmname), ")", NIL);
+ } else {
+ method_def = buildClosFunctionCall(function_arg_types, clos_name, chickenPrimitiveName(scmname));
+ }
+ Printv(clos_methods, method_def, "\n", NIL);
+ Delete(clos_name);
+ Delete(method_def);
+ }
+
+ if (have_constructor && !has_constructor_args && any_specialized_arg) {
+ has_constructor_args = 1;
+ constructor_arg_types = Copy(function_arg_types);
+ }
+ } else {
+ /* add function_arg_types to overload hash */
+ List *flist = Getattr(overload_parameter_lists, scmname);
+ if (!flist) {
+ flist = NewList();
+ Setattr(overload_parameter_lists, scmname, flist);
+ }
+
+ Append(flist, Copy(function_arg_types));
+
+ if (!Getattr(n, "sym:nextSibling")) {
+ dispatchFunction(n);
+ }
+ }
+
+
+ Delete(wname);
+ Delete(get_pointers);
+ Delete(cleanup);
+ Delete(declfunc);
+ Delete(mangle);
+ Delete(function_arg_types);
+ DelWrapper(f);
+ return SWIG_OK;
+}
+
+int CHICKEN::variableWrapper(Node *n) {
+ char *name = GetChar(n, "name");
+ char *iname = GetChar(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+
+ String *wname = NewString("");
+ String *mangle = NewString("");
+ String *tm;
+ String *tm2 = NewString("");;
+ String *argnum = NewString("0");
+ String *arg = NewString("argv[0]");
+ Wrapper *f;
+ String *overname = 0;
+ String *scmname;
+
+ int num_required;
+ int num_arguments;
+
+ scmname = NewString(iname);
+ Replaceall(scmname, "_", "-");
+
+ Printf(mangle, "\"%s\"", SwigType_manglestr(t));
+
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+ }
+
+ f = NewWrapper();
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+ Setattr(n, "wrap:parms", l);
+
+ /* Get number of required and total arguments */
+ num_arguments = emit_num_arguments(l);
+ num_required = emit_num_required(l);
+
+ // evaluation function names
+ Append(wname, Swig_name_wrapper(iname));
+ if (overname) {
+ Append(wname, overname);
+ }
+ Setattr(n, "wrap:name", wname);
+
+ // Check for interrupts
+ Printv(f->code, "C_trace(\"", scmname, "\");\n", NIL);
+
+ if (1 || (SwigType_type(t) != T_USER) || (isPointer(t))) {
+
+ Printv(f->def, "static ", "void ", wname, "(C_word, C_word, C_word, C_word) C_noret;\n", NIL);
+ Printv(f->def, "static " "void ", wname, "(C_word argc, C_word closure, " "C_word continuation, C_word value) {\n", NIL);
+
+ Wrapper_add_local(f, "resultobj", "C_word resultobj");
+
+ Printf(f->code, "if (argc!=2 && argc!=3) C_bad_argc(argc,2);\n");
+
+ /* Check for a setting of the variable value */
+ if (!GetFlag(n, "feature:immutable")) {
+ Printf(f->code, "if (argc > 2) {\n");
+ if ((tm = Swig_typemap_lookup("varin", n, name, 0))) {
+ Replaceall(tm, "$source", "value");
+ Replaceall(tm, "$target", name);
+ Replaceall(tm, "$input", "value");
+ /* Printv(f->code, tm, "\n",NIL); */
+ emit_action_code(n, f->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));
+ }
+ Printf(f->code, "}\n");
+ }
+
+ String *varname;
+ if (SwigType_istemplate((char *) name)) {
+ varname = SwigType_namestr((char *) name);
+ } else {
+ varname = name;
+ }
+
+ // Now return the value of the variable - regardless
+ // of evaluating or setting.
+ if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
+ Replaceall(tm, "$source", varname);
+ Replaceall(tm, "$varname", varname);
+ Replaceall(tm, "$target", "resultobj");
+ Replaceall(tm, "$result", "resultobj");
+ /* Printf(f->code, "%s\n", tm); */
+ emit_action_code(n, f->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(f->code, "{\n",
+ "C_word func;\n",
+ "SWIG_Chicken_FindCreateProxy(func, resultobj)\n",
+ "if (C_swig_is_closurep(func))\n",
+ " ((C_proc4)(void *)C_block_item(func, 0))(4,func,continuation,resultobj,C_SCHEME_FALSE);\n",
+ "else\n", " C_kontinue(continuation, resultobj);\n", "}\n", NIL);
+
+ /* Error handling code */
+#ifdef USE_FAIL
+ Printf(f->code, "fail:\n");
+ Printf(f->code, "swig_panic (\"failure in " "'%s' SWIG wrapper\");\n", proc_name);
+#endif
+ Printf(f->code, "}\n");
+
+ Wrapper_print(f, f_wrappers);
+
+ /* Now register the variable with the interpreter. */
+ addMethod(scmname, wname);
+
+ if (!in_class || member_name) {
+ String *clos_name;
+ if (in_class)
+ clos_name = NewString(member_name);
+ else
+ clos_name = chickenNameMapping(scmname, (char *) "");
+
+ Node *class_node = classLookup(t);
+ String *clos_code = Getattr(n, "tmap:varin:closcode");
+ if (class_node && clos_code && !GetFlag(n, "feature:immutable")) {
+ Replaceall(clos_code, "$input", "(car lst)");
+ Printv(clos_methods, "(define (", clos_name, " . lst) (if (null? lst) (", chickenPrimitiveName(scmname), ") (",
+ chickenPrimitiveName(scmname), " ", clos_code, ")))\n", NIL);
+ } else {
+ /* Simply re-export the procedure */
+ if (GetFlag(n, "feature:immutable") && GetFlag(n, "feature:constasvar")) {
+ Printv(clos_methods, "(define ", clos_name, " (", chickenPrimitiveName(scmname), "))\n", NIL);
+ Printv(scm_const_defs, "(set! ", scmname, " (", scmname, "))\n", NIL);
+ } else {
+ Printv(clos_methods, "(define ", clos_name, " ", chickenPrimitiveName(scmname), ")\n", NIL);
+ }
+ }
+ Delete(clos_name);
+ }
+ } else {
+ Swig_warning(WARN_TYPEMAP_VAR_UNDEF, input_file, line_number, "Unsupported variable type %s (ignored).\n", SwigType_str(t, 0));
+ }
+
+ Delete(wname);
+ Delete(argnum);
+ Delete(arg);
+ Delete(tm2);
+ Delete(mangle);
+ DelWrapper(f);
+ return SWIG_OK;
+}
+
+/* ------------------------------------------------------------
+ * constantWrapper()
+ * ------------------------------------------------------------ */
+
+int CHICKEN::constantWrapper(Node *n) {
+
+ char *name = GetChar(n, "name");
+ char *iname = GetChar(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *value = Getattr(n, "value");
+
+ String *proc_name = NewString("");
+ String *wname = NewString("");
+ String *mangle = NewString("");
+ String *tm;
+ String *tm2 = NewString("");
+ String *source = NewString("");
+ String *argnum = NewString("0");
+ String *arg = NewString("argv[0]");
+ Wrapper *f;
+ String *overname = 0;
+ String *scmname;
+ String *rvalue;
+ SwigType *nctype;
+
+ int num_required;
+ int num_arguments;
+
+ scmname = NewString(iname);
+ Replaceall(scmname, "_", "-");
+
+ Printf(source, "swig_const_%s", iname);
+ Replaceall(source, "::", "__");
+
+ Printf(mangle, "\"%s\"", SwigType_manglestr(t));
+
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+ }
+
+ Append(wname, Swig_name_wrapper(iname));
+ if (overname) {
+ Append(wname, overname);
+ }
+
+ nctype = NewString(t);
+ if (SwigType_isconst(nctype)) {
+ Delete(SwigType_pop(nctype));
+ }
+
+ if (SwigType_type(nctype) == T_STRING) {
+ rvalue = NewStringf("\"%s\"", value);
+ } else if (SwigType_type(nctype) == T_CHAR) {
+ rvalue = NewStringf("\'%s\'", value);
+ } else {
+ rvalue = NewString(value);
+ }
+
+ /* Special hook for member pointer */
+ if (SwigType_type(t) == T_MPOINTER) {
+ Printf(f_header, "static %s = %s;\n", SwigType_str(t, source), rvalue);
+ } else {
+ if ((tm = Swig_typemap_lookup("constcode", n, name, 0))) {
+ Replaceall(tm, "$source", rvalue);
+ Replaceall(tm, "$target", source);
+ Replaceall(tm, "$result", source);
+ Replaceall(tm, "$value", rvalue);
+ Printf(f_header, "%s\n", tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
+ return SWIG_NOWRAP;
+ }
+ }
+
+ f = NewWrapper();
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+ Setattr(n, "wrap:parms", l);
+
+ /* Get number of required and total arguments */
+ num_arguments = emit_num_arguments(l);
+ num_required = emit_num_required(l);
+
+ // evaluation function names
+
+ // Check for interrupts
+ Printv(f->code, "C_trace(\"", scmname, "\");\n", NIL);
+
+ if (1 || (SwigType_type(t) != T_USER) || (isPointer(t))) {
+
+ Setattr(n, "wrap:name", wname);
+ Printv(f->def, "static ", "void ", wname, "(C_word, C_word, C_word) C_noret;\n", NIL);
+
+ Printv(f->def, "static ", "void ", wname, "(C_word argc, C_word closure, " "C_word continuation) {\n", NIL);
+
+ Wrapper_add_local(f, "resultobj", "C_word resultobj");
+
+ Printf(f->code, "if (argc!=2) C_bad_argc(argc,2);\n");
+
+ // Return the value of the variable
+ if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
+
+ Replaceall(tm, "$source", source);
+ Replaceall(tm, "$varname", source);
+ Replaceall(tm, "$target", "resultobj");
+ Replaceall(tm, "$result", "resultobj");
+ /* Printf(f->code, "%s\n", tm); */
+ emit_action_code(n, f->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(f->code, "{\n",
+ "C_word func;\n",
+ "SWIG_Chicken_FindCreateProxy(func, resultobj)\n",
+ "if (C_swig_is_closurep(func))\n",
+ " ((C_proc4)(void *)C_block_item(func, 0))(4,func,continuation,resultobj,C_SCHEME_FALSE);\n",
+ "else\n", " C_kontinue(continuation, resultobj);\n", "}\n", NIL);
+
+ /* Error handling code */
+#ifdef USE_FAIL
+ Printf(f->code, "fail:\n");
+ Printf(f->code, "swig_panic (\"failure in " "'%s' SWIG wrapper\");\n", proc_name);
+#endif
+ Printf(f->code, "}\n");
+
+ Wrapper_print(f, f_wrappers);
+
+ /* Now register the variable with the interpreter. */
+ addMethod(scmname, wname);
+
+ if (!in_class || member_name) {
+ String *clos_name;
+ if (in_class)
+ clos_name = NewString(member_name);
+ else
+ clos_name = chickenNameMapping(scmname, (char *) "");
+ if (GetFlag(n, "feature:constasvar")) {
+ Printv(clos_methods, "(define ", clos_name, " (", chickenPrimitiveName(scmname), "))\n", NIL);
+ Printv(scm_const_defs, "(set! ", scmname, " (", scmname, "))\n", NIL);
+ } else {
+ Printv(clos_methods, "(define ", clos_name, " ", chickenPrimitiveName(scmname), ")\n", NIL);
+ }
+ Delete(clos_name);
+ }
+
+ } else {
+ Swig_warning(WARN_TYPEMAP_VAR_UNDEF, input_file, line_number, "Unsupported variable type %s (ignored).\n", SwigType_str(t, 0));
+ }
+
+ Delete(wname);
+ Delete(nctype);
+ Delete(proc_name);
+ Delete(argnum);
+ Delete(arg);
+ Delete(tm2);
+ Delete(mangle);
+ Delete(source);
+ Delete(rvalue);
+ DelWrapper(f);
+ return SWIG_OK;
+}
+
+int CHICKEN::classHandler(Node *n) {
+ /* Create new strings for building up a wrapper function */
+ have_constructor = 0;
+ constructor_dispatch = 0;
+ constructor_name = 0;
+
+ c_class_name = NewString(Getattr(n, "sym:name"));
+ class_name = NewString("");
+ short_class_name = NewString("");
+ Printv(class_name, "<", c_class_name, ">", NIL);
+ Printv(short_class_name, c_class_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 base = First(baselist);
+ while (base.item) {
+ if (!Getattr(base.item, "feature:ignore"))
+ Printv(base_class, "<", Getattr(base.item, "sym:name"), "> ", NIL);
+ base = Next(base);
+ }
+ }
+
+ Replaceall(base_class, "_", "-");
+
+ String *scmmod = NewString(module);
+ Replaceall(scmmod, "_", "-");
+
+ Printv(clos_class_defines, "(define ", class_name, "\n", " (make <swig-metaclass-", scmmod, "> 'name \"", short_class_name, "\"\n", NIL);
+ Delete(scmmod);
+
+ if (Len(base_class)) {
+ Printv(clos_class_defines, " 'direct-supers (list ", base_class, ")\n", NIL);
+ } else {
+ Printv(clos_class_defines, " 'direct-supers (list <object>)\n", NIL);
+ }
+
+ Printf(clos_class_defines, " 'direct-slots (list 'swig-this\n");
+
+ String *mangled_classname = Swig_name_mangle(Getattr(n, "sym:name"));
+
+ SwigType *ct = NewStringf("p.%s", Getattr(n, "name"));
+ swigtype_ptr = SwigType_manglestr(ct);
+
+ Printf(f_runtime, "static swig_chicken_clientdata _swig_chicken_clientdata%s = { 0 };\n", mangled_classname);
+ Printv(f_init, "SWIG_TypeClientData(SWIGTYPE", swigtype_ptr, ", (void *) &_swig_chicken_clientdata", mangled_classname, ");\n", NIL);
+ SwigType_remember(ct);
+
+ /* Emit all of the members */
+
+ in_class = 1;
+ Language::classHandler(n);
+ in_class = 0;
+
+ Printf(clos_class_defines, ")))\n\n");
+
+ if (have_constructor) {
+ Printv(clos_methods, "(define-method (initialize (obj ", class_name, ") initargs)\n", " (swig-initialize obj initargs ", NIL);
+ if (constructor_arg_types) {
+ String *initfunc_name = NewStringf("%s@@SWIG@initmethod", class_name);
+ String *func_call = buildClosFunctionCall(constructor_arg_types, initfunc_name, chickenPrimitiveName(constructor_name));
+ Printf(clos_methods, "%s)\n)\n", initfunc_name);
+ Printf(clos_methods, "(declare (hide %s))\n", initfunc_name);
+ Printf(clos_methods, "%s\n", func_call);
+ Delete(func_call);
+ Delete(initfunc_name);
+ Delete(constructor_arg_types);
+ constructor_arg_types = 0;
+ } else if (constructor_dispatch) {
+ Printf(clos_methods, "%s)\n)\n", constructor_dispatch);
+ Delete(constructor_dispatch);
+ constructor_dispatch = 0;
+ } else {
+ Printf(clos_methods, "%s)\n)\n", chickenPrimitiveName(constructor_name));
+ }
+ Delete(constructor_name);
+ constructor_name = 0;
+ } else {
+ Printv(clos_methods, "(define-method (initialize (obj ", class_name, ") initargs)\n", " (swig-initialize obj initargs (lambda x #f)))\n", NIL);
+ }
+
+ /* export class initialization function */
+ if (clos) {
+ String *funcname = NewString(mangled_classname);
+ Printf(funcname, "_swig_chicken_setclosclass");
+ String *closfuncname = NewString(funcname);
+ Replaceall(closfuncname, "_", "-");
+
+ Printv(f_wrappers, "static void ", funcname, "(C_word,C_word,C_word,C_word) C_noret;\n",
+ "static void ", funcname, "(C_word argc, C_word closure, C_word continuation, C_word cl) {\n",
+ " C_trace(\"", funcname, "\");\n",
+ " if (argc!=3) C_bad_argc(argc,3);\n",
+ " swig_chicken_clientdata *cdata = (swig_chicken_clientdata *) SWIGTYPE", swigtype_ptr, "->clientdata;\n",
+ " cdata->gc_proxy_create = CHICKEN_new_gc_root();\n",
+ " CHICKEN_gc_root_set(cdata->gc_proxy_create, cl);\n", " C_kontinue(continuation, C_SCHEME_UNDEFINED);\n", "}\n", NIL);
+ addMethod(closfuncname, funcname);
+
+ Printv(clos_methods, "(", chickenPrimitiveName(closfuncname), " (lambda (x lst) (if lst ",
+ "(cons (make ", class_name, " 'swig-this x) lst) ", "(make ", class_name, " 'swig-this x))))\n\n", NIL);
+ Delete(closfuncname);
+ Delete(funcname);
+ }
+
+ Delete(mangled_classname);
+ Delete(swigtype_ptr);
+ swigtype_ptr = 0;
+
+ Delete(class_name);
+ Delete(short_class_name);
+ Delete(c_class_name);
+ class_name = 0;
+ short_class_name = 0;
+ c_class_name = 0;
+
+ return SWIG_OK;
+}
+
+int CHICKEN::memberfunctionHandler(Node *n) {
+ String *iname = Getattr(n, "sym:name");
+ String *proc = NewString(iname);
+ Replaceall(proc, "_", "-");
+
+ member_name = chickenNameMapping(proc, short_class_name);
+ Language::memberfunctionHandler(n);
+ Delete(member_name);
+ member_name = NULL;
+ Delete(proc);
+
+ return SWIG_OK;
+}
+
+int CHICKEN::staticmemberfunctionHandler(Node *n) {
+ String *iname = Getattr(n, "sym:name");
+ String *proc = NewString(iname);
+ Replaceall(proc, "_", "-");
+
+ member_name = NewStringf("%s-%s", short_class_name, proc);
+ Language::staticmemberfunctionHandler(n);
+ Delete(member_name);
+ member_name = NULL;
+ Delete(proc);
+
+ return SWIG_OK;
+}
+
+int CHICKEN::membervariableHandler(Node *n) {
+ String *iname = Getattr(n, "sym:name");
+ //String *pb = SwigType_typedef_resolve_all(SwigType_base(Getattr(n, "type")));
+
+ Language::membervariableHandler(n);
+
+ String *proc = NewString(iname);
+ Replaceall(proc, "_", "-");
+
+ //Node *class_node = Swig_symbol_clookup(pb, Getattr(n, "sym:symtab"));
+ Node *class_node = classLookup(Getattr(n, "type"));
+
+ //String *getfunc = NewStringf("%s-%s-get", short_class_name, proc);
+ //String *setfunc = NewStringf("%s-%s-set", short_class_name, proc);
+ String *getfunc = Swig_name_get(Swig_name_member(c_class_name, iname));
+ Replaceall(getfunc, "_", "-");
+ String *setfunc = Swig_name_set(Swig_name_member(c_class_name, iname));
+ Replaceall(setfunc, "_", "-");
+
+ Printv(clos_class_defines, " (list '", proc, " ':swig-virtual ':swig-get ", chickenPrimitiveName(getfunc), NIL);
+
+ if (!GetFlag(n, "feature:immutable")) {
+ if (class_node) {
+ Printv(clos_class_defines, " ':swig-set (lambda (x y) (", chickenPrimitiveName(setfunc), " x (slot-ref y 'swig-this))))\n", NIL);
+ } else {
+ Printv(clos_class_defines, " ':swig-set ", chickenPrimitiveName(setfunc), ")\n", NIL);
+ }
+ } else {
+ Printf(clos_class_defines, ")\n");
+ }
+
+ Delete(proc);
+ Delete(setfunc);
+ Delete(getfunc);
+ return SWIG_OK;
+}
+
+int CHICKEN::staticmembervariableHandler(Node *n) {
+ String *iname = Getattr(n, "sym:name");
+ String *proc = NewString(iname);
+ Replaceall(proc, "_", "-");
+
+ member_name = NewStringf("%s-%s", short_class_name, proc);
+ Language::staticmembervariableHandler(n);
+ Delete(member_name);
+ member_name = NULL;
+ Delete(proc);
+
+ return SWIG_OK;
+}
+
+int CHICKEN::constructorHandler(Node *n) {
+ have_constructor = 1;
+ has_constructor_args = 0;
+
+
+ exporting_constructor = true;
+ Language::constructorHandler(n);
+ exporting_constructor = false;
+
+ has_constructor_args = 1;
+
+ String *iname = Getattr(n, "sym:name");
+ constructor_name = Swig_name_construct(iname);
+ Replaceall(constructor_name, "_", "-");
+ return SWIG_OK;
+}
+
+int CHICKEN::destructorHandler(Node *n) {
+
+ if (no_collection)
+ member_name = NewStringf("delete-%s", short_class_name);
+
+ exporting_destructor = true;
+ Language::destructorHandler(n);
+ exporting_destructor = false;
+
+ if (no_collection) {
+ Delete(member_name);
+ member_name = NULL;
+ }
+
+ return SWIG_OK;
+}
+
+int CHICKEN::importDirective(Node *n) {
+ String *modname = Getattr(n, "module");
+ if (modname && clos_uses) {
+
+ // 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);
+
+ if (mod) {
+ String *name = Getattr(mod, "name");
+ if (name) {
+ Printf(closprefix, "(declare (uses %s))\n", name);
+ }
+ }
+ }
+
+ return Language::importDirective(n);
+}
+
+String *CHICKEN::buildClosFunctionCall(List *types, const_String_or_char_ptr closname, const_String_or_char_ptr funcname) {
+ String *method_signature = NewString("");
+ String *func_args = NewString("");
+ String *func_call = NewString("");
+
+ Iterator arg_type;
+ int arg_count = 0;
+ int optional_arguments = 0;
+
+ for (arg_type = First(types); arg_type.item; arg_type = Next(arg_type)) {
+ if (Strcmp(arg_type.item, "^^##optional$$") == 0) {
+ optional_arguments = 1;
+ } else {
+ Printf(method_signature, " (arg%i %s)", arg_count, arg_type.item);
+ arg_type = Next(arg_type);
+ if (!arg_type.item)
+ break;
+
+ String *arg = NewStringf("arg%i", arg_count);
+ String *access_arg = Copy(arg_type.item);
+
+ Replaceall(access_arg, "$input", arg);
+ Printf(func_args, " %s", access_arg);
+
+ Delete(arg);
+ Delete(access_arg);
+ }
+ arg_count++;
+ }
+
+ if (optional_arguments) {
+ Printf(func_call, "(define-method (%s %s . args) (apply %s %s args))", closname, method_signature, funcname, func_args);
+ } else {
+ Printf(func_call, "(define-method (%s %s) (%s %s))", closname, method_signature, funcname, func_args);
+ }
+
+ Delete(method_signature);
+ Delete(func_args);
+
+ return func_call;
+}
+
+extern "C" {
+
+ /* compares based on non-primitive names */
+ static int compareTypeListsHelper(const DOH *a, const DOH *b, int opt_equal) {
+ List *la = (List *) a;
+ List *lb = (List *) b;
+
+ Iterator ia = First(la);
+ Iterator ib = First(lb);
+
+ while (ia.item && ib.item) {
+ int ret = Strcmp(ia.item, ib.item);
+ if (ret)
+ return ret;
+ ia = Next(Next(ia));
+ ib = Next(Next(ib));
+ } if (opt_equal && ia.item && Strcmp(ia.item, "^^##optional$$") == 0)
+ return 0;
+ if (ia.item)
+ return -1;
+ if (opt_equal && ib.item && Strcmp(ib.item, "^^##optional$$") == 0)
+ return 0;
+ if (ib.item)
+ return 1;
+
+ return 0;
+ }
+
+ static int compareTypeLists(const DOH *a, const DOH *b) {
+ return compareTypeListsHelper(a, b, 0);
+ }
+}
+
+void CHICKEN::dispatchFunction(Node *n) {
+ /* Last node in overloaded chain */
+
+ int maxargs;
+ String *tmp = NewString("");
+ String *dispatch = Swig_overload_dispatch(n, "%s (2+$numargs,closure," "continuation$commaargs);", &maxargs);
+
+ /* Generate a dispatch wrapper for all overloaded functions */
+
+ Wrapper *f = NewWrapper();
+ String *iname = Getattr(n, "sym:name");
+ String *wname = NewString("");
+ String *scmname = NewString(iname);
+ Replaceall(scmname, "_", "-");
+
+ Append(wname, Swig_name_wrapper(iname));
+
+ Printv(f->def, "static void real_", wname, "(C_word, C_word, C_word, C_word) C_noret;\n", NIL);
+
+ Printv(f->def, "static void real_", wname, "(C_word oldargc, C_word closure, C_word continuation, C_word args) {", NIL);
+
+ Wrapper_add_local(f, "argc", "int argc");
+ Printf(tmp, "C_word argv[%d]", maxargs + 1);
+ Wrapper_add_local(f, "argv", tmp);
+ Wrapper_add_local(f, "ii", "int ii");
+ Wrapper_add_local(f, "t", "C_word t = args");
+ Printf(f->code, "if (!C_swig_is_list (args)) {\n");
+ Printf(f->code, " swig_barf (SWIG_BARF1_BAD_ARGUMENT_TYPE, " "\"Argument #1 must be a list of overloaded arguments\");\n");
+ Printf(f->code, "}\n");
+ Printf(f->code, "argc = C_unfix (C_i_length (args));\n");
+ Printf(f->code, "for (ii = 0; (ii < argc) && (ii < %d); ii++, t = C_block_item (t, 1)) {\n", maxargs);
+ Printf(f->code, "argv[ii] = C_block_item (t, 0);\n");
+ Printf(f->code, "}\n");
+
+ Printv(f->code, dispatch, "\n", NIL);
+ Printf(f->code, "swig_barf (SWIG_BARF1_BAD_ARGUMENT_TYPE," "\"No matching function for overloaded '%s'\");\n", iname);
+ Printv(f->code, "}\n", NIL);
+ Wrapper_print(f, f_wrappers);
+ addMethod(scmname, wname);
+
+ DelWrapper(f);
+ f = NewWrapper();
+
+ /* varargs */
+ Printv(f->def, "void ", wname, "(C_word, C_word, C_word, ...) C_noret;\n", NIL);
+ Printv(f->def, "void ", wname, "(C_word c, C_word t0, C_word t1, ...) {", NIL);
+ Printv(f->code,
+ "C_word t2;\n",
+ "va_list v;\n",
+ "C_word *a, c2 = c;\n",
+ "C_save_rest (t1, c2, 2);\n", "a = C_alloc((c-2)*3);\n", "t2 = C_restore_rest (a, C_rest_count (0));\n", "real_", wname, " (3, t0, t1, t2);\n", NIL);
+ Printv(f->code, "}\n", NIL);
+ Wrapper_print(f, f_wrappers);
+
+ /* Now deal with overloaded function when exporting clos */
+ if (clos) {
+ List *flist = Getattr(overload_parameter_lists, scmname);
+ if (flist) {
+ Delattr(overload_parameter_lists, scmname);
+
+ SortList(flist, compareTypeLists);
+
+ String *clos_name;
+ int construct = 0;
+ if (have_constructor && !has_constructor_args) {
+ has_constructor_args = 1;
+ constructor_dispatch = NewStringf("%s@SWIG@new@dispatch", short_class_name);
+ clos_name = Copy(constructor_dispatch);
+ construct = 1;
+ Printf(clos_methods, "(declare (hide %s))\n", clos_name);
+ } else if (in_class)
+ clos_name = NewString(member_name);
+ else
+ clos_name = chickenNameMapping(scmname, (char *) "");
+
+ Iterator f;
+ List *prev = 0;
+ int all_primitive = 1;
+
+ /* first check for duplicates and an empty call */
+ String *newlist = NewList();
+ for (f = First(flist); f.item; f = Next(f)) {
+ /* check if cur is a duplicate of prev */
+ if (prev && compareTypeListsHelper(f.item, prev, 1) == 0) {
+ Delete(f.item);
+ } else {
+ Append(newlist, f.item);
+ prev = f.item;
+ Iterator j;
+ for (j = First(f.item); j.item; j = Next(j)) {
+ if (Strcmp(j.item, "^^##optional$$") != 0 && Strcmp(j.item, "<top>") != 0)
+ all_primitive = 0;
+ }
+ }
+ }
+ Delete(flist);
+ flist = newlist;
+
+ if (all_primitive) {
+ Printf(clos_methods, "(define %s %s)\n", clos_name, chickenPrimitiveName(scmname));
+ } else {
+ for (f = First(flist); f.item; f = Next(f)) {
+ /* now export clos code for argument */
+ String *func_call = buildClosFunctionCall(f.item, clos_name, chickenPrimitiveName(scmname));
+ Printf(clos_methods, "%s\n", func_call);
+ Delete(f.item);
+ Delete(func_call);
+ }
+ }
+
+ Delete(clos_name);
+ Delete(flist);
+ }
+ }
+
+ DelWrapper(f);
+ Delete(dispatch);
+ Delete(tmp);
+ Delete(wname);
+}
+
+int CHICKEN::isPointer(SwigType *t) {
+ return SwigType_ispointer(SwigType_typedef_resolve_all(t));
+}
+
+void CHICKEN::addMethod(String *scheme_name, String *function) {
+ String *sym = NewString("");
+ if (clos) {
+ Append(sym, "primitive:");
+ }
+ Append(sym, scheme_name);
+
+ /* add symbol to Chicken internal symbol table */
+ if (hide_primitive) {
+ Printv(f_init, "{\n",
+ " C_word *p0 = a;\n", " *(a++)=C_CLOSURE_TYPE|1;\n", " *(a++)=(C_word)", function, ";\n", " C_mutate(return_vec++, (C_word)p0);\n", "}\n", NIL);
+ } else {
+ Printf(f_sym_size, "+C_SIZEOF_INTERNED_SYMBOL(%d)", Len(sym));
+ Printf(f_init, "sym = C_intern (&a, %d, \"%s\");\n", Len(sym), sym);
+ Printv(f_init, "C_mutate ((C_word*)sym+1, (*a=C_CLOSURE_TYPE|1, a[1]=(C_word)", function, ", tmp=(C_word)a, a+=2, tmp));\n", NIL);
+ }
+
+ if (hide_primitive) {
+ Setattr(primitive_names, scheme_name, NewStringf("(vector-ref swig-init-return %i)", num_methods));
+ } else {
+ Setattr(primitive_names, scheme_name, Copy(sym));
+ }
+
+ num_methods++;
+
+ Delete(sym);
+}
+
+String *CHICKEN::chickenPrimitiveName(String *name) {
+ String *value = Getattr(primitive_names, name);
+ if (value)
+ return value;
+ else {
+ Swig_error(input_file, line_number, "Internal Error: attempting to reference non-existant primitive name %s\n", name);
+ return NewString("#f");
+ }
+}
+
+int CHICKEN::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;
+}
+
+ /* ------------------------------------------------------------
+ * closNameMapping()
+ * Maps the identifier from C++ to the CLOS 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 *CHICKEN::chickenNameMapping(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 (clossymnameprefix) {
+ Printf(n, "%s%s", clossymnameprefix, name);
+ } else {
+ Printf(n, "%s", name);
+ }
+ } else {
+ if (useclassprefix) {
+ Printf(n, "%s-%s", class_name, name);
+ } else {
+ if (clossymnameprefix) {
+ Printf(n, "%s%s", clossymnameprefix, name);
+ } else {
+ Printf(n, "%s", name);
+ }
+ }
+ }
+ return n;
+}
+
+String *CHICKEN::runtimeCode() {
+ String *s = Swig_include_sys("chickenrun.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'chickenrun.swg'\n");
+ s = NewString("");
+ }
+ return s;
+}
+
+String *CHICKEN::defaultExternalRuntimeFilename() {
+ return NewString("swigchickenrun.h");
+}
diff --git a/Source/Modules/clisp.cxx b/Source/Modules/clisp.cxx
new file mode 100644
index 0000000..665a8c2
--- /dev/null
+++ b/Source/Modules/clisp.cxx
@@ -0,0 +1,509 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * clisp.cxx
+ *
+ * clisp language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_clisp_cxx[] = "$Id: clisp.cxx 11380 2009-07-08 12:17:45Z wsfulton $";
+
+#include "swigmod.h"
+
+class CLISP:public Language {
+public:
+ File *f_cl;
+ String *module;
+ virtual void main(int argc, char *argv[]);
+ virtual int top(Node *n);
+ virtual int functionWrapper(Node *n);
+ virtual int variableWrapper(Node *n);
+ virtual int constantWrapper(Node *n);
+ virtual int classDeclaration(Node *n);
+ virtual int enumDeclaration(Node *n);
+ virtual int typedefHandler(Node *n);
+ List *entries;
+private:
+ String *get_ffi_type(Node *n, SwigType *ty);
+ String *convert_literal(String *num_param, String *type);
+ String *strip_parens(String *string);
+ int extern_all_flag;
+ int generate_typedef_flag;
+ int is_function;
+};
+
+void CLISP::main(int argc, char *argv[]) {
+ int i;
+
+ Preprocessor_define("SWIGCLISP 1", 0);
+ SWIG_library_directory("clisp");
+ SWIG_config_file("clisp.swg");
+ generate_typedef_flag = 0;
+ extern_all_flag = 0;
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-help")) {
+ Printf(stdout, "clisp Options (available with -clisp)\n");
+ Printf(stdout,
+ " -extern-all\n"
+ "\t If this option is given then clisp definitions for all the functions\n"
+ "and global variables will be created otherwise only definitions for \n"
+ "externed functions and variables are created.\n"
+ " -generate-typedef\n"
+ "\t If this option is given then def-c-type will be used to generate shortcuts\n"
+ "according to the typedefs in the input.\n");
+ } else if ((Strcmp(argv[i], "-extern-all") == 0)) {
+ extern_all_flag = 1;
+ Swig_mark_arg(i);
+ } else if ((Strcmp(argv[i], "-generate-typedef") == 0)) {
+ generate_typedef_flag = 1;
+ Swig_mark_arg(i);
+ }
+ }
+}
+
+int CLISP::top(Node *n) {
+
+ File *f_null = NewString("");
+ module = Getattr(n, "name");
+ String *output_filename;
+ entries = NewList();
+
+ /* Get the output file name */
+ String *outfile = Getattr(n, "outfile");
+
+ if (!outfile)
+ output_filename = outfile;
+ else {
+ output_filename = NewString("");
+ Printf(output_filename, "%s%s.lisp", SWIG_output_directory(), module);
+ }
+
+ f_cl = NewFile(output_filename, "w+", SWIG_output_files());
+ if (!f_cl) {
+ FileErrorDisplay(output_filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ Swig_register_filebyname("header", f_null);
+ Swig_register_filebyname("begin", f_null);
+ Swig_register_filebyname("runtime", f_null);
+ Swig_register_filebyname("wrapper", f_null);
+
+ String *header = NewString("");
+
+ Swig_banner_target_lang(header, ";;");
+
+ Printf(header, "\n(defpackage :%s\n (:use :common-lisp :ffi)", module);
+
+ Language::top(n);
+
+ Iterator i;
+
+ long len = Len(entries);
+ if (len > 0) {
+ Printf(header, "\n (:export");
+ }
+ //else nothing to export
+
+ for (i = First(entries); i.item; i = Next(i)) {
+ Printf(header, "\n\t:%s", i.item);
+ }
+
+ if (len > 0) {
+ Printf(header, ")");
+ }
+
+ Printf(header, ")\n");
+ Printf(header, "\n(in-package :%s)\n", module);
+ Printf(header, "\n(default-foreign-language :stdc)\n");
+
+ len = Tell(f_cl);
+
+ Printf(f_cl, "%s", header);
+
+ long end = Tell(f_cl);
+
+ for (len--; len >= 0; len--) {
+ end--;
+ Seek(f_cl, len, SEEK_SET);
+ int ch = Getc(f_cl);
+ Seek(f_cl, end, SEEK_SET);
+ Putc(ch, f_cl);
+ }
+
+ Seek(f_cl, 0, SEEK_SET);
+ Write(f_cl, Char(header), Len(header));
+
+ Close(f_cl);
+ Delete(f_cl); // Deletes the handle, not the file
+
+ return SWIG_OK;
+}
+
+
+int CLISP::functionWrapper(Node *n) {
+ is_function = 1;
+ String *storage = Getattr(n, "storage");
+ if (!extern_all_flag && (!storage || (Strcmp(storage, "extern") && Strcmp(storage, "externc"))))
+ return SWIG_OK;
+
+ String *func_name = Getattr(n, "sym:name");
+
+ ParmList *pl = Getattr(n, "parms");
+
+ int argnum = 0, first = 1;
+
+ Printf(f_cl, "\n(ffi:def-call-out %s\n\t(:name \"%s\")\n", func_name, func_name);
+
+ Append(entries, func_name);
+
+ if (ParmList_len(pl) != 0) {
+ Printf(f_cl, "\t(:arguments ");
+ }
+ for (Parm *p = pl; p; p = nextSibling(p), argnum++) {
+
+ String *argname = Getattr(p, "name");
+ // SwigType *argtype;
+
+ String *ffitype = get_ffi_type(n, Getattr(p, "type"));
+
+ int tempargname = 0;
+
+ if (!argname) {
+ argname = NewStringf("arg%d", argnum);
+ tempargname = 1;
+ }
+
+ if (!first) {
+ Printf(f_cl, "\n\t\t");
+ }
+ Printf(f_cl, "(%s %s)", argname, ffitype);
+ first = 0;
+
+ Delete(ffitype);
+
+ if (tempargname)
+ Delete(argname);
+ }
+ if (ParmList_len(pl) != 0) {
+ Printf(f_cl, ")\n"); /* finish arg list */
+ }
+ String *ffitype = get_ffi_type(n, Getattr(n, "type"));
+ if (Strcmp(ffitype, "NIL")) { //when return type is not nil
+ Printf(f_cl, "\t(:return-type %s)\n", ffitype);
+ }
+ Printf(f_cl, "\t(:library +library-name+))\n");
+
+ return SWIG_OK;
+}
+
+
+int CLISP::constantWrapper(Node *n) {
+ is_function = 0;
+ String *type = Getattr(n, "type");
+ String *converted_value = convert_literal(Getattr(n, "value"), type);
+ String *name = Getattr(n, "sym:name");
+
+ Printf(f_cl, "\n(defconstant %s %s)\n", name, converted_value);
+ Append(entries, name);
+ Delete(converted_value);
+
+ return SWIG_OK;
+}
+
+int CLISP::variableWrapper(Node *n) {
+ is_function = 0;
+ // SwigType *type=;
+ String *storage = Getattr(n, "storage");
+
+ if (!extern_all_flag && (!storage || (Strcmp(storage, "extern") && Strcmp(storage, "externc"))))
+ return SWIG_OK;
+
+ String *var_name = Getattr(n, "sym:name");
+ String *lisp_type = get_ffi_type(n, Getattr(n, "type"));
+ Printf(f_cl, "\n(ffi:def-c-var %s\n (:name \"%s\")\n (:type %s)\n", var_name, var_name, lisp_type);
+ Printf(f_cl, "\t(:library +library-name+))\n");
+ Append(entries, var_name);
+
+ Delete(lisp_type);
+ return SWIG_OK;
+}
+
+int CLISP::typedefHandler(Node *n) {
+ if (generate_typedef_flag) {
+ is_function = 0;
+ Printf(f_cl, "\n(ffi:def-c-type %s %s)\n", Getattr(n, "name"), get_ffi_type(n, Getattr(n, "type")));
+ }
+
+ return Language::typedefHandler(n);
+}
+
+int CLISP::enumDeclaration(Node *n) {
+ is_function = 0;
+ String *name = Getattr(n, "sym:name");
+
+ Printf(f_cl, "\n(ffi:def-c-enum %s ", name);
+
+ for (Node *c = firstChild(n); c; c = nextSibling(c)) {
+
+ String *slot_name = Getattr(c, "name");
+ String *value = Getattr(c, "enumvalue");
+
+ Printf(f_cl, "(%s %s)", slot_name, value);
+
+ Append(entries, slot_name);
+
+ Delete(value);
+ }
+
+ Printf(f_cl, ")\n");
+ return SWIG_OK;
+}
+
+
+// Includes structs
+int CLISP::classDeclaration(Node *n) {
+ is_function = 0;
+ String *name = Getattr(n, "sym:name");
+ String *kind = Getattr(n, "kind");
+
+ if (Strcmp(kind, "struct")) {
+ Printf(stderr, "Don't know how to deal with %s kind of class yet.\n", kind);
+ Printf(stderr, " (name: %s)\n", name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+
+ Printf(f_cl, "\n(ffi:def-c-struct %s", name);
+
+ Append(entries, NewStringf("make-%s", name));
+
+ for (Node *c = firstChild(n); c; c = nextSibling(c)) {
+
+ if (Strcmp(nodeType(c), "cdecl")) {
+ Printf(stderr, "Structure %s has a slot that we can't deal with.\n", name);
+ Printf(stderr, "nodeType: %s, name: %s, type: %s\n", nodeType(c), Getattr(c, "name"), Getattr(c, "type"));
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ String *temp = Copy(Getattr(c, "decl"));
+ Append(temp, Getattr(c, "type")); //appending type to the end, otherwise wrong type
+ String *lisp_type = get_ffi_type(n, temp);
+ Delete(temp);
+
+ String *slot_name = Getattr(c, "sym:name");
+ Printf(f_cl, "\n\t(%s %s)", slot_name, lisp_type);
+
+ Append(entries, NewStringf("%s-%s", name, slot_name));
+
+ Delete(lisp_type);
+ }
+
+ Printf(f_cl, ")\n");
+
+ /* Add this structure to the known lisp types */
+ //Printf(stdout, "Adding %s foreign type\n", name);
+ // add_defined_foreign_type(name);
+
+ return SWIG_OK;
+}
+
+/* utilities */
+/* returns new string w/ parens stripped */
+String *CLISP::strip_parens(String *string) {
+ char *s = Char(string), *p;
+ int len = Len(string);
+ String *res;
+
+ if (len == 0 || s[0] != '(' || s[len - 1] != ')') {
+ return NewString(string);
+ }
+
+ p = (char *) malloc(len - 2 + 1);
+ if (!p) {
+ Printf(stderr, "Malloc failed\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ strncpy(p, s + 1, len - 1);
+ p[len - 2] = 0; /* null terminate */
+
+ res = NewString(p);
+ free(p);
+
+ return res;
+}
+
+String *CLISP::convert_literal(String *num_param, String *type) {
+ String *num = strip_parens(num_param), *res;
+ char *s = Char(num);
+
+ /* Make sure doubles use 'd' instead of 'e' */
+ if (!Strcmp(type, "double")) {
+ String *updated = Copy(num);
+ if (Replace(updated, "e", "d", DOH_REPLACE_ANY) > 1) {
+ Printf(stderr, "Weird!! number %s looks invalid.\n", num);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(num);
+ return updated;
+ }
+
+ if (SwigType_type(type) == T_CHAR) {
+ /* Use CL syntax for character literals */
+ return NewStringf("#\\%s", num_param);
+ } else if (SwigType_type(type) == T_STRING) {
+ /* Use CL syntax for string literals */
+ return NewStringf("\"%s\"", num_param);
+ }
+
+ if (Len(num) < 2 || s[0] != '0') {
+ return num;
+ }
+
+ /* octal or hex */
+
+ res = NewStringf("#%c%s", s[1] == 'x' ? 'x' : 'o', s + 2);
+ Delete(num);
+
+ return res;
+}
+
+String *CLISP::get_ffi_type(Node *n, SwigType *ty) {
+ Node *node = NewHash();
+ Setattr(node, "type", ty);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *tm = Swig_typemap_lookup("in", node, "", 0);
+ Delete(node);
+
+ if (tm) {
+ return NewString(tm);
+ } else if (SwigType_ispointer(ty)) {
+ SwigType *cp = Copy(ty);
+ SwigType_del_pointer(cp);
+ String *inner_type = get_ffi_type(n, cp);
+
+ if (SwigType_isfunction(cp)) {
+ return inner_type;
+ }
+
+ SwigType *base = SwigType_base(ty);
+ String *base_name = SwigType_str(base, 0);
+
+ String *str;
+ if (!Strcmp(base_name, "int") || !Strcmp(base_name, "float") || !Strcmp(base_name, "short")
+ || !Strcmp(base_name, "double") || !Strcmp(base_name, "long") || !Strcmp(base_name, "char")) {
+
+ str = NewStringf("(ffi:c-ptr %s)", inner_type);
+ } else {
+ str = NewStringf("(ffi:c-pointer %s)", inner_type);
+ }
+ Delete(base_name);
+ Delete(base);
+ Delete(cp);
+ Delete(inner_type);
+ return str;
+ } else if (SwigType_isarray(ty)) {
+ SwigType *cp = Copy(ty);
+ String *array_dim = SwigType_array_getdim(ty, 0);
+
+ if (!Strcmp(array_dim, "")) { //dimension less array convert to pointer
+ Delete(array_dim);
+ SwigType_del_array(cp);
+ SwigType_add_pointer(cp);
+ String *str = get_ffi_type(n, cp);
+ Delete(cp);
+ return str;
+ } else {
+ SwigType_pop_arrays(cp);
+ String *inner_type = get_ffi_type(n, cp);
+ Delete(cp);
+
+ int ndim = SwigType_array_ndim(ty);
+ String *dimension;
+ if (ndim == 1) {
+ dimension = array_dim;
+ } else {
+ dimension = array_dim;
+ for (int i = 1; i < ndim; i++) {
+ array_dim = SwigType_array_getdim(ty, i);
+ Append(dimension, " ");
+ Append(dimension, array_dim);
+ Delete(array_dim);
+ }
+ String *temp = dimension;
+ dimension = NewStringf("(%s)", dimension);
+ Delete(temp);
+ }
+ String *str;
+ if (is_function)
+ str = NewStringf("(ffi:c-ptr (ffi:c-array %s %s))", inner_type, dimension);
+ else
+ str = NewStringf("(ffi:c-array %s %s)", inner_type, dimension);
+
+ Delete(inner_type);
+ Delete(dimension);
+ return str;
+ }
+ } else if (SwigType_isfunction(ty)) {
+ SwigType *cp = Copy(ty);
+ SwigType *fn = SwigType_pop_function(cp);
+ String *args = NewString("");
+ ParmList *pl = SwigType_function_parms(fn);
+ if (ParmList_len(pl) != 0) {
+ Printf(args, "(:arguments ");
+ }
+ int argnum = 0, first = 1;
+ for (Parm *p = pl; p; p = nextSibling(p), argnum++) {
+ String *argname = Getattr(p, "name");
+ SwigType *argtype = Getattr(p, "type");
+ String *ffitype = get_ffi_type(n, argtype);
+
+ int tempargname = 0;
+
+ if (!argname) {
+ argname = NewStringf("arg%d", argnum);
+ tempargname = 1;
+ }
+ if (!first) {
+ Printf(args, "\n\t\t");
+ }
+ Printf(args, "(%s %s)", argname, ffitype);
+ first = 0;
+ Delete(ffitype);
+ if (tempargname)
+ Delete(argname);
+ }
+ if (ParmList_len(pl) != 0) {
+ Printf(args, ")\n"); /* finish arg list */
+ }
+ String *ffitype = get_ffi_type(n, cp);
+ String *str = NewStringf("(ffi:c-function %s \t\t\t\t(:return-type %s))", args, ffitype);
+ Delete(fn);
+ Delete(args);
+ Delete(cp);
+ Delete(ffitype);
+ return str;
+ }
+ String *str = SwigType_str(ty, 0);
+ if (str) {
+ char *st = Strstr(str, "struct");
+ if (st) {
+ st += 7;
+ return NewString(st);
+ }
+ char *cl = Strstr(str, "class");
+ if (cl) {
+ cl += 6;
+ return NewString(cl);
+ }
+ }
+ return str;
+}
+
+extern "C" Language *swig_clisp(void) {
+ return new CLISP();
+}
diff --git a/Source/Modules/contract.cxx b/Source/Modules/contract.cxx
new file mode 100644
index 0000000..89e3150
--- /dev/null
+++ b/Source/Modules/contract.cxx
@@ -0,0 +1,354 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * contract.cxx
+ *
+ * Support for Wrap by Contract in SWIG.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_contract_cxx[] = "$Id: contract.cxx 11049 2009-01-10 01:15:03Z wsfulton $";
+
+#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"), "result");
+ 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 && !checkAttribute(n, "storage", "static")));
+ 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;
+ InClass = 1;
+ CurrentClass = n;
+ emit_children(n);
+ InClass = 0;
+ CurrentClass = 0;
+ return ret;
+}
+
+int Contracts::top(Node *n) {
+ emit_children(n);
+ return SWIG_OK;
+}
diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx
new file mode 100644
index 0000000..5713257
--- /dev/null
+++ b/Source/Modules/csharp.cxx
@@ -0,0 +1,3960 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * csharp.cxx
+ *
+ * C# language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_csharp_cxx[] = "$Id: csharp.cxx 11583 2009-08-15 23:22:20Z wsfulton $";
+
+#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;
+ 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 *module_class_code;
+ String *proxy_class_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 overriden by %pragma
+ String *module_class_modifiers; //class modifiers for module class overriden 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
+
+ // Director method stuff:
+ List *dmethods_seq;
+ Hash *dmethods_table;
+ int n_dmethods;
+ int n_directors;
+ int first_class_dmethod;
+ int curr_class_dmethod;
+
+ enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
+
+ static Parm *NewParmFromNode(SwigType *type, const_String_or_char_ptr name, Node *n) {
+ Parm *p = NewParm(type, name);
+ Setfile(p, Getfile(n));
+ Setline(p, Getline(n));
+ return p;
+ }
+
+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),
+ 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),
+ module_class_code(NULL),
+ proxy_class_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),
+ dmethods_seq(NULL),
+ dmethods_table(NULL),
+ n_dmethods(0),
+ n_directors(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
+ * ----------------------------------------------------------------------------- */
+
+ String *getProxyName(SwigType *t) {
+ if (proxy_flag) {
+ Node *n = classLookup(t);
+ if (n) {
+ return Getattr(n, "sym:name");
+ }
+ }
+ return NULL;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * directorClassName()
+ * ----------------------------------------------------------------------------- */
+
+ String *directorClassName(Node *n) {
+ String *dirclassname;
+ const char *attrib = "director:classname";
+
+ if (!(dirclassname = Getattr(n, attrib))) {
+ String *classname = Getattr(n, "sym:name");
+
+ dirclassname = NewStringf("SwigDirector_%s", classname);
+ Setattr(n, attrib, dirclassname);
+ }
+
+ return dirclassname;
+ }
+
+ /* ------------------------------------------------------------
+ * 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]);
+ 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], "-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();
+ }
+
+ /* ---------------------------------------------------------------------
+ * 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"));
+ }
+
+ 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 (!namespce)
+ namespce = NewString("");
+ if (!dllimport)
+ dllimport = Copy(module_class_name);
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n");
+ Printf(f_runtime, "#define SWIGCSHARP\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)
+ Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h));
+ }
+
+ Printf(f_runtime, "\n");
+
+ Swig_name_register((char *) "wrapper", (char *) "CSharp_%f");
+ if (old_variable_names) {
+ Swig_name_register((char *) "set", (char *) "set_%v");
+ Swig_name_register((char *) "get", (char *) "get_%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.swg", f_runtime);
+ }
+ // Generate the intermediary class
+ {
+ String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), 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);
+
+ addOpenNamespace(namespce, 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(namespce, f_im);
+
+ Close(f_im);
+ }
+
+ // Generate the C# module class
+ {
+ String *filen = NewStringf("%s%s.cs", 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);
+
+ addOpenNamespace(namespce, 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(namespce, f_module);
+
+ Close(f_module);
+ }
+
+ 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");
+
+ Close(f_runtime_h);
+ 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);
+ Close(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 *decl, String *overloaded_name) {
+ UpcallData *udata;
+ String *imclass_methodidx;
+ String *class_methodidx;
+ Hash *new_udata;
+ String *key = NewStringf("%s|%s", imclass_method, decl);
+
+ ++curr_class_dmethod;
+
+ /* Do we know about this director class already? */
+ if ((udata = Getattr(dmethods_table, key))) {
+ Delete(key);
+ return Getattr(udata, "methodoff");
+ }
+
+ imclass_methodidx = NewStringf("%d", n_dmethods);
+ class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
+ n_dmethods++;
+
+ new_udata = NewHash();
+ Append(dmethods_seq, new_udata);
+ Setattr(dmethods_table, key, new_udata);
+
+ Setattr(new_udata, "method", Copy(class_method));
+ // TODO: remove fdesc
+// Setattr(new_udata, "fdesc", Copy(class_desc));
+// Setattr(new_udata, "imclass_method", Copy(imclass_method));
+// Setattr(new_udata, "imclass_methodidx", imclass_methodidx);
+ 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))
+ 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 {
+ Printf(stderr, "%s : Line %d. No return type for %%native method %s.\n", input_file, line_number, 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;
+ int num_required = 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;
+ }
+
+ /*
+ 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"))
+ return SWIG_OK;
+ }
+
+ Printv(imclass_class_code, "\n [DllImport(\"", dllimport, "\", EntryPoint=\"CSharp_", overloaded_name, "\")]\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);
+ num_required = emit_num_required(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 ((tm = Getattr(p, "tmap:throws"))) {
+ canThrow(n, "throws", p);
+ }
+ }
+ }
+
+ String *null_attribute = 0;
+ // Now write code to make the function call
+ if (!native_function_flag) {
+ if (Cmp(nodeType(n), "constant") == 0) {
+ // Wrapping a constant hack
+ Swig_save("functionWrapper", n, "wrap:action", NIL);
+
+ // below based on Swig_VargetToFunction()
+ SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n));
+ Setattr(n, "wrap:action", NewStringf("result = (%s) %s;", SwigType_lstr(ty, 0), Getattr(n, "value")));
+ }
+
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ if (Cmp(nodeType(n), "constant") == 0)
+ Swig_restore(n);
+
+ /* Return value if necessary */
+ if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
+ canThrow(n, "out", n);
+ Replaceall(tm, "$source", "result"); /* 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, "result", 0))) {
+ canThrow(n, "newfree", n);
+ Replaceall(tm, "$source", "result"); /* 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, "result", 0))) {
+ canThrow(n, "ret", n);
+ Replaceall(tm, "$source", "result"); /* 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(Swig_name_member(proxy_class_name, 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;
+ }
+
+ /* ----------------------------------------------------------------------
+ * 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;
+
+ 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
+
+ // 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);
+ } 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 *filen = NewStringf("%s%s.cs", SWIG_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);
+
+ addOpenNamespace(namespce, f_enum);
+
+ Printv(f_enum, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements
+ "\n", enum_code, "\n", NIL);
+
+ addCloseNamespace(namespce, f_enum);
+
+ Close(f_enum);
+ }
+ } 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;
+ }
+ 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");
+ 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);
+
+ {
+ EnumFeature enum_feature = decodeEnumFeature(parentNode(n));
+
+ if ((enum_feature == ProperEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) {
+ // Wrap (non-anonymous) C/C++ enum with a proper C# enum
+ // Emit the enum item.
+ if (!GetFlag(n, "firstenumitem"))
+ Printf(enum_code, ",\n");
+ 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
+ const String *parent_name = Getattr(parentNode(n), "name");
+ String *typemap_lookup_type = parent_name ? Copy(parent_name) : NewString("int");
+ const String *tm = typemapLookup(n, "cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF);
+ String *return_type = Copy(tm);
+ Delete(typemap_lookup_type);
+ typemap_lookup_type = NULL;
+
+ // The %csconst feature determines how the constant value is obtained
+ int const_feature_flag = GetFlag(n, "feature:cs:const");
+
+ const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ if ((enum_feature == TypesafeEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) {
+ // Wrap (non-anonymouse) 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
+ 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);
+ }
+ }
+
+ // Add the enum value to the comma separated list being constructed in the enum declaration.
+ String *enumvalues = Getattr(parentNode(n), "enumvalues");
+ if (!enumvalues)
+ Setattr(parentNode(n), "enumvalues", Copy(symname));
+ else
+ Printv(enumvalues, ", ", symname, NIL);
+ }
+
+ 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");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ String *return_type = NewString("");
+ String *constants_code = NewString("");
+
+ if (!addSymbol(symname, n))
+ return SWIG_ERROR;
+
+ bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
+
+ // 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));
+ }
+
+ // Add the stripped quotes back in
+ String *new_value = NewString("");
+ Swig_save("constantWrapper", n, "value", NIL);
+ 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 *outattributes = Getattr(n, "tmap:cstype:outattributes");
+ if (outattributes)
+ Printf(constants_code, " %s\n", outattributes);
+ const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname;
+
+ 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, imclass_name, Swig_name_get(symname));
+ } else {
+ // This handles function pointers using the %constant directive
+ Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, imclass_name, Swig_name_get(symname));
+ }
+ } else
+ Printf(constants_code, "%s.%s();\n", imclass_name, Swig_name_get(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
+ 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) {
+ String *code = Getattr(n, "code");
+ Replaceall(code, "$module", module_class_name);
+ Replaceall(code, "$imclassname", imclass_name);
+ Replaceall(code, "$dllimport", dllimport);
+ return Language::insertDirective(n);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * 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 {
+ Printf(stderr, "%s : Line %d. Unrecognized pragma.\n", input_file, line_number);
+ }
+ Delete(strvalue);
+ }
+ }
+ return Language::pragmaDirective(n);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * emitProxyClassDefAndCPPCasts()
+ * ----------------------------------------------------------------------------- */
+
+ void emitProxyClassDefAndCPPCasts(Node *n) {
+ String *c_classname = SwigType_namestr(Getattr(n, "name"));
+ String *c_baseclass = NULL;
+ String *baseclass = NULL;
+ String *c_baseclassname = NULL;
+ SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
+ bool feature_director = Swig_directorclass(n) ? true : false;
+
+ // 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 && GetFlag(base.item, "feature:ignore")) {
+ base = Next(base);
+ }
+ if (base.item) {
+ c_baseclassname = Getattr(base.item, "name");
+ baseclass = Copy(getProxyName(c_baseclassname));
+ if (baseclass)
+ c_baseclass = SwigType_namestr(Getattr(base.item, "name"));
+ base = Next(base);
+ /* 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_CSHARP_MULTIPLE_INHERITANCE, input_file, line_number,
+ "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#.\n", proxyclassname, baseclassname);
+ base = Next(base);
+ }
+ }
+ }
+ }
+
+ bool derived = baseclass && getProxyName(c_baseclassname);
+ 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;
+ Delete(baseclass);
+ baseclass = NULL;
+ if (purebase_notderived)
+ Swig_error(input_file, line_number, "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, input_file, line_number,
+ "Warning for %s proxy: 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);
+ // Start writing the proxy class
+ 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(pure_interfaces)) ? " : " : "", wanted_base, (*Char(wanted_base) && *Char(pure_interfaces)) ? // Interfaces
+ ", " : "", pure_interfaces, " {", 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 Dispose method
+ // Note that the method name is specified in a typemap attribute called methodname
+ String *destruct = NewString("");
+ const String *tm = NULL;
+ attributes = NewHash();
+ String *destruct_methodname = NULL;
+ String *destruct_methodmodifiers = NULL;
+ if (derived) {
+ tm = typemapLookup(n, "csdestruct_derived", typemap_lookup_type, WARN_NONE, attributes);
+ destruct_methodname = Getattr(attributes, "tmap:csdestruct_derived:methodname");
+ destruct_methodmodifiers = Getattr(attributes, "tmap:csdestruct_derived:methodmodifiers");
+ } else {
+ tm = typemapLookup(n, "csdestruct", typemap_lookup_type, WARN_NONE, attributes);
+ destruct_methodname = Getattr(attributes, "tmap:csdestruct:methodname");
+ destruct_methodmodifiers = Getattr(attributes, "tmap:csdestruct:methodmodifiers");
+ }
+ if (tm && *Char(tm)) {
+ if (!destruct_methodname) {
+ Swig_error(input_file, line_number, "No methodname attribute defined in csdestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
+ }
+ if (!destruct_methodmodifiers) {
+ Swig_error(input_file, line_number,
+ "No methodmodifiers attribute defined in csdestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name);
+ }
+ }
+ // Emit the Finalize and Dispose methods
+ if (tm) {
+ // Finalize method
+ if (*Char(destructor_call)) {
+ Printv(proxy_class_def, typemapLookup(n, "csfinalize", typemap_lookup_type, WARN_NONE), NIL);
+ }
+ // Dispose method
+ Printv(destruct, tm, NIL);
+ if (*Char(destructor_call))
+ Replaceall(destruct, "$imcall", destructor_call);
+ else
+ Replaceall(destruct, "$imcall", "throw new MethodAccessException(\"C++ destructor does not have public access\")");
+ if (*Char(destruct))
+ Printv(proxy_class_def, "\n ", destruct_methodmodifiers, " ", derived ? "override" : "virtual", " void ", destruct_methodname, "() ", destruct, "\n",
+ 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(SwigDirector%s);\n", methid, proxy_class_name, methid, overname);
+ }
+ Printf(proxy_class_code, " %s.%s_director_connect(swigCPtr", imclass_name, proxy_class_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, Type[] methodTypes) {\n");
+ Printf(proxy_class_code,
+ " System.Reflection.MethodInfo methodInfo = this.GetType().GetMethod(methodName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | 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(attributes);
+ Delete(destruct);
+
+ // Emit extra user code
+ Printv(proxy_class_def, typemapLookup(n, "cscode", typemap_lookup_type, WARN_NONE), // extra C# code
+ "\n", NIL);
+
+ // Substitute various strings into the above template
+ Replaceall(proxy_class_code, "$csclassname", proxy_class_name);
+ Replaceall(proxy_class_def, "$csclassname", proxy_class_name);
+
+ Replaceall(proxy_class_def, "$module", module_class_name);
+ Replaceall(proxy_class_code, "$module", module_class_name);
+
+ Replaceall(proxy_class_def, "$imclassname", imclass_name);
+ Replaceall(proxy_class_code, "$imclassname", imclass_name);
+
+ Replaceall(proxy_class_def, "$dllimport", dllimport);
+ Replaceall(proxy_class_code, "$dllimport", dllimport);
+
+ // Add code to do C++ casting to base class (only for classes in an inheritance hierarchy)
+ if (derived) {
+ Printv(imclass_cppcasts_code, "\n [DllImport(\"", dllimport, "\", EntryPoint=\"CSharp_", proxy_class_name, "Upcast", "\")]\n", NIL);
+ Printf(imclass_cppcasts_code, " public static extern IntPtr $csclassnameUpcast(IntPtr objectRef);\n");
+
+ Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name);
+
+ Printv(upcasts_code,
+ "SWIGEXPORT $cbaseclass * SWIGSTDCALL CSharp_$imclazznameUpcast",
+ "($cclass *objectRef) {\n", " return ($cbaseclass *)objectRef;\n" "}\n", "\n", NIL);
+
+ Replaceall(upcasts_code, "$cbaseclass", c_baseclass);
+ Replaceall(upcasts_code, "$imclazzname", proxy_class_name);
+ Replaceall(upcasts_code, "$cclass", c_classname);
+ }
+ Delete(baseclass);
+ }
+
+ /* ----------------------------------------------------------------------
+ * classHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int classHandler(Node *n) {
+
+ File *f_proxy = NULL;
+ if (proxy_flag) {
+ proxy_class_name = NewString(Getattr(n, "sym:name"));
+
+ if (!addSymbol(proxy_class_name, n))
+ return SWIG_ERROR;
+
+ 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);
+ }
+
+ String *filen = NewStringf("%s%s.cs", SWIG_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);
+ filen = NULL;
+
+ // Start writing out the proxy class file
+ emitBanner(f_proxy);
+
+ addOpenNamespace(namespce, f_proxy);
+
+ Clear(proxy_class_def);
+ Clear(proxy_class_code);
+
+ destructor_call = NewString("");
+ proxy_class_constants_code = NewString("");
+ }
+
+ Language::classHandler(n);
+
+ if (proxy_flag) {
+
+ emitProxyClassDefAndCPPCasts(n);
+
+ 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(proxy_class_def, "$imclassname", imclass_name);
+ Replaceall(proxy_class_code, "$imclassname", imclass_name);
+ Replaceall(proxy_class_constants_code, "$imclassname", imclass_name);
+ Replaceall(proxy_class_def, "$dllimport", dllimport);
+ Replaceall(proxy_class_code, "$dllimport", dllimport);
+ Replaceall(proxy_class_constants_code, "$dllimport", dllimport);
+
+ Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
+
+ // Write out all the constants
+ if (Len(proxy_class_constants_code) != 0)
+ Printv(f_proxy, proxy_class_constants_code, NIL);
+
+ Printf(f_proxy, "}\n");
+ addCloseNamespace(namespce, f_proxy);
+ Close(f_proxy);
+ f_proxy = NULL;
+
+ /* Output the downcast method, if necessary. Note: There's no other really
+ good place to put this code, since Abstract Base Classes (ABCs) can and should have
+ downcasts, making the constructorHandler() a bad place (because ABCs don't get to
+ have constructors emitted.) */
+ if (GetFlag(n, "feature:javadowncast")) {
+ String *norm_name = SwigType_namestr(Getattr(n, "name"));
+
+ Printf(imclass_class_code, " public final static native %s downcast%s(long cPtrBase, boolean cMemoryOwn);\n", proxy_class_name, proxy_class_name);
+
+ Wrapper *dcast_wrap = NewWrapper();
+
+ Printf(dcast_wrap->def, "SWIGEXPORT jobject SWIGSTDCALL CSharp_downcast%s(JNIEnv *jenv, jclass jcls, jlong jCPtrBase, jboolean cMemoryOwn) {",
+ proxy_class_name);
+ Printf(dcast_wrap->code, " Swig::Director *director = (Swig::Director *) 0;\n");
+ Printf(dcast_wrap->code, " jobject jresult = (jobject) 0;\n");
+ Printf(dcast_wrap->code, " %s *obj = *((%s **)&jCPtrBase);\n", norm_name, norm_name);
+ Printf(dcast_wrap->code, " if (obj) director = dynamic_cast<Swig::Director *>(obj);\n");
+ Printf(dcast_wrap->code, " if (director) jresult = director->swig_get_self(jenv);\n");
+ Printf(dcast_wrap->code, " return jresult;\n");
+ Printf(dcast_wrap->code, "}\n");
+
+ Wrapper_print(dcast_wrap, f_wrappers);
+ DelWrapper(dcast_wrap);
+ }
+
+ emitDirectorExtraMethods(n);
+
+ Delete(proxy_class_name);
+ proxy_class_name = NULL;
+ Delete(destructor_call);
+ destructor_call = NULL;
+ Delete(proxy_class_constants_code);
+ proxy_class_constants_code = NULL;
+ }
+
+ 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(proxy_class_name, 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(proxy_class_name, 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("");
+
+ 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(Swig_name_member(proxy_class_name, 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);
+
+ Printv(imcall, 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, ", ");
+ gencomma = 2;
+ Printf(function_code, "%s %s", param_type, arg);
+
+ Delete(arg);
+ Delete(param_type);
+ }
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Printf(imcall, ")");
+ Printf(function_code, ")");
+
+ // 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(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 (this.GetType() == typeof(%s)) %s; else %s", proxy_class_name, imcall, ex_imcall);
+ else
+ Printf(excode, "((this.GetType() == typeof(%s)) ? %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, "$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) {
+ 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(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
+ 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, "$imcall", imcall);
+ excodeSubstitute(n, tm, "csvarin", p);
+ 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(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(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(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, 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 *construct_tm = Copy(typemapLookup(n, "csconstruct", Getattr(n, "name"),
+ 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, imclass_name, ".", Swig_name_destroy(symname), "(swigCPtr)", NIL);
+ }
+ 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;
+ int num_required = 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(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);
+ num_required = emit_num_required(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 {
+ // 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()", imclass_name, Swig_name_get(symname));
+ } else {
+ memberconstantHandler(n);
+ value = NewStringf("%s.%s()", imclass_name, Swig_name_get(Swig_name_member(proxy_class_name, symname)));
+ }
+ }
+ }
+ return value;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getEnumName()
+ * ----------------------------------------------------------------------------- */
+
+ String *getEnumName(SwigType *t) {
+ Node *enum_name = NULL;
+ Node *n = enumLookup(t);
+ if (n) {
+ 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)
+ enum_name = NewStringf("%s.%s", proxyname, symname);
+ else
+ enum_name = NewStringf("%s", symname);
+ Delete(scopename_prefix);
+ }
+ }
+
+ return enum_name;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * 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));
+ 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);
+ }
+
+ Delete(strippedtype);
+ Delete(type);
+
+ return substitution_performed;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substituteClassnameSpecialVariable()
+ * ----------------------------------------------------------------------------- */
+
+ void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable) {
+ if (SwigType_isenum(classnametype)) {
+ String *enumname = getEnumName(classnametype);
+ if (enumname)
+ Replaceall(tm, classnamespecialvariable, enumname);
+ else
+ Replaceall(tm, classnamespecialvariable, NewStringf("int"));
+ } else {
+ String *classname = getProxyName(classnametype);
+ if (classname) {
+ Replaceall(tm, classnamespecialvariable, classname); // getProxyName() works for pointers to classes too
+ } else { // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
+ String *descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
+ Replaceall(tm, classnamespecialvariable, descriptor);
+
+ // Add to hash table so that the type wrapper classes can be created later
+ Setattr(swig_types_hash, descriptor, classnametype);
+ Delete(descriptor);
+ }
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * 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 *makeParameterName(Node *n, Parm *p, int arg_num, bool setter) {
+
+ String *arg = 0;
+ String *pn = Getattr(p, "name");
+
+ // Use C parameter name unless it is a duplicate or an empty parameter name
+ int count = 0;
+ ParmList *plist = Getattr(n, "parms");
+ while (plist) {
+ if ((Cmp(pn, Getattr(plist, "name")) == 0))
+ count++;
+ plist = nextSibling(plist);
+ }
+ String *wrn = pn ? Swig_name_warning(p, 0, pn, 0) : 0;
+ arg = (!pn || (count > 1) || wrn) ? NewStringf("arg%d", arg_num) : Copy(pn);
+
+ if (setter && Cmp(arg, "self") != 0) {
+ // Note that in C# properties, the input variable name is always called 'value'
+ Delete(arg);
+ arg = NewString("value");
+ }
+
+ return arg;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * 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.cs", 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);
+
+ addOpenNamespace(namespce, 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);
+
+ Printv(f_swigtype, swigtype, NIL);
+
+ addCloseNamespace(namespce, f_swigtype);
+
+ Close(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;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * 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(String *namspace, File *file) {
+ if (namspace)
+ if (Len(namspace) > 0)
+ Printf(file, "namespace %s {\n", namspace);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addCloseNamespace()
+ * ----------------------------------------------------------------------------- */
+
+ void addCloseNamespace(String *namspace, File *file) {
+ if (namspace)
+ if (Len(namspace) > 0)
+ Printf(file, "\n}\n");
+ }
+
+ /*----------------------------------------------------------------------
+ * 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 *swig_director_connect = NewStringf("%s_director_connect", proxy_class_name);
+ String *sym_name = Getattr(n, "sym:name");
+ Wrapper *code_wrap;
+
+ Printv(imclass_class_code, "\n [DllImport(\"", dllimport, "\", EntryPoint=\"CSharp_", swig_director_connect, "\")]\n", NIL);
+ Printf(imclass_class_code, " public static extern void %s(HandleRef jarg1", swig_director_connect);
+
+ code_wrap = NewWrapper();
+ Printf(code_wrap->def, "SWIGEXPORT void SWIGSTDCALL CSharp_%s(void *objarg", swig_director_connect);
+
+ Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", norm_name, norm_name);
+ Printf(code_wrap->code, " SwigDirector_%s *director = dynamic_cast<SwigDirector_%s *>(obj);\n", sym_name, sym_name);
+ // TODO: if statement not needed?? - Java too
+ Printf(code_wrap->code, " if (director) {\n");
+ 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, "SwigDirector_%s::SWIG_Callback%s_t callback%s", sym_name, methid, methid);
+ Printf(code_wrap->code, "callback%s", methid);
+ Printf(imclass_class_code, ", %s.SwigDelegate%s_%s delegate%s", sym_name, sym_name, methid, methid);
+ }
+
+ Printf(code_wrap->def, ") {\n");
+ Printf(code_wrap->code, ");\n");
+ Printf(imclass_class_code, ");\n");
+ Printf(code_wrap->code, " }\n");
+ Printf(code_wrap->code, "}\n");
+
+ Wrapper_print(code_wrap, f_wrappers);
+ DelWrapper(code_wrap);
+
+ Delete(swig_director_connect);
+ }
+
+ /* ---------------------------------------------------------------
+ * 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 *empty_str = NewString("");
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ SwigType *returntype = Getattr(n, "returntype");
+ 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 = NewString("");
+ 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("");
+ int gencomma = 0;
+ 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(classname, overloaded_name));
+
+ if (returntype) {
+
+ qualified_return = SwigType_rcaststr(returntype, "c_result");
+
+ if (!is_void && !ignored_method) {
+ 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, "abstract"))) {
+ /* 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. */
+ String *non_ref_type = Copy(returntype);
+
+ /* Remove reference and const qualifiers */
+ Replaceall(non_ref_type, "r.", "");
+ Replaceall(non_ref_type, "q(const).", "");
+ Wrapper_add_localv(w, "result_default", "static", SwigType_str(non_ref_type, "result_default"), "=", SwigType_str(non_ref_type, "()"), NIL);
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= &result_default", NIL);
+
+ Delete(non_ref_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 */
+ Parm *tp = NewParmFromNode(returntype, empty_str, n);
+
+ tm = Swig_typemap_lookup("imtype", tp, "", 0);
+ if (tm) {
+ String *imtypeout = Getattr(tp, "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(tp, "tmap:imtype:directoroutattributes");
+ if (im_directoroutattributes) {
+ Printf(callback_def, " %s\n", im_directoroutattributes);
+ Printf(director_delegate_definitions, " %s\n", im_directoroutattributes);
+ }
+
+ Printf(callback_def, " private %s SwigDirector%s(", tm, overloaded_name);
+ if (!ignored_method)
+ Printf(director_delegate_definitions, " public delegate %s", tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(returntype, 0));
+ }
+
+ Parm *retpm = NewParmFromNode(returntype, empty_str, n);
+
+ if ((c_ret_type = Swig_typemap_lookup("ctype", retpm, "", 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;
+ }
+
+ Delete(retpm);
+ }
+
+ /* Go through argument list, attach lnames for arguments */
+ for (i = 0, p = l; p; p = nextSibling(p), ++i) {
+ String *arg = Getattr(p, "name");
+ String *lname = NewString("");
+
+ if (!arg && Cmp(Getattr(p, "type"), "void")) {
+ lname = NewStringf("arg%d", i);
+ Setattr(p, "name", lname);
+ } else
+ lname = arg;
+
+ Setattr(p, "lname", lname);
+ }
+
+ /* 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, 0);
+ Swig_typemap_attach_parms("csdirectorin", l, 0);
+
+ /* 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, " throw Swig::DirectorPureVirtualException(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
+ }
+
+ if (!ignored_method)
+ Printf(w->code, "} else {\n");
+
+ /* Go through argument list, convert from native to Java */
+ for (p = l; p; /* empty */ ) {
+ /* Is this superfluous? */
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Copy(Getattr(p, "name"));
+ String *c_param_type = NULL;
+ String *c_decl = NewString("");
+ String *arg = NewString("");
+
+ Printf(arg, "j%s", ln);
+
+ /* And add to the upcall args */
+ if (gencomma > 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;
+
+ Parm *tp = NewParmFromNode(c_param_type, empty_str, n);
+ String *desc_tm = 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 */
+ if ((desc_tm = Swig_typemap_lookup("directorin", tp, "", 0))
+ && (tm = Getattr(p, "tmap:directorin"))) {
+
+ Replaceall(tm, "$input", arg);
+ Replaceall(tm, "$owner", "0");
+
+ if (Len(tm))
+ if (!ignored_method)
+ Printf(w->code, "%s\n", tm);
+
+ Delete(tm);
+
+ /* Add C type to callback typedef */
+ if (gencomma > 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);
+
+ if (gencomma > 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);
+ 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");
+
+ Delete(desc_tm);
+ } else {
+ if (!desc_tm) {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_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 (!tm) {
+ 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;
+ }
+
+ Delete(tp);
+ } 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);
+ }
+
+ gencomma++;
+ Delete(arg);
+ Delete(c_decl);
+ Delete(c_param_type);
+ }
+
+ /* header declaration, start wrapper definition */
+ String *target;
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : type;
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ target = Swig_method_decl(rtype, decl, name, l, 0, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Add any exception specifications to the methods in the director class
+ 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 ((tm = 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 (!is_void) {
+ Parm *tp = NewParmFromNode(returntype, empty_str, n);
+
+ if ((tm = Swig_typemap_lookup("csdirectorout", tp, "", 0))) {
+ substituteClassname(returntype, tm);
+ Replaceall(tm, "$cscall", upcall);
+
+ Printf(callback_code, " return %s;\n", tm);
+ }
+
+ Delete(tm);
+ Delete(tp);
+ } 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(%s);\n", overloaded_name, jupcall_args);
+
+ if (!is_void) {
+ String *jresult_str = NewString("jresult");
+ String *result_str = NewString("c_result");
+ Parm *tp = NewParmFromNode(returntype, result_str, n);
+
+ /* Copy jresult into c_result... */
+ if ((tm = Swig_typemap_lookup("directorout", tp, 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(tp);
+ Delete(jresult_str);
+ Delete(result_str);
+ }
+
+ /* 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 code */
+ 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")) {
+ 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");
+
+ 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 Type[] swigMethodTypes%s = new Type[] { %s };\n", methid, proxy_method_types);
+ Printf(director_connect_parms, "SwigDirector%s%s delegate%s", classname, methid, methid);
+ }
+
+ Delete(qualified_return);
+ Delete(c_ret_type);
+ Delete(declaration);
+ Delete(callback_typedef_parms);
+ Delete(delegate_parms);
+ Delete(proxy_method_types);
+ Delete(callback_def);
+ Delete(callback_code);
+ 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 *classname = 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, classname, parms, 0, 0);
+ String *call = Swig_csuperclass_call(0, basetype, superparms);
+ String *classtype = SwigType_namestr(Getattr(n, "name"));
+
+ Printf(f_directors, "%s::%s : %s, %s {\n", classname, 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, classname, parms, 0, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Delete(sub);
+ Delete(supername);
+ Delete(parms);
+ return Language::classDirectorConstructor(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDefaultConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorDefaultConstructor(Node *n) {
+ String *classname = Swig_class_name(n);
+ String *classtype = SwigType_namestr(Getattr(n, "name"));
+ Wrapper *w = NewWrapper();
+
+ Printf(w->def, "SwigDirector_%s::SwigDirector_%s() : %s {", classname, classname, Getattr(n, "director:ctor"));
+ Printf(w->code, "}\n");
+ Wrapper_print(w, f_directors);
+
+ Printf(f_directors_h, " SwigDirector_%s();\n", classname);
+ DelWrapper(w);
+ Delete(classtype);
+ Delete(classname);
+ 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");
+
+ Java_director_declaration(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);
+ }
+
+ /* ----------------------------------------------------------------------
+ * classDirectorDestructor()
+ * ---------------------------------------------------------------------- */
+
+ int classDirectorDestructor(Node *n) {
+ Node *current_class = getCurrentClass();
+ String *full_classname = Getattr(current_class, "name");
+ String *classname = Swig_class_name(current_class);
+ Wrapper *w = NewWrapper();
+
+ if (Getattr(n, "throw")) {
+ Printf(f_directors_h, " virtual ~SwigDirector_%s() throw ();\n", classname);
+ Printf(w->def, "SwigDirector_%s::~SwigDirector_%s() throw () {\n", classname, classname);
+ } else {
+ Printf(f_directors_h, " virtual ~SwigDirector_%s();\n", classname);
+ Printf(w->def, "SwigDirector_%s::~SwigDirector_%s() {\n", classname, classname);
+ }
+
+ /* Ensure that correct directordisconnect typemap's method name is called
+ * here: */
+
+ const String *disconn_tm = NULL;
+ Node *disconn_attr = NewHash();
+ String *disconn_methodname = NULL;
+
+ disconn_tm = typemapLookup(n, "directordisconnect", full_classname, WARN_NONE, disconn_attr);
+ disconn_methodname = Getattr(disconn_attr, "tmap:directordisconnect:methodname");
+
+ Printv(w->code, "}\n", NIL);
+
+ Wrapper_print(w, f_directors);
+
+ DelWrapper(w);
+ Delete(disconn_attr);
+ Delete(classname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorEnd()
+ * ------------------------------------------------------------ */
+
+ 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(");
+
+ Printf(w->def, "void %s::swig_connect_director(", director_classname);
+
+ 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_callback_typedefs) > 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", 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);
+ }
+
+ /* --------------------------------------------------------------------
+ * classDirectorDisown()
+ * ------------------------------------------------------------------*/
+ virtual int classDirectorDisown(Node *n) {
+ (void) n;
+ return SWIG_OK;
+ }
+
+ /*----------------------------------------------------------------------
+ * extraDirectorProtectedCPPMethodsRequired()
+ *--------------------------------------------------------------------*/
+
+ bool extraDirectorProtectedCPPMethodsRequired() const {
+ return false;
+ }
+
+ /*----------------------------------------------------------------------
+ * Java_director_declaration()
+ *
+ * Generate the director class's declaration
+ * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
+ *--------------------------------------------------------------------*/
+
+ void Java_director_declaration(Node *n) {
+
+ String *base = Getattr(n, "classtype");
+ String *class_ctor = NewString("Swig::Director()");
+
+ String *classname = Swig_class_name(n);
+ String *directorname = NewStringf("SwigDirector_%s", classname);
+ 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);
+ }
+
+}; /* 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 = (char *) "\
+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\
+\n";
diff --git a/Source/Modules/directors.cxx b/Source/Modules/directors.cxx
new file mode 100644
index 0000000..158b535
--- /dev/null
+++ b/Source/Modules/directors.cxx
@@ -0,0 +1,288 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * directors.cxx
+ *
+ * Director support functions.
+ * Not all of these may be necessary, and some may duplicate existing functionality
+ * in SWIG. --MR
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_directors_cxx[] = "$Id";
+
+#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;
+}
+
+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 = 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;
+}
+
+
+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
+ *
+ * Misnamed and misappropriated! Taken from SWIG's type string manipulation utilities
+ * and modified to generate full (or partial) type qualifiers for method declarations,
+ * local variable declarations, and return value casting. More importantly, it merges
+ * parameter type information with actual parameter names to produce a complete method
+ * declaration that fully mirrors the original method declaration.
+ *
+ * There is almost certainly a saner way to do this.
+ *
+ * This function needs to be cleaned up and possibly split into several smaller
+ * functions. For instance, attaching default names to parameters should be done in a
+ * separate function.
+ *
+ */
+
+String *Swig_method_decl(SwigType *returntype, SwigType *decl, const_String_or_char_ptr id, List *args, int strip, int values) {
+ String *result;
+ List *elements;
+ String *element = 0, *nextelement;
+ int is_const = 0;
+ int nelements, i;
+ int is_func = 0;
+ int arg_idx = 0;
+
+ if (id) {
+ result = NewString(Char(id));
+ } else {
+ result = NewString("");
+ }
+
+ elements = SwigType_split(decl);
+ nelements = Len(elements);
+ if (nelements > 0) {
+ element = Getitem(elements, 0);
+ }
+ for (i = 0; i < nelements; i++) {
+ if (i < (nelements - 1)) {
+ nextelement = Getitem(elements, i + 1);
+ } else {
+ nextelement = 0;
+ }
+ if (SwigType_isqualifier(element)) {
+ int skip = 0;
+ DOH *q = 0;
+ if (!strip) {
+ q = SwigType_parm(element);
+ if (!Cmp(q, "const")) {
+ is_const = 1;
+ is_func = SwigType_isfunction(nextelement);
+ if (is_func)
+ skip = 1;
+ skip = 1;
+ }
+ if (!skip) {
+ Insert(result, 0, " ");
+ Insert(result, 0, q);
+ }
+ Delete(q);
+ }
+ } else if (SwigType_isfunction(element)) {
+ Parm *parm;
+ String *p;
+ Append(result, "(");
+ parm = args;
+ while (parm != 0) {
+ 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);
+ }
+ if (!name) {
+ name = NewString("");
+ }
+ p = SwigType_str(type, name);
+ Append(result, p);
+ String *value = Getattr(parm, "value");
+ if (values && (value != 0)) {
+ Printf(result, " = %s", value);
+ }
+ parm = nextSibling(parm);
+ if (parm != 0)
+ Append(result, ", ");
+ }
+ Append(result, ")");
+ } else if (returntype) { // This check is intended for conversion operators to a pointer/reference which needs the pointer/reference ignoring in the declaration
+ if (SwigType_ispointer(element)) {
+ Insert(result, 0, "*");
+ if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ } else if (SwigType_ismemberpointer(element)) {
+ String *q;
+ q = SwigType_parm(element);
+ Insert(result, 0, "::*");
+ Insert(result, 0, q);
+ if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ Delete(q);
+ } else if (SwigType_isreference(element)) {
+ Insert(result, 0, "&");
+ } else if (SwigType_isarray(element)) {
+ DOH *size;
+ Append(result, "[");
+ size = SwigType_parm(element);
+ Append(result, size);
+ Append(result, "]");
+ Delete(size);
+ } else {
+ if (Strcmp(element, "v(...)") == 0) {
+ Insert(result, 0, "...");
+ } else {
+ String *bs = SwigType_namestr(element);
+ Insert(result, 0, " ");
+ Insert(result, 0, bs);
+ Delete(bs);
+ }
+ }
+ }
+ element = nextelement;
+ }
+
+ Delete(elements);
+
+ if (is_const) {
+ if (is_func) {
+ Append(result, " ");
+ Append(result, "const");
+ } else {
+ Insert(result, 0, "const ");
+ }
+ }
+
+ Chop(result);
+
+ if (returntype) {
+ Insert(result, 0, " ");
+ String *rtype = SwigType_str(returntype, 0);
+ Insert(result, 0, rtype);
+ Delete(rtype);
+ }
+
+ 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) && !(checkAttribute(n, "staticmemberfunctionHandler:storage", "static") ||
+ checkAttribute(n, "storage", "static"))
+ && !Equal(nodeType(n), "constructor"))) {
+ Node *parent = Getattr(n, "parentNode");
+ String *symname = Getattr(parent, "sym:name");
+ String *dirname = NewStringf("SwigDirector_%s", symname);
+ String *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);
+ }
+}
+
diff --git a/Source/Modules/emit.cxx b/Source/Modules/emit.cxx
new file mode 100644
index 0000000..99631c1
--- /dev/null
+++ b/Source/Modules/emit.cxx
@@ -0,0 +1,512 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * emit.cxx
+ *
+ * Useful functions for emitting various pieces of code.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_emit_cxx[] = "$Id: emit.cxx 11471 2009-07-29 20:52:29Z wsfulton $";
+
+#include "swigmod.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, "result");
+ if (SwigType_ispointer(lt)) {
+ Wrapper_add_localv(f, "result", lstr, "= 0", NULL);
+ } else {
+ Wrapper_add_local(f, "result", 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;
+ String *tm;
+ while (p) {
+ 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"))) {
+ Setattr(l, "emit:varargs", lp);
+ break;
+ }
+ 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 function is a varargs function
+ * ----------------------------------------------------------------------------- */
+
+int emit_isvarargs(ParmList *p) {
+ if (!p)
+ return 0;
+ if (Getattr(p, "emit:varargs"))
+ return 1;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * 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, "$")) {
+ Replaceall(tm, "$name", Getattr(n, "name"));
+ Replaceall(tm, "$symname", Getattr(n, "sym:name"));
+ Replaceall(tm, "$function", eaction); // deprecated
+ Replaceall(tm, "$action", eaction);
+ Replaceall(tm, "$wrapname", Getattr(n, "wrap:name"));
+ String *overloaded = Getattr(n, "sym:overloaded");
+ Replaceall(tm, "$overname", overloaded ? Char(Getattr(n, "sym:overname")) : "");
+
+ if (Strstr(tm, "$decl")) {
+ String *decl = Swig_name_decl(n);
+ Replaceall(tm, "$decl", decl);
+ Delete(decl);
+ }
+ if (Strstr(tm, "$fulldecl")) {
+ String *fulldecl = Swig_name_fulldecl(n);
+ Replaceall(tm, "$fulldecl", fulldecl);
+ Delete(fulldecl);
+ }
+ }
+ 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;
+ SwigType *rt;
+ 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);
+
+ /* Get the return type */
+ rt = Getattr(n, "type");
+
+ /* 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");
+ }
+
+ Printv(eaction, action, NIL);
+
+ if (catchlist) {
+ int unknown_catch = 0;
+ Printf(eaction, "}\n");
+ 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(...) {");
+ } else {
+ Printf(eaction, "catch(%s) {", SwigType_str(et, "&_e"));
+ }
+ Printv(eaction, em, "\n", NIL);
+ Printf(eaction, "}\n");
+ } 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) {
+ Printf(eaction, "catch(...) { throw; }\n");
+ }
+ }
+
+ /* Look for except typemap (Deprecated) */
+ tm = Swig_typemap_lookup("except", n, "result", 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/Source/Modules/guile.cxx b/Source/Modules/guile.cxx
new file mode 100644
index 0000000..2520a07
--- /dev/null
+++ b/Source/Modules/guile.cxx
@@ -0,0 +1,1759 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * guile.cxx
+ *
+ * Guile language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_guile_cxx[] = "$Id: guile.cxx 11133 2009-02-20 07:52:24Z wsfulton $";
+
+#include "swigmod.h"
+
+#include <ctype.h>
+
+// Note string broken in half for compilers that can't handle long strings
+static const char *guile_usage = (char *) "\
+Guile Options (available with -guile)\n\
+ -prefix <name> - Use <name> as prefix [default \"gswig_\"]\n\
+ -package <name> - Set the path of the module to <name>\n\
+ (default NULL)\n\
+ -emitsetters - Emit procedures-with-setters for variables\n\
+ and structure slots.\n\
+ -onlysetters - Don't emit traditional getter and setter\n\
+ procedures for structure slots,\n\
+ only emit procedures-with-setters.\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\
+ -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\
+ -scmstub - Output Scheme file with module declaration and\n\
+ exports; only with `passive' and `simple' linkage\n\
+ -gh - Use the gh_ Guile API. (Guile <= 1.8) \n\
+ -scm - Use the scm Guile API. (Guile >= 1.6, default) \n\
+ -proxy - Export GOOPS class definitions\n\
+ -emitslotaccessors - Emit accessor methods for all GOOPS slots\n" "\
+ -primsuffix <suffix> - Name appended to primitive module when exporting\n\
+ GOOPS classes. (default = \"primitive\")\n\
+ -goopsprefix <prefix> - Prepend <prefix> to all goops identifiers\n\
+ -useclassprefix - Prepend the class name to all goops identifiers\n\
+ -exportprimitive - Add the (export ...) code from scmstub into the\n\
+ GOOPS file.\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 char *prefix = (char *) "gswig_";
+static char *module = 0;
+static char *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 use_scm_interface = 1;
+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") != NULL;
+ }
+}
+
+class GUILE:public Language {
+public:
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+ int i, orig_len;
+
+ 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(guile_usage, stdout);
+ SWIG_exit(EXIT_SUCCESS);
+ } else if (strcmp(argv[i], "-prefix") == 0) {
+ if (argv[i + 1]) {
+ prefix = new char[strlen(argv[i + 1]) + 2];
+ strcpy(prefix, 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 = new char[strlen(argv[i + 1]) + 2];
+ strcpy(package, 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) {
+ use_scm_interface = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-scm") == 0) {
+ use_scm_interface = 1;
+ 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 == NULL)
+ 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");
+ exit(1);
+ }
+ }
+
+ 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
+
+ orig_len = strlen(prefix);
+ if (prefix[orig_len - 1] != '_') {
+ prefix[1 + orig_len] = 0;
+ prefix[orig_len] = '_';
+ }
+
+ /* Add a symbol for this module */
+ Preprocessor_define("SWIGGUILE 1", 0);
+ /* Read in default typemaps */
+ if (use_scm_interface)
+ SWIG_config_file("guile_scm.swg");
+ else
+ SWIG_config_file("guile_gh.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");
+ Printf(f_runtime, "#define SWIGGUILE\n");
+
+ if (!use_scm_interface) {
+ if (SwigRuntime == 1)
+ Printf(f_runtime, "#define SWIG_GLOBAL\n");
+ if (SwigRuntime == 2)
+ Printf(f_runtime, "#define SWIG_NOINCLUDE\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);
+ Close(f_begin);
+ 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 == NULL) ? (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) ? 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 (use_scm_interface && 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
+ if (!use_scm_interface)
+ Printv(f->code, tab4, "gh_defer_ints();\n", NIL);
+
+ String *actioncode = emit_action(n);
+
+ if (!use_scm_interface)
+ Printv(actioncode, tab4, "gh_allow_ints();\n", NIL);
+
+ // Now have return value, figure out what to do with it.
+ if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
+ Replaceall(tm, "$result", "gswig_result");
+ Replaceall(tm, "$target", "gswig_result");
+ Replaceall(tm, "$source", "result");
+ 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, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ Printv(f->code, tm, "\n", NIL);
+ }
+ }
+ // Free any memory allocated by the function being wrapped..
+ if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ 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 */
+ if (use_scm_interface) {
+ Printf(f_init, "scm_c_define_gsubr(\"%s\", 0, 0, 1, (swig_guile_proc) %s_rest);\n", proc_name, wname);
+ } else {
+ Printf(f_init, "gh_new_procedure(\"%s\", (swig_guile_proc) %s_rest, 0, 0, 1);\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 = ");
+ if (use_scm_interface) {
+ /* 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);
+ } else {
+ if (only_setters && !goops)
+ Printf(f_init, "scm_make_gsubr(\"%s\", %d, %d, 0, (swig_guile_proc) %s);\n", proc_name, numreq, numargs - numreq, wname);
+ else
+ Printf(f_init, "gh_new_procedure(\"%s\", (swig_guile_proc) %s, %d, %d, 0);\n", proc_name, wname, numreq, numargs - numreq);
+ }
+ 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 */
+ if (use_scm_interface) {
+ Printf(f_init, "scm_c_define");
+ } else {
+ Printf(f_init, "gh_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 */
+ if (use_scm_interface) {
+ Printf(f_init, "scm_c_define");
+ } else {
+ Printf(f_init, "gh_define");
+ }
+ Printf(f_init, "(\"%s\", getter);\n", pws_name);
+ }
+ Printf(exported_symbols, "\"%s\", ", pws_name);
+ free(pws_name);
+ }
+ } else {
+ /* Register the function */
+ if (use_scm_interface) {
+ 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 {
+ Printf(f_init, "gh_new_procedure(\"%s\", (swig_guile_proc) %s, %d, %d, 0);\n", proc_name, wname, numreq, numargs - numreq);
+ }
+ }
+ } 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);
+ if (use_scm_interface) {
+ Printf(f_init, "scm_c_define_gsubr(\"%s\", 0, 0, 1, (swig_guile_proc) %s);\n", proc_name, dname);
+ } else {
+ Printf(f_init, "gh_new_procedure(\"%s\", (swig_guile_proc) %s, 0, 0, 1);\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, (char *) "");
+ 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 (use_scm_interface) {
+
+ 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 {
+ Printf(f_init, "\t gh_new_procedure(\"%s\", (swig_guile_proc) %s, 0, %d, 0);\n", proc_name, var_name, !GetFlag(n, "feature:immutable"));
+ }
+ } else {
+ /* Read/write variables become a procedure with setter. */
+ if (use_scm_interface) {
+ 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");
+ } else {
+ Printf(f_init, "\t{ SCM p = gh_new_procedure(\"%s\", (swig_guile_proc) %s, 0, 1, 0);\n", proc_name, var_name);
+ Printf(f_init, "gh_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, (char *) "");
+ 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 *value = Getattr(n, "value");
+ int constasvar = GetFlag(n, "feature:constasvar");
+
+
+ String *proc_name;
+ String *var_name;
+ String *rvalue;
+ 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 (SwigType_type(nctype) == T_STRING) {
+ rvalue = NewStringf("\"%s\"", value);
+ } else if (SwigType_type(nctype) == T_CHAR) {
+ rvalue = NewStringf("\'%s\'", value);
+ } else {
+ rvalue = NewString(value);
+ }
+
+ if ((tm = Swig_typemap_lookup("constant", n, name, 0))) {
+ Replaceall(tm, "$source", rvalue);
+ Replaceall(tm, "$value", rvalue);
+ Replaceall(tm, "$target", name);
+ Printv(f_header, tm, "\n", NIL);
+ } else {
+ // Create variable and assign it a value
+ Printf(f_header, "static %s = %s;\n", SwigType_lstr(nctype, var_name), rvalue);
+ }
+ {
+ /* Hack alert: will cleanup later -- Dave */
+ Node *n = NewHash();
+ Setattr(n, "name", var_name);
+ Setattr(n, "sym:name", iname);
+ Setattr(n, "type", nctype);
+ SetFlag(n, "feature:immutable");
+ if (constasvar) {
+ SetFlag(n, "feature:constasvar");
+ }
+ variableWrapper(n);
+ Delete(n);
+ }
+ Delete(var_name);
+ Delete(nctype);
+ Delete(proc_name);
+ Delete(rvalue);
+ 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 */
+ if (use_scm_interface) {
+ 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;
+ if (use_scm_interface) {
+ s = Swig_include_sys("guile_scm_run.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'guile_scm_run.swg");
+ s = NewString("");
+ }
+ } else {
+ s = Swig_include_sys("guile_gh_run.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'guile_gh_run.swg");
+ s = NewString("");
+ }
+ }
+ return s;
+ }
+
+ String *defaultExternalRuntimeFilename() {
+ if (use_scm_interface) {
+ return NewString("swigguilerun.h");
+ } else {
+ return NewString("swigguileghrun.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/Source/Modules/java.cxx b/Source/Modules/java.cxx
new file mode 100644
index 0000000..469f899
--- /dev/null
+++ b/Source/Modules/java.cxx
@@ -0,0 +1,4166 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * java.cxx
+ *
+ * Java language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_java_cxx[] = "$Id: java.cxx 11584 2009-08-16 00:04:29Z wsfulton $";
+
+#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 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
+
+ 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 *module_class_code;
+ String *proxy_class_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 *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 overriden by %pragma
+ String *module_class_modifiers; //class modifiers for module class overriden 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;
+
+ enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
+
+ static Parm *NewParmFromNode(SwigType *type, const_String_or_char_ptr name, Node *n) {
+ Parm *p = NewParm(type, name);
+ Setfile(p, Getfile(n));
+ Setline(p, Getline(n));
+ return p;
+ }
+
+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),
+ imclass_name(NULL),
+ module_class_name(NULL),
+ imclass_class_code(NULL),
+ proxy_class_def(NULL),
+ proxy_class_code(NULL),
+ module_class_code(NULL),
+ proxy_class_name(NULL),
+ variable_name(NULL),
+ proxy_class_constants_code(NULL),
+ module_class_constants_code(NULL),
+ package(NULL),
+ jnipackage(NULL),
+ package_path(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),
+ imclass_directors(NULL),
+ destructor_call(NULL),
+ destructor_throws_clause(NULL),
+ dmethods_seq(NULL),
+ dmethods_table(NULL),
+ n_dmethods(0),
+ n_directors(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
+ * ----------------------------------------------------------------------------- */
+
+ String *getProxyName(SwigType *t) {
+ if (proxy_flag) {
+ Node *n = classLookup(t);
+ if (n) {
+ return Getattr(n, "sym:name");
+ }
+ }
+ return NULL;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * makeValidJniName()
+ * ----------------------------------------------------------------------------- */
+
+ String *makeValidJniName(const String *name) {
+ String *valid_jni_name = NewString(name);
+ Replaceall(valid_jni_name, "_", "_1");
+ return valid_jni_name;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * directorClassName()
+ * ----------------------------------------------------------------------------- */
+
+ String *directorClassName(Node *n) {
+ String *dirclassname;
+ const char *attrib = "director:classname";
+
+ if (!(dirclassname = Getattr(n, attrib))) {
+ String *classname = Getattr(n, "sym:name");
+
+ dirclassname = NewStringf("SwigDirector_%s", classname);
+ Setattr(n, attrib, dirclassname);
+ }
+
+ return dirclassname;
+ }
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+
+ SWIG_library_directory("java");
+
+ // 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]);
+ 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], "-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);
+ }
+ }
+ }
+
+ // 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();
+ }
+
+ /* ---------------------------------------------------------------------
+ * 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"));
+ }
+
+ 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("");
+ imclass_directors = NewString("");
+ upcasts_code = NewString("");
+ dmethods_seq = NewList();
+ dmethods_table = NewHash();
+ n_dmethods = 0;
+ n_directors = 0;
+ if (!package)
+ package = NewString("");
+ jnipackage = NewString("");
+ package_path = NewString("");
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n#define SWIGJAVA\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)
+ Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h));
+ }
+
+ Printf(f_runtime, "\n");
+
+ String *wrapper_name = NewString("");
+
+ if (Len(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", Char(jnipackage), jniname);
+ Delete(jniname);
+
+ Swig_name_register((char *) "wrapper", Char(wrapper_name));
+ if (old_variable_names) {
+ Swig_name_register((char *) "set", (char *) "set_%v");
+ Swig_name_register((char *) "get", (char *) "get_%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.swg", f_runtime);
+ }
+ // Generate the intermediary class
+ {
+ String *filen = NewStringf("%s%s.java", SWIG_output_directory(), 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 (Len(package) > 0)
+ 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");
+ Close(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 (Len(package) > 0)
+ Printf(f_module, "package %s;\n", package);
+
+ 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, "extends %s ", module_baseclass);
+ if (Len(module_interfaces) > 0) {
+ if (Len(module_class_constants_code) != 0)
+ Printv(f_module, "implements ", Getattr(n, "name"), "Constants, ", module_interfaces, " ", NIL);
+ else
+ Printv(f_module, "implements ", module_interfaces, " ", NIL);
+ } else {
+ if (Len(module_class_constants_code) != 0)
+ Printv(f_module, "implements ", Getattr(n, "name"), "Constants ", 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");
+ Close(f_module);
+ }
+
+ // Generate the Java constants interface
+ if (Len(module_class_constants_code) != 0) {
+ String *filen = NewStringf("%s%sConstants.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 Java constants interface file
+ emitBanner(f_module);
+
+ if (Len(package) > 0)
+ Printf(f_module, "package %s;\n", package);
+
+ if (module_imports)
+ Printf(f_module, "%s\n", module_imports);
+
+ Printf(f_module, "public interface %sConstants {\n", module_class_name);
+
+ // Write out all the global constants
+ Printv(f_module, module_class_constants_code, NIL);
+
+ // Finish off the Java interface
+ Printf(f_module, "}\n");
+ Close(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_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(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");
+
+ Close(f_runtime_h);
+ 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);
+ Close(f_begin);
+ 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) {
+ UpcallData *udata;
+ String *imclass_methodidx;
+ String *class_methodidx;
+ Hash *new_udata;
+ String *key = NewStringf("%s|%s", imclass_method, decl);
+
+ ++curr_class_dmethod;
+
+ /* Do we know about this director class already? */
+ if ((udata = Getattr(dmethods_table, key))) {
+ Delete(key);
+ return Getattr(udata, "methodoff");
+ }
+
+ imclass_methodidx = NewStringf("%d", n_dmethods);
+ class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
+ n_dmethods++;
+
+ 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))
+ 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 {
+ Printf(stderr, "%s : Line %d. No return type for %%native method %s.\n", input_file, line_number, 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 num_required = 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(Getattr(n, "sym:name"), n))
+ 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"))
+ return SWIG_OK;
+ }
+
+ Printf(imclass_class_code, " public final static native %s %s(", im_return_type, overloaded_name);
+
+ /* Get number of required and total arguments */
+ num_arguments = emit_num_arguments(l);
+ num_required = emit_num_required(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 ((tm = Getattr(p, "tmap:throws"))) {
+ addThrows(n, "tmap:throws", p);
+ }
+ }
+ }
+
+ if (!native_function_flag) {
+ if (Cmp(nodeType(n), "constant") == 0) {
+ // Wrapping a constant hack
+ Swig_save("functionWrapper", n, "wrap:action", NIL);
+
+ // below based on Swig_VargetToFunction()
+ SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n));
+ Setattr(n, "wrap:action", NewStringf("result = (%s) %s;", SwigType_lstr(ty, 0), Getattr(n, "value")));
+ }
+
+ // Now write code to make the function call
+ 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);
+
+ if (Cmp(nodeType(n), "constant") == 0)
+ Swig_restore(n);
+
+ /* Return value if necessary */
+ if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
+ addThrows(n, "tmap:out", n);
+ Replaceall(tm, "$source", "result"); /* 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, "result", 0))) {
+ addThrows(n, "tmap:newfree", n);
+ Replaceall(tm, "$source", "result"); /* 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, "result", 0))) {
+ addThrows(n, "tmap:ret", n);
+ Replaceall(tm, "$source", "result"); /* 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(Swig_name_member(proxy_class_name, 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;
+ }
+
+ /* ----------------------------------------------------------------------
+ * 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;
+
+ 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
+
+ // 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 ", "");
+ } 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 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");
+
+ Printv(proxy_class_constants_code, " ", enum_code, "\n\n", NIL);
+ } else {
+ // Global enums are defined in their own file
+ String *filen = NewStringf("%s%s.java", SWIG_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 (Len(package) > 0)
+ Printf(f_enum, "package %s;\n", package);
+
+ Printv(f_enum, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE), // Import statements
+ "\n", enum_code, "\n", NIL);
+
+ Printf(f_enum, "\n");
+ Close(f_enum);
+ }
+ } 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;
+ }
+ 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");
+ 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);
+
+ {
+ EnumFeature enum_feature = decodeEnumFeature(parentNode(n));
+
+ if ((enum_feature == ProperEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) {
+ // Wrap (non-anonymous) C/C++ enum with a proper Java enum
+ // Emit the enum item.
+ if (!GetFlag(n, "firstenumitem"))
+ Printf(enum_code, ",\n");
+ 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
+ const String *parent_name = Getattr(parentNode(n), "name");
+ String *typemap_lookup_type = parent_name ? Copy(parent_name) : NewString("int");
+ const String *tm = typemapLookup(n, "jstype", typemap_lookup_type, WARN_JAVA_TYPEMAP_JSTYPE_UNDEF);
+ String *return_type = Copy(tm);
+ Delete(typemap_lookup_type);
+ typemap_lookup_type = NULL;
+
+ const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ if ((enum_feature == TypesafeEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) {
+ // Wrap (non-anonymouse) 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);
+ }
+ }
+
+ // Add the enum value to the comma separated list being constructed in the enum declaration.
+ String *enumvalues = Getattr(parentNode(n), "enumvalues");
+ if (!enumvalues)
+ Setattr(parentNode(n), "enumvalues", Copy(symname));
+ else
+ Printv(enumvalues, ", ", symname, NIL);
+ }
+
+ 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");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ String *return_type = NewString("");
+ String *constants_code = NewString("");
+
+ if (!addSymbol(symname, n))
+ return SWIG_ERROR;
+
+ bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
+
+ // 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("");
+ Swig_save("constantWrapper", n, "value", NIL);
+ 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 *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname;
+ 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, imclass_name, Swig_name_get(symname));
+ } else {
+ // This handles function pointers using the %constant directive
+ Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, imclass_name, Swig_name_get(symname));
+ }
+ } else
+ Printf(constants_code, "%s.%s();\n", imclass_name, Swig_name_get(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
+ 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) {
+ String *code = Getattr(n, "code");
+ Replaceall(code, "$module", module_class_name);
+ Replaceall(code, "$imclassname", imclass_name);
+ return Language::insertDirective(n);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * pragmaDirective()
+ *
+ * Valid Pragmas:
+ * jniclassbase - base (extends) for 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, "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) {
+ Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use the moduleimports pragma.\n", input_file, line_number);
+ } else if (Strcmp(code, "moduleinterface") == 0) {
+ Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use the moduleinterfaces pragma.\n", input_file, line_number);
+ } else if (Strcmp(code, "modulemethodmodifiers") == 0) {
+ Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%javamethodmodifiers.\n", input_file, line_number);
+ } else if (Strcmp(code, "allshadowimport") == 0) {
+ Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javaimports).\n", input_file, line_number);
+ } else if (Strcmp(code, "allshadowcode") == 0) {
+ Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javacode).\n", input_file, line_number);
+ } else if (Strcmp(code, "allshadowbase") == 0) {
+ Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javabase).\n", input_file, line_number);
+ } else if (Strcmp(code, "allshadowinterface") == 0) {
+ Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javainterfaces).\n", input_file, line_number);
+ } else if (Strcmp(code, "allshadowclassmodifiers") == 0) {
+ Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javaclassmodifiers).\n", input_file, line_number);
+ } else if (proxy_flag) {
+ if (Strcmp(code, "shadowcode") == 0) {
+ Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javacode).\n", input_file, line_number);
+ } else if (Strcmp(code, "shadowimport") == 0) {
+ Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javaimports).\n", input_file, line_number);
+ } else if (Strcmp(code, "shadowbase") == 0) {
+ Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javabase).\n", input_file, line_number);
+ } else if (Strcmp(code, "shadowinterface") == 0) {
+ Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javainterfaces).\n", input_file, line_number);
+ } else if (Strcmp(code, "shadowclassmodifiers") == 0) {
+ Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javaclassmodifiers).\n", input_file, line_number);
+ } else {
+ Printf(stderr, "%s : Line %d. Unrecognized pragma.\n", input_file, line_number);
+ }
+ } else {
+ Printf(stderr, "%s : Line %d. Unrecognized pragma.\n", input_file, line_number);
+ }
+ Delete(strvalue);
+ }
+ }
+ return Language::pragmaDirective(n);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * emitProxyClassDefAndCPPCasts()
+ * ----------------------------------------------------------------------------- */
+
+ void emitProxyClassDefAndCPPCasts(Node *n) {
+ String *c_classname = SwigType_namestr(Getattr(n, "name"));
+ String *c_baseclass = NULL;
+ String *baseclass = NULL;
+ String *c_baseclassname = NULL;
+ SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
+ bool feature_director = Swig_directorclass(n) ? true : false;
+
+ // 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 && GetFlag(base.item, "feature:ignore")) {
+ base = Next(base);
+ }
+ if (base.item) {
+ c_baseclassname = Getattr(base.item, "name");
+ baseclass = Copy(getProxyName(c_baseclassname));
+ if (baseclass)
+ c_baseclass = SwigType_namestr(Getattr(base.item, "name"));
+ base = Next(base);
+ /* 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_JAVA_MULTIPLE_INHERITANCE, input_file, line_number,
+ "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Java.\n", proxyclassname, baseclassname);
+ base = Next(base);
+ }
+ }
+ }
+ }
+
+ bool derived = baseclass && getProxyName(c_baseclassname);
+ 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;
+ Delete(baseclass);
+ baseclass = NULL;
+ if (purebase_notderived)
+ Swig_error(input_file, line_number, "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, input_file, line_number,
+ "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Java. "
+ "Perhaps you need one of the 'replace' or 'notderived' attributes in the csbase typemap?\n", typemap_lookup_type, pure_baseclass);
+ }
+
+ // Pure Java interfaces
+ const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE);
+
+ // Start writing the proxy class
+ Printv(proxy_class_def, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE), // Import statements
+ "\n", 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(pure_interfaces) ? // Pure Java interfaces
+ " implements " : "", pure_interfaces, " {", 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();
+ String *destruct_methodname = NULL;
+ String *destruct_methodmodifiers = 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");
+ } 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");
+ }
+ if (tm && *Char(tm)) {
+ if (!destruct_methodname) {
+ Swig_error(input_file, line_number,
+ "No methodname attribute defined in javadestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
+ }
+ if (!destruct_methodmodifiers) {
+ Swig_error(input_file, line_number,
+ "No methodmodifiers attribute defined in javadestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name);
+ }
+ }
+ // 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 ", destruct_methodmodifiers, " void ", destruct_methodname, "()", destructor_throws_clause, " ", destruct, "\n", 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;
+
+ destruct_jnicall = NewStringf("%s()", destruct_methodname);
+ release_jnicall = NewStringf("%s.%s_change_ownership(this, swigCPtr, false)", imclass_name, proxy_class_name);
+ take_jnicall = NewStringf("%s.%s_change_ownership(this, swigCPtr, true)", imclass_name, proxy_class_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(release_jnicall);
+ Delete(take_jnicall);
+ }
+
+ 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);
+
+ // Substitute various strings into the above template
+ Replaceall(proxy_class_code, "$javaclassname", proxy_class_name);
+ Replaceall(proxy_class_def, "$javaclassname", proxy_class_name);
+
+ Replaceall(proxy_class_def, "$module", module_class_name);
+ Replaceall(proxy_class_code, "$module", module_class_name);
+
+ Replaceall(proxy_class_def, "$imclassname", imclass_name);
+ Replaceall(proxy_class_code, "$imclassname", imclass_name);
+
+ // Add code to do C++ casting to base class (only for classes in an inheritance hierarchy)
+ if (derived) {
+ Printv(imclass_cppcasts_code, " public final static native long SWIG$javaclassnameUpcast(long jarg1);\n", NIL);
+
+ Replaceall(imclass_cppcasts_code, "$javaclassname", proxy_class_name);
+
+ Printv(upcasts_code,
+ "SWIGEXPORT jlong JNICALL Java_$jnipackage$imimclass_SWIG$imclazznameUpcast",
+ "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n",
+ " jlong baseptr = 0;\n"
+ " (void)jenv;\n" " (void)jcls;\n" " *($cbaseclass **)&baseptr = *($cclass **)&jarg1;\n" " return baseptr;\n" "}\n", "\n", NIL);
+
+ String *imimclass = makeValidJniName(imclass_name);
+ String *imclazzname = makeValidJniName(proxy_class_name);
+ Replaceall(upcasts_code, "$cbaseclass", c_baseclass);
+ Replaceall(upcasts_code, "$imclazzname", imclazzname);
+ Replaceall(upcasts_code, "$cclass", c_classname);
+ Replaceall(upcasts_code, "$jnipackage", jnipackage);
+ Replaceall(upcasts_code, "$imimclass", imimclass);
+
+ Delete(imclazzname);
+ Delete(imimclass);
+ }
+ Delete(baseclass);
+ }
+
+ /* ----------------------------------------------------------------------
+ * classHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int classHandler(Node *n) {
+
+ File *f_proxy = NULL;
+ if (proxy_flag) {
+ proxy_class_name = NewString(Getattr(n, "sym:name"));
+
+ if (!addSymbol(proxy_class_name, n))
+ return SWIG_ERROR;
+
+ 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);
+ }
+
+ String *filen = NewStringf("%s%s.java", SWIG_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);
+ filen = NULL;
+
+ // Start writing out the proxy class file
+ emitBanner(f_proxy);
+
+ if (Len(package) > 0)
+ Printf(f_proxy, "package %s;\n", package);
+
+ Clear(proxy_class_def);
+ Clear(proxy_class_code);
+
+ destructor_call = NewString("");
+ destructor_throws_clause = NewString("");
+ proxy_class_constants_code = NewString("");
+ }
+
+ Language::classHandler(n);
+
+ if (proxy_flag) {
+
+ emitProxyClassDefAndCPPCasts(n);
+
+ 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(proxy_class_def, "$imclassname", imclass_name);
+ Replaceall(proxy_class_code, "$imclassname", imclass_name);
+ Replaceall(proxy_class_constants_code, "$imclassname", imclass_name);
+ Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
+
+ // Write out all the constants
+ if (Len(proxy_class_constants_code) != 0)
+ Printv(f_proxy, proxy_class_constants_code, NIL);
+
+ Printf(f_proxy, "}\n");
+ Close(f_proxy);
+ f_proxy = NULL;
+
+ /* Output the downcast method, if necessary. Note: There's no other really
+ good place to put this code, since Abstract Base Classes (ABCs) can and should have
+ downcasts, making the constructorHandler() a bad place (because ABCs don't get to
+ have constructors emitted.) */
+ if (GetFlag(n, "feature:javadowncast")) {
+ String *jni_imclass_name = makeValidJniName(imclass_name);
+ String *jni_class_name = makeValidJniName(proxy_class_name);
+ String *norm_name = SwigType_namestr(Getattr(n, "name"));
+
+ Printf(imclass_class_code, " public final static native %s downcast%s(long cPtrBase, boolean cMemoryOwn);\n", proxy_class_name, proxy_class_name);
+
+ Wrapper *dcast_wrap = NewWrapper();
+
+ Printf(dcast_wrap->def, "SWIGEXPORT jobject JNICALL Java_%s%s_downcast%s(JNIEnv *jenv, jclass jcls, jlong jCPtrBase, jboolean cMemoryOwn) {",
+ jnipackage, jni_imclass_name, jni_class_name);
+ Printf(dcast_wrap->code, " Swig::Director *director = (Swig::Director *) 0;\n");
+ Printf(dcast_wrap->code, " jobject jresult = (jobject) 0;\n");
+ Printf(dcast_wrap->code, " %s *obj = *((%s **)&jCPtrBase);\n", norm_name, norm_name);
+ Printf(dcast_wrap->code, " if (obj) director = dynamic_cast<Swig::Director *>(obj);\n");
+ Printf(dcast_wrap->code, " if (director) jresult = director->swig_get_self(jenv);\n");
+ Printf(dcast_wrap->code, " return jresult;\n");
+ Printf(dcast_wrap->code, "}\n");
+
+ Wrapper_print(dcast_wrap, f_wrappers);
+ DelWrapper(dcast_wrap);
+ }
+
+ emitDirectorExtraMethods(n);
+
+ Delete(proxy_class_name);
+ proxy_class_name = NULL;
+ Delete(destructor_call);
+ destructor_call = NULL;
+ Delete(destructor_throws_clause);
+ destructor_throws_clause = NULL;
+ Delete(proxy_class_constants_code);
+ proxy_class_constants_code = NULL;
+ }
+
+ 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(proxy_class_name, 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(proxy_class_name, 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("");
+
+ 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(Swig_name_member(proxy_class_name, variable_name))) == 0);
+ }
+
+ /* 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);
+
+ Printv(imcall, imclass_name, ".$imfuncname(", NIL);
+ if (!static_flag) {
+ Printf(imcall, "swigCPtr");
+
+ String *this_type = Copy(getClassType());
+ String *name = NewString("self");
+ String *qualifier = Getattr(n, "qualifier");
+ if (qualifier)
+ SwigType_push(this_type, qualifier);
+ SwigType_add_pointer(this_type);
+ Parm *this_parm = NewParm(this_type, name);
+ 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, ", ");
+ 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);
+ }
+ }
+
+ 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(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 (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));
+ }
+
+ generateThrowsClause(n, function_code);
+ 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(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(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);
+
+ 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, 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 *construct_tm = Copy(typemapLookup(n, "javaconstruct", Getattr(n, "name"),
+ 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, imclass_name, ".", Swig_name_destroy(symname), "(swigCPtr)", NIL);
+ generateThrowsClause(n, destructor_throws_clause);
+ }
+ 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;
+ int num_required = 0;
+ String *overloaded_name = getOverloadedName(n);
+ String *func_name = NULL;
+ bool setter_flag = false;
+ String *pre_code = NewString("");
+ String *post_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("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(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);
+ num_required = emit_num_required(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 ? (const String *) 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 {
+ // 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()", imclass_name, Swig_name_get(symname));
+ } else {
+ memberconstantHandler(n);
+ value = NewStringf("%s.%s()", imclass_name, Swig_name_get(Swig_name_member(proxy_class_name, symname)));
+ }
+ }
+ }
+ return value;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getEnumName()
+ *
+ * If jnidescriptor is set, inner class names are separated with '$' otherwise a '.'
+ * ----------------------------------------------------------------------------- */
+
+ String *getEnumName(SwigType *t, bool jnidescriptor) {
+ Node *enum_name = NULL;
+ Node *n = enumLookup(t);
+ if (n) {
+ 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) {
+ const char *class_separator = jnidescriptor ? "$" : ".";
+ enum_name = NewStringf("%s%s%s", proxyname, class_separator, symname);
+ } else {
+ enum_name = NewStringf("%s", symname);
+ }
+ Delete(scopename_prefix);
+ }
+ }
+
+ return enum_name;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * 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.
+ * 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 '.'
+ * 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));
+ 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);
+ }
+
+ Delete(strippedtype);
+ Delete(type);
+
+ return substitution_performed;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substituteClassnameSpecialVariable()
+ * ----------------------------------------------------------------------------- */
+
+ void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable, bool jnidescriptor) {
+ if (SwigType_isenum(classnametype)) {
+ String *enumname = getEnumName(classnametype, jnidescriptor);
+ if (enumname)
+ Replaceall(tm, classnamespecialvariable, enumname);
+ else
+ Replaceall(tm, classnamespecialvariable, NewStringf("int"));
+ } else {
+ String *classname = getProxyName(classnametype);
+ if (classname) {
+ Replaceall(tm, classnamespecialvariable, classname); // getProxyName() works for pointers to classes too
+ } else { // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
+ String *descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
+ Replaceall(tm, classnamespecialvariable, descriptor);
+
+ // Add to hash table so that the type wrapper classes can be created later
+ Setattr(swig_types_hash, descriptor, classnametype);
+ Delete(descriptor);
+ }
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * 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 *makeParameterName(Node *n, Parm *p, int arg_num, bool setter) {
+
+ String *arg = 0;
+ String *pn = Getattr(p, "name");
+
+ // Use C parameter name unless it is a duplicate or an empty parameter name
+ int count = 0;
+ ParmList *plist = Getattr(n, "parms");
+ while (plist) {
+ if ((Cmp(pn, Getattr(plist, "name")) == 0))
+ count++;
+ plist = nextSibling(plist);
+ }
+ String *wrn = pn ? Swig_name_warning(p, 0, pn, 0) : 0;
+ arg = (!pn || (count > 1) || wrn) ? NewStringf("arg%d", arg_num) : Copy(pn);
+
+ if (setter && Cmp(arg, "self") != 0) {
+ // Note that for setters the parameter name is always set but sometimes includes C++
+ // scope resolution, so we need to strip off the scope resolution to make a valid name.
+ Delete(arg);
+ arg = NewString("value"); //Swig_scopename_last(pn);
+ }
+
+ return arg;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * 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 (Len(package) > 0)
+ 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);
+ Printv(f_swigtype, swigtype, NIL);
+
+ Close(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 *proxyClassName = 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) {
+ Node *n = classLookup(t);
+ if (n) {
+ // Found a struct/class parameter passed by value, reference, pointer, or pointer reference
+ proxyClassName = Getattr(n, "sym:name");
+ } else {
+ // 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) {
+ proxyClassName = symname;
+ }
+ }
+ }
+ }
+ }
+ Delete(jstype);
+ }
+ }
+ }
+ }
+ Delete(jtype);
+ return proxyClassName;
+ }
+
+ /*----------------------------------------------------------------------
+ * 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, " static jclass jclass_%s = NULL;\n", imclass_name);
+ Printf(f_runtime, " static jmethodID director_methids[%d];\n", n_methods);
+ 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_methids[i] = jenv->GetStaticMethodID(jcls, methods[i].method, methods[i].signature);\n");
+ Printf(w->code, " if (!Swig::director_methids[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 $javaclassname_director_connect 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 = NewStringf("%s_director_connect", proxy_class_name);
+ String *swig_director_connect_jni = makeValidJniName(swig_director_connect);
+ String *sym_name = Getattr(n, "sym:name");
+ 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, 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);
+ Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
+ Printf(code_wrap->code, " (void)jcls;\n");
+ Printf(code_wrap->code, " SwigDirector_%s *director = dynamic_cast<SwigDirector_%s *>(obj);\n", sym_name, sym_name);
+ Printf(code_wrap->code, " if (director) {\n");
+ 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");
+ 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 = NewStringf("%s_change_ownership", proxy_class_name);
+ 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, 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);
+ Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
+ Printf(code_wrap->code, " SwigDirector_%s *director = dynamic_cast<SwigDirector_%s *>(obj);\n", sym_name, sym_name);
+ 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(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);
+ }
+
+ /* ---------------------------------------------------------------
+ * Canonicalize the JNI field descriptor
+ *
+ * Replace the $javapackage 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) {
+ String *pkg_path = Swig_typemap_lookup("javapackage", p, "", 0);
+ SwigType *type = Getattr(p, "type");
+
+ if (pkg_path && Len(pkg_path) != 0) {
+ Replaceall(pkg_path, ".", "/");
+ } else
+ pkg_path = package_path;
+
+ String *descriptor_out = Copy(descriptor_in);
+
+ if (Len(pkg_path) > 0) {
+ Replaceall(descriptor_out, "$packagepath", pkg_path);
+ } else {
+ Replaceall(descriptor_out, "$packagepath/", empty_string);
+ Replaceall(descriptor_out, "$packagepath", empty_string);
+ }
+
+ substituteClassname(type, descriptor_out, true);
+
+ if (pkg_path != package_path)
+ Delete(pkg_path);
+
+ 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 *empty_str = NewString("");
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ SwigType *returntype = Getattr(n, "returntype");
+ 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 = NewString("");
+ 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 gencomma = 0;
+ int classmeth_off = curr_class_dmethod - first_class_dmethod;
+ 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(classname, overloaded_name));
+
+ if (returntype) {
+
+ 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, "abstract"))) {
+ /* 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. */
+ String *non_ref_type = Copy(returntype);
+
+ /* Remove reference and const qualifiers */
+ Replaceall(non_ref_type, "r.", "");
+ Replaceall(non_ref_type, "q(const).", "");
+ Wrapper_add_localv(w, "result_default", "static", SwigType_str(non_ref_type, "result_default"), "=", SwigType_str(non_ref_type, "()"), NIL);
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= &result_default", NIL);
+
+ Delete(non_ref_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 */
+ Parm *tp = NewParmFromNode(returntype, empty_str, n);
+
+ tm = Swig_typemap_lookup("jtype", tp, "", 0);
+ if (tm) {
+ Printf(callback_def, " public static %s %s(%s self", tm, imclass_dmethod, 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 = NewParmFromNode(adjustedreturntype, empty_str, n);
+
+ if ((tm = 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 */
+
+ Parm *retpm = NewParmFromNode(returntype, empty_str, n);
+
+ if ((c_ret_type = Swig_typemap_lookup("jni", retpm, "", 0))) {
+ Parm *tp = NewParmFromNode(c_ret_type, empty_str, 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 ((tm = 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);
+ Delete(retpm);
+ }
+
+ /* Go through argument list, attach lnames for arguments */
+ for (i = 0, p = l; p; p = nextSibling(p), ++i) {
+ String *arg = Getattr(p, "name");
+ String *lname = NewString("");
+
+ if (!arg && Cmp(Getattr(p, "type"), "void")) {
+ lname = NewStringf("arg%d", i);
+ Setattr(p, "name", lname);
+ } else
+ lname = arg;
+
+ Setattr(p, "lname", lname);
+ }
+
+ /* 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, 0);
+ Swig_typemap_attach_parms("javadirectorin", l, 0);
+
+ 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 self object) */
+ Parm *tp = NewParmFromNode(c_classname, empty_str, 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(type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Delete(tp);
+
+ /* Go through argument list, convert from native to Java */
+ for (p = l; p; /* empty */ ) {
+ /* Is this superfluous? */
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Copy(Getattr(p, "name"));
+ 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 = NewParmFromNode(c_param_type, empty_str, 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);
+
+ Replaceall(tm, "$input", arg);
+ Replaceall(tm, "$owner", "0");
+
+ if (Len(tm))
+ if (!ignored_method)
+ Printf(w->code, "%s\n", tm);
+
+ Delete(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 (++gencomma > 1)
+ 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;
+ }
+
+ 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(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ p = nextSibling(p);
+ }
+
+ Delete(arg);
+ Delete(c_decl);
+ Delete(c_param_type);
+ }
+
+ /* header declaration, start wrapper definition */
+ String *target;
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : type;
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ target = Swig_method_decl(rtype, decl, name, l, 0, 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;
+
+ 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 ((tm = Getattr(p, "tmap:throws"))) {
+ 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("self.%s(%s)", symname, imcall_args);
+
+ if (!is_void) {
+ Parm *tp = NewParmFromNode(returntype, empty_str, n);
+
+ if ((tm = Swig_typemap_lookup("javadirectorout", tp, "", 0))) {
+ addThrows(n, "tmap:javadirectorout", tp);
+ substituteClassname(returntype, tm);
+ Replaceall(tm, "$javacall", upcall);
+
+ Printf(callback_code, " return %s;\n", tm);
+ }
+
+ if ((tm = Swig_typemap_lookup("out", tp, "", 0)))
+ addThrows(n, "tmap:out", tp);
+
+ Delete(tm);
+ Delete(tp);
+ } 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_methids[%s], %s);\n", methop, imclass_name, methid, jupcall_args);
+
+ Printf(w->code, "if (jenv->ExceptionOccurred()) return $null;\n");
+
+ if (!is_void) {
+ String *jresult_str = NewString("jresult");
+ String *result_str = NewString("c_result");
+ Parm *tp = NewParmFromNode(returntype, result_str, n);
+
+ /* Copy jresult into c_result... */
+ if ((tm = Swig_typemap_lookup("directorout", tp, result_str, w))) {
+ addThrows(n, "tmap:directorout", tp);
+ 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(tp);
+ Delete(jresult_str);
+ Delete(result_str);
+ }
+
+ 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\");\n");
+ 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 code */
+ 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")) {
+ 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;
+ }
+
+ /* ------------------------------------------------------------
+ * 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 = NewParmFromNode(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 *classname = 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 = NewParmFromNode(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, classname, parms, 0, 0);
+ String *call = Swig_csuperclass_call(0, basetype, superparms);
+ String *classtype = SwigType_namestr(Getattr(n, "name"));
+
+ Printf(f_directors, "%s::%s : %s, %s {\n", classname, 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, classname, parms, 0, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Delete(sub);
+ Delete(supername);
+ Delete(jenv_type);
+ Delete(parms);
+ return Language::classDirectorConstructor(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDefaultConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorDefaultConstructor(Node *n) {
+ String *classname = Swig_class_name(n);
+ String *classtype = SwigType_namestr(Getattr(n, "name"));
+ Wrapper *w = NewWrapper();
+
+ Printf(w->def, "SwigDirector_%s::SwigDirector_%s(JNIEnv *jenv) : %s {", classname, classname, Getattr(n, "director:ctor"));
+ Printf(w->code, "}\n");
+ Wrapper_print(w, f_directors);
+
+ Printf(f_directors_h, " SwigDirector_%s(JNIEnv *jenv);\n", classname);
+ DelWrapper(w);
+ Delete(classtype);
+ Delete(classname);
+ 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");
+
+ Java_director_declaration(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);
+ Wrapper *w = NewWrapper();
+
+ if (Getattr(n, "throw")) {
+ Printf(f_directors_h, " virtual ~SwigDirector_%s() throw ();\n", classname);
+ Printf(w->def, "SwigDirector_%s::~SwigDirector_%s() throw () {\n", classname, classname);
+ } else {
+ Printf(f_directors_h, " virtual ~SwigDirector_%s();\n", classname);
+ Printf(w->def, "SwigDirector_%s::~SwigDirector_%s() {\n", classname, classname);
+ }
+
+ /* Ensure that correct directordisconnect typemap's method name is called
+ * here: */
+
+ const String *disconn_tm = NULL;
+ Node *disconn_attr = NewHash();
+ String *disconn_methodname = NULL;
+
+ disconn_tm = 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);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorEnd()
+ * ------------------------------------------------------------ */
+
+ int classDirectorEnd(Node *n) {
+ String *classname = Getattr(n, "sym:name");
+ 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);
+
+ 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, " bool swig_override[%d];\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");
+ 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;
+ }
+
+ /*----------------------------------------------------------------------
+ * Java_director_declaration()
+ *
+ * Generate the director class's declaration
+ * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
+ *--------------------------------------------------------------------*/
+
+ void Java_director_declaration(Node *n) {
+ String *base = Getattr(n, "classtype");
+ String *class_ctor = NewString("Swig::Director(jenv)");
+
+ String *classname = Swig_class_name(n);
+ String *directorname = NewStringf("SwigDirector_%s", classname);
+ 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);
+ }
+
+}; /* 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 = (char *) "\
+Java Options (available with -java)\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/Source/Modules/lang.cxx b/Source/Modules/lang.cxx
new file mode 100644
index 0000000..d4715ee
--- /dev/null
+++ b/Source/Modules/lang.cxx
@@ -0,0 +1,3431 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * lang.cxx
+ *
+ * Language base class functions. Default C++ handling is also implemented here.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_lang_cxx[] = "$Id: lang.cxx 11482 2009-07-30 18:48:14Z wsfulton $";
+
+#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 *ClassPrefix = 0; /* Class prefix */
+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
+#define IMPORT_MODULE 2
+
+/* ----------------------------------------------------------------------
+ * Dispatcher::emit_one()
+ *
+ * Dispatch a single node
+ * ---------------------------------------------------------------------- */
+
+int Dispatcher::emit_one(Node *n) {
+ String *wrn;
+ 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 */
+ 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);
+ }
+
+ /* ===============================================================
+ * 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 {
+ Printf(stderr, "%s:%d. Unrecognized parse tree node type '%s'\n", input_file, line_number, 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::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),
+symbols(NewHash()),
+classtypes(NewHash()),
+enumtypes(NewHash()),
+overloading(0),
+multiinput(0),
+cplus_runtime(0),
+directors(0) {
+ 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;
+}
+
+Language::~Language() {
+ Delete(symbols);
+ Delete(classtypes);
+ Delete(enumtypes);
+ Delete(director_ctor_code);
+ Delete(none_comparison);
+ this_ = 0;
+}
+
+/* ----------------------------------------------------------------------
+ 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;
+ }
+ }
+}
+
+/* --------------------------------------------------------------------------
+ * use_naturalvar_mode()
+ * -------------------------------------------------------------------------- */
+int use_naturalvar_mode(Node *n) {
+ if (Getattr(n, "unnamed"))
+ return 0;
+ int nvar = naturalvar_mode || GetFlag(n, "feature:naturalvar");
+ if (!nvar) {
+ /* look for feature in the class */
+ SwigType *ty = Getattr(n, "type");
+ SwigType *fullty = SwigType_typedef_resolve_all(ty);
+ if (SwigType_isclass(fullty)) {
+ Node *m = Copy(n);
+ SwigType *tys = SwigType_strip_qualifiers(fullty);
+ Swig_features_get(Swig_cparse_features(), 0, tys, 0, m);
+ nvar = GetFlag(m, "feature:naturalvar");
+ Delete(tys);
+ Delete(m);
+ }
+ Delete(fullty);
+ }
+ return 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;
+ }
+ if (Getattr(options, "nonaturalvar")) {
+ naturalvar_mode = 0;
+ }
+ }
+ }
+ classhash = Getattr(n, "classes");
+ return emit_children(n);
+}
+
+/* ----------------------------------------------------------------------
+ * Language::extendDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::extendDirective(Node *n) {
+ int oldam = Extend;
+ AccessMode oldmode = cplus_mode;
+ Extend = CWRAP_EXTEND;
+ cplus_mode = PUBLIC;
+
+ emit_children(n);
+
+ Extend = oldam;
+ cplus_mode = oldmode;
+ 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) {
+ 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.\n");
+ }
+ }
+ 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;
+
+ /* 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 = storage && (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)) || is_non_virtual_protected_access(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 (symname && !validIdentifier(symname)) {
+ Swig_warning(WARN_LANG_IDENTIFIER, input_file, line_number, "Can't wrap '%s' unless renamed to a valid identifier.\n", 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);
+ 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 ((Cmp(storage, "extern") == 0) || (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 (Cmp(storage, "externc") == 0) {
+ /* 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);
+ if (GetFlag(n, "feature:onlychildren") && !GetFlag(n, "feature:ignore")) {
+ // Found an unignored templated method that has a an empty template instantiation (%template())
+ // Ignore it unless it has been %rename'd
+ if (Strncmp(symname, "__dummy_", 8) == 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));
+ }
+ }
+ if (!GetFlag(n, "feature:ignore"))
+ 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 (Getattr(n, "nested"))
+ SetFlag(n, "feature:immutable");
+ if (!CurrentClass) {
+ if ((Cmp(storage, "extern") == 0) || ForceExtern) {
+ f_header = Swig_filebyname("header");
+ if (AddExtern) {
+ if (f_header) {
+ String *str = SwigType_str(ty, name);
+ Printf(f_header, "extern %s;\n", 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 && Cmp(storage, "static") == 0 && !(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) {
+ globalfunctionHandler(n);
+ } else {
+ 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 *call = Swig_cfunction_call(name, parms);
+ String *cres = Swig_cresult(type, "result", 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 *symname = Getattr(n, "sym:name");
+ String *type = Getattr(n, "type");
+ String *name = Getattr(n, "name");
+ String *parms = Getattr(n, "parms");
+ String *cb = GetFlagAttr(n, "feature:callback");
+ 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);
+
+ if (!cbname) {
+ cbname = NewStringf(cb, symname);
+ Setattr(n, "feature:callback:name", cbname);
+ }
+
+ Setattr(n, "sym:name", cbname);
+ Setattr(n, "type", cbty);
+ Setattr(n, "value", calltype);
+
+ Node *ns = Getattr(symbols, cbname);
+ if (!ns)
+ constantWrapper(n);
+
+ Delete(cbname);
+ 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);
+
+ memberconstantHandler(cbn);
+ Setattr(n, "feature:callback:name", Swig_name_member(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(ClassPrefix, symname);
+ if (Extend && SmartPointer) {
+ if (!Getattr(n, "classname")) {
+ Setattr(n, "classname", Getattr(CurrentClass, "allocate:smartpointerbase"));
+ }
+ }
+ // 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") || is_non_virtual_protected_access(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;
+
+ Swig_MethodToFunction(n, ClassType, Getattr(n, "template") ? SmartPointer : Extend | SmartPointer | DirectorExtraCall, director_type,
+ is_member_director(CurrentClass, n));
+ Setattr(n, "sym:name", fname);
+
+ 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 (is_non_virtual_protected_access(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(mname, name);
+ Delete(mname);
+ }
+ mrename = Swig_name_member(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 */
+ Swig_add_extension_code(n, cname, parms, type, code, CPlusPlus, 0);
+ }
+ }
+
+ Setattr(n, "name", cname);
+ Setattr(n, "sym:name", mrename);
+
+ if (cb) {
+ String *cbname = NewStringf(cb, symname);
+ Setattr(n, "feature:callback:name", Swig_name_member(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 {
+ String *storage = Getattr(n, "storage");
+ 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:smartpointerconst")) {
+ SetFlag(n, "feature:immutable");
+ }
+ }
+ if ((Cmp(storage, "static") == 0) && !(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(ClassPrefix, symname);
+ String *mrename_get = Swig_name_get(mname);
+ String *mrename_set = Swig_name_set(mname);
+ Delete(mname);
+
+ /* Create a function to set the value of the variable */
+
+ int assignable = is_assignable(n);
+
+ if (SmartPointer) {
+ if (Getattr(CurrentClass, "allocate:smartpointerconst")) {
+ assignable = 0;
+ }
+ }
+
+ if (assignable) {
+ int make_set_wrapper = 1;
+ String *tm = 0;
+ String *target = 0;
+ if (!Extend) {
+ if (SmartPointer) {
+ if (checkAttribute(n, "storage", "static")) {
+ 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 = is_non_virtual_protected_access(n) ? NewString("darg") : Swig_cparm_name(0, 0);
+ target = NewStringf("%s->%s", pname, name);
+ Delete(pname);
+ }
+ } else {
+ target = NewStringf("$extendgetcall"); // member variable access expanded later
+ }
+ tm = Swig_typemap_lookup("memberin", n, target, 0);
+ int flags = Extend | SmartPointer | use_naturalvar_mode(n);
+ if (is_non_virtual_protected_access(n))
+ flags = flags | CWRAP_ALL_PROTECTED_ACCESS;
+
+ String *call = 0;
+ Swig_MembersetToFunction(n, ClassType, flags, &call);
+ Setattr(n, "memberset", "1");
+
+ 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);
+ Replace(tm, "$extendgetcall", call, DOH_REPLACE_ANY);
+ Setattr(n, "wrap:action", tm);
+ Delete(tm);
+ Delete(pname0);
+ Delete(pname1);
+ }
+ Delete(call);
+ 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);
+
+ /* 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 (is_non_virtual_protected_access(n))
+ flags = flags | CWRAP_ALL_PROTECTED_ACCESS;
+ Swig_MembergetToFunction(n, ClassType, flags);
+ Setattr(n, "sym:name", mrename_get);
+ Setattr(n, "memberget", "1");
+ functionWrapper(n);
+ }
+ 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);
+ 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(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(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 ? (is_non_virtual_protected_access(n) ? DirectorClassName : ClassName) : Getattr(CurrentClass, "allocate:smartpointerbase");
+
+ 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(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 (!ImportMode) {
+ emit_children(n);
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::enumvalueDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::enumvalueDeclaration(Node *n) {
+ if (CurrentClass && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ Swig_require("enumvalueDeclaration", n, "*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);
+
+ 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;
+ 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 *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *value = Getattr(n, "value");
+
+ String *mrename = Swig_name_member(ClassPrefix, symname);
+ Setattr(n, "sym:name", mrename);
+
+ String *new_name = 0;
+ if (Extend)
+ new_name = Copy(value);
+ else
+ new_name = NewStringf("%s::%s", is_non_virtual_protected_access(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 */
+ if (!checkAttribute(ni, "storage", "virtual"))
+ continue;
+ nodeType = Getattr(ni, "nodeType");
+ /* 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(ni, "decl");
+ /* extra check for function type and proper access */
+ if (SwigType_isfunction(decl) && (((!protectedbase || dirprot_mode()) && is_public(ni)) || need_nonpublic_member(ni))) {
+ String *name = Getattr(ni, "name");
+ Node *method_id = is_destructor ? NewStringf("~destructor") : vtable_method_id(ni);
+ /* 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(ni);
+
+ /* 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);
+
+ 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'
+ an 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(symname); //Getattr(n, "name"));
+ String *type = NewString(ClassType);
+ String *name = NewString("self");
+ SwigType_add_pointer(type);
+ Parm *p = NewParm(type, name);
+ Delete(name);
+ Delete(type);
+ type = NewString("void");
+ String *action = NewString("");
+ Printv(action, "{\n", "Swig::Director *director = dynamic_cast<Swig::Director *>(arg1);\n", "if (director) director->swig_disown();\n", "}\n", NULL);
+ 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) {
+ 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 compileable code (Example2 in director_abastract.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"))
+ continue;
+
+ String *type = Getattr(method, "nodeType");
+ if (!Cmp(type, "destructor")) {
+ classDirectorDestructor(method);
+ } else {
+ if (classDirectorMethod(method, n, fqdname) == SWIG_OK) {
+ Setattr(item, "director", "1");
+ }
+ }
+ }
+
+ 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");
+ bool cdeclaration = (Cmp(nodeType, "cdecl") == 0);
+ if (cdeclaration && !GetFlag(ni, "feature:ignore")) {
+ if (is_non_virtual_protected_access(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 *last = Swig_scopename_last(cname);
+ String *name = NewStringf("%s::%s", cname, last);
+ String *cc = NewStringf("r.q(const).%s", type);
+ String *decl = NewStringf("f(%s).", cc);
+ String *csymname = Getattr(n, "sym:name");
+ String *oldname = csymname;
+
+ 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, last, decl, oldname);
+ if (Strcmp(symname, "$ignore") != 0) {
+ if (!symname) {
+ symname = Copy(csymname);
+ }
+ Parm *p = NewParm(cc, "other");
+
+ 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_symbol_setscope(oldscope);
+ Swig_features_get(Swig_cparse_features(), 0, name, decl, cn);
+
+ 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(last);
+ 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 *last = Swig_scopename_last(cname);
+ String *name = NewStringf("%s::%s", cname, last);
+ String *decl = NewString("f().");
+ String *csymname = Getattr(n, "sym:name");
+ String *oldname = csymname;
+ String *symname = Swig_name_make(cn, cname, last, decl, oldname);
+ if (Strcmp(symname, "$ignore") != 0) {
+ if (!symname) {
+ symname = Copy(csymname);
+ }
+
+ 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_symbol_setscope(oldscope);
+ Swig_features_get(Swig_cparse_features(), 0, name, decl, cn);
+
+ 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(last);
+ 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 *last = Swig_scopename_last(cname);
+ Insert(last, 0, "~");
+ String *name = NewStringf("%s::%s", cname, last);
+ String *decl = NewString("f().");
+ String *symname = Swig_name_make(cn, cname, last, decl, 0);
+ if (Strcmp(symname, "$ignore") != 0) {
+ if (!symname) {
+ 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 *on = Swig_symbol_add(symname, cn);
+ Swig_symbol_setscope(oldscope);
+ Swig_features_get(Swig_cparse_features(), 0, name, decl, cn);
+
+ if (on == cn) {
+ 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(cn);
+ Delete(last);
+ 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;
+ }
+
+ String *kind = Getattr(n, "kind");
+ String *name = Getattr(n, "name");
+ String *tdname = Getattr(n, "tdname");
+ String *symname = Getattr(n, "sym:name");
+
+ char *classname = tdname ? Char(tdname) : Char(name);
+ char *iname = Char(symname);
+ int strip = (tdname || CPlusPlus) ? 1 : 0;
+
+
+ if (!classname) {
+ 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;
+ }
+
+ Swig_save("classDeclaration", n, "name", NIL);
+ Setattr(n, "name", classname);
+
+ if (Cmp(kind, "class") == 0) {
+ cplus_mode = PRIVATE;
+ } else {
+ cplus_mode = PUBLIC;
+ }
+
+ ClassName = NewString(classname);
+ ClassPrefix = NewString(iname);
+ if (strip) {
+ ClassType = NewString(classname);
+ } else {
+ ClassType = NewStringf("%s %s", kind, classname);
+ }
+ Setattr(n, "classtypeobj", Copy(ClassType));
+ Setattr(n, "classtype", SwigType_namestr(ClassType));
+
+ InClass = 1;
+ CurrentClass = n;
+
+
+ /* Call classHandler() here */
+ if (!ImportMode) {
+ int dir = 0;
+ 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 = NewStringf("SwigDirector_%s", symname);
+ classDirector(n);
+ }
+ /* check for abstract after resolving directors */
+ Abstract = abstractClassTest(n);
+
+ classHandler(n);
+ } else {
+ Abstract = abstractClassTest(n);
+ Language::classHandler(n);
+ }
+
+ InClass = 0;
+ CurrentClass = 0;
+ Delete(ClassType);
+ ClassType = 0;
+ Delete(ClassPrefix);
+ ClassPrefix = 0;
+ Delete(ClassName);
+ ClassName = 0;
+ Delete(DirectorClassName);
+ DirectorClassName = 0;
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::classHandler(Node *n) {
+
+ 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;
+ 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");
+ 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 (!Getattr(symbols, 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 overidden 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);
+ }
+ cplus_mode = old_mode;
+ }
+ }
+
+ 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 {
+ if (name && (Cmp(Swig_scopename_last(name), Swig_scopename_last(ClassName))) && !(Getattr(n, "template"))) {
+ Swig_warning(WARN_LANG_RETURN_TYPE, input_file, line_number, "Function %s must have a return type.\n", SwigType_namestr(name));
+ 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 *&abstract) {
+ String *director_ctor = director_ctor_code;
+ int use_director = Swig_directorclass(n);
+ if (use_director) {
+ Node *pn = Swig_methodclass(n);
+ abstract = Getattr(pn, "abstract");
+ if (director_prot_ctor_code) {
+ int is_notabstract = GetFlag(pn, "feature:notabstract");
+ int is_abstract = abstract && !is_notabstract;
+ if (is_protected(n) || is_abstract) {
+ director_ctor = director_prot_ctor_code;
+ Delattr(pn, "abstract");
+ } else {
+ if (is_notabstract) {
+ Delattr(pn, "abstract");
+ } else {
+ abstract = 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(symname);
+ String *nodeType = Getattr(n, "nodeType");
+ int constructor = (!Cmp(nodeType, "constructor"));
+ List *abstract = 0;
+ String *director_ctor = get_director_ctor_code(n, director_ctor_code,
+ director_prot_ctor_code,
+ abstract);
+ if (!constructor) {
+ /* if not originally a constructor, still handle it as one */
+ Setattr(n, "handled_as_constructor", "1");
+ }
+
+ Swig_ConstructorToFunction(n, ClassType, none_comparison, director_ctor, CPlusPlus, Getattr(n, "template") ? 0 : Extend);
+ Setattr(n, "sym:name", mrename);
+ functionWrapper(n);
+ Delete(mrename);
+ Swig_restore(n);
+ if (abstract)
+ Setattr(Swig_methodclass(n), "abstract", abstract);
+ 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(symname);
+ List *abstract = 0;
+ String *director_ctor = get_director_ctor_code(n, director_ctor_code,
+ director_prot_ctor_code,
+ abstract);
+ Swig_ConstructorToFunction(n, ClassType, none_comparison, director_ctor, CPlusPlus, Getattr(n, "template") ? 0 : Extend);
+ Setattr(n, "sym:name", mrename);
+ functionWrapper(n);
+ Delete(mrename);
+ Swig_restore(n);
+ if (abstract)
+ Setattr(Swig_methodclass(n), "abstract", abstract);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::destructorDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::destructorDeclaration(Node *n) {
+
+ if (!CurrentClass)
+ return SWIG_NOWRAP;
+ if (cplus_mode != PUBLIC)
+ return SWIG_NOWRAP;
+ if (ImportMode)
+ return SWIG_NOWRAP;
+
+ if (Extend) {
+ /* extend destructor can be safetly ignored if there is already one */
+ if (Getattr(CurrentClass, "has_destructor")) {
+ return SWIG_NOWRAP;
+ }
+ }
+
+ Swig_save("destructorDeclaration", n, "name", "sym:name", NIL);
+
+ char *c = GetChar(n, "name");
+ if (c && (*c == '~'))
+ Setattr(n, "name", c + 1);
+
+ c = GetChar(n, "sym:name");
+ if (c && (*c == '~'))
+ Setattr(n, "sym:name", c + 1);
+
+ /* Name adjustment for %name */
+
+ 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);
+ }
+
+ 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 == '~'))
+ csymname += 1;
+
+ mrename = Swig_name_destroy(csymname);
+
+ Swig_DestructorToFunction(n, 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)) {
+ 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", NIL);
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *name = Getattr(n, "name");
+
+ /* 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(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) {
+ functionWrapper(n);
+ }
+ /* Restore parameters */
+ Setattr(n, "sym:name", symname);
+ Setattr(n, "type", type);
+ Setattr(n, "name", name);
+
+ /* 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(symname);
+ Setattr(n, "sym:name", gname);
+ Delete(gname);
+ functionWrapper(n);
+ Swig_restore(n);
+ 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. Returns 1 if the symbol is added successfully.
+ * Prints an error message and returns 0 if a conflict occurs.
+ * ----------------------------------------------------------------------------- */
+
+int
+Language::addSymbol(const String *s, const Node *n) {
+ Node *c = Getattr(symbols, s);
+ if (c && (c != n)) {
+ Swig_error(input_file, line_number, "'%s' is multiply defined in the generated module.\n", s);
+ Swig_error(Getfile(c), Getline(c), "Previous declaration of '%s'\n", s);
+ return 0;
+ }
+ Setattr(symbols, s, n);
+ return 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::symbolLookup()
+ * ----------------------------------------------------------------------------- */
+
+Node *Language::symbolLookup(String *s) {
+ return Getattr(symbols, s);
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::classLookup()
+ *
+ * Tries to locate a class from a type definition
+ * ----------------------------------------------------------------------------- */
+
+Node *Language::classLookup(SwigType *s) {
+ Node *n = 0;
+
+ /* Look in hash of cached values */
+ n = Getattr(classtypes, s);
+ if (!n) {
+ Symtab *stab = 0;
+ SwigType *ty1 = SwigType_typedef_resolve_all(s);
+ SwigType *ty2 = SwigType_strip_qualifiers(ty1);
+ Delete(ty1);
+ ty1 = 0;
+
+ 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;
+ 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 where we want a proxy class for the particular type */
+ if ((Len(prefix) == 0) || // simple type (pass by value)
+ (Strcmp(prefix, "p.") == 0) || // pointer
+ (Strcmp(prefix, "r.") == 0) || // reference
+ (Strcmp(prefix, "r.p.") == 0) || // pointer by reference
+ SwigType_prefix_is_simple_1D_array(prefix)) { // Simple 1D array (not arrays of pointers/references)
+ SwigType *cs = Copy(s);
+ Setattr(classtypes, cs, n);
+ Delete(cs);
+ } else {
+ n = 0;
+ }
+ }
+ Delete(ty2);
+ Delete(base);
+ Delete(prefix);
+ }
+ 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) {
+ Node *n = 0;
+
+ /* Look in hash of cached values */
+ n = Getattr(enumtypes, s);
+ if (!n) {
+ Symtab *stab = 0;
+ SwigType *lt = SwigType_ltype(s);
+ SwigType *ty1 = SwigType_typedef_resolve_all(lt);
+ SwigType *ty2 = SwigType_strip_qualifiers(ty1);
+ Delete(lt);
+ Delete(ty1);
+ lt = 0;
+ ty1 = 0;
+
+ 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 (Strcmp(nodeType(n), "enum") == 0)
+ 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 */
+ Setattr(enumtypes, Copy(s), n);
+ } else {
+ n = 0;
+ }
+ }
+ Delete(ty2);
+ Delete(base);
+ Delete(prefix);
+ }
+ 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 whan 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()) {
+ 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::extraDirectorProtectedCPPMethodsRequired()
+ * ----------------------------------------------------------------------------- */
+
+bool Language::extraDirectorProtectedCPPMethodsRequired() const {
+ return true;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::is_wrapping_class()
+ * ----------------------------------------------------------------------------- */
+
+int Language::is_wrapping_class() {
+ return InClass;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::getCurrentClass()
+ * ----------------------------------------------------------------------------- */
+
+Node *Language::getCurrentClass() const {
+ return CurrentClass;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::getClassName()
+ * ----------------------------------------------------------------------------- */
+
+String *Language::getClassName() const {
+ return ClassName;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::getClassPrefix()
+ * ----------------------------------------------------------------------------- */
+
+String *Language::getClassPrefix() const {
+ return ClassPrefix;
+}
+
+/* -----------------------------------------------------------------------------
+ * 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;
+ /* now check for the rest */
+ List *abstract = Getattr(n, "abstract");
+ if (!abstract)
+ return 0;
+ int labs = Len(abstract);
+#ifdef SWIG_DEBUG
+ List *bases = Getattr(n, "allbases");
+ Printf(stderr, "testing %s %d %d\n", Getattr(n, "name"), labs, Len(bases));
+#endif
+ if (!labs)
+ return 0; /*strange, but need to be fixed */
+ if (abstract && !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(abstract, 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 accesible, 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 dirabstract ? 1 : 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/Source/Modules/lua.cxx b/Source/Modules/lua.cxx
new file mode 100644
index 0000000..8835667
--- /dev/null
+++ b/Source/Modules/lua.cxx
@@ -0,0 +1,1226 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * 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)
+
+
+*/
+
+char cvsroot_lua_cxx[] = "$Id: lua.cxx 11133 2009-02-20 07:52:24Z wsfulton $";
+
+#include "swigmod.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 (DohIterator it = DohFirst(d); it.item; it = DohNext(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);
+ }
+}
+
+
+
+/* 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 = (char *) "\
+ Lua Options (available with -lua)\n\
+ (coming soon.)\n\n";
+
+
+
+/* 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 *PrefixPlusUnderscore;
+ String *s_cmd_tab; // table of command names
+ String *s_var_tab; // table of global variables
+ String *s_const_tab; // table of global constants
+ String *s_methods_tab; // table of class methods
+ String *s_attr_tab; // table of class atributes
+ String *s_luacode; // luacode to be called during init
+
+ int have_constructor;
+ int have_destructor;
+ String *destructor_action;
+ String *class_name;
+ String *constructor_name;
+
+ enum {
+ NO_CPP,
+ VARIABLE,
+ MEMBER_FUNC,
+ CONSTRUCTOR,
+ DESTRUCTOR,
+ MEMBER_VAR,
+ CLASS_CONST,
+ STATIC_FUNC,
+ STATIC_VAR
+ }current;
+
+public:
+
+ /* ---------------------------------------------------------------------
+ * LUA()
+ *
+ * Initialize member data
+ * --------------------------------------------------------------------- */
+
+ LUA() {
+ f_begin = 0;
+ f_runtime = 0;
+ f_header = 0;
+ f_wrappers = 0;
+ f_init = 0;
+ f_initbeforefunc = 0;
+ PrefixPlusUnderscore = 0;
+
+ s_cmd_tab = s_var_tab = s_const_tab = s_luacode = 0;
+ current=NO_CPP;
+ }
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ This is called to initalise 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, stderr);
+ }
+ }
+ }
+
+ /* 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 */
+ String *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);
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ s_cmd_tab,s_var_tab & s_const_tab hold the names of the fns for
+ registering with SWIG.
+ These will be filled in when the functions/variables are wrapped &
+ then added to the end of the wrappering code
+ just before it is written to file
+ NEW LANGUAGE NOTE:END ************************************************/
+ // Initialize some variables for the object interface
+ s_cmd_tab = NewString("");
+ s_var_tab = NewString("");
+ // s_methods_tab = NewString("");
+ s_const_tab = NewString("");
+
+ s_luacode = NewString("");
+ Swig_register_filebyname("luacode", s_luacode);
+
+ current=NO_CPP;
+
+ /* Standard stuff for the SWIG runtime section */
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n");
+ Printf(f_runtime, "#define SWIGLUA\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\n", module);
+
+ Printf(s_cmd_tab, "\nstatic const struct luaL_reg swig_commands[] = {\n");
+ Printf(s_var_tab, "\nstatic swig_lua_var_info swig_variables[] = {\n");
+ Printf(s_const_tab, "\nstatic swig_lua_const_info swig_constants[] = {\n");
+ 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");
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n}\n#endif\n");
+
+ // Done. Close up the module & write to the wrappers
+ Printv(s_cmd_tab, tab4, "{0,0}\n", "};\n", NIL);
+ Printv(s_var_tab, tab4, "{0,0,0}\n", "};\n", NIL);
+ Printv(s_const_tab, tab4, "{0,0,0,0,0,0}\n", "};\n", NIL);
+ Printv(f_wrappers, s_cmd_tab, s_var_tab, s_const_tab, NIL);
+ 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 excaped 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(s_cmd_tab);
+ Delete(s_var_tab);
+ Delete(s_const_tab);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_initbeforefunc);
+ Close(f_begin);
+ Delete(f_runtime);
+ Delete(f_begin);
+
+ /* Done */
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * importDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int importDirective(Node *n) {
+ return Language::importDirective(n);
+ }
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ This is it!
+ you get this one right, and most of your work is done
+ but its going to take soem file to get it working right
+ quite a bit of this is generally boilerplate code
+ (or stuff I dont understand)
+ that which matters will have extra added comments
+ NEW LANGUAGE NOTE:END ************************************************/
+ /* ---------------------------------------------------------------------
+ * functionWrapper()
+ *
+ * Create a function declaration and register it with the interpreter.
+ * --------------------------------------------------------------------- */
+
+ virtual int functionWrapper(Node *n) {
+ REPORT("functionWrapper",n);
+
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *d = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ //Printf(stdout,"functionWrapper %s %s\n",name,iname);
+ Parm *p;
+ String *tm;
+ int i;
+ //Printf(stdout,"functionWrapper %s %s %d\n",name,iname,current);
+ // int returnval=0; // number of arguments returned
+
+ String *overname = 0;
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n)) {
+ Printf(stderr,"addSymbol(%s) failed\n",iname);
+ return SWIG_ERROR;
+ }
+ }
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ the wrapper object holds all the wrappering 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);
+ }
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ the format of a lua fn is:
+ static int wrap_XXX(lua_State* L){...}
+ this line adds this into the wrappering 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");
+ }
+
+
+ /* Which input argument to start with? */
+ // int start = (current == MEMBER_FUNC || current == MEMBER_VAR || current == DESTRUCTOR) ? 1 : 0;
+
+ /* Offset to skip over the attribute name */
+ // int offset = (current == MEMBER_VAR) ? 1 : 0;
+
+ /* 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 on 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;
+ // String *numoutputs=NULL;
+ char source[64];
+ //Printf(argument_check, "SWIG_check_num_args(\"%s\",%d,%d)\n",name,num_required,num_arguments);
+ Printf(argument_check, "SWIG_check_num_args(\"%s\",%d,%d)\n",name,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", name, 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 dont 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", "result");
+ 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 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, "result", 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", "result");
+ 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, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ 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", "result");
+
+ /* Dump the function out */
+ /* in Lua we will not emit the destructor as a wrappered 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. */
+ if (!Getattr(n, "sym:overloaded")) {
+ // add_method(n, iname, wname, description);
+ if (current==NO_CPP || current==STATIC_FUNC) // emit normal fns & static fns
+ Printv(s_cmd_tab, tab4, "{ \"", iname, "\", ", Swig_name_wrapper(iname), "},\n", NIL);
+ // Printv(s_cmd_tab, tab4, "{ SWIG_prefix \"", iname, "\", (swig_wrapper_func) ", Swig_name_wrapper(iname), "},\n", NIL);
+ } else {
+ if (!Getattr(n, "sym:nextSibling")) {
+ dispatchFunction(n);
+ }
+ }
+
+ Delete(argument_check);
+ Delete(argument_parse);
+
+ Delete(cleanup);
+ Delete(outarg);
+ // Delete(description);
+ Delete(wname);
+ DelWrapper(f);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * 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
+ nost of the real work in again typemaps:
+ look for %typecheck(SWIG_TYPECHECK_*) in the .swg file
+ NEW LANGUAGE NOTE:END ************************************************/
+ void dispatchFunction(Node *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 *wname = Swig_name_wrapper(symname);
+
+ //Printf(stdout,"Swig_overload_dispatch %s %s '%s' %d\n",symname,wname,dispatch,maxargs);
+
+ 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 {
+ Printf(protoTypes, "\n\" %s(%s)\\n\"", SwigType_str(Getattr(sibl, "name"), 0), ParmList_protostr(Getattr(sibl, "wrap:parms")));
+ } while ((sibl = Getattr(sibl, "sym:nextSibling")));
+ Printf(f->code, "lua_pushstring(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);
+ //add_method(symname,wname,0);
+ if (current==NO_CPP || current==STATIC_FUNC) // emit normal fns & static fns
+ Printv(s_cmd_tab, tab4, "{ \"", symname, "\",", wname, "},\n", NIL);
+
+ DelWrapper(f);
+ Delete(dispatch);
+ Delete(tmp);
+ Delete(wname);
+ }
+
+
+ /* ------------------------------------------------------------
+ * 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 *iname = Getattr(n, "sym:name");
+ current=VARIABLE;
+ // let SWIG generate the wrappers
+ int result = Language::variableWrapper(n);
+ current=NO_CPP;
+ // normally SWIG will generate 2 wrappers, a get and a set
+ // but in certain scenarios (immutable, or if its arrays), it will not
+ String *getName = Swig_name_wrapper(Swig_name_get(iname));
+ String *setName = 0;
+ // checking whether it can be set to or not appears to be a very error prone issue
+ // I refered to the Language::variableWrapper() to find this out
+ bool assignable=is_assignable(n) ? true : false;
+ SwigType *type = Getattr(n, "type");
+ String *tm = Swig_typemap_lookup("globalin", n, iname, 0);
+ if (!tm && SwigType_isarray(type))
+ assignable=false;
+ Delete(tm);
+
+ if (assignable) {
+ setName = Swig_name_wrapper(Swig_name_set(iname));
+ } else {
+ // how about calling a 'this is not settable' error message?
+ setName = NewString("SWIG_Lua_set_immutable"); // error message
+ //setName = NewString("0");
+ }
+ // register the variable
+ Printf(s_var_tab, "%s{ \"%s\", %s, %s },\n", tab4, iname, getName, setName);
+ Delete(getName);
+ Delete(setName);
+ return result;
+ }
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ * ------------------------------------------------------------ */
+ virtual int constantWrapper(Node *n) {
+ // REPORT("constantWrapper", n);
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ //String *nsname = !nspace ? Copy(iname) : NewStringf("%s::%s",ns_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;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+ //if (nspace) 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(s_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) {
+ // REPORT("nativeWrapper", n);
+ String *symname = Getattr(n, "sym:name");
+ String *wrapname = Getattr(n, "wrap:name");
+ if (!addSymbol(wrapname, n))
+ return SWIG_ERROR;
+
+ Printv(s_cmd_tab, tab4, "{ \"", symname, "\",", wrapname, "},\n", NIL);
+ // return Language::nativeWrapper(n); // this does nothing...
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * enumDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int enumDeclaration(Node *n) {
+ return Language::enumDeclaration(n);
+ }
+
+ /* ------------------------------------------------------------
+ * enumvalueDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int enumvalueDeclaration(Node *n) {
+ return Language::enumvalueDeclaration(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int classDeclaration(Node *n) {
+ return Language::classDeclaration(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int classHandler(Node *n) {
+ //REPORT("classHandler", n);
+
+ String *mangled_classname = 0;
+ String *real_classname = 0;
+
+ constructor_name = 0;
+ have_constructor = 0;
+ have_destructor = 0;
+ destructor_action = 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);
+
+ // not sure exactly how this workswhat 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 (Getattr(emitted, mangled_classname))
+ return SWIG_NOWRAP;
+ Setattr(emitted, mangled_classname, "1");
+
+ s_attr_tab = NewString("");
+ Printf(s_attr_tab, "static swig_lua_attribute swig_");
+ Printv(s_attr_tab, mangled_classname, "_attributes[] = {\n", NIL);
+
+ s_methods_tab = NewString("");
+ Printf(s_methods_tab, "static swig_lua_method swig_");
+ Printv(s_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'
+ String *wrap_class = NewStringf("&_wrap_class_%s", mangled_classname);
+ SwigType_remember_clientdata(t, wrap_class);
+
+ String *rt = Copy(Getattr(n, "classtype"));
+ 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);
+
+ // emit a function to be called to delete the object
+ if (have_destructor) {
+ Printv(f_wrappers, "static 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(s_methods_tab, " {0,0}\n};\n");
+ Printv(f_wrappers, s_methods_tab, NIL);
+
+ Printf(s_attr_tab, " {0,0,0}\n};\n");
+ Printv(f_wrappers, s_attr_tab, NIL);
+
+ Delete(s_methods_tab);
+ Delete(s_attr_tab);
+
+ // Handle inheritance
+ // note: with the idea of class hireachied 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;
+ }
+ // old code: (used the pointer to the base class)
+ //String *bmangle = Swig_name_mangle(bname);
+ //Printf(base_class, "&_wrap_class_%s", bmangle);
+ //Putc(',', base_class);
+ //Delete(bmangle);
+ // new code: stores a null pointer & the name
+ Printf(base_class, "0,");
+ Printf(base_class_names, "\"%s *\",", SwigType_namestr(bname));
+
+ b = Next(b);
+ index++;
+ }
+ }
+
+ Printv(f_wrappers, "static swig_lua_class *swig_", mangled_classname, "_bases[] = {", base_class, "0};\n", NIL);
+ Delete(base_class);
+ Printv(f_wrappers, "static const char *swig_", mangled_classname, "_base_names[] = {", base_class_names, "0};\n", NIL);
+ Delete(base_class_names);
+
+ Printv(f_wrappers, "static swig_lua_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(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");
+ }
+ Printf(f_wrappers, ", swig_%s_methods, swig_%s_attributes, swig_%s_bases, swig_%s_base_names };\n\n", mangled_classname, mangled_classname, mangled_classname, mangled_classname);
+
+ // Printv(f_wrappers, ", swig_", mangled_classname, "_methods, swig_", mangled_classname, "_attributes, swig_", mangled_classname, "_bases };\n\n", NIL);
+ // Printv(s_cmd_tab, tab4, "{ SWIG_prefix \"", class_name, "\", (swig_wrapper_func) SWIG_ObjectConstructor, &_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");
+ //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(Getattr(n, "sym:name"), "__unm") == 0) {
+ //Printf(stdout, "unary minus: ignore one argument\n");
+ SetInt(n, "lua:ignore_args", 1);
+ }
+
+ String *realname, *rname;
+
+ current = MEMBER_FUNC;
+ Language::memberfunctionHandler(n);
+ current = NO_CPP;
+
+ realname = iname ? iname : name;
+ rname = Swig_name_wrapper(Swig_name_member(class_name, realname));
+ if (!Getattr(n, "sym:nextSibling")) {
+ Printv(s_methods_tab, tab4, "{\"", realname, "\", ", rname, "}, \n", NIL);
+ }
+ Delete(rname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * membervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int membervariableHandler(Node *n) {
+ // REPORT("membervariableHandler",n);
+ String *symname = Getattr(n, "sym:name");
+ String *gname, *sname;
+
+ current = MEMBER_VAR;
+ Language::membervariableHandler(n);
+ current = NO_CPP;
+ gname = Swig_name_wrapper(Swig_name_get(Swig_name_member(class_name, symname)));
+ if (!GetFlag(n, "feature:immutable")) {
+ sname = Swig_name_wrapper(Swig_name_set(Swig_name_member(class_name, symname)));
+ } else {
+ //sname = NewString("0");
+ sname = NewString("SWIG_Lua_set_immutable"); // error message
+ }
+ Printf(s_attr_tab,"%s{ \"%s\", %s, %s},\n",tab4,symname,gname,sname);
+ Delete(gname);
+ Delete(sname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constructorHandler()
+ *
+ * Method for adding C++ member constructor
+ * ------------------------------------------------------------ */
+
+ virtual int constructorHandler(Node *n) {
+ // REPORT("constructorHandler", n);
+ current = CONSTRUCTOR;
+ Language::constructorHandler(n);
+ current = NO_CPP;
+ constructor_name = NewString(Getattr(n, "sym:name"));
+ have_constructor = 1;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * destructorHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int destructorHandler(Node *n) {
+ REPORT("destructorHandler", n);
+ current = DESTRUCTOR;
+ Language::destructorHandler(n);
+ current = NO_CPP;
+ have_destructor = 1;
+ destructor_action = Getattr(n, "wrap:action");
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ *
+ * Wrap a static C++ function
+ * ---------------------------------------------------------------------- */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ current = STATIC_FUNC;
+ return Language::staticmemberfunctionHandler(n);
+ }
+
+ /* ------------------------------------------------------------
+ * memberconstantHandler()
+ *
+ * Create a C++ constant
+ * ------------------------------------------------------------ */
+
+ virtual int memberconstantHandler(Node *n) {
+ // REPORT("memberconstantHandler",n);
+ return Language::memberconstantHandler(n);
+ }
+
+ /* ---------------------------------------------------------------------
+ * staticmembervariableHandler()
+ * --------------------------------------------------------------------- */
+
+ virtual int staticmembervariableHandler(Node *n) {
+ // REPORT("staticmembervariableHandler",n);
+ current = STATIC_VAR;
+ return Language::staticmembervariableHandler(n);
+ }
+
+ /* ---------------------------------------------------------------------
+ * 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 termiated
+ String *sfile;
+ 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
+ * --------------------------------------------------------------------- */
+
+ /* This is to convert the string of Lua code into a proper string, which can then be
+ emitted into the C/C++ code.
+ Basically is 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);
+ }
+};
+
+/* 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/Source/Modules/main.cxx b/Source/Modules/main.cxx
new file mode 100644
index 0000000..477d83b
--- /dev/null
+++ b/Source/Modules/main.cxx
@@ -0,0 +1,1251 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * main.cxx
+ *
+ * Main entry point to the SWIG core.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_main_cxx[] = "$Id: main.cxx 11135 2009-02-20 20:55:16Z wsfulton $";
+
+#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 <limits.h> // for INT_MAX
+
+// Global variables
+
+Language *lang; // 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_TYPE_ABSTRACT 403
+ WARN_LANG_OVERLOAD_CONST 512
+ WARN_PARSE_BUILTIN_NAME 321
+ WARN_PARSE_REDUNDANT 322
+ */
+#define EXTRA_WARNINGS "202,309,403,512,321,322"
+
+extern "C" {
+ extern String *ModuleName;
+}
+
+/* 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\
+ -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-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 information for debugging typemaps\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\
+ -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\
+";
+
+static const char *usage2 = (const char *) "\
+ -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 - This output\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\
+ -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\
+ -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\
+";
+
+static const char *usage3 = (const char *) "\
+ -notemplatereduce - Disable reduction of the typedefs in templates\n\
+ -O - Enable the optimization options: \n\
+ -fastdispatch -fvirtual \n\
+ -o <outfile> - Set name of the output file to <outfile>\n\
+ -oh <headfile> - Set name of the output header file 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\
+ -small - Compile in virtual elimination & 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\
+\n";
+
+// Local variables
+static String *LangSubDir = 0; // Target language library subdirectory
+static char *SwigLib = 0; // Library directory
+static String *SwigLibWin = 0; // Extra Library directory for Windows
+static int freeze = 0;
+static String *lang_config = 0;
+static char *hpp_extension = (char *) "h";
+static char *cpp_extension = (char *) "cxx";
+static char *depends_extension = (char *) "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 char *outfile_name = 0;
+static char *outfile_name_h = 0;
+static int tm_debug = 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 memory_debug = 0;
+static int allkw = 0;
+static DOH *libfiles = 0;
+static DOH *cpps = 0;
+static String *dependencies_file = 0;
+static File *f_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 *all_output_files = 0;
+
+// -----------------------------------------------------------------------------
+// check_suffix()
+//
+// Checks the suffix of a file to see if we should emit extern declarations.
+// -----------------------------------------------------------------------------
+
+static int check_suffix(String *filename) {
+ const char *name = Char(filename);
+ const char *c;
+ if (!name)
+ return 0;
+ c = Swig_file_suffix(name);
+ 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)) {
+ return 1;
+ }
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+// install_opts(int argc, char *argv[])
+// 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(String *numlist)
+// 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 if not set and
+// adds trailing file separator if necessary.
+// -----------------------------------------------------------------------------
+
+static void set_outdir(const String *c_wrapper_file_dir) {
+
+ // Add file delimiter if not present in output directory name
+ if (outdir && 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);
+ }
+ // Use the C wrapper file's directory if the output directory has not been set by user
+ if (!outdir)
+ outdir = NewString(c_wrapper_file_dir);
+}
+
+/* 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 = (char *) 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");
+ Close(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");
+ Close(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");
+ Close(runtime);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Printf(runtime, "%s", s);
+ s = Swig_include_sys("swigrun.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'swigrun.swg'\n");
+ Close(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");
+ Close(runtime);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Printf(runtime, "%s", s);
+ Delete(s);
+
+ Close(runtime);
+ Delete(runtime);
+ SWIG_exit(EXIT_SUCCESS);
+}
+
+void SWIG_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, (char *) "=", (char *) " ", 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], "-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], "-nonaturalvar") == 0) {
+ Wrapper_naturalvar_mode_set(0);
+ 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], "-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) {
+ if (SwigLibWin)
+ printf("%s\n", Char(SwigLibWin));
+ printf("%s\n", SwigLib);
+ SWIG_exit(EXIT_SUCCESS);
+ } else if (strcmp(argv[i], "-o") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ outfile_name = Swig_copy_string(argv[i + 1]);
+ if (!outfile_name_h || !dependencies_file) {
+ char *ext = strrchr(outfile_name, '.');
+ String *basename = ext ? NewStringWithSize(outfile_name, ext - 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 = Swig_copy_string(Char(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 = Swig_copy_string(argv[i + 1]);
+ 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, "Please 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], "-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], "-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], "-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-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);
+ Swig_mark_arg(i);
+ help = 1;
+ }
+ }
+ }
+}
+
+
+
+
+
+int SWIG_main(int argc, char *argv[], Language *l) {
+ char *c;
+ extern void Swig_print_xml(Node *obj, String *filename);
+
+ /* Initialize the SWIG core */
+ Swig_init();
+
+ // Default warning suppression
+ Swig_warnfilter(EXTRA_WARNINGS, 1);
+
+ // Initialize the preprocessor
+ Preprocessor_init();
+
+ lang = l;
+
+ // 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);
+#ifdef MACSWIG
+ Preprocessor_define((DOH *) "SWIGMAC 1", 0);
+#endif
+#ifdef SWIGWIN32
+ Preprocessor_define((DOH *) "SWIGWIN32 1", 0);
+#endif
+
+ // 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 = 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);
+
+ // 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';
+ SwigLibWin = NewStringf("%sLib", buf); // Native windows installation path
+ }
+ SwigLib = Swig_copy_string(SWIG_LIB_WIN_UNIX); // Unix installation path using a drive letter (for msys/mingw)
+#else
+ SwigLib = Swig_copy_string(SWIG_LIB);
+#endif
+ } else {
+ SwigLib = Swig_copy_string(c);
+ }
+
+ libfiles = NewList();
+ all_output_files = NewList();
+
+ /* Check for SWIG_FEATURES environment variable */
+
+ SWIG_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);
+
+ 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 (SwigLibWin) {
+ rl = NewString("");
+ Printf(rl, "%s%s%s", SwigLibWin, 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 (SwigLibWin)
+ Swig_add_directory((String *) SwigLibWin);
+ Swig_add_directory((String *) SwigLib);
+
+ if (Verbose) {
+ printf("LangSubDir: %s\n", Char(LangSubDir));
+ printf("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;
+ char *outfile = Char(input_file);
+ if (outfile_name)
+ outfile = outfile_name;
+
+ if (Verbose)
+ printf("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);
+ Close(f_outfile);
+ }
+ }
+ }
+ } else {
+ // Run the preprocessor
+ if (Verbose)
+ printf("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 (!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_last_file());
+ for (i = 0; i < Len(libfiles); i++) {
+ Printf(fs, "\n%%include \"%s\"\n", 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;
+
+ char *basename = Swig_file_basename(outcurrentdir ? Swig_file_filename(input_file): Char(input_file));
+ 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: ", dependencies_target);
+ } else {
+ Printf(f_dependencies_file, "%s: ", outfile);
+ }
+ List *files = Preprocessor_depend();
+ for (int i = 0; i < Len(files); i++) {
+ if ((depend != 2) || ((depend == 2) && (Strncmp(Getitem(files, i), SwigLib, Len(SwigLib)) != 0))) {
+ Printf(f_dependencies_file, "\\\n %s ", Getitem(files, i));
+ }
+ }
+ Printf(f_dependencies_file, "\n");
+ if (f_dependencies_file != stdout)
+ Close(f_dependencies_file);
+ if (depend_only)
+ SWIG_exit(EXIT_SUCCESS);
+ } 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 (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 (dump_top & STAGE3) {
+ Printf(stdout, "debug-top stage 3\n");
+ Swig_print_tree(top);
+ }
+ if (dump_module & STAGE3) {
+ Printf(stdout, "debug-module stage 3\n");
+ Swig_print_tree(Getattr(top, "module"));
+ }
+
+ if (Verbose) {
+ Printf(stdout, "Generating wrappers...\n");
+ }
+
+ if (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(0);
+ }
+
+ 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);
+
+ char *basename = Swig_file_basename(outcurrentdir ? Swig_file_filename(infile): Char(infile));
+ 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);
+ }
+ set_outdir(Swig_file_dirname(Getattr(top, "outfile")));
+ if (Swig_contract_mode_get()) {
+ Swig_contracts(top);
+ }
+
+ // Check the suffix for a c/c++ file. If so, we're going to declare everything we see as "extern"
+ ForceExtern = check_suffix(input_file);
+
+ lang->top(top);
+
+ if (browse) {
+ Swig_browser(top, 0);
+ }
+ }
+ }
+ 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) {
+ 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));
+ Close(f_outfiles);
+ }
+ }
+
+ // Deletes
+ Delete(libfiles);
+ Preprocessor_delete();
+
+ while (freeze) {
+ }
+
+ if ((werror) && (Swig_warn_count())) {
+ return Swig_warn_count();
+ }
+ return Swig_error_count();
+}
+
+// --------------------------------------------------------------------------
+// SWIG_exit(int exit_code)
+//
+// Cleanup and either freeze or exit
+// --------------------------------------------------------------------------
+
+void SWIG_exit(int exit_code) {
+ while (freeze) {
+ }
+ exit(exit_code);
+}
diff --git a/Source/Modules/modula3.cxx b/Source/Modules/modula3.cxx
new file mode 100644
index 0000000..40f275a
--- /dev/null
+++ b/Source/Modules/modula3.cxx
@@ -0,0 +1,3987 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * modula3.cxx
+ *
+ * Modula3 language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_modula3_cxx[] = "$Id: modula3.cxx 11584 2009-08-16 00:04:29Z wsfulton $";
+
+/*
+ Text formatted with
+ indent -sob -br -ce -nut -npsl
+*/
+
+/*
+ Report:
+ - It's not a good concept to use member variables or global variables
+ for passing parameters to functions.
+ It's not a good concept to use functions of superclasses for specific services.
+ E.g. For SWIG this means: Generating accessor functions for member variables
+ is the most common but no general task to be processed in membervariableHandler.
+ Better provide a service function which generates accessor function code
+ and equip this service function with all parameters needed for input (parse node)
+ and output (generated code).
+ - How can I make globalvariableHandler not to generate
+ interface functions to two accessor functions
+ (that don't exist) ?
+ - How can I generate a typemap that turns every C reference argument into
+ its Modula 3 counterpart, that is
+ void test(Complex &z);
+ PROCEDURE test(VAR z:Complex);
+ - neither $*n_mangle nor $*n_type nor $*n_ltype return the type without
+ pointer converted to Modula3 equivalent,
+ $*n_mangle is the variant closest to what I expect
+ - using a typemap like
+ typemap(m3wrapintype) int * %{VAR $1_name: INTEGER%}
+ has the advantages:
+ - one C parameter can be turned into multiple M3 parameters
+ - the argument can be renamed
+ - using typemaps like
+ typemap(m3wrapinmode) int * "VAR"
+ typemap(m3wrapintype) int * "INTEGER"
+ has the advantages:
+ - multiple parameters with same type and default value can be bundled
+ - more conform to the other language modules
+ - Where takes the reduction of multi-typemaps place?
+ How can I preserve all parameters for functions of the intermediary class?
+ The answer is Getattrs(n,"tmap:m3rawintype:next")
+ - Char() can be used to transform a String to (char *)
+ which can be used for output with printf
+ - What is the while (checkAttribute()) loop in functionWrapper good for?
+ Appearently for skipping (numinputs=0) typemaps.
+ - SWIGTYPE const * - typemap is ignored, whereas
+ SWIGTYPE * - typemap is invoked, why?
+ Had it been (const SWIGTYPE *) instead?
+ - enumeration items should definitely be equipped
+ with its plain numerical value
+ One could add tag 'numvalue' in CParse/parser.y,
+ but it is still possible that someone declares an
+ enumeration using a symbolic constant.
+ I have quickly hacked
+ that the successive number is assigned
+ if "enumvalue" has suffix "+1".
+ The ultimate solution would be to generate a C program
+ which includes the header and outputs all constants.
+ This program might be compiled and run
+ by 'make' or by SWIG and the resulting output is fed back to SWIG.
+ - It's a bad idea to interpret feature value ""
+ 'disable feature' because the value ""
+ might be sensible in case of feature:modula3:oldprefix.
+ - What's the difference between "sym:name" and "name" ?
+ "name" is the original name and
+ "sym:name" is probably modified by the user using %rename
+ - Is it possible for 'configure' to find out if m3pp is installed
+ and to invoke it for generated Modula3 files?
+ - It would be better to separate an arguments purpose and its name,
+ because an output variable with name "OUTPUT" is not very descriptive.
+ In case of PLPlot this could be solved by typedefs
+ that assign special purposes to the array types.
+ - Can one interpret $n_basetype as the identifier matched with SWIGTYPE ?
+
+ Swig's odds:
+ - arguments of type (Node *) for SWIG functions
+ should be most often better (const Node *):
+ Swig_symbol_qualified, Getattr, nodeType, parentNode
+ - unique identifier style instead of
+ NewString, Getattr, firstChild
+ - 'class'.name is qualified,
+ 'enum'.name and 'enumitem'.name is not
+ - Swig_symbol_qualified() returns NIL for enumeration nodes
+
+ - Is there a function that creates a C representation of a SWIG type string?
+
+ ToDo:
+ - create WeakRefs only for resources returned by function marked with %newobject
+ -> part of output conversion
+ - clean typemap conception
+ - should a multi-typemap for m3wrapouttype skip the corresponding input parameters?
+ when yes - How to handle inout-arguments? In this case like in-argument.
+ - C++ classes
+ - C++ exceptions
+ - allow for moving RECORD and OBJECT definitions
+ to separate files, with the main type called T
+ - call-back functions
+ - special option: fast access to class members by pointer arithmetic,
+ member offsets can be determined by a C++ program that print them.
+ - emit enumeration definitions when its first item is declared,
+ currently enumerations are emitted at the beginning of the file
+
+ Done:
+ - addThrow should convert the typemap by itself
+ - not possible because routine for attaching mapped types to parameter nodes
+ won't work for the function node
+ - turning error codes into exceptions
+ -> part of output value checking
+ - create WeakRefs for resources allocated by the library
+ -> part of output conversion
+ - TRY..FINALLY..END; can be omitted
+ - if there is no m3wrapfreearg
+ - no exception can be raised in the body (empty RAISES) list
+*/
+
+#include "swigmod.h"
+
+#include <limits.h> // for INT_MAX
+#include <ctype.h>
+
+#define USAGE_ARG_DIR "m3wrapargdir typemap expect values: in, out, inout\n"
+
+class MODULA3:public Language {
+public:
+ enum block_type { no_block, constant, variable, blocktype, revelation };
+
+private:
+ struct M3File {
+ String *f;
+ Hash *import;
+ block_type bt;
+ /* VC++ 6 doesn't allow the access to 'no_block'
+ if it is a private member of MODULA3 class */
+ M3File():f(NewString("")), import(NewHash()), bt(no_block) {
+ }
+ ~M3File() {
+ Delete(f);
+ Delete(import);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * enterBlock()
+ *
+ * Make sure that a given declaration is written to the right declaration block,
+ * that is constants are written after "CONST" and so on ...
+ * ----------------------------------------------------------------------------- */
+ void enterBlock(block_type newbt) {
+ static const char *ident[] = { "", "\nCONST\n", "\nVAR\n", "\nTYPE\n", "\nREVEAL\n" };
+#ifdef DEBUG
+ if ((bt < 0) || (4 < bt)) {
+ printf("bt %d out of range\n", bt);
+ }
+#endif
+ if (newbt != bt) {
+ Append(f, ident[newbt]);
+ bt = newbt;
+ }
+ }
+
+ };
+
+ static const char *usage;
+ const String *empty_string;
+
+ Hash *swig_types_hash;
+ File *f_begin;
+ File *f_runtime;
+ File *f_header;
+ File *f_wrappers;
+ File *f_init;
+
+ bool proxy_flag; // Flag for generating proxy classes
+ bool have_default_constructor_flag;
+ 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 unsafe_module;
+
+ String *m3raw_name; // raw interface name
+ M3File m3raw_intf; // raw interface
+ M3File m3raw_impl; // raw implementation (usually empty)
+ String *m3wrap_name; // wrapper module
+ M3File m3wrap_intf;
+ M3File m3wrap_impl;
+ String *m3makefile;
+ String *targetlibrary;
+ String *proxy_class_def;
+ String *proxy_class_code;
+ String *proxy_class_name;
+ String *variable_name; //Name of a variable being wrapped
+ String *variable_type; //Type of this variable
+ String *enumeration_name; //Name of the current enumeration type
+ Hash *enumeration_items; //and its members
+ int enumeration_max;
+ Hash *enumeration_coll; //Collection of all enumerations.
+ /* The items are nodes with members:
+ "items" - hash of with key 'itemname' and content 'itemvalue'
+ "max" - maximum value in item list
+ */
+ String *constant_values;
+ String *constantfilename;
+ String *renamefilename;
+ String *typemapfilename;
+ String *m3raw_imports; //intermediary class imports from %pragma
+ String *module_imports; //module imports from %pragma
+ String *m3raw_baseclass; //inheritance for intermediary class class from %pragma
+ String *module_baseclass; //inheritance for module class from %pragma
+ String *m3raw_interfaces; //interfaces for intermediary class class from %pragma
+ String *module_interfaces; //interfaces for module class from %pragma
+ String *m3raw_class_modifiers; //class modifiers for intermediary class overriden by %pragma
+ String *m3wrap_modifiers; //class modifiers for module class overriden by %pragma
+ String *upcasts_code; //C++ casts for inheritance hierarchies C++ code
+ String *m3raw_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code
+ String *destructor_call; //C++ destructor call if any
+ String *outfile;
+
+ enum type_additions { none, pointer, reference };
+
+public:
+
+ /* -----------------------------------------------------------------------------
+ * MODULA3()
+ * ----------------------------------------------------------------------------- */
+
+MODULA3():
+ empty_string(NewString("")),
+ swig_types_hash(NULL),
+ f_begin(NULL),
+ f_runtime(NULL),
+ f_header(NULL),
+ f_wrappers(NULL),
+ f_init(NULL),
+ proxy_flag(true),
+ have_default_constructor_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),
+ unsafe_module(false),
+ m3raw_name(NULL),
+ m3raw_intf(),
+ m3raw_impl(),
+ m3wrap_name(NULL),
+ m3wrap_intf(),
+ m3wrap_impl(),
+ m3makefile(NULL),
+ targetlibrary(NULL),
+ proxy_class_def(NULL),
+ proxy_class_code(NULL),
+ proxy_class_name(NULL),
+ variable_name(NULL),
+ variable_type(NULL),
+ enumeration_name(NULL),
+ enumeration_items(NULL),
+ enumeration_max(0),
+ enumeration_coll(NULL),
+ constant_values(NULL),
+ constantfilename(NULL),
+ renamefilename(NULL),
+ typemapfilename(NULL),
+ m3raw_imports(NULL),
+ module_imports(NULL),
+ m3raw_baseclass(NULL),
+ module_baseclass(NULL),
+ m3raw_interfaces(NULL),
+ module_interfaces(NULL),
+ m3raw_class_modifiers(NULL),
+ m3wrap_modifiers(NULL),
+ upcasts_code(NULL),
+ m3raw_cppcasts_code(NULL),
+ destructor_call(NULL),
+ outfile(NULL) {
+ }
+
+ /************** some utility functions ***************/
+
+ /* -----------------------------------------------------------------------------
+ * getMappedType()
+ *
+ * Return the type of 'p' mapped by 'map'.
+ * Print a standard warning if 'p' can't be mapped.
+ * ----------------------------------------------------------------------------- */
+
+ String *getMappedType(Node *p, const char *map) {
+ String *mapattr = NewString("tmap:");
+ Append(mapattr, map);
+
+ String *tm = Getattr(p, mapattr);
+ if (tm == NIL) {
+ Swig_warning(WARN_MODULA3_TYPEMAP_TYPE_UNDEF, input_file, line_number,
+ "No '%s' typemap defined for type '%s'\n", map, SwigType_str(Getattr(p, "type"), 0));
+ }
+ Delete(mapattr);
+ return tm;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getMappedTypeNew()
+ *
+ * Similar to getMappedType but uses Swig_type_lookup_new.
+ * ----------------------------------------------------------------------------- */
+
+ String *getMappedTypeNew(Node *n, const char *map, const char *lname = "", bool warn = true) {
+ String *tm = Swig_typemap_lookup(map, n, lname, 0);
+ if ((tm == NIL) && warn) {
+ Swig_warning(WARN_MODULA3_TYPEMAP_TYPE_UNDEF, input_file, line_number,
+ "No '%s' typemap defined for type '%s'\n", map, SwigType_str(Getattr(n, "type"), 0));
+ }
+ return tm;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * attachMappedType()
+ *
+ * Obtain the type mapped by 'map' and attach it to the node
+ * ----------------------------------------------------------------------------- */
+
+ void attachMappedType(Node *n, const char *map, const char *lname = "") {
+ String *tm = Swig_typemap_lookup(map, n, lname, 0);
+ if (tm != NIL) {
+ String *attr = NewStringf("tmap:%s", map);
+ Setattr(n, attr, tm);
+ Delete(attr);
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * skipIgnored()
+ *
+ * Skip all parameters that have 'numinputs=0'
+ * with respect to a given typemap.
+ * ----------------------------------------------------------------------------- */
+
+ Node *skipIgnored(Node *p, const char *map) {
+ String *niattr = NewStringf("tmap:%s:numinputs", map);
+ String *nextattr = NewStringf("tmap:%s:next", map);
+
+ while ((p != NIL) && checkAttribute(p, niattr, "0")) {
+ p = Getattr(p, nextattr);
+ }
+
+ Delete(nextattr);
+ Delete(niattr);
+ return p;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * isInParam()
+ * isOutParam()
+ *
+ * Check if the parameter is intended for input or for output.
+ * ----------------------------------------------------------------------------- */
+
+ bool isInParam(Node *p) {
+ String *dir = Getattr(p, "tmap:m3wrapargdir");
+//printf("dir for %s: %s\n", Char(Getattr(p,"name")), Char(dir));
+ if ((dir == NIL) || (Strcmp(dir, "in") == 0)
+ || (Strcmp(dir, "inout") == 0)) {
+ return true;
+ } else if (Strcmp(dir, "out") == 0) {
+ return false;
+ } else {
+ printf("%s", USAGE_ARG_DIR);
+ return false;
+ }
+ }
+
+ bool isOutParam(Node *p) {
+ String *dir = Getattr(p, "tmap:m3wrapargdir");
+ if ((dir == NIL) || (Strcmp(dir, "in") == 0)) {
+ return false;
+ } else if ((Strcmp(dir, "out") == 0) || (Strcmp(dir, "inout") == 0)) {
+ return true;
+ } else {
+ printf("%s", USAGE_ARG_DIR);
+ return false;
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * printAttrs()
+ *
+ * For debugging: Show all attributes of a node and their values.
+ * ----------------------------------------------------------------------------- */
+ void printAttrs(Node *n) {
+ Iterator it;
+ for (it = First(n); it.key != NIL; it = Next(it)) {
+ printf("%s = %s\n", Char(it.key), Char(Getattr(n, it.key)));
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * hasPrefix()
+ *
+ * Check if a string have a given prefix.
+ * ----------------------------------------------------------------------------- */
+ bool hasPrefix(const String *str, const String *prefix) {
+ int len_prefix = Len(prefix);
+ return (Len(str) > len_prefix)
+ && (Strncmp(str, prefix, len_prefix) == 0);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getQualifiedName()
+ *
+ * Return fully qualified identifier of n.
+ * ----------------------------------------------------------------------------- */
+#if 0
+ // Swig_symbol_qualified returns NIL for enumeration nodes
+ String *getQualifiedName(Node *n) {
+ String *qual = Swig_symbol_qualified(n);
+ String *name = Getattr(n, "name");
+ if (hasContent(qual)) {
+ return NewStringf("%s::%s", qual, name);
+ } else {
+ return name;
+ }
+ }
+#else
+ String *getQualifiedName(Node *n) {
+ String *name = Copy(Getattr(n, "name"));
+ n = parentNode(n);
+ while (n != NIL) {
+ const String *type = nodeType(n);
+ if ((Strcmp(type, "class") == 0) || (Strcmp(type, "struct") == 0) || (Strcmp(type, "namespace") == 0)) {
+ String *newname = NewStringf("%s::%s", Getattr(n, "name"), name);
+ Delete(name);
+ //name = newname;
+ // Hmpf, the class name is already qualified.
+ return newname;
+ }
+ n = parentNode(n);
+ }
+ //printf("qualified name: %s\n", Char(name));
+ return name;
+ }
+#endif
+
+ /* -----------------------------------------------------------------------------
+ * nameToModula3()
+ *
+ * Turn usual C identifiers like "this_is_an_identifier"
+ * into usual Modula 3 identifier like "thisIsAnIdentifier"
+ * ----------------------------------------------------------------------------- */
+ String *nameToModula3(const String *sym, bool leadingCap) {
+ int len_sym = Len(sym);
+ char *csym = Char(sym);
+ char *m3sym = new char[len_sym + 1];
+ int i, j;
+ bool cap = leadingCap;
+ for (i = 0, j = 0; j < len_sym; j++) {
+ char c = csym[j];
+ if ((c == '_') || (c == ':')) {
+ cap = true;
+ } else {
+ if (isdigit(c)) {
+ m3sym[i] = c;
+ cap = true;
+ } else {
+ if (cap) {
+ m3sym[i] = (char)toupper(c);
+ } else {
+ m3sym[i] = (char)tolower(c);
+ }
+ cap = false;
+ }
+ i++;
+ }
+ }
+ m3sym[i] = 0;
+ String *result = NewString(m3sym);
+ delete[]m3sym;
+ return result;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * capitalizeFirst()
+ *
+ * Make the first character upper case.
+ * ----------------------------------------------------------------------------- */
+ String *capitalizeFirst(const String *str) {
+ return NewStringf("%c%s", toupper(*Char(str)), Char(str) + 1);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * prefixedNameToModula3()
+ *
+ * If feature modula3:oldprefix and modula3:newprefix is present
+ * and the C identifier has leading 'oldprefix'
+ * then it is replaced by the 'newprefix'.
+ * The rest is converted to Modula style.
+ * ----------------------------------------------------------------------------- */
+ String *prefixedNameToModula3(Node *n, const String *sym, bool leadingCap) {
+ String *oldPrefix = Getattr(n, "feature:modula3:oldprefix");
+ String *newPrefix = Getattr(n, "feature:modula3:newprefix");
+ String *result = NewString("");
+ char *short_sym = Char(sym);
+ // if at least one prefix feature is present
+ // the replacement takes place
+ if ((oldPrefix != NIL) || (newPrefix != NIL)) {
+ if ((oldPrefix == NIL) || hasPrefix(sym, oldPrefix)) {
+ short_sym += Len(oldPrefix);
+ if (newPrefix != NIL) {
+ Append(result, newPrefix);
+ }
+ }
+ }
+ String *suffix = nameToModula3(short_sym, leadingCap || hasContent(newPrefix));
+ Append(result, suffix);
+ Delete(suffix);
+ return result;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * hasContent()
+ *
+ * Check if the string exists and contains something.
+ * ----------------------------------------------------------------------------- */
+ bool hasContent(const String *str) {
+ return (str != NIL) && (Strcmp(str, "") != 0);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * openWriteFile()
+ *
+ * Caution: The file must be freshly allocated and will be destroyed
+ * by this routine.
+ * ----------------------------------------------------------------------------- */
+
+ File *openWriteFile(String *name) {
+ File *file = NewFile(name, "w", SWIG_output_files());
+ if (!file) {
+ FileErrorDisplay(name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(name);
+ return file;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * aToL()
+ *
+ * like atol but with additional user warning
+ * ----------------------------------------------------------------------------- */
+
+ long aToL(const String *value) {
+ char *endptr;
+ long numvalue = strtol(Char(value), &endptr, 0);
+ if (*endptr != 0) {
+ Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "The string <%s> does not denote a numeric value.\n", value);
+ }
+ return numvalue;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * strToL()
+ *
+ * like strtol but returns if the conversion was successful
+ * ----------------------------------------------------------------------------- */
+
+ bool strToL(const String *value, long &numvalue) {
+ char *endptr;
+ numvalue = strtol(Char(value), &endptr, 0);
+ return (*endptr == 0);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * evalExpr()
+ *
+ * Evaluate simple expression as they may occur in "enumvalue" attributes.
+ * ----------------------------------------------------------------------------- */
+
+ bool evalExpr(String *value, long &numvalue) {
+ // Split changes file status of String and thus cannot receive 'const' strings
+//printf("evaluate <%s>\n", Char(value));
+ List *summands = Split(value, '+', INT_MAX);
+ Iterator sm = First(summands);
+ numvalue = 0;
+ for (; sm.item != NIL; sm = Next(sm)) {
+ String *smvalue = Getattr(constant_values, sm.item);
+ long smnumvalue;
+ if (smvalue != NIL) {
+ if (!strToL(smvalue, smnumvalue)) {
+//printf("evaluation: abort 0 <%s>\n", Char(smvalue));
+ return false;
+ }
+ } else {
+ if (!strToL(sm.item, smnumvalue)) {
+//printf("evaluation: abort 1 <%s>\n", Char(sm));
+ return false;
+ }
+ }
+ numvalue += smnumvalue;
+ }
+//printf("evaluation: return %ld\n", numvalue);
+ return true;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * log2()
+ *
+ * Determine the position of the single bit of a power of two.
+ * Returns true if the given number is a power of two.
+ * ----------------------------------------------------------------------------- */
+
+ bool log2(long n, long &exp) {
+ exp = 0;
+ while (n > 0) {
+ if ((n & 1) != 0) {
+ return n == 1;
+ }
+ exp++;
+ n >>= 1;
+ }
+ return false;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * writeArg
+ *
+ * Write a function argument or RECORD entry definition.
+ * Bundles arguments of same type and default value.
+ * 'name.next==NIL' denotes the end of the entry or argument list.
+ * ----------------------------------------------------------------------------- */
+
+ bool equalNilStr(const String *str0, const String *str1) {
+ if (str0 == NIL) {
+ return (str1 == NIL);
+ //return (str0==NIL) == (str1==NIL);
+ } else {
+ return (str1 != NIL) && (Cmp(str0, str1) == 0);
+ //return Cmp(str0,str1)==0;
+ }
+ }
+
+ struct writeArgState {
+ String *mode, *name, *type, *value;
+ bool hold;
+ writeArgState():mode(NIL), name(NIL), type(NIL), value(NIL), hold(false) {
+ }
+ };
+
+ void writeArg(File *f, writeArgState & state, String *mode, String *name, String *type, String *value) {
+ /* skip the first argument,
+ only store the information for the next call in this case */
+ if (state.name != NIL) {
+ if ((!state.hold) && (state.mode != NIL)) {
+ Printf(f, "%s ", state.mode);
+ }
+ if ((name != NIL) && equalNilStr(state.mode, mode) && equalNilStr(state.type, type) && (state.value == NIL) && (value == NIL)
+ /* the same expression may have different values
+ due to side effects of the called function */
+ /*equalNilStr(state.value,value) */
+ ) {
+ Printf(f, "%s, ", state.name);
+ state.hold = true;
+ } else {
+ Append(f, state.name);
+ if (state.type != NIL) {
+ Printf(f, ": %s", state.type);
+ }
+ if (state.value != NIL) {
+ Printf(f, ":= %s", state.value);
+ }
+ Append(f, ";\n");
+ state.hold = false;
+ }
+ }
+ /* at the next call the current argument will be the previous one */
+ state.mode = mode;
+ state.name = name;
+ state.type = type;
+ state.value = value;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getProxyName()
+ *
+ * Test to see if a type corresponds to something wrapped with a proxy class
+ * Return NULL if not otherwise the proxy class name
+ * ----------------------------------------------------------------------------- */
+
+ String *getProxyName(SwigType *t) {
+ if (proxy_flag) {
+ Node *n = classLookup(t);
+ if (n) {
+ return Getattr(n, "sym:name");
+ }
+ }
+ return NULL;
+ }
+
+ /*************** language processing ********************/
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+
+ SWIG_library_directory("modula3");
+
+ // Look for certain command line options
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-generateconst") == 0) {
+ if (argv[i + 1]) {
+ constantfilename = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-generaterename") == 0) {
+ if (argv[i + 1]) {
+ renamefilename = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-generatetypemap") == 0) {
+ if (argv[i + 1]) {
+ typemapfilename = NewString(argv[i + 1]);
+ 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], "-help") == 0) {
+ Printf(stdout, "%s\n", usage);
+ }
+ }
+ }
+
+ // Add a symbol to the parser for conditional compilation
+ Preprocessor_define("SWIGMODULA3 1", 0);
+
+ // Add typemap definitions
+ SWIG_typemap_lang("modula3");
+ SWIG_config_file("modula3.swg");
+
+ allow_overloading();
+ }
+
+ /* ---------------------------------------------------------------------
+ * top()
+ * --------------------------------------------------------------------- */
+
+ virtual int top(Node *n) {
+ if (hasContent(constantfilename) || hasContent(renamefilename) || hasContent(typemapfilename)) {
+ int result = SWIG_OK;
+ if (hasContent(constantfilename)) {
+ result = generateConstantTop(n) && result;
+ }
+ if (hasContent(renamefilename)) {
+ result = generateRenameTop(n) && result;
+ }
+ if (hasContent(typemapfilename)) {
+ result = generateTypemapTop(n) && result;
+ }
+ return result;
+ } else {
+ return generateM3Top(n);
+ }
+ }
+
+ void scanConstant(File *file, Node *n) {
+ Node *child = firstChild(n);
+ while (child != NIL) {
+ String *constname = NIL;
+ String *type = nodeType(child);
+ if ((Strcmp(type, "enumitem") == 0)
+ || (Strcmp(type, "constant") == 0)) {
+#if 1
+ constname = getQualifiedName(child);
+#else
+ constname = Getattr(child, "value");
+ if ((!hasContent(constname))
+ || (('0' <= *Char(constname)) && (*Char(constname) <= '9'))) {
+ constname = Getattr(child, "name");
+ }
+#endif
+ }
+ if (constname != NIL) {
+ Printf(file, " printf(\"%%%%constnumeric(%%Lg) %s;\\n\", (long double)%s);\n", constname, constname);
+ }
+ scanConstant(file, child);
+ child = nextSibling(child);
+ }
+ }
+
+ int generateConstantTop(Node *n) {
+ File *file = openWriteFile(NewStringf("%s.c", constantfilename));
+ if (CPlusPlus) {
+ Printf(file, "#include <cstdio>\n");
+ } else {
+ Printf(file, "#include <stdio.h>\n");
+ }
+ Printf(file, "#include \"%s\"\n", input_file);
+ Printf(file, "\n");
+ Printf(file, "int main (int argc, char *argv[]) {\n");
+ Printf(file, "\
+/*This progam must work for floating point numbers and integers.\n\
+ Thus all numbers are converted to double precision floating point format.*/\n");
+ scanConstant(file, n);
+ Printf(file, " return 0;\n");
+ Printf(file, "}\n");
+ Close(file);
+ return SWIG_OK;
+ }
+
+ void scanRename(File *file, Node *n) {
+ Node *child = firstChild(n);
+ while (child != NIL) {
+ String *type = nodeType(child);
+ if (Strcmp(type, "cdecl") == 0) {
+ ParmList *p = Getattr(child, "parms");
+ if (p != NIL) {
+ String *name = getQualifiedName(child);
+ String *m3name = nameToModula3(name, true);
+ /*don't know how to get the original C type identifiers */
+ //String *arguments = createCSignature (child);
+ Printf(file, "%%rename(\"%s\") %s;\n", m3name, name);
+ /*Printf(file, "%%rename(\"%s\") %s %s(%s);\n",
+ m3name, Getattr(n,"type"), name, arguments); */
+ Delete(name);
+ Delete(m3name);
+ //Delete (arguments);
+ }
+ }
+ scanRename(file, child);
+ child = nextSibling(child);
+ }
+ }
+
+ int generateRenameTop(Node *n) {
+ File *file = openWriteFile(NewStringf("%s.i", renamefilename));
+ Printf(file, "\
+/* This file was generated from %s\n\
+ by SWIG with option -generaterename. */\n\
+\n", input_file);
+ scanRename(file, n);
+ Close(file);
+ return SWIG_OK;
+ }
+
+ void scanTypemap(File *file, Node *n) {
+ Node *child = firstChild(n);
+ while (child != NIL) {
+ String *type = nodeType(child);
+ //printf("nodetype %s\n", Char(type));
+ String *storage = Getattr(child, "storage");
+ if ((Strcmp(type, "class") == 0) || ((Strcmp(type, "cdecl") == 0) && (storage != NIL)
+ && (Strcmp(storage, "typedef") == 0))) {
+ String *name = getQualifiedName(child);
+ String *m3name = nameToModula3(name, true);
+ Printf(file, "%%typemap(\"m3wrapintype\") %s %%{%s%%}\n", name, m3name);
+ Printf(file, "%%typemap(\"m3rawintype\") %s %%{%s%%}\n", name, m3name);
+ Printf(file, "\n");
+ }
+ scanTypemap(file, child);
+ child = nextSibling(child);
+ }
+ }
+
+ int generateTypemapTop(Node *n) {
+ File *file = openWriteFile(NewStringf("%s.i", typemapfilename));
+ Printf(file, "\
+/* This file was generated from %s\n\
+ by SWIG with option -generatetypemap. */\n\
+\n", input_file);
+ scanTypemap(file, n);
+ Close(file);
+ return SWIG_OK;
+ }
+
+ int generateM3Top(Node *n) {
+ /* Initialize all of the output files */
+ 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("");
+
+ m3makefile = 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("m3rawintf", m3raw_intf.f);
+ Swig_register_filebyname("m3rawimpl", m3raw_impl.f);
+ Swig_register_filebyname("m3wrapintf", m3wrap_intf.f);
+ Swig_register_filebyname("m3wrapimpl", m3wrap_impl.f);
+ Swig_register_filebyname("m3makefile", m3makefile);
+
+ swig_types_hash = NewHash();
+
+ String *name = Getattr(n, "name");
+ // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
+ Node *optionsnode = Getattr(Getattr(n, "module"), "options");
+ if (optionsnode != NIL) {
+ String *m3raw_name_tmp = Getattr(optionsnode, "m3rawname");
+ if (m3raw_name_tmp != NIL) {
+ m3raw_name = Copy(m3raw_name_tmp);
+ }
+ }
+ if (m3raw_name == NIL) {
+ m3raw_name = NewStringf("%sRaw", name);
+ }
+ Setattr(m3wrap_impl.import, m3raw_name, "");
+
+ m3wrap_name = Copy(name);
+
+ proxy_class_def = NewString("");
+ proxy_class_code = NewString("");
+ m3raw_baseclass = NewString("");
+ m3raw_interfaces = NewString("");
+ m3raw_class_modifiers = NewString(""); // package access only to the intermediary class by default
+ m3raw_imports = NewString("");
+ m3raw_cppcasts_code = NewString("");
+ m3wrap_modifiers = NewString("public");
+ module_baseclass = NewString("");
+ module_interfaces = NewString("");
+ module_imports = NewString("");
+ upcasts_code = NewString("");
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n");
+ Printf(f_runtime, "#define SWIGMODULA3\n");
+ Printf(f_runtime, "\n");
+
+ Swig_name_register((char *) "wrapper", (char *) "Modula3_%f");
+ if (old_variable_names) {
+ Swig_name_register((char *) "set", (char *) "set_%v");
+ Swig_name_register((char *) "get", (char *) "get_%v");
+ }
+
+ Printf(f_wrappers, "\n#ifdef __cplusplus\n");
+ Printf(f_wrappers, "extern \"C\" {\n");
+ Printf(f_wrappers, "#endif\n\n");
+
+ constant_values = NewHash();
+ scanForConstPragmas(n);
+ enumeration_coll = NewHash();
+ collectEnumerations(enumeration_coll, n);
+
+ /* Emit code */
+ Language::top(n);
+
+ // Generate m3makefile
+ // This will be unnecessary if SWIG is invoked from Quake.
+ {
+ File *file = openWriteFile(NewStringf("%sm3makefile", Swig_file_dirname(outfile)));
+
+ Printf(file, "%% automatically generated quake file for %s\n\n", name);
+
+ /* Write the fragments written by '%insert'
+ collected while 'top' processed the parse tree */
+ Printv(file, m3makefile, NIL);
+
+ Printf(file, "import(\"libm3\")\n");
+ //Printf(file, "import_lib(\"%s\",\"/usr/lib\")\n", name);
+ Printf(file, "module(\"%s\")\n", m3raw_name);
+ Printf(file, "module(\"%s\")\n\n", m3wrap_name);
+
+ if (targetlibrary != NIL) {
+ Printf(file, "library(\"%s\")\n", targetlibrary);
+ } else {
+ Printf(file, "library(\"m3%s\")\n", name);
+ }
+ Close(file);
+ }
+
+ // Generate the raw interface
+ {
+ File *file = openWriteFile(NewStringf("%s%s.i3", Swig_file_dirname(outfile), m3raw_name));
+
+ emitBanner(file);
+
+ Printf(file, "INTERFACE %s;\n\n", m3raw_name);
+
+ emitImportStatements(m3raw_intf.import, file);
+ Printf(file, "\n");
+
+ // Write the interface generated within 'top'
+ Printv(file, m3raw_intf.f, NIL);
+
+ Printf(file, "\nEND %s.\n", m3raw_name);
+ Close(file);
+ }
+
+ // Generate the raw module
+ {
+ File *file = openWriteFile(NewStringf("%s%s.m3", Swig_file_dirname(outfile), m3raw_name));
+
+ emitBanner(file);
+
+ Printf(file, "MODULE %s;\n\n", m3raw_name);
+
+ emitImportStatements(m3raw_impl.import, file);
+ Printf(file, "\n");
+
+ // will be empty usually
+ Printv(file, m3raw_impl.f, NIL);
+
+ Printf(file, "BEGIN\nEND %s.\n", m3raw_name);
+ Close(file);
+ }
+
+ // Generate the interface for the comfort wrappers
+ {
+ File *file = openWriteFile(NewStringf("%s%s.i3", Swig_file_dirname(outfile), m3wrap_name));
+
+ emitBanner(file);
+
+ Printf(file, "INTERFACE %s;\n", m3wrap_name);
+
+ emitImportStatements(m3wrap_intf.import, file);
+ Printf(file, "\n");
+
+ {
+ Iterator it = First(enumeration_coll);
+ if (it.key != NIL) {
+ Printf(file, "TYPE\n");
+ }
+ for (; it.key != NIL; it = Next(it)) {
+ Printf(file, "\n");
+ emitEnumeration(file, it.key, it.item);
+ }
+ }
+
+ // Add the wrapper methods
+ Printv(file, m3wrap_intf.f, NIL);
+
+ // Finish off the class
+ Printf(file, "\nEND %s.\n", m3wrap_name);
+ Close(file);
+ }
+
+ // Generate the wrapper routines implemented in Modula 3
+ {
+ File *file = openWriteFile(NewStringf("%s%s.m3", Swig_file_dirname(outfile), m3wrap_name));
+
+ emitBanner(file);
+
+ if (unsafe_module) {
+ Printf(file, "UNSAFE ");
+ }
+ Printf(file, "MODULE %s;\n\n", m3wrap_name);
+
+ emitImportStatements(m3wrap_impl.import, file);
+ Printf(file, "\n");
+
+ // Add the wrapper methods
+ Printv(file, m3wrap_impl.f, NIL);
+
+ Printf(file, "\nBEGIN\nEND %s.\n", m3wrap_name);
+ Close(file);
+ }
+
+ 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 Modula 3 type wrapper class for each SWIG type
+ for (Iterator swig_type = First(swig_types_hash); swig_type.item != NIL; swig_type = Next(swig_type)) {
+ emitTypeWrapperClass(swig_type.key, swig_type.item);
+ }
+
+ Delete(swig_types_hash);
+ swig_types_hash = NULL;
+ Delete(constant_values);
+ constant_values = NULL;
+ Delete(enumeration_coll);
+ enumeration_coll = NULL;
+ Delete(m3raw_name);
+ m3raw_name = NULL;
+ Delete(m3raw_baseclass);
+ m3raw_baseclass = NULL;
+ Delete(m3raw_interfaces);
+ m3raw_interfaces = NULL;
+ Delete(m3raw_class_modifiers);
+ m3raw_class_modifiers = NULL;
+ Delete(m3raw_imports);
+ m3raw_imports = NULL;
+ Delete(m3raw_cppcasts_code);
+ m3raw_cppcasts_code = NULL;
+ Delete(proxy_class_def);
+ proxy_class_def = NULL;
+ Delete(proxy_class_code);
+ proxy_class_code = NULL;
+ Delete(m3wrap_name);
+ m3wrap_name = NULL;
+ Delete(m3wrap_modifiers);
+ m3wrap_modifiers = NULL;
+ Delete(targetlibrary);
+ targetlibrary = NULL;
+ Delete(module_baseclass);
+ module_baseclass = NULL;
+ Delete(module_interfaces);
+ module_interfaces = NULL;
+ Delete(module_imports);
+ module_imports = NULL;
+ Delete(upcasts_code);
+ upcasts_code = NULL;
+ Delete(constantfilename);
+ constantfilename = NULL;
+ Delete(renamefilename);
+ renamefilename = NULL;
+ Delete(typemapfilename);
+ typemapfilename = NULL;
+
+ /* 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);
+ Close(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");
+ }
+
+ /* ----------------------------------------------------------------------
+ * 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 {
+ Printf(stderr, "%s : Line %d. No return type for %%native method %s.\n", input_file, line_number, Getattr(n, "wrap:name"));
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * functionWrapper()
+ * ---------------------------------------------------------------------- */
+
+ virtual int functionWrapper(Node *n) {
+ String *type = nodeType(n);
+ String *funcType = Getattr(n, "modula3:functype");
+ String *rawname = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *capname = capitalizeFirst(symname);
+ //String *wname = Swig_name_wrapper(symname);
+
+ //printf("function: %s\n", Char(symname));
+ //printf(" purpose: %s\n", Char(funcType));
+
+ if (Strcmp(type, "cdecl") == 0) {
+ if (funcType == NIL) {
+ // no wrapper needed for plain functions
+ emitM3RawPrototype(n, rawname, symname);
+ emitM3Wrapper(n, symname);
+ } else if (Strcmp(funcType, "method") == 0) {
+ Setattr(n, "modula3:funcname", capname);
+ emitCWrapper(n, capname);
+ emitM3RawPrototype(n, capname, capname);
+ emitM3Wrapper(n, capname);
+ } else if (Strcmp(funcType, "accessor") == 0) {
+ /*
+ * 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 function name
+ Setattr(n, "proxyfuncname", capname);
+ Setattr(n, "imfuncname", symname);
+ if (hasPrefix(capname, "Set")) {
+ Setattr(n, "modula3:setname", capname);
+ } else {
+ Setattr(n, "modula3:getname", capname);
+ }
+
+ emitCWrapper(n, capname);
+ emitM3RawPrototype(n, capname, capname);
+ emitM3Wrapper(n, capname);
+ //proxyClassFunctionHandler(n);
+ }
+#ifdef DEBUG
+ } else {
+ Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Function type <%s> unknown.\n", Char(funcType));
+#endif
+ }
+ } else if ((Strcmp(type, "constructor") == 0) || (Strcmp(type, "destructor") == 0)) {
+ emitCWrapper(n, capname);
+ emitM3RawPrototype(n, capname, capname);
+ emitM3Wrapper(n, capname);
+ }
+// a Java relict
+#if 0
+ if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
+ emitM3Wrapper(n, capname);
+ }
+#endif
+
+ Delete(capname);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * emitCWrapper()
+ *
+ * Generate the wrapper in C which calls C++ methods.
+ * ---------------------------------------------------------------------- */
+
+ virtual int emitCWrapper(Node *n, const String *wname) {
+ String *rawname = Getattr(n, "name");
+ String *c_return_type = NewString("");
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ String *body = NewString("");
+ Hash *throws_hash = NewHash();
+ ParmList *l = Getattr(n, "parms");
+ SwigType *t = Getattr(n, "type");
+ String *symname = Getattr(n, "sym:name");
+
+ if (!Getattr(n, "sym:overloaded")) {
+ if (!addSymbol(wname, n)) {
+ return SWIG_ERROR;
+ }
+ }
+ // A new wrapper function object
+ Wrapper *f = NewWrapper();
+
+ /* Attach the non-standard typemaps to the parameter list. */
+ Swig_typemap_attach_parms("ctype", l, f);
+
+ /* Get return types */
+ {
+ String *tm = getMappedTypeNew(n, "ctype", "");
+ if (tm != NIL) {
+ Printf(c_return_type, "%s", tm);
+ }
+ }
+
+ bool is_void_return = (Cmp(c_return_type, "void") == 0);
+ if (!is_void_return) {
+ Wrapper_add_localv(f, "cresult", c_return_type, "cresult = 0", 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);
+ Setattr(n, "wrap:parms", l);
+
+ // Generate signature and argument conversion for C wrapper
+ {
+ Parm *p;
+ attachParameterNames(n, "tmap:name", "c:wrapname", "m3arg%d");
+ bool gencomma = false;
+ for (p = skipIgnored(l, "in"); p != NULL; p = skipIgnored(p, "in")) {
+
+ String *arg = Getattr(p, "c:wrapname");
+ {
+ /* Get the ctype types of the parameter */
+ String *c_param_type = getMappedType(p, "ctype");
+ // Add parameter to C function
+ Printv(f->def, gencomma ? ", " : "", c_param_type, " ", arg, NIL);
+ Delete(c_param_type);
+ gencomma = true;
+ }
+
+ // Get typemap for this argument
+ String *tm = getMappedType(p, "in");
+ if (tm != NIL) {
+ addThrows(throws_hash, "in", p);
+ Replaceall(tm, "$input", arg);
+ Setattr(p, "emit:input", arg); /*??? */
+ Printf(f->code, "%s\n", tm);
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ /* Insert constraint checking code */
+ {
+ Parm *p;
+ for (p = l; p;) {
+ String *tm = Getattr(p, "tmap:check");
+ if (tm != NIL) {
+ addThrows(throws_hash, "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 */
+ {
+ Parm *p;
+ for (p = l; p;) {
+ String *tm = Getattr(p, "tmap:freearg");
+ if (tm != NIL) {
+ addThrows(throws_hash, "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 */
+ {
+ Parm *p;
+ for (p = l; p;) {
+ String *tm = Getattr(p, "tmap:argout");
+ if (tm != NIL) {
+ addThrows(throws_hash, "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", "cresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ // Get any Modula 3 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);
+ Parm *p;
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ addThrows(throws_hash, "throws", p);
+ }
+ }
+
+ if (Cmp(nodeType(n), "constant") == 0) {
+ // Wrapping a constant hack
+ Swig_save("functionWrapper", n, "wrap:action", NIL);
+
+ // below based on Swig_VargetToFunction()
+ SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n));
+ Setattr(n, "wrap:action", NewStringf("result = (%s) %s;", SwigType_lstr(ty, 0), Getattr(n, "value")));
+ }
+
+ Setattr(n, "wrap:name", wname);
+
+ // Now write code to make the function call
+ if (!native_function_flag) {
+ String *actioncode = emit_action(n);
+
+ if (Cmp(nodeType(n), "constant") == 0) {
+ Swig_restore(n);
+ }
+
+ /* Return value if necessary */
+ String *tm;
+ if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
+ addThrows(throws_hash, "out", n);
+ Replaceall(tm, "$source", "result"); /* deprecated */
+ Replaceall(tm, "$target", "cresult"); /* deprecated */
+ Replaceall(tm, "$result", "cresult");
+ Printf(f->code, "%s", tm);
+ if (hasContent(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), rawname);
+ }
+ 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")) {
+ String *tm = Swig_typemap_lookup("newfree", n, "result", 0);
+ if (tm != NIL) {
+ addThrows(throws_hash, "newfree", n);
+ Replaceall(tm, "$source", "result"); /* deprecated */
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if (!native_function_flag) {
+ String *tm = Swig_typemap_lookup("ret", n, "result", 0);
+ if (tm != NIL) {
+ Replaceall(tm, "$source", "result"); /* deprecated */
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* Finish C wrapper */
+ Printf(f->def, ") {");
+
+ if (!is_void_return)
+ Printv(f->code, " return cresult;\n", NIL);
+ Printf(f->code, "}\n");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", symname);
+
+ 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);
+ }
+
+ Delete(c_return_type);
+ Delete(cleanup);
+ Delete(outarg);
+ Delete(body);
+ Delete(throws_hash);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * emitM3RawPrototype()
+ *
+ * Generate an EXTERNAL procedure declaration in Modula 3
+ * which is the interface to an existing C routine or a C wrapper.
+ * ---------------------------------------------------------------------- */
+
+ virtual int emitM3RawPrototype(Node *n, const String *cname, const String *m3name) {
+ String *im_return_type = NewString("");
+ //String *symname = Getattr(n,"sym:name");
+ ParmList *l = Getattr(n, "parms");
+
+ /* Attach the non-standard typemaps to the parameter list. */
+ Swig_typemap_attach_parms("m3rawinmode", l, NULL);
+ Swig_typemap_attach_parms("m3rawintype", l, NULL);
+
+ /* Get return types */
+ bool has_return;
+ {
+ String *tm = getMappedTypeNew(n, "m3rawrettype", "");
+ if (tm != NIL) {
+ Printf(im_return_type, "%s", tm);
+ }
+ has_return = hasContent(tm);
+ }
+
+ /* cname is the original name if 'n' denotes a C function
+ and it is the relabeled name (sym:name) if 'n' denotes a C++ method or similar */
+ m3raw_intf.enterBlock(no_block);
+ Printf(m3raw_intf.f, "\n<* EXTERNAL %s *>\nPROCEDURE %s (", cname, m3name);
+
+ // Generate signature for raw interface
+ {
+ Parm *p;
+ writeArgState state;
+ attachParameterNames(n, "tmap:rawinname", "modula3:rawname", "arg%d");
+ for (p = skipIgnored(l, "m3rawintype"); p != NULL; p = skipIgnored(p, "m3rawintype")) {
+
+ /* Get argument passing mode, should be one of VALUE, VAR, READONLY */
+ String *mode = Getattr(p, "tmap:m3rawinmode");
+ String *argname = Getattr(p, "modula3:rawname");
+ String *im_param_type = getMappedType(p, "m3rawintype");
+ addImports(m3raw_intf.import, "m3rawintype", p);
+
+ writeArg(m3raw_intf.f, state, mode, argname, im_param_type, NIL);
+ if (im_param_type != NIL) {
+ p = Getattr(p, "tmap:m3rawintype:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ writeArg(m3raw_intf.f, state, NIL, NIL, NIL, NIL);
+ }
+
+ /* Finish M3 raw prototype */
+ Printf(m3raw_intf.f, ")");
+ // neither a C wrapper nor a plain C function may throw an exception
+ //generateThrowsClause(throws_hash, m3raw_intf.f);
+ if (has_return) {
+ Printf(m3raw_intf.f, ": %s", im_return_type);
+ }
+ Printf(m3raw_intf.f, ";\n");
+
+ Delete(im_return_type);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * variableWrapper()
+ * ----------------------------------------------------------------------- */
+
+ virtual int variableWrapper(Node *n) {
+ Language::variableWrapper(n);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * globalvariableHandler()
+ * ----------------------------------------------------------------------- */
+
+ virtual int globalvariableHandler(Node *n) {
+ SwigType *t = Getattr(n, "type");
+ String *tm;
+
+ // Get the variable type
+ if ((tm = getMappedTypeNew(n, "m3wraptype", ""))) {
+ substituteClassname(t, tm);
+ }
+
+ variable_name = Getattr(n, "sym:name");
+ variable_type = Copy(tm);
+
+ // Get the variable type expressed in terms of Modula 3 equivalents of C types
+ if ((tm = getMappedTypeNew(n, "m3rawtype", ""))) {
+ m3raw_intf.enterBlock(no_block);
+ Printf(m3raw_intf.f, "\n<* EXTERNAL *> VAR %s: %s;\n", variable_name, tm);
+ }
+ // Output the property's accessor methods
+ /*
+ global_variable_flag = true;
+ int ret = Language::globalvariableHandler(n);
+ global_variable_flag = false;
+ */
+
+ Printf(m3wrap_impl.f, "\n\n");
+
+ //return ret;
+ return 1;
+ }
+
+ long getConstNumeric(Node *n) {
+ String *constnumeric = Getfeature(n, "constnumeric");
+ String *name = Getattr(n, "name");
+ long numvalue;
+ if (constnumeric == NIL) {
+ Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Feature 'constnumeric' is necessary to obtain value of %s.\n", name);
+ return 0;
+ } else if (!strToL(constnumeric, numvalue)) {
+ Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number,
+ "The feature 'constnumeric' of %s specifies value <%s> which is not an integer constant.\n", name, constnumeric);
+ return 0;
+ } else {
+ return numvalue;
+ }
+ }
+
+ /* ------------------------------------------------------------------------
+ * generateIntConstant()
+ *
+ * Considers node as an integer constant definition
+ * and generate a Modula 3 constant definition.
+ * ------------------------------------------------------------------------ */
+ void generateIntConstant(Node *n, String *name) {
+ String *value = Getattr(n, "value");
+ String *type = Getfeature(n, "modula3:constint:type");
+ String *conv = Getfeature(n, "modula3:constint:conv");
+
+ if (name == NIL) {
+ name = Getattr(n, "sym:name");
+ }
+
+ long numvalue;
+ bool isSimpleNum = strToL(value, numvalue);
+ if (!isSimpleNum) {
+ numvalue = getConstNumeric(n);
+ }
+
+ String *m3value;
+ if ((conv == NIL) || ((Strcmp(conv, "set:int") != 0) && (Strcmp(conv, "int:set") != 0))) {
+ /* The original value of the constant has precedence over
+ 'constnumeric' feature since we like to keep
+ the style (that is the base) of simple numeric constants */
+ if (isSimpleNum) {
+ if (hasPrefix(value, "0x")) {
+ m3value = NewStringf("16_%s", Char(value) + 2);
+ } else if ((Len(value) > 1) && (*Char(value) == '0')) {
+ m3value = NewStringf("8_%s", Char(value) + 1);
+ } else {
+ m3value = Copy(value);
+ }
+ /* If we cannot easily obtain the value of a numeric constant,
+ we use the results given by a C compiler. */
+ } else {
+ m3value = Copy(Getfeature(n, "constnumeric"));
+ }
+ } else {
+ // if the value can't be converted, it is ignored
+ if (convertInt(numvalue, numvalue, conv)) {
+ m3value = NewStringf("%d", numvalue);
+ } else {
+ m3value = NIL;
+ }
+ }
+
+ if (m3value != NIL) {
+ m3wrap_intf.enterBlock(constant);
+ Printf(m3wrap_intf.f, "%s", name);
+ if (hasContent(type)) {
+ Printf(m3wrap_intf.f, ": %s", type);
+ }
+ Printf(m3wrap_intf.f, " = %s;\n", m3value);
+ Delete(m3value);
+ }
+ }
+
+ /* -----------------------------------------------------------------------
+ * generateSetConstant()
+ *
+ * Considers node as a set constant definition
+ * and generate a Modula 3 constant definition.
+ * ------------------------------------------------------------------------ */
+ void generateSetConstant(Node *n, String *name) {
+ String *value = Getattr(n, "value");
+ String *type = Getfeature(n, "modula3:constset:type");
+ String *setname = Getfeature(n, "modula3:constset:set");
+ String *basename = Getfeature(n, "modula3:constset:base");
+ String *conv = Getfeature(n, "modula3:constset:conv");
+
+ m3wrap_intf.enterBlock(constant);
+
+ Printf(m3wrap_intf.f, "%s", name);
+ if (type != NIL) {
+ Printf(m3wrap_intf.f, ":%s ", type);
+ }
+ Printf(m3wrap_intf.f, " = %s{", setname);
+
+ long numvalue = 0;
+ if (!strToL(value, numvalue)) {
+ numvalue = getConstNumeric(n);
+ }
+ convertInt(numvalue, numvalue, conv);
+
+ bool isIntType = Strcmp(basename, "CARDINAL") == 0;
+ Hash *items = NIL;
+ if (!isIntType) {
+ Hash *enumeration = Getattr(enumeration_coll, basename);
+ if (enumeration == NIL) {
+ Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "There is no enumeration <%s> as needed for the set.\n", setname);
+ isIntType = true;
+ } else {
+ items = Getattr(enumeration, "items");
+ }
+ }
+
+ bool gencomma = false;
+ int bitpos = 0;
+ while (numvalue > 0) {
+ if ((numvalue & 1) != 0) {
+ if (isIntType) {
+ if (gencomma) {
+ Printv(m3wrap_intf.f, ",", NIL);
+ }
+ gencomma = true;
+ Printf(m3wrap_intf.f, "%d", bitpos);
+ } else {
+ char bitval[15];
+ sprintf(bitval, "%d", bitpos);
+ String *bitname = Getattr(items, bitval);
+ if (bitname == NIL) {
+ Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Enumeration <%s> has no value <%s>.\n", setname, bitval);
+ } else {
+ if (gencomma) {
+ Printv(m3wrap_intf.f, ",", NIL);
+ }
+ gencomma = true;
+ Printf(m3wrap_intf.f, "%s.%s", basename, bitname);
+ }
+ }
+ }
+ numvalue >>= 1;
+ bitpos++;
+ }
+ Printf(m3wrap_intf.f, "};\n");
+ }
+
+ void generateConstant(Node *n) {
+ // any of the special interpretation disables the default behaviour
+ String *enumitem = Getfeature(n, "modula3:enumitem:name");
+ String *constset = Getfeature(n, "modula3:constset:name");
+ String *constint = Getfeature(n, "modula3:constint:name");
+ if (hasContent(enumitem) || hasContent(constset) || hasContent(constint)) {
+ if (hasContent(constset)) {
+ generateSetConstant(n, constset);
+ }
+ if (hasContent(constint)) {
+ generateIntConstant(n, constint);
+ }
+ } else {
+ String *value = Getattr(n, "value");
+ String *name = Getattr(n, "sym:name");
+ if (name == NIL) {
+ name = Getattr(n, "name");
+ }
+ m3wrap_intf.enterBlock(constant);
+ Printf(m3wrap_intf.f, "%s = %s;\n", name, value);
+ }
+ }
+
+#if 0
+ void generateEnumerationItem(const String *name, const String *value, int numvalue) {
+ String *oldsymname = Getattr(enumeration_items, value);
+ if (oldsymname != NIL) {
+ Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "The value <%s> is already assigned to <%s>.\n", value, oldsymname);
+ }
+ Setattr(enumeration_items, value, name);
+ if (enumeration_max < numvalue) {
+ enumeration_max = numvalue;
+ }
+ }
+#endif
+
+ void emitEnumeration(File *file, String *name, Node *n) {
+ Printf(file, "%s = {", name);
+ int i;
+ bool gencomma = false;
+ int max = aToL(Getattr(n, "max"));
+ Hash *items = Getattr(n, "items");
+ for (i = 0; i <= max; i++) {
+ if (gencomma) {
+ Printf(file, ",");
+ }
+ Printf(file, "\n");
+ gencomma = true;
+ char numstr[15];
+ sprintf(numstr, "%d", i);
+ String *name = Getattr(items, numstr);
+ if (name != NIL) {
+ Printv(file, name, NIL);
+ } else {
+ Printf(file, "Dummy%d", i);
+ }
+ }
+ Printf(file, "\n};\n");
+ }
+
+ /* -----------------------------------------------------------------------
+ * constantWrapper()
+ *
+ * Handles constants and enumeration items.
+ * ------------------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ generateConstant(n);
+ return SWIG_OK;
+ }
+
+#if 0
+// enumerations are handled like constant definitions
+ /* -----------------------------------------------------------------------------
+ * enumDeclaration()
+ * ----------------------------------------------------------------------------- */
+
+ virtual int enumDeclaration(Node *n) {
+ String *symname = nameToModula3(Getattr(n, "sym:name"), true);
+ enumerationStart(symname);
+ int result = Language::enumDeclaration(n);
+ enumerationStop();
+ Delete(symname);
+ return result;
+ }
+#endif
+
+ /* -----------------------------------------------------------------------------
+ * enumvalueDeclaration()
+ * ----------------------------------------------------------------------------- */
+
+ virtual int enumvalueDeclaration(Node *n) {
+ generateConstant(n);
+ /*
+ This call would continue processing in the constantWrapper
+ which cannot handle values like "RED+1".
+ return Language::enumvalueDeclaration(n);
+ */
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * pragmaDirective()
+ *
+ * Valid Pragmas:
+ * imclassbase - base (extends) for the intermediary class
+ * imclassclassmodifiers - class modifiers for the intermediary class
+ * imclasscode - text (Modula 3 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 (Modula 3 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, "modula3") == 0) {
+
+ String *strvalue = NewString(value);
+ Replaceall(strvalue, "\\\"", "\"");
+/*
+ bool isEnumItem = Strcmp(code, "enumitem") == 0;
+ bool isSetItem = Strcmp(code, "setitem") == 0;
+*/
+ if (Strcmp(code, "imclassbase") == 0) {
+ Delete(m3raw_baseclass);
+ m3raw_baseclass = Copy(strvalue);
+ } else if (Strcmp(code, "imclassclassmodifiers") == 0) {
+ Delete(m3raw_class_modifiers);
+ m3raw_class_modifiers = Copy(strvalue);
+ } else if (Strcmp(code, "imclasscode") == 0) {
+ Printf(m3raw_intf.f, "%s\n", strvalue);
+ } else if (Strcmp(code, "imclassimports") == 0) {
+ Delete(m3raw_imports);
+ m3raw_imports = Copy(strvalue);
+ } else if (Strcmp(code, "imclassinterfaces") == 0) {
+ Delete(m3raw_interfaces);
+ m3raw_interfaces = Copy(strvalue);
+ } else if (Strcmp(code, "modulebase") == 0) {
+ Delete(module_baseclass);
+ module_baseclass = Copy(strvalue);
+ } else if (Strcmp(code, "moduleclassmodifiers") == 0) {
+ Delete(m3wrap_modifiers);
+ m3wrap_modifiers = Copy(strvalue);
+ } else if (Strcmp(code, "modulecode") == 0) {
+ Printf(m3wrap_impl.f, "%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, "unsafe") == 0) {
+ unsafe_module = true;
+ } else if (Strcmp(code, "library") == 0) {
+ if (targetlibrary != NULL) {
+ Delete(targetlibrary);
+ }
+ targetlibrary = Copy(strvalue);
+ } else if (Strcmp(code, "enumitem") == 0) {
+ } else if (Strcmp(code, "constset") == 0) {
+ } else if (Strcmp(code, "constint") == 0) {
+ } else if (Strcmp(code, "makesetofenum") == 0) {
+ m3wrap_intf.enterBlock(blocktype);
+ Printf(m3wrap_intf.f, "%sSet = SET OF %s;\n", value, value);
+ } else {
+ Swig_warning(WARN_MODULA3_UNKNOWN_PRAGMA, input_file, line_number, "Unrecognized pragma <%s>.\n", code);
+ }
+ Delete(strvalue);
+ }
+ }
+ return Language::pragmaDirective(n);
+ }
+
+ void Setfeature(Node *n, const char *feature, const String *value, bool warn = false) {
+ //printf("tag feature <%s> with value <%s>\n", feature, Char(value));
+ String *attr = NewStringf("feature:%s", feature);
+ if ((Setattr(n, attr, value) != 0) && warn) {
+ Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Feature <%s> of %s did already exist.\n", feature, Getattr(n, "name"));
+ }
+ Delete(attr);
+ }
+
+ String *Getfeature(Node *n, const char *feature) {
+ //printf("retrieve feature <%s> with value <%s>\n", feature, Char(value));
+ String *attr = NewStringf("feature:%s", feature);
+ String *result = Getattr(n, attr);
+ Delete(attr);
+ return result;
+ }
+
+ bool convertInt(long in, long &out, const String *mode) {
+ if ((mode == NIL) || (Strcmp(mode, "int:int") == 0) || (Strcmp(mode, "set:set") == 0)) {
+ out = in;
+ return true;
+ } else if (Strcmp(mode, "set:int") == 0) {
+ return log2(in, out);
+ } else if (Strcmp(mode, "int:set") == 0) {
+ out = 1L << in;
+ return unsigned (in) < (sizeof(out) * 8);
+ } else {
+ Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Unknown integer conversion method <%s>.\n", mode);
+ return false;
+ }
+ }
+
+ void collectEnumerations(Hash *enums, Node *n) {
+ Node *child = firstChild(n);
+ while (child != NIL) {
+ String *name = Getattr(child, "name");
+ const bool isConstant = Strcmp(nodeType(child), "constant") == 0;
+ const bool isEnumItem = Strcmp(nodeType(child), "enumitem") == 0;
+ if (isConstant || isEnumItem) {
+//printf("%s%s name %s\n", isConstant?"constant":"", isEnumItem?"enumitem":"", Char(name));
+ {
+ String *m3name = Getfeature(child, "modula3:enumitem:name");
+ String *m3enum = Getfeature(child, "modula3:enumitem:enum");
+ String *conv = Getfeature(child, "modula3:enumitem:conv");
+
+ if (m3enum != NIL) {
+//printf("m3enum %s\n", Char(m3enum));
+ if (m3name == NIL) {
+ m3name = name;
+ }
+
+ long max = -1;
+ Hash *items;
+ Hash *enumnode = Getattr(enums, m3enum);
+ if (enumnode == NIL) {
+ enumnode = NewHash();
+ items = NewHash();
+ Setattr(enumnode, "items", items);
+ Setattr(enums, m3enum, enumnode);
+ } else {
+ String *maxstr = Getattr(enumnode, "max");
+ if (maxstr != NIL) {
+ max = aToL(maxstr);
+ }
+ items = Getattr(enumnode, "items");
+ }
+ long numvalue;
+ String *value = Getattr(child, "value");
+//printf("value: %s\n", Char(value));
+ if ((value == NIL) || (!strToL(value, numvalue))) {
+ value = Getattr(child, "enumvalue");
+ if ((value == NIL) || (!evalExpr(value, numvalue))) {
+ numvalue = getConstNumeric(child);
+ }
+//printf("constnumeric: %s\n", Char(value));
+ }
+ Setattr(constant_values, name, NewStringf("%d", numvalue));
+ if (convertInt(numvalue, numvalue, conv)) {
+ String *newvalue = NewStringf("%d", numvalue);
+ String *oldname = Getattr(items, newvalue);
+ if (oldname != NIL) {
+ Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "The value <%s> is already assigned to <%s>.\n", value, oldname);
+ }
+//printf("items %lx, set %s = %s\n", (long) items, Char(newvalue), Char(m3name));
+ Setattr(items, newvalue, m3name);
+ if (max < numvalue) {
+ max = numvalue;
+ }
+ Setattr(enumnode, "max", NewStringf("%d", max));
+ }
+ }
+ }
+ }
+
+ collectEnumerations(enums, child);
+ child = nextSibling(child);
+ }
+ }
+
+ enum const_pragma_type { cpt_none, cpt_constint, cpt_constset, cpt_enumitem };
+
+ struct const_id_pattern {
+ String *prefix, *parentEnum;
+ };
+
+ void tagConstants(Node *first, String *parentEnum, const const_id_pattern & pat, const String *pragma, List *convdesc) {
+ Node *n = first;
+ while (n != NIL) {
+ String *name = getQualifiedName(n);
+ bool isConstant = Strcmp(nodeType(n), "constant") == 0;
+ bool isEnumItem = Strcmp(nodeType(n), "enumitem") == 0;
+ if ((isConstant || isEnumItem) && ((pat.prefix == NIL) || (hasPrefix(name, pat.prefix))) && ((pat.parentEnum == NIL) || ((parentEnum != NIL)
+ &&
+ (Strcmp
+ (pat.parentEnum, parentEnum)
+ == 0)))) {
+ //printf("tag %s\n", Char(name));
+ String *srctype = Getitem(convdesc, 1);
+ String *relationstr = Getitem(convdesc, 3);
+ List *relationdesc = Split(relationstr, ',', 2);
+
+ // transform name from C to Modula3 style
+ String *srcstyle = NIL;
+ String *newprefix = NIL;
+ {
+ //printf("name conversion <%s>\n", Char(Getitem(convdesc,2)));
+ List *namedesc = Split(Getitem(convdesc, 2), ',', INT_MAX);
+ Iterator nameit = First(namedesc);
+ for (; nameit.item != NIL; nameit = Next(nameit)) {
+ List *nameassign = Split(nameit.item, '=', 2);
+ String *tag = Getitem(nameassign, 0);
+ String *data = Getitem(nameassign, 1);
+ //printf("name conv <%s> = <%s>\n", Char(tag), Char(data));
+ if (Strcmp(tag, "srcstyle") == 0) {
+ srcstyle = Copy(data);
+ } else if (Strcmp(tag, "prefix") == 0) {
+ newprefix = Copy(data);
+ } else {
+ Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Unknown name conversion tag <%s> with value <%s>.\n", tag, data);
+ }
+ Delete(nameassign);
+ }
+ Delete(namedesc);
+ }
+ const char *stem = Char(name);
+ if (pat.prefix != NIL) {
+ //printf("pat.prefix %s for %s\n", Char(pat.prefix), Char(name));
+ stem += Len(pat.prefix);
+ }
+ String *newname;
+ if (Strcmp(srcstyle, "underscore") == 0) {
+ if (newprefix != NIL) {
+ String *newstem = nameToModula3(stem, true);
+ newname = NewStringf("%s%s", newprefix, newstem);
+ Delete(newstem);
+ } else {
+ newname = nameToModula3(stem, true);
+ }
+ } else {
+ if (srcstyle != NIL) {
+ Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Unknown C identifier style <%s>.\n", srcstyle);
+ }
+ newname = Copy(name);
+ }
+
+ if (Strcmp(pragma, "enumitem") == 0) {
+ if (Len(relationdesc) != 1) {
+ Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Expected <enumeration>, got <%s>.\n", relationstr);
+ }
+ Setfeature(n, "modula3:enumitem:name", newname, true);
+ Setfeature(n, "modula3:enumitem:enum", relationstr, true);
+ Setfeature(n, "modula3:enumitem:conv", NewStringf("%s:int", srctype), true);
+ } else if (Strcmp(pragma, "constint") == 0) {
+ if (Len(relationdesc) != 1) {
+ Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Expected <ordinal type>, got <%s>.\n", relationstr);
+ }
+ Setfeature(n, "modula3:constint:name", newname, true);
+ Setfeature(n, "modula3:constint:type", Getitem(relationdesc, 0), true);
+ Setfeature(n, "modula3:constint:conv", NewStringf("%s:int", srctype), true);
+ } else if (Strcmp(pragma, "constset") == 0) {
+ if (Len(relationdesc) != 2) {
+ Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Expected <set type,base type>, got <%s>.\n", relationstr);
+ }
+ String *settype = Getitem(relationdesc, 0);
+ Setfeature(n, "modula3:constset:name", newname, true);
+ //Setfeature(n,"modula3:constset:type",settype,true);
+ Setfeature(n, "modula3:constset:set", settype, true);
+ Setfeature(n, "modula3:constset:base", Getitem(relationdesc, 1), true);
+ Setfeature(n, "modula3:constset:conv", NewStringf("%s:set", srctype), true);
+ }
+
+ Delete(newname);
+ Delete(relationdesc);
+ }
+
+ if (Strcmp(nodeType(n), "enum") == 0) {
+ //printf("explore enum %s, qualification %s\n", Char(name), Char(Swig_symbol_qualified(n)));
+ tagConstants(firstChild(n), name, pat, pragma, convdesc);
+ } else {
+ tagConstants(firstChild(n), NIL, pat, pragma, convdesc);
+ }
+ n = nextSibling(n);
+ }
+ }
+
+ void scanForConstPragmas(Node *n) {
+ Node *child = firstChild(n);
+ while (child != NIL) {
+ const String *type = nodeType(child);
+ if (Strcmp(type, "pragma") == 0) {
+ const String *lang = Getattr(child, "lang");
+ const String *code = Getattr(child, "name");
+ String *value = Getattr(child, "value");
+
+ if (Strcmp(lang, "modula3") == 0) {
+ const_pragma_type cpt = cpt_none;
+ if (Strcmp(code, "constint") == 0) {
+ cpt = cpt_constint;
+ } else if (Strcmp(code, "constset") == 0) {
+ cpt = cpt_constset;
+ } else if (Strcmp(code, "enumitem") == 0) {
+ cpt = cpt_enumitem;
+ }
+ if (cpt != cpt_none) {
+ const_id_pattern pat = { NIL, NIL };
+
+ List *convdesc = Split(value, ';', 4);
+ List *patterndesc = Split(Getitem(convdesc, 0), ',', INT_MAX);
+ Iterator patternit;
+ for (patternit = First(patterndesc); patternit.item != NIL; patternit = Next(patternit)) {
+ List *patternassign = Split(patternit.item, '=', 2);
+ String *tag = Getitem(patternassign, 0);
+ String *data = Getitem(patternassign, 1);
+ if (Strcmp(tag, "prefix") == 0) {
+ pat.prefix = Copy(data);
+ } else if (Strcmp(tag, "enum") == 0) {
+ pat.parentEnum = Copy(data);
+ } else {
+ Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Unknown identification tag <%s> with value <%s>.\n", tag, data);
+ }
+ Delete(patternassign);
+ }
+ tagConstants(child, NIL, pat, code, convdesc);
+
+ Delete(patterndesc);
+ }
+ }
+ }
+ scanForConstPragmas(child);
+ child = nextSibling(child);
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * emitProxyClassDefAndCPPCasts()
+ * ----------------------------------------------------------------------------- */
+
+ void emitProxyClassDefAndCPPCasts(Node *n) {
+ String *c_classname = SwigType_namestr(Getattr(n, "name"));
+ String *c_baseclass = NULL;
+ String *baseclass = NULL;
+ String *c_baseclassname = NULL;
+ String *classDeclarationName = Getattr(n, "classDeclaration:name");
+
+ /* Deal with inheritance */
+ List *baselist = Getattr(n, "bases");
+ if (baselist != NIL) {
+ Iterator base = First(baselist);
+ c_baseclassname = Getattr(base.item, "name");
+ baseclass = Copy(getProxyName(c_baseclassname));
+ if (baseclass) {
+ c_baseclass = SwigType_namestr(Getattr(base.item, "name"));
+ }
+ base = Next(base);
+ if (base.item != NIL) {
+ Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, input_file,
+ line_number,
+ "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Modula 3.\n",
+ classDeclarationName, Getattr(base.item, "name"));
+ }
+ }
+
+ bool derived = baseclass && getProxyName(c_baseclassname);
+ if (!baseclass)
+ baseclass = NewString("");
+
+ // Inheritance from pure Modula 3 classes
+ const String *pure_baseclass = typemapLookup(n, "m3base", classDeclarationName, WARN_NONE);
+ if (hasContent(pure_baseclass) && hasContent(baseclass)) {
+ Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, input_file,
+ line_number,
+ "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Modula 3.\n", classDeclarationName, pure_baseclass);
+ }
+ // Pure Modula 3 interfaces
+ const String *pure_interfaces = typemapLookup(n, derived ? "m3interfaces_derived" : "m3interfaces",
+ classDeclarationName, WARN_NONE);
+
+ // Start writing the proxy class
+ Printv(proxy_class_def, typemapLookup(n, "m3imports", classDeclarationName, WARN_NONE), // Import statements
+ "\n", typemapLookup(n, "m3classmodifiers", classDeclarationName, WARN_MODULA3_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
+ " class $m3classname", // Class name and bases
+ (derived || *Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", baseclass, pure_baseclass, ((derived || *Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces
+ ", " : "", pure_interfaces, " {\n", " private IntPtr swigCPtr;\n", // Member variables for memory handling
+ derived ? "" : " protected bool swigCMemOwn;\n", "\n", " ", typemapLookup(n, "m3ptrconstructormodifiers", classDeclarationName, WARN_MODULA3_TYPEMAP_PTRCONSTMOD_UNDEF), // pointer constructor modifiers
+ " $m3classname(IntPtr cPtr, bool cMemoryOwn) ", // Constructor used for wrapping pointers
+ derived ?
+ ": base($imclassname.$m3classnameTo$baseclass(cPtr), cMemoryOwn) {\n"
+ : "{\n swigCMemOwn = cMemoryOwn;\n", " swigCPtr = cPtr;\n", " }\n", NIL);
+
+ if (!have_default_constructor_flag) { // All proxy classes need a constructor
+ Printv(proxy_class_def, "\n", " protected $m3classname() : this(IntPtr.Zero, false) {\n", " }\n", NIL);
+ }
+ // C++ destructor is wrapped by the Dispose method
+ // Note that the method name is specified in a typemap attribute called methodname
+ String *destruct = NewString("");
+ const String *tm = NULL;
+ Node *attributes = NewHash();
+ String *destruct_methodname = NULL;
+ if (derived) {
+ tm = typemapLookup(n, "m3destruct_derived", classDeclarationName, WARN_NONE, attributes);
+ destruct_methodname = Getattr(attributes, "tmap:m3destruct_derived:methodname");
+ } else {
+ tm = typemapLookup(n, "m3destruct", classDeclarationName, WARN_NONE, attributes);
+ destruct_methodname = Getattr(attributes, "tmap:m3destruct:methodname");
+ }
+ if (!destruct_methodname) {
+ Swig_error(input_file, line_number, "No methodname attribute defined in m3destruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
+ }
+ // Emit the Finalize and Dispose methods
+ if (tm) {
+ // Finalize method
+ if (*Char(destructor_call)) {
+ Printv(proxy_class_def, typemapLookup(n, "m3finalize", classDeclarationName, WARN_NONE), NIL);
+ }
+ // Dispose method
+ Printv(destruct, tm, NIL);
+ if (*Char(destructor_call))
+ Replaceall(destruct, "$imcall", destructor_call);
+ else
+ Replaceall(destruct, "$imcall", "throw new MethodAccessException(\"C++ destructor does not have public access\")");
+ if (*Char(destruct))
+ Printv(proxy_class_def, "\n public ", derived ? "override" : "virtual", " void ", destruct_methodname, "() ", destruct, "\n", NIL);
+ }
+ Delete(attributes);
+ Delete(destruct);
+
+ // Emit various other methods
+ Printv(proxy_class_def, typemapLookup(n, "m3getcptr", classDeclarationName, WARN_MODULA3_TYPEMAP_GETCPTR_UNDEF), // getCPtr method
+ typemapLookup(n, "m3code", classDeclarationName, WARN_NONE), // extra Modula 3 code
+ "\n", NIL);
+
+ // Substitute various strings into the above template
+ Replaceall(proxy_class_def, "$m3classname", proxy_class_name);
+ Replaceall(proxy_class_code, "$m3classname", proxy_class_name);
+
+ Replaceall(proxy_class_def, "$baseclass", baseclass);
+ Replaceall(proxy_class_code, "$baseclass", baseclass);
+
+ Replaceall(proxy_class_def, "$imclassname", m3raw_name);
+ Replaceall(proxy_class_code, "$imclassname", m3raw_name);
+
+ // Add code to do C++ casting to base class (only for classes in an inheritance hierarchy)
+ if (derived) {
+ Printv(m3raw_cppcasts_code, "\n [DllImport(\"", m3wrap_name, "\", EntryPoint=\"Modula3_", proxy_class_name, "To", baseclass, "\")]\n", NIL);
+ Printv(m3raw_cppcasts_code, " public static extern IntPtr ", "$m3classnameTo$baseclass(IntPtr objectRef);\n", NIL);
+
+ Replaceall(m3raw_cppcasts_code, "$m3classname", proxy_class_name);
+ Replaceall(m3raw_cppcasts_code, "$baseclass", baseclass);
+
+ Printv(upcasts_code,
+ "SWIGEXPORT long Modula3_$imclazznameTo$imbaseclass",
+ "(long objectRef) {\n",
+ " long baseptr = 0;\n" " *($cbaseclass **)&baseptr = *($cclass **)&objectRef;\n" " return baseptr;\n" "}\n", "\n", NIL);
+
+ Replaceall(upcasts_code, "$imbaseclass", baseclass);
+ Replaceall(upcasts_code, "$cbaseclass", c_baseclass);
+ Replaceall(upcasts_code, "$imclazzname", proxy_class_name);
+ Replaceall(upcasts_code, "$cclass", c_classname);
+ }
+ Delete(baseclass);
+ }
+
+ /* ----------------------------------------------------------------------
+ * getAttrString()
+ *
+ * If necessary create and return the string
+ * associated with a certain attribute of 'n'.
+ * ---------------------------------------------------------------------- */
+
+ String *getAttrString(Node *n, const char *attr) {
+ String *str = Getattr(n, attr);
+ if (str == NIL) {
+ str = NewString("");
+ Setattr(n, attr, str);
+ }
+ return str;
+ }
+
+ /* ----------------------------------------------------------------------
+ * getMethodDeclarations()
+ *
+ * If necessary create and return the handle
+ * where the methods of the current access can be written to.
+ * 'n' must be a member of a struct or a class.
+ * ---------------------------------------------------------------------- */
+
+ String *getMethodDeclarations(Node *n) {
+ String *acc_str = Getattr(n, "access");
+ String *methodattr;
+ if (acc_str == NIL) {
+ methodattr = NewString("modula3:method:public");
+ } else {
+ methodattr = NewStringf("modula3:method:%s", acc_str);
+ }
+ String *methods = getAttrString(parentNode(n), Char(methodattr));
+ Delete(methodattr);
+ return methods;
+ }
+
+ /* ----------------------------------------------------------------------
+ * classHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int classHandler(Node *n) {
+
+ File *f_proxy = NULL;
+ proxy_class_name = Copy(Getattr(n, "sym:name"));
+ //String *rawname = Getattr(n,"name");
+
+ if (proxy_flag) {
+ if (!addSymbol(proxy_class_name, n))
+ return SWIG_ERROR;
+
+ if (Cmp(proxy_class_name, m3raw_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, m3wrap_name) == 0) {
+ Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ String *filen = NewStringf("%s%s.m3", Swig_file_dirname(outfile), proxy_class_name);
+ f_proxy = NewFile(filen, "w", SWIG_output_files());
+ if (!f_proxy) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(filen);
+ filen = NULL;
+
+ emitBanner(f_proxy);
+
+ Clear(proxy_class_def);
+ Clear(proxy_class_code);
+
+ have_default_constructor_flag = false;
+ destructor_call = NewString("");
+ }
+
+ /* This will invoke memberfunctionHandler, membervariableHandler ...
+ and finally it may invoke functionWrapper
+ for wrappers and member variable accessors.
+ It will invoke Language:constructorDeclaration
+ which decides whether to call MODULA3::constructorHandler */
+ Language::classHandler(n);
+
+ {
+ String *kind = Getattr(n, "kind");
+ if (Cmp(kind, "struct") == 0) {
+ String *entries = NewString("");
+ Node *child;
+ writeArgState state;
+ for (child = firstChild(n); child != NIL; child = nextSibling(child)) {
+ String *childType = nodeType(child);
+ if (Strcmp(childType, "cdecl") == 0) {
+ String *member = Getattr(child, "sym:name");
+ ParmList *pl = Getattr(child, "parms");
+ if (pl == NIL) {
+ // Get the variable type in Modula 3 type equivalents
+ String *m3ct = getMappedTypeNew(child, "m3rawtype", "");
+
+ writeArg(entries, state, NIL, member, m3ct, NIL);
+ }
+ }
+ }
+ writeArg(entries, state, NIL, NIL, NIL, NIL);
+
+ m3raw_intf.enterBlock(blocktype);
+ Printf(m3raw_intf.f, "%s =\nRECORD\n%sEND;\n", proxy_class_name, entries);
+
+ Delete(entries);
+
+ } else if (Cmp(kind, "class") == 0) {
+ enum access_privilege { acc_public, acc_protected, acc_private };
+ int max_acc = acc_public;
+
+ const char *acc_name[3] = { "public", "protected", "private" };
+ String *methods[3];
+ int acc;
+ for (acc = acc_public; acc <= acc_private; acc++) {
+ String *methodattr = NewStringf("modula3:method:%s", acc_name[acc]);
+ methods[acc] = Getattr(n, methodattr);
+ Delete(methodattr);
+ max_acc = max_acc > acc ? max_acc : acc;
+ }
+
+ /* Determine the name of the base class */
+ String *baseclassname = NewString("");
+ {
+ List *baselist = Getattr(n, "bases");
+ if (baselist) {
+ /* Look for the first (principal?) base class -
+ Modula 3 does not support multiple inheritance */
+ Iterator base = First(baselist);
+ Append(baseclassname, Getattr(base.item, "sym:name"));
+ base = Next(base);
+ if (base.item != NIL) {
+ Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, input_file,
+ line_number,
+ "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Modula 3.\n",
+ proxy_class_name, Getattr(base.item, "name"));
+ }
+ }
+ }
+
+ /* the private class of the base class and only this
+ need a pointer to the C++ object */
+ bool need_private = !hasContent(baseclassname);
+ max_acc = need_private ? acc_private : max_acc;
+
+ /* Declare C++ object as abstract pointer in Modula 3 */
+ /* The revelation system does not allow us
+ to imitate the whole class hierarchy of the C++ library,
+ but at least we can distinguish between classes of different roots. */
+ if (hasContent(baseclassname)) {
+ m3raw_intf.enterBlock(blocktype);
+ Printf(m3raw_intf.f, "%s = %s;\n", proxy_class_name, baseclassname);
+ } else {
+ m3raw_intf.enterBlock(blocktype);
+ Printf(m3raw_intf.f, "%s <: ADDRESS;\n", proxy_class_name);
+ m3raw_impl.enterBlock(revelation);
+ Printf(m3raw_impl.f, "%s = UNTRACED BRANDED REF RECORD (*Dummy*) END;\n", proxy_class_name);
+ }
+
+ String *superclass;
+ m3wrap_intf.enterBlock(blocktype);
+ if (hasContent(methods[acc_public])) {
+ superclass = NewStringf("%sPublic", proxy_class_name);
+ } else if (hasContent(baseclassname)) {
+ superclass = Copy(baseclassname);
+ } else {
+ superclass = NewString("ROOT");
+ }
+ Printf(m3wrap_intf.f, "%s <: %s;\n", proxy_class_name, superclass);
+ Delete(superclass);
+
+ {
+ static const char *acc_m3suffix[] = { "Public", "Protected", "Private" };
+ int acc;
+ for (acc = acc_public; acc <= acc_private; acc++) {
+ bool process_private = (acc == acc_private) && need_private;
+ if (hasContent(methods[acc]) || process_private) {
+ String *subclass = NewStringf("%s%s", proxy_class_name, acc_m3suffix[acc]);
+ /*
+ m3wrap_intf.enterBlock(revelation);
+ Printf(m3wrap_intf.f, "%s <: %s;\n", proxy_class_name, subclass);
+ */
+ if (acc == max_acc) {
+ m3wrap_intf.enterBlock(revelation);
+ Printf(m3wrap_intf.f, "%s =\n", proxy_class_name);
+ } else {
+ m3wrap_intf.enterBlock(blocktype);
+ Printf(m3wrap_intf.f, "%s =\n", subclass);
+ }
+ Printf(m3wrap_intf.f, "%s BRANDED OBJECT\n", baseclassname);
+ if (process_private) {
+ Setattr(m3wrap_intf.import, m3raw_name, "");
+ Printf(m3wrap_intf.f, "cxxObj:%s.%s;\n", m3raw_name, proxy_class_name);
+ }
+ if (hasContent(methods[acc])) {
+ Printf(m3wrap_intf.f, "METHODS\n%s", methods[acc]);
+ }
+ if (acc == max_acc) {
+ String *overrides = Getattr(n, "modula3:override");
+ Printf(m3wrap_intf.f, "OVERRIDES\n%s", overrides);
+ }
+ Printf(m3wrap_intf.f, "END;\n");
+ Delete(baseclassname);
+ baseclassname = subclass;
+ }
+ }
+ }
+
+ Delete(methods[acc_public]);
+ Delete(methods[acc_protected]);
+ Delete(methods[acc_private]);
+
+ } else {
+ Swig_warning(WARN_MODULA3_TYPECONSTRUCTOR_UNKNOWN, input_file, line_number, "Unknown type constructor %s\n", kind);
+ }
+ }
+
+ if (proxy_flag) {
+
+ emitProxyClassDefAndCPPCasts(n);
+
+ Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
+
+ Printf(f_proxy, "}\n");
+ Close(f_proxy);
+ f_proxy = NULL;
+
+ Delete(proxy_class_name);
+ proxy_class_name = NULL;
+ Delete(destructor_call);
+ destructor_call = NULL;
+ }
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * memberfunctionHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int memberfunctionHandler(Node *n) {
+ //printf("begin memberfunctionHandler(%s)\n", Char(Getattr(n,"name")));
+ Setattr(n, "modula3:functype", "method");
+ Language::memberfunctionHandler(n);
+
+ {
+ /* Language::memberfunctionHandler will remove the mapped types
+ that emitM3Wrapper may attach */
+ ParmList *pl = Getattr(n, "parms");
+ Swig_typemap_attach_parms("m3wrapinmode", pl, NULL);
+ Swig_typemap_attach_parms("m3wrapinname", pl, NULL);
+ Swig_typemap_attach_parms("m3wrapintype", pl, NULL);
+ Swig_typemap_attach_parms("m3wrapindefault", pl, NULL);
+ attachParameterNames(n, "tmap:m3wrapinname", "autoname", "arg%d");
+ String *rettype = getMappedTypeNew(n, "m3wrapouttype", "");
+
+ String *methodname = Getattr(n, "sym:name");
+/*
+ if (methodname==NIL) {
+ methodname = Getattr(n,"name");
+ }
+*/
+ String *arguments = createM3Signature(n);
+ String *storage = Getattr(n, "storage");
+ String *overridden = Getattr(n, "override");
+ bool isVirtual = (storage != NIL) && (Strcmp(storage, "virtual") == 0);
+ bool isOverridden = (overridden != NIL)
+ && (Strcmp(overridden, "1") == 0);
+ if ((!isVirtual) || (!isOverridden)) {
+ {
+ String *methods = getMethodDeclarations(n);
+ Printf(methods, "%s(%s)%s%s;%s\n",
+ methodname, arguments,
+ hasContent(rettype) ? ": " : "", hasContent(rettype) ? (const String *) rettype : "", isVirtual ? " (* base method *)" : "");
+ }
+ {
+ /* this was attached by functionWrapper
+ invoked by Language::memberfunctionHandler */
+ String *fname = Getattr(n, "modula3:funcname");
+ String *overrides = getAttrString(parentNode(n), "modula3:override");
+ Printf(overrides, "%s := %s;\n", methodname, fname);
+ }
+ }
+ }
+
+ if (proxy_flag) {
+ String *overloaded_name = getOverloadedName(n);
+ String *intermediary_function_name = Swig_name_member(proxy_class_name, overloaded_name);
+ Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
+ Setattr(n, "imfuncname", intermediary_function_name);
+ proxyClassFunctionHandler(n);
+ Delete(overloaded_name);
+ }
+ //printf("end memberfunctionHandler(%s)\n", Char(Getattr(n,"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(proxy_class_name, 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 Modula 3 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 Modula 3 static functions.
+ * Two extra attributes in the Node must be available. These are "proxyfuncname" -
+ * the name of the Modula 3 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");
+ Hash *throws_hash = NewHash();
+ 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;
+
+ if (!proxy_flag)
+ 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("m3wraptype", l, NULL);
+ Swig_typemap_attach_parms("m3in", l, NULL);
+
+ /* Get return types */
+ if ((tm = getMappedTypeNew(n, "m3wraptype", ""))) {
+ substituteClassname(t, tm);
+ Printf(return_type, "%s", tm);
+ }
+
+ if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
+ // Properties
+ setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(Swig_name_member(proxy_class_name, variable_name)))
+ == 0);
+ }
+
+ /* Start generating the proxy function */
+ Printf(function_code, " %s ", Getattr(n, "feature:modula3:methodmodifiers"));
+ if (static_flag)
+ Printf(function_code, "static ");
+ if (Getattr(n, "override"))
+ Printf(function_code, "override ");
+ else if (checkAttribute(n, "storage", "virtual"))
+ Printf(function_code, "virtual ");
+
+ Printf(function_code, "%s %s(", return_type, proxy_function_name);
+
+ Printv(imcall, m3raw_name, ".", intermediary_function_name, "(", NIL);
+ if (!static_flag)
+ Printv(imcall, "swigCPtr", NIL);
+
+ 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("");
+
+ /* Get the Modula 3 parameter type */
+ if ((tm = getMappedType(p, "m3wraptype"))) {
+ substituteClassname(pt, tm);
+ Printf(param_type, "%s", tm);
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ String *arg = variable_wrapper_flag ? NewString("value") : makeParameterName(n,
+ p,
+ i);
+
+ // Use typemaps to transform type used in Modula 3 wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
+ if ((tm = getMappedType(p, "in"))) {
+ addThrows(throws_hash, "in", p);
+ substituteClassname(pt, tm);
+ Replaceall(tm, "$input", arg);
+ Printv(imcall, tm, NIL);
+ }
+
+ /* Add parameter to proxy function */
+ if (gencomma >= 2)
+ Printf(function_code, ", ");
+ gencomma = 2;
+ Printf(function_code, "%s %s", param_type, arg);
+
+ Delete(arg);
+ Delete(param_type);
+ }
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Printf(imcall, ")");
+ Printf(function_code, ")");
+
+ // Transform return type used in PInvoke function (in intermediary class) to type used in Modula 3 wrapper function (in proxy class)
+ if ((tm = getMappedTypeNew(n, "m3out", ""))) {
+ addThrows(throws_hash, "m3out", n);
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ substituteClassname(t, tm);
+ Replaceall(tm, "$imcall", imcall);
+ }
+
+ generateThrowsClause(throws_hash, function_code);
+ Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
+
+ if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
+ // Properties
+ if (setter_flag) {
+ // Setter method
+ if ((tm = getMappedTypeNew(n, "m3varin", ""))) {
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ substituteClassname(t, tm);
+ Replaceall(tm, "$imcall", imcall);
+ Printf(proxy_class_code, "%s", tm);
+ }
+ } else {
+ // Getter method
+ if ((tm = getMappedTypeNew(n, "m3varout", ""))) {
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ substituteClassname(t, tm);
+ Replaceall(tm, "$imcall", imcall);
+ Printf(proxy_class_code, "%s", tm);
+ }
+ }
+ } else {
+ // Normal function call
+ Printv(proxy_class_code, function_code, NIL);
+ }
+
+ Delete(function_code);
+ Delete(return_type);
+ Delete(imcall);
+ Delete(throws_hash);
+ }
+
+ /* ----------------------------------------------------------------------
+ * constructorHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int constructorHandler(Node *n) {
+ // this invokes functionWrapper
+ Language::constructorHandler(n);
+
+ if (proxy_flag) {
+ ParmList *l = Getattr(n, "parms");
+
+ Hash *throws_hash = NewHash();
+ String *overloaded_name = getOverloadedName(n);
+ String *imcall = NewString("");
+
+ Printf(proxy_class_code, " %s %s(", Getattr(n, "feature:modula3:methodmodifiers"), proxy_class_name);
+ Printv(imcall, " : this(", m3raw_name, ".", Swig_name_construct(overloaded_name), "(", NIL);
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("in", l, NULL);
+ Swig_typemap_attach_parms("m3wraptype", l, NULL);
+ Swig_typemap_attach_parms("m3in", l, NULL);
+
+ emit_mark_varargs(l);
+
+ int gencomma = 0;
+
+ String *tm;
+ Parm *p = l;
+ int i;
+
+ /* Output each parameter */
+ for (i = 0; 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 Modula 3 parameter type */
+ if ((tm = getMappedType(p, "m3wraptype"))) {
+ substituteClassname(pt, tm);
+ Printf(param_type, "%s", tm);
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ String *arg = makeParameterName(n, p, i);
+
+ // Use typemaps to transform type used in Modula 3 wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
+ if ((tm = getMappedType(p, "in"))) {
+ addThrows(throws_hash, "in", p);
+ substituteClassname(pt, tm);
+ Replaceall(tm, "$input", arg);
+ Printv(imcall, tm, NIL);
+ }
+
+ /* Add parameter to proxy function */
+ if (gencomma)
+ Printf(proxy_class_code, ", ");
+ Printf(proxy_class_code, "%s %s", param_type, arg);
+ gencomma = 1;
+
+ Delete(arg);
+ Delete(param_type);
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Printf(imcall, "), true)");
+
+ Printf(proxy_class_code, ")");
+ Printf(proxy_class_code, "%s", imcall);
+ generateThrowsClause(throws_hash, proxy_class_code);
+ Printf(proxy_class_code, " {\n");
+ Printf(proxy_class_code, " }\n\n");
+
+ if (!gencomma) // We must have a default constructor
+ have_default_constructor_flag = true;
+
+ Delete(overloaded_name);
+ Delete(imcall);
+ Delete(throws_hash);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * destructorHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int destructorHandler(Node *n) {
+ Language::destructorHandler(n);
+ String *symname = Getattr(n, "sym:name");
+
+ if (proxy_flag) {
+ Printv(destructor_call, m3raw_name, ".", Swig_name_destroy(symname), "(swigCPtr)", NIL);
+ }
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * membervariableHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int membervariableHandler(Node *n) {
+ //printf("begin membervariableHandler(%s)\n", Char(Getattr(n,"name")));
+ SwigType *t = Getattr(n, "type");
+ String *tm;
+
+ // Get the variable type
+ if ((tm = getMappedTypeNew(n, "m3wraptype", ""))) {
+ substituteClassname(t, tm);
+ }
+
+ variable_name = Getattr(n, "sym:name");
+ //printf("member variable: %s\n", Char(variable_name));
+
+ // Output the property's field declaration and accessor methods
+ Printf(proxy_class_code, " public %s %s {", tm, variable_name);
+
+ Setattr(n, "modula3:functype", "accessor");
+ wrapping_member_flag = true;
+ variable_wrapper_flag = true;
+ Language::membervariableHandler(n);
+ wrapping_member_flag = false;
+ variable_wrapper_flag = false;
+
+ Printf(proxy_class_code, "\n }\n\n");
+
+ {
+ String *methods = getMethodDeclarations(n);
+ String *overrides = getAttrString(parentNode(n), "modula3:override");
+ SwigType *type = Getattr(n, "type");
+ String *m3name = capitalizeFirst(variable_name);
+ //String *m3name = nameToModula3(variable_name,true);
+ if (!SwigType_isconst(type)) {
+ {
+ String *inmode = getMappedTypeNew(n, "m3wrapinmode", "", false);
+ String *intype = getMappedTypeNew(n, "m3wrapintype", "");
+ Printf(methods, "set%s(%s val:%s);\n", m3name, (inmode != NIL) ? (const String *) inmode : "", intype);
+ }
+ {
+ /* this was attached by functionWrapper
+ invoked by Language::memberfunctionHandler */
+ String *fname = Getattr(n, "modula3:setname");
+ Printf(overrides, "set%s := %s;\n", m3name, fname);
+ }
+ }
+ {
+ {
+ String *outtype = getMappedTypeNew(n, "m3wrapouttype", "");
+ Printf(methods, "get%s():%s;\n", m3name, outtype);
+ }
+ {
+ /* this was attached by functionWrapper
+ invoked by Language::memberfunctionHandler */
+ String *fname = Getattr(n, "modula3:getname");
+ Printf(overrides, "get%s := %s;\n", m3name, fname);
+ }
+ }
+ Delete(m3name);
+ }
+ //printf("end membervariableHandler(%s)\n", Char(Getattr(n,"name")));
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * staticmembervariableHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int staticmembervariableHandler(Node *n) {
+
+ bool static_const_member_flag = (Getattr(n, "value") == 0);
+ if (static_const_member_flag) {
+ SwigType *t = Getattr(n, "type");
+ String *tm;
+
+ // Get the variable type
+ if ((tm = getMappedTypeNew(n, "m3wraptype", ""))) {
+ substituteClassname(t, tm);
+ }
+ // Output the property's field declaration and accessor methods
+ Printf(proxy_class_code, " public static %s %s {", tm, Getattr(n, "sym:name"));
+ }
+
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ static_flag = true;
+ Language::staticmembervariableHandler(n);
+ wrapping_member_flag = false;
+ static_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) {
+ String *overloaded_name = Copy(Getattr(n, "sym:name"));
+
+ if (Getattr(n, "sym:overloaded")) {
+ Printv(overloaded_name, Getattr(n, "sym:overname"), NIL);
+ }
+
+ return overloaded_name;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * emitM3Wrapper()
+ * It is also used for set and get methods of global variables.
+ * ----------------------------------------------------------------------------- */
+
+ void emitM3Wrapper(Node *n, const String *func_name) {
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ Hash *throws_hash = NewHash();
+ int num_exceptions = 0;
+ int num_returns = 0;
+ String *rawcall = NewString("");
+ String *reccall = NewString("");
+ String *local_variables = NewString("");
+ String *local_constants = NewString("");
+ String *incheck = NewString("");
+ String *outcheck = NewString("");
+ String *setup = NewString("");
+ String *cleanup = NewString("");
+ String *outarg = NewString(""); /* don't mix up with 'autark' :-] */
+ String *storeout = NewString("");
+ String *result_name = NewString("");
+ String *return_variables = NewString("");
+ const char *result_return = "ret";
+ String *function_code = NewString("");
+ /*several names for the same function */
+ String *raw_name = Getattr(n, "name"); /*original C function name */
+ //String *func_name = Getattr(n,"sym:name"); /*final Modula3 name chosen by the user*/
+ bool setter_flag = false;
+ int multiretval = GetFlag(n, "feature:modula3:multiretval");
+
+ 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("m3wrapargvar", l, NULL);
+ Swig_typemap_attach_parms("m3wrapargconst", l, NULL);
+ Swig_typemap_attach_parms("m3wrapargraw", l, NULL);
+ Swig_typemap_attach_parms("m3wrapargdir", l, NULL);
+ Swig_typemap_attach_parms("m3wrapinmode", l, NULL);
+ Swig_typemap_attach_parms("m3wrapinname", l, NULL);
+ Swig_typemap_attach_parms("m3wrapintype", l, NULL);
+ Swig_typemap_attach_parms("m3wrapindefault", l, NULL);
+ Swig_typemap_attach_parms("m3wrapinconv", l, NULL);
+ Swig_typemap_attach_parms("m3wrapincheck", l, NULL);
+ Swig_typemap_attach_parms("m3wrapoutname", l, NULL);
+ Swig_typemap_attach_parms("m3wrapouttype", l, NULL);
+ Swig_typemap_attach_parms("m3wrapoutconv", l, NULL);
+ Swig_typemap_attach_parms("m3wrapoutcheck", l, NULL);
+
+ attachMappedType(n, "m3wrapretraw");
+ attachMappedType(n, "m3wrapretname");
+ attachMappedType(n, "m3wraprettype");
+ attachMappedType(n, "m3wrapretvar");
+ attachMappedType(n, "m3wrapretconv");
+ attachMappedType(n, "m3wrapretcheck");
+
+ Swig_typemap_attach_parms("m3wrapfreearg", l, NULL);
+
+/*
+ Swig_typemap_attach_parms("m3wrapargvar:throws", l, NULL);
+ Swig_typemap_attach_parms("m3wrapargraw:throws", l, NULL);
+ Swig_typemap_attach_parms("m3wrapinconv:throws", l, NULL);
+ Swig_typemap_attach_parms("m3wrapincheck:throws", l, NULL);
+ Swig_typemap_attach_parms("m3wrapoutconv:throws", l, NULL);
+ Swig_typemap_attach_parms("m3wrapoutcheck:throws", l, NULL);
+
+ attachMappedType(n, "m3wrapretvar:throws");
+ attachMappedType(n, "m3wrapretconv:throws");
+ attachMappedType(n, "m3wrapretcheck:throws");
+
+ Swig_typemap_attach_parms("m3wrapfreearg:throws", l, NULL);
+*/
+
+ /* Attach argument names to the parameter list */
+ /* should be a separate procedure making use of hashes */
+ attachParameterNames(n, "tmap:m3wrapinname", "autoname", "arg%d");
+
+ /* Get return types */
+ String *result_m3rawtype = Copy(getMappedTypeNew(n, "m3rawrettype", ""));
+ String *result_m3wraptype = Copy(getMappedTypeNew(n, "m3wraprettype", ""));
+ bool has_return_raw = hasContent(result_m3rawtype);
+ bool has_return_m3 = hasContent(result_m3wraptype);
+ if (has_return_m3) {
+ num_returns++;
+ //printf("%s: %s\n", Char(func_name),Char(result_m3wraptype));
+ }
+
+ String *arguments = createM3Signature(n);
+
+ /* Create local variables or RECORD fields for return values
+ and determine return type that might result from a converted VAR argument. */
+ {
+ writeArgState state;
+ if (multiretval && has_return_m3) {
+ writeArg(return_variables, state, NIL, NewString(result_return), result_m3wraptype, NIL);
+ }
+
+ Parm *p = skipIgnored(l, "m3wrapouttype");
+ while (p != NIL) {
+
+ String *arg = Getattr(p, "tmap:m3wrapoutname");
+ if (arg == NIL) {
+ arg = Getattr(p, "name");
+ }
+
+ String *tm = Getattr(p, "tmap:m3wrapouttype");
+ if (tm != NIL) {
+ if (isOutParam(p)) {
+ if (!multiretval) {
+ if (num_returns == 0) {
+ Printv(result_name, arg, NIL);
+ Clear(result_m3wraptype);
+ Printv(result_m3wraptype, tm, NIL);
+ } else {
+ Swig_warning(WARN_MODULA3_TYPEMAP_MULTIPLE_RETURN, input_file, line_number,
+ "Typemap m3wrapargdir set to 'out' for %s implies a RETURN value, but the routine %s has already one.\nUse %%multiretval feature.\n",
+ SwigType_str(Getattr(p, "type"), 0), raw_name);
+ }
+ }
+ num_returns++;
+ addImports(m3wrap_intf.import, "m3wrapouttype", p);
+ writeArg(return_variables, state, NIL, arg, tm, NIL);
+ }
+ p = skipIgnored(Getattr(p, "tmap:m3wrapouttype:next"), "m3wrapouttype");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ writeArg(return_variables, state, NIL, NIL, NIL, NIL);
+
+ if (multiretval) {
+ Printv(result_name, "result", NIL);
+ Printf(result_m3wraptype, "%sResult", func_name);
+ m3wrap_intf.enterBlock(blocktype);
+ Printf(m3wrap_intf.f, "%s =\nRECORD\n%sEND;\n", result_m3wraptype, return_variables);
+ Printf(local_variables, "%s: %s;\n", result_name, result_m3wraptype);
+ } else {
+ Append(local_variables, return_variables);
+ }
+ }
+
+ /* Declare local constants e.g. for storing argument names. */
+ {
+ Parm *p = l;
+ while (p != NIL) {
+
+ String *arg = Getattr(p, "autoname");
+
+ String *tm = Getattr(p, "tmap:m3wrapargconst");
+ if (tm != NIL) {
+ addImports(m3wrap_impl.import, "m3wrapargconst", p);
+ Replaceall(tm, "$input", arg);
+ Printv(local_constants, tm, "\n", NIL);
+ p = Getattr(p, "tmap:m3wrapargconst:next");
+ } else {
+ p = nextSibling(p);
+ }
+
+ }
+ }
+
+ /* Declare local variables e.g. for converted input values. */
+ {
+ String *tm = getMappedTypeNew(n, "m3wrapretvar", "", false);
+ if (tm != NIL) {
+ addImports(m3wrap_impl.import, "m3wrapretvar", n);
+ addThrows(throws_hash, "m3wrapretvar", n);
+ Printv(local_variables, tm, "\n", NIL);
+ }
+
+ Parm *p = l;
+ while (p != NIL) {
+
+ String *arg = Getattr(p, "autoname");
+
+ tm = Getattr(p, "tmap:m3wrapargvar");
+ if (tm != NIL) {
+ /* exceptions that may be raised but can't be catched,
+ thus we won't count them in num_exceptions */
+ addImports(m3wrap_impl.import, "m3wrapargvar", p);
+ addThrows(throws_hash, "m3wrapargvar", p);
+ Replaceall(tm, "$input", arg);
+ Printv(local_variables, tm, "\n", NIL);
+ p = Getattr(p, "tmap:m3wrapargvar:next");
+ } else {
+ p = nextSibling(p);
+ }
+
+ }
+ }
+
+ /* Convert input values from Modula 3 to C. */
+ {
+ Parm *p = l;
+ while (p != NIL) {
+
+ String *arg = Getattr(p, "autoname");
+
+ String *tm = Getattr(p, "tmap:m3wrapinconv");
+ if (tm != NIL) {
+ addImports(m3wrap_impl.import, "m3wrapinconv", p);
+ num_exceptions += addThrows(throws_hash, "m3wrapinconv", p);
+ Replaceall(tm, "$input", arg);
+ Printv(setup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:m3wrapinconv:next");
+ } else {
+ p = nextSibling(p);
+ }
+
+ }
+ }
+
+ /* Generate checks for input value integrity. */
+ {
+ Parm *p = l;
+ while (p != NIL) {
+
+ String *arg = Getattr(p, "autoname");
+
+ String *tm = Getattr(p, "tmap:m3wrapincheck");
+ if (tm != NIL) {
+ addImports(m3wrap_impl.import, "m3wrapincheck", p);
+ num_exceptions += addThrows(throws_hash, "m3wrapincheck", p);
+ Replaceall(tm, "$input", arg);
+ Printv(incheck, tm, "\n", NIL);
+ p = Getattr(p, "tmap:m3wrapincheck:next");
+ } else {
+ p = nextSibling(p);
+ }
+
+ }
+ }
+
+ Printv(rawcall, m3raw_name, ".", func_name, "(", NIL);
+ /* Arguments to the raw C function */
+ {
+ bool gencomma = false;
+ Parm *p = l;
+ while (p != NIL) {
+ if (gencomma) {
+ Printf(rawcall, ", ");
+ }
+ gencomma = true;
+ addImports(m3wrap_impl.import, "m3wrapargraw", p);
+ num_exceptions += addThrows(throws_hash, "m3wrapargraw", p);
+
+ String *arg = Getattr(p, "autoname");
+ String *qualarg = NewString("");
+ if (!isInParam(p)) {
+ String *tmparg = Getattr(p, "tmap:m3wrapoutname");
+ if (tmparg != NIL) {
+ arg = tmparg;
+ }
+ if (multiretval /*&& isOutParam(p) - automatically fulfilled */ ) {
+ Printf(qualarg, "%s.", result_name);
+ }
+ }
+ Append(qualarg, arg);
+ Setattr(p, "m3outarg", qualarg);
+
+ String *tm = Getattr(p, "tmap:m3wrapargraw");
+ if (tm != NIL) {
+ Replaceall(tm, "$input", arg);
+ Replaceall(tm, "$output", qualarg);
+ Printv(rawcall, tm, NIL);
+ p = Getattr(p, "tmap:m3wrapargraw:next");
+ } else {
+ //Printv(rawcall, Getattr(p,"lname"), NIL);
+ Printv(rawcall, qualarg, NIL);
+ p = nextSibling(p);
+ }
+ Delete(qualarg);
+ }
+ }
+ Printf(rawcall, ")");
+
+ /* Check for error codes and integrity of results */
+ {
+ String *tm = getMappedTypeNew(n, "m3wrapretcheck", "", false);
+ if (tm != NIL) {
+ addImports(m3wrap_impl.import, "m3wrapretcheck", n);
+ num_exceptions += addThrows(throws_hash, "m3wrapretcheck", n);
+ Printv(outcheck, tm, "\n", NIL);
+ }
+
+ Parm *p = l;
+ while (p != NIL) {
+ tm = Getattr(p, "tmap:m3wrapoutcheck");
+ if (tm != NIL) {
+ String *arg = Getattr(p, "autoname");
+ String *outarg = Getattr(p, "m3outarg");
+ addImports(m3wrap_impl.import, "m3wrapoutcheck", p);
+ num_exceptions += addThrows(throws_hash, "m3wrapoutcheck", p);
+ //substituteClassname(Getattr(p,"type"), tm);
+ Replaceall(tm, "$input", arg);
+ Replaceall(tm, "$output", outarg);
+ Printv(outcheck, tm, "\n", NIL);
+ p = Getattr(p, "tmap:m3wrapoutcheck:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ /* Convert the results to Modula 3 data structures and
+ put them in the record prepared for returning */
+ {
+ /* m3wrapretconv is processed
+ when it is clear if there is some output conversion and checking code */
+ Parm *p = l;
+ while (p != NIL) {
+ String *tm = Getattr(p, "tmap:m3wrapoutconv");
+ if (tm != NIL) {
+ String *arg = Getattr(p, "autoname");
+ String *outarg = Getattr(p, "m3outarg");
+ addImports(m3wrap_impl.import, "m3wrapoutconv", n);
+ num_exceptions += addThrows(throws_hash, "m3wrapoutconv", p);
+ //substituteClassname(Getattr(p,"type"), tm);
+ Replaceall(tm, "$input", arg);
+ Replaceall(tm, "$output", outarg);
+ Printf(storeout, "%s := %s;\n", outarg, tm);
+ p = Getattr(p, "tmap:m3wrapoutconv:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ /* Generate cleanup code */
+ {
+ Parm *p = l;
+ while (p != NIL) {
+ String *tm = Getattr(p, "tmap:m3wrapfreearg");
+ if (tm != NIL) {
+ String *arg = Getattr(p, "autoname");
+ String *outarg = Getattr(p, "m3outarg");
+ addImports(m3wrap_impl.import, "m3wrapfreearg", p);
+ num_exceptions += addThrows(throws_hash, "m3wrapfreearg", p);
+ //substituteClassname(Getattr(p,"type"), tm);
+ Replaceall(tm, "$input", arg);
+ Replaceall(tm, "$output", outarg);
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:m3wrapfreearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ {
+ /* Currently I don't know how a typemap similar to the original 'out' typemap
+ could help returning the return value. */
+ /* Receive result from call to raw library function */
+ if (!has_return_raw) {
+ /*
+ rawcall(arg1);
+ result.val := arg1;
+ RETURN result;
+ */
+ /*
+ rawcall(arg1);
+ RETURN arg1;
+ */
+ Printf(reccall, "%s;\n", rawcall);
+
+ if (hasContent(result_name)) {
+ Printf(outarg, "RETURN %s;\n", result_name);
+ }
+ } else {
+ /*
+ arg0 := rawcall(arg1);
+ result.ret := Convert(arg0);
+ result.val := arg1;
+ RETURN result;
+ */
+ /*
+ arg0 := rawcall();
+ RETURN Convert(arg0);
+ */
+ /*
+ RETURN rawcall();
+ */
+ String *return_raw = getMappedTypeNew(n, "m3wrapretraw", "", false);
+ String *return_conv = getMappedTypeNew(n, "m3wrapretconv", "", false);
+
+ /* immediate RETURN would skip result checking */
+ if ((hasContent(outcheck) || hasContent(storeout)
+ || hasContent(cleanup)) && (!hasContent(result_name))
+ && (return_raw == NIL)) {
+ Printv(result_name, "result", NIL);
+ Printf(local_variables, "%s: %s;\n", result_name, result_m3wraptype);
+ }
+
+ String *result_lvalue = Copy(result_name);
+ if (multiretval) {
+ Printf(result_lvalue, ".%s", result_return);
+ }
+ if (return_raw != NIL) {
+ Printf(reccall, "%s := %s;\n", return_raw, rawcall);
+ } else if (hasContent(result_name)) {
+ Printf(reccall, "%s := %s;\n", result_lvalue, rawcall);
+ } else {
+ Printf(outarg, "RETURN %s;\n", rawcall);
+ }
+ if (return_conv != NIL) {
+ addImports(m3wrap_impl.import, "m3wrapretconv", n);
+ num_exceptions += addThrows(throws_hash, "m3wrapretconv", n);
+ if (hasContent(result_name)) {
+ Printf(reccall, "%s := %s;\n", result_lvalue, return_conv);
+ Printf(outarg, "RETURN %s;\n", result_name);
+ } else {
+ Printf(outarg, "RETURN %s;\n", return_conv);
+ }
+ } else {
+ if (hasContent(result_name)) {
+ Printf(outarg, "RETURN %s;\n", result_name);
+ }
+ }
+ }
+ }
+
+ /* Create procedure header */
+ {
+ String *header = NewStringf("PROCEDURE %s (%s)",
+ func_name, arguments);
+
+ if ((num_returns > 0) || multiretval) {
+ Printf(header, ": %s", result_m3wraptype);
+ }
+ generateThrowsClause(throws_hash, header);
+
+ Append(function_code, header);
+
+ m3wrap_intf.enterBlock(no_block);
+ Printf(m3wrap_intf.f, "%s;\n\n", header);
+ }
+
+ {
+ String *body = NewStringf("%s%s%s%s%s",
+ incheck,
+ setup,
+ reccall,
+ outcheck,
+ storeout);
+
+ String *exc_handler;
+ if (hasContent(cleanup) && (num_exceptions > 0)) {
+ exc_handler = NewStringf("TRY\n%sFINALLY\n%sEND;\n", body, cleanup);
+ } else {
+ exc_handler = NewStringf("%s%s", body, cleanup);
+ }
+
+ Printf(function_code, " =\n%s%s%s%sBEGIN\n%s%sEND %s;\n\n",
+ hasContent(local_constants) ? "CONST\n" : "", local_constants,
+ hasContent(local_variables) ? "VAR\n" : "", local_variables, exc_handler, outarg, func_name);
+
+ Delete(exc_handler);
+ Delete(body);
+ }
+
+ m3wrap_impl.enterBlock(no_block);
+ if (proxy_flag && global_variable_flag) {
+ // Properties
+ if (setter_flag) {
+ // Setter method
+ String *tm = getMappedTypeNew(n, "m3varin", "");
+ if (tm != NIL) {
+ if (GetFlag(n, "feature:new")) {
+ Replaceall(tm, "$owner", "true");
+ } else {
+ Replaceall(tm, "$owner", "false");
+ }
+ substituteClassname(t, tm);
+ Replaceall(tm, "$rawcall", rawcall);
+ Replaceall(tm, "$vartype", variable_type); /* $type is already replaced by some super class */
+ Replaceall(tm, "$var", variable_name);
+ Printf(m3wrap_impl.f, "%s", tm);
+ }
+ } else {
+ // Getter method
+ String *tm = getMappedTypeNew(n, "m3varout", "");
+ if (tm != NIL) {
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ substituteClassname(t, tm);
+ Replaceall(tm, "$rawcall", rawcall);
+ Replaceall(tm, "$vartype", variable_type);
+ Replaceall(tm, "$var", variable_name);
+ Printf(m3wrap_impl.f, "%s", tm);
+ }
+ }
+ } else {
+ // Normal function call
+ Printv(m3wrap_impl.f, function_code, NIL);
+ }
+
+ Delete(arguments);
+ Delete(return_variables);
+ Delete(local_variables);
+ Delete(local_constants);
+ Delete(outarg);
+ Delete(incheck);
+ Delete(outcheck);
+ Delete(setup);
+ Delete(cleanup);
+ Delete(storeout);
+ Delete(function_code);
+ Delete(result_name);
+ Delete(result_m3wraptype);
+ Delete(reccall);
+ Delete(rawcall);
+ Delete(throws_hash);
+ }
+
+ /*----------------------------------------------------------------------
+ * replaceSpecialVariables()
+ *--------------------------------------------------------------------*/
+
+ virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
+ (void)method;
+ SwigType *type = Getattr(parm, "type");
+ substituteClassname(type, tm);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substituteClassname()
+ *
+ * Substitute the special variable $m3classname with the proxy class name for classes/structs/unions
+ * that SWIG knows about.
+ * Otherwise use the $descriptor name for the Modula 3 class name. Note that the $&m3classname 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;
+ if (Strstr(tm, "$m3classname") || Strstr(tm, "$&m3classname")) {
+ String *classname = getProxyName(pt);
+ if (classname) {
+ Replaceall(tm, "$&m3classname", classname); // getProxyName() works for pointers to classes too
+ Replaceall(tm, "$m3classname", classname);
+ } else { // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
+ String *descriptor = NULL;
+ SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
+
+ if (Strstr(tm, "$&m3classname")) {
+ SwigType_add_pointer(type);
+ descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(type));
+ Replaceall(tm, "$&m3classname", descriptor);
+ } else { // $m3classname
+ descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(type));
+ Replaceall(tm, "$m3classname", descriptor);
+ }
+
+ // Add to hash table so that the type wrapper classes can be created later
+ Setattr(swig_types_hash, descriptor, type);
+ Delete(descriptor);
+ Delete(type);
+ }
+ substitution_performed = true;
+ }
+ return substitution_performed;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * makeParameterName()
+ *
+ * Inputs:
+ * n - Node
+ * p - parameter node
+ * arg_num - parameter argument number
+ * Return:
+ * arg - a unique parameter name
+ * ----------------------------------------------------------------------------- */
+
+ String *makeParameterName(Node *n, Parm *p, int arg_num) {
+
+ // Use C parameter name unless it is a duplicate or an empty parameter name
+ String *pn = Getattr(p, "name");
+ int count = 0;
+ ParmList *plist = Getattr(n, "parms");
+ while (plist) {
+ if ((Cmp(pn, Getattr(plist, "name")) == 0))
+ count++;
+ plist = nextSibling(plist);
+ }
+ String *arg = (!pn || (count > 1)) ? NewStringf("arg%d",
+ arg_num) : Copy(Getattr(p,
+ "name"));
+
+ return arg;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * attachParameterNames()
+ *
+ * Inputs:
+ * n - Node of a function declaration
+ * tmid - attribute name for overriding C argument names,
+ * e.g. "tmap:m3wrapinname",
+ * don't forget to attach the mapped types before
+ * nameid - attribute for attaching the names,
+ * e.g. "modula3:inname"
+ * fmt - format for the argument name containing %d
+ * e.g. "arg%d"
+ * ----------------------------------------------------------------------------- */
+
+ void attachParameterNames(Node *n, const char *tmid, const char *nameid, const char *fmt) {
+ /* Use C parameter name if present and unique,
+ otherwise create an 'arg%d' name */
+ Hash *hash = NewHash();
+ Parm *p = Getattr(n, "parms");
+ int count = 0;
+ while (p != NIL) {
+ String *name = Getattr(p, tmid);
+ if (name == NIL) {
+ name = Getattr(p, "name");
+ }
+ String *newname;
+ if ((!hasContent(name)) || (Getattr(hash, name) != NIL)) {
+ newname = NewStringf(fmt, count);
+ } else {
+ newname = Copy(name);
+ }
+ if (1 == Setattr(hash, newname, "1")) {
+ Swig_warning(WARN_MODULA3_DOUBLE_ID, input_file, line_number, "Argument '%s' twice.\n", newname);
+ }
+ Setattr(p, nameid, newname);
+// Delete(newname);
+ p = nextSibling(p);
+ count++;
+ }
+ Delete(hash);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * createM3Signature()
+ *
+ * Create signature of M3 wrapper procedure
+ * Call attachParameterNames and attach mapped types before!
+ * m3wrapintype, m3wrapinmode, m3wrapindefault
+ * ----------------------------------------------------------------------------- */
+
+ String *createM3Signature(Node *n) {
+ String *arguments = NewString("");
+ Parm *p = skipIgnored(Getattr(n, "parms"), "m3wrapintype");
+ writeArgState state;
+ while (p != NIL) {
+
+ /* Get the M3 parameter type */
+ String *tm = getMappedType(p, "m3wrapintype");
+ if (tm != NIL) {
+ if (isInParam(p)) {
+ addImports(m3wrap_intf.import, "m3wrapintype", p);
+ addImports(m3wrap_impl.import, "m3wrapintype", p);
+ String *mode = Getattr(p, "tmap:m3wrapinmode");
+ String *deflt = Getattr(p, "tmap:m3wrapindefault");
+ String *arg = Getattr(p, "autoname");
+ SwigType *pt = Getattr(p, "type");
+ substituteClassname(pt, tm); /* do we need this ? */
+
+ writeArg(arguments, state, mode, arg, tm, deflt);
+ }
+ p = skipIgnored(Getattr(p, "tmap:m3wrapintype:next"), "m3wrapintype");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ writeArg(arguments, state, NIL, NIL, NIL, NIL);
+ return (arguments);
+ }
+
+/* not used any longer
+ - try SwigType_str if required again */
+#if 0
+ /* -----------------------------------------------------------------------------
+ * createCSignature()
+ *
+ * Create signature of C function
+ * ----------------------------------------------------------------------------- */
+
+ String *createCSignature(Node *n) {
+ String *arguments = NewString("");
+ bool gencomma = false;
+ Node *p;
+ for (p = Getattr(n, "parms"); p != NIL; p = nextSibling(p)) {
+ if (gencomma) {
+ Append(arguments, ",");
+ }
+ gencomma = true;
+ String *type = Getattr(p, "type");
+ String *ctype = getMappedTypeNew(type, "ctype");
+ Append(arguments, ctype);
+ }
+ return arguments;
+ }
+#endif
+
+ /* -----------------------------------------------------------------------------
+ * emitTypeWrapperClass()
+ * ----------------------------------------------------------------------------- */
+
+ void emitTypeWrapperClass(String *classname, SwigType *type) {
+ Node *n = NewHash();
+ Setfile(n, input_file);
+ Setline(n, line_number);
+
+ String *filen = NewStringf("%s%s.m3", Swig_file_dirname(outfile), classname);
+ File *f_swigtype = NewFile(filen, "w", SWIG_output_files());
+ if (!f_swigtype) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ String *swigtype = NewString("");
+
+ // Emit banner name
+ emitBanner(f_swigtype);
+
+ // Pure Modula 3 baseclass and interfaces
+ const String *pure_baseclass = typemapLookup(n, "m3base", type, WARN_NONE);
+ const String *pure_interfaces = typemapLookup(n, "m3interfaces", type, WARN_NONE);
+
+ // Emit the class
+ Printv(swigtype, typemapLookup(n, "m3imports", type, WARN_NONE), // Import statements
+ "\n", typemapLookup(n, "m3classmodifiers", type, WARN_MODULA3_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
+ " class $m3classname", // Class name and bases
+ *Char(pure_baseclass) ? " : " : "", pure_baseclass, *Char(pure_interfaces) ? // Interfaces
+ " : " : "", pure_interfaces, " {\n", " private IntPtr swigCPtr;\n", "\n", " ", typemapLookup(n, "m3ptrconstructormodifiers", type, WARN_MODULA3_TYPEMAP_PTRCONSTMOD_UNDEF), // pointer constructor modifiers
+ " $m3classname(IntPtr cPtr, bool bFutureUse) {\n", // Constructor used for wrapping pointers
+ " swigCPtr = cPtr;\n", " }\n", "\n", " protected $m3classname() {\n", // Default constructor
+ " swigCPtr = IntPtr.Zero;\n", " }\n", typemapLookup(n, "m3getcptr", type, WARN_MODULA3_TYPEMAP_GETCPTR_UNDEF), // getCPtr method
+ typemapLookup(n, "m3code", type, WARN_NONE), // extra Modula 3 code
+ "}\n", "\n", NIL);
+
+ Replaceall(swigtype, "$m3classname", classname);
+ Printv(f_swigtype, swigtype, NIL);
+
+ Close(f_swigtype);
+ Delete(filen);
+ Delete(swigtype);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * 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()
+ *
+ * Add all exceptions to a hash that are associated with the 'typemap'.
+ * Return number the number of these exceptions.
+ * ----------------------------------------------------------------------------- */
+
+ int addThrows(Hash *throws_hash, const String *typemap, Node *parameter) {
+ // Get the comma separated throws clause - held in "throws" attribute in the typemap passed in
+ int len = 0;
+ String *throws_attribute = NewStringf("%s:throws", typemap);
+
+ addImports(m3wrap_intf.import, throws_attribute, parameter);
+ addImports(m3wrap_impl.import, throws_attribute, parameter);
+
+ String *throws = getMappedTypeNew(parameter, Char(throws_attribute), "", false);
+ //printf("got exceptions %s for %s\n", Char(throws), Char(throws_attribute));
+
+ if (throws) {
+ // Put the exception classes in the throws clause into a temporary List
+ List *temp_classes_list = Split(throws, ',', INT_MAX);
+ len = Len(temp_classes_list);
+
+ // Add the exception classes to the node throws list, but don't duplicate if already in list
+ if (temp_classes_list /*&& hasContent(temp_classes_list) */ ) {
+ for (Iterator cls = First(temp_classes_list); cls.item != NIL; cls = Next(cls)) {
+ String *exception_class = NewString(cls.item);
+ Replaceall(exception_class, " ", ""); // remove spaces
+ Replaceall(exception_class, "\t", ""); // remove tabs
+ if (hasContent(exception_class)) {
+ // $m3classname substitution
+ SwigType *pt = Getattr(parameter, "type");
+ substituteClassname(pt, exception_class);
+ // Don't duplicate the exception class in the throws clause
+ //printf("add exception %s\n", Char(exception_class));
+ Setattr(throws_hash, exception_class, "1");
+ }
+ Delete(exception_class);
+ }
+ }
+ Delete(temp_classes_list);
+ }
+ Delete(throws_attribute);
+ return len;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * generateThrowsClause()
+ * ----------------------------------------------------------------------------- */
+
+ void generateThrowsClause(Hash *throws_hash, String *code) {
+ // Add the throws clause into code
+ if (Len(throws_hash) > 0) {
+ Iterator cls = First(throws_hash);
+ Printf(code, " RAISES {%s", cls.key);
+ for (cls = Next(cls); cls.key != NIL; cls = Next(cls)) {
+ Printf(code, ", %s", cls.key);
+ }
+ Printf(code, "}");
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addImports()
+ *
+ * Add all imports that are needed for contents of 'typemap'.
+ * ----------------------------------------------------------------------------- */
+
+ void addImports(Hash *imports_hash, const String *typemap, Node *node) {
+ // Get the comma separated throws clause - held in "throws" attribute in the typemap passed in
+ String *imports_attribute = NewStringf("%s:import", typemap);
+ String *imports = getMappedTypeNew(node, Char(imports_attribute), "", false);
+ //printf("got imports %s for %s\n", Char(imports), Char(imports_attribute));
+
+ if (imports != NIL) {
+ List *import_list = Split(imports, ',', INT_MAX);
+
+ // Add the exception classes to the node imports list, but don't duplicate if already in list
+ if (import_list != NIL) {
+ for (Iterator imp = First(import_list); imp.item != NIL; imp = Next(imp)) {
+ List *import_pair = Split(imp.item, ' ', 3);
+ if (Len(import_pair) == 1) {
+ Setattr(imports_hash, Getitem(import_pair, 0), "");
+ } else if ((Len(import_pair) == 3)
+ && Strcmp(Getitem(import_pair, 1), "AS") == 0) {
+ Setattr(imports_hash, Getitem(import_pair, 0), Getitem(import_pair, 2));
+ } else {
+ Swig_warning(WARN_MODULA3_BAD_IMPORT, input_file, line_number,
+ "Malformed import '%s' for typemap '%s' defined for type '%s'\n", imp, typemap, SwigType_str(Getattr(node, "type"), 0));
+ }
+ Delete(import_pair);
+ }
+ }
+ Delete(import_list);
+ }
+ Delete(imports_attribute);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * emitImportStatements()
+ * ----------------------------------------------------------------------------- */
+
+ void emitImportStatements(Hash *imports_hash, String *code) {
+ // Add the imports statements into code
+ Iterator imp = First(imports_hash);
+ while (imp.key != NIL) {
+ Printf(code, "IMPORT %s", imp.key);
+ String *imp_as = imp.item;
+ if (hasContent(imp_as)) {
+ Printf(code, " AS %s", imp_as);
+ }
+ Printf(code, ";\n");
+ imp = Next(imp);
+ }
+ }
+
+}; /* class MODULA3 */
+
+/* -----------------------------------------------------------------------------
+ * swig_modula3() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+extern "C" Language *swig_modula3(void) {
+ return new MODULA3();
+}
+
+/* -----------------------------------------------------------------------------
+ * Static member variables
+ * ----------------------------------------------------------------------------- */
+
+const char *MODULA3::usage = (char *) "\
+Modula 3 Options (available with -modula3)\n\
+ -generateconst <file> - generate code for computing numeric values of constants\n\
+ -generaterename <file> - generate suggestions for %rename\n\
+ -generatetypemap <file> - generate templates for some basic typemaps\n\
+ -oldvarnames - old intermediary method names for variable wrappers\n\
+\n";
+
+/*
+ -generateconst <file> - stem of the .c source file for computing the numeric values of constants\n\
+ -generaterename <file> - stem of the .i source file containing %rename suggestions\n\
+ -generatetypemap <file> - stem of the .i source file containing typemap patterns\n\
+*/
diff --git a/Source/Modules/module.cxx b/Source/Modules/module.cxx
new file mode 100644
index 0000000..bd82b9e
--- /dev/null
+++ b/Source/Modules/module.cxx
@@ -0,0 +1,57 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * module.cxx
+ *
+ * This file is responsible for the module system.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_module_cxx[] = "$Id: module.cxx 10003 2007-10-17 21:42:11Z wsfulton $";
+
+#include "swigmod.h"
+
+struct Module {
+ ModuleFactory fac;
+ char *name;
+ Module *next;
+ Module(const char *n, ModuleFactory f) {
+ fac = f;
+ name = new char[strlen(n) + 1];
+ strcpy(name, n);
+ next = 0;
+ } ~Module() {
+ delete[]name;
+ }
+};
+
+static Module *modules = 0;
+
+/* -----------------------------------------------------------------------------
+ * void Swig_register_module()
+ *
+ * Register a module.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_register_module(const char *n, ModuleFactory f) {
+ Module *m = new Module(n, f);
+ m->next = modules;
+ modules = m;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language *Swig_find_module()
+ *
+ * Given a command line option, locates the factory function.
+ * ----------------------------------------------------------------------------- */
+
+ModuleFactory Swig_find_module(const char *name) {
+ Module *m = modules;
+ while (m) {
+ if (strcmp(m->name, name) == 0) {
+ return m->fac;
+ }
+ m = m->next;
+ }
+ return 0;
+}
diff --git a/Source/Modules/mzscheme.cxx b/Source/Modules/mzscheme.cxx
new file mode 100644
index 0000000..a40f00d
--- /dev/null
+++ b/Source/Modules/mzscheme.cxx
@@ -0,0 +1,834 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * mzscheme.cxx
+ *
+ * Mzscheme language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_mzscheme_cxx[] = "$Id: mzscheme.cxx 11133 2009-02-20 07:52:24Z wsfulton $";
+
+#include "swigmod.h"
+
+#include <ctype.h>
+
+static const char *usage = (char *) "\
+Mzscheme Options (available with -mzscheme)\n\
+ -prefix <name> - Set a prefix <name> to be prepended to all names\n\
+ -declaremodule - Create extension that declares a module\n\
+ -noinit - Do not emit scheme_initialize, scheme_reload,\n\
+ scheme_module_name functions\n\
+ -dynamic-load <library>,[library,...] - Do not link with these libraries, dynamic load\n\
+ them\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 char *prefix = 0;
+static bool declaremodule = false;
+static bool noinit = false;
+//DLOPEN PATCH
+static char *load_libraries = NULL;
+//DLOPEN PATCH
+static String *module = 0;
+static char *mzscheme_path = (char *) "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 = new char[strlen(argv[i + 1]) + 2];
+ strcpy(prefix, 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);
+ }
+// DLOPEN PATCH
+ else if (strcmp(argv[i], "-dynamic-load") == 0) {
+ load_libraries = new char[strlen(argv[i + 1]) + 2];
+ strcpy(load_libraries, argv[i + 1]);
+ Swig_mark_arg(i++);
+ Swig_mark_arg(i);
+ }
+// DLOPEN PATCH
+ }
+ }
+
+ // If a prefix has been specified make sure it ends in a '_'
+
+ if (prefix) {
+ if (prefix[strlen(prefix)] != '_') {
+ prefix[strlen(prefix) + 1] = 0;
+ prefix[strlen(prefix)] = '_';
+ }
+ } else
+ prefix = (char *) "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");
+ Printf(f_runtime, "#define SWIGMZSCHEME\n");
+ Printf(f_runtime, "\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");
+
+ // DLOPEN PATCH
+ if (load_libraries) {
+ Printf(f_init, "mz_set_dlopen_libraries(\"%s\");\n", load_libraries);
+ }
+ // DLOPEN PATCH
+
+ 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);
+ Close(f_begin);
+ 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 *source = NewString("");
+ String *target = NewString("");
+ String *arg = NewString("");
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ String *build = NewString("");
+ String *tm;
+ int argout_set = 0;
+ int i = 0;
+ int numargs;
+ int numreq;
+ String *overname = 0;
+
+ // PATCH DLOPEN
+ if (load_libraries) {
+ ParmList *parms = Getattr(n, "parms");
+ SwigType *type = Getattr(n, "type");
+ String *name = NewString("caller");
+ Setattr(n, "wrap:action", Swig_cresult(type, "result", Swig_cfunction_call(name, parms)));
+ }
+ // PATCH DLOPEN
+
+ // 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);
+
+ // DLOPEN PATCH
+ /* 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)()")); */
+ }
+ }
+ // DLOPEN PATCH
+
+ // adds local variables
+ Wrapper_add_local(f, "lenv", "int lenv = 1");
+ Wrapper_add_local(f, "values", "Scheme_Object *values[MAXVALUES]");
+
+ // DLOPEN PATCH
+ 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");
+ }
+ // DLOPEN PATCH
+
+ // 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(source);
+ Clear(target);
+ Clear(arg);
+ Printf(source, "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");
+ }
+ }
+
+ /* 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");
+ argout_set = 1;
+ } 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, "result", f, actioncode))) {
+ Replaceall(tm, "$source", "result");
+ 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, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ Printv(f->code, tm, "\n", NIL);
+ }
+ }
+ // Free any memory allocated by the function being wrapped..
+
+ if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ 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);
+ } else {
+ 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);
+ 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(source);
+ 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]");
+ /* Printv(f->code, tm, "\n",NIL); */
+ 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));
+ if ((SwigType_type(type) == T_STRING)) {
+ Printf(f_header, "\"%s\";\n", value);
+ } else if (SwigType_type(type) == T_CHAR) {
+ 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 *n = NewHash();
+ Setattr(n, "name", var_name);
+ Setattr(n, "sym:name", iname);
+ Setattr(n, "type", type);
+ SetFlag(n, "feature:immutable");
+ variableWrapper(n);
+ Delete(n);
+ }
+ }
+ 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", Getattr(n, "classtype"));
+
+ 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, ""), ")&((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;
+ }
+
+
+ /* ------------------------------------------------------------
+ * validIdentifer()
+ * ------------------------------------------------------------ */
+
+ 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/Source/Modules/ocaml.cxx b/Source/Modules/ocaml.cxx
new file mode 100644
index 0000000..5b0e78a
--- /dev/null
+++ b/Source/Modules/ocaml.cxx
@@ -0,0 +1,1866 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * ocaml.cxx
+ *
+ * Ocaml language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_ocaml_cxx[] = "$Id: ocaml.cxx 11246 2009-06-05 17:19:29Z wsfulton $";
+
+#include "swigmod.h"
+
+#include <ctype.h>
+
+static const char *usage = (char *)
+ ("Ocaml Options (available with -ocaml)\n"
+ "-prefix <name> - Set a prefix <name> to be prepended to all names\n"
+ "-where - Emit library location\n"
+ "-suffix <name> - Change .cxx to something else\n" "-oldvarnames - old intermediary method names for variable wrappers\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 char *prefix = 0;
+static char *ocaml_path = (char *) "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 String *name_qualifier = 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", " 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 = new char[strlen(argv[i + 1]) + 2];
+ strcpy(prefix, 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]) {
+ 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 '_'
+
+ if (prefix) {
+ if (prefix[strlen(prefix)] != '_') {
+ prefix[strlen(prefix) + 1] = 0;
+ prefix[strlen(prefix)] = '_';
+ }
+ } else
+ prefix = (char *) "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;
+ }
+
+ /* ------------------------------------------------------------
+ * 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.
+ */
+ {
+ 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;
+ }
+ }
+ }
+ }
+
+ /* 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", "%v__set__");
+ Swig_name_register("get", "%v__get__");
+ }
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n");
+ Printf(f_runtime, "#define SWIGOCAML\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);
+ }
+
+ Language::top(n);
+
+ 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.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);
+ Close(f_begin);
+ 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);
+ Close(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);
+ Close(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));
+ }
+
+ /* ------------------------------------------------------------
+ * 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 *source = NewString("");
+ String *target = NewString("");
+ String *arg = NewString("");
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ String *build = NewString("");
+ String *tm;
+ int argout_set = 0;
+ 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;
+
+ // 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) { // 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) {
+ String *opname = Copy(Getattr(n, "memberfunctionHandler:sym:name"));
+
+ Replaceall(opname, "operator ", "");
+
+ if (strstr(Char(mangled_name), "__get__")) {
+ String *set_name = Copy(mangled_name);
+ if (!GetFlag(n, "feature:immutable")) {
+ Replaceall(set_name, "__get__", "__set__");
+ Printf(f_class_ctors, " \"%s\", (fun args -> " "if args = (C_list [ raw_ptr ]) then %s args else %s args) ;\n", opname, mangled_name, set_name);
+ Delete(set_name);
+ } else {
+ Printf(f_class_ctors, " \"%s\", (fun args -> " "if args = (C_list [ raw_ptr ]) then %s args else C_void) ;\n", opname, mangled_name);
+ }
+ } else if (strstr(Char(mangled_name), "__set__")) {
+ ; /* Nothing ... handled by the case above */
+ } else {
+ 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)");
+ Wrapper_add_local(f, "_v", "int _v = 0");
+ if (isOverloaded) {
+ Wrapper_add_local(f, "i", "int i");
+ Wrapper_add_local(f, "argc", "int argc = caml_list_length(args)");
+ Wrapper_add_local(f, "argv", "CAML_VALUE *argv");
+
+ Printv(f->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);
+ }
+ 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);
+
+ 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(source);
+ Clear(target);
+ Clear(arg);
+ Printf(source, "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");
+ }
+ }
+
+ /* 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");
+ argout_set = 1;
+ } 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 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");
+ 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, "result", 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, "result", 0))) {
+ Replaceall(tm, "$source", "swig_result");
+ Printv(f->code, tm, "\n", NIL);
+ }
+ }
+ // Free any memory allocated by the function being wrapped..
+
+ if ((tm = Swig_typemap_lookup("swig_result", n, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ 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);
+ if (isOverloaded)
+ Printv(f->code, "free(argv);\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, "_v", "int _v = 0");
+ 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, "\n", NIL);
+ Printf(df->code, "failwith(\"No matching function for overloaded '%s'\");\n", iname);
+ Printv(df->code, "}\n", NIL);
+ Wrapper_print(df, f_wrappers);
+
+ DelWrapper(df);
+ Delete(dispatch);
+ }
+ }
+
+ Printf(f_mlbody,
+ "external %s_f : c_obj list -> c_obj list = \"%s\" ;;\n"
+ "let %s arg = match %s_f (fnhelper arg) with\n"
+ " [] -> 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", mangled_name, wname, mangled_name, mangled_name, newobj ? "true" : "false");
+
+ if (!classmode || in_constructor || in_destructor || static_member_function)
+ Printf(f_mlibody, "val %s : c_obj -> c_obj\n", mangled_name);
+
+ Delete(proc_name);
+ Delete(source);
+ 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. In the set case we return C_void.
+ *
+ * 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;
+ String *tm2 = NewString("");;
+ String *argnum = NewString("0");
+ String *arg = NewString("SWIG_Field(args,0)");
+ 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 scheme.
+ 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, "swig_result", "CAML_VALUE swig_result");
+
+ 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");
+ /* Printv(f->code, tm, "\n",NIL); */
+ 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");
+ Printv(f->code, tm, "\n", NIL);
+ } 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");
+ Printf(f->code, "%s\n", tm);
+ } else {
+ throw_unhandled_ocaml_type_error(t, "varout/out");
+ }
+
+ Printf(f->code, "\nreturn 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);
+ Delete(argnum);
+ Delete(arg);
+ Delete(tm2);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * staticmemberfunctionHandler --
+ * Overridden to set static_member_function
+ * ------------------------------------------------------------ */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ int rv;
+ static_member_function = 1;
+ rv = 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 *value = Getattr(n, "value");
+ String *qvalue = Getattr(n, "qualified:value");
+ String *rvalue = NewString("");
+ String *temp = 0;
+
+ if (qvalue)
+ value = qvalue;
+
+ if (!name) {
+ name = mangleNameForCaml(Getattr(n, "name"));
+ Insert(name, 0, "_swig_wrap_");
+ Setattr(n, "feature:symname", name);
+ }
+ // 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);
+ Delete(temp);
+ }
+ if ((SwigType_type(type) == T_CHAR) && (is_a_pointer(type) == 0)) {
+ temp = Copy(rvalue);
+ Clear(rvalue);
+ Printv(rvalue, "'", temp, "'", NIL);
+ Delete(temp);
+ }
+ // Create variable and assign it a value
+
+ Printf(f_header, "static %s = ", SwigType_lstr(type, name));
+ if ((SwigType_type(type) == T_STRING)) {
+ Printf(f_header, "\"%s\";\n", value);
+ } else if (SwigType_type(type) == T_CHAR) {
+ Printf(f_header, "\'%s\';\n", value);
+ } else {
+ Printf(f_header, "%s;\n", 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 = 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, 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");
+
+ if (!name)
+ return SWIG_OK;
+
+ String *mangled_sym_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);
+
+
+ classname = mangled_sym_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_sym_name, name_normalized);
+
+ Printf(f_mlbody, "external __%s_sizeof : unit -> int = " "\"_wrap_%s_sizeof\"\n", classname, mangled_sym_name);
+ }
+
+
+ /* Insert sizeof operator for concrete classes */
+ if (sizeof_feature) {
+ Printv(f_class_ctors, "\"sizeof\" , (fun args -> C_int (__", classname, "_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", classname);
+ 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", classname);
+
+ 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;
+ }
+
+ String *fully_qualify_enum_name(Node *n, String *name) {
+ Node *parent = 0;
+ String *qualification = NewString("");
+ String *fully_qualified_name = NewString("");
+ String *parent_type = 0;
+ String *normalized_name;
+
+ 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") || !Cmp(parent_type, "namespace"))
+ Insert(qualification, 0, parent_copy);
+ Delete(parent_copy);
+ }
+ if (!Cmp(parent_type, "class"))
+ break;
+ parent = parentNode(parent);
+ }
+
+ Printf(fully_qualified_name, "%s%s", qualification, name);
+
+ normalized_name = normalizeTemplatedClassName(fully_qualified_name);
+ if (!strncmp(Char(normalized_name), "enum ", 5)) {
+ Insert(normalized_name, 5, qualification);
+ }
+
+ return normalized_name;
+ }
+
+ /* Benedikt Grundmann inspired --> Enum wrap styles */
+
+ int enumvalueDeclaration(Node *n) {
+ String *name = Getattr(n, "name");
+ String *qvalue = 0;
+
+ if (name_qualifier) {
+ qvalue = Copy(name_qualifier);
+ Printv(qvalue, name, NIL);
+ }
+
+ if (const_enum && 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
+
+ if (qvalue)
+ Setattr(n, "qualified:value", qvalue);
+
+ String *evname = SwigType_manglestr(qvalue);
+ 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) {
+ 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)
+ Delete(name_qualifier);
+ char *strip_position;
+ name_qualifier = fully_qualify_enum_name(n, NewString(""));
+
+ 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.
+ * Original:
+ * C++/Python polymorphism demo code, copyright (C) 2002 Mark Rose
+ * <mrose@stm.lbl.gov>
+ *
+ * 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;
+ String *value;
+ String *decl;
+ String *type;
+ String *name;
+ String *classname;
+ String *c_classname = Getattr(parent, "name");
+ String *declaration;
+ ParmList *l;
+ Wrapper *w;
+ String *tm;
+ String *wrap_args = NewString("");
+ String *return_type;
+ int status = SWIG_OK;
+ int idx;
+ bool pure_virtual = false;
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+
+ storage = Getattr(n, "storage");
+ value = Getattr(n, "value");
+ classname = Getattr(parent, "sym:name");
+ type = Getattr(n, "type");
+ name = Getattr(n, "name");
+
+ if (Cmp(storage, "virtual") == 0) {
+ if (Cmp(value, "0") == 0) {
+ pure_virtual = true;
+ }
+ }
+
+ w = NewWrapper();
+ declaration = NewString("");
+ Wrapper_add_local(w, "swig_result", "CAMLparam0();\n" "SWIG_CAMLlocal2(swig_result,args)");
+
+ /* determine if the method returns a pointer */
+ decl = Getattr(n, "decl");
+ is_pointer = SwigType_ispointer_return(decl);
+ is_void = (!Cmp(type, "void") && !is_pointer);
+
+ /* form complete return type */
+ return_type = Copy(type);
+ {
+ SwigType *t = Copy(decl);
+ SwigType *f = 0;
+ f = SwigType_pop_function(t);
+ SwigType_push(return_type, t);
+ Delete(f);
+ Delete(t);
+ }
+
+ /* virtual method definition */
+ l = Getattr(n, "parms");
+ String *target;
+ String *pclassname = NewStringf("SwigDirector_%s", classname);
+ String *qualified_name = NewStringf("%s::%s", pclassname, name);
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : type;
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
+ Printf(w->def, "%s {", target);
+ Delete(qualified_name);
+ Delete(target);
+ /* header declaration */
+ target = Swig_method_decl(rtype, decl, name, l, 0, 1);
+ Printf(declaration, " virtual %s;", target);
+ Delete(target);
+
+ /* 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) {
+ if (!(ignored_method && !pure_virtual)) {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(return_type, "c_result"), 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++ -> Ocaml) */
+ String *arglist = NewString("");
+
+ Swig_typemap_attach_parms("in", l, 0);
+ Swig_typemap_attach_parms("directorin", l, 0);
+ 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) {
+ 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 Python 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, "swig_result = " "callback3(*caml_named_value(\"swig_runmethod\")," "swig_get_self(),copy_string(\"%s\"),args);\n", Getattr(n, "name"));
+ /* exception handling */
+ tm = Swig_typemap_lookup("director:except", n, "result", 0);
+ if (!tm) {
+ tm = Getattr(n, "feature:director:except");
+ }
+ if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
+ Printf(w->code, "if (result == NULL) {\n");
+ 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 aruments, 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("");
+
+ idx = 0;
+
+ /* this seems really silly. the node's type excludes
+ * qualifier/pointer/reference markers, which have to be retrieved
+ * from the decl field to construct return_type. but the typemap
+ * lookup routine uses the node's type, so we have to swap in and
+ * out the correct type. it's not just me, similar silliness also
+ * occurs in Language::cDeclaration().
+ */
+ Setattr(n, "type", return_type);
+ tm = Swig_typemap_lookup("directorout", n, "c_result", w);
+ Setattr(n, "type", type);
+ 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, "$input", "swig_result");
+ Replaceall(tm, "$result", Getattr(p, "name"));
+ 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. return_type 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(return_type)) {
+ Printf(w->code, "CAMLreturn_type((%s)c_result);\n", SwigType_lstr(return_type, ""));
+ } else {
+ Printf(w->code, "CAMLreturn_type(*c_result);\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")) {
+ 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(return_type);
+ 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"));
+ 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, 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, 0, 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"));
+ q = Copy(p);
+ set_nextSibling(p, parms);
+ parms = p;
+
+ {
+ 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("ocaml.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'ocaml.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/Source/Modules/octave.cxx b/Source/Modules/octave.cxx
new file mode 100644
index 0000000..aeb72f7
--- /dev/null
+++ b/Source/Modules/octave.cxx
@@ -0,0 +1,1425 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * octave.cxx
+ *
+ * Octave language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_octave_cxx[] = "$Id$";
+
+#include "swigmod.h"
+
+static const char *usage = (char *) "\
+Octave Options (available with -octave)\n\
+ -api <N> - Generate code that assumes Octave API N [default: 37]\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;
+
+ int api_version;
+
+ Hash *docs;
+
+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) {
+ /* 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();
+ api_version = 0;
+ }
+
+ 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, stderr);
+ } else if (strcmp(argv[i], "-api") == 0) {
+ if (argv[i + 1]) {
+ api_version = atoi(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ }
+ }
+ }
+
+ SWIG_library_directory("octave");
+ Preprocessor_define("SWIGOCTAVE 1", 0);
+ SWIG_config_file("octave.swg");
+ SWIG_typemap_lang("octave");
+ allow_overloading();
+ }
+
+ 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");
+ Printf(f_runtime, "#define SWIGOCTAVE\n");
+ Printf(f_runtime, "#define SWIG_name_d \"%s\"\n", module);
+ Printf(f_runtime, "#define SWIG_name %s\n", module);
+ Printf(f_runtime, "#define OCTAVE_API_VERSION_OPTION %i\n", api_version);
+
+ 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 void 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.swg", f_runtime);
+
+ Printf(f_init, "}\n");
+ Printf(s_global_tab, "{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);
+ Close(f_begin);
+ 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,"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) {
+ 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, "0");
+ 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")) {
+ type = SwigType_base(type);
+ Node *lookup = Swig_symbol_clookup(type, 0);
+ if (lookup)
+ type = Getattr(lookup, "sym:name");
+ Append(decl_info, "@var{retval} = ");
+ String *type_str = NewString("");
+ Printf(type_str, "@var{retval} is of type %s. ", type);
+ Append(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, "feval(\"%s\",octave_value_list(),0);\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";
+ }
+
+ void make_autodocParmList(Node *n, String *decl_str, String *args_str) {
+ String *pdocs = Copy(Getattr(n, "feature:pdocs"));
+ ParmList *plist = CopyParmList(Getattr(n, "parms"));
+ Parm *p;
+ Parm *pnext;
+ Node *lookup;
+
+ if (pdocs)
+ Append(pdocs, "\n");
+
+ Swig_typemap_attach_parms("in", plist, 0);
+ Swig_typemap_attach_parms("doc", plist, 0);
+
+ for (p = plist; p; p = pnext) {
+ String *name = 0;
+ String *type = 0;
+ String *value = 0;
+ String *ptype = 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");
+ ptype = Getattr(p, "tmap:doc:pytype");
+ }
+
+ name = name ? name : Getattr(p, "name");
+ type = type ? type : Getattr(p, "type");
+ value = value ? value : Getattr(p, "value");
+
+ String *tex_name = NewString("");
+ if (name)
+ Printf(tex_name, "@var{%s}", name);
+ else
+ Printf(tex_name, "@var{?}");
+
+ String *tm = Getattr(p, "tmap:in");
+ if (tm) {
+ pnext = Getattr(p, "tmap:in:next");
+ } else {
+ pnext = nextSibling(p);
+ }
+
+ if (Len(decl_str))
+ Append(decl_str, ", ");
+ Append(decl_str, tex_name);
+
+ if (value) {
+ if (Strcmp(value, "NULL") == 0)
+ value = NewString("nil");
+ else if (Strcmp(value, "true") == 0 || Strcmp(value, "TRUE") == 0)
+ value = NewString("true");
+ else if (Strcmp(value, "false") == 0 || Strcmp(value, "FALSE") == 0)
+ value = NewString("false");
+ else {
+ lookup = Swig_symbol_clookup(value, 0);
+ if (lookup)
+ value = Getattr(lookup, "sym:name");
+ }
+ Printf(decl_str, " = %s", value);
+ }
+
+ if (type) {
+ String *type_str = NewString("");
+ type = SwigType_base(type);
+ lookup = Swig_symbol_clookup(type, 0);
+ if (lookup)
+ type = Getattr(lookup, "sym:name");
+ Printf(type_str, "%s is of type %s. ", tex_name, type);
+ Append(args_str, type_str);
+ Delete(type_str);
+ }
+
+ Delete(tex_name);
+ }
+ if (pdocs)
+ Setattr(n, "feature:pdocs", pdocs);
+ Delete(plist);
+ }
+
+ virtual int functionWrapper(Node *n) {
+ Wrapper *f = NewWrapper();
+ 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"));
+
+ Printv(f->def, "static octave_value_list ", overname, " (const octave_value_list& args, int nargout) {", NIL);
+
+ 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, "result", f, actioncode))) {
+ Replaceall(tm, "$source", "result");
+ 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, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ Replaceall(tm, "$result", "_outv");
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+
+ Printf(f->code, "fail:\n"); // we should free locals etc if this happens
+ Printf(f->code, "return _out;\n");
+ Printf(f->code, "}\n");
+
+ Replaceall(f->code, "$symname", iname);
+ Wrapper_print(f, f_wrappers);
+ DelWrapper(f);
+
+ if (last_overload)
+ dispatchFunction(n);
+
+ if (!overloaded || last_overload) {
+ process_autodoc(n);
+ 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("");
+
+ Printv(f->def, "static octave_value_list ", wname, " (const octave_value_list& args, int nargout) {", NIL);
+ 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(iname);
+ String *setname = Swig_name_set(iname);
+
+ Printf(setf->def, "static octave_value_list _wrap_%s(const octave_value_list& args,int nargout) {", setname);
+ Printf(setf->def, "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, "fail:\n");
+ Printf(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;
+ Printf(getf->def, "static octave_value_list _wrap_%s(const octave_value_list& args,int nargout) {", getname);
+ 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,_wrap_%s,_wrap_%s,2,0},\n", iname, getname, setname);
+
+ 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 *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", 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);
+
+ 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 *disown_shadow = NewString("");
+ Printf(disown_shadow, "static octave_value_list _wrap_disown_%s_shadow " "(const octave_value_list& args, int nargout) {\n", class_name);
+ Printf(disown_shadow, " if (args.length()!=1) {\n");
+ Printf(disown_shadow, " error(\"disown takes no arguments\");\n");
+ Printf(disown_shadow, " return octave_value_list();\n");
+ Printf(disown_shadow, " }\n");
+ Printf(disown_shadow, " _wrap_disown_%s (args, nargout);\n", class_name);
+ Printf(disown_shadow, " return args;\n");
+ Printf(disown_shadow, "}\n");
+ Printv(f_wrappers, disown_shadow, NIL);
+ Delete(disown_shadow);
+ Printf(s_members_tab, "{\"__disown\",_wrap_disown_%s_shadow,0,0,0,0},\n", class_name);
+ }
+
+ Printf(s_members_tab, "{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 *cname = Swig_name_construct(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)
+ Printv(f_wrappers, "_wrap_delete_", class_name, ",", NIL);
+ 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(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 *rname = Swig_name_wrapper(Swig_name_member(class_name, realname));
+
+ if (!Getattr(n, "sym:nextSibling")) {
+ String *tname = texinfo_name(n);
+ Printf(s_members_tab, "{\"%s\",%s,0,0,0,%s},\n",
+ realname, rname, tname);
+ Delete(tname);
+ }
+
+ Delete(rname);
+ 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_wrapper(Swig_name_get(Swig_name_member(class_name, symname)));
+ String *setname = GetFlag(n, "feature:immutable") ?
+ NewString("octave_set_immutable") : Swig_name_wrapper(Swig_name_set(Swig_name_member(class_name, symname)));
+ assert(s_members_tab);
+
+ Printf(s_members_tab, "{\"%s\",0,%s,%s,0,0},\n", symname, getname, setname);
+
+ Delete(getname);
+ Delete(setname);
+ 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);
+ 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 *rname = Swig_name_wrapper(Swig_name_member(class_name, realname));
+
+ if (!Getattr(n, "sym:nextSibling")) {
+ String *tname = texinfo_name(n);
+ Printf(s_members_tab, "{\"%s\",%s,0,0,1,%s},\n",
+ realname, rname, tname);
+ Delete(tname);
+ }
+
+ Delete(rname);
+ 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_wrapper(Swig_name_get(Swig_name_member(class_name, symname)));
+ String *setname = GetFlag(n, "feature:immutable") ?
+ NewString("octave_set_immutable") : Swig_name_wrapper(Swig_name_set(Swig_name_member(class_name, symname)));
+ assert(s_members_tab);
+
+ Printf(s_members_tab, "{\"%s\",0,%s,%s,1,0},\n", symname, getname, setname);
+
+ Delete(getname);
+ Delete(setname);
+ }
+ 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"));
+ 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, 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, 0, 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;
+ String *type;
+ String *name;
+ String *classname;
+ String *c_classname = Getattr(parent, "name");
+ String *declaration;
+ ParmList *l;
+ Wrapper *w;
+ String *tm;
+ String *wrap_args = NewString("");
+ String *return_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;
+ }
+ }
+
+ classname = Getattr(parent, "sym:name");
+ type = Getattr(n, "type");
+ name = Getattr(n, "name");
+
+ w = NewWrapper();
+ declaration = NewString("");
+
+ // determine if the method returns a pointer
+ decl = Getattr(n, "decl");
+ is_pointer = SwigType_ispointer_return(decl);
+ is_void = (!Cmp(type, "void") && !is_pointer);
+
+ // form complete return type
+ return_type = Copy(type);
+ {
+ SwigType *t = Copy(decl);
+ SwigType *f = 0;
+ f = SwigType_pop_function(t);
+ SwigType_push(return_type, t);
+ Delete(f);
+ Delete(t);
+ }
+
+ // virtual method definition
+ l = Getattr(n, "parms");
+ String *target;
+ String *pclassname = NewStringf("SwigDirector_%s", classname);
+ String *qualified_name = NewStringf("%s::%s", pclassname, name);
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : type;
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+
+ // header declaration
+ target = Swig_method_decl(rtype, decl, name, l, 0, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Get any exception classes in the throws typemap
+ 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 ((tm = 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) {
+ if (!(ignored_method && !pure_virtual)) {
+ String *cres = SwigType_lstr(return_type, "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++ -> Python)
+ String *parse_args = NewString("");
+
+ Swig_typemap_attach_parms("in", l, 0);
+ Swig_typemap_attach_parms("directorin", l, 0);
+ 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;
+ int use_parse = 0;
+ while (p != NULL) {
+ 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) {
+ 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 {
+ use_parse = 1;
+ Append(parse_args, parse);
+ 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");
+
+ Setattr(n, "type", return_type);
+ tm = Swig_typemap_lookup("directorout", n, "result", w);
+ Setattr(n, "type", type);
+ 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(return_type, 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, "$input", temp);
+ Replaceall(tm, "$result", Getattr(p, "name"));
+ 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(return_type, 0);
+ if (!SwigType_isreference(return_type)) {
+ 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")) {
+ 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(return_type);
+ 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/Source/Modules/overload.cxx b/Source/Modules/overload.cxx
new file mode 100644
index 0000000..38cb729
--- /dev/null
+++ b/Source/Modules/overload.cxx
@@ -0,0 +1,792 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * 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.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_overload_cxx[] = "$Id: overload.cxx 11455 2009-07-26 21:29:55Z wsfulton $";
+
+#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 */
+};
+
+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;
+}
+
+/* -----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------- */
+
+static 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;
+ 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 (no type checking rule 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 (no type checking rule 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. Non-const method %s at %s:%d used.\n",
+ Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), Getfile(nodes[i].n), Getline(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. Method %s at %s:%d used.\n",
+ Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), Getfile(nodes[i].n), Getline(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. Non-const method %s at %s:%d used.\n",
+ Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), Getfile(nodes[i].n), Getline(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. Method %s at %s:%d used.\n",
+ Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), Getfile(nodes[i].n), Getline(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 is shadowed by %s at %s:%d.\n",
+ Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n),
+ Getfile(nodes[i].n), Getline(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. Method %s at %s:%d used.\n",
+ Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n),
+ Getfile(nodes[i].n), Getline(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;
+}
+
+// /* -----------------------------------------------------------------------------
+// * print_typecheck()
+// * ----------------------------------------------------------------------------- */
+
+static bool print_typecheck(String *f, int j, Parm *pj) {
+ char tmp[256];
+ sprintf(tmp, Char(argv_template_string), j);
+ String *tm = Getattr(pj, "tmap:typecheck");
+ if (tm) {
+ Replaceid(tm, Getattr(pj, "lname"), "_v");
+ String *conv = Getattr(pj, "implicitconv");
+ if (conv) {
+ Replaceall(tm, "$implicitconv", conv);
+ } else {
+ Replaceall(tm, "$implicitconv", "0");
+ }
+ Replaceall(tm, "$input", tmp);
+ Printv(f, tm, "\n", NIL);
+ 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 = 1;
+ for (i = 0; i < nfunc; i++) {
+ int fn = 0;
+ Node *ni = Getitem(dispatch, i);
+ Parm *pi = Getattr(ni, "wrap:parms");
+ int num_required = emit_num_required(pi);
+ int num_arguments = emit_num_arguments(pi);
+ if (num_arguments > *maxargs)
+ *maxargs = num_arguments;
+ int varargs = emit_isvarargs(pi);
+
+ if (!varargs) {
+ 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);
+ }
+ } else {
+ Printf(f, "if (%s >= %d) {\n", argc_template_string, num_required);
+ }
+ 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) {
+ /* 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 = 1;
+ //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) {
+ Replaceall(tm, "$implicitconv", conv);
+ } else {
+ Replaceall(tm, "$implicitconv", "0");
+ }
+ Replaceall(tm, "$input", tmp);
+ Printv(f, "{\n", tm, "}\n", NIL);
+ 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);
+
+ 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).
+*/
+String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *maxargs) {
+ 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");
+ int num_required = emit_num_required(pi);
+ int num_arguments = emit_num_arguments(pi);
+ if (num_arguments > *maxargs)
+ *maxargs = num_arguments;
+ int varargs = emit_isvarargs(pi);
+
+ if (!varargs) {
+ 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);
+ }
+ } else {
+ Printf(f, "if (%s >= %d) {\n", argc_template_string, num_required);
+ }
+
+ /* 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 = (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) {
+ /* 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 */
+ bool emitcheck = 0;
+ 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 = 1;
+ //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) {
+ Replaceall(tm, "$implicitconv", conv);
+ } else {
+ Replaceall(tm, "$implicitconv", "0");
+ }
+ Replaceall(tm, "$input", tmp);
+ Printv(f, "{\n", tm, "}\n", NIL);
+ 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");
+
+
+ String *lfmt = ReplaceFormat(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);
+
+ Delete(lfmt);
+ Delete(coll);
+ }
+ Delete(dispatch);
+ return f;
+}
+
+String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *maxargs) {
+
+ if (fast_dispatch_mode || GetFlag(n, "feature:fastdispatch")) {
+ return Swig_overload_dispatch_fast(n, fmt, maxargs);
+ }
+
+ 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");
+ 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;
+ int varargs = emit_isvarargs(pi);
+
+ if (!varargs) {
+ 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);
+ }
+ } else {
+ Printf(f, "if (%s >= %d) {\n", argc_template_string, num_required);
+ }
+
+ 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)) {
+ 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 */
+ }
+ Delete(dispatch);
+ return f;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_overload_check()
+ * ----------------------------------------------------------------------------- */
+void Swig_overload_check(Node *n) {
+ Swig_overload_rank(n, false);
+}
diff --git a/Source/Modules/perl5.cxx b/Source/Modules/perl5.cxx
new file mode 100644
index 0000000..34b2701
--- /dev/null
+++ b/Source/Modules/perl5.cxx
@@ -0,0 +1,1768 @@
+/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=2:tabstop=8:smarttab:
+ */
+
+/* ----------------------------------------------------------------------------
+ * 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.
+ *
+ * perl5.cxx
+ *
+ * Perl5 language module for SWIG.
+ * ------------------------------------------------------------------------- */
+
+char cvsroot_perl5_cxx[] = "$Id: perl5.cxx 11397 2009-07-15 07:43:16Z olly $";
+
+#include "swigmod.h"
+#include "cparse.h"
+static int treduce = SWIG_cparse_template_reduce(0);
+
+#include <ctype.h>
+
+static const char *usage = (char *) "\
+Perl5 Options (available with -perl5)\n\
+ -static - Omit code related to dynamic loading\n\
+ -nopm - Do not generate the .pm file\n\
+ -proxy - Create proxy classes\n\
+ -noproxy - Don't create proxy classes\n\
+ -const - Wrap constants as constants and not variables (implies -proxy)\n\
+ -nocppcast - Disable C++ casting operators, useful for generating bugs\n\
+ -cppcast - Enable C++ casting operators\n\
+ -compat - Compatibility mode\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_header = 0;
+static File *f_wrappers = 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);
+ }
+
+ /* 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' --> '%x'\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;
+ int cppcast = 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], "-cppcast") == 0) {
+ cppcast = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocppcast") == 0) {
+ cppcast = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-compat") == 0) {
+ compat = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ }
+ }
+ }
+
+ if (cppcast) {
+ Preprocessor_define((DOH *) "SWIG_CPLUSPLUS_CAST", 0);
+ }
+
+ 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) {
+
+ /* 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);
+
+ 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");
+ Printf(f_runtime, "#define SWIGPERL\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"));
+
+ 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");
+ }
+ }
+ String *underscore_module = Copy(module);
+ Replaceall(underscore_module,":","_");
+
+ if (verbose > 0) {
+ fprintf(stdout, "top: using namespace_module: %s\n", Char(namespace_module));
+ }
+
+ /* 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 == NULL) {
+ 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);
+
+ 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");
+ Close(f_pm);
+ 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);
+ Dump(f_wrappers, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Close(f_begin);
+ 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;
+
+ 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. */
+ i = 0;
+ 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);
+ }
+
+ /* 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, "result", f, actioncode))) {
+ SwigType *t = Getattr(n, "type");
+ Replaceall(tm, "$source", "result");
+ 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, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ Printf(f->code, "%s\n", 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, "++PL_markstack_ptr; 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(iname);
+ String *setname = Swig_name_set(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));
+ 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) {
+ String *tm = NewStringf("&SWIGTYPE%s", SwigType_manglestr(t));
+ if (Replaceall(tt, "$1_descriptor", tm)) {
+ SwigType_remember(t);
+ }
+ Delete(tm);
+ SwigType *st = Copy(t);
+ SwigType_add_pointer(st);
+ tm = NewStringf("&SWIGTYPE%s", SwigType_manglestr(st));
+ if (Replaceall(tt, "$&1_descriptor", tm)) {
+ SwigType_remember(st);
+ }
+ Delete(tm);
+ Delete(st);
+ } else {
+ tt = (String *) "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);
+
+ 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 */
+
+ Printv(pm,
+ "sub DISOWN {\n",
+ tab4, "my $self = shift;\n",
+ 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);
+
+ /* Only output the following methods if a class has member data */
+
+ Delete(operators);
+ operators = 0;
+ }
+ 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(class_name, symname));
+ Replaceall(plcode, "$action", plaction);
+ Delete(plaction);
+ Printv(pcode, plcode, NIL);
+ } else {
+ Printv(pcode, "*", symname, " = *", cmodule, "::", Swig_name_member(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(Swig_name_member(class_name, symname)), ";\n", NIL);
+ Printv(pcode, "*swig_", symname, "_set = *", cmodule, "::", Swig_name_set(Swig_name_member(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;
+ Language::constructorHandler(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(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(symname), " {\n", NIL);
+ }
+
+ Printv(pcode,
+ tab4, "my $pkg = shift;\n",
+ tab4, "my $self = ", cmodule, "::", Swig_name_construct(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(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(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(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(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(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) {
+ Printf(stderr, "%s : Line %d. Unable to locate file %s\n", input_file, line_number, value);
+ } else {
+ char buffer[4096];
+ while (fgets(buffer, 4095, f)) {
+ Printf(pragma_include, "%s", buffer);
+ }
+ }
+ fclose(f);
+ }
+ } else {
+ Printf(stderr, "%s : Line %d. Unrecognized pragma.\n", input_file, line_number);
+ }
+ }
+ }
+ 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 = DohSplitLines(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");
+ }
+};
+
+/* -----------------------------------------------------------------------------
+ * 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/Source/Modules/php.cxx b/Source/Modules/php.cxx
new file mode 100644
index 0000000..a0c9e24
--- /dev/null
+++ b/Source/Modules/php.cxx
@@ -0,0 +1,2739 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * php.cxx
+ *
+ * PHP language module for SWIG.
+ * -----------------------------------------------------------------------------
+ */
+
+/* FIXME: PHP5 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...)
+ */
+
+char cvsroot_php_cxx[] = "$Id: php.cxx 11637 2009-08-18 16:23:23Z vmiklos $";
+
+#include "swigmod.h"
+
+#include <ctype.h>
+#include <errno.h>
+
+static const char *usage = (char *) "\
+PHP Options (available with -php)\n\
+ -cppext - cpp file extension (default to .cpp)\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_entry;
+static String *cs_entry;
+static String *all_cs_entry;
+static String *pragma_incl;
+static String *pragma_code;
+static String *pragma_phpinfo;
+static String *s_oowrappers;
+static String *s_fakeoowrappers;
+static String *s_phpclasses;
+
+/* 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) (SwigType *t, String *mangled, String *clientdata) = 0;
+}
+
+static void SwigPHP_emit_resource_registrations() {
+ Iterator ki;
+
+ 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;
+
+ // Write out destructor function header
+ Printf(s_wrappers, "static ZEND_RSRC_DTOR_FUNC(_wrap_destroy%s) {\n", key);
+
+ // 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) {
+ Printf(s_wrappers, " %s(rsrc, SWIGTYPE%s->name TSRMLS_CC);\n", destructor, key);
+ } else {
+ Printf(s_wrappers, " /* No destructor for class %s */\n", human_name);
+ Printf(s_wrappers, " efree(rsrc->ptr);\n");
+ }
+ } else {
+ Printf(s_wrappers, " /* No destructor for simple type %s */\n", key);
+ Printf(s_wrappers, " efree(rsrc->ptr);\n");
+ }
+
+ // close function
+ Printf(s_wrappers, "}\n");
+
+ // 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"
+ "(_wrap_destroy%s,NULL,(char *)(SWIGTYPE%s->name),module_number);\n", key, key, key);
+
+ // store php type in class struct
+ Printf(s_oinit, "SWIG_TypeClientData(SWIGTYPE%s,&le_swig_%s);\n", key, key);
+
+ ki = Next(ki);
+ }
+}
+
+class PHP : public Language {
+public:
+ PHP() {
+ director_language = 1;
+ }
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+ SWIG_library_directory("php");
+ SWIG_config_cppext("cpp");
+
+ 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], "-cppext") == 0) {
+ if (argv[i + 1]) {
+ 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], "-noshadow") == 0) || (strcmp(argv[i], "-noproxy") == 0)) {
+ shadow = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ } else if (strcmp(argv[i], "-make") == 0 ||
+ strcmp(argv[i], "-withc") == 0 ||
+ strcmp(argv[i], "-withcxx") == 0) {
+ Printf(stderr, "*** %s is no longer supported.\n", argv[i]);
+ SWIG_exit(EXIT_FAILURE);
+ } else if (strcmp(argv[i], "-phpfull") == 0 ||
+ strcmp(argv[i], "-withlibs") == 0 ||
+ strcmp(argv[i], "-withincs") == 0) {
+ Printf(stderr, "*** %s is no longer supported.\n*** We recommend building as a dynamically loadable module.\n", argv[i]);
+ SWIG_exit(EXIT_FAILURE);
+ } else if (strcmp(argv[i], "-dlname") == 0) {
+ Printf(stderr, "*** -dlname is no longer supported.\n*** If you want to change the module name, use -module instead.\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+
+ Preprocessor_define("SWIGPHP 1", 0);
+ // SWIGPHP5 is deprecated, and no longer documented.
+ Preprocessor_define("SWIGPHP5 1", 0);
+ SWIG_typemap_lang("php");
+ SWIG_config_file("php.swg");
+ allow_overloading();
+ }
+
+ /* ------------------------------------------------------------
+ * top()
+ * ------------------------------------------------------------ */
+
+ virtual int top(Node *n) {
+
+ String *filen;
+ String *s_type;
+
+ /* 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("$arg->type != 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 = NewString("/* init section */\n");
+ r_init = NewString("/* rinit section */\n");
+ s_shutdown = NewString("/* shutdown section */\n");
+ r_shutdown = NewString("/* rshutdown section */\n");
+ s_header = NewString("/* header section */\n");
+ s_wrappers = NewString("/* wrapper section */\n");
+ s_type = NewStringEmpty();
+ /* subsections of the init section */
+ s_vinit = NewString("/* vinit subsection */\n");
+ 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");
+ Printf(f_runtime, "#define SWIGPHP\n");
+ Printf(f_runtime, "\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();
+
+ 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);
+
+ Printf(f_directors, "\n#include \"%s\"\n\n", Swig_file_filename(outfile_h));
+ }
+
+ /* 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();
+
+ /* Initialize the rest of the module */
+
+ Printf(s_oinit, "ZEND_INIT_MODULE_GLOBALS(%s, %s_init_globals, %s_destroy_globals);\n", module, 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, "#ifdef ZTS\n");
+ Printf(s_header, "#define SWIG_ErrorMsg() TSRMG(%s_globals_id, zend_%s_globals *, error_msg )\n", module, module);
+ Printf(s_header, "#define SWIG_ErrorCode() TSRMG(%s_globals_id, zend_%s_globals *, error_code )\n", module, module);
+ Printf(s_header, "#else\n");
+ Printf(s_header, "#define SWIG_ErrorMsg() (%s_globals.error_msg)\n", module);
+ Printf(s_header, "#define SWIG_ErrorCode() (%s_globals.error_code)\n", module);
+ Printf(s_header, "#endif\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 %s_destroy_globals(zend_%s_globals * globals) { (void)globals; }\n", module, module);
+
+ Printf(s_header, "\n");
+ Printf(s_header, "static void SWIG_ResetError() {\n");
+ Printf(s_header, " TSRMLS_FETCH();\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, " int type;\n");
+ Append(s_header, " int thisown;\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 *) zend_list_find((*args[0])->value.lval, &type);\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, " int type;\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 *) zend_list_find((*args[0])->value.lval, &type);\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 HAVE_CONFIG_H\n");
+ Printf(s_header,"#include \"config.h\"\n");
+ Printf(s_header,"#endif\n\n");
+ */
+ 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.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");
+ Printf(f_h, "#ifdef ZTS\n");
+ Printf(f_h, "#include \"TSRM.h\"\n");
+ Printf(f_h, "#endif\n\n");
+ Printf(f_h, "PHP_MINIT_FUNCTION(%s);\n", module);
+ Printf(f_h, "PHP_MSHUTDOWN_FUNCTION(%s);\n", module);
+ Printf(f_h, "PHP_RINIT_FUNCTION(%s);\n", module);
+ Printf(f_h, "PHP_RSHUTDOWN_FUNCTION(%s);\n", module);
+ Printf(f_h, "PHP_MINFO_FUNCTION(%s);\n\n", module);
+
+ /* 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);
+
+ /* start the init section */
+ Append(s_init, "#if ZEND_MODULE_API_NO <= 20090626\n");
+ Append(s_init, "#undef ZEND_MODULE_BUILD_ID\n");
+ Append(s_init, "#define ZEND_MODULE_BUILD_ID (char*)\"API\" ZEND_TOSTR(ZEND_MODULE_API_NO) ZEND_BUILD_TS ZEND_BUILD_DEBUG ZEND_BUILD_SYSTEM ZEND_BUILD_EXTRA\n");
+ Append(s_init, "#endif\n");
+ Printv(s_init, "zend_module_entry ", module, "_module_entry = {\n" "#if ZEND_MODULE_API_NO > 20010900\n" " STANDARD_MODULE_HEADER,\n" "#endif\n", NIL);
+ Printf(s_init, " (char*)\"%s\",\n", module);
+ Printf(s_init, " %s_functions,\n", module);
+ Printf(s_init, " PHP_MINIT(%s),\n", module);
+ Printf(s_init, " PHP_MSHUTDOWN(%s),\n", module);
+ Printf(s_init, " PHP_RINIT(%s),\n", module);
+ Printf(s_init, " PHP_RSHUTDOWN(%s),\n", module);
+ Printf(s_init, " PHP_MINFO(%s),\n", module);
+ Printf(s_init, "#if ZEND_MODULE_API_NO > 20010900\n");
+ Printf(s_init, " NO_VERSION_YET,\n");
+ Printf(s_init, "#endif\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 PHP5 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");
+
+ /* 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
+ */
+ Printf(s_init, "#define SWIG_php_minit PHP_MINIT_FUNCTION(%s)\n", module);
+
+ /* Emit all of the code */
+ Language::top(n);
+
+ SwigPHP_emit_resource_registrations();
+ // 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
+ Printf(s_init, "PHP_RINIT_FUNCTION(%s)\n{\n", module);
+ Printf(s_init, "%s\n", r_init);
+
+ /* finish our init section which will have been used by class wrappers */
+ Printf(s_vinit, "/* end vinit subsection */\n");
+ Printf(s_init, "%s\n", s_vinit);
+ Clear(s_vinit);
+ Delete(s_vinit);
+
+ Printf(s_init, " return SUCCESS;\n");
+ Printf(s_init, "}\n\n");
+
+ Printv(s_init, "PHP_MSHUTDOWN_FUNCTION(", module, ")\n"
+ "{\n",
+ s_shutdown,
+ "#ifdef ZTS\n"
+ " ts_free_id(", module, "_globals_id);\n"
+ "#endif\n"
+ " return SUCCESS;\n"
+ "}\n\n", NIL);
+
+ Printf(s_init, "PHP_RSHUTDOWN_FUNCTION(%s)\n{\n", module);
+ Printf(s_init, "%s\n", r_shutdown);
+ Printf(s_init, " return SUCCESS;\n");
+ Printf(s_init, "}\n\n");
+
+ 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, "#endif /* PHP_%s_H */\n", cap_module);
+
+ Close(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");
+ Close(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_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"
+ "{NULL, NULL, NULL}\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);
+ Close(f_begin);
+ Delete(f_runtime);
+ Delete(f_begin);
+
+ 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?>\n", s_phpclasses);
+ Close(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) {
+ // This is for the single main zend_function_entry record
+ Printf(f_h, "ZEND_NAMED_FUNCTION(%s);\n", iname);
+ String * s = cs_entry;
+ if (!s) s = s_entry;
+ Printf(s, " SWIG_ZEND_NAMED_FE(%(lower)s,%s,NULL)\n", cname, iname);
+ }
+
+ /* ------------------------------------------------------------
+ * 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, "return %s(INTERNAL_FUNCTION_PARAM_PASSTHRU);", &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);
+ 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, "zend_error(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());\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();
+ numopt = 0;
+
+ String *outarg = NewStringEmpty();
+ String *cleanup = NewStringEmpty();
+
+ // Not issued for overloaded functions.
+ if (!overloaded) {
+ create_command(iname, wname);
+ }
+ Printv(f->def, "ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL);
+
+ emit_parameter_variables(l, f);
+ /* Attach standard typemaps */
+
+ emit_attach_parmmaps(l, f);
+
+ // 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;
+ }
+ if (is_member_director(n)) {
+ 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");
+ Printf(f->code, "upcall = !director->is_overriden_method((char *)\"%s\", (char *)\"%s\");\n",
+ Swig_class_name(Swig_methodclass(n)), name);
+ }
+
+ // 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);
+ }
+
+ 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 */
+ for (i = 0, p = l; p; i++) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ 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, "result", f, actioncode))) {
+ Replaceall(tm, "$input", "result");
+ Replaceall(tm, "$source", "result");
+ 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, "result", 0))) {
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+
+ Printf(f->code, "return;\n");
+
+ /* Error handling code */
+ Printf(f->code, "fail:\n");
+ Printv(f->code, cleanup, NIL);
+ Printv(f->code, "zend_error_noreturn(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());", NIL);
+
+ 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, iname);
+ } 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;
+ // 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(Swig_methodclass(n), "sym:name"), ':');
+ if (ptr) {
+ ptr++;
+ } else {
+ ptr = GetChar(Swig_methodclass(n), "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);
+
+ // For a function with default arguments, we end up with the fullest
+ // parmlist in full_parmlist.
+ ParmList *full_parmlist = l;
+ Hash *ret_types = NewHash();
+ Setattr(ret_types, d, d);
+
+ 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);
+ }
+
+ 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;
+ full_parmlist = l2;
+ }
+ 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 (l != full_parmlist) {
+ l = full_parmlist;
+ if (wrapperType == memberfn)
+ l = nextSibling(l);
+ }
+ }
+ }
+
+ 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");
+ exit(1);
+ }
+ for (i = 0; i < max_num_of_arguments; ++i) {
+ arg_names[i] = NULL;
+ }
+
+ arg_values = (String **) malloc(max_num_of_arguments * sizeof(String *));
+ if (!arg_values) {
+ /* FIXME: How should this be handled? The rest of SWIG just seems
+ * to not bother checking for malloc failing! */
+ fprintf(stderr, "Malloc failed!\n");
+ exit(1);
+ }
+ for (i = 0; i < max_num_of_arguments; ++i) {
+ arg_values[i] = NULL;
+ }
+
+ 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);
+ 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 == NULL) {
+ 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;
+ int 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: {
+ char *p;
+ errno = 0;
+ unsigned int 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: {
+ 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:{
+ 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), '.') == NULL) {
+ // 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_REFERENCE:
+ case T_USER:
+ case T_ARRAY:
+ 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, "0") == 0 ||
+ Strcmp(value, "0L") == 0) {
+ Clear(value);
+ Append(value, "null");
+ } else {
+ 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);
+ /* We use $r to store the return value, so disallow that as a parameter
+ * name in case the user uses the "call-time pass-by-reference" feature
+ * (it's deprecated and off by default in PHP5, but we want to be
+ * maximally portable). Similarly we use $c for the classname or new
+ * stdClass object.
+ */
+ Setattr(seen, "r", seen);
+ Setattr(seen, "c", 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, ",");
+ 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 {
+ 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);
+ 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 (Cmp(d, "void") != 0) {
+ if ((!directorsEnabled() || !Swig_directorclass(n)) && !newobject) {
+ Append(prepare, "$r=");
+ } else {
+ Printf(prepare, "$this->%s=", SWIG_PTR);
+ }
+ }
+ if (!directorsEnabled() || !Swig_directorclass(n) || !newobject) {
+ 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 (Cmp(d, "void") != 0) {
+ if ((!directorsEnabled() || !Swig_directorclass(n)) && !newobject) {
+ Append(prepare, "$r=");
+ } else {
+ Printf(prepare, "$this->%s=", SWIG_PTR);
+ }
+ }
+
+ if (!directorsEnabled() || !Swig_directorclass(n) || !newobject) {
+ 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) {
+ if (Strcmp(Getattr(j, "name"), 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 = NewString("public");
+ Swig_warning(WARN_PHP_PUBLIC_BASE, input_file, line_number, Char(warnmsg));
+ Delete(warnmsg);
+ }
+ }
+ if (Cmp(acc, "") != 0) {
+ Append(acc, " ");
+ }
+ if (constructor) {
+ const char * arg0;
+ if (max_num_of_arguments > 0) {
+ arg0 = Char(arg_names[0]);
+ } else {
+ arg0 = "res";
+ Delete(args);
+ args = NewString("$res=null");
+ }
+ SwigType *t = Getattr(current_class, "classtype");
+ String *mangled_type = SwigType_manglestr(SwigType_ltype(t));
+ Printf(output, "\t%sfunction %s(%s) {\n", acc, methodname, args);
+ Printf(output, "\t\tif (is_resource($%s) && get_resource_type($%s) === '_p%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 (!newobject)
+ Printf(output, "%s", prepare);
+ if (constructor) {
+ if (!directorsEnabled() || !Swig_directorclass(n)) {
+ 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);\n", 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 (Cmp(d, "void") == 0) {
+ 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 it has an abstract base, then we can't create a new
+ * base object. */
+ int hasabstractbase = 0;
+ Node *bases = Getattr(Swig_methodclass(n), "bases");
+ if (bases) {
+ Iterator i = First(bases);
+ while(i.item) {
+ if (Getattr(i.item, "abstract")) {
+ hasabstractbase = 1;
+ break;
+ }
+ i = Next(i);
+ }
+ }
+ if (newobject || !hasabstractbase) {
+ /*
+ * _p_Foo -> Foo, _p_ns__Bar -> Bar
+ * TODO: do this in a more elegant way
+ */
+ Printf(output, "\t\tif (is_resource($r)) {\n");
+ if (Getattr(classLookup(Getattr(n, "type")), "module")) {
+ 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)) {\n");
+ Printf(output, "\t\t\t\treturn new %s($r);\n", Getattr(classLookup(d), "sym:name"));
+ Printf(output, "\t\t\t}\n");
+ Printf(output, "\t\t\treturn new $c($r);\n");
+ } else {
+ Printf(output, "\t\t\t$c = new stdClass();\n");
+ Printf(output, "\t\t\t$c->_cPtr = $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");
+ Printf(output, "\t\tswitch (get_resource_type($r)) {\n");
+ Iterator i = First(ret_types);
+ while (i.item) {
+ SwigType *ret_type = i.item;
+ i = Next(i);
+ Printf(output, "\t\t");
+ 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. */
+ class_node = current_class;
+ Delete(mangled);
+ mangled = NewString(SwigType_manglestr(ret_type));
+ class_node = Getattr(zend_types, mangled);
+ }
+ if (i.item) {
+ Printf(output, "case '%s': ", mangled);
+ } else {
+ Printf(output, "default: ");
+ }
+ const char *classname = GetChar(class_node, "sym:name");
+ if (!classname)
+ classname = GetChar(class_node, "name");
+ if (classname)
+ Printf(output, "return new %s%s($r);\n", prefix, classname);
+ else
+ Printf(output, "return $r;\n");
+ Delete(mangled);
+ }
+ Printf(output, "\t\t}\n");
+ }
+ } else {
+ Printf(output, "\t\treturn %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;
+
+ SwigType_remember(t);
+
+ /* 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 {
+ Printf(stderr, "%s: Line %d, Unable to link with type %s\n", input_file, line_number, 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 {
+ Printf(stderr,"%s: Line %d, Unable to link with type %s\n", input_file, line_number, 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 {
+ Printf(stderr,"%s: Line %d, Unable to link with type %s\n", input_file, line_number, 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) {
+ // 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 || Strcmp(lang, "php4") == 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 {
+ 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;
+ //SwigType *t = Getattr(n, "classtype");
+ current_class = n;
+ // String *use_class_name=SwigType_manglestr(SwigType_ltype(t));
+
+ 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 proxy: 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) {
+ DOH *key;
+ 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, "abstract") && !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 ");
+ }
+ 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.
+ while (ki.key) {
+ key = ki.key;
+ Printf(s_phpclasses, "\t\tif ($var === '%s') return %s($this->%s,$value);\n", key, ki.item, SWIG_PTR);
+ ki = Next(ki);
+ }
+ } 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");
+
+ /* Create __isset for PHP 5.1 and later; PHP 5.0 will just ignore it. */
+ Printf(s_phpclasses, "\n\tfunction __isset($var) {\n");
+ Printf(s_phpclasses, "\t\tif (function_exists('%s_'.$var.'_set')) 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 __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");
+ 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");
+ }
+ // Write property GET handlers
+ ki = First(shadow_get_vars);
+
+ if (ki.key) {
+ // This class has getters.
+ Printf(s_phpclasses, "\n\tfunction __get($var) {\n");
+ // FIXME: Currently we always use call_user_func for __get, so we can
+ // check and wrap the result. This is needless if all the properties
+ // are primitive types. Also this doesn't handle all the cases which
+ // a method returning an object does.
+ Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_get';\n", shadow_classname);
+ Printf(s_phpclasses, "\t\tif (function_exists($func)) {\n");
+ Printf(s_phpclasses, "\t\t\t$r = call_user_func($func,$this->%s);\n", SWIG_PTR);
+ Printf(s_phpclasses, "\t\t\tif (!is_resource($r)) return $r;\n");
+ if (Len(prefix) == 0) {
+ Printf(s_phpclasses, "\t\t\t$c=substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));\n");
+ } else {
+ Printf(s_phpclasses, "\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(s_phpclasses, "\t\t\treturn new $c($r);\n");
+ Printf(s_phpclasses, "\t\t}\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 {
+ // 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");
+ } 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");
+ }
+
+ 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 ( arg0->type == IS_NULL ) { /* not subclassed */\n");
+ Printf(director_prot_ctor_code, "if ( arg0->type == IS_NULL ) { /* not subclassed */\n");
+ Printf(director_ctor_code, " result = (%s *)new %s(%s);\n", 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 result = (%s *)new SwigDirector_%s(arg0%s);\n}\n", ctype, sname, args);
+ Printf(director_prot_ctor_code, "} else {\n result = (%s *)new SwigDirector_%s(arg0%s);\n}\n", 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_rsrc_list_entry *rsrc, const char *type_name TSRMLS_DC) {\n", destructorname);
+
+ Wrapper_add_localv(f, "value", "swig_object_wrapper *value=(swig_object_wrapper *) rsrc->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_ZTS_ConvertResourceData(ptr,type_name,SWIGTYPE%s TSRMLS_CC);\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);
+
+ Append(f->code, "return;\n");
+ Append(f->code, "fail:\n");
+ Append(f->code, "zend_error_noreturn(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());\n");
+ Printf(f->code, "}\n");
+
+ Wrapper_print(f, s_wrappers);
+
+ 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"));
+ 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, 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, 0, 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;
+ String *type;
+ String *name;
+ String *classname;
+ String *c_classname = Getattr(parent, "name");
+ String *declaration;
+ ParmList *l;
+ Wrapper *w;
+ String *tm;
+ String *wrap_args = NewStringEmpty();
+ String *return_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;
+ }
+ }
+
+ classname = Getattr(parent, "sym:name");
+ type = Getattr(n, "type");
+ name = Getattr(n, "name");
+
+ w = NewWrapper();
+ declaration = NewStringEmpty();
+
+ /* determine if the method returns a pointer */
+ decl = Getattr(n, "decl");
+ is_pointer = SwigType_ispointer_return(decl);
+ is_void = (Cmp(type, "void") == 0 && !is_pointer);
+
+ /* form complete return type */
+ return_type = Copy(type);
+ {
+ SwigType *t = Copy(decl);
+ SwigType *f = SwigType_pop_function(t);
+ SwigType_push(return_type, t);
+ Delete(f);
+ Delete(t);
+ }
+
+ /* virtual method definition */
+ l = Getattr(n, "parms");
+ String *target;
+ String *pclassname = NewStringf("SwigDirector_%s", classname);
+ String *qualified_name = NewStringf("%s::%s", pclassname, name);
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : type;
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ /* header declaration */
+ target = Swig_method_decl(rtype, decl, name, l, 0, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Get any exception classes in the throws typemap
+ 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 ((tm = 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) {
+ if (!(ignored_method && !pure_virtual)) {
+ String *cres = SwigType_lstr(return_type, "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();
+
+ /* remove the wrapper 'w' since it was producing spurious temps */
+ Swig_typemap_attach_parms("in", l, 0);
+ Swig_typemap_attach_parms("directorin", l, 0);
+ 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 != NULL) {
+ 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) {
+ sprintf(source, "obj%d", idx++);
+ String *input = NewStringf("&%s", source);
+ Replaceall(tm, "$input", input);
+ Delete(input);
+ Replaceall(tm, "$owner", "0");
+ Printv(wrap_args, "zval ", source, ";\n", NIL);
+ Printf(wrap_args, "args[%d] = &%s;\n", idx - 1, source);
+
+ Printv(wrap_args, tm, "\n", NIL);
+ Putc('O', parse_args);
+ } else {
+ use_parse = 1;
+ Append(parse_args, parse);
+ 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);
+ }
+ Append(w->code, "int error;\n");
+ if (!idx) {
+ Printf(w->code, "zval **args = NULL;\n", idx);
+ } else {
+ Printf(w->code, "zval *args[%d];\n", idx);
+ }
+ Append(w->code, "zval *result, funcname;\n");
+ Append(w->code, "MAKE_STD_ZVAL(result);\n");
+ Printf(w->code, "ZVAL_STRING(&funcname, (char *)\"%s\", 0);\n", name);
+ Append(w->code, "if (!swig_self) {\n");
+ Append(w->code, " SWIG_PHP_Error(E_ERROR, \"this pointer is NULL\");");
+ Append(w->code, "}\n\n");
+
+ /* wrap complex arguments to zvals */
+ Printv(w->code, wrap_args, NIL);
+
+ Append(w->code, "call_user_function(EG(function_table), (zval**)&swig_self, &funcname,\n");
+ Printf(w->code, " result, %d, args TSRMLS_CC);\n", idx);
+
+ /* exception handling */
+ tm = Swig_typemap_lookup("director:except", n, "result", 0);
+ if (!tm) {
+ tm = Getattr(n, "feature:director:except");
+ if (tm)
+ tm = Copy(tm);
+ }
+ if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
+ Replaceall(tm, "$error", "error");
+ 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) {
+ /* this seems really silly. the node's type excludes
+ * qualifier/pointer/reference markers, which have to be retrieved
+ * from the decl field to construct return_type. but the typemap
+ * lookup routine uses the node's type, so we have to swap in and
+ * out the correct type. it's not just me, similar silliness also
+ * occurs in Language::cDeclaration().
+ */
+ Setattr(n, "type", return_type);
+ tm = Swig_typemap_lookup("directorout", n, "result", w);
+ Setattr(n, "type", type);
+ if (tm != 0) {
+ Replaceall(tm, "$input", "&result");
+ 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(return_type, 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, "$input", "result");
+ Replaceall(tm, "$result", Getattr(p, "name"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ Append(w->code, "FREE_ZVAL(result);\n");
+
+ Delete(parse_args);
+ Delete(cleanup);
+ Delete(outarg);
+ }
+
+ if (!is_void) {
+ if (!(ignored_method && !pure_virtual)) {
+ String *rettype = SwigType_str(return_type, 0);
+ if (!SwigType_isreference(return_type)) {
+ 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, "zend_error_noreturn(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());\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")) {
+ 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(return_type);
+ 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" void typetrace(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_php4(void) {
+ Printf(stderr, "*** -php4 is no longer supported.\n"
+ "*** Either upgrade to PHP5 or use SWIG 1.3.36 or earlier.\n");
+ SWIG_exit(EXIT_FAILURE);
+ return NULL; // To avoid compiler warnings.
+}
+
+extern "C" Language *swig_php(void) {
+ return new_swig_php();
+}
diff --git a/Source/Modules/pike.cxx b/Source/Modules/pike.cxx
new file mode 100644
index 0000000..00e7500
--- /dev/null
+++ b/Source/Modules/pike.cxx
@@ -0,0 +1,903 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * pike.cxx
+ *
+ * Pike language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+/*
+ * Notes:
+ *
+ * - The current approach used for "out" typemaps is inconsistent with
+ * how "out" typemaps are handled by other language modules. Instead
+ * of converting the C/C++ type ($1) to a Pike object type (e.g. a
+ * struct svalue), we're just calling the appropriate push_XXX
+ * (e.g. push_int) to push the return value onto the stack.
+ *
+ * - Pike classes can't have static member functions or data, so we need
+ * to find some other appropriate mapping for C++ static member functions
+ * and data.
+ *
+ * - Pike doesn't seem to provide any default way to print the memory
+ * address, etc. for extension objects. Should we do something here?
+ *
+ */
+
+char cvsroot_pike_cxx[] = "$Id: pike.cxx 11133 2009-02-20 07:52:24Z wsfulton $";
+
+#include "swigmod.h"
+
+#include <ctype.h> // for isalnum()
+
+static const char *usage = (char *) "\
+Pike Options (available with -pike)\n\
+ [None]\n\
+\n";
+
+class PIKE:public Language {
+private:
+
+ File *f_begin;
+ File *f_runtime;
+ File *f_header;
+ File *f_wrappers;
+ File *f_init;
+ File *f_classInit;
+
+ String *PrefixPlusUnderscore;
+ int current;
+
+ // Wrap modes
+ enum {
+ NO_CPP,
+ MEMBER_FUNC,
+ CONSTRUCTOR,
+ DESTRUCTOR,
+ MEMBER_VAR,
+ CLASS_CONST,
+ STATIC_FUNC,
+ STATIC_VAR
+ };
+
+public:
+
+ /* ---------------------------------------------------------------------
+ * PIKE()
+ *
+ * Initialize member data
+ * --------------------------------------------------------------------- */
+
+ PIKE() {
+ f_begin = 0;
+ f_runtime = 0;
+ f_header = 0;
+ f_wrappers = 0;
+ f_init = 0;
+ f_classInit = 0;
+ PrefixPlusUnderscore = 0;
+ current = NO_CPP;
+ }
+
+ /* ---------------------------------------------------------------------
+ * main()
+ *
+ * Parse command line options and initializes variables.
+ * --------------------------------------------------------------------- */
+
+ virtual void main(int argc, char *argv[]) {
+
+ /* Set location of SWIG library */
+ SWIG_library_directory("pike");
+
+ /* Look for certain command line options */
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ }
+ }
+ }
+
+ /* Add a symbol to the parser for conditional compilation */
+ Preprocessor_define("SWIGPIKE 1", 0);
+
+ /* Set language-specific configuration file */
+ SWIG_config_file("pike.swg");
+
+ /* Set typemap language */
+ SWIG_typemap_lang("pike");
+
+ /* Enable overloaded methods support */
+ allow_overloading();
+ }
+
+ /* ---------------------------------------------------------------------
+ * top()
+ * --------------------------------------------------------------------- */
+
+ virtual int top(Node *n) {
+ /* Get the module name */
+ String *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_classInit = 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);
+ Swig_register_filebyname("classInit", f_classInit);
+
+ /* Standard stuff for the SWIG runtime section */
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n");
+ Printf(f_runtime, "#define SWIGPIKE\n");
+ Printf(f_runtime, "\n");
+
+ Printf(f_header, "#define SWIG_init pike_module_init\n");
+ Printf(f_header, "#define SWIG_name \"%s\"\n\n", module);
+
+ /* Change naming scheme for constructors and destructors */
+ Swig_name_register("construct", "%c_create");
+ Swig_name_register("destroy", "%c_destroy");
+
+ /* Current wrap type */
+ current = NO_CPP;
+
+ /* Emit code for children */
+ Language::top(n);
+
+ /* Close the initialization 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);
+ Dump(f_wrappers, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_classInit);
+
+ Close(f_begin);
+ Delete(f_runtime);
+ Delete(f_begin);
+
+ /* Done */
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * validIdentifier()
+ * ------------------------------------------------------------ */
+
+ virtual int validIdentifier(String *s) {
+ char *c = Char(s);
+ const char *c0 = c;
+ const char *c1 = c0 + 1;
+ while (*c) {
+ if (*c == '`' && c == c0) {
+ c++;
+ continue;
+ }
+ if ((*c == '+' || *c == '-' || *c == '*' || *c == '/') && c == c1) {
+ c++;
+ continue;
+ }
+ if (!(isalnum(*c) || (*c == '_')))
+ return 0;
+ c++;
+ }
+ return 1;
+ }
+
+ /* ------------------------------------------------------------
+ * importDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int importDirective(Node *n) {
+ String *modname = Getattr(n, "module");
+ if (modname) {
+ Printf(f_init, "pike_require(\"%s\");\n", modname);
+ }
+ return Language::importDirective(n);
+ }
+
+ /* ------------------------------------------------------------
+ * strip()
+ *
+ * For names that begin with the current class prefix plus an
+ * underscore (e.g. "Foo_enum_test"), return the base function
+ * name (i.e. "enum_test").
+ * ------------------------------------------------------------ */
+
+ String *strip(const DOHconst_String_or_char_ptr name) {
+ String *s = Copy(name);
+ if (Strncmp(name, PrefixPlusUnderscore, Len(PrefixPlusUnderscore)) != 0) {
+ return s;
+ }
+ Replaceall(s, PrefixPlusUnderscore, "");
+ return s;
+ }
+
+ /* ------------------------------------------------------------
+ * add_method()
+ * ------------------------------------------------------------ */
+
+ void add_method(const DOHconst_String_or_char_ptr name, const DOHconst_String_or_char_ptr function, const DOHconst_String_or_char_ptr description) {
+ String *rename = NULL;
+ switch (current) {
+ case NO_CPP:
+ rename = NewString(name);
+ Printf(f_init, "ADD_FUNCTION(\"%s\", %s, tFunc(%s), 0);\n", rename, function, description);
+ break;
+ case STATIC_FUNC:
+ case STATIC_VAR:
+ rename = NewString(name);
+ Printf(f_init, "ADD_FUNCTION(\"%s\", %s, tFunc(%s), 0);\n", rename, function, description);
+ break;
+ case CONSTRUCTOR:
+ case DESTRUCTOR:
+ case MEMBER_FUNC:
+ case MEMBER_VAR:
+ rename = strip(name);
+ Printf(f_classInit, "ADD_FUNCTION(\"%s\", %s, tFunc(%s), 0);\n", rename, function, description);
+ break;
+ case CLASS_CONST:
+ assert(false); // shouldn't have gotten here for CLASS_CONST nodes
+ default:
+ assert(false); // what is this?
+ }
+ Delete(rename);
+ }
+
+ /* ---------------------------------------------------------------------
+ * functionWrapper()
+ *
+ * Create a function declaration and register it with the interpreter.
+ * --------------------------------------------------------------------- */
+
+ 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");
+
+ Parm *p;
+ String *tm;
+ int i;
+
+ String *overname = 0;
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+ }
+
+ Wrapper *f = NewWrapper();
+
+ // 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 */
+ int num_arguments = emit_num_arguments(l);
+ int varargs = emit_isvarargs(l);
+
+ /* Which input argument to start with? */
+ int start = (current == MEMBER_FUNC || current == MEMBER_VAR || current == DESTRUCTOR) ? 1 : 0;
+
+ /* Offset to skip over the attribute name */
+ // int offset = (current == MEMBER_VAR) ? 1 : 0;
+ int offset = 0;
+
+ String *wname = Swig_name_wrapper(iname);
+ if (overname) {
+ Append(wname, overname);
+ }
+ Setattr(n, "wrap:name", wname);
+
+ Printv(f->def, "static void ", wname, "(INT32 args) {", NIL);
+
+ /* Generate code for argument marshalling */
+ String *description = NewString("");
+ char source[64];
+ 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");
+
+ if (i < start) {
+ String *lstr = SwigType_lstr(pt, 0);
+ Printf(f->code, "%s = (%s) THIS;\n", ln, lstr);
+ Delete(lstr);
+ } else {
+ /* Look for an input typemap */
+ sprintf(source, "Pike_sp[%d-args]", i - start + offset);
+ 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);
+ String *pikedesc = Getattr(p, "tmap:in:pikedesc");
+ if (pikedesc) {
+ Printv(description, pikedesc, " ", NIL);
+ }
+ 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;
+ }
+ }
+ p = nextSibling(p);
+ }
+
+ /* 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"))) {
+ 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);
+ }
+ }
+
+ /* Emit the function call */
+ String *actioncode = emit_action(n);
+
+ /* Clear the return stack */
+ Printf(actioncode, "pop_n_elems(args);\n");
+
+ /* Return the function value */
+ if (current == CONSTRUCTOR) {
+ Printv(actioncode, "THIS = (void *) result;\n", NIL);
+ Printv(description, ", tVoid", NIL);
+ } else if (current == DESTRUCTOR) {
+ Printv(description, ", tVoid", NIL);
+ } else {
+ Printv(description, ", ", NIL);
+ if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
+ actioncode = 0;
+ Replaceall(tm, "$source", "result");
+ Replaceall(tm, "$target", "resultobj");
+ Replaceall(tm, "$result", "resultobj");
+ if (GetFlag(n, "feature:new")) {
+ Replaceall(tm, "$owner", "1");
+ } else {
+ Replaceall(tm, "$owner", "0");
+ }
+ String *pikedesc = Getattr(n, "tmap:out:pikedesc");
+ if (pikedesc) {
+ Printv(description, pikedesc, NIL);
+ }
+ 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);
+ }
+ }
+ if (actioncode) {
+ Append(f->code, actioncode);
+ Delete(actioncode);
+ }
+ 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, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ Printf(f->code, "%s\n", tm);
+ }
+
+ /* Close the function */
+ 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", "resultobj");
+
+ /* Dump the function out */
+ Wrapper_print(f, f_wrappers);
+
+ /* Now register the function with the interpreter. */
+ if (!Getattr(n, "sym:overloaded")) {
+ add_method(iname, wname, description);
+ } else {
+ if (!Getattr(n, "sym:nextSibling")) {
+ dispatchFunction(n);
+ }
+ }
+
+ Delete(cleanup);
+ Delete(outarg);
+ Delete(description);
+ Delete(wname);
+ DelWrapper(f);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * dispatchFunction()
+ *
+ * Emit overloading dispatch function
+ * ------------------------------------------------------------ */
+
+ void dispatchFunction(Node *n) {
+ /* Last node in overloaded chain */
+
+ int maxargs;
+ String *tmp = NewString("");
+ String *dispatch = Swig_overload_dispatch(n, "%s(args); 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);
+
+ Printf(f->def, "static void %s(INT32 args) {", wname);
+
+ Wrapper_add_local(f, "argc", "INT32 argc");
+ Printf(tmp, "struct svalue argv[%d]", maxargs);
+ Wrapper_add_local(f, "argv", tmp);
+ Wrapper_add_local(f, "ii", "INT32 ii");
+
+ Printf(f->code, "argc = args;\n");
+ Printf(f->code, "for (ii = 0; (ii < argc) && (ii < %d); ii++) {\n", maxargs);
+ Printf(f->code, "argv[ii] = Pike_sp[ii-args];\n");
+ Printf(f->code, "}\n");
+
+ Replaceall(dispatch, "$args", "self, args");
+ Printv(f->code, dispatch, "\n", NIL);
+ Printf(f->code, "Pike_error(\"No matching function for overloaded '%s'.\");\n", symname);
+ Printv(f->code, "}\n", NIL);
+
+ Wrapper_print(f, f_wrappers);
+
+ String *description = NewString("");
+ Printf(description, "tAny,");
+ if (current == CONSTRUCTOR || current == DESTRUCTOR) {
+ Printf(description, " tVoid");
+ } else {
+ String *pd = Getattr(n, "tmap:out:pikedesc");
+ if (pd)
+ Printf(description, " %s", pd);
+ }
+ add_method(symname, wname, description);
+ Delete(description);
+
+ DelWrapper(f);
+ Delete(dispatch);
+ Delete(tmp);
+ Delete(wname);
+ }
+
+ /* ------------------------------------------------------------
+ * variableWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int variableWrapper(Node *n) {
+ return Language::variableWrapper(n);
+ }
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+
+ Swig_require("constantWrapper", n, "*sym:name", "type", "value", NIL);
+
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+
+ /* Special hook for member pointer */
+ if (SwigType_type(type) == T_MPOINTER) {
+ String *wname = Swig_name_wrapper(symname);
+ Printf(f_header, "static %s = %s;\n", SwigType_str(type, wname), value);
+ value = wname;
+ }
+
+ /* Perform constant typemap substitution */
+ String *tm = Swig_typemap_lookup("constant", n, value, 0);
+ if (tm) {
+ Replaceall(tm, "$source", value);
+ Replaceall(tm, "$target", symname);
+ Replaceall(tm, "$symname", symname);
+ Replaceall(tm, "$value", value);
+ 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;
+ }
+
+ /* ------------------------------------------------------------
+ * nativeWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int nativeWrapper(Node *n) {
+ // return Language::nativeWrapper(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);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * enumDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int enumDeclaration(Node *n) {
+ return Language::enumDeclaration(n);
+ }
+
+ /* ------------------------------------------------------------
+ * enumvalueDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int enumvalueDeclaration(Node *n) {
+ return Language::enumvalueDeclaration(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int classDeclaration(Node *n) {
+ return Language::classDeclaration(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int classHandler(Node *n) {
+
+ String *symname = Getattr(n, "sym:name");
+ if (!addSymbol(symname, n))
+ return SWIG_ERROR;
+
+ PrefixPlusUnderscore = NewStringf("%s_", getClassPrefix());
+
+ Printf(f_classInit, "start_new_program();\n");
+
+ /* Handle inheritance */
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist) > 0) {
+ Iterator base = First(baselist);
+ while (base.item) {
+ String *basename = Getattr(base.item, "name");
+ SwigType *basetype = NewString(basename);
+ SwigType_add_pointer(basetype);
+ SwigType_remember(basetype);
+ String *basemangle = SwigType_manglestr(basetype);
+ Printf(f_classInit, "low_inherit((struct program *) SWIGTYPE%s->clientdata, 0, 0, 0, 0, 0);\n", basemangle);
+ Delete(basemangle);
+ Delete(basetype);
+ base = Next(base);
+ }
+ } else {
+ Printf(f_classInit, "ADD_STORAGE(swig_object_wrapper);\n");
+ }
+
+ Language::classHandler(n);
+
+ /* Accessors for member variables */
+ /*
+ List *membervariables = Getattr(n,"membervariables");
+ if (membervariables && Len(membervariables) > 0) {
+ membervariableAccessors(membervariables);
+ }
+ */
+
+ /* Done, close the class and dump its definition to the init function */
+ Printf(f_classInit, "add_program_constant(\"%s\", pr = end_program(), 0);\n", symname);
+ Dump(f_classInit, f_init);
+ Clear(f_classInit);
+
+ SwigType *tt = NewString(symname);
+ SwigType_add_pointer(tt);
+ SwigType_remember(tt);
+ String *tm = SwigType_manglestr(tt);
+ Printf(f_init, "SWIG_TypeClientData(SWIGTYPE%s, (void *) pr);\n", tm);
+ Delete(tm);
+ Delete(tt);
+
+ Delete(PrefixPlusUnderscore);
+ PrefixPlusUnderscore = 0;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * memberfunctionHandler()
+ *
+ * Method for adding C++ member function
+ * ------------------------------------------------------------ */
+
+ virtual int memberfunctionHandler(Node *n) {
+ current = MEMBER_FUNC;
+ Language::memberfunctionHandler(n);
+ current = NO_CPP;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constructorHandler()
+ *
+ * Method for adding C++ member constructor
+ * ------------------------------------------------------------ */
+
+ virtual int constructorHandler(Node *n) {
+ current = CONSTRUCTOR;
+ Language::constructorHandler(n);
+ current = NO_CPP;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * destructorHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int destructorHandler(Node *n) {
+ current = DESTRUCTOR;
+ Language::destructorHandler(n);
+ current = NO_CPP;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * membervariableAccessors()
+ * ------------------------------------------------------------ */
+
+ void membervariableAccessors(List *membervariables) {
+ String *name;
+ Iterator i;
+ bool need_setter;
+ String *funcname;
+
+ /* If at least one of them is mutable, we need a setter */
+ need_setter = false;
+ i = First(membervariables);
+ while (i.item) {
+ if (!GetFlag(i.item, "feature:immutable")) {
+ need_setter = true;
+ break;
+ }
+ i = Next(i);
+ }
+
+ /* Create a function to set the values of the (mutable) variables */
+ if (need_setter) {
+ Wrapper *wrapper = NewWrapper();
+ String *setter = Swig_name_member(getClassPrefix(), (char *) "`->=");
+ String *wname = Swig_name_wrapper(setter);
+ Printv(wrapper->def, "static void ", wname, "(INT32 args) {", NIL);
+ Printf(wrapper->locals, "char *name = (char *) STR0(Pike_sp[0-args].u.string);\n");
+
+ i = First(membervariables);
+ while (i.item) {
+ if (!GetFlag(i.item, "feature:immutable")) {
+ name = Getattr(i.item, "name");
+ funcname = Swig_name_wrapper(Swig_name_set(Swig_name_member(getClassPrefix(), name)));
+ Printf(wrapper->code, "if (!strcmp(name, \"%s\")) {\n", name);
+ Printf(wrapper->code, "%s(args);\n", funcname);
+ Printf(wrapper->code, "return;\n");
+ Printf(wrapper->code, "}\n");
+ Delete(funcname);
+ }
+ i = Next(i);
+ }
+
+ /* Close the function */
+ Printf(wrapper->code, "pop_n_elems(args);\n");
+ Printf(wrapper->code, "}\n");
+
+ /* Dump wrapper code to the output file */
+ Wrapper_print(wrapper, f_wrappers);
+
+ /* Register it with Pike */
+ String *description = NewString("tStr tFloat, tVoid");
+ add_method("`->=", wname, description);
+ Delete(description);
+
+ /* Clean up */
+ Delete(wname);
+ Delete(setter);
+ DelWrapper(wrapper);
+ }
+
+ /* Create a function to get the values of the (mutable) variables */
+ Wrapper *wrapper = NewWrapper();
+ String *getter = Swig_name_member(getClassPrefix(), (char *) "`->");
+ String *wname = Swig_name_wrapper(getter);
+ Printv(wrapper->def, "static void ", wname, "(INT32 args) {", NIL);
+ Printf(wrapper->locals, "char *name = (char *) STR0(Pike_sp[0-args].u.string);\n");
+
+ i = First(membervariables);
+ while (i.item) {
+ name = Getattr(i.item, "name");
+ funcname = Swig_name_wrapper(Swig_name_get(Swig_name_member(getClassPrefix(), name)));
+ Printf(wrapper->code, "if (!strcmp(name, \"%s\")) {\n", name);
+ Printf(wrapper->code, "%s(args);\n", funcname);
+ Printf(wrapper->code, "return;\n");
+ Printf(wrapper->code, "}\n");
+ Delete(funcname);
+ i = Next(i);
+ }
+
+ /* Close the function */
+ Printf(wrapper->code, "pop_n_elems(args);\n");
+ Printf(wrapper->code, "}\n");
+
+ /* Dump wrapper code to the output file */
+ Wrapper_print(wrapper, f_wrappers);
+
+ /* Register it with Pike */
+ String *description = NewString("tStr, tMix");
+ add_method("`->", wname, description);
+ Delete(description);
+
+ /* Clean up */
+ Delete(wname);
+ Delete(getter);
+ DelWrapper(wrapper);
+ }
+
+ /* ------------------------------------------------------------
+ * membervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int membervariableHandler(Node *n) {
+ List *membervariables = Getattr(getCurrentClass(), "membervariables");
+ if (!membervariables) {
+ membervariables = NewList();
+ Setattr(getCurrentClass(), "membervariables", membervariables);
+ }
+ Append(membervariables, n);
+ current = MEMBER_VAR;
+ Language::membervariableHandler(n);
+ current = NO_CPP;
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ *
+ * Wrap a static C++ function
+ * ---------------------------------------------------------------------- */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ current = STATIC_FUNC;
+ Language::staticmemberfunctionHandler(n);
+ current = NO_CPP;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * memberconstantHandler()
+ *
+ * Create a C++ constant
+ * ------------------------------------------------------------ */
+
+ virtual int memberconstantHandler(Node *n) {
+ current = CLASS_CONST;
+ constantWrapper(n);
+ current = NO_CPP;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------
+ * staticmembervariableHandler()
+ * --------------------------------------------------------------------- */
+
+ virtual int staticmembervariableHandler(Node *n) {
+ current = STATIC_VAR;
+ Language::staticmembervariableHandler(n);
+ current = NO_CPP;
+ return SWIG_OK;
+ }
+};
+
+/* -----------------------------------------------------------------------------
+ * swig_pike() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_pike() {
+ return new PIKE();
+}
+extern "C" Language *swig_pike(void) {
+ return new_swig_pike();
+}
diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx
new file mode 100644
index 0000000..83df3aa
--- /dev/null
+++ b/Source/Modules/python.cxx
@@ -0,0 +1,4067 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * python.cxx
+ *
+ * Python language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_python_cxx[] = "$Id: python.cxx 11518 2009-08-08 22:56:10Z wsfulton $";
+
+#include "swigmod.h"
+#include "cparse.h"
+
+static int treduce = SWIG_cparse_template_reduce(0);
+
+#include <ctype.h>
+
+#define PYSHADOW_MEMBER 0x2
+
+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 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_imports = 0;
+static String *f_shadow_stubs = 0;
+
+static String *methods;
+static String *class_name;
+static String *shadow_indent = 0;
+static int in_class = 0;
+static int classic = 0;
+static int modern = 0;
+static int new_repr = 1;
+static int no_header_file = 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;
+static int classptr = 0;
+/* Other options */
+static int shadowimport = 1;
+static int buildnone = 0;
+static int nobuildnone = 0;
+static int safecstrings = 0;
+static int dirvtable = 0;
+static int proxydel = 1;
+static int fastunpack = 0;
+static int fastproxy = 0;
+static int fastquery = 0;
+static int fastinit = 0;
+static int olddefs = 0;
+static int modernargs = 0;
+static int aliasobj0 = 0;
+static int castmode = 0;
+static int extranative = 0;
+static int outputtuple = 0;
+static int nortti = 0;
+
+/* flags for the make_autodoc function */
+enum autodoc_t {
+ AUTODOC_CLASS,
+ AUTODOC_CTOR,
+ AUTODOC_DTOR,
+ AUTODOC_STATICFUNC,
+ AUTODOC_FUNC,
+ AUTODOC_METHOD
+};
+
+
+static const char *usage1 = (char *) "\
+Python Options (available with -python)\n\
+ -aliasobj0 - Alias obj0 when using fastunpack, needed for some old typemaps \n\
+ -buildnone - Use Py_BuildValue(" ") to obtain Py_None (default in Windows)\n\
+ -castmode - Enable the casting mode, which allows implicit cast between types in python\n\
+ -classic - Use classic classes only\n\
+ -classptr - Generate shadow 'ClassPtr' as in older swig versions\n\
+ -cppcast - Enable C++ casting operators (default) \n\
+ -dirvtable - Generate a pseudo virtual table for directors for faster dispatch \n\
+ -extranative - Return extra native C++ wraps for std containers when possible \n\
+ -fastinit - Use fast init mechanism for classes (default)\n\
+ -fastunpack - Use fast unpack mechanism to parse the argument functions \n\
+ -fastproxy - Use fast proxy mechanism for member methods \n\
+ -fastquery - Use fast query mechanism for types \n\
+ -globals <name> - Set <name> used to access C global variable [default: 'cvar']\n\
+ -interface <lib>- Set the lib name to <lib>\n\
+ -keyword - Use keyword arguments\n\
+ -modern - Use modern python features only, without compatibility code\n\
+ -modernargs - Use \"modern\" args mechanism to pack/unpack the function arguments\n";
+static const char *usage2 = (char *) "\
+ -newrepr - Use more informative version of __repr__ in proxy classes (default) \n\
+ -newvwm - New value wrapper mode, use only when everything else fails \n\
+ -noaliasobj0 - Don't generate an obj0 alias when using fastunpack (default) \n\
+ -nobuildnone - Access Py_None directly (default in non-Windows systems)\n\
+ -nocastmode - Disable the casting mode (default)\n\
+ -nocppcast - Disable C++ casting operators, useful for generating bugs\n\
+ -nodirvtable - Don't use the virtual table feature, resolve the python method each time (default)\n\
+ -noexcept - No automatic exception handling\n\
+ -noextranative - Don't use extra native C++ wraps for std containers when possible (default) \n\
+ -nofastinit - Use traditional init mechanism for classes \n\
+ -nofastunpack - Use traditional UnpackTuple method to parse the argument functions (default) \n\
+ -nofastproxy - Use traditional proxy mechanism for member methods (default) \n\
+ -nofastquery - Use traditional query mechanism for types (default) \n\
+ -noh - Don't generate the output header file\n\
+ -nomodern - Don't use modern python features which are not back compatible \n\
+ -nomodernargs - Use classic ParseTuple/CallFunction methods to pack/unpack the function arguments (default) \n";
+static const char *usage3 = (char *) "\
+ -noolddefs - Don't emit the old method definitions even when using fastproxy (default) \n\
+ -nooutputtuple - Use a PyList for appending output values (default) \n\
+ -noproxy - Don't generate proxy classes \n\
+ -noproxydel - Don't generate the redundant __del__ method \n\
+ -noproxyimport - Don't insert proxy import statements derived from the %import directive \n\
+ -nortti - Disable the use of the native C++ RTTI with directors\n\
+ -nosafecstrings - Avoid extra strings copies when possible (default)\n\
+ -nothreads - Disable thread support for the entire interface\n\
+ -olddefs - Keep the old method definitions even when using fastproxy\n\
+ -oldrepr - Use shorter and old version of __repr__ in proxy classes\n\
+ -outputtuple - Use a PyTuple for outputs instead of a PyList (use carefully with legacy interfaces) \n\
+ -proxydel - Generate a __del__ method even though it is now redundant (default) \n\
+ -safecstrings - Use safer (but slower) C string mapping, generating copies from Python -> C/C++\n\
+ -threads - Add thread support for all the interface\n\
+ -O - Enable all the optimization options: \n\
+ -modern -fastdispatch -dirvtable -nosafecstrings -fvirtual -noproxydel \n\
+ -fastproxy -fastinit -fastunpack -fastquery -modernargs -nobuildnone \n\
+ -py3 - Generate code with Python 3 specific features:\n\
+ Function annotation \n\
+\n";
+
+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;
+ }
+
+ /* ------------------------------------------------------------
+ * 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");
+ 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");
+ if (eb) {
+ Append(f, eb);
+ } else {
+ Append(f, "SWIG_PYTHON_THREAD_END_ALLOW;\n");
+ }
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+ int cppcast = 1;
+
+ SWIG_library_directory("python");
+
+ 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], "-new_repr") == 0) || (strcmp(argv[i], "-newrepr") == 0)) {
+ new_repr = 1;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-old_repr") == 0) || (strcmp(argv[i], "-oldrepr") == 0)) {
+ new_repr = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-classptr") == 0) {
+ classptr = 1;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-noproxy") == 0)) {
+ shadow = 0;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-noproxyimport") == 0)) {
+ shadowimport = 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], "-classic") == 0) {
+ classic = 1;
+ modernargs = 0;
+ modern = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-cppcast") == 0) {
+ cppcast = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocppcast") == 0) {
+ cppcast = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-outputtuple") == 0) {
+ outputtuple = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nooutputtuple") == 0) {
+ outputtuple = 0;
+ 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 suppor mode */
+ nothreads = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-safecstrings") == 0) {
+ safecstrings = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nosafecstrings") == 0) {
+ safecstrings = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-buildnone") == 0) {
+ buildnone = 1;
+ nobuildnone = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nobuildnone") == 0) {
+ buildnone = 0;
+ nobuildnone = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-dirvtable") == 0) {
+ dirvtable = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nodirvtable") == 0) {
+ dirvtable = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-fastunpack") == 0) {
+ fastunpack = 1;
+ 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], "-nofastproxy") == 0) {
+ fastproxy = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-fastquery") == 0) {
+ fastquery = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nofastquery") == 0) {
+ fastquery = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-fastinit") == 0) {
+ fastinit = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nofastinit") == 0) {
+ fastinit = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-olddefs") == 0) {
+ olddefs = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-noolddefs") == 0) {
+ olddefs = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-castmode") == 0) {
+ castmode = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocastmode") == 0) {
+ castmode = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-extranative") == 0) {
+ extranative = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-noextranative") == 0) {
+ extranative = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-modernargs") == 0) {
+ modernargs = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nomodernargs") == 0) {
+ modernargs = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-aliasobj0") == 0) {
+ aliasobj0 = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-noaliasobj0") == 0) {
+ aliasobj0 = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-proxydel") == 0) {
+ proxydel = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-noproxydel") == 0) {
+ proxydel = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-modern") == 0) {
+ classic = 0;
+ modern = 1;
+ modernargs = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nomodern") == 0) {
+ modern = 0;
+ modernargs = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-noh") == 0) {
+ no_header_file = 1;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-new_vwm") == 0) || (strcmp(argv[i], "-newvwm") == 0)) {
+ /* Turn on new value wrapper mpde */
+ Swig_value_wrapper_mode(1);
+ no_header_file = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-O") == 0) {
+ classic = 0;
+ modern = 1;
+ dirvtable = 1;
+ safecstrings = 0;
+ buildnone = 0;
+ nobuildnone = 1;
+ classptr = 0;
+ proxydel = 0;
+ fastunpack = 1;
+ fastproxy = 1;
+ fastinit = 1;
+ fastquery = 1;
+ modernargs = 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;
+ Swig_mark_arg(i);
+ }
+
+ }
+ } /* for */
+
+ if (py3) {
+ /* force disable features that not compatible with Python 3.x */
+ classic = 0;
+ }
+
+ if (cppcast) {
+ Preprocessor_define((DOH *) "SWIG_CPLUSPLUS_CAST", 0);
+ }
+
+ 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;
+ {
+ 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")) {
+ castmode = 0;
+ }
+ if (Getattr(options, "extranative")) {
+ extranative = 1;
+ }
+ if (Getattr(options, "noextranative")) {
+ extranative = 0;
+ }
+ if (Getattr(options, "outputtuple")) {
+ outputtuple = 1;
+ }
+ if (Getattr(options, "nooutputtuple")) {
+ outputtuple = 0;
+ }
+ mod_docstring = Getattr(options, "docstring");
+ package = Getattr(options, "package");
+ }
+ }
+ }
+
+ /* 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("");
+
+ 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("");
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n");
+ Printf(f_runtime, "#define SWIGPYTHON\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 (safecstrings) {
+ Printf(f_runtime, "#define SWIG_PYTHON_SAFE_CSTRINGS\n");
+ }
+
+ if (buildnone) {
+ Printf(f_runtime, "#define SWIG_PYTHON_BUILD_NONE\n");
+ }
+
+ if (nobuildnone) {
+ Printf(f_runtime, "#define SWIG_PYTHON_NO_BUILD_NONE\n");
+ }
+
+ if (!dirvtable) {
+ Printf(f_runtime, "#define SWIG_PYTHON_DIRECTOR_NO_VTABLE\n");
+ }
+
+ if (outputtuple) {
+ Printf(f_runtime, "#define SWIG_PYTHON_OUTPUT_TUPLE\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 (classic) {
+ Printf(f_runtime, "#define SWIG_PYTHON_CLASSIC\n");
+ }
+
+ Printf(f_runtime, "\n");
+
+ Printf(f_header, "#if (PY_VERSION_HEX <= 0x02000000)\n");
+ Printf(f_header, "# if !defined(SWIG_PYTHON_CLASSIC)\n");
+ Printf(f_header, "# error \"This python version requires swig to be run with the '-classic' option\"\n");
+ Printf(f_header, "# endif\n");
+ Printf(f_header, "#endif\n");
+
+ if (modern) {
+ Printf(f_header, "#if (PY_VERSION_HEX <= 0x02020000)\n");
+ Printf(f_header, "# error \"This python version requires swig to be run with the '-nomodern' option\"\n");
+ Printf(f_header, "#endif\n");
+ }
+
+ if (modernargs) {
+ Printf(f_header, "#if (PY_VERSION_HEX <= 0x02020000)\n");
+ Printf(f_header, "# error \"This python version requires swig to be run with the '-nomodernargs' option\"\n");
+ Printf(f_header, "#endif\n");
+ }
+
+ if (fastunpack) {
+ Printf(f_header, "#ifndef METH_O\n");
+ Printf(f_header, "# error \"This python version requires swig to be run with the '-nofastunpack' option\"\n");
+ Printf(f_header, "#endif\n");
+ }
+
+ if (fastquery) {
+ 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)
+ Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h));
+ }
+
+ /* If shadow classing is enabled, we're going to change the module name to "_module" */
+ 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_imports = NewString("");
+ f_shadow_stubs = NewString("");
+
+ Swig_register_filebyname("shadow", f_shadow);
+ Swig_register_filebyname("python", f_shadow);
+
+ Swig_banner_target_lang(f_shadow, "#");
+
+ if (!modern) {
+ Printv(f_shadow, "# This file is compatible with both classic and new-style classes.\n", NIL);
+ }
+
+ if (mod_docstring && Len(mod_docstring)) {
+ Printv(f_shadow, "\n\"\"\"\n", mod_docstring, "\n\"\"\"\n", NIL);
+ Delete(mod_docstring);
+ mod_docstring = NULL;
+ }
+
+ Printv(f_shadow, "\nfrom sys import version_info\n", NULL);
+
+ if(fastproxy)
+ {
+ Printv(f_shadow, "if version_info >= (3,0,0):\n", NULL);
+ Printf(f_shadow, tab4 "new_instancemethod = lambda func, inst, cls: %s.SWIG_PyInstanceMethod_New(func)\n", module);
+ Printv(f_shadow, "else:\n", NULL);
+ Printv(f_shadow, tab4, "from new import instancemethod as new_instancemethod\n", NULL);
+ }
+ /* Import the C-extension 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 C-extension is on
+ * sys.path. Relative imports must be explicitly specified from 2.6.0
+ * onwards (implicit relative imports will raise a DeprecationWarning
+ * in 2.6, and fail in 2.7 onwards), but the relative import syntax
+ * isn't available in python 2.4 or earlier, so we have to write some
+ * code conditional on the python version.
+ */
+ Printv(f_shadow, "if version_info >= (2,6,0):\n", NULL);
+ Printv(f_shadow, tab4, "def swig_import_helper():\n", NULL);
+ Printv(f_shadow, tab8, "from os.path import dirname\n", NULL);
+ Printv(f_shadow, tab8, "import imp\n", NULL);
+ Printv(f_shadow, tab8, "fp = None\n", NULL);
+ Printv(f_shadow, tab8, "try:\n", NULL);
+ Printf(f_shadow, tab4 tab8 "fp, pathname, description = imp.find_module('%s', [dirname(__file__)])\n", module);
+ Printf(f_shadow, tab8 "except ImportError:\n");
+ /* At here, the module may already loaded, so simply import it. */
+ Printf(f_shadow, tab4 tab8 "import %s\n", module);
+ Printf(f_shadow, tab4 tab8 "return %s\n", module);
+ Printv(f_shadow, tab8 "if fp is not None:\n", NULL);
+ Printv(f_shadow, tab4 tab8 "try:\n", NULL);
+ Printf(f_shadow, tab8 tab8 "_mod = imp.load_module('%s', fp, pathname, description)\n", module);
+ Printv(f_shadow, tab4 tab8, "finally:\n", NULL);
+ Printv(f_shadow, tab8 tab8, "fp.close()\n", NULL);
+ Printv(f_shadow, tab4 tab8, "return _mod\n", NULL);
+ Printf(f_shadow, tab4 "%s = swig_import_helper()\n", module);
+ Printv(f_shadow, tab4, "del swig_import_helper\n", NULL);
+ Printv(f_shadow, "else:\n", NULL);
+ Printf(f_shadow, tab4 "import %s\n", module);
+
+ /* Delete the version_info symbol since we don't use it elsewhere in the
+ * module. */
+ Printv(f_shadow, "del version_info\n", NULL);
+
+ if (modern || !classic) {
+ Printv(f_shadow, "try:\n", tab4, "_swig_property = property\n", "except NameError:\n", tab4, "pass # Python < 2.2 doesn't have 'property'.\n", NULL);
+ }
+ /* if (!modern) */
+ /* always needed, a class can be forced to be no-modern, such as an exception */
+ {
+ // Python-2.2 object hack
+ Printv(f_shadow,
+ "def _swig_setattr_nondynamic(self,class_type,name,value,static=1):\n",
+ tab4, "if (name == \"thisown\"): return self.this.own(value)\n",
+ tab4, "if (name == \"this\"):\n", tab4, tab4, "if type(value).__name__ == 'SwigPyObject':\n", tab4, tab8, "self.__dict__[name] = value\n",
+#ifdef USE_THISOWN
+ tab4, tab8, "if hasattr(value,\"thisown\"): self.__dict__[\"thisown\"] = value.thisown\n", tab4, tab8, "del value.thisown\n",
+#endif
+ tab4, tab8, "return\n", tab4, "method = class_type.__swig_setmethods__.get(name,None)\n", tab4, "if method: return method(self,value)\n",
+#ifdef USE_THISOWN
+ tab4, "if (not static) or hasattr(self,name) or (name == \"thisown\"):\n",
+#else
+ tab4, "if (not static) or hasattr(self,name):\n",
+#endif
+ tab4, tab4, "self.__dict__[name] = value\n",
+ tab4, "else:\n",
+ tab4, tab4, "raise AttributeError(\"You cannot add attributes to %s\" % self)\n\n",
+ "def _swig_setattr(self,class_type,name,value):\n", tab4, "return _swig_setattr_nondynamic(self,class_type,name,value,0)\n\n", NIL);
+
+ Printv(f_shadow,
+ "def _swig_getattr(self,class_type,name):\n",
+ tab4, "if (name == \"thisown\"): return self.this.own()\n",
+ tab4, "method = class_type.__swig_getmethods__.get(name,None)\n",
+ tab4, "if method: return method(self)\n", tab4, "raise AttributeError(name)\n\n", NIL);
+
+ Printv(f_shadow,
+ "def _swig_repr(self):\n",
+ tab4, "try: strthis = \"proxy of \" + self.this.__repr__()\n",
+ tab4, "except: strthis = \"\"\n", tab4, "return \"<%s.%s; %s >\" % (self.__class__.__module__, self.__class__.__name__, strthis,)\n\n", NIL);
+
+ if (!classic) {
+ /* Usage of types.ObjectType is deprecated.
+ * But don't sure wether this would broken old Python?
+ */
+ Printv(f_shadow,
+// "import types\n",
+ "try:\n",
+// " _object = types.ObjectType\n",
+ " _object = object\n",
+ " _newclass = 1\n", "except AttributeError:\n", " class _object : pass\n", " _newclass = 0\n",
+// "del types\n",
+ "\n\n", NIL);
+ }
+ }
+ if (modern) {
+ Printv(f_shadow, "def _swig_setattr_nondynamic_method(set):\n", tab4, "def set_attr(self,name,value):\n",
+#ifdef USE_THISOWN
+ tab4, tab4, "if hasattr(self,name) or (name in (\"this\", \"thisown\")):\n",
+#else
+ tab4, tab4, "if (name == \"thisown\"): return self.this.own(value)\n", tab4, tab4, "if hasattr(self,name) or (name == \"this\"):\n",
+#endif
+ tab4, tab4, tab4, "set(self,name,value)\n",
+ tab4, tab4, "else:\n",
+ tab4, tab4, tab4, "raise AttributeError(\"You cannot add attributes to %s\" % self)\n", tab4, "return set_attr\n\n\n", NIL);
+ }
+
+ if (directorsEnabled()) {
+ // Try loading weakref.proxy, which is only available in Python 2.1 and higher
+ Printv(f_shadow,
+ "try:\n", tab4, "import weakref\n", tab4, "weakref_proxy = weakref.proxy\n", "except:\n", tab4, "weakref_proxy = lambda x: x\n", "\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");
+
+ /* the method exported for replacement of new.instancemethod in Python 3 */
+ add_pyinstancemethod_new();
+
+ /* 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.swg", f_runtime);
+ }
+
+ /* Close language module */
+ Append(methods, "\t { NULL, NULL, 0, NULL }\n");
+ Append(methods, "};\n");
+ Printf(f_wrappers, "%s\n", methods);
+
+ 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) {
+ Printv(f_shadow_py, f_shadow, "\n", NIL);
+ Printv(f_shadow_py, f_shadow_stubs, "\n", NIL);
+
+ Close(f_shadow_py);
+ 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)
+ Close(f_runtime_h);
+ 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);
+
+ Close(f_begin);
+ 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");
+ Printf(methods, "\t { (char *)\"%s\", (PyCFunction)%s, METH_O, NULL},\n", name, name);
+ Delete(name);
+ return 0;
+ }
+
+ /* ------------------------------------------------------------
+ * importDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int importDirective(Node *n) {
+ if (shadow) {
+ String *modname = Getattr(n, "module");
+
+ if (modname) {
+ String *import = NewString("import ");
+
+ // 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);
+
+ // 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 *options = Getattr(mod, "options");
+ String *pkg = options ? Getattr(options, "package") : 0;
+ if (pkg && (!package || Strcmp(pkg, package) != 0)) {
+ Printf(import, "%s.", pkg);
+ }
+ // finally, output the name of the imported module
+ if (shadowimport) {
+ if (!options || (!Getattr(options, "noshadow") && !Getattr(options, "noproxy"))) {
+ Printf(import, "_%s\n", modname);
+ if (!Strstr(f_shadow_imports, import)) {
+ if (pkg && (!package || Strcmp(pkg, package) != 0)) {
+ Printf(f_shadow, "import %s.%s\n", pkg, modname);
+ } else {
+ Printf(f_shadow, "import %s\n", modname);
+ }
+ Printv(f_shadow_imports, import, NULL);
+ }
+ }
+ }
+
+ 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;
+ }
+
+
+ /* ------------------------------------------------------------
+ * pythoncode() - Output python code into the shadow file
+ * ------------------------------------------------------------ */
+
+ String *pythoncode(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 = DohSplitLines(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;
+ }
+
+
+ /* ------------------------------------------------------------
+ * 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;
+ if (autodoc) {
+ char *c = Char(autodoc);
+ if (c && 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 != NULL && Len(str) > 0) || (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc"));
+ }
+
+ /* ------------------------------------------------------------
+ * docstring()
+ * Get the docstring text, stripping off {} if neccessary,
+ * 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 use_triple = true) {
+ String *str = Getattr(n, "feature:docstring");
+ bool have_ds = (str != NULL && Len(str) > 0);
+ bool have_auto = (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc"));
+ const char *triple_double = use_triple ? "\"\"\"" : "";
+ 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 != NULL && Len(autodoc) > 0);
+ }
+ // 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 (have_auto && have_ds) { // Both autodoc and docstring are present
+ doc = NewString("");
+ Printv(doc, triple_double, "\n", pythoncode(autodoc, indent), "\n", pythoncode(str, indent), indent, triple_double, NIL);
+ } else if (!have_auto && have_ds) { // only docstring
+ if (Strchr(str, '\n') == NULL) {
+ doc = NewStringf("%s%s%s", triple_double, str, triple_double);
+ } else {
+ doc = NewString("");
+ Printv(doc, triple_double, "\n", pythoncode(str, indent), indent, triple_double, NIL);
+ }
+ } else if (have_auto && !have_ds) { // only autodoc
+ if (Strchr(autodoc, '\n') == NULL) {
+ doc = NewStringf("%s%s%s", triple_double, autodoc, triple_double);
+ } else {
+ doc = NewString("");
+ Printv(doc, triple_double, "\n", pythoncode(autodoc, indent), indent, triple_double, NIL);
+ }
+ } else
+ doc = NewString("");
+
+ // Save the generated strings in the parse tree in case they are used later
+ // by post processing tools
+ Setattr(n, "python:docstring", doc);
+ Setattr(n, "python:autodoc", autodoc);
+ return doc;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * makeParameterName()
+ * Note: the generated name should consist with that in kwnames[]
+ *
+ * Inputs:
+ * n - Node
+ * p - parameter node
+ * arg_num - parameter argument number
+ * Return:
+ * arg - a unique parameter name
+ * ----------------------------------------------------------------------------- */
+
+ String *makeParameterName(ParmList *plist, Parm *p, int arg_num) {
+ String *arg = 0;
+ String *pn = Swig_name_make(p, 0, Getattr(p, "name"), 0, 0);
+ // Use C parameter name unless it is a duplicate or an empty parameter name
+ int count = 0;
+ if ( SwigType_isvarargs(Getattr(p, "type")) ) {
+ return NewString("*args");
+ }
+ while (plist) {
+ if ((Cmp(pn, Getattr(plist, "name")) == 0))
+ count++;
+ plist = nextSibling(plist);
+ }
+ arg = (!pn || !Len(pn) || (count > 1)) ? NewStringf("arg%d", arg_num) : Copy(pn);
+ return arg;
+ }
+
+
+ /* ------------------------------------------------------------
+ * make_autodocParmList()
+ * Generate the documentation for the function parameters
+ * Parameters:
+ * func_annotation: Function annotation support
+ * ------------------------------------------------------------ */
+
+ String *make_autodocParmList(Node *n, bool showTypes, bool calling=false, bool func_annotation=false) {
+
+
+ String *doc = NewString("");
+ String *pdocs = Copy(Getattr(n, "feature:pdocs"));
+ ParmList *plist = CopyParmList(Getattr(n, "parms"));
+ Parm *p;
+ Parm *pnext;
+ Node *lookup;
+
+
+ int lines = 0;
+ int arg_num = 0;
+ const int maxwidth = 50;
+
+ if(calling)
+ func_annotation = false;
+
+ if (pdocs)
+ Append(pdocs, "\n");
+
+ 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 *ptype = 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");
+ ptype = Getattr(p, "tmap:doc:pytype");
+ }
+
+ name = name ? name : Getattr(p, "name");
+ type = type ? type : Getattr(p, "type");
+ value = value ? value : Getattr(p, "value");
+
+ name = makeParameterName(plist, p, arg_num);
+ // Reset it for convinient in further use. (mainly for makeParameterName())
+ // Since the plist is created by CopyParmList,
+ // we can hope that the set would have no side effect
+ Setattr(p, "name", name);
+
+ arg_num++;
+
+
+ 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;
+ }
+ }
+
+ type = SwigType_base(type);
+ lookup = Swig_symbol_clookup(type, 0);
+ if (lookup)
+ type = Getattr(lookup, "sym:name");
+
+ // Do the param type too?
+ if (showTypes)
+ Printf(doc, "%s ", type);
+
+
+ Append(doc, name);
+ if (pdoc) {
+ if (!pdocs)
+ pdocs = NewString("Parameters:\n");
+ Printf(pdocs, " %s\n", pdoc);
+ }
+
+ // Write the function annoation
+ if (func_annotation)
+ Printf(doc, " : '%s'", type);
+
+ // Write default value
+ if (value && !calling) {
+ String* pv = pyvalue(value, Getattr(p, "type"));
+ if (pv)
+ value = pv;
+ else {
+ lookup = Swig_symbol_clookup(value, 0);
+ if (lookup) {
+ value = Getattr(lookup, "sym:name");
+ }
+ }
+ Printf(doc, " = %s", value);
+ }
+ }
+ 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 funciton 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) {
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+
+ if (type) {
+ if (Strcmp(type, "void") == 0)
+ type = NULL;
+ else {
+ type = SwigType_base(type);
+ Node *lookup = Swig_symbol_clookup(type, 0);
+ if (lookup)
+ type = Getattr(lookup, "sym:name");
+ }
+ }
+
+ 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 == NULL || Len(str) == 0) {
+ if (CPlusPlus) {
+ Printf(doc, "Proxy of C++ %s class", real_classname);
+ } else {
+ Printf(doc, "Proxy of C %s struct", real_classname);
+ }
+ }
+ }
+ break;
+ case AUTODOC_CTOR:
+ if (Strcmp(class_name, symname) == 0) {
+ String *paramList = make_autodocParmList(n, showTypes);
+ if (Len(paramList))
+ Printf(doc, "__init__(self, %s) -> %s", paramList, class_name);
+ else
+ Printf(doc, "__init__(self) -> %s", class_name);
+ } else
+ Printf(doc, "%s(%s) -> %s", symname, make_autodocParmList(n, showTypes), class_name);
+ break;
+
+ case AUTODOC_DTOR:
+ Append(doc, "__del__(self)");
+ break;
+
+ case AUTODOC_STATICFUNC:
+ Printf(doc, "%s(%s)", symname, make_autodocParmList(n, showTypes));
+ if (type)
+ Printf(doc, " -> %s", type);
+ break;
+
+ case AUTODOC_FUNC:
+ Printf(doc, "%s(%s)", symname, make_autodocParmList(n, showTypes));
+ if (type)
+ Printf(doc, " -> %s", type);
+ break;
+
+ case AUTODOC_METHOD:
+ String *paramList = make_autodocParmList(n, showTypes);
+ if (Len(paramList))
+ Printf(doc, "%s(self, %s)", symname, paramList);
+ else
+ Printf(doc, "%s(self)", symname);
+ if (type)
+ Printf(doc, " -> %s", type);
+ break;
+ }
+ }
+ if (extended) {
+ 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)
+ Append(doc, "\n");
+ }
+
+ return doc;
+ }
+
+ /* ------------------------------------------------------------
+ * pyvalue()
+ * Check if string v can be a Python value literal,
+ * (eg. number or string), or translate it to a Python literal.
+ * ------------------------------------------------------------ */
+ String* pyvalue(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, "true")==0 || Strcmp(v, "FALSE")==0)
+ return NewString("True");
+ if (Strcmp(v, "false")==0 || Strcmp(v, "FALSE")==0)
+ return NewString("False");
+ if (Strcmp(v, "NULL")==0)
+ return NewString("None");
+ }
+ return 0;
+ }
+ /* ------------------------------------------------------------
+ * is_primitive_defaultargs()
+ * Check if all the default args have primitive type.
+ * (So we can generate proper parameter list with default
+ * values..)
+ * ------------------------------------------------------------ */
+ bool is_primitive_defaultargs(Node *n)
+ {
+ ParmList *plist = CopyParmList(Getattr(n, "parms"));
+ Parm *p;
+ Parm *pnext;
+
+ Swig_typemap_attach_parms("in", plist, 0);
+ 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 *type = Getattr(p, "type");
+ String *value = Getattr(p, "value");
+ if (!pyvalue(value, type))
+ return false;
+ }
+ return true;
+ }
+
+
+ /* ------------------------------------------------------------
+ * is_real_overloaded()
+ * Check if the function is overloaded, but not just have some
+ * siblings generated due to the original function have
+ * 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)
+ {
+ /* Get the original function for a defaultargs copy,
+ * see default_arguments() in parser.y. */
+ Node *nn = Getattr(n, "defaultargs");
+ if (nn) n = nn;
+
+ /* For overloaded function, just use *args */
+ if (is_real_overloaded(n) ||
+ GetFlag(n, "feature:compactdefaultargs") ||
+ !is_primitive_defaultargs(n))
+ {
+ 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, 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 != NULL && Len(str) > 0);
+ }
+
+ /* ------------------------------------------------------------
+ * pythonprepend()
+ * Get the %pythonprepend code, stripping off {} if neccessary
+ * ------------------------------------------------------------ */
+
+ 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 != NULL && Len(str) > 0);
+ }
+
+ /* ------------------------------------------------------------
+ * pythonappend()
+ * Get the %pythonappend code, stripping off {} if neccessary
+ * ------------------------------------------------------------ */
+
+ 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) || have_docstring(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);
+ /* Make a wrapper function to insert the code into */
+ Printv(f_dest, "\ndef ", name, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
+ if (have_docstring(n))
+ Printv(f_dest, " ", docstring(n, AUTODOC_FUNC, tab4), "\n", NIL);
+ if (have_pythonprepend(n))
+ Printv(f_dest, pythoncode(pythonprepend(n), " "), "\n", NIL);
+ if (have_pythonappend(n)) {
+ Printv(f_dest, " val = ", funcCall(name, callParms), "\n", NIL);
+ Printv(f_dest, pythoncode(pythonappend(n), " "), "\n", NIL);
+ Printv(f_dest, " return val\n", NIL);
+ } else {
+ Printv(f_dest, " return ", funcCall(name, callParms), "\n", NIL);
+ }
+
+ if (Getattr(n, "feature:python:callback") || !have_addtofunc(n)) {
+ /* 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) {
+ 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) {
+ if (!kw) {
+ if (n && funpack) {
+ if (num_required == 0 && num_arguments == 0) {
+ Printf(methods, "\t { (char *)\"%s\", (PyCFunction)%s, METH_NOARGS, ", name, function);
+ } else if (num_required == 1 && num_arguments == 1) {
+ Printf(methods, "\t { (char *)\"%s\", (PyCFunction)%s, METH_O, ", name, function);
+ } else {
+ Printf(methods, "\t { (char *)\"%s\", %s, METH_VARARGS, ", name, function);
+ }
+ } else {
+ Printf(methods, "\t { (char *)\"%s\", %s, METH_VARARGS, ", name, function);
+ }
+ } else {
+ Printf(methods, "\t { (char *)\"%s\", (PyCFunction) %s, METH_VARARGS | METH_KEYWORDS, ", name, function);
+ }
+
+ if (!n) {
+ Append(methods, "NULL");
+ } else if (Getattr(n, "feature:callback")) {
+ if (have_docstring(n)) {
+ String *ds = docstring(n, AUTODOC_FUNC, "", false);
+ Replaceall(ds, "\\", "\\\\");
+ Replaceall(ds, "\"", "\\\"");
+ Replaceall(ds, "\n", "\\n\"\n\t\t\"");
+ Printf(methods, "(char *)\"%s\\nswig_ptr: %s\"", ds, Getattr(n, "feature:callback:name"));
+ } else {
+ Printf(methods, "(char *)\"swig_ptr: %s\"", Getattr(n, "feature:callback:name"));
+ }
+ } else if (have_docstring(n)) {
+ String *ds = docstring(n, AUTODOC_FUNC, "", false);
+ Replaceall(ds, "\\", "\\\\");
+ Replaceall(ds, "\"", "\\\"");
+ Replaceall(ds, "\n", "\\n\"\n\t\t\"");
+ Printf(methods, "(char *)\"%s\"", ds);
+ } else {
+ Append(methods, "NULL");
+ }
+
+ Append(methods, "},\n");
+ }
+
+ /* ------------------------------------------------------------
+ * dispatchFunction()
+ * ------------------------------------------------------------ */
+ void dispatchFunction(Node *n, int funpack = 0) {
+ /* Last node in overloaded chain */
+
+ int maxargs;
+
+ String *tmp = NewString("");
+ String *dispatch;
+ const char *dispatch_code = funpack ? "return %s(self, argc, argv);" : "return %s(self, args);";
+
+ if (castmode) {
+ dispatch = Swig_overload_dispatch_cast(n, dispatch_code, &maxargs);
+ } else {
+ dispatch = Swig_overload_dispatch(n, dispatch_code, &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 PyObject *", wname, "(PyObject *self, PyObject *args) {", NIL);
+
+ Wrapper_add_local(f, "argc", "int argc");
+ Printf(tmp, "PyObject *argv[%d]", maxargs + 1);
+ Wrapper_add_local(f, "argv", tmp);
+
+ if (!fastunpack) {
+ Wrapper_add_local(f, "ii", "int ii");
+ Append(f->code, "if (!PyTuple_Check(args)) SWIG_fail;\n");
+ Append(f->code, "argc = (int)PyObject_Length(args);\n");
+ Printf(f->code, "for (ii = 0; (ii < argc) && (ii < %d); ii++) {\n", maxargs);
+ Append(f->code, "argv[ii] = PyTuple_GET_ITEM(args,ii);\n");
+ Append(f->code, "}\n");
+ } else {
+ String *iname = Getattr(n, "sym:name");
+ Printf(f->code, "if (!(argc = SWIG_Python_UnpackTuple(args,\"%s\",0,%d,argv))) SWIG_fail;\n", iname, maxargs);
+ 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 {
+ Printf(protoTypes, "\n\" %s(%s)\\n\"", SwigType_str(Getattr(sibl, "name"), 0), ParmList_protostr(Getattr(sibl, "wrap:parms")));
+ } while ((sibl = Getattr(sibl, "sym:nextSibling")));
+ Append(f->code, "fail:\n");
+ Printf(f->code, "SWIG_SetErrorMsg(PyExc_NotImplementedError,"
+ "\"Wrong number of arguments for overloaded function '%s'.\\n\"" "\n\" Possible C/C++ prototypes are:\\n\"%s);\n", symname, protoTypes);
+ Append(f->code, "return NULL;\n");
+ Delete(protoTypes);
+ }
+ Printv(f->code, "}\n", NIL);
+ Wrapper_print(f, f_wrappers);
+ Node *p = Getattr(n, "sym:previousSibling");
+ add_method(symname, wname, 0, p);
+
+ /* Create a shadow for this function (if enabled and not in a member function) */
+ if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) {
+ emitFunctionShadowHelper(n, f_shadow_stubs, symname, 0);
+ }
+ DelWrapper(f);
+ Delete(dispatch);
+ Delete(tmp);
+ Delete(wname);
+ }
+
+ /* ------------------------------------------------------------
+ * functionWrapper()
+ * ------------------------------------------------------------ */
+
+
+ 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");
+ int director_method = 0;
+
+ Parm *p;
+ int i;
+ char source[64];
+ Wrapper *f;
+ 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 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(sname);
+ handled_as_init = (Strcmp(nname, sname) == 0) || (Strcmp(nname, cname) == 0);
+ Delete(cname);
+ }
+
+
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+ }
+
+ f = NewWrapper();
+ 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 */
+ num_arguments = emit_num_arguments(l);
+ num_required = emit_num_required(l);
+ if (((num_arguments == 0) && (num_required == 0)) || ((num_arguments == 1) && (num_required == 1) && Getattr(l, "self")))
+ allow_kwargs = 0;
+ varargs = emit_isvarargs(l);
+
+ String *wname = Swig_name_wrapper(iname);
+ if (overname) {
+ Append(wname, overname);
+ }
+
+ if (!allow_kwargs || Getattr(n, "sym:overloaded")) {
+ if (!varargs) {
+ Printv(f->def, "SWIGINTERN PyObject *", wname, "(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {", NIL);
+ } else {
+ Printv(f->def, "SWIGINTERN PyObject *", wname, "__varargs__", "(PyObject *SWIGUNUSEDPARM(self), 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, "SWIGINTERN PyObject *", wname, "(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {", NIL);
+ }
+ if (!allow_kwargs) {
+ Append(parse_args, " if (!PyArg_ParseTuple(args,(char *)\"");
+ } else {
+ Append(parse_args, " if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)\"");
+ Append(arglist, ",kwnames");
+ }
+
+ int funpack = modernargs && fastunpack && !varargs && !allow_kwargs;
+ int noargs = funpack && (num_required == 0 && num_arguments == 0);
+ int onearg = funpack && (num_required == 1 && num_arguments == 1);
+
+ /* Generate code for argument marshalling */
+ if (funpack) {
+ if (overname) {
+ if (aliasobj0) {
+ Append(f->code, "#define obj0 (swig_obj[0])\n");
+ }
+ } else if (num_arguments) {
+ sprintf(source, "PyObject *swig_obj[%d]", num_arguments);
+ Wrapper_add_localv(f, "swig_obj", source, NIL);
+ if (aliasobj0) {
+ Append(f->code, "#define obj0 (swig_obj[0])\n");
+ }
+ }
+ }
+
+
+ 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);
+ }
+ }
+ }
+
+ 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 *pn = Getattr(p, "name");
+ String *ln = Getattr(p, "lname");
+ if (funpack) {
+ sprintf(source, "swig_obj[%d]", i);
+ } else {
+ sprintf(source, "obj%d", i);
+ }
+
+
+ Putc(',', arglist);
+ if (i == num_required)
+ Putc('|', parse_args); /* Optional argument separator */
+
+ /* Keyword argument handling */
+ if (allow_kwargs) {
+ if (Len(pn)) {
+ String *tmp = 0;
+ String *name = pn;
+ if (!Getattr(p,"hidden")) {
+ name = tmp = Swig_name_make(p, 0, pn, 0, 0);
+ }
+ Printf(kwargs, "(char *) \"%s\",", name);
+ if (tmp)
+ Delete(tmp);
+ } else {
+ Printf(kwargs, "(char *)\"arg%d\",", i + 1);
+ }
+ }
+
+ /* Look for an input typemap */
+ if ((tm = Getattr(p, "tmap:in"))) {
+ String *parse = Getattr(p, "tmap:in:parse");
+ if (!parse) {
+ 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);
+ }
+
+ Putc('O', parse_args);
+ if (!funpack) {
+ 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);
+ 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 || !modernargs) {
+ 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, "SWIGINTERN PyObject *", wname, "(PyObject *SWIGUNUSEDPARM(self), int nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) {", NIL);
+ } else {
+ Printv(f->def, "SWIGINTERN PyObject *", wname, "(PyObject *SWIGUNUSEDPARM(self), int nobjs, PyObject **swig_obj) {", NIL);
+ }
+ Printf(parse_args, "if ((nobjs < %d) || (nobjs > %d)) SWIG_fail;\n", num_required, num_arguments);
+ } else {
+ if (noargs) {
+ Printv(f->def, "SWIGINTERN PyObject *", wname, "(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {", NIL);
+ } else {
+ Printv(f->def, "SWIGINTERN PyObject *", wname, "(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {", NIL);
+ }
+ if (onearg) {
+ Printf(parse_args, "if (!args) SWIG_fail;\n");
+ Printf(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_required, num_arguments);
+ } else if (noargs) {
+ Printf(parse_args, "if (!SWIG_Python_UnpackTuple(args,\"%s\",%d,%d,0)) SWIG_fail;\n", iname, num_required, num_arguments);
+ }
+ }
+ } else {
+ Printf(parse_args, "if(!PyArg_UnpackTuple(args,(char *)\"%s\",%d,%d", iname, num_required, num_arguments);
+ Printv(parse_args, arglist, ")) SWIG_fail;\n", NIL);
+ }
+ }
+
+ /* Now piece together the first part of the wrapper function */
+ Printv(f->code, 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 (!checkAttribute(p,"tmap:in:numinputs","0") && !Getattr(p,"tmap:in:parse")) {
+ 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) {
+ Append(f->code, "upcall = (director && (director->swig_get_self()==swig_obj[0]));\n");
+ } else {
+ Append(f->code, "upcall = (director && (director->swig_get_self()==obj0));\n");
+ }
+ }
+
+ /* Emit the function call */
+ if (director_method) {
+ Append(f->code, "try {\n");
+ } else {
+ if (allow_thread) {
+ Append(f->code, "{\n");
+ thread_begin_allow(n, f->code);
+ }
+ }
+
+ 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");
+ } else {
+ if (allow_thread) {
+ thread_end_allow(n, actioncode);
+ Append(actioncode, "}\n");
+ }
+ }
+
+ /* This part below still needs cleanup */
+
+ /* Return the function value */
+ if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
+ if (funpack) {
+ Replaceall(tm, "$self", "swig_obj[0]");
+ } else {
+ Replaceall(tm, "$self", "obj0");
+ }
+ Replaceall(tm, "$source", "result");
+ Replaceall(tm, "$target", "resultobj");
+ Replaceall(tm, "$result", "resultobj");
+ 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 *parent = Swig_methodclass(n);
+ 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");
+ Append(f->code, "director = SWIG_DIRECTOR_CAST(result);\n");
+ 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, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+
+ if (director_method) {
+ if ((tm = Swig_typemap_lookup("directorfree", n, "result", 0))) {
+ Replaceall(tm, "$input", "result");
+ Replaceall(tm, "$result", "resultobj");
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+ }
+
+ Append(f->code, " return resultobj;\n");
+
+ /* Error handling code */
+
+ Append(f->code, "fail:\n");
+ if (need_cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+ Printv(f->code, " return NULL;\n", NIL);
+
+
+ if (funpack) {
+ if (aliasobj0) {
+ Append(f->code, "#if defined(obj0)\n");
+ Append(f->code, "#undef obj0\n");
+ Append(f->code, "#endif\n");
+ }
+ }
+
+
+ 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 (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();
+ Printv(f->def, "SWIGINTERN PyObject *", wname, "(PyObject *self, PyObject *args) {", NIL);
+ Wrapper_add_local(f, "resultobj", "PyObject *resultobj");
+ Wrapper_add_local(f, "varargs", "PyObject *varargs");
+ Wrapper_add_local(f, "newargs", "PyObject *newargs");
+ Printf(f->code, "newargs = PyTuple_GetSlice(args,0,%d);\n", num_arguments);
+ Printf(f->code, "varargs = PyTuple_GetSlice(args,%d,PyTuple_Size(args)+1);\n", num_arguments);
+ Printf(f->code, "resultobj = %s__varargs__(self,newargs,varargs);\n", wname);
+ 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")) {
+ 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 ((shadow) && (!(shadow & PYSHADOW_MEMBER))) {
+ emitFunctionShadowHelper(n, in_class ? f_shadow_stubs : f_shadow, iname, allow_kwargs);
+ }
+ } else {
+ if (!Getattr(n, "sym:nextSibling")) {
+ dispatchFunction(n, funpack);
+ }
+ }
+ Delete(parse_args);
+ Delete(arglist);
+ Delete(get_pointers);
+ Delete(cleanup);
+ Delete(outarg);
+ Delete(kwargs);
+ Delete(wname);
+ 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");
+
+ 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 PyDict_SetItemString(d,(char*)\"%s\", SWIG_globals());\n", global_name);
+ have_globals = 1;
+ if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) {
+ Printf(f_shadow_stubs, "%s = %s.%s\n", global_name, module, global_name);
+ }
+ }
+ int assignable = is_assignable(n);
+
+ if ((shadow) && !assignable) {
+ if (!in_class) {
+ Printf(f_shadow_stubs, "%s = %s.%s\n", iname, global_name, iname);
+ }
+ }
+
+ String *getname = Swig_name_get(iname);
+ String *setname = Swig_name_set(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);
+ 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);
+ int addfail = 0;
+ Printf(getf->def, "SWIGINTERN PyObject *%s(void) {", vargetname);
+ Wrapper_add_local(getf, "pyobj", "PyObject *pyobj = 0");
+ 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(SWIG_globals(),(char*)\"%s\",%s, %s);\n", iname, vargetname, varsetname);
+
+ Delete(vargetname);
+ Delete(varsetname);
+ Delete(getname);
+ Delete(setname);
+ DelWrapper(setf);
+ DelWrapper(getf);
+ 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;
+ int have_tm = 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 ((tm = Swig_typemap_lookup("constcode", n, name, 0))) {
+ Replaceall(tm, "$source", value);
+ Replaceall(tm, "$target", name);
+ Replaceall(tm, "$value", value);
+ Printf(f_init, "%s\n", tm);
+ Delete(tm);
+ have_tm = 1;
+ }
+ if (!have_tm) {
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
+ return SWIG_NOWRAP;
+ }
+ if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) {
+ if (!in_class) {
+ Printv(f_shadow, iname, " = ", module, ".", iname, "\n", NIL);
+ } else {
+ if (!(Getattr(n, "feature:python:callback"))) {
+ Printv(f_shadow_stubs, iname, " = ", module, ".", iname, "\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 (shadow) {
+ Printv(f_shadow_stubs, name, " = ", module, ".", name, "\n", NIL);
+ }
+ return SWIG_OK;
+ }
+
+
+
+/* ----------------------------------------------------------------------------
+ * BEGIN C++ Director Class modifications
+ * ------------------------------------------------------------------------- */
+
+/* C++/Python polymorphism demo code, copyright (C) 2002 Mark Rose <mrose@stm.lbl.gov>
+ *
+ * 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"));
+ 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, 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, 0, 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\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* name) const {\n");
+ Printf(f_directors_h, " std::map<std::string, bool>::const_iterator iv = inner.find(name);\n");
+ Printf(f_directors_h, " return (iv != inner.end() ? iv->second : false);\n");
+ Printf(f_directors_h, " }\n\n");
+
+ Printf(f_directors_h, " void swig_set_inner(const char* name, bool val) const\n");
+ Printf(f_directors_h, " { inner[name] = val;}\n\n");
+ Printf(f_directors_h, "private:\n");
+ Printf(f_directors_h, " mutable std::map<std::string, bool> inner;\n");
+
+ }
+ if (director_method_index) {
+ Printf(f_directors_h, "\n\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 == NULL) {\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) {
+ String *symname = Getattr(n, "sym:name");
+ String *mrename = Swig_name_disown(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 *importname = NewString("");
+ String *modname = Getattr(mod, "name");
+ if (Strcmp(modname, mainmodule) != 0) {
+ // check if the module has a package option
+ Node *options = Getattr(mod, "options");
+ String *pkg = options ? Getattr(options, "package") : 0;
+ if (pkg && (!package || Strcmp(pkg, package) != 0)) {
+ Printf(importname, "%s.", pkg);
+ }
+ Printf(importname, "%s.", modname);
+ }
+ Append(importname, Getattr(n, "sym:name"));
+ Setattr(n, "python:proxy", importname);
+ }
+ }
+ return Language::classDeclaration(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int classHandler(Node *n) {
+ int oldclassic = classic;
+ int oldmodern = modern;
+ File *f_shadow_file = f_shadow;
+
+ if (shadow) {
+
+ /* Create new strings for building up a wrapper function */
+ have_constructor = 0;
+ have_repr = 0;
+
+ if (GetFlag(n, "feature:classic")) {
+ classic = 1;
+ modern = 0;
+ }
+ if (GetFlag(n, "feature:modern")) {
+ classic = 0;
+ modern = 1;
+ }
+ if (GetFlag(n, "feature:exceptionclass")) {
+ classic = 1;
+ modern = 0;
+ }
+
+ shadow_indent = (String *) tab4;
+
+ class_name = Getattr(n, "sym:name");
+ real_classname = Getattr(n, "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 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, input_file, line_number,
+ "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) {
+ Putc(',', base_class);
+ }
+ }
+ }
+
+ /* dealing with abstract base class */
+ String *abcs = Getattr(n, "feature:python:abc");
+ if (py3 && abcs) {
+ if (Len(base_class)) {
+ Putc(',', base_class);
+ }
+ Printv(base_class, abcs, NIL);
+ }
+
+ Printv(f_shadow, "class ", class_name, NIL);
+
+ if (Len(base_class)) {
+ Printf(f_shadow, "(%s)", base_class);
+ } else {
+ if (!classic) {
+ Printf(f_shadow, modern ? "(object)" : "(_object)");
+ }
+ if (GetFlag(n, "feature:exceptionclass") ) {
+ Printf(f_shadow, "(Exception)");
+ }
+ }
+ Printf(f_shadow, ":\n");
+ if (have_docstring(n)) {
+ String *str = docstring(n, AUTODOC_CLASS, tab4);
+ if (str != NULL && Len(str))
+ Printv(f_shadow, tab4, str, "\n", NIL);
+ }
+ if (!modern) {
+ Printv(f_shadow, tab4, "__swig_setmethods__ = {}\n", NIL);
+ if (Len(base_class)) {
+ Printf(f_shadow, "%sfor _s in [%s]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{}))\n", tab4, base_class);
+ }
+
+ if (!GetFlag(n, "feature:python:nondynamic")) {
+ Printv(f_shadow, tab4, "__setattr__ = lambda self, name, value: _swig_setattr(self, ", class_name, ", name, value)\n", NIL);
+ } else {
+ Printv(f_shadow, tab4, "__setattr__ = lambda self, name, value: _swig_setattr_nondynamic(self, ", class_name, ", name, value)\n", NIL);
+ }
+
+ Printv(f_shadow, tab4, "__swig_getmethods__ = {}\n", NIL);
+ if (Len(base_class)) {
+ Printf(f_shadow, "%sfor _s in [%s]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{}))\n", tab4, base_class);
+ }
+
+ Printv(f_shadow, tab4, "__getattr__ = lambda self, name: _swig_getattr(self, ", class_name, ", name)\n", NIL);
+ } else {
+ Printv(f_shadow, tab4, "thisown = _swig_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_method(object.__setattr__)\n",
+ tab4, "class __metaclass__(type):\n", tab4, tab4, "__setattr__ = _swig_setattr_nondynamic_method(type.__setattr__)\n", NIL);
+ }
+ }
+ }
+
+ /* Emit all of the members */
+
+ in_class = 1;
+
+ /* Overide the shadow file so we can capture its methods */
+ f_shadow = NewString("");
+
+ Language::classHandler(n);
+ in_class = 0;
+
+ /* Complete the class */
+ if (shadow) {
+ /* Generate a class registration function */
+ {
+ String *smartptr = Getattr(n, "feature:smartptr"); // Replace storing a pointer to underlying class with a smart pointer (intended for use with non-intrusive smart pointers)
+ SwigType *smart = 0;
+ if (smartptr) {
+ SwigType *cpt = Swig_cparse_type(smartptr);
+ if (cpt) {
+ smart = SwigType_typedef_resolve_all(cpt);
+ Delete(cpt);
+ } else {
+ // TODO: report line number of where the feature comes from
+ Swig_error(Getfile(n), Getline(n), "Invalid type (%s) in 'smartptr' feature for class %s.\n", smartptr, real_classname);
+ }
+ }
+ SwigType *ct = Copy(smart ? smart : real_classname);
+ SwigType_add_pointer(ct);
+ SwigType *realct = Copy(real_classname);
+ SwigType_add_pointer(realct);
+ SwigType_remember(realct);
+ Printv(f_wrappers, "SWIGINTERN PyObject *", class_name, "_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {\n", NIL);
+ Printv(f_wrappers, " PyObject *obj;\n", NIL);
+ if (modernargs) {
+ if (fastunpack) {
+ Printv(f_wrappers, " if (!SWIG_Python_UnpackTuple(args,(char*)\"swigregister\", 1, 1,&obj)) return NULL;\n", NIL);
+ } else {
+ Printv(f_wrappers, " if (!PyArg_UnpackTuple(args,(char*)\"swigregister\", 1, 1,&obj)) return NULL;\n", NIL);
+ }
+ } else {
+ Printv(f_wrappers, " if (!PyArg_ParseTuple(args,(char*)\"O:swigregister\", &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);
+ Delete(smart);
+ Delete(cname);
+ Delete(ct);
+ Delete(realct);
+ }
+ if (!have_constructor) {
+ Printv(f_shadow_file, tab4, "def __init__(self, *args, **kwargs): raise AttributeError(\"", "No constructor defined", (Getattr(n, "abstract") ? " - class is abstract" : ""), "\")\n", NIL);
+ } else if (fastinit) {
+
+ 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) {
+ /* Supply a repr method for this class */
+ String *rname = SwigType_namestr(real_classname);
+ if (new_repr) {
+ Printv(f_shadow_file, tab4, "__repr__ = _swig_repr\n", NIL);
+ } else {
+ Printv(f_shadow_file, tab4, "def __repr__(self):\n", tab8, "return \"<C ", rname, " instance at 0x%x>\" % (self.this,)\n", NIL);
+ }
+ Delete(rname);
+ }
+
+
+ /* Now emit methods */
+ Printv(f_shadow_file, f_shadow, NIL);
+
+ /* Now the Ptr class */
+ if (classptr) {
+ Printv(f_shadow_file, "\nclass ", class_name, "Ptr(", class_name, "):\n", tab4, "def __init__(self, this):\n", NIL);
+ if (!modern) {
+ Printv(f_shadow_file,
+ tab8, "try: self.this.append(this)\n",
+ tab8, "except: self.this = this\n", tab8, "self.this.own(0)\n", tab8, "self.__class__ = ", class_name, "\n\n", NIL);
+ } else {
+ Printv(f_shadow_file,
+ tab8, "try: self.this.append(this)\n",
+ tab8, "except: self.this = this\n", tab8, "self.this.own(0)\n", tab8, "self.__class__ = ", class_name, "\n\n", NIL);
+ }
+ }
+
+ if (fastproxy) {
+ List *shadow_list = Getattr(n, "shadow_methods");
+ for (int i = 0; i < Len(shadow_list); ++i) {
+ String *symname = Getitem(shadow_list, i);
+ Printf(f_shadow_file, "%s.%s = new_instancemethod(%s.%s,None,%s)\n", class_name, symname, module, Swig_name_member(class_name, symname), class_name);
+ }
+ }
+ Printf(f_shadow_file, "%s_swigregister = %s.%s_swigregister\n", class_name, module, class_name);
+ Printf(f_shadow_file, "%s_swigregister(%s)\n", class_name, class_name);
+
+ shadow_indent = 0;
+ Printf(f_shadow_file, "%s\n", f_shadow_stubs);
+ Clear(f_shadow_stubs);
+ }
+ classic = oldclassic;
+ modern = oldmodern;
+
+ /* 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;
+
+ /* 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 (!Getattr(n, "sym:nextSibling")) {
+ if (shadow) {
+ int allow_kwargs = (check_kwargs(n) && !Getattr(n, "sym:overloaded")) ? 1 : 0;
+ int fproxy = fastproxy;
+ if (Strcmp(symname, "__repr__") == 0) {
+ have_repr = 1;
+ }
+ if (Getattr(n, "feature:shadow")) {
+ String *pycode = pythoncode(Getattr(n, "feature:shadow"), tab4);
+ String *pyaction = NewStringf("%s.%s", module, Swig_name_member(class_name, symname));
+ Replaceall(pycode, "$action", pyaction);
+ Delete(pyaction);
+ Printv(f_shadow, pycode, "\n", NIL);
+ Delete(pycode);
+ fproxy = 0;
+ } else {
+ 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, tab4, "def ", symname, "(", parms, ")", returnTypeAnnotation(n), ":", NIL);
+ Printv(f_shadow, " return ", funcCall(Swig_name_member(class_name, symname), callParms), "\n", NIL);
+ }
+ } else {
+ Printv(f_shadow, tab4, "def ", symname, "(",parms , ")", returnTypeAnnotation(n), ":", NIL);
+ Printv(f_shadow, "\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, pythoncode(pythonprepend(n), tab8), "\n", NIL);
+ }
+ if (have_pythonappend(n)) {
+ fproxy = 0;
+ Printv(f_shadow, tab8, "val = ", funcCall(Swig_name_member(class_name, symname), callParms), "\n", NIL);
+ Printv(f_shadow, pythoncode(pythonappend(n), tab8), "\n", NIL);
+ Printv(f_shadow, tab8, "return val\n\n", NIL);
+ } else {
+ Printv(f_shadow, tab8, "return ", funcCall(Swig_name_member(class_name, symname), callParms), "\n\n", NIL);
+ }
+ }
+ }
+ if (fproxy) {
+ List *shadow_list = Getattr(getCurrentClass(), "shadow_methods");
+ if (!shadow_list) {
+ shadow_list = NewList();
+ Setattr(getCurrentClass(), "shadow_methods", shadow_list);
+ Delete(shadow_list);
+ }
+ Append(shadow_list, symname);
+ }
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ Language::staticmemberfunctionHandler(n);
+
+ if (Getattr(n, "sym:nextSibling")) {
+ return SWIG_OK;
+ }
+
+ if (shadow) {
+ if (!classic && !Getattr(n, "feature:python:callback") && have_addtofunc(n)) {
+ 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, 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, pythoncode(pythonprepend(n), tab8), "\n", NIL);
+ if (have_pythonappend(n)) {
+ Printv(f_shadow, tab8, "val = ", funcCall(Swig_name_member(class_name, symname), callParms), "\n", NIL);
+ Printv(f_shadow, pythoncode(pythonappend(n), tab8), "\n", NIL);
+ Printv(f_shadow, tab8, "return val\n\n", NIL);
+ } else {
+ Printv(f_shadow, tab8, "return ", funcCall(Swig_name_member(class_name, symname), callParms), "\n\n", NIL);
+ }
+ Printv(f_shadow, tab4, modern ? "" : "if _newclass:", symname, " = staticmethod(", symname, ")\n", NIL);
+
+ if (!modern) {
+ Printv(f_shadow, tab4, "__swig_getmethods__[\"", symname, "\"] = lambda x: ", symname, "\n", NIL);
+ }
+
+ } else {
+ if (!modern) {
+ Printv(f_shadow, tab4, "__swig_getmethods__[\"", symname, "\"] = lambda x: ", module, ".", Swig_name_member(class_name, symname), "\n", NIL);
+ }
+ if (!classic) {
+ Printv(f_shadow, tab4, modern ? "" : "if _newclass:", symname, " = staticmethod(", module, ".", Swig_name_member(class_name, symname), ")\n", NIL);
+ }
+ }
+ }
+ 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);
+ 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(sname);
+ handled_as_init = (Strcmp(nname, sname) == 0) || (Strcmp(nname, cname) == 0);
+ Delete(cname);
+ }
+
+ if (!have_constructor && handled_as_init) {
+ if (Getattr(n, "feature:shadow")) {
+ String *pycode = pythoncode(Getattr(n, "feature:shadow"), tab4);
+ String *pyaction = NewStringf("%s.%s", module, Swig_name_construct(symname));
+ 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);
+
+ 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, 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, pythoncode(pythonprepend(n), tab8), "\n", NIL);
+ Printv(f_shadow, pass_self, NIL);
+ if (fastinit) {
+ Printv(f_shadow, tab8, module, ".", class_name, "_swiginit(self,", funcCall(Swig_name_construct(symname), callParms), ")\n", NIL);
+ } else {
+ Printv(f_shadow,
+ tab8, "this = ", funcCall(Swig_name_construct(symname), callParms), "\n",
+ tab8, "try: self.this.append(this)\n", tab8, "except: self.this = this\n", NIL);
+ }
+ if (have_pythonappend(n))
+ Printv(f_shadow, pythoncode(pythonappend(n), tab8), "\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 (Getattr(n, "feature:shadow")) {
+ String *pycode = pythoncode(Getattr(n, "feature:shadow"), "");
+ String *pyaction = NewStringf("%s.%s", module, Swig_name_construct(symname));
+ Replaceall(pycode, "$action", pyaction);
+ Delete(pyaction);
+ Printv(f_shadow_stubs, pycode, "\n", NIL);
+ Delete(pycode);
+ } else {
+ String *parms = make_pyParmList(n, true, false, allow_kwargs);
+ String *callParms = make_pyParmList(n, true, 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, pythoncode(pythonprepend(n), tab4), "\n", NIL);
+ Printv(f_shadow_stubs, tab4, "val = ", funcCall(Swig_name_construct(symname), 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, pythoncode(pythonappend(n), tab4), "\n", NIL);
+ Printv(f_shadow_stubs, tab4, "return val\n", NIL);
+ }
+ }
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * destructorHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int destructorHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ int oldshadow = shadow;
+
+ 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 = pythoncode(Getattr(n, "feature:shadow"), tab4);
+ String *pyaction = NewStringf("%s.%s", module, Swig_name_destroy(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(symname), "\n", NIL);
+ if (!have_pythonprepend(n) && !have_pythonappend(n)) {
+ if (proxydel) {
+ Printv(f_shadow, tab4, "__del__ = lambda self : None;\n", NIL);
+ }
+ 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, pythoncode(pythonprepend(n), tab8), "\n", NIL);
+#ifdef USE_THISOWN
+ Printv(f_shadow, tab8, "try:\n", NIL);
+ Printv(f_shadow, tab8, tab4, "if self.thisown: ", module, ".", Swig_name_destroy(symname), "(self)\n", NIL);
+ Printv(f_shadow, tab8, "except: pass\n", NIL);
+#else
+#endif
+ if (have_pythonappend(n))
+ Printv(f_shadow, pythoncode(pythonappend(n), tab8), "\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) {
+ String *mname = Swig_name_member(class_name, symname);
+ String *setname = Swig_name_set(mname);
+ String *getname = Swig_name_get(mname);
+ if (shadow) {
+ int assignable = is_assignable(n);
+ if (!modern) {
+ if (assignable) {
+ Printv(f_shadow, tab4, "__swig_setmethods__[\"", symname, "\"] = ", module, ".", setname, "\n", NIL);
+ }
+ Printv(f_shadow, tab4, "__swig_getmethods__[\"", symname, "\"] = ", module, ".", getname, "\n", NIL);
+ }
+ if (!classic) {
+ if (!assignable) {
+ Printv(f_shadow, tab4, modern ? "" : "if _newclass:", symname, " = _swig_property(", module, ".", getname, ")\n", NIL);
+ } else {
+ Printv(f_shadow, tab4, modern ? "" : "if _newclass:", symname, " = _swig_property(", module, ".", getname, ", ", module, ".", setname, ")\n", NIL);
+ }
+ }
+ }
+ Delete(mname);
+ Delete(setname);
+ Delete(getname);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * staticmembervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int staticmembervariableHandler(Node *n) {
+ Language::staticmembervariableHandler(n);
+
+ if (shadow && !GetFlag(n, "wrappedasconstant")) {
+ String *symname = Getattr(n, "sym:name");
+ if (GetFlag(n, "hasconsttype")) {
+ String *mname = Swig_name_member(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(class_name, symname);
+ String *getname = Swig_name_get(mname);
+ String *wrapgetname = Swig_name_wrapper(getname);
+ String *vargetname = NewStringf("Swig_var_%s", getname);
+ String *setname = Swig_name_set(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) {
+ Wrapper *f = NewWrapper();
+ Printv(f->def, "SWIGINTERN PyObject *", wrapsetname, "(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {", NIL);
+ Wrapper_add_local(f, "value", "PyObject *value");
+ Wrapper_add_local(f, "res", "int res");
+ Append(f->code, "if (!PyArg_ParseTuple(args,(char *)\"O:set\",&value)) return NULL;\n");
+ Printv(f->code, "res = ", varsetname, "(value);\n", NIL);
+ Append(f->code, "return !res ? SWIG_Py_Void() : NULL;\n");
+ Append(f->code, "}\n");
+ Wrapper_print(f, f_wrappers);
+ add_method(setname, wrapsetname, 0);
+ DelWrapper(f);
+ }
+ if (!modern) {
+ if (assignable) {
+ Printv(f_shadow, tab4, "__swig_setmethods__[\"", symname, "\"] = ", module, ".", setname, "\n", NIL);
+ }
+ Printv(f_shadow, tab4, "__swig_getmethods__[\"", symname, "\"] = ", module, ".", getname, "\n", NIL);
+ }
+ if (!classic) {
+ if (!assignable) {
+ Printv(f_shadow, tab4, modern ? "" : "if _newclass:", symname, " = _swig_property(", module, ".", getname, ")\n", NIL);
+ } else {
+ Printv(f_shadow, tab4, modern ? "" : "if _newclass:", symname, " = _swig_property(", module, ".", getname, ", ", module, ".", setname, ")\n", NIL);
+ }
+ }
+ 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");
+ int oldshadow = shadow;
+ if (shadow)
+ shadow = shadow | PYSHADOW_MEMBER;
+ Language::memberconstantHandler(n);
+ shadow = oldshadow;
+
+ if (shadow) {
+ Printv(f_shadow, tab4, symname, " = ", module, ".", Swig_name_member(class_name, symname), "\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 = pythoncode(code, shadow_indent);
+ Printv(f_shadow, 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");
+ }
+
+};
+
+/* ---------------------------------------------------------------
+ * 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;
+ String *type;
+ String *name;
+ String *classname;
+ String *c_classname = Getattr(parent, "name");
+ String *declaration;
+ ParmList *l;
+ Wrapper *w;
+ String *tm;
+ String *wrap_args = NewString("");
+ String *return_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;
+ }
+ }
+
+ classname = Getattr(parent, "sym:name");
+ type = Getattr(n, "type");
+ name = Getattr(n, "name");
+
+ w = NewWrapper();
+ declaration = NewString("");
+
+ /* determine if the method returns a pointer */
+ decl = Getattr(n, "decl");
+ is_pointer = SwigType_ispointer_return(decl);
+ is_void = (!Cmp(type, "void") && !is_pointer);
+
+ /* form complete return type */
+ return_type = Copy(type);
+ {
+ SwigType *t = Copy(decl);
+ SwigType *f = 0;
+ f = SwigType_pop_function(t);
+ SwigType_push(return_type, t);
+ Delete(f);
+ Delete(t);
+ }
+
+ /* virtual method definition */
+ l = Getattr(n, "parms");
+ String *target;
+ String *pclassname = NewStringf("SwigDirector_%s", classname);
+ String *qualified_name = NewStringf("%s::%s", pclassname, name);
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : type;
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ /* header declaration */
+ target = Swig_method_decl(rtype, decl, name, l, 0, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Get any exception classes in the throws typemap
+ 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 ((tm = 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) {
+ if (!(ignored_method && !pure_virtual)) {
+ String *cres = SwigType_lstr(return_type, "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++ -> Python) */
+ String *arglist = NewString("");
+ String *parse_args = NewString("");
+
+ /* remove the wrapper 'w' since it was producing spurious temps */
+ Swig_typemap_attach_parms("in", l, 0);
+ Swig_typemap_attach_parms("directorin", l, 0);
+ 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 != NULL) {
+ 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);
+ 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);
+ 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_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, "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_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);
+ }
+ 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 || !modernargs) {
+ Printf(w->code, "swig::SwigVar_PyObject result = PyObject_CallFunction(method, (char *)\"(%s)\" %s);\n", parse_args, arglist);
+ } else {
+ Printf(w->code, "swig::SwigVar_PyObject result = PyObject_CallFunctionObjArgs(method %s, NULL);\n", arglist);
+ }
+ } else {
+ if (modernargs) {
+ Append(w->code, "swig::SwigVar_PyObject args = PyTuple_New(0);\n");
+ Append(w->code, "swig::SwigVar_PyObject result = PyObject_Call(method, (PyObject*) args, NULL);\n");
+ } else {
+ Printf(w->code, "swig::SwigVar_PyObject result = PyObject_CallFunction(method, NULL, NULL);\n");
+ }
+ }
+ Append(w->code, "#else\n");
+ if (Len(parse_args) > 0) {
+ if (use_parse || !modernargs) {
+ Printf(w->code, "swig::SwigVar_PyObject result = PyObject_CallMethod(swig_get_self(), (char *)\"%s\", (char *)\"(%s)\" %s);\n",
+ pyname, parse_args, arglist);
+ } else {
+ Printf(w->code, "swig::SwigVar_PyObject swig_method_name = SWIG_Python_str_FromChar((char *)\"%s\");\n", pyname);
+ Printf(w->code, "swig::SwigVar_PyObject result = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name %s, NULL);\n", arglist);
+ }
+ } else {
+ if (!modernargs) {
+ Printf(w->code, "swig::SwigVar_PyObject result = PyObject_CallMethod(swig_get_self(), (char *) \"%s\", NULL);\n", pyname);
+ } else {
+ Printf(w->code, "swig::SwigVar_PyObject swig_method_name = SWIG_Python_str_FromChar((char *)\"%s\");\n", pyname);
+ Append(w->code, "swig::SwigVar_PyObject result = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name, NULL);\n");
+ }
+ }
+ 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, "result", 0);
+ if (!tm) {
+ tm = Getattr(n, "feature:director:except");
+ if (tm)
+ tm = Copy(tm);
+ }
+ Append(w->code, "if (result == NULL) {\n");
+ 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 != NULL) {\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 aruments, 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");
+ Append(w->code, "if (!PyTuple_Check(result)) {\n");
+ 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) {
+ /* this seems really silly. the node's type excludes
+ * qualifier/pointer/reference markers, which have to be retrieved
+ * from the decl field to construct return_type. but the typemap
+ * lookup routine uses the node's type, so we have to swap in and
+ * out the correct type. it's not just me, similar silliness also
+ * occurs in Language::cDeclaration().
+ */
+ Setattr(n, "type", return_type);
+ tm = Swig_typemap_lookup("directorout", n, "result", w);
+ Setattr(n, "type", type);
+ if (tm != 0) {
+ if (outputs > 1) {
+ Printf(w->code, "output = PyTuple_GetItem(result, %d);\n", idx++);
+ Replaceall(tm, "$input", "output");
+ } else {
+ Replaceall(tm, "$input", "result");
+ }
+ 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(return_type, 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(result, %d);\n", idx++);
+ Replaceall(tm, "$input", "output");
+ } else {
+ Replaceall(tm, "$input", "result");
+ }
+ Replaceall(tm, "$result", Getattr(p, "name"));
+ 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(return_type, 0);
+ if (!SwigType_isreference(return_type)) {
+ 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")) {
+ 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(return_type);
+ 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/Source/Modules/r.cxx b/Source/Modules/r.cxx
new file mode 100644
index 0000000..966feb7
--- /dev/null
+++ b/Source/Modules/r.cxx
@@ -0,0 +1,2745 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * r.cxx
+ *
+ * R language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_r_cxx[] = "$Id: r.cxx 11454 2009-07-26 21:21:26Z wsfulton $";
+
+#include "swigmod.h"
+
+#define UNUSED(a) (void)a
+
+static const double DEFAULT_NUMBER = .0000123456712312312323;
+static const int MAX_OVERLOAD_ARGS = 5;
+
+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);
+
+ /* Printf(stderr, "<getRTypeName> %s,base = %s\n", t, b);
+ for(i = 0; i < Len(els); i++)
+ Printf(stderr, "%d) %s, ", i, Getitem(els,i));
+ Printf(stderr, "\n"); */
+
+ 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;
+
+ /*
+ if(count)
+ return(b);
+
+ Delete(b);
+ return(NewString(""));
+ */
+}
+
+#if 0
+static String * getRType(Node *n) {
+ SwigType *elType = Getattr(n, "type");
+ SwigType *elDecl = Getattr(n, "decl");
+ //XXX How can we tell if this is already done.
+ SwigType_push(elType, elDecl);
+ String *ans;
+
+ String *rtype = Swig_typemap_lookup("rtype", n, "", 0);
+ String *i = getRTypeName(elType);
+
+ if(Len(i) == 0) {
+ SwigType *td = SwigType_typedef_resolve(elType);
+ if(td) {
+ // Printf(stderr, "Resolving typedef %s -> %s\n", elType, td);
+ i = getRTypeName(td);
+ }
+ }
+ // Printf(stderr, "<getRType> i = %s, rtype = %s (for %s)\n",
+ // i, rtype, elType);
+ if(rtype) {
+ ans = NewString("");
+ Printf(ans, "%s", rtype);
+ Replaceall(ans, "$R_class", Char(i));
+ // Printf(stderr, "Found r type in typemap for %s (for %s) => %s (%s) => %s\n",
+ // SwigType_str(elType, 0), Getattr(n, "name"), rtype, i, ans);
+ } else {
+ ans = i;
+ }
+
+ return(ans);
+}
+#endif
+
+/*********************
+ 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 *getRClassName(String *retType, int /*addRef*/ = 1, int upRef=0) {
+ String *tmp = NewString("");
+ SwigType *resolved = SwigType_typedef_resolve_all(retType);
+ char *retName = Char(SwigType_manglestr(resolved));
+ if (upRef) {
+ Printf(tmp, "_p%s", retName);
+ } else{
+ Insert(tmp, 0, retName);
+ }
+
+ return tmp;
+/*
+#if 1
+ List *l = SwigType_split(retType);
+ int n = Len(l);
+ if(!l || n == 0) {
+#ifdef R_SWIG_VERBOSE
+ if (debugMode)
+ Printf(stderr, "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");
+ }
+ }
+
+#else
+ char *retName = Char(SwigType_manglestr(retType));
+ if(!retName)
+ return(tmp);
+
+ if(addRef) {
+ while(retName && strlen(retName) > 1 && strncmp(retName, "_p", 2) == 0) {
+ retName += 2;
+ Printf(tmp, "Ref");
+ }
+ }
+ if(retName[0] == '_')
+ retName ++;
+ Insert(tmp, 0, retName);
+#endif
+
+ 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("");
+
+#if 1
+ List *l = SwigType_split(retType);
+ int n = Len(l);
+ if(!l || n == 0) {
+#ifdef R_SWIG_VERBOSE
+ Printf(stderr, "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");
+ }
+ }
+
+#else
+ char *retName = Char(SwigType_manglestr(retType));
+ if(!retName)
+ return(tmp);
+
+ if(addRef) {
+ while(retName && strlen(retName) > 1 &&
+ strncmp(retName, "_p", 2) == 0) {
+ retName += 2;
+ Printf(tmp, "Ref");
+ }
+ }
+
+ if(retName[0] == '_')
+ retName ++;
+ Insert(tmp, 0, retName);
+#endif
+
+ 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 = (char *)"\
+R Options (available with -r)\n\
+ -copystruct - Emit R code to copy C structs (on by default)\n\
+ -cppcast - Enable C++ casting operators (default) \n\
+ -debug - Output debug\n\
+ -dll <name> - Name of the DLL (without the .dll or .so suffix). 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 (registration information still generated)\n\
+ -package <name> - Package name for the PACKAGE argument of the R .Call() 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);
+ String *tmp_base = getRClassName(type, 0);
+ String *tmp_ref = getRClassName(type, 1, 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);
+}
+
+static double getNumber(String *value, String *type) {
+ UNUSED(type);
+
+ double d = DEFAULT_NUMBER;
+ if(Char(value)) {
+ // Printf(stderr, "getNumber %s %s\n", Char(value), type);
+ if(sscanf(Char(value), "%lf", &d) != 1)
+ return(DEFAULT_NUMBER);
+ }
+ return(d);
+}
+
+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 variableWrapper(Node *n);
+
+ int classDeclaration(Node *n);
+ int enumDeclaration(Node *n);
+
+ int membervariableHandler(Node *n);
+
+ int typedefHandler(Node *n);
+
+ int memberfunctionHandler(Node *n) {
+ if (debugMode)
+ Printf(stderr, "<memberfunctionHandler> %s %s\n",
+ Getattr(n, "name"),
+ Getattr(n, "type"));
+ member_name = Getattr(n, "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 *el, File *out);
+ int OutputArrayMethod(String *className, List *el, File *out);
+ int OutputClassMemberTable(Hash *tb, File *out);
+ int OutputClassMethodsTable(File *out);
+ int OutputClassAccessInfo(Hash *tb, 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, int isSet = -1);
+
+ static int getFunctionPointerNumArgs(Node *n, SwigType *tt);
+
+protected:
+ bool copyStruct;
+ bool memoryProfile;
+ bool aggressiveGc;
+
+ // Strings into which we cumulate the generated code that is to be written
+ //vto the files.
+ 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;
+
+
+ int processing_class_member_function;
+ List *class_member_functions;
+ List *class_member_set_functions;
+
+ /* */
+ 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),
+ 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),
+ processing_class_member_function(0),
+ class_member_functions(0),
+ class_member_set_functions(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(stderr, "type: %s\n", n);
+#if 0
+ SwigType *tmp = SwigType_typedef_resolve(tt);
+
+ n = SwigType_typedef_resolve(tt);
+#endif
+
+ ParmList *parms = Getattr(n, "parms");
+ if (debugMode)
+ Printf(stderr, "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(stderr, "[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(stderr, "<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)));
+
+
+ // if (debugMode) {
+ Printf(stderr, "Type: %s\n", t);
+ Printf(stderr, "Return type: %s\n", SwigType_base(t));
+ //}
+
+ bool isVoidType = Strcmp(rettype, "void") == 0;
+ if (debugMode)
+ Printf(stderr, "%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 = NewString("");
+
+ if (!arg && Cmp(Getattr(p, "type"), "void")) {
+ lname = NewStringf("s_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(stderr, "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");
+ // String *lname = Getattr(p,"lname");
+ Printf(f->def, "%s %s", SwigType_str(tt, 0), name);
+ String *tm = Getattr(p, "tmap:out");
+ if(tm) {
+ Replaceall(tm, "$1", name);
+ Replaceall(tm, "$result", "r_tmp");
+ replaceRClass(tm, Getattr(p,"type"));
+ Replaceall(tm,"$owner", "R_SWIG_EXTERNAL");
+ }
+
+ 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?
+ */
+ Node *bbase = NewHash();
+
+ Setattr(bbase, "type", rettype);
+ Setattr(bbase, "name", NewString("result"));
+ String *returnTM = Swig_typemap_lookup("in", bbase, "result", f);
+ if(returnTM) {
+ String *tm = returnTM;
+ Replaceall(tm,"$input", "r_swig_cb_data->retValue");
+ Replaceall(tm,"$target", "result");
+ replaceRClass(tm, rettype);
+ Replaceall(tm,"$owner", "R_SWIG_EXTERNAL");
+ 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(!isVoidType)
+ Printv(f->code, "return result;\n", NIL);
+
+ Printv(f->code, "\n}\n", NIL);
+
+ /* 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 the 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);
+
+ 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("");
+}
+
+
+
+#if 0
+int R::cDeclaration(Node *n) {
+ SwigType *t = Getattr(n, "type");
+ SwigType *name = Getattr(n, "name");
+ if (debugMode)
+ Printf(stderr, "cDeclaration (%s): %s\n", name, SwigType_lstr(t, 0));
+ return Language::cDeclaration(n);
+}
+#endif
+
+
+/**
+ 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(!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);
+ }
+
+ /* 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");
+ Printf(f_runtime, "#define SWIGR\n");
+ Printf(f_runtime, "\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);
+ Close(f_begin);
+ 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(stderr, "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);
+
+ Close(scode);
+ // 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);
+
+ Close(runtime);
+ 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(namespaceFunctions, ns, 1);
+ Printf(ns, ")\n");
+ Close(ns);
+ Delete(ns);
+ Delete(s_namespace);
+ }
+
+ return SWIG_OK;
+}
+
+
+
+/*
+ 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(stderr, "%d) %s\n", i, key);
+ List *els = Getattr(tb, key);
+ int nels = Len(els);
+ Printf(stderr, "\t");
+ for(int j = 0; j < nels; j+=2) {
+ Printf(stderr, "%s%s", Getitem(els, j), j < nels - 1 ? ", " : "");
+ Printf(stderr, "%s\n", Getitem(els, j+1));
+ }
+ Printf(stderr, "\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. */
+
+ 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);
+ ptr = &ptr[Len(key) - 3];
+ int isSet = strcmp(ptr, "set") == 0;
+
+ // OutputArrayMethod(className, el, out);
+ OutputMemberReferenceMethod(className, isSet, el, out);
+
+ if(outputNamespaceInfo)
+ Printf(s_namespace, "\"%s\"%s", className, i < n-1 ? "," : "");
+ }
+ if(n && outputNamespaceInfo) {
+ Printf(s_namespace, ")\n");
+ }
+
+ return n;
+}
+
+/*******************************************************************
+ 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 *el, File *out) {
+ int numMems = Len(el), j;
+ int has_getitem = 0, has_setitem = 0, has_str = 0;
+ 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+=3) {
+ String *item = Getitem(el, j);
+ if (Getattr(itemList, item))
+ continue;
+ Setattr(itemList, item, "1");
+ if (!Strcmp(item, "__getitem__")) has_getitem = 1;
+ if (!Strcmp(item, "__setitem__")) has_setitem = 1;
+ if (!Strcmp(item, "__str__")) has_str = 1;
+
+ String *dup = Getitem(el, j + 1);
+ char *ptr = Char(dup);
+ ptr = &ptr[Len(dup) - 3];
+
+ if (!strcmp(ptr, "get"))
+ varaccessor++;
+
+ 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);
+ int vcount = 0;
+ for(j = 0; j < numMems; j+=3) {
+ String *item = Getitem(el, j);
+ String *dup = Getitem(el, j + 1);
+ char *ptr = Char(dup);
+ ptr = &ptr[Len(dup) - 3];
+
+ if (!strcmp(ptr, "get")) {
+ vcount++;
+ Printf(f->code, "'%s'%s", item, vcount < varaccessor ? ", " : "");
+ }
+ }
+ Printf(f->code, ")\n");
+ }
+
+
+ /* Printv(f->code, tab8,
+ "idx = pmatch(name, names(accessorFuns))\n",
+ tab8,
+ "if(is.na(idx)) {\n",
+ tab8, tab4,
+ "stop(\"No ", (isSet ? "modifiable" : "accessible"), " field named \", name, \" in ", className,
+ ": fields are \", paste(names(accessorFuns), sep = \", \")",
+ ")", "\n}\n", NIL); */
+ 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 {
+ Printv(f->code, tab8, "formals(f)[[1]] = x\n", NIL);
+ if (varaccessor) {
+ Printv(f->code, tab8,
+ "if (is.na(match(name, vaccessors))) f else f(x)\n", NIL);
+ } else {
+ Printv(f->code, tab8, "f\n", NIL);
+ }
+ }
+ Printf(f->code, "}\n");
+
+
+ Printf(out, "# Start of accessor method for %s\n", className);
+ 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");
+ }
+
+ DelWrapper(attr);
+ DelWrapper(f);
+
+ Printf(out, "# end of accessor method for %s\n", className);
+
+ return SWIG_OK;
+}
+
+/*******************************************************************
+ 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)
+ 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::OutputArrayMethod(String *className, List *el, File *out) {
+ int numMems = Len(el), j;
+
+ if(!el || numMems == 0)
+ return(0);
+
+ Printf(out, "# start of array methods for %s\n", className);
+ for(j = 0; j < numMems; j+=3) {
+ String *item = Getitem(el, j);
+ String *dup = Getitem(el, j + 1);
+ if (!Strcmp(item, "__getitem__")) {
+ Printf(out,
+ "setMethod('[', '_p%s', function(x, i, j, ..., drop =TRUE) ",
+ getRClassName(className));
+ Printf(out, " sapply(i, function (n) %s(x, as.integer(n-1))))\n\n", dup);
+ }
+ if (!Strcmp(item, "__setitem__")) {
+ Printf(out, "setMethod('[<-', '_p%s', function(x, i, j, ..., value)",
+ getRClassName(className));
+ Printf(out, " sapply(1:length(i), function(n) %s(x, as.integer(i[n]-1), value[n])))\n\n", dup);
+ }
+
+ }
+
+ Printf(out, "# end of array methods for %s\n", className);
+
+ 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) {
+ String *name = Getattr(n, "name");
+ String *tdname = Getattr(n, "tdname");
+
+ /* Using name if tdname is empty. */
+
+ if(Len(tdname) == 0)
+ tdname = name;
+
+
+ if(!tdname || Strcmp(tdname, "") == 0) {
+ Language::enumDeclaration(n);
+ return SWIG_OK;
+ }
+
+ String *mangled_tdname = SwigType_manglestr(tdname);
+ String *scode = NewString("");
+
+ Printv(scode, "defineEnumeration('", mangled_tdname, "'",
+ ",\n", tab8, tab8, tab4, ".values = c(\n", NIL);
+
+ Node *c;
+ int value = -1; // First number is zero
+ for (c = firstChild(n); c; c = nextSibling(c)) {
+ // const char *tag = Char(nodeType(c));
+ // if (Strcmp(tag,"cdecl") == 0) {
+ name = Getattr(c, "name");
+ String *type = Getattr(c, "type");
+ String *val = Getattr(c, "enumvalue");
+ if(val && Char(val)) {
+ int inval = (int) getNumber(val, type);
+ if(inval == DEFAULT_NUMBER)
+ value++;
+ else
+ value = inval;
+ } else
+ value++;
+
+ Printf(scode, "%s%s%s'%s' = %d%s\n", tab8, tab8, tab8, name, value,
+ nextSibling(c) ? ", " : "");
+ // }
+ }
+
+ Printv(scode, "))", NIL);
+ Printf(sfile, "%s\n", scode);
+
+ Delete(scode);
+ Delete(mangled_tdname);
+
+ return SWIG_OK;
+}
+
+
+/*************************************************************
+**************************************************************/
+int R::variableWrapper(Node *n) {
+ String *name = Getattr(n, "sym:name");
+
+ processing_variable = 1;
+ Language::variableWrapper(n); // Force the emission of the _set and _get function wrappers.
+ processing_variable = 0;
+
+
+ SwigType *ty = Getattr(n, "type");
+ int addCopyParam = addCopyParameter(ty);
+
+ //XXX
+ processType(ty, n);
+
+ 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;
+}
+
+
+void R::addAccessor(String *memberName, Wrapper *wrapper, String *name,
+ int isSet) {
+ if(isSet < 0) {
+ int n = Len(name);
+ char *ptr = Char(name);
+ isSet = Strcmp(NewString(&ptr[n-3]), "set") == 0;
+ }
+
+ List *l = isSet ? class_member_set_functions : class_member_functions;
+
+ if(!l) {
+ l = NewList();
+ if(isSet)
+ class_member_set_functions = l;
+ else
+ class_member_functions = l;
+ }
+
+ Append(l, memberName);
+ Append(l, name);
+
+ String *tmp = NewString("");
+ Wrapper_print(wrapper, tmp);
+ Append(l, tmp);
+ // if we could put the wrapper in directly: Append(l, Copy(sfun));
+ if (debugMode)
+ Printf(stderr, "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 */
+};
+
+
+static List * 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;
+ }
+ /* 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")) {
+ 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)) {
+ // 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 (no type checking rule 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),
+ "xx Overloaded method %s not supported (no type checking rule 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 %s(%s) const ignored. Non-const method at %s:%d used.\n",
+ Getattr(nodes[j].n,"name"), ParmList_errorstr(nodes[j].parms),
+ Getfile(nodes[i].n), Getline(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(%s) ignored. Method %s(%s) const at %s:%d used.\n",
+ Getattr(nodes[j].n,"name"), ParmList_errorstr(nodes[j].parms),
+ Getattr(nodes[i].n,"name"), ParmList_errorstr(nodes[i].parms),
+ Getfile(nodes[i].n), Getline(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 %s(%s) const ignored. Non-const method at %s:%d used.\n",
+ Getattr(nodes[j].n,"name"), ParmList_errorstr(nodes[j].parms),
+ Getfile(nodes[i].n), Getline(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(%s) const ignored. Method %s(%s) at %s:%d used.\n",
+ Getattr(nodes[j].n,"name"), ParmList_errorstr(nodes[j].parms),
+ Getattr(nodes[i].n,"name"), ParmList_errorstr(nodes[i].parms),
+ Getfile(nodes[i].n), Getline(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 is shadowed by %s at %s:%d.\n",
+ Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n),
+ Getfile(nodes[i].n), Getline(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. Method %s at %s:%d used.\n",
+ Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n),
+ Getfile(nodes[i].n), Getline(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);
+ 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++) {
+ String *tm = Swig_typemap_lookup("rtype", p, "", 0);
+ if(tm) {
+ replaceRClass(tm, Getattr(p, "type"));
+ }
+ if (DohStrcmp(tm,"numeric")==0) {
+ Printf(f->code, "%sis.numeric(argv[[%d]])",
+ j == 0 ? "" : " && ",
+ j+1);
+ }
+ else {
+ Printf(f->code, "%sextends(argtypes[%d], '%s')",
+ j == 0 ? "" : " && ",
+ j+1,
+ tm);
+ }
+ 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) {
+ Printv(f->code, "}", NIL);
+ }
+ 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(stderr,
+ "<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(stderr,
+ "<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)) {
+ 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 (expandTypedef(resolved)) {
+ type = Copy(resolved);
+ Setattr(n, "type", type);
+ }
+ }
+ if (debugMode)
+ Printf(stderr, "<functionWrapper> unresolved_return_type %s\n",
+ unresolved_return_type);
+ if(processing_member_access_function) {
+ if (debugMode)
+ Printf(stderr, "<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. */
+
+ int n = Len(iname);
+ char *ptr = Char(iname);
+ bool isSet(Strcmp(NewString(&ptr[n-3]), "set") == 0);
+
+
+ String *tmp = NewString("");
+ Printf(tmp, "%s_%s", class_name, isSet ? "set" : "get");
+
+ 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, num_required, varargs;
+ UNUSED(varargs);
+
+ String *wname = Swig_name_wrapper(iname);
+ Replace(wname, "_wrap", "R_swig", DOH_REPLACE_FIRST);
+ 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);
+
+
+ // Can we get the nodeType() of the type node! and see if it is a struct.
+ // int addCopyParam = SwigType_isclass(rtype);
+
+ // if(addCopyParam)
+ if (debugMode)
+ Printf(stderr, "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
+ 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);
+ num_required = emit_num_required(l);
+ varargs = emit_isvarargs(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 && Swig_name_warning(p, 0, name, 0))
+ name = 0;
+
+ /* 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(stderr, "+++ parameter name with :: in it %s\n", name);
+ }
+ if (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",
+ "}\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"));
+ 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", "R_SWIG_EXTERNAL");
+
+
+ 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, "result", f, actioncode))) {
+ SwigType *retType = Getattr(n, "type");
+ //Printf(stderr, "Return Value for %s, array? %s\n", retType, SwigType_isarray(retType) ? "yes" : "no");
+ /* if(SwigType_isarray(retType)) {
+ defineArrayAccessors(retType);
+ } */
+
+
+ Replaceall(tm,"$1", "result");
+ Replaceall(tm,"$result", "r_ans");
+ replaceRClass(tm, retType);
+
+ if (GetFlag(n,"feature:new")) {
+ Replaceall(tm, "$owner", "R_SWIG_OWNER");
+ } else {
+ Replaceall(tm,"$owner", "R_SWIG_EXTERNAL");
+ }
+
+#if 0
+ if(addCopyParam) {
+ Printf(f->code, "if(LOGICAL(s_swig_copy)[0]) {\n");
+ Printf(f->code, "/* Deal with returning a reference. */\nr_ans = R_NilValue;\n");
+ Printf(f->code, "}\n else {\n");
+ }
+#endif
+ Printf(f->code, "%s\n", tm);
+#if 0
+ if(addCopyParam)
+ Printf(f->code, "}\n"); /* end of if(s_swig_copy) ... else { ... } */
+#endif
+
+ } 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 */
+ Printv(f->code, cleanup, NIL);
+ Delete(cleanup);
+
+
+
+ Printv(f->code, UnProtectWrapupCode, NIL);
+
+ /*If the user gave us something to convert the result in */
+ if ((tm = Swig_typemap_lookup("scoerceout", n,
+ "result", sfun))) {
+ Replaceall(tm,"$source","ans");
+ Replaceall(tm,"$result","ans");
+ 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\nans\n", tm);
+ if (destructor)
+ Printv(f->code, "R_ClearExternalPtr(self);\n", NIL);
+
+ Printv(f->code, "return r_ans;\n}\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");
+ 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 potentialy insert
+ */
+ if(processing_member_access_function || processing_class_member_function) {
+ String *tmp;
+ if(member_name)
+ tmp = member_name;
+ else
+ tmp = Getattr(n, "memberfunctionHandler:name");
+ addAccessor(member_name, sfun, iname);
+ }
+
+ 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;
+}
+
+/*****************************************************
+ 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);
+ Printf(out, "SWIGEXPORT void R_init_%s(DllInfo *dll) {\n", Rpackage);
+ 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);
+ }
+
+}
+
+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") && Strcmp(Getattr(n, "storage"), "typedef") == 0
+ && Getattr(n, "tdname") && Strcmp(Getattr(n, "tdname"), name) == 0) {
+ if (debugMode)
+ Printf(stderr, "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;
+
+
+ // OutputArrayMethod(name, class_member_functions, sfile);
+ if (class_member_functions)
+ OutputMemberReferenceMethod(name, 0, class_member_functions, sfile);
+ if (class_member_set_functions)
+ OutputMemberReferenceMethod(name, 1, class_member_set_functions, sfile);
+
+ if(class_member_functions) {
+ Delete(class_member_functions);
+ class_member_functions = NULL;
+ }
+ if(class_member_set_functions) {
+ Delete(class_member_set_functions);
+ class_member_set_functions = NULL;
+ }
+ if (Getattr(n, "has_destructor")) {
+ Printf(sfile, "setMethod('delete', '_p%s', function(obj) {delete%s(obj)})\n",
+ getRClassName(Getattr(n, "name")),
+ getRClassName(Getattr(n, "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 (Strcmp(elKind, "variable") != 0) {
+ c = nextSibling(c);
+ continue;
+ }
+ if (!Len(elName)) {
+ c = nextSibling(c);
+ continue;
+ }
+#if 0
+ tp = getRType(c);
+#else
+ 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(stderr, "<classDeclaration> elType %p\n", elType);
+ // tp = getRClassNameCopyStruct(Getattr(c, "type"), 1);
+#endif
+ 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(stderr, "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 (Strcmp(elKind, "variable") != 0) {
+ Delete(elKind);
+ 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(stderr, "<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(stderr, "<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(stderr, "<membervariableHandler> name = %s, sym:name = %s\n",
+ Getattr(n, "name"), member_name);
+
+ int status(Language::membervariableHandler(n));
+
+ if(opaqueClassDeclaration == NULL && debugMode)
+ Printf(stderr, "<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(stderr, "*** 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[]) {
+ bool cppcast = true;
+ 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],"-cppcast")) {
+ cppcast = true;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i],"-nocppcast")) {
+ cppcast = false;
+ 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);
+ }
+
+ if (cppcast) {
+ Preprocessor_define((DOH *) "SWIG_CPLUSPLUS_CAST", 0);
+ }
+ /// 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(stderr, "processType %s (tdname = %s)\n", Getattr(n, "name"), tmp);
+
+ 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(stderr, "<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(stderr,
+ "<processType> Defining pointer handler %s\n", t);
+
+ String *tmp = createFunctionPointerHandler(t, n, nargs);
+ return tmp;
+ }
+
+#if 0
+ SwigType_isfunction(t) && SwigType_ispointer(t)
+#endif
+
+ return NULL;
+}
+
+
+
+
+
+
+
+
+
+/*************************************************************************************/
+
+
+
+
+
diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx
new file mode 100644
index 0000000..c9e935e
--- /dev/null
+++ b/Source/Modules/ruby.cxx
@@ -0,0 +1,3427 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * ruby.cxx
+ *
+ * Ruby language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_ruby_cxx[] = "$Id: ruby.cxx 11246 2009-06-05 17:19:29Z wsfulton $";
+
+#include "swigmod.h"
+#include "cparse.h"
+static int treduce = SWIG_cparse_template_reduce(0);
+
+#define SWIG_PROTECTED_TARGET_METHODS 1
+
+#include <ctype.h>
+#include <string.h>
+#include <limits.h> /* for INT_MAX */
+
+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
+};
+
+static const char *usage = "\
+Ruby Options (available with -ruby)\n\
+ -globalmodule - Wrap everything into the global module\n\
+ -minherit - Attempt to support multiple inheritance\n\
+ -nocppcast - Disable C++ casting operators, useful for generating bugs\n\
+ -cppcast - Enable C++ casting operators (default)\n\
+ -autorename - Enable renaming of classes and methods to follow Ruby coding standards\n\
+ -noautorename - Disable renaming of classes and methods (default)\n\
+ -prefix <name> - Set a prefix <name> to be prepended to all names\n\
+ -initname <name> - Set entry function to Init_<name> (used by `require')\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;
+ if (autodoc) {
+ char *c = Char(autodoc);
+ if (c && 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 != NULL && Len(str) > 0) || (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc"));
+ }
+
+ /* ------------------------------------------------------------
+ * docstring()
+ * Get the docstring text, stripping off {} if neccessary,
+ * 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 != NULL && 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 != NULL && Len(autodoc) > 0);
+ }
+ // 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 (have_auto && have_ds) { // Both autodoc and docstring are present
+ doc = NewString("");
+ Printv(doc, "\n", autodoc, "\n", str, NIL);
+ } else if (!have_auto && have_ds) { // only docstring
+ if (Strchr(str, '\n') == NULL) {
+ doc = NewString(str);
+ } else {
+ doc = NewString("");
+ Printv(doc, str, NIL);
+ }
+ } else if (have_auto && !have_ds) { // only autodoc
+ if (Strchr(autodoc, '\n') == NULL) {
+ doc = NewStringf("%s", autodoc);
+ } else {
+ doc = NewString("");
+ Printv(doc, "\n", autodoc, NIL);
+ }
+ } else
+ doc = NewString("");
+
+ // 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;
+ }
+
+ /* ------------------------------------------------------------
+ * make_autodocParmList()
+ * Generate the documentation for the function parameters
+ * ------------------------------------------------------------ */
+
+ String *make_autodocParmList(Node *n, bool showTypes) {
+ String *doc = NewString("");
+ String *pdocs = Copy(Getattr(n, "feature:pdocs"));
+ ParmList *plist = CopyParmList(Getattr(n, "parms"));
+ Parm *p;
+ Parm *pnext;
+ Node *lookup;
+ int lines = 0;
+ const int maxwidth = 50;
+
+ if (pdocs)
+ Append(pdocs, ".\n");
+
+
+ Swig_typemap_attach_parms("in", plist, 0);
+ Swig_typemap_attach_parms("doc", plist, 0);
+
+ for (p = plist; p; p = pnext) {
+ String *name = 0;
+ String *type = 0;
+ String *value = 0;
+ String *ptype = 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");
+ ptype = Getattr(p, "tmap:doc:pytype");
+ }
+
+ name = name ? name : Getattr(p, "name");
+ type = type ? type : Getattr(p, "type");
+ value = value ? value : Getattr(p, "value");
+
+
+ String *tm = Getattr(p, "tmap:in");
+ if (tm) {
+ pnext = Getattr(p, "tmap:in:next");
+ } else {
+ pnext = nextSibling(p);
+ }
+
+ // Skip ignored input attributes
+ if (checkAttribute(p, "tmap:in:numinputs", "0"))
+ continue;
+
+ // 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?
+ if (showTypes) {
+ type = SwigType_base(type);
+ lookup = Swig_symbol_clookup(type, 0);
+ if (lookup)
+ type = Getattr(lookup, "sym:name");
+ Printf(doc, "%s ", type);
+ }
+
+ if (name) {
+ Append(doc, name);
+ if (pdoc) {
+ if (!pdocs)
+ pdocs = NewString("Parameters:\n");
+ Printf(pdocs, " %s.\n", pdoc);
+ }
+ } else {
+ Append(doc, "?");
+ }
+
+ if (value) {
+ if (Strcmp(value, "NULL") == 0)
+ value = NewString("nil");
+ else if (Strcmp(value, "true") == 0 || Strcmp(value, "TRUE") == 0)
+ value = NewString("true");
+ else if (Strcmp(value, "false") == 0 || Strcmp(value, "FALSE") == 0)
+ value = NewString("false");
+ else {
+ lookup = Swig_symbol_clookup(value, 0);
+ if (lookup)
+ value = Getattr(lookup, "sym:name");
+ }
+ Printf(doc, "=%s", value);
+ }
+ }
+ 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 funciton 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 (class_name && 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("/*\n");
+ int counter = 0;
+ bool skipAuto = false;
+ Node* on = n;
+ for ( ; n; ++counter ) {
+ 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 = NULL;
+ else {
+ SwigType *qt = SwigType_typedef_resolve_all(type);
+ if (SwigType_isenum(qt))
+ type = NewString("int");
+ else {
+ type = SwigType_base(type);
+ Node *lookup = Swig_symbol_clookup(type, 0);
+ if (lookup)
+ type = Getattr(lookup, "sym:name");
+ }
+ }
+ }
+
+ 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;
+ }
+ }
+
+
+ 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)
+ Printf(doc, " -> %s", type);
+ break;
+ }
+ case AUTODOC_SETTER:
+ {
+ Printf(doc, " %s=(x)", symname);
+ if (type) Printf(doc, " -> %s", type);
+ 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 == NULL || 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)
+ Printf(doc, " -> %s", type);
+ break;
+ }
+ case AUTODOC_SETTER:
+ {
+ Printf(doc, " call-seq:\n");
+ Printf(doc, " %s=(x)", symname);
+ if (type) Printf(doc, " -> %s", type);
+ break;
+ }
+ }
+ }
+
+ // if it's overloaded then get the next decl and loop around again
+ n = Getattr(n, "sym:nextSibling");
+ if (n)
+ Append(doc, "\n");
+ }
+
+ 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;
+ }
+ }
+
+
+ n = on;
+ while ( n ) {
+ String *autodoc = Getattr(n, "feature:autodoc");
+ autodoc_l dlevel = autodoc_level(autodoc);
+
+ symname = Getattr(n, "sym:name");
+ if ( Getattr( special_methods, symname ) )
+ symname = Getattr( special_methods, symname );
+
+ 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");
+ }
+
+ Append(doc, "\n*/\n");
+ Delete(full_name);
+ Delete(class_name);
+ Delete(super_names);
+ Delete(methodName);
+
+ return doc;
+ }
+
+public:
+
+ /* ---------------------------------------------------------------------
+ * RUBY()
+ *
+ * Initialize member data
+ * --------------------------------------------------------------------- */
+
+ RUBY() {
+ module = 0;
+ modvar = 0;
+ feature = 0;
+ prefix = 0;
+ last_autodoc = NewString("");
+ current = NO_CPP;
+ classes = 0;
+ klass = 0;
+ special_methods = 0;
+ f_begin = 0;
+ f_runtime = 0;
+ f_header = 0;
+ f_wrappers = 0;
+ f_init = 0;
+ f_initbeforefunc = 0;
+ useGlobalModule = false;
+ multipleInheritance = false;
+ 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 cppcast = 1;
+ 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], "-cppcast") == 0) {
+ cppcast = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocppcast") == 0) {
+ cppcast = 0;
+ 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);
+ }
+ }
+ }
+
+ if (cppcast) {
+ /* Turn on cppcast mode */
+ Preprocessor_define((DOH *) "SWIG_CPLUSPLUS_CAST", 0);
+ }
+
+ 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) {
+
+ /**
+ * 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;
+ }
+ }
+ }
+
+ /* 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");
+ Printf(f_runtime, "#define SWIGRUBY\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, (char *) "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)
+ Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h));
+
+ Delete(module_macro);
+ }
+
+ Printf(f_header, "#define SWIG_init Init_%s\n", feature);
+ Printf(f_header, "#define SWIG_name \"%s\"\n\n", module);
+ 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.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");
+ Close(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);
+ Close(f_begin);
+ 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 (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) {
+ 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:
+ assert(false); // Should not have gotten here for these types
+ default:
+ assert(false);
+ }
+
+ 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) {
+ Printv(f->locals, tab4, "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 constructor;
+ bool destructor;
+ String *storage;
+
+ 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");
+ constructor = (!Cmp(nodeType, "constructor"));
+ destructor = (!Cmp(nodeType, "destructor"));
+ storage = Getattr(n, "storage");
+
+ /* 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) {
+ Printf(f->def, "#ifdef HAVE_RB_DEFINE_ALLOC_FUNC\n");
+ Printv(f->def, "SWIGINTERN VALUE\n", wname, "(VALUE self) {", NIL);
+ Printf(f->def, "#else\n");
+ Printv(f->def, "SWIGINTERN VALUE\n", wname, "(int argc, VALUE *argv, VALUE self) {", NIL);
+ Printf(f->def, "#endif\n");
+ } 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 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");
+ 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) {
+ Append(action, "\nDATA_PTR(self) = result;");
+ if (GetFlag(pn, "feature:trackobjects")) {
+ Append(action, "\nSWIG_RubyAddTracking(result, self);");
+ }
+ }
+ }
+
+ /* 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 = (result ? Qtrue : Qfalse);\n", NIL);
+ } else {
+ tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode);
+ actioncode = 0;
+ if (tm) {
+ Replaceall(tm, "$result", "vresult");
+ Replaceall(tm, "$source", "result");
+ 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 *>(result);\n");
+ 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) {
+ need_result = 1;
+ Printf(f->code, "VALUE vresult = SWIG_NewClassInstance(self, SWIGTYPE%s);\n", Char(SwigType_manglestr(t)));
+ 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");
+ } else if (current == CONSTRUCTOR_INITIALIZE) {
+ need_result = 1;
+ // Printf(f->code, "DATA_PTR(self) = result;\n");
+ }
+ 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, "result", 0);
+ if (tm) {
+ Replaceall(tm, "$source", "result");
+ Printv(f->code, tm, "\n", NIL);
+ Delete(tm);
+ }
+ }
+
+ /* Special processing on return value. */
+ tm = Swig_typemap_lookup("ret", n, "result", 0);
+ if (tm) {
+ Replaceall(tm, "$source", "result");
+ Printv(f->code, tm, NIL);
+ Delete(tm);
+ }
+
+ if (director_method) {
+ if ((tm = Swig_typemap_lookup("directorfree", n, "result", 0))) {
+ Replaceall(tm, "$input", "result");
+ 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;
+
+ String* type = SwigType_str(Getattr(sibl,"type"),NULL);
+
+ 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,"feature:new"), "1") == 0;
+ const bool isMethod = ( Cmp(Getattr(sibl, "ismember"), "1") == 0 &&
+ (!isCtor) );
+
+ // Construct real method name
+ String* methodName = NewString("");
+ if ( isMethod )
+ Printv( methodName, Getattr(parentNode(sibl),"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 ) Printv( protoTypes, type, " ", NIL );
+ 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(type);
+ 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;
+
+ getf = NewWrapper();
+ setf = NewWrapper();
+
+ /* create getter */
+ int addfail = 0;
+ String *getname = Swig_name_get(iname);
+ getfname = Swig_name_wrapper(getname);
+ Setattr(n, "wrap:name", getfname);
+ Printv(getf->def, "SWIGINTERN VALUE\n", getfname, "(", NIL);
+ Printf(getf->def, "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 (!is_assignable(n)) {
+ setfname = NewString("NULL");
+ } else {
+ /* create setter */
+ String* docs = docstring(n, AUTODOC_SETTER);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ String *setname = Swig_name_set(iname);
+ setfname = Swig_name_wrapper(setname);
+ Setattr(n, "wrap:name", setfname);
+ Printv(setf->def, "SWIGINTERN VALUE\n", setfname, "(VALUE self, ", NIL);
+ Printf(setf->def, "VALUE _val) {");
+ 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));
+ }
+ 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 method */
+ if (CPlusPlus) {
+ Insert(getfname, 0, "VALUEFUNC(");
+ Append(getfname, ")");
+ Insert(setfname, 0, "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 (!GetFlag(n, "feature:immutable")) {
+ 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 (!GetFlag(n, "feature:immutable")) {
+ Printv(s, tab4, "rb_define_singleton_method(", modvar, ", \"", iname, "=\", ", setfname, ", 1);\n", NIL);
+ }
+ } else {
+ Printv(s, tab4, "rb_define_global_method(\"", iname, "\", ", getfname, ", 0);\n", NIL);
+ if (!GetFlag(n, "feature:immutable")) {
+ Printv(s, tab4, "rb_define_global_method(\"", iname, "=\", ", setfname, ", 1);\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 *tdname = Getattr(n, "tdname");
+
+ name = tdname ? tdname : 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);
+ if (multipleInheritance) {
+ String *bmangle = SwigType_manglestr(btype);
+ Insert(bmangle, 0, "((swig_class *) SWIGTYPE");
+ Append(bmangle, "->clientdata)->mImpl");
+ Printv(klass->init, "rb_include_module(", klass->mImpl, ", ", bmangle, ");\n", NIL);
+ Delete(bmangle);
+ } else {
+ String *bmangle = SwigType_manglestr(btype);
+ Insert(bmangle, 0, "((swig_class *) SWIGTYPE");
+ Append(bmangle, "->clientdata)->klass");
+ Replaceall(klass->init, "$super", bmangle);
+ Delete(bmangle);
+ }
+ 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, input_file, line_number,
+ "Warning for %s proxy: 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, "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);
+ String *tm = SwigType_manglestr(tt);
+ Printf(klass->init, "SWIG_TypeClientData(SWIGTYPE%s, (void *) &SwigClass%s);\n", tm, valid_name);
+ Delete(tm);
+ 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((const_String_or_char_ptr ) "construct", (const_String_or_char_ptr ) "%c_allocate");
+
+
+ Language::constructorHandler(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("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);
+ 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 */
+ String* docs = docstring(n, AUTODOC_CTOR);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ current = CONSTRUCTOR_INITIALIZE;
+ Swig_name_register((const_String_or_char_ptr ) "construct", (const_String_or_char_ptr ) "new_%c");
+ Language::constructorHandler(n);
+
+ /* Restore original parameter list */
+ Delattr(n, "wrap:self");
+ Swig_restore(n);
+
+ /* Done */
+ Swig_name_unregister((const_String_or_char_ptr ) "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((const_String_or_char_ptr ) "construct", (const_String_or_char_ptr ) "%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, "(", klass->type, " *", pname0, ") {\n", 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"));
+ 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, 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, 0, 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, "result", 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, "result", "VALUE", "result", "= Qnil", NIL);
+ Printf(body->code, "%s++;\n", depthCountName);
+ Printv(body->code, "result = rb_funcall2(args->recv, args->id, args->argc, args->argv);\n", NIL);
+ Printf(body->code, "%s--;\n", depthCountName);
+ Printv(body->code, "return result;\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, "}", 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, "result = rb_protect(PROTECTFUNC(%s), reinterpret_cast<VALUE>(&args), &status);\n", 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, "result = rb_funcall(swig_get_self(), rb_intern(\"%s\"), %d%s);\n", methodName, argc, args);
+ } else {
+ Printf(w->code, "result = rb_funcall(swig_get_self(), rb_intern(\"%s\"), 0, NULL);\n", 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;
+ String *type;
+ String *name;
+ String *classname;
+ String *c_classname = Getattr(parent, "name");
+ String *declaration;
+ ParmList *l;
+ Wrapper *w;
+ String *tm;
+ String *wrap_args = NewString("");
+ String *return_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"));
+ }
+
+ classname = Getattr(parent, "sym:name");
+ type = Getattr(n, "type");
+ name = Getattr(n, "name");
+
+ w = NewWrapper();
+ declaration = NewString("");
+
+ /* determine if the method returns a pointer */
+ decl = Getattr(n, "decl");
+ is_pointer = SwigType_ispointer_return(decl);
+ is_void = (!Cmp(type, "void") && !is_pointer);
+
+ /* form complete return type */
+ return_type = Copy(type);
+ {
+ SwigType *t = Copy(decl);
+ SwigType *f = 0;
+ f = SwigType_pop_function(t);
+ SwigType_push(return_type, t);
+ Delete(f);
+ Delete(t);
+ }
+
+ /* virtual method definition */
+ l = Getattr(n, "parms");
+ String *target;
+ String *pclassname = NewStringf("SwigDirector_%s", classname);
+ String *qualified_name = NewStringf("%s::%s", pclassname, name);
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : type;
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ /* header declaration */
+ target = Swig_method_decl(rtype, decl, name, l, 0, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Get any exception classes in the throws typemap
+ 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 ((tm = 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) {
+ if (!(ignored_method && !pure_virtual)) {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(return_type, "c_result"), 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++ -> Ruby) */
+ String *arglist = NewString("");
+
+ /**
+ * For each parameter to 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 your "directorin" typemaps.
+ * Not sure if it's OK to leave it like this, but seems OK so far.
+ */
+ typemap_copy_pname_to_lname(l);
+
+ Swig_typemap_attach_parms("in", l, 0);
+ Swig_typemap_attach_parms("directorin", l, 0);
+ 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++);
+ Replaceall(tm, "$input", source);
+ Replaceall(tm, "$owner", "0");
+ 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 */
+ Wrapper_add_local(w, "result", "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(result) != T_ARRAY) {\n");
+ 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) {
+ /* This seems really silly. The node's type excludes qualifier/pointer/reference markers,
+ * which have to be retrieved from the decl field to construct return_type. But the typemap
+ * lookup routine uses the node's type, so we have to swap in and out the correct type.
+ * It's not just me, similar silliness also occurs in Language::cDeclaration().
+ */
+ Setattr(n, "type", return_type);
+ tm = Swig_typemap_lookup("directorout", n, "result", w);
+ Setattr(n, "type", type);
+ if (tm != 0) {
+ if (outputs > 1 && !asvoid ) {
+ Printf(w->code, "output = rb_ary_entry(result, %d);\n", idx++);
+ Replaceall(tm, "$input", "output");
+ } else {
+ Replaceall(tm, "$input", "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);
+ } 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(return_type, 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(result, %d);\n", idx++);
+ Replaceall(tm, "$input", "output");
+ } else {
+ Replaceall(tm, "$input", "result");
+ }
+ Replaceall(tm, "$result", Getattr(p, "name"));
+ 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(return_type, 0);
+ if (!SwigType_isreference(return_type)) {
+ 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")) {
+ 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(return_type);
+ 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);
+ }
+
+ void typemap_copy_pname_to_lname(ParmList *parms) {
+ Parm *p;
+ String *pname;
+ String *lname;
+
+ p = parms;
+ while (p) {
+ pname = Getattr(p, "name");
+ lname = Copy(pname);
+ Setattr(p, "lname", lname);
+ p = nextSibling(p);
+ }
+ }
+
+ 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");
+ }
+}; /* 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/Source/Modules/s-exp.cxx b/Source/Modules/s-exp.cxx
new file mode 100644
index 0000000..c87d18c
--- /dev/null
+++ b/Source/Modules/s-exp.cxx
@@ -0,0 +1,394 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * s-exp.cxx
+ *
+ * A parse tree represented as Lisp s-expressions.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_s_exp_cxx[] = "$Id: s-exp.cxx 11133 2009-02-20 07:52:24Z wsfulton $";
+
+#include "swigmod.h"
+#include "dohint.h"
+
+static const char *usage = "\
+S-Exp Options (available with -sexp)\n\
+ -typemaplang <lang> - Typemap language\n\n";
+
+//static Node *view_top = 0;
+static File *out = 0;
+
+class Sexp:public Language {
+public:
+ int indent_level;
+ Sexp():indent_level(0) {
+ }
+
+ virtual ~ Sexp() {
+ }
+
+ virtual void main(int argc, char *argv[]) {
+ // Add a symbol to the parser for conditional compilation
+ Preprocessor_define("SWIGSEXP 1", 0);
+
+ SWIG_typemap_lang("sexp");
+ for (int iX = 0; iX < argc; iX++) {
+ if (strcmp(argv[iX], "-typemaplang") == 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);
+ }
+ }
+ }
+
+ DOHHash *print_circle_hash;
+ int print_circle_count;
+ int hanging_parens;
+ bool need_whitespace;
+ bool need_newline;
+
+ /* Top of the parse tree */
+ virtual int top(Node *n) {
+ if (out == 0) {
+ String *outfile = Getattr(n, "outfile");
+ Replaceall(outfile, "_wrap.cxx", ".lisp");
+ Replaceall(outfile, "_wrap.c", ".lisp");
+ out = NewFile(outfile, "w", SWIG_output_files());
+ if (!out) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+ String *f_sink = NewString("");
+ Swig_register_filebyname("header", f_sink);
+ Swig_register_filebyname("wrapper", f_sink);
+ Swig_register_filebyname("begin", f_sink);
+ Swig_register_filebyname("runtime", f_sink);
+ Swig_register_filebyname("init", f_sink);
+
+ Swig_banner_target_lang(out, ";;;");
+
+ Language::top(n);
+ Printf(out, "\n");
+ Printf(out, ";;; Lisp parse tree produced by SWIG\n");
+ print_circle_hash = DohNewHash();
+ print_circle_count = 0;
+ hanging_parens = 0;
+ need_whitespace = 0;
+ need_newline = 0;
+ Sexp_print_node(n);
+ flush_parens();
+ return SWIG_OK;
+ }
+
+ void print_indent() {
+ int i;
+ for (i = 0; i < indent_level; i++) {
+ Printf(out, " ");
+ }
+ }
+
+ void open_paren(const String *oper) {
+ flush_parens();
+ Printf(out, "(");
+ if (oper)
+ Printf(out, "%s ", oper);
+ indent_level += 2;
+ }
+
+ void close_paren(bool neednewline = false) {
+ hanging_parens++;
+ if (neednewline)
+ print_lazy_whitespace();
+ indent_level -= 2;
+ }
+
+ void flush_parens() {
+ int i;
+ if (hanging_parens) {
+ for (i = 0; i < hanging_parens; i++)
+ Printf(out, ")");
+ hanging_parens = 0;
+ need_newline = true;
+ need_whitespace = true;
+ }
+ if (need_newline) {
+ Printf(out, "\n");
+ print_indent();
+ need_newline = false;
+ need_whitespace = false;
+ } else if (need_whitespace) {
+ Printf(out, " ");
+ need_whitespace = false;
+ }
+ }
+
+ void print_lazy_whitespace() {
+ need_whitespace = 1;
+ }
+
+ void print_lazy_newline() {
+ need_newline = 1;
+ }
+
+ bool internal_key_p(DOH *key) {
+ return ((Cmp(key, "nodeType") == 0)
+ || (Cmp(key, "firstChild") == 0)
+ || (Cmp(key, "lastChild") == 0)
+ || (Cmp(key, "parentNode") == 0)
+ || (Cmp(key, "nextSibling") == 0)
+ || (Cmp(key, "previousSibling") == 0)
+ || (Cmp(key, "csym:nextSibling") == 0)
+ || (Cmp(key, "csym:previousSibling") == 0)
+ || (Cmp(key, "typepass:visit") == 0)
+ || (Cmp(key, "allocate:visit") == 0)
+ || (*(Char(key)) == '$'));
+ }
+
+ bool boolean_key_p(DOH *key) {
+ return ((Cmp(key, "allocate:default_constructor") == 0)
+ || (Cmp(key, "allocate:default_destructor") == 0)
+ || (Cmp(key, "allows_typedef") == 0)
+ || (Cmp(key, "feature:immutable") == 0));
+ }
+
+ bool list_key_p(DOH *key) {
+ return ((Cmp(key, "parms") == 0)
+ || (Cmp(key, "baselist") == 0));
+ }
+
+ bool plist_key_p(DOH *key)
+ // true if KEY is the name of data that is a mapping from keys to
+ // values, which should be printed as a plist.
+ {
+ return ((Cmp(key, "typescope") == 0));
+ }
+
+ bool maybe_plist_key_p(DOH *key) {
+ return (Strncmp(key, "tmap:", 5) == 0);
+ }
+
+ bool print_circle(DOH *obj, bool list_p)
+ // We have a complex object, which might be referenced several
+ // times, or even recursively. Use Lisp's reader notation for
+ // circular structures (#n#, #n=).
+ //
+ // An object can be printed in list-mode or object-mode; LIST_P toggles.
+ // return TRUE if OBJ still needs to be printed
+ {
+ flush_parens();
+ // Following is a silly hack. It works around the limitation of
+ // DOH's hash tables that only work with string keys!
+ char address[32];
+ sprintf(address, "%p%c", obj, list_p ? 'L' : 'O');
+ DOH *placeholder = Getattr(print_circle_hash, address);
+ if (placeholder) {
+ Printv(out, placeholder, NIL);
+ return false;
+ } else {
+ String *placeholder = NewStringf("#%d#", ++print_circle_count);
+ Setattr(print_circle_hash, address, placeholder);
+ Printf(out, "#%d=", print_circle_count);
+ return true;
+ }
+ }
+
+ void Sexp_print_value_of_key(DOH *value, DOH *key) {
+ if ((Cmp(key, "parms") == 0) || (Cmp(key, "wrap:parms") == 0)
+ || (Cmp(key, "kwargs") == 0) || (Cmp(key, "pattern") == 0))
+ Sexp_print_parms(value);
+ else if (plist_key_p(key))
+ Sexp_print_plist(value);
+ else if (maybe_plist_key_p(key)) {
+ if (DohIsMapping(value))
+ Sexp_print_plist(value);
+ else
+ Sexp_print_doh(value);
+ } else if (list_key_p(key))
+ Sexp_print_list(value);
+ else if (boolean_key_p(key))
+ Sexp_print_boolean(value);
+ else
+ Sexp_print_doh(value);
+ }
+
+ void Sexp_print_boolean(DOH *obj) {
+ flush_parens();
+ /* See DOH/Doh/base.c, DohGetInt() */
+ if (DohIsString(obj)) {
+ if (atoi(Char(obj)) != 0)
+ Printf(out, "t");
+ else
+ Printf(out, "nil");
+ } else
+ Printf(out, "nil");
+ }
+
+ void Sexp_print_list(DOH *obj) {
+ if (print_circle(obj, true)) {
+ open_paren(NIL);
+ for (; obj; obj = nextSibling(obj)) {
+ Sexp_print_doh(obj);
+ print_lazy_whitespace();
+ }
+ close_paren(true);
+ }
+ }
+
+ void Sexp_print_parms(DOH *obj) {
+ // print it as a list of plists
+ if (print_circle(obj, true)) {
+ open_paren(NIL);
+ for (; obj; obj = nextSibling(obj)) {
+ if (DohIsMapping(obj)) {
+ Iterator k;
+ open_paren(NIL);
+ for (k = First(obj); k.key; k = Next(k)) {
+ if (!internal_key_p(k.key)) {
+ DOH *value = Getattr(obj, k.key);
+ Sexp_print_as_keyword(k.key);
+ Sexp_print_value_of_key(value, k.key);
+ print_lazy_whitespace();
+ }
+ }
+ close_paren(true);
+ } else
+ Sexp_print_doh(obj);
+ print_lazy_whitespace();
+ }
+ close_paren(true);
+ }
+ }
+
+ void Sexp_print_doh(DOH *obj) {
+ flush_parens();
+ if (DohIsString(obj)) {
+ String *o = Str(obj);
+ Replaceall(o, "\\", "\\\\");
+ Replaceall(o, "\"", "\\\"");
+ Printf(out, "\"%s\"", o);
+ Delete(o);
+ } else {
+ if (print_circle(obj, false)) {
+ // Dispatch type
+ if (nodeType(obj)) {
+ Sexp_print_node(obj);
+ }
+
+ else if (DohIsMapping(obj)) {
+ Iterator k;
+ open_paren(NIL);
+ for (k = First(obj); k.key; k = Next(k)) {
+ if (!internal_key_p(k.key)) {
+ DOH *value = Getattr(obj, k.key);
+ flush_parens();
+ open_paren(NIL);
+ Sexp_print_doh(k.key);
+ Printf(out, " . ");
+ Sexp_print_value_of_key(value, k.key);
+ close_paren();
+ }
+ }
+ close_paren();
+ } else if (strcmp(ObjType(obj)->objname, "List") == 0) {
+ int i;
+ open_paren(NIL);
+ for (i = 0; i < Len(obj); i++) {
+ DOH *item = Getitem(obj, i);
+ Sexp_print_doh(item);
+ }
+ close_paren();
+ } else {
+ // What is it?
+ Printf(out, "#<DOH %s %x>", ObjType(obj)->objname, obj);
+ }
+ }
+ }
+ }
+
+ void Sexp_print_as_keyword(const DOH *k) {
+ /* Print key, replacing ":" with "-" because : is CL's package prefix */
+ flush_parens();
+ String *key = NewString(k);
+ Replaceall(key, ":", "-");
+ Replaceall(key, "_", "-");
+ Printf(out, ":%s ", key);
+ Delete(key);
+ }
+
+ void Sexp_print_plist_noparens(DOH *obj) {
+ /* attributes map names to objects */
+ Iterator k;
+ bool first;
+ for (k = First(obj), first = true; k.key; k = Next(k), first = false) {
+ if (!internal_key_p(k.key)) {
+ DOH *value = Getattr(obj, k.key);
+ flush_parens();
+ if (!first) {
+ Printf(out, " ");
+ }
+ Sexp_print_as_keyword(k.key);
+ /* Print value */
+ Sexp_print_value_of_key(value, k.key);
+ }
+ }
+ }
+
+ void Sexp_print_plist(DOH *obj) {
+ flush_parens();
+ if (print_circle(obj, true)) {
+ open_paren(NIL);
+ Sexp_print_plist_noparens(obj);
+ close_paren();
+ }
+ }
+
+ void Sexp_print_attributes(Node *obj) {
+ Sexp_print_plist_noparens(obj);
+ }
+
+ void Sexp_print_node(Node *obj) {
+ Node *cobj;
+ open_paren(nodeType(obj));
+ /* A node has an attribute list... */
+ Sexp_print_attributes(obj);
+ /* ... and child nodes. */
+ cobj = firstChild(obj);
+ if (cobj) {
+ print_lazy_newline();
+ flush_parens();
+ Sexp_print_as_keyword("children");
+ open_paren(NIL);
+ for (; cobj; cobj = nextSibling(cobj)) {
+ Sexp_print_node(cobj);
+ }
+ close_paren();
+ }
+ close_paren();
+ }
+
+
+ virtual int functionWrapper(Node *n) {
+ ParmList *l = Getattr(n, "parms");
+ Wrapper *f = NewWrapper();
+ emit_attach_parmmaps(l, f);
+ Setattr(n, "wrap:parms", l);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+};
+
+
+static Language *new_swig_sexp() {
+ return new Sexp();
+}
+extern "C" Language *swig_sexp(void) {
+ return new_swig_sexp();
+}
diff --git a/Source/Modules/swigmain.cxx b/Source/Modules/swigmain.cxx
new file mode 100644
index 0000000..aed915d
--- /dev/null
+++ b/Source/Modules/swigmain.cxx
@@ -0,0 +1,202 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * Simplified Wrapper and Interface Generator (SWIG)
+ *
+ * swigmain.cxx
+ *
+ * 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.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_swigmain_cxx[] = "$Id: swigmain.cxx 10969 2008-12-06 23:15:20Z wsfulton $";
+
+#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_tcl(void);
+ Language *swig_python(void);
+ Language *swig_perl5(void);
+ Language *swig_ruby(void);
+ Language *swig_guile(void);
+ Language *swig_modula3(void);
+ Language *swig_mzscheme(void);
+ Language *swig_java(void);
+ Language *swig_php(void);
+ Language *swig_php4(void);
+ Language *swig_ocaml(void);
+ Language *swig_octave(void);
+ Language *swig_pike(void);
+ Language *swig_sexp(void);
+ Language *swig_xml(void);
+ Language *swig_chicken(void);
+ Language *swig_csharp(void);
+ Language *swig_allegrocl(void);
+ Language *swig_lua(void);
+ Language *swig_clisp(void);
+ Language *swig_cffi(void);
+ Language *swig_uffi(void);
+ Language *swig_r(void);
+}
+
+struct swig_module {
+ const char *name;
+ ModuleFactory fac;
+ const char *help;
+};
+
+/* Association of command line options to language modules.
+ Place an entry for new language modules here, keeping the
+ list sorted alphabetically. */
+
+static swig_module modules[] = {
+ {"-allegrocl", swig_allegrocl, "ALLEGROCL"},
+ {"-chicken", swig_chicken, "CHICKEN"},
+ {"-clisp", swig_clisp, "CLISP"},
+ {"-cffi", swig_cffi, "CFFI"},
+ {"-csharp", swig_csharp, "C#"},
+ {"-guile", swig_guile, "Guile"},
+ {"-java", swig_java, "Java"},
+ {"-lua", swig_lua, "Lua"},
+ {"-modula3", swig_modula3, "Modula 3"},
+ {"-mzscheme", swig_mzscheme, "Mzscheme"},
+ {"-ocaml", swig_ocaml, "Ocaml"},
+ {"-octave", swig_octave, "Octave"},
+ {"-perl", swig_perl5, "Perl"},
+ {"-perl5", swig_perl5, 0},
+ {"-php", swig_php, "PHP"},
+ {"-php4", swig_php4, 0},
+ {"-php5", swig_php, 0},
+ {"-pike", swig_pike, "Pike"},
+ {"-python", swig_python, "Python"},
+ {"-r", swig_r, "R (aka GNU S)"},
+ {"-ruby", swig_ruby, "Ruby"},
+ {"-sexp", swig_sexp, "Lisp S-Expressions"},
+ {"-tcl", swig_tcl, "Tcl"},
+ {"-tcl8", swig_tcl, 0},
+ {"-uffi", swig_uffi, "Common Lisp / UFFI"},
+ {"-xml", swig_xml, "XML"},
+ {NULL, NULL, NULL}
+};
+
+#ifdef MACSWIG
+#include <console.h>
+#include <SIOUX.h>
+#endif
+
+#ifndef SWIG_LANG
+#define SWIG_LANG "-python"
+#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 = oargv;
+ return;
+ }
+
+ int argc = 1;
+ int arge = oargc + 1024;
+ char **argv = (char **) malloc(sizeof(char *) * (arge));
+ 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];
+ }
+
+ *nargc = argc;
+ *nargv = argv;
+}
+
+int main(int margc, char **margv) {
+ int i;
+ Language *dl = 0;
+ ModuleFactory fac = 0;
+
+ int argc;
+ char **argv;
+
+ SWIG_merge_envopt(getenv("SWIG_FEATURES"), margc, margv, &argc, &argv);
+
+#ifdef MACSWIG
+ SIOUXSettings.asktosaveonclose = false;
+ argc = ccommand(&argv);
+#endif
+
+ /* Register built-in modules */
+ for (i = 0; modules[i].name; i++) {
+ Swig_register_module(modules[i].name, modules[i].fac);
+ }
+
+ Swig_init_args(argc, argv);
+
+ /* Get options */
+ for (i = 1; i < argc; i++) {
+ if (argv[i]) {
+ fac = Swig_find_module(argv[i]);
+ if (fac) {
+ dl = (fac) ();
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nolang") == 0) {
+ dl = new Language;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-dnone") == 0) ||
+ (strcmp(argv[i], "-dhtml") == 0) ||
+ (strcmp(argv[i], "-dlatex") == 0) || (strcmp(argv[i], "-dascii") == 0) || (strcmp(argv[i], "-stat") == 0)) {
+ Printf(stderr, "swig: Warning. %s option deprecated.\n", argv[i]);
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-help") == 0) || (strcmp(argv[i], "--help") == 0)) {
+ if (strcmp(argv[i], "--help") == 0)
+ strcpy(argv[i], "-help");
+ Printf(stdout, "Target Language Options\n");
+ for (int j = 0; modules[j].name; j++) {
+ if (modules[j].help) {
+ 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
+ }
+ }
+ }
+ if (!dl) {
+ fac = Swig_find_module(SWIG_LANG);
+ if (fac) {
+ dl = (fac) ();
+ }
+ }
+ int res = SWIG_main(argc, argv, dl);
+ delete dl;
+ return res;
+}
diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h
new file mode 100644
index 0000000..dbb62b2
--- /dev/null
+++ b/Source/Modules/swigmod.h
@@ -0,0 +1,391 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * swigmod.h
+ *
+ * Main header file for SWIG modules.
+ * ----------------------------------------------------------------------------- */
+
+/* $Id: swigmod.h 11470 2009-07-29 20:50:39Z wsfulton $ */
+
+#ifndef SWIG_SWIGMOD_H_
+#define SWIG_SWIGMOD_H_
+
+#include "swig.h"
+#include "preprocessor.h"
+#include "swigwarn.h"
+
+#if !defined(HAVE_BOOL)
+typedef int bool;
+#define true ((bool)1)
+#define false ((bool)0)
+#endif
+
+#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);
+
+ 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);
+
+ /* 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); /* Add symbol */
+ virtual Node *symbolLookup(String *s); /* Symbol lookup */
+ virtual Node *classLookup(SwigType *s); /* Class lookup */
+ virtual 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();
+
+ /* Return the node for the current class */
+ Node *getCurrentClass() const;
+
+ /* Return C++ mode */
+ int getCPlusMode() 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;
+
+ /* 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;
+
+ /* Some language modules require additional wrappers for virtual methods not declared in sub-classes */
+ virtual bool extraDirectorProtectedCPPMethodsRequired() 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;
+
+private:
+ Hash *symbols;
+ Hash *classtypes;
+ Hash *enumtypes;
+ int overloading;
+ int multiinput;
+ int cplus_runtime;
+ int directors;
+ static Language *this_;
+};
+
+int SWIG_main(int, char **, Language *);
+void emit_parameter_variables(ParmList *l, Wrapper *f);
+void emit_return_variable(Node *n, SwigType *rt, Wrapper *f);
+void SWIG_exit(int); /* use EXIT_{SUCCESS,FAILURE} */
+void SWIG_config_file(const_String_or_char_ptr );
+const String *SWIG_output_directory();
+void SWIG_config_cppext(const char *ext);
+
+/* 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 *);
+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 *);
+String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int *);
+String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *);
+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 *rtype, SwigType *decl, const_String_or_char_ptr id, List *args, int strip, int values);
+String *Swig_director_declaration(Node *n);
+void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f);
+/* directors.cxx end */
+
+extern "C" {
+ void SWIG_typemap_lang(const char *);
+ typedef Language *(*ModuleFactory) (void);
+}
+
+void Swig_register_module(const char *name, ModuleFactory fac);
+ModuleFactory Swig_find_module(const char *name);
+
+/* 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) */
+int use_naturalvar_mode(Node *n);
+
+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);
+
+/* 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);
+
+
+#endif
diff --git a/Source/Modules/tcl8.cxx b/Source/Modules/tcl8.cxx
new file mode 100644
index 0000000..3ff69fe
--- /dev/null
+++ b/Source/Modules/tcl8.cxx
@@ -0,0 +1,1306 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * tcl8.cxx
+ *
+ * Tcl8 language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_tcl8_cxx[] = "$Id: tcl8.cxx 11518 2009-08-08 22:56:10Z wsfulton $";
+
+#include "swigmod.h"
+#include "cparse.h"
+static int treduce = SWIG_cparse_template_reduce(0);
+
+static const char *usage = (char *) "\
+Tcl 8 Options (available with -tcl)\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 nspace = 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[]) {
+ int cppcast = 1;
+
+ 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) {
+ nspace = 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], "-cppcast") == 0) {
+ cppcast = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocppcast") == 0) {
+ cppcast = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ }
+ }
+ }
+
+ if (cppcast) {
+ Preprocessor_define((DOH *) "SWIG_CPLUSPLUS_CAST", 0);
+ }
+
+ 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");
+ Printf(f_runtime, "#define SWIGTCL\n");
+ Printf(f_runtime, "\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_file_dirname(outfile), 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 (nspace) {
+ 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);
+ Close(f_shadow);
+ 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);
+ Close(f_begin);
+ 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, "result", f, actioncode))) {
+ Replaceall(tm, "$source", "result");
+#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, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
+ Replaceall(tm, "$source", "result");
+ 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);
+ Printf(df->code, "Tcl_SetResult(interp,(char *) \"No matching function for overloaded '%s'\", TCL_STATIC);\n", iname);
+ 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(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(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 = !nspace ? 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 (nspace)
+ 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;
+
+ 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);
+
+ // t = Copy(Getattr(n,"classtype"));
+ // SwigType_add_pointer(t);
+
+ String *rt = Copy(Getattr(n, "classtype"));
+ 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 (nspace) {
+
+ 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, "abstract") ? " - 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(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 };\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(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 (nspace) {
+ 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 (nspace) {
+ 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(Swig_name_member(class_name, symname)));
+ Printv(attr_tab, rname, ", ", NIL);
+ Delete(rname);
+ if (!GetFlag(n, "feature:immutable")) {
+ rname = Swig_name_wrapper(Swig_name_set(Swig_name_member(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 (nspace) {
+ 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);
+ }
+ }
+
+ 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 (nspace) {
+ 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/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx
new file mode 100644
index 0000000..6cb7f0a
--- /dev/null
+++ b/Source/Modules/typepass.cxx
@@ -0,0 +1,1164 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * 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.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_typepass_cxx[] = "$Id: typepass.cxx 11279 2009-06-16 19:29:08Z wsfulton $";
+
+#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;
+ Hash *classhash;
+ List *normalize;
+
+ TypePass() {
+ }
+
+ /* 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;
+ }
+ }
+ if (Strcmp(nodeType(bcls), "classforward") != 0) {
+ Swig_error(Getfile(cls), Getline(cls), "'%s' does not have a valid base class.\n", Getattr(cls, "name"));
+ Swig_error(Getfile(bcls), Getline(bcls), "'%s' is not a valid base class.\n", SwigType_namestr(bname));
+ } else {
+ Swig_warning(WARN_TYPE_INCOMPLETE, Getfile(cls), Getline(cls), "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 (!ilist)
+ ilist = alist = NewList();
+ Append(ilist, bcls);
+ } else {
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(cls), Getline(cls), "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) {
+ if (ispublic && !Getmeta(bname, "already_warned")) {
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(cls), Getline(cls), "Nothing known about base class '%s'. Ignored.\n", SwigType_namestr(bname));
+ if (Strchr(bname, '<')) {
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(cls), Getline(cls), "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 (!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", 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;
+ 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");
+ Node *oldinclass = inclass;
+ List *olist = normalize;
+ Symtab *symtab;
+ String *nname = 0;
+ String *fname = 0;
+ String *scopename = 0;
+
+ normalize = NewList();
+
+ if (name) {
+ if (SwigType_istemplate(name)) {
+ // We need to fully resolve the name to make templates work correctly */
+ Node *cn;
+ fname = SwigType_typedef_resolve_all(name);
+ if (Strcmp(fname, name) != 0 && (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);
+ 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);
+ }
+ } 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);
+ }
+
+ if (nsname) {
+ nname = NewStringf("%s::%s", nsname, name);
+ String *tdname = Getattr(n, "tdname");
+ if (tdname) {
+ tdname = NewStringf("%s::%s", nsname, tdname);
+ Setattr(n, "tdname", tdname);
+ }
+ }
+ SwigType_new_scope(scopename);
+ SwigType_attach_symtab(Getattr(n, "symtab"));
+
+ /* Inherit type definitions into the class */
+ if (name) {
+ 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);
+
+ /* 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;
+
+ inclass = oldinclass;
+
+ /* If in a namespace, patch the class name */
+ if (nname) {
+ Setattr(n, "name", nname);
+ Delete(nname);
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * namespaceDeclaration()
+ * ------------------------------------------------------------ */
+
+ 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); */
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classforwardDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int classforwardDeclaration(Node *n) {
+
+ /* Temporary hack. Can't do inside a class because it breaks
+ C nested structure wrapping */
+
+ if ((!inclass) || (CPlusPlus)) {
+ String *name = Getattr(n, "name");
+ String *nname;
+ SwigType_typedef_class(name);
+ if (nsname) {
+ nname = NewStringf("%s::%s", nsname, name);
+ Setattr(n, "name", nname);
+ }
+
+ }
+ 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) {
+ Node *ns;
+ /* Create a empty scope for the alias */
+ ns = Getattr(n, "namespace");
+ if (ns) {
+ 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;
+ nsname = Swig_symbol_qualified(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(nsname);
+ nsname = oldnsname;
+ return SWIG_OK;
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * cDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int cDeclaration(Node *n) {
+ if (NoExcept) {
+ Delattr(n, "throws");
+ }
+
+ /* Normalize types. */
+ SwigType *ty = Getattr(n, "type");
+ 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"));
+
+ /* If in a namespace, patch the class name */
+ if (nsname) {
+ String *nname = NewStringf("%s::%s", nsname, Getattr(n, "name"));
+ Setattr(n, "name", nname);
+ }
+ clean_overloaded(n);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * destructorDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int destructorDeclaration(Node *n) {
+ /* If in a namespace, patch the class name */
+ if (nsname) {
+ String *nname = NewStringf("%s::%s", nsname, Getattr(n, "name"));
+ Setattr(n, "name", nname);
+ }
+ 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);
+
+ // 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")) {
+ 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");
+ if (!value)
+ value = name;
+ if (Strcmp(value, name) == 0) {
+ String *new_value;
+ if (((nsname) || (inclass)) && cparse_cplusplus) {
+ new_value = NewStringf("%s::%s", SwigType_namestr(Swig_symbol_qualified(n)), value);
+ } else {
+ new_value = NewString(value);
+ }
+ 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.
+ return enumDeclaration(n);
+ }
+
+#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);
+ exit (1);
+ }
+
+ 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);
+ exit (1);
+ }
+ 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 (!(checkAttribute(c, "storage", "static")
+ || 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
+ 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"))
+ {
+#ifdef DEBUG_OVERLOADED
+show_overloaded(n);
+#endif
+ int cnt = 0;
+ Node *debugnode = n;
+ 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);
+ }
+ debugnode = firstoverloaded;
+ }
+ 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"));
+ }
+ }
+ }
+ 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/Source/Modules/uffi.cxx b/Source/Modules/uffi.cxx
new file mode 100644
index 0000000..780b9e8
--- /dev/null
+++ b/Source/Modules/uffi.cxx
@@ -0,0 +1,398 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * uffi.cxx
+ *
+ * Uffi language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+// TODO: remove remnants of lisptype
+
+char cvsroot_uffi_cxx[] = "$Id: uffi.cxx 11380 2009-07-08 12:17:45Z wsfulton $";
+
+#include "swigmod.h"
+
+class UFFI:public Language {
+public:
+
+ virtual void main(int argc, char *argv[]);
+ virtual int top(Node *n);
+ virtual int functionWrapper(Node *n);
+ virtual int constantWrapper(Node *n);
+ virtual int classHandler(Node *n);
+ virtual int membervariableHandler(Node *n);
+
+};
+
+static File *f_cl = 0;
+
+static struct {
+ int count;
+ String **entries;
+} defined_foreign_types;
+
+static const char *identifier_converter = "identifier-convert-null";
+
+static int any_varargs(ParmList *pl) {
+ Parm *p;
+
+ for (p = pl; p; p = nextSibling(p)) {
+ if (SwigType_isvarargs(Getattr(p, "type")))
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* utilities */
+/* returns new string w/ parens stripped */
+static String *strip_parens(String *string) {
+ char *s = Char(string), *p;
+ int len = Len(string);
+ String *res;
+
+ if (len == 0 || s[0] != '(' || s[len - 1] != ')') {
+ return NewString(string);
+ }
+
+ p = (char *) malloc(len - 2 + 1);
+ if (!p) {
+ Printf(stderr, "Malloc failed\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ strncpy(p, s + 1, len - 1);
+ p[len - 2] = 0; /* null terminate */
+
+ res = NewString(p);
+ free(p);
+
+ return res;
+}
+
+
+static String *convert_literal(String *num_param, String *type) {
+ String *num = strip_parens(num_param), *res;
+ char *s = Char(num);
+
+ /* Make sure doubles use 'd' instead of 'e' */
+ if (!Strcmp(type, "double")) {
+ String *updated = Copy(num);
+ if (Replace(updated, "e", "d", DOH_REPLACE_ANY) > 1) {
+ Printf(stderr, "Weird!! number %s looks invalid.\n", num);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(num);
+ return updated;
+ }
+
+ if (SwigType_type(type) == T_CHAR) {
+ /* Use CL syntax for character literals */
+ return NewStringf("#\\%s", num_param);
+ } else if (SwigType_type(type) == T_STRING) {
+ /* Use CL syntax for string literals */
+ return NewStringf("\"%s\"", num_param);
+ }
+
+ if (Len(num) < 2 || s[0] != '0') {
+ return num;
+ }
+
+ /* octal or hex */
+
+ res = NewStringf("#%c%s", s[1] == 'x' ? 'x' : 'o', s + 2);
+ Delete(num);
+
+ return res;
+}
+
+static void add_defined_foreign_type(String *type) {
+ if (!defined_foreign_types.count) {
+ /* Make fresh */
+ defined_foreign_types.count = 1;
+ defined_foreign_types.entries = (String **) malloc(sizeof(String *));
+ } else {
+ /* make room */
+ defined_foreign_types.count++;
+ defined_foreign_types.entries = (String **)
+ realloc(defined_foreign_types.entries, defined_foreign_types.count * sizeof(String *));
+ }
+
+ if (!defined_foreign_types.entries) {
+ Printf(stderr, "Out of memory\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ /* Fill in the new data */
+ defined_foreign_types.entries[defined_foreign_types.count - 1] = Copy(type);
+
+}
+
+
+static String *get_ffi_type(Node *n, SwigType *ty, const_String_or_char_ptr name) {
+ Node *node = NewHash();
+ Setattr(node, "type", ty);
+ Setattr(node, "name", name);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *tm = Swig_typemap_lookup("ffitype", node, "", 0);
+ Delete(node);
+
+ if (tm) {
+ return NewString(tm);
+ } else {
+ SwigType *tr = SwigType_typedef_resolve_all(ty);
+ char *type_reduced = Char(tr);
+ int i;
+
+ //Printf(stdout,"convert_type %s\n", ty);
+ if (SwigType_isconst(tr)) {
+ SwigType_pop(tr);
+ type_reduced = Char(tr);
+ }
+
+ if (SwigType_ispointer(type_reduced) || SwigType_isarray(ty) || !strncmp(type_reduced, "p.f", 3)) {
+ return NewString(":pointer-void");
+ }
+
+ for (i = 0; i < defined_foreign_types.count; i++) {
+ if (!Strcmp(ty, defined_foreign_types.entries[i])) {
+ return NewStringf("#.(%s \"%s\" :type :type)", identifier_converter, ty);
+ }
+ }
+
+ if (!Strncmp(type_reduced, "enum ", 5)) {
+ return NewString(":int");
+ }
+
+ Printf(stderr, "Unsupported data type: %s (was: %s)\n", type_reduced, ty);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ return 0;
+}
+
+static String *get_lisp_type(Node *n, SwigType *ty, const_String_or_char_ptr name) {
+ Node *node = NewHash();
+ Setattr(node, "type", ty);
+ Setattr(node, "name", name);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *tm = Swig_typemap_lookup("lisptype", node, "", 0);
+ Delete(node);
+
+ return tm ? NewString(tm) : NewString("");
+}
+
+void UFFI::main(int argc, char *argv[]) {
+ int i;
+
+ Preprocessor_define("SWIGUFFI 1", 0);
+ SWIG_library_directory("uffi");
+ SWIG_config_file("uffi.swg");
+
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-identifier-converter")) {
+ char *conv = argv[i + 1];
+
+ if (!conv)
+ Swig_arg_error();
+
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+
+ /* check for built-ins */
+ if (!strcmp(conv, "lispify")) {
+ identifier_converter = "identifier-convert-lispify";
+ } else if (!strcmp(conv, "null")) {
+ identifier_converter = "identifier-convert-null";
+ } else {
+ /* Must be user defined */
+ char *idconv = new char[strlen(conv) + 1];
+ strcpy(idconv, conv);
+ identifier_converter = idconv;
+ }
+ }
+
+ if (!strcmp(argv[i], "-help")) {
+ fprintf(stdout, "UFFI Options (available with -uffi)\n");
+ fprintf(stdout,
+ " -identifier-converter <type or funcname>\n"
+ "\tSpecifies the type of conversion to do on C identifiers to convert\n"
+ "\tthem to symbols. There are two built-in converters: 'null' and\n"
+ "\t 'lispify'. The default is 'null'. If you supply a name other\n"
+ "\tthan one of the built-ins, then a function by that name will be\n"
+ "\tcalled to convert identifiers to symbols.\n");
+ }
+ }
+}
+
+int UFFI::top(Node *n) {
+ String *module = Getattr(n, "name");
+ String *output_filename = NewString("");
+ File *f_null = NewString("");
+
+ Printf(output_filename, "%s%s.cl", SWIG_output_directory(), module);
+
+
+ f_cl = NewFile(output_filename, "w", SWIG_output_files());
+ if (!f_cl) {
+ FileErrorDisplay(output_filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ Swig_register_filebyname("header", f_null);
+ Swig_register_filebyname("begin", f_null);
+ Swig_register_filebyname("runtime", f_null);
+ Swig_register_filebyname("wrapper", f_cl);
+
+ Swig_banner_target_lang(f_cl, ";;");
+
+ Printf(f_cl, "\n"
+ ";; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; package: %s -*-\n\n(defpackage :%s\n (:use :common-lisp :uffi))\n\n(in-package :%s)\n",
+ module, module, module);
+ Printf(f_cl, "(eval-when (compile load eval)\n (defparameter *swig-identifier-converter* '%s))\n", identifier_converter);
+
+ Language::top(n);
+
+ Close(f_cl);
+ Delete(f_cl); // Delete the handle, not the file
+ Close(f_null);
+ Delete(f_null);
+
+ return SWIG_OK;
+}
+
+int UFFI::functionWrapper(Node *n) {
+ String *funcname = Getattr(n, "sym:name");
+ ParmList *pl = Getattr(n, "parms");
+ Parm *p;
+ int argnum = 0, first = 1, varargs = 0;
+
+ //Language::functionWrapper(n);
+
+ Printf(f_cl, "(swig-defun \"%s\"\n", funcname);
+ Printf(f_cl, " (");
+
+ /* Special cases */
+
+ if (ParmList_len(pl) == 0) {
+ Printf(f_cl, ":void");
+ } else if (any_varargs(pl)) {
+ Printf(f_cl, "#| varargs |#");
+ varargs = 1;
+ } else {
+ for (p = pl; p; p = nextSibling(p), argnum++) {
+ String *argname = Getattr(p, "name");
+ SwigType *argtype = Getattr(p, "type");
+ String *ffitype = get_ffi_type(n, argtype, argname);
+ String *lisptype = get_lisp_type(n, argtype, argname);
+ int tempargname = 0;
+
+ if (!argname) {
+ argname = NewStringf("arg%d", argnum);
+ tempargname = 1;
+ }
+
+ if (!first) {
+ Printf(f_cl, "\n ");
+ }
+ Printf(f_cl, "(%s %s %s)", argname, ffitype, lisptype);
+ first = 0;
+
+ Delete(ffitype);
+ Delete(lisptype);
+ if (tempargname)
+ Delete(argname);
+
+ }
+ }
+ Printf(f_cl, ")\n"); /* finish arg list */
+ Printf(f_cl, " :returning %s\n"
+ //" :strings-convert t\n"
+ //" :call-direct %s\n"
+ //" :optimize-for-space t"
+ ")\n", get_ffi_type(n, Getattr(n, "type"), "result")
+ //,varargs ? "nil" : "t"
+ );
+
+
+ return SWIG_OK;
+}
+
+int UFFI::constantWrapper(Node *n) {
+ String *type = Getattr(n, "type");
+ String *converted_value = convert_literal(Getattr(n, "value"), type);
+ String *name = Getattr(n, "sym:name");
+
+#if 0
+ Printf(stdout, "constant %s is of type %s. value: %s\n", name, type, converted_value);
+#endif
+
+ Printf(f_cl, "(swig-defconstant \"%s\" %s)\n", name, converted_value);
+
+ Delete(converted_value);
+
+ return SWIG_OK;
+}
+
+// Includes structs
+int UFFI::classHandler(Node *n) {
+
+ String *name = Getattr(n, "sym:name");
+ String *kind = Getattr(n, "kind");
+ Node *c;
+
+ if (Strcmp(kind, "struct")) {
+ Printf(stderr, "Don't know how to deal with %s kind of class yet.\n", kind);
+ Printf(stderr, " (name: %s)\n", name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ Printf(f_cl, "(swig-def-struct \"%s\"\n \n", name);
+
+ for (c = firstChild(n); c; c = nextSibling(c)) {
+ SwigType *type = Getattr(c, "type");
+ SwigType *decl = Getattr(c, "decl");
+ type = Copy(type);
+ SwigType_push(type, decl);
+ String *lisp_type;
+
+ if (Strcmp(nodeType(c), "cdecl")) {
+ Printf(stderr, "Structure %s has a slot that we can't deal with.\n", name);
+ Printf(stderr, "nodeType: %s, name: %s, type: %s\n", nodeType(c), Getattr(c, "name"), Getattr(c, "type"));
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+
+ /* Printf(stdout, "Converting %s in %s\n", type, name); */
+ lisp_type = get_ffi_type(n, type, Getattr(c, "sym:name"));
+
+ Printf(f_cl, " (#.(%s \"%s\" :type :slot) %s)\n", identifier_converter, Getattr(c, "sym:name"), lisp_type);
+
+ Delete(lisp_type);
+ }
+
+ // Language::classHandler(n);
+
+ Printf(f_cl, " )\n");
+
+ /* Add this structure to the known lisp types */
+ //Printf(stdout, "Adding %s foreign type\n", name);
+ add_defined_foreign_type(name);
+
+ return SWIG_OK;
+}
+
+int UFFI::membervariableHandler(Node *n) {
+ Language::membervariableHandler(n);
+ return SWIG_OK;
+}
+
+
+extern "C" Language *swig_uffi(void) {
+ return new UFFI();
+}
diff --git a/Source/Modules/utils.cxx b/Source/Modules/utils.cxx
new file mode 100644
index 0000000..496700a
--- /dev/null
+++ b/Source/Modules/utils.cxx
@@ -0,0 +1,98 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * utils.cxx
+ *
+ * Various utility functions.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_utils_cxx[] = "$Id: utils.cxx 10423 2008-05-07 20:59:00Z wsfulton $";
+
+#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")) {
+ if (is_member_director_helper(Getattr(n, "parentNode"), n))
+ 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");
+ }
+}
diff --git a/Source/Modules/xml.cxx b/Source/Modules/xml.cxx
new file mode 100644
index 0000000..a3d393a
--- /dev/null
+++ b/Source/Modules/xml.cxx
@@ -0,0 +1,320 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * xml.cxx
+ *
+ * An Xml parse tree generator.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_xml_cxx[] = "$Id: xml.cxx 10898 2008-11-03 12:51:45Z wsfulton $";
+
+#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");
+ Replaceall(outfile, ".cxx", ".xml");
+ Replaceall(outfile, ".cpp", ".xml");
+ Replaceall(outfile, ".c", ".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=\"%x\" >\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 {
+ 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=\"%x\" />\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=\"%x\" id=\"%ld\" addr=\"%x\" />\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=\"%x\" >\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) {
+
+ print_indent(0);
+ Printf(out, "<parmlist id=\"%ld\" addr=\"%x\" >\n", ++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, "</parmlist >\n");
+ }
+
+ void Xml_print_baselist(List *p) {
+
+ print_indent(0);
+ Printf(out, "<baselist id=\"%ld\" addr=\"%x\" >\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=\"%x\" />\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=\"%x\" />\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=\"%x\" >\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=\"%x\" >\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();
+}