From 74a3aa015c7a5e8e5ce00781d2c97fccd5e1bb47 Mon Sep 17 00:00:00 2001 From: Dave Beazley Date: Tue, 3 Dec 2002 20:33:35 +0000 Subject: [PATCH] File move git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@4150 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- Source/Modules/Makefile.in | 41 + Source/Modules/README | 9 + Source/Modules/allocate.cxx | 453 ++++++++ Source/Modules/browser.cxx | 415 +++++++ Source/Modules/contract.cxx | 118 ++ Source/Modules/emit.cxx | 452 ++++++++ Source/Modules/guile.cxx | 1208 ++++++++++++++++++++ Source/Modules/java.cxx | 1900 +++++++++++++++++++++++++++++++ Source/Modules/lang.cxx | 1853 ++++++++++++++++++++++++++++++ Source/Modules/main.cxx | 622 +++++++++++ Source/Modules/module.cxx | 57 + Source/Modules/mzscheme.cxx | 668 +++++++++++ Source/Modules/ocaml.cxx | 1072 ++++++++++++++++++ Source/Modules/overload.cxx | 338 ++++++ Source/Modules/perl5.cxx | 1594 ++++++++++++++++++++++++++ Source/Modules/php4.cxx | 2113 +++++++++++++++++++++++++++++++++++ Source/Modules/pike.cxx | 881 +++++++++++++++ Source/Modules/python.cxx | 1268 +++++++++++++++++++++ Source/Modules/ruby.cxx | 1440 ++++++++++++++++++++++++ Source/Modules/s-exp.cxx | 401 +++++++ Source/Modules/swigmain.cxx | 153 +++ Source/Modules/swigmod.h | 255 +++++ Source/Modules/tcl8.cxx | 832 ++++++++++++++ Source/Modules/typepass.cxx | 966 ++++++++++++++++ Source/Modules/xml.cxx | 318 ++++++ 25 files changed, 19427 insertions(+) create mode 100644 Source/Modules/Makefile.in create mode 100644 Source/Modules/README create mode 100644 Source/Modules/allocate.cxx create mode 100644 Source/Modules/browser.cxx create mode 100644 Source/Modules/contract.cxx create mode 100644 Source/Modules/emit.cxx create mode 100644 Source/Modules/guile.cxx create mode 100644 Source/Modules/java.cxx create mode 100644 Source/Modules/lang.cxx create mode 100644 Source/Modules/main.cxx create mode 100644 Source/Modules/module.cxx create mode 100644 Source/Modules/mzscheme.cxx create mode 100755 Source/Modules/ocaml.cxx create mode 100644 Source/Modules/overload.cxx create mode 100644 Source/Modules/perl5.cxx create mode 100644 Source/Modules/php4.cxx create mode 100644 Source/Modules/pike.cxx create mode 100644 Source/Modules/python.cxx create mode 100644 Source/Modules/ruby.cxx create mode 100644 Source/Modules/s-exp.cxx create mode 100644 Source/Modules/swigmain.cxx create mode 100644 Source/Modules/swigmod.h create mode 100644 Source/Modules/tcl8.cxx create mode 100644 Source/Modules/typepass.cxx create mode 100644 Source/Modules/xml.cxx diff --git a/Source/Modules/Makefile.in b/Source/Modules/Makefile.in new file mode 100644 index 000000000..353a59699 --- /dev/null +++ b/Source/Modules/Makefile.in @@ -0,0 +1,41 @@ +####################################################################### +# $Header$ +####################################################################### + +srcdir = @srcdir@ +VPATH = @srcdir@ + +SHELL = /bin/sh +CXX = @CXX@ +CFLAGS = @CFLAGS@ @SWILL@ +YACC = @YACC@ +AR = @AR@ +RANLIB = @RANLIB@ + +TARGET = libmodules.a +OBJS = main.@OBJEXT@ module.@OBJEXT@ emit.@OBJEXT@ overload.@OBJEXT@ lang.@OBJEXT@ typepass.@OBJEXT@ allocate.@OBJEXT@ browser.@OBJEXT@ contract.@OBJEXT@ swigmain.@OBJEXT@ tcl8.@OBJEXT@ python.@OBJEXT@ perl5.@OBJEXT@ guile.@OBJEXT@ ruby.@OBJEXT@ mzscheme.@OBJEXT@ java.@OBJEXT@ php4.@OBJEXT@ ocaml.@OBJEXT@ xml.@OBJEXT@ pike.@OBJEXT@ s-exp.@OBJEXT@ +SRCS = main.cxx module.cxx emit.cxx overload.cxx lang.cxx typepass.cxx allocate.cxx browser.cxx contract.cxx swigmain.cxx tcl8.cxx python.cxx perl5.cxx guile.cxx ruby.cxx mzscheme.cxx java.cxx php4.cxx ocaml.cxx xml.cxx pike.cxx s-exp.cxx + +INCLUDES = -I$(srcdir)/../Include \ + -I$(srcdir)/../DOH/Include \ + -I$(srcdir)/../Preprocessor \ + -I$(srcdir)/../Swig \ + -I../Include + +# Rules for creation of a .@OBJEXT@ file from .cxx +.SUFFIXES: .cxx +.cxx.@OBJEXT@: + $(CXX) $(INCLUDES) $(CFLAGS) -c -o $*.@OBJEXT@ $< + + +swig: $(TARGET) + +$(TARGET): $(OBJS) + $(AR) cr $(TARGET) $(OBJS) + $(RANLIB) $(TARGET) + +clean:: + rm -f *.@OBJEXT@ *~ $(TARGET) + +nuke:: + rm -f Makefile *~ diff --git a/Source/Modules/README b/Source/Modules/README new file mode 100644 index 000000000..058779d22 --- /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/allocate.cxx b/Source/Modules/allocate.cxx new file mode 100644 index 000000000..4d7db5fae --- /dev/null +++ b/Source/Modules/allocate.cxx @@ -0,0 +1,453 @@ +/* ----------------------------------------------------------------------------- + * 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. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1998-2002. The University of Chicago + * Copyright (C) 1995-1998. The University of Utah and The Regents of the + * University of California. + * + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_allocate_cxx[] = "$Header$"; + +#include "swigmod.h" + +class Allocate : public Dispatcher { + Node *inclass; + enum AccessMode { PUBLIC, PRIVATE, PROTECTED }; + AccessMode cplus_mode; + int extendmode; + + /* Checks to see if a class is abstract through inheritance */ + 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) { + for (int i = 0; i < Len(abstract); i++) { + Node *nn = Getitem(abstract,i); + String *name = Getattr(nn,"name"); + String *base_decl = Getattr(nn,"decl"); + if (Strstr(name,"~")) continue; /* Don't care about destructors */ + int implemented = 0; + Node *dn = Swig_symbol_clookup(name,0); + if (!dn) { + Printf(stdout,"node: %x '%s'. base: %x '%s'. member '%s'\n", n, Getattr(n,"name"), base, Getattr(base,"name"), name); + } + assert(dn); // Assertion of doom + while (dn && !implemented) { + String *local_decl = Getattr(dn,"decl"); + if (local_decl && !Strcmp(local_decl, base_decl)) { + if (Getattr(dn,"abstract")) return 1; + implemented++; + } + dn = Getattr(dn,"csym:nextSibling"); + } + if (!implemented && (Getattr(nn,"abstract"))) { + return 1; + } + /* + if (dn && (Getattr(dn,"abstract"))) { + return 1; + } + */ + } + } + List *bases = Getattr(base,"bases"); + 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) { + if (!methods) { + methods = NewList(); + } + + Node *c = firstChild(cls); + String *kind = Getattr(cls,"kind"); + int mode; + if (Strcmp(kind,"class") == 0) mode = PRIVATE; + else mode = PUBLIC; + + while (c) { + if (Getattr(c,"error") || Getattr(c,"feature:ignore")) { + c = nextSibling(c); + continue; + } + if (Strcmp(nodeType(c),"cdecl") == 0) { + if (!Getattr(c,"feature:ignore")) { + String *storage = Getattr(c,"storage"); + if (!((Cmp(storage,"static") == 0) || (Cmp(storage,"typedef") == 0))) { + String *name = Getattr(c,"name"); + String *symname = Getattr(c,"sym:name"); + Node *e = Swig_symbol_clookup_local(name,0); + if (e && !Getattr(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->() at %s:%d\n", + name, Getfile(c),Getline(c)); + } 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) { + Append(methods,cc); + 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); + } + } + /* Remove protected/private members */ + { + for (int i = 0; i < Len(methods); ) { + Node *n = Getitem(methods,i); + if (checkAttribute(n,"access","protected") || checkAttribute(n,"access","private")) { + 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); + Node *c = Swig_symbol_clookup(t,0); + if (c) { + Setattr(c,"cplus:exceptionclass","1"); + } + p = nextSibling(p); + } + } + +public: + 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 (is_abstract_inherit(n)) { + if ((!Getattr(n,"abstract")) && ((Getattr(n,"allocate:public_constructor") || (!Getattr(n,"feature:nodefault") && !Getattr(n,"allocate:has_constructor"))))) { + if (!Getattr(n,"feature:notabstract")) { + Swig_warning(WARN_TYPE_ABSTRACT,Getfile(n),Getline(n),"Class '%s' might be abstract. No constructors generated. \n", SwigType_namestr(Getattr(n,"name"))); + Setattr(n,"abstract",NewList()); + } + } + } + + 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,"bases"); + 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_destructor")) { + /* No destructor was defined. We need to check a few things here too */ + List *bases = Getattr(n,"bases"); + 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"); + } + } + + + /* 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 (Getattr(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 cDeclaration(Node *n) { + + mark_exception_classes(Getattr(n,"throws")); + + if (inclass) { + String *name = Getattr(n,"name"); + if (cplus_mode != PUBLIC) { + /* Look for a private assignment operator */ + if (Strcmp(name,"operator =") == 0) { + Setattr(inclass,"allocate:noassign","1"); + } + } else { + /* Look for smart pointer operator */ + if ((Strcmp(name,"operator ->") == 0) && (!Getattr(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.")) { + List *methods = smart_pointer_methods(sc,0); + Setattr(inclass,"allocate:smartpointer",methods); + break; + } 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) { + sn = nn; + continue; + } else { + break; + } + } else { + break; + } + } + } else { + break; + } + } else { + break; + } + } + } + } + } + return SWIG_OK; + } + + virtual int constructorDeclaration(Node *n) { + if (!inclass) return SWIG_OK; + Parm *parms = Getattr(n,"parms"); + + mark_exception_classes(Getattr(n,"throws")); + 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"); + } + } + + /* 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 *) */ + + String *cc = NewStringf("r.q(const).%s", Getattr(inclass,"name")); + if (Strcmp(cc,Getattr(parms,"type")) == 0) { + Setattr(n,"copy_constructor","1"); + } + Delete(cc); + cc = NewStringf("r.%s", Getattr(inclass,"name")); + if (Strcmp(cc,Getattr(parms,"type")) == 0) { + Setattr(n,"copy_constructor","1"); + } + Delete(cc); + cc = NewStringf("p.%s", Getattr(inclass,"name")); + String *ty = SwigType_strip_qualifiers(Getattr(parms,"type")); + if (Strcmp(cc,ty) == 0) { + Setattr(n,"copy_constructor","1"); + } + Delete(cc); + Delete(ty); + } + return SWIG_OK; + } + + virtual int destructorDeclaration(Node *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 000000000..da90a81b8 --- /dev/null +++ b/Source/Modules/browser.cxx @@ -0,0 +1,415 @@ +/* ----------------------------------------------------------------------------- + * browser.cxx + * + * A web-base parse tree browser using SWILL. This is an optional + * feature that's normally disabled. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 2002. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_browser_cxx[] = "$Header$"; + +#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,"[-] ", n, t, n,n); + } else { + Printf(out,"[+] ", n, t, n,n); + } + } + void show_attributes(Node *obj) { + if (!Getmeta(obj,"visible")) return; + String *os = NewString(""); + String *k; + k = Firstkey(obj); + while (k) { + 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,"&","&"); + Replaceall(o,"<","<"); + Replaceall(o,">",">"); + Printf(os,"? %-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,"&","&"); + Replaceall(o,"<","<"); + Printf(os,"? %-12s - \"%(escape)-0.70s%s\"\n", Getattr(obj,k), k, o, trunc); + Delete(o); + } else { + Printf(os,"? %-12s - 0x%x\n", Getattr(obj,k), k, Getattr(obj,k)); + } + } + k = Nextkey(obj); + } + Printf(out,"
\n%s
\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,"%s", n, tag); + if (name) { + Printf(out," (%s)", name); + } + Printf(out,". %s:%d\n", file, line); + Printf(out,"
"); + Dispatcher::emit_one(n); + return SWIG_OK; + } + virtual int emit_children(Node *n) { + if (Getmeta(n,"visible")) { + Printf(out,"
\n"); + Dispatcher::emit_children(n); + Printf(out,"
\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,"SWIG-%s\n", SWIG_VERSION); + Printf(f,"SWIG-%s
\n", SWIG_VERSION); + Printf(f,"[ Exit ]"); + Printf(f," [ Top ]", tree_top); + if (n != tree_top) { + Printf(f," [ Up ]", parentNode(n)); + } + Printf(f," [ Symbols ]"); + Printf(f,"

\n"); + + out = f; + + browse->emit_one(n); + + /* Print standard footer */ + Printf(f,"


\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; + String *os = NewString(""); + Printf(os,"Hash {\n"); + k = Firstkey(obj); + while (k) { + DOH *o; + const char *trunc = ""; + if (DohIsString(Getattr(obj,k))) { + o = Str(Getattr(obj,k)); + if (Len(o) > 70) { + trunc = "..."; + } + Replaceall(o,"<","<"); + Printf(os," ? %-12s - \"%(escape)-0.70s%s\"\n", Getattr(obj,k), k, o, trunc); + Delete(o); + } else { + Printf(os," ? %-12s - 0x%x\n", Getattr(obj,k), k, Getattr(obj,k)); + } + k = Nextkey(obj); + } + Printf(os,"}\n"); + Printf(out,"
\n%s
\n", Char(os)); + Delete(os); + } else if (DohIsString(obj)) { + String *o = Str(obj); + Replaceall(o,"<","<"); + Printf(out,"
\n%s
\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,"<","<"); + Printf(os," ? [%d] - \"%(escape)-0.70s%s\"\n", o,i,s, trunc); + Delete(s); + } else { + Printf(os," ? [%d] - 0x%x\n", o, i, o); + } + } + Printf(os,"\n]\n"); + Printf(out,"
\n%s
\n", Char(os)); + Delete(os); + } +} + +void data_handler(FILE *f) { + DOH *n = 0; + if (!swill_getargs("p(n)", &n)) { + n = 0; + } + Printf(f,"SWIG-%s\n", SWIG_VERSION); + Printf(f,"SWIG-%s
\n", SWIG_VERSION); + Printf(f,"[ Exit ]"); + Printf(f," [ Top ]", tree_top); + Printf(f,"

\n"); + if (n) { + raw_data(f,n); + } + /* Print standard footer */ + Printf(f,"


\n"); +} + +void symbol_handler(FILE *f) { + Symtab *sym; + char *name = 0; + + Printf(f,"SWIG-%s\n", SWIG_VERSION); + Printf(f,"SWIG-%s
\n", SWIG_VERSION); + Printf(f,"[ Exit ]"); + Printf(f," [ Top ]", tree_top); + Printf(f," [ Symbols ]"); + Printf(f,"

\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,"Symbol table: :: (global)
\n"); + } else { + Printf(f,"Symbol table: %s
\n", q); + } + Delete(q); + } + + fprintf(f,"

\n"); + fprintf(f,"Symbol lookup:
\n"); + fprintf(f,"\n", sym); + fprintf(f,"Submit : \n"); + fprintf(f,"
"); + + if (name) { + Node *n = Swig_symbol_clookup(name,sym); + Printf(f,"Symbol '%s':\n", name); + Printf(f,"
\n"); + if (!n) { + Printf(f,"Not defined!\n"); + } else { + raw_data(f,n); + } + Printf(f,"
\n"); + } + + Printf(f,"

Nested scopes
\n"); + Printf(f,"

\n");
+  {
+    Hash   *h;
+    h = firstChild(sym);
+    while (h) {
+      Printf(f,"%s\n", h, Getattr(h,"name"));
+      h = nextSibling(h);
+    }
+  }
+  Printf(f,"
\n"); + + Printf(f,"

Symbol table contents
\n"); + raw_data(f,Getattr(sym,"symtab")); + Printf(f,"


\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; +#endif +} + + + + + diff --git a/Source/Modules/contract.cxx b/Source/Modules/contract.cxx new file mode 100644 index 000000000..fba5827aa --- /dev/null +++ b/Source/Modules/contract.cxx @@ -0,0 +1,118 @@ +/* ----------------------------------------------------------------------------- + * contract.cxx + * + * Experimental support for contracts + * + * Author(s) : Aquinas Hobor (aahobor@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_contract_cxx[] = "$Header$"; + +#include "swigmod.h" + +class Contracts : public Dispatcher { + +public: + virtual int top(Node *n) { + 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); } + + String * strParms(ParmList *l) { + int comma = 0; + int i = 0; + Parm *p = l; + SwigType *pt; + String * returns = NewString(""); + while(p) { + String *pname; + pt = Getattr(p,"type"); + if ((SwigType_type(pt) != T_VOID)) { + if (comma) Printf(returns,","); + pname = Swig_cparm_name(p,i); + Printf(returns,"%s",SwigType_rcaststr(pt,pname)); + comma = 1; + i++; + } + p = nextSibling(p); + } + return returns; + } + + virtual int cDeclaration(Node *n) { + String *name = Getattr(n,"name"); + String *k = Getattr(n,"feature:contract"); + + if(k) + { + /* make the names */ + ParmList *l = Getmeta(k,"parms"); + String *params = ParmList_str(l); + String *transformed = strParms(l); + if(DohStrcmp(params,"")==0) { + DohDelete(params); + params = DohNewString("void"); + } + String *contractName = DohNewStringf("__SWIG_precontract_%s",name); + + /* make the contract */ + String *contract = DohNewStringf("int %s(%s,int rt[2])\n{\n",contractName,params); + SwigScanner * ss = NewSwigScanner(); + SwigScanner_clear(ss); + SwigScanner_push(ss,Copy(k)); + SwigScanner_token(ss); // Get rid of the '{' at the begining + + /* loop over the clauses */ + int clauseNum = 1; + int token = -1; + while(1) { + String *clause = DohNewString(""); /*BUG -- should free*/ + while((token=SwigScanner_token(ss))) { + if ((token==SWIG_TOKEN_SEMI)||(token==SWIG_TOKEN_RBRACE)) + break; + // if (token != SWIG_TOKEN_ENDLINE) + Printf(clause,"%s",SwigScanner_text(ss)); + } + if (DohStrcmp(clause,"\n") != 0) { + Printf(contract,"if (!(%s",clause); + Printf(contract,")) {\nrt[0]=__LINE__;\nrt[1]=%i;\nreturn 1;\n}\n",clauseNum); + } + if(token==SWIG_TOKEN_RBRACE) break; + clauseNum++; + } + + /* finish it off and attach it to the main tree */ + Printf(contract,"return 0;\n}\n"); + Setattr(n,"wrap:code",contract); /*BUG -- WHAT IF SOMETHING IS ALREADY THERE*/ + + /* Generate the calling code */ + String * calling = DohNewString("{\nint cfail[2];\nchar message[255];\n"); + Printf(calling,"if (%s(%s,cfail)) {\n",contractName,transformed); + Printf(calling,"sprintf(message,\"Contract %s failed on clause %%i (line %%i)!\",cfail[1],cfail[0]);\n",contractName); + Printf(calling,"PyErr_SetString(PyExc_Exception,message);return NULL;\n}\n"); + Printf(calling,"}\n"); + /* Setattr(n,"feature:preassert",calling); */ + } + /*There are two attributes "feature:preassert" and "feature:postassert".*/ + + + return SWIG_OK; + } + +}; + +void Swig_contracts(Node *n) { + Printf(stdout,"Applying contracts (experimental v0.09)\n"); + + Contracts *a = new Contracts; + a->top(n); + delete a; + +} diff --git a/Source/Modules/emit.cxx b/Source/Modules/emit.cxx new file mode 100644 index 000000000..1f4bcf8bb --- /dev/null +++ b/Source/Modules/emit.cxx @@ -0,0 +1,452 @@ +/* ----------------------------------------------------------------------------- + * emit.cxx + * + * Useful functions for emitting various pieces of code. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1998-2000. The University of Chicago + * Copyright (C) 1995-1998. The University of Utah and The Regents of the + * University of California. + * + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +#include "swigmod.h" + +char cvsroot_emit_cxx[] = "$Header$"; + +extern SwigType *cplus_value_type(SwigType *t); + +/* ----------------------------------------------------------------------------- + * emit_args() + * + * Creates a list of variable declarations for both the return value + * and function parameters. + * + * The return value is always called result and arguments arg0, arg1, arg2, etc... + * Returns the number of parameters associated with a function. + * ----------------------------------------------------------------------------- */ + +void emit_args(SwigType *rt, ParmList *l, Wrapper *f) { + + Parm *p; + String *tm; + + /* Emit function arguments */ + Swig_cargs(f, l); + + /* Handle return type */ + if (rt && (SwigType_type(rt) != T_VOID)) { + if (!CPlusPlus || (CPlusPlus && !SwigType_isclass(rt))) { + Wrapper_add_local(f,"result", SwigType_lstr(rt,"result")); + } else { + SwigType *vt = 0; + vt = cplus_value_type(rt); + if (!vt) { + Wrapper_add_local(f,"result", SwigType_lstr(rt,"result")); + } else { + Wrapper_add_local(f,"result", SwigType_lstr(vt,"result")); + Delete(vt); + } + } + } + + /* 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); + } + } + +#ifdef DEPRECATED + /* Apply the ignore typemap */ + p = l; + while (p) { + tm = Getattr(p,"tmap:ignore"); + if (tm) { + Parm *np; + Replace(tm,"$target", Getattr(p,"lname"), DOH_REPLACE_ANY); + Printv(f->code,tm,"\n",NIL); + np = Getattr(p,"tmap:ignore:next"); + + /* Deprecate this part later */ + while (p && (p != np)) { + Setattr(p,"ignore","1"); + p = nextSibling(p); + } + /* -- end deprecate */ + + } else { + p = nextSibling(p); + } + } +#endif + return; +} + +/* ----------------------------------------------------------------------------- + * 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"); + 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() ** new in 1.3.10 + * + * Calculate the total number of arguments. This function is safe for use + * with multi-valued 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); + } + } + +#ifdef DEPRECATED + while (p) { + /* Ignored arguments */ + if (Getattr(p,"tmap:ignore")) { + p = Getattr(p,"tmap:ignore:next"); + } else { + /* Marshalled arguments */ + nargs++; + if (Getattr(p,"tmap:in")) { + p = Getattr(p,"tmap:in:next"); + } else { + p = nextSibling(p); + } + } + } +#endif + if (parms && (p = Getattr(parms,"emit:varargs"))) { + if (!nextSibling(p)) { + nargs--; + } + } + return nargs; +} + +/* ----------------------------------------------------------------------------- + * emit_num_required() ** new in 1.3.10 + * + * Computes the number of required arguments. This is function is safe for + * use with multi-valued typemaps and knows how to skip over everything + * properly. + * ----------------------------------------------------------------------------- */ + +int emit_num_required(ParmList *parms) { + Parm *p = parms; + int nargs = 0; + + while (p) { + if (Getattr(p,"tmap:in") && checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + } else { + if (Getattr(p,"value")) break; + if (Getattr(p,"tmap:default")) break; + nargs+= GetInt(p,"tmap:in:numinputs"); + if (Getattr(p,"tmap:in")) { + p = Getattr(p,"tmap:in:next"); + } else { + p = nextSibling(p); + } + } + } + + /* Print message for non-default arguments */ + 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),"Error. 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); + } + } + } + + 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; +} + +/* ----------------------------------------------------------------------------- + * replace_args() + * ----------------------------------------------------------------------------- */ + +static +void replace_args(Parm *p, String *s) { + while (p) { + String *n = Getattr(p,"name"); + if (n) { + Replace(s,n,Getattr(p,"lname"), DOH_REPLACE_ID); + } + p = nextSibling(p); + } +} + +/* ----------------------------------------------------------------------------- + * int emit_action() + * + * Emits action code for a wrapper and checks for exception handling + * ----------------------------------------------------------------------------- */ + +void emit_action(Node *n, Wrapper *f) { + String *tm; + String *action; + String *wrap; + Parm *p; + SwigType *rt; + ParmList *throws = Getattr(n,"throws"); + + /* Look for fragments */ + { + String *f; + f = Getattr(n,"feature:fragment"); + if (f) { + char *c, *tok; + String *t = Copy(f); + c = Char(t); + tok = strtok(c,","); + while (tok) { + Swig_fragment_emit(tok); + 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); + + /* Get the return type */ + + rt = Getattr(n,"type"); + + /* Preassert -- EXPERIMENTAL */ + tm = Getattr(n,"feature:preassert"); + if (tm) { + p = Getattr(n,"parms"); + replace_args(p,tm); + Printv(f->code,tm,"\n",NIL); + } + + /* Exception handling code */ + + /* If we are in C++ mode and there is a throw specifier. We're going to + enclose the block in a try block */ + + if (throws) { + Printf(f->code,"try {\n"); + } + + /* Look for except typemap (Deprecated) */ + tm = Swig_typemap_lookup_new("except",n,"result",0); + + /* Look for except feature */ + if (!tm) { + tm = Getattr(n,"feature:except"); + if (tm) tm = Copy(tm); + } + if ((tm) && Len(tm) && (Strcmp(tm,"1") != 0)) { + Replaceall(tm,"$name",Getattr(n,"name")); + Replaceall(tm,"$symname", Getattr(n,"sym:name")); + Replaceall(tm,"$function", action); + Replaceall(tm,"$action", action); + Printv(f->code,tm,"\n", NIL); + Delete(tm); + } else { + Printv(f->code, action, "\n",NIL); + } + + if (throws) { + Printf(f->code,"}\n"); + for (Parm *ep = throws; ep; ep = nextSibling(ep)) { + String *em = Swig_typemap_lookup_new("throws",ep,"_e",0); + if (em) { + Printf(f->code,"catch(%s) {\n", SwigType_str(Getattr(ep,"type"),"&_e")); + Printv(f->code,em,"\n",NIL); + Printf(f->code,"}\n"); + } else { + Swig_warning(WARN_TYPEMAP_THROW, Getfile(n), Getline(n), + "No 'throw' typemap defined for exception type '%s'\n", SwigType_str(Getattr(ep,"type"),0)); + } + } + Printf(f->code,"catch(...) { throw; }\n"); + } + + /* Postassert - EXPERIMENTAL */ + tm = Getattr(n,"feature:postassert"); + if (tm) { + p = Getattr(n,"parms"); + replace_args(p,tm); + Printv(f->code,tm,"\n",NIL); + } +} + + + + diff --git a/Source/Modules/guile.cxx b/Source/Modules/guile.cxx new file mode 100644 index 000000000..a6b53b536 --- /dev/null +++ b/Source/Modules/guile.cxx @@ -0,0 +1,1208 @@ +/****************************************************************************** + * Simplified Wrapper and Interface Generator (SWIG) + * + * Author : David Beazley + * + * Department of Computer Science + * University of Chicago + * 1100 E 58th Street + * Chicago, IL 60637 + * beazley@cs.uchicago.edu + * + * Please read the file LICENSE for the copyright and terms by which SWIG + * can be used and distributed. + *****************************************************************************/ + +char cvsroot_guile_cxx[] = "$Header$"; + +/*********************************************************************** + * $Header$ + * + * guile.cxx + * + * Definitions for adding functions to Guile + ***********************************************************************/ + +#include "swigmod.h" + +#ifndef MACSWIG +#include "swigconfig.h" +#endif +#include + +static const char *guile_usage = (char*)"\ +Guile Options (available with -guile)\n\ + -ldflags - Print runtime libraries to link with\n\ + -prefix name - Use NAME as prefix [default \"gswig_\"]\n\ + -package name - Set the path of the module [default NULL]\n\ + -emit-setters - Emit procedures-with-setters for variables\n\ + and structure slots.\n\ + -linkage lstyle - Use linkage protocol LSTYLE [default `module']\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\ + -scmstub file - Output Scheme FILE with module declaration and\n\ + exports; only with `passive' and `simple' linkage\n\ +\n\ + When unspecified, the default LSTYLE is `simple'. For native Guile\n\ + module linking (for Guile versions >=1.5.0), use `module'. Other\n\ + LSTYLE values are: `passive' for passive linking (no C-level\n\ + module-handling code), `ltdlmod' for Guile's old dynamic module\n\ + convention (versions <= 1.4), or `hobbit' for hobbit modules.\n\ +\n"; + +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 File *scmstub = 0; +static String *scmtext; + +static enum { + GUILE_1_4, + PLAIN, + TEXINFO +} docformat = GUILE_1_4; + +static int emit_setters = 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; + +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, stderr); + 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], "-ldflags") == 0) { + printf("%s\n", SWIG_GUILE_RUNTIME); + SWIG_exit (EXIT_SUCCESS); + } + 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], (char *) "w"); + 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) { + emit_setters = 1; + Swig_mark_arg (i); + } + else if (strcmp (argv[i], "-scmstub") == 0) { + if (argv[i + 1]) { + scmstub = NewFile(argv[i + 1], (char *) "w"); + Swig_mark_arg (i); + Swig_mark_arg (i + 1); + i++; + } else { + Swig_arg_error(); + } + } + } + } + + // 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 */ + SWIG_config_file("guile.i"); + allow_overloading(); + + } + + /* ------------------------------------------------------------ + * top() + * ------------------------------------------------------------ */ + + virtual int top(Node *n) { + /* Initialize all of the output files */ + String *outfile = Getattr(n,"outfile"); + + f_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + 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("runtime",f_runtime); + Swig_register_filebyname("init",f_init); + + scmtext = NewString(""); + Swig_register_filebyname("scheme", scmtext); + exported_symbols = NewString(""); + + Printf(f_runtime, "/* -*- buffer-read-only: t -*- vi: set ro: */\n"); + Swig_banner (f_runtime); + + Printf (f_runtime, "/* Implementation : GUILE */\n\n"); + + /* Write out directives and declarations */ + + if (NoInclude) { + Printf(f_runtime, "#define SWIG_NOINCLUDE\n"); + } + + module = Swig_copy_string(Char(Getattr(n,"name"))); + + if (CPlusPlus) { + Printf(f_runtime, "extern \"C\" {\n\n"); + } + + 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, "extern void\nSWIG_init (void)\n;\n"); + Printf (f_init, "extern void\nSWIG_init (void)\n{\n"); + break; + default: + /* Other linkage; we make the SWIG_init function static */ + Printf (f_runtime, "static void\nSWIG_init (void)\n;\n"); + Printf (f_init, "static void\nSWIG_init (void)\n{\n"); + break; + } + Printf (f_init, "\tSWIG_Guile_Init();\n"); + if (CPlusPlus) { + Printf(f_runtime, "\n}\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_wrappers,"#ifdef __cplusplus\n}\n#endif\n"); + + Printf (f_init, "SWIG_Guile_RegisterTypes(swig_types, swig_types_initial);\n"); + Printf (f_init, "}\n\n"); + char module_name[256]; + + if (!module) + sprintf(module_name, "swig"); + else { + if (package) + sprintf(module_name,"%s/%s", package,module); + else + strcpy(module_name,module); + } + emit_linkage (module_name); + + if (procdoc) { + Delete(procdoc); + procdoc = NULL; + } + if (scmstub) { + Delete(scmstub); + scmstub = NULL; + } + + /* Close all of the files */ + Dump(f_header,f_runtime); + Dump(f_wrappers,f_runtime); + Wrapper_pretty_print(f_init,f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + Delete(f_runtime); + return SWIG_OK; + } + + void emit_linkage (char *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); + Replaceall(mod,"/", " "); + Printf(f_init, " SCM module = 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 *mod = NewString(module_name); + Replaceall(mod, "/", " "); + Printf (scmstub, ";;; -*- buffer-read-only: t -*- vi: set ro: */\n"); + Printf (scmstub, ";;; Automatically generated by SWIG; do not edit.\n\n"); + if (linkage == GUILE_LSTYLE_SIMPLE + || linkage == GUILE_LSTYLE_PASSIVE) + Printf (scmstub, "(define-module (%s))\n\n", mod); + Delete(mod); + Printf (scmstub, "%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(scmstub, "\n(export %s)\n", ex); + Delete(ex); + } + } + + 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) + { + 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); + } + String *pn = Getattr(p,"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], target[256]; + Wrapper *f = NewWrapper();; + String *cleanup = NewString(""); + String *outarg = NewString(""); + String *signature = NewString(""); + String *doc_body = NewString(""); + String *returns = NewString(""); + 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; + + // 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)) 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_args (d, 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", "int gswig_list_p = 0"); + + /* Get the output typemap so we can start generating documentation. Don't + worry, the returned string is saved as 'tmap:out' */ + + Swig_typemap_lookup_new("out",n,"result",0); + + 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; + } + + /* 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"); + String *ln = Getattr(p,"lname"); + 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); + sprintf(target,"%s", Char(ln)); + + 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 != GH_NOT_PASSED) {\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); + + if (procdoc) { + /* Add to signature (arglist) */ + handle_documentation_typemap(signature, " ", p, "tmap:in:arglist", + "$name"); + /* Document the type of the arg in the documentation body */ + handle_documentation_typemap(doc_body, ", ", p, "tmap:in:doc", + "$NAME is of type <$type>"); + } + 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 */ + 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, ", ", + 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")); + Printv(cleanup,tm,"\n",NIL); + p = Getattr(p,"tmap:freearg:next"); + } else { + p = nextSibling(p); + } + } + + /* 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 + Printv(f->code, tab4, "gh_defer_ints();\n", NIL); + emit_action(n,f); + Printv(f->code, tab4, "gh_allow_ints();\n", NIL); + + // Now have return value, figure out what to do with it. + + if ((tm = Getattr(n,"tmap:out"))) { + Replaceall(tm,"$result","gswig_result"); + Replaceall(tm,"$target","gswig_result"); + Replaceall(tm,"$source","result"); + Printv(f->code,tm,"\n",NIL); + } + else { + throw_unhandled_guile_type_error (d); + } + + // 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 (Getattr(n,"feature:new")) { + if ((tm = Swig_typemap_lookup_new("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_new("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); + + // 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; i3) { + 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 = "); + 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 */ + Printf (f_init, "gh_define(\"%s\", " + "scm_make_procedure_with_setter(getter, setter));\n", + pws_name); + } + else { + /* There was no setter, so make an alias to the getter */ + Printf (f_init, "gh_define(\"%s\", getter);\n", + pws_name); + } + Printf (exported_symbols, "\"%s\", ", pws_name); + free(pws_name); + } + } + else { + /* Register the function */ + 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, "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); + Printv(df->code,"}\n",NIL); + Wrapper_print(df,f_wrappers); + 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 (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(doc_body); + Delete(returns); + Delete(tmp); + 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; + char var_name[256]; + Wrapper *f; + String *tm; + + if (!addSymbol(iname,n)) return SWIG_ERROR; + + f = NewWrapper(); + // evaluation function names + + strcpy(var_name, Char(Swig_name_wrapper(iname))); + + // Build the name for scheme. + proc_name = NewString(iname); + Replaceall(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 (!Getattr(n,"feature:immutable")) { + /* Check for a setting of the variable value */ + Printf (f->code, "if (s_0 != GH_NOT_PASSED) {\n"); + if ((tm = Swig_typemap_lookup_new("varin",n,name,0))) { + Replaceall(tm,"$source","s_0"); + Replaceall(tm,"$input","s_0"); + Replaceall(tm,"$target",name); + Printv(f->code,tm,"\n",NIL); + } + 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_new("varout",n,name,0))) { + Replaceall(tm,"$source",name); + Replaceall(tm,"$target","gswig_result"); + Replaceall(tm,"$result", "gswig_result"); + Printv(f->code,tm,"\n",NIL); + } + 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 + || Getattr(n,"feature:immutable")) { + /* Read-only variables become a simple procedure returning the + value; read-write variables become a simple procedure with + an optional argument. */ + Printf (f_init, "\t gh_new_procedure(\"%s\", (swig_guile_proc) %s, 0, %d, 0);\n", + proc_name, var_name, Getattr(n,"feature:immutable") ? 0 : 1); + } + else { + /* Read/write variables become a procedure with setter. */ + 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, "\t gh_define(\"%s\", " + "scm_make_procedure_with_setter(p, p)); }\n", + proc_name); + } + Printf (exported_symbols, "\"%s\", ", proc_name); + + if (procdoc) { + /* Compute documentation */ + String *signature = NewString(""); + String *signature2 = NULL; + String *doc = NewString(""); + + if (Getattr(n,"feature:immutable")) { + Printv(signature, proc_name, NIL); + 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(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"); + + String *proc_name; + char var_name[256]; + String *rvalue; + Wrapper *f; + SwigType *nctype; + String *tm; + + f = NewWrapper(); + + // Make a static variable; + + sprintf (var_name, "%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"); + 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_new("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); + Setattr(n,"feature:immutable", "1"); + variableWrapper(n); + Delete(n); + } + Delete(nctype); + Delete(proc_name); + Delete(rvalue); + DelWrapper(f); + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * membervariableHandler() + * ------------------------------------------------------------ */ + virtual int membervariableHandler(Node *n) { + if (emit_setters) { + struct_member = 1; + Printf(f_init, "{\n"); + Language::membervariableHandler(n); + Printf(f_init, "}\n"); + struct_member = 0; + } + else { + /* Only emit traditional VAR-get and VAR-set procedures */ + Language::membervariableHandler(n); + } + 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); + } + + /* ------------------------------------------------------------ + * 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. */ + /* --> * | */ + /* --> | */ + if (!(isalpha(*c) || (*c == '!') || (*c == '$') || (*c == '%') + || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':') + || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?') + || (*c == '^') || (*c == '_') || (*c == '~'))) { + /* --> + | - | ... */ + if ((strcmp(c, "+") == 0) + || strcmp(c, "-") == 0 + || strcmp(c, "...") == 0) return 1; + else return 0; + } + /* --> | | */ + 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; + } +}; + +/* ----------------------------------------------------------------------------- + * swig_guile() - Instantiate module + * ----------------------------------------------------------------------------- */ + +extern "C" Language * +swig_guile(void) { + return new GUILE(); +} diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx new file mode 100644 index 000000000..499a58b24 --- /dev/null +++ b/Source/Modules/java.cxx @@ -0,0 +1,1900 @@ +/* ----------------------------------------------------------------------------- + * java.cxx + * + * Java wrapper module. + * + * Author(s) : Harco de Hilster + * William Fulton + * + * Copyright (C) 1999-2002. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_java_cxx[] = "$Header$"; + +#include +#include // for INT_MAX +#include "swigmod.h" + +class JAVA : public Language { + static const char *usage; + const String *empty_string; + + Hash *swig_types_hash; + File *f_runtime; + File *f_header; + File *f_wrappers; + File *f_init; + + bool proxy_flag; // Flag for generating shadow 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 + + String *jniclass_name; // JNI class name + String *module_class_name; // module class name + String *jniclass_class_code; // JNI class Java code - that is the native methods + String *shadow_classdef; + String *shadow_code; + String *module_class_code; + String *shadow_classname; + String *variable_name; //Name of a variable being wrapped + String *shadow_constants_code; + String *module_constants_code; + String *package; // Package name + String *jnipackage; // JNI package name + String *jniclass_imports; //jniclass imports from %pragma + String *module_imports; //module imports from %pragma + String *jniclass_baseclass; //inheritance for jniclass class from %pragma + String *module_baseclass; //inheritance for module class from %pragma + String *jniclass_interfaces; //interfaces for jniclass class from %pragma + String *module_interfaces; //interfaces for module class from %pragma + String *jniclass_class_modifiers; //class modifiers for jniclass class overriden by %pragma + String *module_class_modifiers; //class modifiers for module class overriden by %pragma + String *wrapper_conversion_code; //C++ casts for inheritance hierarchies JNI code + String *jniclass_cppcasts_code; //C++ casts up inheritance hierarchies JNI class Java code + String *destructor_call; //Destructor (delete) call if any + + enum type_additions {none, pointer, reference}; + + public: + + /* ----------------------------------------------------------------------------- + * JAVA() + * ----------------------------------------------------------------------------- */ + + JAVA() : + empty_string(NewString("")), + + swig_types_hash(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), + + jniclass_name(NULL), + module_class_name(NULL), + jniclass_class_code(NULL), + shadow_classdef(NULL), + shadow_code(NULL), + module_class_code(NULL), + shadow_classname(NULL), + variable_name(NULL), + shadow_constants_code(NULL), + module_constants_code(NULL), + package(NULL), + jnipackage(NULL), + jniclass_imports(NULL), + module_imports(NULL), + jniclass_baseclass(NULL), + module_baseclass(NULL), + jniclass_interfaces(NULL), + module_interfaces(NULL), + jniclass_class_modifiers(NULL), + module_class_modifiers(NULL), + wrapper_conversion_code(NULL), + jniclass_cppcasts_code(NULL), + destructor_call(NULL) + + { + } + + /* ----------------------------------------------------------------------------- + * is_shadow() + * + * Test to see if a type corresponds to something wrapped with a shadow/proxy class + * Return NULL if not otherwise the shadow name + * ----------------------------------------------------------------------------- */ + + String *is_shadow(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; + } + + /* ------------------------------------------------------------ + * 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],"-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 typemaps 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(stderr,"%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) { + + /* Initialize all of the output files */ + String *outfile = Getattr(n,"outfile"); + + f_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"Unable to open %s\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + 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("runtime",f_runtime); + Swig_register_filebyname("init",f_init); + swig_types_hash = NewHash(); + + // Make the JNI class and module class names. The jniclassname can be set in the module directive. + Node* optionsnode = Getattr( Getattr(n,"module") ,"options"); + if (optionsnode) + if (Getattr(optionsnode,"jniclassname")) + jniclass_name = Copy(Getattr(optionsnode,"jniclassname")); + if (!jniclass_name) { + jniclass_name = NewStringf("%sJNI", Getattr(n,"name")); + module_class_name = Copy(Getattr(n,"name")); + } else { + // Rename the module name if it is the same as JNI class name - a backwards compatibility solution + if (Cmp(jniclass_name, Getattr(n,"name")) == 0) + module_class_name = NewStringf("%sModule", Getattr(n,"name")); + else + module_class_name = Copy(Getattr(n,"name")); + } + + + jniclass_class_code = NewString(""); + shadow_classdef = NewString(""); + shadow_code = NewString(""); + module_constants_code = NewString(""); + jniclass_baseclass = NewString(""); + jniclass_interfaces = NewString(""); + jniclass_class_modifiers = NewString(""); // package access only to the JNI class by default + module_class_code = NewString(""); + module_baseclass = NewString(""); + module_interfaces = NewString(""); + module_imports = NewString(""); + module_class_modifiers = NewString("public"); + jniclass_imports = NewString(""); + jniclass_cppcasts_code = NewString(""); + wrapper_conversion_code = NewString(""); + if (!package) package = NewString(""); + jnipackage = NewString(""); + + Swig_banner(f_runtime); // Print the SWIG banner message + + if (NoInclude) { + Printf(f_runtime,"#define SWIG_NOINCLUDE\n"); + } + + String *wrapper_name = NewString(""); + + if(Len(package)) { + String *jniname = makeValidJniName(package); + Printv(jnipackage, jniname, NIL); + Delete(jniname); + Replaceall(jnipackage,".","_"); + Append(jnipackage, "_"); + } + String *jniname = makeValidJniName(jniclass_name); + Printf(wrapper_name, "Java_%s%s_%%f", Char(jnipackage), jniname); + Delete(jniname); + + Swig_name_register((char*)"wrapper", Char(wrapper_name)); + Swig_name_register((char*)"set", (char*)"set_%v"); + Swig_name_register((char*)"get", (char*)"get_%v"); + Swig_name_register((char*)"member", (char*)"%c_%m"); + + Delete(wrapper_name); + + Printf(f_wrappers,"#ifdef __cplusplus\n"); + Printf(f_wrappers,"extern \"C\" {\n"); + Printf(f_wrappers,"#endif\n"); + + /* Emit code */ + Language::top(n); + + // Generate the Java JNI class + { + String *filen = NewStringf("%s.java", jniclass_name); + File *f_java = NewFile(filen,"w"); + if(!f_java) { + Printf(stderr,"Unable to open %s\n", filen); + SWIG_exit(EXIT_FAILURE); + } + Delete(filen); filen = NULL; + + // Start writing out the Java JNI class + if(Len(package) > 0) + Printf(f_java, "package %s;\n\n", package); + + emitBanner(f_java); + if(jniclass_imports) + Printf(f_java, "%s\n", jniclass_imports); + + if (Len(jniclass_class_modifiers) > 0) + Printf(f_java, "%s ", jniclass_class_modifiers); + Printf(f_java, "class %s ", jniclass_name); + + if (jniclass_baseclass && *Char(jniclass_baseclass)) + Printf(f_java, "extends %s ", jniclass_baseclass); + if (Len(jniclass_interfaces) > 0) + Printv(f_java, "implements ", jniclass_interfaces, " ", NIL); + Printf(f_java, "{\n"); + + // Add the native methods + Printv(f_java, jniclass_class_code, NIL); + Printv(f_java, jniclass_cppcasts_code, NIL); + + // Finish off the Java class + Printf(f_java, "}\n"); + Close(f_java); + } + + // Generate the Java module class + { + String *filen = NewStringf("%s.java", module_class_name); + File *f_module = NewFile(filen,"w"); + if(!f_module) { + Printf(stderr,"Unable to open %s\n", filen); + SWIG_exit(EXIT_FAILURE); + } + Delete(filen); filen = NULL; + + // Start writing out the Java module class + if(Len(package) > 0) + Printf(f_module, "package %s;\n\n", package); + + emitBanner(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, "class %s ", module_class_name); + + if (module_baseclass && *Char(module_baseclass)) + Printf(f_module, "extends %s ", module_baseclass); + if (Len(module_interfaces) > 0) + Printv(f_module, "implements ", module_interfaces, " ", NIL); + Printf(f_module, "{\n"); + + // Add the wrapper methods + Printv(f_module, module_class_code, NIL); + + // Write out all the enums constants + if (Len(module_constants_code) != 0 ) + Printv(f_module, " // enums and constants\n", module_constants_code, NIL); + + // Finish off the Java class + Printf(f_module, "}\n"); + Close(f_module); + } + + if(wrapper_conversion_code) + Printv(f_wrappers,wrapper_conversion_code,NIL); + + Printf(f_wrappers,"#ifdef __cplusplus\n"); + Printf(f_wrappers,"}\n"); + Printf(f_wrappers,"#endif\n"); + + // Output a Java class for each SWIG type + for (String *swig_type = Firstkey(swig_types_hash); swig_type; swig_type = Nextkey(swig_types_hash)) { + emitJavaClass(swig_type, Getattr(swig_types_hash, swig_type)); + } + + Delete(swig_types_hash); swig_types_hash = NULL; + Delete(jniclass_name); jniclass_name = NULL; + Delete(jniclass_class_code); jniclass_class_code = NULL; + Delete(shadow_classdef); shadow_classdef = NULL; + Delete(shadow_code); shadow_code = NULL; + Delete(module_constants_code); module_constants_code = NULL; + Delete(jniclass_baseclass); jniclass_baseclass = NULL; + Delete(jniclass_interfaces); jniclass_interfaces = NULL; + Delete(jniclass_class_modifiers); jniclass_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(jniclass_imports); jniclass_imports = NULL; + Delete(jniclass_cppcasts_code); jniclass_cppcasts_code = NULL; + Delete(wrapper_conversion_code); wrapper_conversion_code = NULL; + Delete(package); package = NULL; + Delete(jnipackage); jnipackage = NULL; + + /* Close all of the files */ + Dump(f_header,f_runtime); + Dump(f_wrappers,f_runtime); + Wrapper_pretty_print(f_init,f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + Delete(f_runtime); + return SWIG_OK; + } + + /* ----------------------------------------------------------------------------- + * emitBanner() + * ----------------------------------------------------------------------------- */ + + void emitBanner(File *f) { + Printf(f, "/* ----------------------------------------------------------------------------\n"); + Printf(f, " * This file was automatically generated by SWIG (http://www.swig.org).\n"); + Printf(f, " * Version: %s\n", SWIG_VERSION); + Printf(f, " *\n"); + Printf(f, " * Do not make changes to this file unless you know what you are doing--modify\n"); + Printf(f, " * the SWIG interface file instead.\n"); + 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(&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 *jnirettype = NewString(""); + String *javarettype = NewString(""); + String *cleanup = NewString(""); + String *outarg = NewString(""); + String *body = NewString(""); + String *javaParameterSignature = NewString(""); + 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; + } + + /* + Generate the java class wrapper function ie the java shadow class. Only done for public + member variables. That is this generates the getters/setters for 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 + String *getter_setter_name = NewString(""); + if(Cmp(symname, Swig_name_set(Swig_name_member(shadow_classname, variable_name))) == 0) + 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,"java:shadowfuncname", getter_setter_name); + Setattr(n,"java:funcname", symname); + + javaShadowFunctionHandler(n); + + Delete(getter_setter_name); + } + + /* + The rest of this function deals with generating the java 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); + + /* Get Java return types */ + if ((tm = Swig_typemap_lookup_new("jni",n,"",0))) { + Printf(jnirettype,"%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_new("jtype",n,"",0))) { + Printf(javarettype,"%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(jnirettype, "void") == 0); + if (!is_void_return) + Wrapper_add_localv(f,"jresult", jnirettype, "jresult = 0",NIL); + + Printf(jniclass_class_code, " public final static native %s %s(", javarettype, overloaded_name); + + Printv(f->def, "JNIEXPORT ", jnirettype, " 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_args(t,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); + + 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 *javaparamtype = NewString(""); + String *jni_param_type = NewString(""); + String *arg = NewString(""); + + Printf(arg,"j%s", ln); + + /* Get the jni types of the parameter */ + if ((tm = Getattr(p,"tmap:jni"))) { + Printv(jni_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 java types of the parameter */ + if ((tm = Getattr(p,"tmap:jtype"))) { + Printv(javaparamtype, 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 to java function header */ + if(gencomma) Printf(jniclass_class_code, ", "); + Printf(jniclass_class_code, "%s %s", javaparamtype, arg); + + gencomma = 1; + + // Add to Jni function header + Printv(f->def, ", ", jni_param_type, " ", arg, NIL); + + // 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(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(javaparamtype); + Delete(jni_param_type); + Delete(arg); + } + + /* 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 throw typemap + if (ParmList *throw_parm_list = Getattr(n,"throws")) { + 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 (Cmp(nodeType(n), "constant") == 0) { + // Wrapping a constant hack + Swig_save(&n,"wrap:action",NIL); + + // below based on Swig_VargetToFunction() + SwigType *ty = Swig_wrapped_var_type(Getattr(n,"type")); + Setattr(n,"wrap:action", NewStringf("result = (%s) %s;\n", SwigType_lstr(ty,0), Getattr(n, "value"))); + } + + // Now write code to make the function call + if(!native_function_flag) + emit_action(n,f); + + if (Cmp(nodeType(n), "constant") == 0) + Swig_restore(&n); + + /* Return value if necessary */ + if(!native_function_flag) { + if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) { + addThrows(n, "tmap:out", n); + Replaceall(tm,"$source", "result"); /* deprecated */ + Replaceall(tm,"$target", "jresult"); /* deprecated */ + Replaceall(tm,"$result","jresult"); + 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")); + } + } + + /* 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 (Getattr(n,"feature:new")) { + if ((tm = Swig_typemap_lookup_new("newfree",n,"result",0))) { + 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_new("ret", n, "result", 0))) { + Replaceall(tm,"$source","result"); /* deprecated */ + Printf(f->code,"%s\n",tm); + } + } + + /* Finish JNI C function and JNI class native function definitions */ + Printf(jniclass_class_code, ")"); + generateThrowsClause(n, jniclass_class_code); + Printf(jniclass_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); + + 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); + + Setattr(n,"wrap:name", wname); + + /* Emit warnings for the few cases that can't be overloaded in Java */ + if (Getattr(n,"sym:overloaded")) { + if (!Getattr(n,"sym:nextSibling")) + Swig_overload_rank(n); + } + + if(!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) { + moduleClassFunctionHandler(n); + } + + Delete(jnirettype); + Delete(javarettype); + Delete(cleanup); + Delete(outarg); + Delete(body); + Delete(javaParameterSignature); + Delete(overloaded_name); + DelWrapper(f); + return SWIG_OK; + } + + /* ----------------------------------------------------------------------- + * variableWrapper() + * + * Create a JAVA link to a C variable. + * ----------------------------------------------------------------------- */ + + virtual int variableWrapper(Node *n) { + Language::variableWrapper(n); /* Default to functions */ + 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; + } + + /* ----------------------------------------------------------------------- + * constantWrapper() + * ------------------------------------------------------------------------ */ + + virtual int constantWrapper(Node *n) { + String *symname = Getattr(n,"sym:name"); + SwigType *t = Getattr(n,"type"); + ParmList *l = Getattr(n,"parms"); + String *tm; + String *shadowrettype = NewString(""); + String *constants_code = NewString(""); + + if (!addSymbol(symname,n)) return SWIG_ERROR; + + /* Attach the non-standard typemaps to the parameter list. */ + Swig_typemap_attach_parms("jstype", l, NULL); + + /* Get Java return types */ + bool is_return_type_java_class = false; + if ((tm = Swig_typemap_lookup_new("jstype",n,"",0))) { + is_return_type_java_class = substituteJavaclassname(t, tm); + Printf(shadowrettype, "%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(&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); + } + + // enums are wrapped using a public final static int in java. + // Other constants are wrapped using a public final static [jstype] in Java. + Printf(constants_code, " public final static %s %s = ", shadowrettype, ((proxy_flag && wrapping_member_flag) ? variable_name : symname)); + + // The %javaconst directive determines how the constant value is obtained + String *javaconst = Getattr(n,"feature:java:const"); + if (Cmp(nodeType(n), "enumitem") == 0 || !javaconst || Cmp(javaconst, "0") == 0) { + // Enums and default constant handling will work with any type of C constant and initialises the Java variable from C through a JNI call. + + if(is_return_type_java_class) // This handles function pointers using the %constant directive + Printf(constants_code, "new %s(%s.%s(), false);\n", shadowrettype, jniclass_name, Swig_name_get(symname)); + else + Printf(constants_code, "%s.%s();\n", jniclass_name, Swig_name_get(symname)); + + // Each constant and enum value is wrapped with a separate JNI function call + 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")); + } + + if(proxy_flag && wrapping_member_flag) + Printv(shadow_constants_code, constants_code, NIL); + else + Printv(module_constants_code, constants_code, NIL); + + Swig_restore(&n); + Delete(new_value); + Delete(shadowrettype); + Delete(constants_code); + return SWIG_OK; + } + + /* ----------------------------------------------------------------------------- + * pragmaDirective() + * + * Valid Pragmas: + * jniclassbase - base (extends) for the JNI class + * jniclassclassmodifiers - class modifiers for the JNI class + * jniclasscode - text (java code) is copied verbatim to the JNI class + * jniclassimports - import statements for the JNI class + * jniclassinterfaces - interface (implements) for the JNI 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(jniclass_baseclass); + jniclass_baseclass = Copy(strvalue); + } + else if(Strcmp(code, "jniclassclassmodifiers") == 0) { + Delete(jniclass_class_modifiers); + jniclass_class_modifiers = Copy(strvalue); + } + else if(Strcmp(code, "jniclasscode") == 0) { + Printf(jniclass_class_code, "%s\n", strvalue); + } + else if(Strcmp(code, "jniclassimports") == 0) { + Delete(jniclass_imports); + jniclass_imports = Copy(strvalue); + } + else if(Strcmp(code, "jniclassinterfaces") == 0) { + Delete(jniclass_interfaces); + jniclass_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); + } + + /* ----------------------------------------------------------------------------- + * emitShadowClassDefAndCPPCasts() + * ----------------------------------------------------------------------------- */ + + void emitShadowClassDefAndCPPCasts(Node *n) { + String *c_classname = SwigType_namestr(Getattr(n,"name")); + String *c_baseclass = NULL; + String *baseclass = NULL; + String *c_baseclassname = NULL; + + /* Deal with inheritance */ + List *baselist = Getattr(n,"bases"); + if (baselist) { + Node *base = Firstitem(baselist); + c_baseclassname = Getattr(base,"name"); + baseclass = Copy(is_shadow(c_baseclassname)); + if (baseclass){ + c_baseclass = SwigType_namestr(Getattr(base,"name")); + } + base = Nextitem(baselist); + if (base) { + Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, input_file, line_number, + "Warning for %s: Base %s ignored. Multiple inheritance is not supported in Java.\n", shadow_classname, Getattr(base,"name")); + } + } + + bool derived = baseclass && is_shadow(c_baseclassname); + if (!baseclass) + baseclass = NewString(""); + + // Inheritance from pure Java classes + const String *pure_java_baseclass = javaTypemapLookup("javabase", shadow_classname, WARN_NONE); + if (Len(pure_java_baseclass) > 0 && Len(baseclass) > 0) { + Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, input_file, line_number, + "Warning for %s: Base %s ignored. Multiple inheritance is not supported in Java.\n", shadow_classname, pure_java_baseclass); + } + + // Pure Java interfaces + const String *pure_java_interfaces = javaTypemapLookup("javainterfaces", shadow_classname, WARN_NONE); + + // Start writing the shadow class + Printv(shadow_classdef, + javaTypemapLookup("javaimports", shadow_classname, WARN_NONE), // Import statements + "\n", + javaTypemapLookup("javaclassmodifiers", shadow_classname, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers + " class $javaclassname", // Class name and bases + (derived || *Char(pure_java_baseclass)) ? + " extends " : + "", + baseclass, + pure_java_baseclass, + *Char(pure_java_interfaces) ? // Pure Java interfaces + " implements " : + "", + pure_java_interfaces, + " {\n", + " private long swigCPtr;\n", // Member variables for memory handling + derived ? + "" : + " protected boolean swigCMemOwn;\n", + "\n", + " ", + javaTypemapLookup("javaptrconstructormodifiers", shadow_classname, WARN_JAVA_TYPEMAP_PTRCONSTMOD_UNDEF), // pointer constructor modifiers + " $javaclassname(long cPtr, boolean cMemoryOwn) {\n", // Constructor used for wrapping pointers + derived ? + " super($jniclassname.SWIG$javaclassnameTo$baseclass(cPtr), cMemoryOwn);\n" : + " swigCMemOwn = cMemoryOwn;\n", + " swigCPtr = cPtr;\n", + " }\n", + NIL); + + if(!have_default_constructor_flag) { // All Java classes need a constructor + Printv(shadow_classdef, + "\n", + " protected $javaclassname() {\n", + " this(0, false);\n", + " }\n", + NIL); + } + + Printv(shadow_classdef, + javaTypemapLookup("javafinalize", shadow_classname, WARN_NONE), // finalize method + "\n", + *Char(destructor_call) ? + " public void delete() {\n" : + " protected void delete() {\n", + " if(swigCPtr != 0 && swigCMemOwn) {\n", + destructor_call, + "", + " swigCMemOwn = false;\n", + derived ? // Zero all pointers up any inheritance hierarchy + " super.delete();\n" : + "", + " }\n", + " swigCPtr = 0;\n", + " }\n", + javaTypemapLookup("javagetcptr", shadow_classname, WARN_JAVA_TYPEMAP_GETCPTR_UNDEF), // getCPtr method + javaTypemapLookup("javacode", shadow_classname, WARN_NONE), // extra Java code + "\n", + NIL); + + // Substitute various strings into the above template + Replaceall(shadow_code, "$javaclassname", shadow_classname); + Replaceall(shadow_classdef, "$javaclassname", shadow_classname); + + Replaceall(shadow_classdef, "$baseclass", baseclass); + Replaceall(shadow_code, "$baseclass", baseclass); + + Replaceall(shadow_classdef, "$jniclassname", jniclass_name); + Replaceall(shadow_code, "$jniclassname", jniclass_name); + + // Add JNI code to do C++ casting to base class (only for classes in an inheritance hierarchy) + if(derived){ + Printv(jniclass_cppcasts_code," public final static native long ", + "SWIG$javaclassnameTo$baseclass(long jarg1);\n", + NIL); + + Replaceall(jniclass_cppcasts_code, "$javaclassname", shadow_classname); + Replaceall(jniclass_cppcasts_code, "$baseclass", baseclass); + + Printv(wrapper_conversion_code, + "JNIEXPORT jlong JNICALL Java_$jnipackage$jnijniclass_SWIG$jniclazznameTo$jnibaseclass", + "(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 *jnijniclass = makeValidJniName(jniclass_name); + String *jniclazzname = makeValidJniName(shadow_classname); + String *jnibaseclass = makeValidJniName(baseclass); + Replaceall(wrapper_conversion_code, "$jnibaseclass",jnibaseclass); + Replaceall(wrapper_conversion_code, "$cbaseclass", c_baseclass); + Replaceall(wrapper_conversion_code, "$jniclazzname",jniclazzname); + Replaceall(wrapper_conversion_code, "$cclass", c_classname); + Replaceall(wrapper_conversion_code, "$jnipackage", jnipackage); + Replaceall(wrapper_conversion_code, "$jnijniclass", jnijniclass); + + Delete(jnibaseclass); + Delete(jniclazzname); + Delete(jnijniclass); + } + Delete(baseclass); + } + + /* ---------------------------------------------------------------------- + * classHandler() + * ---------------------------------------------------------------------- */ + + virtual int classHandler(Node *n) { + + File *f_shadow = NULL; + if (proxy_flag) { + shadow_classname = NewString(Getattr(n,"sym:name")); + + if (!addSymbol(shadow_classname,n)) return SWIG_ERROR; + + if (Cmp(shadow_classname, jniclass_name) == 0) { + Printf(stderr, "Class name cannot be equal to JNI class name: %s\n", shadow_classname); + SWIG_exit(EXIT_FAILURE); + } + + if (Cmp(shadow_classname, module_class_name) == 0) { + Printf(stderr, "Class name cannot be equal to module class name: %s\n", shadow_classname); + SWIG_exit(EXIT_FAILURE); + } + + String *filen = NewStringf("%s.java", shadow_classname); + f_shadow = NewFile(filen,"w"); + if(!f_shadow) { + Printf(stderr, "Unable to create proxy class file: %s\n", filen); + SWIG_exit(EXIT_FAILURE); + } + Delete(filen); filen = NULL; + + emitBanner(f_shadow); + + if(Len(package) > 0) + Printf(f_shadow, "package %s;\n\n", package); + + Clear(shadow_classdef); + Clear(shadow_code); + + have_default_constructor_flag = false; + destructor_call = NewString(""); + shadow_constants_code = NewString(""); + } + Language::classHandler(n); + + if (proxy_flag) { + + emitShadowClassDefAndCPPCasts(n); + + Printv(f_shadow, shadow_classdef, shadow_code, NIL); + + // Write out all the enums and constants + if (Len(shadow_constants_code) != 0 ) + Printv(f_shadow, " // enums and constants\n", shadow_constants_code, NIL); + + Printf(f_shadow, "}\n"); + Close(f_shadow); + f_shadow = NULL; + + Delete(shadow_classname); shadow_classname = NULL; + Delete(destructor_call); destructor_call = NULL; + Delete(shadow_constants_code); shadow_constants_code = NULL; + } + return SWIG_OK; + } + + /* ---------------------------------------------------------------------- + * memberfunctionHandler() + * ---------------------------------------------------------------------- */ + + virtual int memberfunctionHandler(Node *n) { + Language::memberfunctionHandler(n); + + if (proxy_flag) { + String *overloaded_name = getOverloadedName(n); + String *java_function_name = Swig_name_member(shadow_classname, overloaded_name); + Setattr(n,"java:shadowfuncname", Getattr(n, "sym:name")); + Setattr(n,"java:funcname", java_function_name); + javaShadowFunctionHandler(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 *java_function_name = Swig_name_member(shadow_classname, overloaded_name); + Setattr(n,"java:shadowfuncname", Getattr(n,"sym:name")); + Setattr(n,"java:funcname", java_function_name); + javaShadowFunctionHandler(n); + Delete(overloaded_name); + } + static_flag = false; + + return SWIG_OK; + } + + /* ----------------------------------------------------------------------------- + * javaShadowFunctionHandler() + * + * Function called for creating a java class wrapper function around a c++ function in the + * java wrapper class. Used for both static and non static functions. + * C++ static functions map to java static functions. + * Two extra attributes in the Node must be available. These are "java:shadowfuncname" - the name of the java class shadow + * function, which in turn will call "java:funcname" - the java native function name which wraps the c++ function. + * ----------------------------------------------------------------------------- */ + + void javaShadowFunctionHandler(Node *n) { + SwigType *t = Getattr(n,"type"); + ParmList *l = Getattr(n,"parms"); + String *java_function_name = Getattr(n,"java:funcname"); + String *java_shadow_function_name = Getattr(n,"java:shadowfuncname"); + String *tm; + Parm *p; + int i; + String *nativecall = NewString(""); + String *shadowrettype = NewString(""); + String *user_arrays = NewString(""); + + 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("jstype", l, NULL); + Swig_typemap_attach_parms("javain", l, NULL); + + /* Get Java return types */ + if ((tm = Swig_typemap_lookup_new("jstype",n,"",0))) { + substituteJavaclassname(t, tm); + Printf(shadowrettype, "%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)); + } + + /* Start generating the shadow function */ + Printf(shadow_code, " %s ", Getattr(n,"feature:java:methodmodifiers")); + if (static_flag) + Printf(shadow_code, "static "); + Printf(shadow_code, "%s %s(", shadowrettype, java_shadow_function_name); + + Printv(nativecall, jniclass_name, ".", java_function_name, "(", NIL); + if (!static_flag) + Printv(nativecall, "swigCPtr", NIL); + + int gencomma = !static_flag; + + /* Output each parameter */ + for (i = 0, p=l; p; i++) { + + /* 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 *javaparamtype = NewString(""); + + /* Get the java type of the parameter */ + if ((tm = Getattr(p,"tmap:jstype"))) { + substituteJavaclassname(pt, tm); + Printf(javaparamtype, "%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(nativecall, ", "); + + String *arg = makeParameterName(n, p, i); + + // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in native function (in JNI class) + if ((tm = Getattr(p,"tmap:javain"))) { + substituteJavaclassname(pt, tm); + Replaceall(tm, "$javainput", arg); + Printv(nativecall, 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 to java shadow function header */ + if (gencomma >= 2) + Printf(shadow_code, ", "); + gencomma = 2; + Printf(shadow_code, "%s %s", javaparamtype, arg); + + Delete(arg); + Delete(javaparamtype); + } + p = Getattr(p,"tmap:in:next"); + } + + Printf(nativecall, ")"); + Printf(shadow_code, ")"); + generateThrowsClause(n, shadow_code); + + // Transform return type used in native function (in JNI class) to type used in Java wrapper function (in proxy class) + if ((tm = Swig_typemap_lookup_new("javaout",n,"",0))) { + if (Getattr(n,"feature:new")) + Replaceall(tm,"$owner","true"); + else + Replaceall(tm,"$owner","false"); + substituteJavaclassname(t, tm); + Replaceall(tm, "$jnicall", nativecall); + Printf(shadow_code, " %s\n\n", tm); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, + "No javaout typemap defined for %s\n", SwigType_str(t,0)); + } + + Delete(shadowrettype); + Delete(nativecall); + Delete(user_arrays); + } + + /* ---------------------------------------------------------------------- + * constructorHandler() + * ---------------------------------------------------------------------- */ + + virtual int constructorHandler(Node *n) { + + ParmList *l = Getattr(n,"parms"); + String *tm; + Parm *p; + int i; + String *user_arrays = NewString(""); + + Language::constructorHandler(n); + + if(proxy_flag) { + String *overloaded_name = getOverloadedName(n); + String *nativecall = NewString(""); + + Printf(shadow_code, " %s %s(", Getattr(n,"feature:java:methodmodifiers"), shadow_classname); + Printv(nativecall, "this(", jniclass_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("jstype", l, NULL); + Swig_typemap_attach_parms("javain", l, NULL); + + int gencomma = 0; + + /* Output each parameter */ + for (i = 0, p=l; p; i++) { + + /* Ignored parameters */ + if (checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + continue; + } + + SwigType *pt = Getattr(p,"type"); + String *javaparamtype = NewString(""); + + /* Get the java type of the parameter */ + if ((tm = Getattr(p,"tmap:jstype"))) { + substituteJavaclassname(pt, tm); + Printf(javaparamtype, "%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(nativecall, ", "); + + String *arg = makeParameterName(n, p, i); + + // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in native function (in JNI class) + if ((tm = Getattr(p,"tmap:javain"))) { + substituteJavaclassname(pt, tm); + Replaceall(tm, "$javainput", arg); + Printv(nativecall, 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 to java shadow function header */ + if(gencomma) + Printf(shadow_code, ", "); + Printf(shadow_code, "%s %s", javaparamtype, arg); + gencomma = 1; + + Delete(arg); + Delete(javaparamtype); + p = Getattr(p,"tmap:in:next"); + } + + Printf(nativecall, "), true);\n"); + + Printf(shadow_code, ")"); + generateThrowsClause(n, shadow_code); + Printf(shadow_code, " {\n"); + Printv(shadow_code, user_arrays, NIL); + Printf(shadow_code, " %s", nativecall); + Printf(shadow_code, " }\n\n"); + + if(!gencomma) // We must have a default constructor + have_default_constructor_flag = true; + + Delete(overloaded_name); + Delete(nativecall); + } + + Delete(user_arrays); + + return SWIG_OK; + } + + /* ---------------------------------------------------------------------- + * destructorHandler() + * ---------------------------------------------------------------------- */ + + virtual int destructorHandler(Node *n) { + Language::destructorHandler(n); + String *symname = Getattr(n,"sym:name"); + + if(proxy_flag) { + Printv(destructor_call, " ", jniclass_name, ".", Swig_name_destroy(symname), "(swigCPtr);\n", NIL); + } + 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 the JNI is designed to handle overloaded Java functions, a Java long is used for all classes in the SWIG + * JNI native interface. The JNI native interface function is 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 *nativecall = NewString(""); + String *shadowrettype = NewString(""); + String *user_arrays = NewString(""); + int num_arguments = 0; + int num_required = 0; + String *overloaded_name = getOverloadedName(n); + String *func_name = NULL; + + 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 Java return types */ + if ((tm = Swig_typemap_lookup_new("jstype",n,"",0))) { + substituteJavaclassname(t, tm); + Printf(shadowrettype, "%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(""); + if(Cmp(Getattr(n,"sym:name"), Swig_name_set(variable_name)) == 0) + 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 */ + Printf(module_class_code, " %s static %s %s(", Getattr(n,"feature:java:methodmodifiers"), shadowrettype, func_name); + Printv(nativecall, jniclass_name, ".", overloaded_name, "(", NIL); + + /* Get number of required and total arguments */ + num_arguments = emit_num_arguments(l); + num_required = emit_num_required(l); + + int gencomma = 0; + + /* Output each parameter */ + for (i = 0, p=l; i < num_arguments; i++) { + + /* Ignored parameters */ + while (checkAttribute(p,"tmap:in:numinputs","0")) { + p = Getattr(p,"tmap:in:next"); + } + + SwigType *pt = Getattr(p,"type"); + String *javaparamtype = NewString(""); + + /* Get the java type of the parameter */ + if ((tm = Getattr(p,"tmap:jstype"))) { + substituteJavaclassname(pt, tm); + Printf(javaparamtype, "%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(nativecall, ", "); + + String *arg = makeParameterName(n, p, i); + + // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in native function (in JNI class) + if ((tm = Getattr(p,"tmap:javain"))) { + substituteJavaclassname(pt, tm); + Replaceall(tm, "$javainput", arg); + Printv(nativecall, 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 to java shadow function header */ + if (gencomma >= 2) + Printf(module_class_code, ", "); + gencomma = 2; + Printf(module_class_code, "%s %s", javaparamtype, arg); + + p = Getattr(p,"tmap:in:next"); + Delete(arg); + Delete(javaparamtype); + } + + Printf(nativecall, ")"); + Printf(module_class_code, ")"); + generateThrowsClause(n, module_class_code); + + // Transform return type used in native function (in JNI class) to type used in Java wrapper function (in module class) + if ((tm = Swig_typemap_lookup_new("javaout",n,"",0))) { + if (Getattr(n,"feature:new")) + Replaceall(tm,"$owner","true"); + else + Replaceall(tm,"$owner","false"); + substituteJavaclassname(t, tm); + Replaceall(tm, "$jnicall", nativecall); + Printf(module_class_code, " %s\n\n", tm); + } else { + Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, + "No javaout typemap defined for %s\n", SwigType_str(t,0)); + } + + Delete(shadowrettype); + Delete(nativecall); + Delete(user_arrays); + Delete(func_name); + } + + /* ----------------------------------------------------------------------------- + * substituteJavaclassname() + * + * Substitute $javaclassname with either the shadow class name for classes/structs/unions that SWIG knows about. + * 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 - jstype typemap + * Outputs: + * tm - jstype typemap with $javaclassname substitution + * Return: + * is_java_class - flag indicating if a substitution was performed + * ----------------------------------------------------------------------------- */ + + bool substituteJavaclassname(SwigType *pt, String *tm) { + bool is_java_class = false; + if (Strstr(tm, "$javaclassname") || Strstr(tm,"$&javaclassname")) { + String *javaclassname = is_shadow(pt); + if (javaclassname) { + Replaceall(tm,"$&javaclassname", javaclassname); // is_shadow() works for pointers to classes too + Replaceall(tm,"$javaclassname", javaclassname); + } + 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, "$&javaclassname")) { + SwigType_add_pointer(type); + descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(type)); + Replaceall(tm, "$&javaclassname", descriptor); + } + else { // $javaclassname + descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(type)); + Replaceall(tm, "$javaclassname", descriptor); + } + + // Add to hash table so that the SWIGTYPE Java classes can be created later + Setattr(swig_types_hash, descriptor, type); + Delete(descriptor); + Delete(type); + } + is_java_class = true; + } + return is_java_class; + } + + /* ----------------------------------------------------------------------------- + * 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; + } + + /* ----------------------------------------------------------------------------- + * emitJavaClass() + * ----------------------------------------------------------------------------- */ + + void emitJavaClass(String *javaclassname, SwigType *type) { + String *filen = NewStringf("%s.java", javaclassname); + File *f_swigtype = NewFile(filen,"w"); + String *swigtype = NewString(""); + + // Emit banner and package name + emitBanner(f_swigtype); + if(Len(package) > 0) + Printf(f_swigtype, "package %s;\n\n", package); + + // Pure Java baseclass and interfaces + const String *pure_java_baseclass = javaTypemapLookup("javabase", type, WARN_NONE); + const String *pure_java_interfaces = javaTypemapLookup("javainterfaces", type, WARN_NONE); + + // Emit the class + Printv(swigtype, + javaTypemapLookup("javaimports", type, WARN_NONE), // Import statements + "\n", + javaTypemapLookup("javaclassmodifiers", type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers + " class $javaclassname", // Class name and bases + *Char(pure_java_baseclass) ? + " extends " : + "", + pure_java_baseclass, + *Char(pure_java_interfaces) ? // Pure Java interfaces + " implements " : + "", + pure_java_interfaces, + " {\n", + " private long swigCPtr;\n", + "\n", + " ", + javaTypemapLookup("javaptrconstructormodifiers", type, WARN_JAVA_TYPEMAP_PTRCONSTMOD_UNDEF), // pointer constructor modifiers + " $javaclassname(long cPtr, boolean bFutureUse) {\n", // Constructor used for wrapping pointers + " swigCPtr = cPtr;\n", + " }\n", + "\n", + " protected $javaclassname() {\n", // Default constructor + " swigCPtr = 0;\n", + " }\n", + javaTypemapLookup("javagetcptr", type, WARN_JAVA_TYPEMAP_GETCPTR_UNDEF), // getCPtr method + javaTypemapLookup("javacode", type, WARN_NONE), // extra Java code + "}\n", + "\n", + NIL); + + Replaceall(swigtype, "$javaclassname", javaclassname); + Printv(f_swigtype, swigtype, NIL); + + Close(f_swigtype); + Delete(filen); + Delete(swigtype); + } + + /* ----------------------------------------------------------------------------- + * javaTypemapLookup() + * ----------------------------------------------------------------------------- */ + + const String *javaTypemapLookup(const String *op, String *type, int warning) { + String *tm = NULL; + const String *code = NULL; + + if((tm = Swig_typemap_search(op, type, NULL, NULL))) { + code = Getattr(tm,"code"); + } + + if (!code) { + code = empty_string; + if (warning != WARN_NONE) + Swig_warning(warning, input_file, line_number, "No %s typemap defined for %s\n", op, type); + } + + return code ? code : empty_string; + } + + /* ----------------------------------------------------------------------------- + * addThrows() + * ----------------------------------------------------------------------------- */ + + void addThrows(Node *n, const String *typemap, Node *parameter) { + // Get the comma separated throws clause - held in "throws" attribute in the typemap passed in + String *throws_attribute = NewStringf("%s:throws", typemap); + String *throws = Getattr(parameter,throws_attribute); + + if (throws) { + 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 (String *cls = Firstitem(temp_classes_list); cls; cls = Nextitem(temp_classes_list)) { + String *javacls = NewString(cls); + Replaceall(javacls," ",""); // remove spaces + Replaceall(javacls,"\t",""); // remove tabs + if (Len(javacls) > 0) { + // $javaclassname substitution + SwigType *pt = Getattr(parameter,"type"); + substituteJavaclassname(pt, javacls); + + // Don't duplicate the Java class in the throws clause + bool found_flag = false; + for (String *item = Firstitem(throws_list); item; item = Nextitem(throws_list)) { + if (Strcmp(item, javacls) == 0) + found_flag = true; + } + if (!found_flag) + Append(throws_list, javacls); + } + Delete(javacls); + } + } + Delete(temp_classes_list); + } + Delete(throws_attribute); + } + + /* ----------------------------------------------------------------------------- + * generateThrowsClause() + * ----------------------------------------------------------------------------- */ + + void generateThrowsClause(Node *n, String *code) { + // Add the throws clause into code + List *throws_list = Getattr(n,"java:throwslist"); + if (throws_list) { + String *cls = Firstitem(throws_list); + Printf(code, " throws %s", cls); + while ( (cls = Nextitem(throws_list)) ) + Printf(code, ", %s", cls); + } + } + +}; /* class JAVA */ + +/* ----------------------------------------------------------------------------- + * swig_java() - Instantiate module + * ----------------------------------------------------------------------------- */ + +extern "C" Language * +swig_java(void) { + return new JAVA(); +} + +/* ----------------------------------------------------------------------------- + * Static member variables + * ----------------------------------------------------------------------------- */ + +const char *JAVA::usage = (char*)"\ +Java Options (available with -java)\n\ + -package - set name of the Java package\n\ + -noproxy - Generate the low-level functional interface instead of proxy classes\n"; + + diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx new file mode 100644 index 000000000..4245b7193 --- /dev/null +++ b/Source/Modules/lang.cxx @@ -0,0 +1,1853 @@ +/* ----------------------------------------------------------------------------- + * lang.cxx + * + * Language base class functions. Default C++ handling is also implemented here. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1998-2000. The University of Chicago + * Copyright (C) 1995-1998. The University of Utah and The Regents of the + * University of California. + * + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_lang_cxx[] = "$Header$"; + +#include "swigmod.h" +#include + +/* 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 */ +int Abstract = 0; +int ImportMode = 0; +int IsVirtual = 0; +static String *AttributeFunctionGet = 0; +static String *AttributeFunctionSet = 0; +static int cplus_mode = 0; +static Node *CurrentClass = 0; +int line_number = 0; +char *input_file = 0; +int SmartPointer = 0; + +extern int GenerateDefault; +extern int ForceExtern; +extern int NoExtern; + +/* import modes */ + +#define IMPORT_MODE 1 +#define IMPORT_MODULE 2 + +/* C++ access modes */ + +#define CPLUS_PUBLIC 0 +#define CPLUS_PROTECTED 1 +#define CPLUS_PRIVATE 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_ERROR; + } + + /* 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,"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. + * ---------------------------------------------------------------------- */ + +int Dispatcher::emit_children(Node *n) { + Node *c; + for (c = firstChild(n); c; c = nextSibling(c)) { + 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::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() { + symbols = NewHash(); + classtypes = NewHash(); + overloading = 0; + multiinput = 0; +} + +Language::~Language() { + Delete(symbols); + Delete(classtypes); +} + +/* ---------------------------------------------------------------------- + emit_one() + ---------------------------------------------------------------------- */ + +int Language::emit_one(Node *n) { + int ret; + int oldext; + if (!n) return SWIG_OK; + + if (Getattr(n,"feature:ignore")) return SWIG_OK; + + oldext = Extend; + if (Getattr(n,"feature:extend")) Extend = 1; + + line_number = Getline(n); + input_file = Char(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; +} + +/* This is a hack */ +SwigType *cplus_value_type(SwigType *t) { + Node *n; + if (!CPlusPlus) return 0; + if (SwigType_isclass(t)) { + SwigType *td = SwigType_typedef_resolve_all(t); + if ((n = Swig_symbol_clookup(td,0))) { + if ((Strcmp(nodeType(n),"class") == 0) && (!Getattr(n,"allocate:default_constructor") || (Getattr(n,"allocate:noassign")))) { + String *s = NewStringf("SwigValueWrapper< %s >",t); + Delete(td); + return s; + } + } + if (SwigType_issimple(td) && SwigType_istemplate(td)) { + String *s = NewStringf("SwigValueWrapper< %s >",t); + Delete(td); + return s; + } + Delete(td); + } + return 0; +} + +/* Patch C++ pass-by-value */ +void Language::patch_parms(Parm *p) { + while (p) { + SwigType *t = Getattr(p,"type"); + SwigType *s = cplus_value_type(t); + if (s) { + Setattr(p,"alttype",s); + Delete(s); + } + p = nextSibling(p); + } +} + +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))) { + GenerateDefault = 0; + } else if (strcmp(name,"attributefunction") == 0) { + String *nvalue = NewString(value); + char *s = strchr(Char(nvalue),':'); + if (!s) { + Swig_error(input_file, line_number, "Bad value for attributefunction. Expected \"fmtget:fmtset\".\n"); + } else { + *s = 0; + AttributeFunctionGet = NewString(Char(nvalue)); + AttributeFunctionSet = NewString(s+1); + } + Delete(nvalue); + } else if (strcmp(name,"noattributefunction") == 0) { + AttributeFunctionGet = 0; + AttributeFunctionSet = 0; + } + } +} + +/* ---------------------------------------------------------------------- + * Language::top() - Top of parsing tree + * ---------------------------------------------------------------------- */ + +int Language::top(Node *n) { + return emit_children(n); +} + +/* ---------------------------------------------------------------------- + * Language::extendDirective() + * ---------------------------------------------------------------------- */ + +int Language::extendDirective(Node *n) { + int oldam = Extend; + int oldmode = cplus_mode; + Extend = CWRAP_EXTEND; + cplus_mode = CPLUS_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 != CPLUS_PUBLIC)) return SWIG_NOWRAP; + + if (!ImportMode) { + Swig_require(&n,"name", "?value",NIL); + String *name = Getattr(n,"name"); + String *value = Getattr(n,"value"); + if (!value) { + value = Copy(name); + } else { + value = NewStringf("%(escape)s", value); + } + Setattr(n,"value", value); + this->constantWrapper(n); + Swig_restore(&n); + return SWIG_OK; + } + return SWIG_NOWRAP; +} + +/* ---------------------------------------------------------------------- + * Language::fragmentDirective() + * ---------------------------------------------------------------------- */ + +int Language::fragmentDirective(Node *n) { + String *name = Getattr(n,"name"); + String *code = Getattr(n,"code"); + String *section = Getattr(n,"section"); + Swig_fragment_register(name,section,code); + 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) { + /* %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() + * ---------------------------------------------------------------------- */ + +extern "C" void Swig_cparse_replace_descriptor(String *s); + +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"); + 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); + } + } + parms = nextSibling(parms); + } + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::cDeclaration() + * ---------------------------------------------------------------------- */ + +int Language::cDeclaration(Node *n) { + + String *name = Getattr(n,"name"); + String *symname = Getattr(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + SwigType *decl = Getattr(n,"decl"); + String *storage = Getattr(n,"storage"); + Node *over; + File *f_header = 0; + SwigType *ty, *fullty; + + if (CurrentClass && (cplus_mode != CPLUS_PUBLIC)) return SWIG_NOWRAP; + + if (Cmp(storage,"typedef") == 0) { + Swig_save(&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; + } else if (Cmp(storage,"friend") == 0) { + Swig_warning(WARN_LANG_FRIEND_IGNORE, Getfile(n), Getline(n), + "friend function '%s' ignored.\n", name); + return SWIG_NOWRAP; + } + + /* If in import mode, we proceed no further */ + if (ImportMode) return SWIG_NOWRAP; + + /* Overloaded symbol check */ + over = Swig_symbol_isoverloaded(n); + if (!overloading) { + if (over) over = first_nontemplate(over); + if (over && (over != n)) { + SwigType *tc = Copy(decl); + SwigType *td = SwigType_pop_function(tc); + String *oname; + String *cname; + if (CurrentClass) { + oname = NewStringf("%s::%s",ClassName,name); + cname = NewStringf("%s::%s",ClassName,Getattr(over,"name")); + } else { + oname = NewString(name); + cname = NewString(Getattr(over,"name")); + } + + SwigType *tc2 = Copy(Getattr(over,"decl")); + SwigType *td2 = SwigType_pop_function(tc2); + + Swig_warning(WARN_LANG_OVERLOAD_DECL, input_file, line_number, "Overloaded declaration ignored. %s\n", SwigType_str(td,SwigType_namestr(oname))); + Swig_warning(WARN_LANG_OVERLOAD_DECL, Getfile(over), Getline(over),"Previous declaration is %s\n", SwigType_str(td2,SwigType_namestr(cname))); + + Delete(tc2); + Delete(td2); + Delete(tc); + Delete(td); + Delete(oname); + Delete(cname); + 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 (!NoExtern) { + if (f_header) { + if ((Cmp(storage,"extern") == 0) || (ForceExtern && !storage)) { + Printf(f_header,"extern %s;\n", SwigType_str(ty,name)); + } else if (Cmp(storage,"externc") == 0) { + Printf(f_header,"extern \"C\" %s;\n", SwigType_str(ty,name)); + } + } + } + } + /* This needs to check qualifiers */ + if (SwigType_isqualifier(ty)) { + Setattr(n,"qualifier", SwigType_pop(ty)); + } + Delete(SwigType_pop_function(ty)); + DohIncref(type); + Setattr(n,"type",ty); + functionHandler(n); + Setattr(n,"type",type); + Delete(ty); + Delete(type); + return SWIG_OK; + } else { + /* Some kind of variable declaration */ + Delattr(n,"decl"); + if (Getattr(n,"nested")) Setattr(n,"feature:immutable","1"); + if (!CurrentClass) { + if ((Cmp(storage,"extern") == 0) || ForceExtern) { + f_header = Swig_filebyname("header"); + if (!NoExtern) { + if (f_header) { + Printf(f_header,"extern %s;\n", SwigType_str(ty,name)); + } + } + } + } + if (!SwigType_ismutable(ty)) { + Setattr(n,"feature:immutable","1"); + } + /* If an array and elements are const, then read-only */ + if (SwigType_isarray(ty)) { + SwigType *tya = SwigType_array_type(ty); + if (SwigType_isconst(tya)) { + Setattr(n,"feature:immutable","1"); + } + } + DohIncref(type); + Setattr(n,"type",ty); + variableHandler(n); + Setattr(n,"type",type); + Setattr(n,"decl",decl); + Delete(ty); + Delete(type); + Delete(fullty); + return SWIG_OK; + } +} + +/* ---------------------------------------------------------------------- + * Language::functionHandler() + * ---------------------------------------------------------------------- */ + +int +Language::functionHandler(Node *n) { + Parm *p; + p = Getattr(n,"parms"); + if (CPlusPlus) patch_parms(p); + if (!CurrentClass) { + globalfunctionHandler(n); + } else { + String *storage = Getattr(n,"storage"); + if (Cmp(storage,"static") == 0) { + staticmemberfunctionHandler(n); + } else { + memberfunctionHandler(n); + } + } + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::globalfunctionHandler() + * ---------------------------------------------------------------------- */ + +int +Language::globalfunctionHandler(Node *n) { + + Swig_require(&n,"name","sym:name","type","?parms",NIL); + + String *name = Getattr(n,"name"); + String *symname = Getattr(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + String *storage = Getattr(n,"storage"); + ParmList *parms = Getattr(n,"parms"); + + if (0 && (Cmp(storage,"static") == 0)) { + Swig_restore(&n); + return SWIG_NOWRAP; /* Can't wrap static functions */ + } else { + /* Check for callback mode */ + String *cb = Getattr(n,"feature:callback"); + if (cb) { + String *cbname = NewStringf(cb,symname); + callbackfunctionHandler(n); + if (Cmp(cbname, symname) == 0) { + Delete(cbname); + Swig_restore(&n); + return SWIG_NOWRAP; + } + Delete(cbname); + } + Setattr(n,"parms",nonvoid_parms(parms)); + Setattr(n,"wrap:action", Swig_cresult(type,"result", Swig_cfunction_call(name,parms))); + functionWrapper(n); + } + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::callbackfunctionHandler() + * ---------------------------------------------------------------------- */ + +int +Language::callbackfunctionHandler(Node *n) { + Swig_require(&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 = Getattr(n,"feature:callback"); + String *cbname = NewStringf(cb,symname); + SwigType *cbty = Copy(type); + SwigType_add_function(cbty,parms); + SwigType_add_pointer(cbty); + + Setattr(n,"sym:name", cbname); + Setattr(n,"type", cbty); + Setattr(n,"value", name); + + constantWrapper(n); + Delete(cbname); + Delete(cbty); + + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::memberfunctionHandler() + * ---------------------------------------------------------------------- */ + +int +Language::memberfunctionHandler(Node *n) { + + Swig_require(&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; + + if (Cmp(storage,"virtual") == 0) { + if (Cmp(value,"0") == 0) { + IsVirtual = PURE_VIRTUAL; + } else { + IsVirtual = PLAIN_VIRTUAL; + } + } else { + IsVirtual = 0; + } + cb = Getattr(n,"feature:callback"); + if (cb) { + Node *cb = NewHash(); + String *cbname = NewStringf(cb,symname); + String *cbvalue; + SwigType *cbty = Copy(type); + SwigType_add_function(cbty,parms); + SwigType_add_memberpointer(cbty,ClassName); + cbvalue = NewStringf("&%s::%s",ClassName,name); + Setattr(cb,"sym:name", cbname); + Setattr(cb,"type", cbty); + Setattr(cb,"value", cbvalue); + Setattr(cb,"name", name); + + memberconstantHandler(n); + + Delete(cb); + Delete(cbvalue); + Delete(cbty); + Delete(cbname); + if (Cmp(cbname,symname) == 0) { + Swig_restore(&n); + return SWIG_NOWRAP; + } + } + + String *fname = Swig_name_member(ClassPrefix, symname); + /* Transformation */ + Swig_MethodToFunction(n,ClassType, Getattr(n,"template") ? 0 : Extend | SmartPointer); + Setattr(n,"sym:name",fname); + functionWrapper(n); + + /* DelWrapper(w);*/ + Delete(fname); + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::staticmemberfunctionHandler() + * ---------------------------------------------------------------------- */ + +int +Language::staticmemberfunctionHandler(Node *n) { + + Swig_require(&n,"*name","*sym:name","*type",NIL); + Swig_save(&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 *code = Getattr(n,"code"); + String *cname, *mrename; + + if (!Extend) { + cname = NewStringf("%s::%s",ClassName,name); + } else { + cname = Copy(Swig_name_member(ClassPrefix,name)); + } + mrename = Swig_name_member(ClassPrefix, symname); + + Setattr(n,"name",cname); + Setattr(n,"sym:name",mrename); + + if ((Extend) && (code)) { + /* Hmmm. An added static member. We have to create a little wrapper for this */ + String *tmp = NewStringf("%s(%s)", cname, ParmList_str(parms)); + String *wrap = SwigType_str(type,tmp); + Printv(wrap,code,"\n",NIL); + Setattr(n,"wrap:code",wrap); + Delete(tmp); + Delete(wrap); + } + Delattr(n,"storage"); + globalfunctionHandler(n); + + Delete(cname); + Delete(mrename); + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::variableHandler() + * ---------------------------------------------------------------------- */ + +int +Language::variableHandler(Node *n) { + if (!CurrentClass) { + globalvariableHandler(n); + } else { + String *storage = Getattr(n,"storage"); + if ((Cmp(storage,"static") == 0)) { + if (!SmartPointer) { + staticmembervariableHandler(n); + } + } else { + membervariableHandler(n); + } + } + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::globalvariableHandler() + * ---------------------------------------------------------------------- */ + +int +Language::globalvariableHandler(Node *n) { + String *storage = Getattr(n,"storage"); + if (0 && (Cmp(storage,"static") == 0)) return SWIG_NOWRAP; + variableWrapper(n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::membervariableHandler() + * ---------------------------------------------------------------------- */ + +int +Language::membervariableHandler(Node *n) { + + Swig_require(&n,"*name","*sym:name","*type",NIL); + Swig_save(&n,"parms",NIL); + + String *name = Getattr(n,"name"); + String *symname = Getattr(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + + /* 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 + */ + + if (!(Extend | SmartPointer)) { + Delattr(n,"feature:except"); + } + + if (!AttributeFunctionGet) { + + String *mrename_get, *mrename_set; + + mrename_get = Swig_name_get(Swig_name_member(ClassPrefix, symname)); + mrename_set = Swig_name_set(Swig_name_member(ClassPrefix, symname)); + + /* Create a function to set the value of the variable */ + + if (!Getattr(n,"feature:immutable")) { + int make_wrapper = 1; + String *tm = 0; + String *target = 0; + if (!Extend) { + target = NewStringf("%s->%s", Swig_cparm_name(0,0),name); + tm = Swig_typemap_lookup_new("memberin",n,target,0); + } + Swig_MembersetToFunction(n,ClassType,Extend | SmartPointer); + if (!Extend) { + /* Check for a member in typemap here */ + + /* String *tm = Swig_typemap_lookup((char *) "memberin",type,name,target,Swig_cparm_name(0,1),target,0);*/ + if (!tm) { + if (SwigType_isarray(type)) { + /* Printf(stderr,"%s:%d. Warning. Array member %s will be read-only.\n", input_file, line_number, name);*/ + make_wrapper = 0; + } + } else { + Replace(tm,"$source", Swig_cparm_name(0,1), DOH_REPLACE_ANY); + Replace(tm,"$target", target, DOH_REPLACE_ANY); + Replace(tm,"$input",Swig_cparm_name(0,1),DOH_REPLACE_ANY); + Replace(tm,"$self",Swig_cparm_name(0,0),DOH_REPLACE_ANY); + Setattr(n,"wrap:action", tm); + Delete(tm); + } + Delete(target); + } + if (make_wrapper) { + Setattr(n,"sym:name", mrename_set); + functionWrapper(n); + } else { + Setattr(n,"feature:immutable","1"); + } + /* Restore parameters */ + Setattr(n,"type",type); + Setattr(n,"name",name); + Setattr(n,"sym:name",symname); + } + /* Emit get function */ + { + Swig_MembergetToFunction(n,ClassType,Extend | SmartPointer); + Setattr(n,"sym:name", mrename_get); + 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 = Copy(Swig_name_get(name)); + cpp_member_func(Char(cname),Char(gname),type,0); + Delete(cname); + } + Delete(gname); + if (!Getattr(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 = Copy(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(&n,"*name","*sym:name","*type", "?value", NIL); + String *value = Getattr(n,"value"); + if (!value) { + 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 { + String *name = Getattr(n,"name"); + String *cname = NewStringf("%s::%s", ClassName,name); + 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); + + 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 != CPLUS_PUBLIC)) return SWIG_NOWRAP; + + Swig_require(&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) { + 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::memberconstantHandler() + * ----------------------------------------------------------------------------- */ + +int Language::memberconstantHandler(Node *n) { + + Swig_require(&n,"*name","*sym:name","*value",NIL); + + String *name = Getattr(n,"name"); + String *symname = Getattr(n,"sym:name"); + String *value = Getattr(n,"value"); + + String *mrename; + String *new_value; + + mrename = Swig_name_member(ClassPrefix, symname); + /* Fixed by namespace-enum patch + if ((!value) || (Cmp(value,name) == 0)) { + new_value = NewStringf("%s::%s",ClassName,name); + } else { + new_value = NewString(value); + } + */ + new_value = Copy(value); + Setattr(n,"sym:name", mrename); + Setattr(n,"value", new_value); + Setattr(n,"name", NewStringf("%s::%s", ClassName,name)); + constantWrapper(n); + Delete(mrename); + Delete(new_value); + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::typedefHandler() + * ---------------------------------------------------------------------- */ + +int Language::typedefHandler(Node *) { + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::classDeclaration() + * ---------------------------------------------------------------------- */ + +int Language::classDeclaration(Node *n) { + 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 */ + /* Printf(stdout,"sym:name = %s\n", symname); */ + + 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(&n,"name",NIL); + Setattr(n,"name",classname); + + if (Cmp(kind,"class") == 0) { + cplus_mode = CPLUS_PRIVATE; + } else { + cplus_mode = CPLUS_PUBLIC; + } + + ClassName = NewString(classname); + ClassPrefix = NewString(iname); + if (strip) { + ClassType = NewString(classname); + } else { + ClassType = NewStringf("%s %s", kind, classname); + } + Setattr(n,"classtype", SwigType_namestr(ClassType)); + + InClass = 1; + CurrentClass = n; + + if (Getattr(n,"abstract")) { + Abstract = 1; + } else { + Abstract = 0; + } + + /* Call classHandler() here */ + if (!ImportMode) + classHandler(n); + else + Language::classHandler(n); + + InClass = 0; + CurrentClass = 0; + Delete(ClassType); ClassType = 0; + Delete(ClassPrefix); ClassPrefix = 0; + Delete(ClassName); ClassName = 0; + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::classHandler() + * ---------------------------------------------------------------------- */ + +int Language::classHandler(Node *n) { + + /* 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 = CPLUS_PUBLIC; + SmartPointer = CWRAP_SMART_POINTER; + Node *c; + for (c = Firstitem(methods); c; c= Nextitem(methods)) { + /* Swig_print_node(c); */ + emit_one(c); + } + SmartPointer = 0; + } + + cplus_mode = CPLUS_PUBLIC; + if (!ImportMode && (GenerateDefault && !Getattr(n,"feature:nodefault"))) { + if (!Getattr(n,"has_constructor") && !Getattr(n,"allocate:has_constructor") && (Getattr(n,"allocate:default_constructor"))) { + /* Note: will need to change this to support different kinds of classes */ + if (!Abstract) { + Setattr(CurrentClass,"feature:new","1"); + constructorHandler(CurrentClass); + Delattr(CurrentClass,"feature:new"); + } + } + if (!Getattr(n,"has_destructor") && (!Getattr(n,"allocate:has_destructor")) && (Getattr(n,"allocate:default_destructor"))) { + destructorHandler(CurrentClass); + } + } + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::classforwardDeclaration() + * ---------------------------------------------------------------------- */ + +int Language::classforwardDeclaration(Node *n) { + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::constructorDeclaration() + * ---------------------------------------------------------------------- */ + +int Language::constructorDeclaration(Node *n) { + String *name = Getattr(n,"name"); + String *symname = Getattr(n,"sym:name"); + + if (!CurrentClass) return SWIG_NOWRAP; + if (cplus_mode != CPLUS_PUBLIC) return SWIG_NOWRAP; + if (ImportMode) return SWIG_NOWRAP; + + /* Name adjustment for %name */ + Swig_save(&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) { + String *oname = NewStringf("%s::%s", ClassName, Swig_scopename_last(SwigType_namestr(name))); + String *cname = NewStringf("%s::%s", ClassName, Swig_scopename_last(SwigType_namestr(Getattr(over,"name")))); + SwigType *decl = Getattr(n,"decl"); + Swig_warning(WARN_LANG_OVERLOAD_CONSTRUCT, input_file, line_number, + "Overloaded constructor ignored. %s\n", SwigType_str(decl,SwigType_namestr(oname))); + Swig_warning(WARN_LANG_OVERLOAD_CONSTRUCT, Getfile(over), Getline(over), + "Previous declaration is %s\n", SwigType_str(Getattr(over,"decl"),SwigType_namestr(cname))); + Delete(oname); + Delete(cname); + } else { + constructorHandler(n); + } + } + } else { + if (name && (Cmp(name,ClassName)) && !(Getattr(n,"template"))) { + Printf(stdout,"name = '%s', ClassName='%s'\n", name, ClassName); + Swig_warning(WARN_LANG_RETURN_TYPE, input_file,line_number,"Function %s must have a return type.\n", + name); + Swig_restore(&n); + return SWIG_NOWRAP; + } + constructorHandler(n); + } + } + Setattr(CurrentClass,"has_constructor","1"); + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::constructorHandler() + * ---------------------------------------------------------------------- */ + +int +Language::constructorHandler(Node *n) { + Swig_require(&n,"?name","*sym:name","?type","?parms",NIL); + String *symname = Getattr(n,"sym:name"); + String *mrename; + Parm *parms = Getattr(n,"parms"); + + mrename = Swig_name_construct(symname); + if (CPlusPlus) patch_parms(parms); + Swig_ConstructorToFunction(n,ClassType,CPlusPlus,Getattr(n,"template") ? 0 :Extend); + Setattr(n,"sym:name", mrename); + functionWrapper(n); + Delete(mrename); + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::copyconstructorHandler() + * ---------------------------------------------------------------------- */ + +int +Language::copyconstructorHandler(Node *n) { + Swig_require(&n,"?name","*sym:name","?type","?parms", NIL); + String *symname = Getattr(n,"sym:name"); + String *mrename; + Parm *parms = Getattr(n,"parms"); + if (CPlusPlus) patch_parms(parms); + mrename = Swig_name_copyconstructor(symname); + Swig_ConstructorToFunction(n,ClassType, CPlusPlus, Getattr(n,"template") ? 0 : Extend); + Setattr(n,"sym:name", mrename); + functionWrapper(n); + Delete(mrename); + Swig_restore(&n); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::destructorDeclaration() + * ---------------------------------------------------------------------- */ + +int Language::destructorDeclaration(Node *n) { + + if (!CurrentClass) return SWIG_NOWRAP; + if (cplus_mode != CPLUS_PUBLIC) return SWIG_NOWRAP; + if (ImportMode) return SWIG_NOWRAP; + + Swig_save(&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(&n,"?name","*sym:name",NIL); + Swig_save(&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 = CPLUS_PUBLIC; + } else if (Cmp(kind,"private") == 0) { + cplus_mode = CPLUS_PRIVATE; + } else if (Cmp(kind,"protected") == 0) { + cplus_mode = CPLUS_PROTECTED; + } + return SWIG_OK; +} + +/* ----------------------------------------------------------------------------- + * Language::namespaceDeclaration() + * ----------------------------------------------------------------------------- */ + +int Language::namespaceDeclaration(Node *n) { + if (Getattr(n,"alias")) 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 == CPLUS_PUBLIC) { + emit_children(n); + } + 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"); + + Printf(stdout,"constantWrapper : %s = %s\n", SwigType_str(type,name), value); + return SWIG_OK; +} + +/* ---------------------------------------------------------------------- + * Language::variableWrapper() + * ---------------------------------------------------------------------- */ +int Language::variableWrapper(Node *n) { + Swig_require(&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 */ + if (!Getattr(n,"feature:immutable")) { + int make_wrapper = 1; + String *tm = Swig_typemap_lookup_new("globalin", n, name, 0); + + Swig_VarsetToFunction(n); + Setattr(n,"sym:name", Swig_name_set(symname)); + + /* String *tm = Swig_typemap_lookup((char *) "globalin",type,name,name,Swig_cparm_name(0,0),name,0);*/ + + if (!tm) { + if (SwigType_isarray(type)) { + /* Printf(stderr,"%s:%d. Warning. Array member %s will be read-only.\n", input_file, line_number, name);*/ + make_wrapper = 0; + } + } else { + Replace(tm,"$source", Swig_cparm_name(0,0), DOH_REPLACE_ANY); + Replace(tm,"$target", name, DOH_REPLACE_ANY); + Replace(tm,"$input",Swig_cparm_name(0,0),DOH_REPLACE_ANY); + Setattr(n,"wrap:action", tm); + Delete(tm); + } + if (make_wrapper) { + functionWrapper(n); + } + Setattr(n,"sym:name",symname); + Setattr(n,"type",type); + Setattr(n,"name",name); + } + Swig_VargetToFunction(n); + Setattr(n,"sym:name", Swig_name_get(symname)); + 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(parms)))); + Printf(stdout," action : %s\n", Getattr(n,"wrap:action")); + return SWIG_OK; +} + +/* ----------------------------------------------------------------------------- + * Language::nativeWrapper() + * ----------------------------------------------------------------------------- */ + +int Language::nativeWrapper(Node *n) { + return SWIG_OK; +} + +void Language::main(int argc, char *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(String *s, Node *n) { + Node *c = Getattr(symbols,s); + if (c && (c != n)) { + Swig_error(input_file, line_number, "Error. '%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; + SwigType *lt, *ty1,*ty2; + String *base; + String *prefix; + Symtab *stab = 0; + + /* Look in hash of cached values */ + n = Getattr(classtypes,s); + if (n) return n; + + lt = SwigType_ltype(s); + ty1 = SwigType_typedef_resolve_all(lt); + ty2 = SwigType_strip_qualifiers(ty1); + Delete(lt); + Delete(ty1); + + base = SwigType_base(ty2); + + Replaceall(base,"class ",""); + Replaceall(base,"struct ",""); + Replaceall(base,"union ",""); + + prefix = SwigType_prefix(ty2); + + 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; + } + /* Do a symbol table search on the base type */ + /* n = Swig_symbol_clookup(base,0); */ + if (n) { + /* Found a match. Look at the prefix. We only allow + a few cases: pointers, references, and simple */ + if ((Len(prefix) == 0) || /* Simple type */ + (Strcmp(prefix,"p.") == 0) || /* pointer */ + (Strcmp(prefix,"r.") == 0)) { /* reference */ + Setattr(classtypes,Copy(s),n); + } else { + n = 0; + } + } + Delete(ty2); + Delete(base); + Delete(prefix); + + if (n && (Getattr(n,"feature:ignore"))) return 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::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; +} diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx new file mode 100644 index 000000000..2cbdbec66 --- /dev/null +++ b/Source/Modules/main.cxx @@ -0,0 +1,622 @@ +/* ----------------------------------------------------------------------------- + * main.cxx + * + * Main entry point to the SWIG core. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1998-2000. The University of Chicago + * Copyright (C) 1995-1998. The University of Utah and The Regents of the + * University of California. + * + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_main_cxx[] = "$Header$"; + +#if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#include "swigmod.h" +#ifndef MACSWIG +#include "swigconfig.h" +#endif + +#include "swigwarn.h" + +extern "C" { +#include "preprocessor.h" +} + +#include + +#ifndef SWIG_LIB +#define SWIG_LIB "/usr/local/lib/swig1.3" +#endif + +#ifndef SWIG_CC +#define SWIG_CC "CC" +#endif + +// Global variables + + char LibDir[512]; // Library directory + Language *lang; // Language method + int CPlusPlus = 0; + int Extend = 0; // Extend flag + int ForceExtern = 0; // Force extern mode + int GenerateDefault = 1; // Generate default constructors + char *Config = 0; + int NoInclude = 0; + int Verbose = 0; + int NoExtern = 0; + int NoExcept = 0; + +extern "C" { +extern String *ModuleName; +} + +static char *usage = (char*)"\ +\nGeneral Options\n\ + -c - Produce raw wrapper code (omit support code)\n\ + -c++ - Enable C++ processing\n\ + -co - Check a file out of the SWIG library\n\ + -Dsymbol - Define a symbol (for conditional compilation)\n\ + -I - Look for SWIG files in \n\ + -includeall - Follow all #include statements\n\ + -importall - Follow all #include statements as imports\n\ + -ignoremissing - Ignore missing include files.\n\ + -l - Include SWIG library file.\n\ + -M - List all dependencies. \n\ + -MM - List dependencies, but omit files in SWIG library.\n\ + -makedefault - Create default constructors/destructors (the default)\n\ + -module - Set module name\n\ + -nodefault - Do not generate constructors/destructors\n\ + -noexcept - Do not wrap exception specifiers.\n\ + -noextern - Do not generate extern declarations.\n\ + -o outfile - Set name of the output file.\n\ + -swiglib - Report location of SWIG library and exit\n\ + -v - Run in verbose mode\n\ + -version - Print SWIG version number\n\ + -Wall - Enable all warning messages\n\ + -wn - Suppress warning number n\n\ + -help - This output.\n\n"; + +// ----------------------------------------------------------------------------- +// check_suffix(char *name) +// +// Checks the suffix of a file to see if we should emit extern declarations. +// ----------------------------------------------------------------------------- + +int +check_suffix(char *name) { + 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); + } + } + } + } +} +//----------------------------------------------------------------- +// main() +// +// Main program. Initializes the files and starts the parser. +//----------------------------------------------------------------- + +char *SwigLib; +static int freeze = 0; +static String *lang_config = 0; +static char *cpp_extension = (char *) "cxx"; + +/* This function sets the name of the configuration file */ + +void SWIG_config_file(const String_or_char *filename) { + lang_config = NewString(filename); +} + +void SWIG_library_directory(const char *filename) { + strcpy(LibDir,filename); +} + +void SWIG_config_cppext(const char *ext) { + cpp_extension = (char *) ext; +} + +extern "C" Node *Swig_cparse(File *); +extern "C" void Swig_cparse_cplusplus(int); +extern "C" void Swig_cparse_debug_templates(int); + +int SWIG_main(int argc, char *argv[], Language *l) { + int i; + char *c; + char temp[512]; + char *outfile_name = 0; + int help = 0; + int checkout = 0; + int cpp_only = 0; + int tm_debug = 0; + char *includefiles[256]; + int includecount = 0; + extern int check_suffix(char *); + int dump_tags = 0; + int dump_tree = 0; + int contracts = 0; + int browse = 0; + int dump_typedef = 0; + int dump_classes = 0; + int werror = 0; + int depend = 0; + + DOH *libfiles = 0; + DOH *cpps = 0 ; + extern void Swig_contracts(Node *n); + extern void Swig_browser(Node *n, int); + extern void Swig_default_allocators(Node *n); + extern void Swig_process_types(Node *n); + + + /* Initialize the SWIG core */ + Swig_init(); + + /* Suppress warning messages for private inheritance, preprocessor evaluation, + might be abstract, and overloaded const */ + + Swig_warnfilter("202,309,403,512",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 + String *vers; + vers = NewStringf("SWIG_VERSION 0x%02d%02d%02d", SWIG_MAJOR_VERSION, SWIG_MINOR_VERSION, SWIG_SPIN); + Preprocessor_define(vers,0); + + // 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) { + Printf(stderr, "Warning: Could not determine SWIG library location. Assuming " SWIG_LIB "\n"); + sprintf(LibDir,"%s",SWIG_LIB); // Build up search paths + } else { + strcpy(p+1, "Lib"); + strcpy(LibDir, buf); + } +#else + sprintf(LibDir,"%s",SWIG_LIB); // Build up search paths +#endif + } else { + strcpy(LibDir,c); + } + + SwigLib = Swig_copy_string(LibDir); // Make a copy of the real library location + + libfiles = NewList(); + + // Get options + for (i = 1; i < argc; i++) { + if (argv[i]) { + if (strncmp(argv[i],"-I",2) == 0) { + // Add a new directory search path + includefiles[includecount++] = Swig_copy_string(argv[i]+2); + Swig_mark_arg(i); + } else if (strncmp(argv[i],"-D",2) == 0) { + DOH *d = NewString(argv[i]+2); + Replace(d,(char*)"=",(char*)" ", DOH_REPLACE_ANY | DOH_REPLACE_FIRST); + Preprocessor_define((DOH *) d,0); + // 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],"-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 1", 0); + Swig_cparse_cplusplus(1); + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-c") == 0) { + NoInclude=1; + Preprocessor_define((DOH *) "SWIG_NOINCLUDE 1", 0); + Swig_mark_arg(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_mark_arg(i); + } else if (strcmp(argv[i],"-noexcept") == 0) { + NoExcept = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-noextern") == 0) { + NoExtern = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-show_templates") == 0) { + Swig_cparse_debug_templates(1); + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-swiglib") == 0) { + printf("%s\n", LibDir); + 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]); + Swig_mark_arg(i+1); + i++; + } else { + Swig_arg_error(); + } + } else if (strcmp(argv[i],"-version") == 0) { + fprintf(stderr,"\nSWIG Version %s\n", + SWIG_VERSION); + fprintf(stderr,"Copyright (c) 1995-1998\n"); + fprintf(stderr,"University of Utah and the Regents of the University of California\n"); + fprintf(stderr,"Copyright (c) 1998-2002\n"); + fprintf(stderr,"University of Chicago\n"); + fprintf(stderr,"\nCompiled with %s\n", SWIG_CC); + 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],"-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],"-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; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-MM") == 0) { + depend = 2; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-Wall") == 0) { + Swig_mark_arg(i); + Swig_warnall(); + } else if (strcmp(argv[i],"-Werror") == 0) { + werror = 1; + Swig_mark_arg(i); + } else if (strncmp(argv[i],"-w",2) == 0) { + Swig_mark_arg(i); + Swig_warnfilter(argv[i]+2,1); + } else if (strcmp(argv[i],"-dump_tags") == 0) { + dump_tags = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-dump_tree") == 0) { + dump_tree = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-contracts") == 0) { + Swig_mark_arg(i); + contracts = 1; + } else if (strcmp(argv[i],"-browse") == 0) { + browse = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-dump_typedef") == 0) { + dump_typedef = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-dump_classes") == 0) { + dump_classes = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-help") == 0) { + fputs(usage,stderr); + Swig_mark_arg(i); + help = 1; + } + } + } + + for (i = 0; i < includecount; i++) { + Swig_add_directory((DOH *) includefiles[i]); + } + + // Define the __cplusplus symbol + if (CPlusPlus) + Preprocessor_define((DOH *) "__cplusplus 1", 0); + + // Parse language dependent options + lang->main(argc,argv); + + if (help) SWIG_exit (EXIT_SUCCESS); // Exit if we're in help mode + + // Check all of the options to make sure we're cool. + Swig_check_options(); + + install_opts(argc, argv); + + // Add language dependent directory to the search path + { + DOH *rl = NewString(""); + Printf(rl,"%s%s%s", SwigLib, SWIG_FILE_DELIMETER, LibDir); + Swig_add_directory(rl); + rl = NewString(""); + Printf(rl,".%sswig_lib%s%s", SWIG_FILE_DELIMETER, SWIG_FILE_DELIMETER, LibDir); + Swig_add_directory(rl); + } + + sprintf(temp,"%s%sconfig", SwigLib, SWIG_FILE_DELIMETER); + Swig_add_directory((DOH *) temp); + Swig_add_directory((DOH *) "." SWIG_FILE_DELIMETER "swig_lib" SWIG_FILE_DELIMETER "config"); + Swig_add_directory((DOH *) SwigLib); + Swig_add_directory((DOH *) "." SWIG_FILE_DELIMETER "swig_lib"); + + if (Verbose) { + printf ("LibDir: %s\n", LibDir); + List *sp = Swig_search_path(); + String *s; + for (s = Firstitem(sp); s; s = Nextitem(sp)) { + Printf(stdout," %s\n", s); + } + } + + // If we made it this far, looks good. go for it.... + + input_file = argv[argc-1]; + + // If the user has requested to check out a file, handle that + if (checkout) { + DOH *s; + char *outfile = input_file; + if (outfile_name) + outfile = outfile_name; + + if (Verbose) + printf ("Handling checkout...\n"); + + s = Swig_include(input_file); + if (!s) { + fprintf(stderr,"Unable to locate '%s' in the SWIG library.\n", input_file); + } else { + FILE *f = fopen(outfile,"r"); + if (f) { + fclose(f); + fprintf(stderr,"File '%s' already exists. Checkout aborted.\n", outfile); + } else { + f = fopen(outfile,"w"); + if (!f) { + fprintf(stderr,"Unable to create file '%s'\n", outfile); + } else { + fprintf(stderr,"'%s' checked out from the SWIG library.\n", input_file); + fputs(Char(s),f); + fclose(f); + } + } + } + } else { + // Check the suffix for a .c file. If so, we're going to + // declare everything we see as "extern" + + ForceExtern = check_suffix(input_file); + + // Run the preprocessor + if (Verbose) + printf ("Preprocessing...\n"); + { + int i; + String *fs = NewString(""); + FILE *df = Swig_open(input_file); + if (!df) { + Printf(stderr,"Unable to find '%s'\n", input_file); + SWIG_exit (EXIT_FAILURE); + } + fclose(df); + Printf(fs,"%%include \"swig.swg\"\n"); + if (lang_config) { + Printf(fs,"\n%%include \"%s\"\n", lang_config); + } + Printf(fs,"%%include \"%s\"\n", 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); + if (Swig_error_count()) { + SWIG_exit(EXIT_FAILURE); + } + if (cpp_only) { + Printf(stdout,"%s", cpps); + while (freeze); + SWIG_exit (EXIT_SUCCESS); + } + if (depend) { + String *outfile; + if (!outfile_name) { + if (CPlusPlus) { + outfile = NewStringf("%s_wrap.%s", Swig_file_basename(input_file),cpp_extension); + } else { + outfile = NewStringf("%s_wrap.c", Swig_file_basename(input_file)); + } + } else { + outfile = NewString(outfile_name); + } + Printf(stdout,"%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(stdout,"\\\n %s ", Getitem(files,i)); + } + } + Printf(stdout,"\n"); + SWIG_exit(EXIT_SUCCESS); + } + 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 (Verbose) { + Printf(stdout,"Processing types...\n"); + } + Swig_process_types(top); + + if (Verbose) { + Printf(stdout,"C++ analysis...\n"); + } + Swig_default_allocators(top); + + if (Verbose) { + Printf(stdout,"Generating wrappers...\n"); + } + + if (dump_classes) { + Hash *classes = Getattr(top,"classes"); + if (classes) { + Printf(stdout,"Classes\n"); + Printf(stdout,"------------\n"); + String *key; + for (key = Firstkey(classes); key; key = Nextkey(classes)) { + Printf(stdout,"%s\n", key); + } + } + } + + if (dump_typedef) { + SwigType_print_scope(0); + } + if (dump_tags) { + Swig_print_tags(top,0); + } + if (dump_tree) { + Swig_print_tree(top); + } + 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 */ + Setattr(top,"infile", input_file); + if (!outfile_name) { + if (CPlusPlus) { + Setattr(top,"outfile", NewStringf("%s_wrap.%s", Swig_file_basename(input_file),cpp_extension)); + } else { + Setattr(top,"outfile", NewStringf("%s_wrap.c", Swig_file_basename(input_file))); + } + } else { + Setattr(top,"outfile", outfile_name); + } + if (contracts) { + Swig_contracts(top); + } + lang->top(top); + if (browse) { + Swig_browser(top,0); + } + } + } + } + if (tm_debug) Swig_typemap_debug(); + 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/module.cxx b/Source/Modules/module.cxx new file mode 100644 index 000000000..57aa6c304 --- /dev/null +++ b/Source/Modules/module.cxx @@ -0,0 +1,57 @@ +/* ----------------------------------------------------------------------------- + * module.cxx + * + * This file is responsible for the module system. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_module_cxx[] = "$Header$"; + +#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; + } +}; + +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 000000000..14e4a3ac2 --- /dev/null +++ b/Source/Modules/mzscheme.cxx @@ -0,0 +1,668 @@ +/****************************************************************************** + * Simplified Wrapper and Interface Generator (SWIG) + * + * Author : David Beazley + * + * Department of Computer Science + * University of Chicago + * 1100 E 58th Street + * Chicago, IL 60637 + * beazley@cs.uchicago.edu + * + * Please read the file LICENSE for the copyright and terms by which SWIG + * can be used and distributed. + *****************************************************************************/ + +char cvsroot_mzscheme_cxx[] = "$Header$"; + +/*********************************************************************** + * $Header$ + * + * mzscheme.cxx + * + * Definitions for adding functions to Mzscheme 101 + ***********************************************************************/ + +#include "swigmod.h" + +#include + +static const char *mzscheme_usage = (char*)"\ +\n\ +Mzscheme Options (available with -mzscheme)\n\ +-help - Print this help\n\ +-prefix name - Set a prefix to be appended to all names\n\ +-declaremodule - Create extension that declares a module\n\ +\n" +; + +static char *prefix=0; +static bool declaremodule = false; +static String *module=0; +static char *mzscheme_path=(char*)"mzscheme"; +static String *init_func_def = 0; + +static File *f_runtime = 0; +static File *f_header = 0; +static File *f_wrappers = 0; +static File *f_init = 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 (mzscheme_usage, stderr); + 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); + } + } + } + + // 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.i"); + allow_overloading(); + + } + + /* ------------------------------------------------------------ + * top() + * ------------------------------------------------------------ */ + + virtual int top(Node *n) { + + /* Initialize all of the output files */ + String *outfile = Getattr(n,"outfile"); + + f_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + 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("runtime",f_runtime); + + init_func_def = NewString(""); + Swig_register_filebyname("init",init_func_def); + + Printf(f_runtime, "/* -*- buffer-read-only: t -*- vi: set ro: */\n"); + Swig_banner (f_runtime); + + if (NoInclude) { + Printf(f_runtime, "#define SWIG_NOINCLUDE\n"); + } + + module = Getattr(n,"name"); + + Language::top(n); + + SwigType_emit_type_table (f_runtime, f_wrappers); + Printf(f_init, "Scheme_Object *scheme_reload(Scheme_Env *env) {\n"); + Printf(f_init, "\tScheme_Env *menv = env;\n"); + if (declaremodule) { + Printf(f_init, "\tmenv = scheme_primitive_module(scheme_intern_symbol(\"%s\"), env);\n", module); + } + Printf (f_init, "\tSWIG_RegisterTypes(swig_types, swig_types_initial);\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"); + 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_header,f_runtime); + Dump(f_wrappers,f_runtime); + Wrapper_pretty_print(f_init,f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + Delete(f_runtime); + 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; + + // 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)) 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); + + // Declare return variable and arguments + // number of parameters + // they are called arg0, arg1, ... + // the return value is called result + + emit_args(d, 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); + + // adds local variables + Wrapper_add_local(f, "_len", "int _len"); + Wrapper_add_local(f, "lenv", "int lenv = 1"); + Wrapper_add_local(f, "values", "Scheme_Object *values[MAXVALUES]"); + + // 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 + + emit_action(n,f); + + // Now have return value, figure out what to do with it. + + if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) { + Replaceall(tm,"$source","result"); + Replaceall(tm,"$target","values[0]"); + Replaceall(tm,"$result","values[0]"); + Printv(f->code, tm, "\n",NIL); + } else { + throw_unhandled_mzscheme_type_error (d); + } + + // 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 (Getattr(n,"feature:new")) { + if ((tm = Swig_typemap_lookup_new("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_new("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_package_values(lenv, values);\n", NIL); + Printf(f->code, "#undef FUNC_NAME\n"); + Printv(f->code, "}\n",NIL); + + Wrapper_print(f, f_wrappers); + + if (!Getattr(n,"sym:overloaded")) { + + // Now register the function + char temp[256]; + sprintf(temp, "%d", numargs); + 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(""); + char var_name[256]; + 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 + + strcpy(var_name, Char(Swig_name_wrapper(iname))); + + // Build the name for scheme. + Printv(proc_name, iname,NIL); + Replaceall(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 (!Getattr(n,"feature:immutable")) { + /* Check for a setting of the variable value */ + Printf (f->code, "if (argc) {\n"); + if ((tm = Swig_typemap_lookup_new("varin",n,name,0))) { + Replaceall(tm,"$source","argv[0]"); + Replaceall(tm,"$target",name); + Replaceall(tm,"$input","argv[0]"); + Printv(f->code, tm, "\n",NIL); + } + 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_new("varout",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_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(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(iname)); + + // 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_new("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); + variableWrapper(n); + Delete(n); + } + } + Delete(proc_name); + Delete(rvalue); + Delete(temp); + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * validIdentifer() + * ------------------------------------------------------------ */ + + virtual int validIdentifier(String *s) { + char *c = Char(s); + /* Check whether we have an R5RS identifier.*/ + /* --> * | */ + /* --> | */ + if (!(isalpha(*c) || (*c == '!') || (*c == '$') || (*c == '%') + || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':') + || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?') + || (*c == '^') || (*c == '_') || (*c == '~'))) { + /* --> + | - | ... */ + if ((strcmp(c, "+") == 0) + || strcmp(c, "-") == 0 + || strcmp(c, "...") == 0) return 1; + else return 0; + } + /* --> | | */ + 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; + } +}; + +/* ----------------------------------------------------------------------------- + * swig_mzscheme() - Instantiate module + * ----------------------------------------------------------------------------- */ + +extern "C" Language * +swig_mzscheme(void) { + return new MZSCHEME(); +} + + diff --git a/Source/Modules/ocaml.cxx b/Source/Modules/ocaml.cxx new file mode 100755 index 000000000..786fee5dd --- /dev/null +++ b/Source/Modules/ocaml.cxx @@ -0,0 +1,1072 @@ +/* -*- c-indentation-style: gnu -*- */ +/****************************************************************************** + * Simplified Wrapper and Interface Generator (SWIG) + * + * Author : Art Yerkes + * Modified from mzscheme.cxx : David Beazley + * + * Please read the file LICENSE for the copyright and terms by which SWIG + * can be used and distributed. + *****************************************************************************/ + +char cvsroot_ocaml_cxx[] = "$Header$"; + +/*********************************************************************** + * $Header$ + * + * ocaml.cxx + * + * Definitions for adding functions to Ocaml 101 + ***********************************************************************/ + +#include "swigmod.h" + +#include + +static const char *ocaml_usage = (char*)"\ +\n\ +Ocaml Options (available with -ocaml)\n\ +-help - Print this help\n\ +-prefix name - Set a prefix to be appended to all names\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 char *prefix=0; +static String *classname=0; +static String *module=0; +static char *ocaml_path=(char*)"ocaml"; +static String *init_func_def = 0; + +static Hash *seen_enums = 0; +static Hash *seen_enumvalues = 0; +static Hash *seen_constructors = 0; + +static File *f_header = 0; +static File *f_runtime = 0; +static File *f_wrappers = 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_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: + + /* ------------------------------------------------------------ + * main() + * ------------------------------------------------------------ */ + + virtual void main (int argc, char *argv[]) { + + int i; + + 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 (ocaml_usage, stderr); + 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(); + } + } + } + } + + // 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(); + + } + + /* ------------------------------------------------------------ + * top() + * ------------------------------------------------------------ */ + + virtual int top(Node *n) { + /* Initialize all of the output files */ + String *outfile = Getattr(n,"outfile"); + + f_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + f_init = NewString(""); + f_header = NewString(""); + f_wrappers = NewString(""); + f_enumtypes_type = NewString(""); + f_enumtypes_value = NewString(""); + f_mlbody = NewString(""); + f_mlibody = NewString(""); + f_class_ctors = NewString(""); + f_class_ctors_end = NewString(""); + f_enum_to_int = NewString(""); + f_int_to_enum = 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("header",f_header); + Swig_register_filebyname("wrapper",f_wrappers); + Swig_register_filebyname("runtime",f_runtime); + Swig_register_filebyname("mli",f_mlibody); + Swig_register_filebyname("ml",f_mlbody); + + init_func_def = NewString(""); + Swig_register_filebyname("init",init_func_def); + + Swig_name_register("set","%v__set__"); + Swig_name_register("get","%v__get__"); + + Printf(f_runtime, + "/* -*- buffer-read-only: t -*- vi: set ro: */\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 =\n" + " match v with C_enum y -> (\n" + " match (x : c_enum_type) with\n" + " `unknown -> (match (y : c_enum_tag) with\n" + " `int (x : int) -> 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" ); + + Swig_banner (f_runtime); + + if (NoInclude) { + Printf(f_runtime, "#define SWIG_NOINCLUDE\n"); + } + + /* Produce the enum_to_int and int_to_enum functions */ + + Printf(f_enumtypes_type,"type c_enum_type = [ \n `unknown\n" ); + Printf(f_enumtypes_value,"type c_enum_tag = [ \n `int of int\n" ); + + String *mlfile = NewString(""); + String *mlifile = NewString(""); + + Printv(mlfile,module,".ml",NIL); + Printv(mlifile,module,".mli",NIL); + + f_mlout = NewFile(mlfile,"w"); + f_mliout = NewFile(mlifile,"w"); + + 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 -> 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_enumtypes_type, "]\n" ); + Printf( f_enumtypes_value, "]\n" ); + + SwigType_emit_type_table (f_runtime, f_wrappers); + /* Close all of the files */ + Dump(f_header,f_runtime); + Dump(f_wrappers,f_runtime); + Wrapper_pretty_print(f_init,f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + Delete(f_runtime); + + 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); + Close(f_mlout); + Delete(f_mlout); + + Dump(f_enumtypes_type,f_mliout); + Dump(f_enumtypes_value,f_mliout); + Dump(f_mlibody,f_mliout); + Close(f_mliout); + Delete(f_mliout); + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * functionWrapper() + * Create a function declaration and register it with the interpreter. + * ------------------------------------------------------------ */ + + void throw_unhandled_ocaml_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; + int newobj = Getattr(n,"feature:new") ? 1 : 0; + String *overname = 0; + + // 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)) return SWIG_ERROR; + } + if (overname) { + Append(wname, overname); + } + 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,"name")); + + Replaceall(opname,"operator ",""); + + if( strstr( Char(mangled_name), "__get__" ) ) { + String *set_name = Copy(mangled_name); + if( !Getattr(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, + "#ifdef __cplusplus\n" + "extern \"C\"\n" + "#endif\n" + "value ", wname, " (", NIL); + Printv(f->def, "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", "CAMLlocal2(swig_result,rv)"); + Wrapper_add_local(f, "_len", "int _len"); + Wrapper_add_local(f, "lenv", "int lenv = 1"); + Wrapper_add_local(f, "argc", "int argc = caml_list_length(args)"); + Wrapper_add_local(f, "argv", "value *argv"); + Wrapper_add_local(f, "i", "int i"); + + Printv( f->code, + "argv = (value *)malloc( argc * sizeof( value ) );\n" + "for( i = 0; i < argc; i++ ) {\n" + " argv[i] = caml_list_nth(args,i);\n" + "}\n", NIL ); + + // Declare return variable and arguments + // number of parameters + // they are called arg0, arg1, ... + // the return value is called result + + emit_args(d, 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"); + + // 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); + 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 + + emit_action(n,f); + + // Now have return value, figure out what to do with it. + + if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) { + Replaceall(tm,"$source","result"); + Replaceall(tm,"$target","rv"); + Replaceall(tm,"$result","rv"); + Printv(f->code, tm, "\n",NIL); + } else { + throw_unhandled_ocaml_type_error (d); + } + + // 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 (Getattr(n,"feature:new")) { + if ((tm = Swig_typemap_lookup_new("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_new("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" + tab4, "free( argv );\n" + tab4, "if( lenv == 0 )\n" + tab4, "{\n" + tab4, tab4, "CAMLreturn(Val_unit);\n", + tab4, "}\n" + tab4, "else\n" + tab4, "{\n", + tab4, tab4, "CAMLreturn(swig_result);\n", + tab4, "}\n", NIL); + Printf(f->code, "#undef FUNC_NAME\n"); + Printv(f->code, "}\n",NIL); + + Wrapper_print(f, f_wrappers); + + if( Getattr(n,"sym:overloaded") ) { + if( !Getattr(n,"sym:nextSibling") ) { + int maxargs; + Wrapper *df = NewWrapper(); + String *dname = Swig_name_wrapper(iname); + String *dispatch = + Swig_overload_dispatch(n, + "free(argv);\nCAMLreturn(%s(args));\n", + &maxargs); + + Wrapper_add_local(df, "argv", "value *argv"); + + Printv(df->def, + "#ifdef __cplusplus\n" + "extern \"C\"\n" + "#endif\n" + "value ",dname,"(value args) {\n" + " CAMLparam1(args);\n" + " int i;\n" + " int argc = caml_list_length(args);\n",NIL); + Printv( df->code, + "argv = (value *)malloc( argc * sizeof( 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); + + Printf(f_mlbody, + "external %s_f : c_obj list -> c_obj list = \"%s\"\n" + "let %s = fnhelper %s %s_f\n", + mangled_name, dname, mangled_name, + newobj ? "true" : "false", + mangled_name ); + if( !classmode || in_constructor || in_destructor || + static_member_function ) + Printf(f_mlibody, + "(* overload *)\n" + "val %s : c_obj -> c_obj\n", mangled_name ); + + DelWrapper(df); + Delete(dispatch); + Delete(dname); + } + } else { + Printf(f_mlbody, + "external %s_f : c_obj list -> c_obj list = \"%s\"\n" + "let %s = fnhelper %s %s_f\n", + mangled_name, wname, mangled_name, newobj ? "true" : "false", + mangled_name ); + if( !classmode || in_constructor || in_destructor || + static_member_function ) + Printf(f_mlibody, + "(* Non-overload *)\n" + "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. Either way, we return the variables + * value. + * ------------------------------------------------------------ */ + + virtual int variableWrapper(Node *n) { + + char *name = GetChar(n,"name"); + String *iname = Getattr(n,"sym:name"); + String *mname = mangleNameForCaml(iname); + SwigType *t = Getattr(n,"type"); + + String *proc_name = NewString(""); + char var_name[256]; + String *tm; + String *tm2 = NewString("");; + String *argnum = NewString("0"); + String *arg = NewString("Field(args,0)"); + Wrapper *f; + + if (!iname || !addSymbol(iname,n)) return SWIG_ERROR; + + f = NewWrapper(); + + // evaluation function names + + strcpy(var_name, Char(Swig_name_wrapper(iname))); + + // Build the name for scheme. + Printv(proc_name, iname,NIL); + //Replaceall(proc_name, "_", "-"); + + if ((SwigType_type(t) != T_USER) || (is_a_pointer(t))) { + + Printf (f->def, + "#ifdef __cplusplus\n" + "extern \"C\"\n" + "#endif\n" + "value %s(value args) {\n", var_name); + Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL); + + Wrapper_add_local (f, "swig_result", "value swig_result"); + + if (!Getattr(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_new("varin",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); + } + Printf (f->code, "}\n"); + } + + // Now return the value of the variable (regardless + // of evaluating or setting) + + if ((tm = Swig_typemap_lookup_new("varout",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); + } + + 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 Ocaml interpreter + + if( Getattr( n, "feature:immutable" ) ) { + Printf( f_mlbody, + "external __%s : c_obj -> c_obj = \"%s\"\n" + "let _%s = __%s C_void\n", + mname, var_name, mname, mname ); + Printf( f_mlibody, "val _%s : c_obj\n", iname ); + if( const_enum ) { + Printf( f_enum_to_int, + " | `%s -> _%s\n", + mname, mname ); + Printf( f_int_to_enum, + " if y = (get_int _%s) 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 ); + } + } else { + Swig_warning(WARN_TYPEMAP_VAR_UNDEF, input_file, line_number, + "Unsupported variable type %s (ignored).\n", SwigType_str(t,0)); + } + + 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() + * ------------------------------------------------------------ */ + + 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(iname)); + + // 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_new("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); + } + + { + /* Hack alert: will cleanup later -- Dave */ + Node *n = NewHash(); + Setattr(n,"name",var_name); + Setattr(n,"sym:name",iname); + Setattr(n,"type", type); + Setattr(n,"feature:immutable","1"); + variableWrapper(n); + Delete(n); + } + } + Delete(proc_name); + Delete(rvalue); + Delete(temp); + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * validIdentifer() + * ------------------------------------------------------------ */ + + virtual int validIdentifier(String *s) { +#if 0 + char *c = Char(s); + /* Check whether we have an R5RS identifier.*/ + /* --> * | */ + /* --> | */ + if (!(isalpha(*c) || (*c == '!') || (*c == '$') || (*c == '%') + || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':') + || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?') + || (*c == '^') || (*c == '_') || (*c == '~'))) { + /* --> + | - | ... */ + if ((strcmp(c, "+") == 0) + || strcmp(c, "-") == 0 + || strcmp(c, "...") == 0) return 1; + else return 0; + } + /* --> | | */ + 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++; + } +#endif + return 1; + } + + int constructorHandler(Node *n) { + int ret; + + in_constructor = 1; + ret = Language::constructorHandler(n); + in_constructor = 0; + + return ret; + } + + int destructorHandler(Node *n) { + int ret; + + in_destructor = 1; + ret = Language::destructorHandler(n); + in_destructor = 0; + + return ret; + } + + int copyconstructorHandler(Node *n) { + int ret; + + in_copyconst = 1; + in_constructor = 1; + ret = Language::copyconstructorHandler(n); + in_constructor = 0; + in_copyconst = 0; + + return ret; + } + + int classHandler( Node *n ) { + String *name = Getattr(n,"name"); + String *mangled_sym_name = mangleNameForCaml(name); + + if( !name ) return SWIG_OK; + + classname = mangled_sym_name; + + Printf( f_class_ctors, + "let create_%s_from_ptr raw_ptr =\n" + " C_obj (let rec method_table = [\n" + " \"nop\", (fun args -> C_void) ;\n", + classname ); + + Printf( f_mlibody, + "val create_%s_from_ptr : c_obj -> c_obj\n", + classname ); + + classmode = 1; + int rv = Language::classHandler(n); + classmode = 0; + +#if 0 + Printf(f_mlibody, + "val delete_%s : c_obj -> unit\n", + mangled_sym_name ); +#endif + + /* Handle up-casts in a nice way */ + List *baselist = Getattr(n,"bases"); + if (baselist && Len(baselist)) { + Node *base = Firstitem(baselist); + while (base) { + String *bname = Getattr(base, "ocaml:ctor"); + if (bname) + Printv(f_class_ctors, + " \"::",bname,"\", (fun args -> " + "create_",bname,"_from_ptr raw_ptr) ;\n",NIL); + + base = Nextitem(baselist); + } + } + + Printf(f_class_ctors, + " \"&\", (fun args -> raw_ptr) ;\n" + " \":parents\",\n" + " (fun args -> \n" + " C_list \n" + " (List.map \n" + " (fun (x,y) -> \n" + " C_string (String.sub x 2 ((String.length x) - 2)))\n" + " (List.filter \n" + " (fun (x,y) -> \n" + " ((String.length x) > 2) && \n" + " x.[0] == ':' && \n" + " x.[1] == ':') method_table))) ;\n" + " \":classof\", (fun args -> (C_string \"%s\")) ;\n" + " \":methods\", " + "(fun args -> C_list (List.map (fun (x,y) -> C_string x) " + "method_table)) ] in\n" + " (fun mth arg ->\n" + " try\n" + " let method_name,application = List.hd (List.filter (fun (x,y) -> x = mth) method_table) in\n" + " application \n" + " (match arg with C_list l -> (C_list (raw_ptr :: l)) | C_void -> (C_list [ raw_ptr ]) | v -> (C_list [ raw_ptr ; v ]))\n" + " with (Failure \"hd\") -> \n" + " (* Try parent classes *)\n" + " begin\n" + " let parent_classes = [ \n", + name ); + + /* Handle inheritance -- Mostly stolen from python code */ + baselist = Getattr(n,"bases"); + if (baselist && Len(baselist)) { + Node *base = Firstitem(baselist); + while (base) { + String *bname = Getattr(base, "ocaml:ctor"); + if (bname) + Printv(f_class_ctors, + " create_",bname,"_from_ptr",NIL); + + base = Nextitem(baselist); + if (base) + Printv(f_class_ctors," ;\n",NIL); + else + Printv(f_class_ctors,"\n",NIL); + } + } + + Printv(f_class_ctors," ]\n",NIL); + + Printf(f_class_ctors, + " in let rec try_parent plist raw_ptr = \n" + " match plist with\n" + " p :: tl -> (try\n" + " (invoke (p raw_ptr)) mth arg\n" + " with (BadMethodName (p,m,s)) -> try_parent tl raw_ptr)\n" + " | [] ->\n" + " raise (BadMethodName (raw_ptr,mth,\"%s\"))\n" + " in try_parent parent_classes raw_ptr\n" + " end\n" + " | e -> raise e))\n", + name ); + + Printf( f_class_ctors, + "let _ = Callback.register \"create_%s_from_ptr\" " + "create_%s_from_ptr\n", + classname, classname ); + + Setattr(n,"ocaml:ctor",classname); + + return rv; + } + + String *mangleNameForCaml( String *s ) { + String *out = Copy(s); + Replaceall(out," ","_"); + Replaceall(out,"::","_"); + Replaceall(out,",","_x_"); + Replaceall(out,"+","__plus__"); + Replaceall(out,"-","__minus__"); + Replaceall(out,"<","__ldbrace__"); + Replaceall(out,">","__rdbrace__"); + Replaceall(out,"!","__not__"); + Replaceall(out,"%","__mod__"); + Replaceall(out,"^","__xor__"); + Replaceall(out,"*","__star__"); + Replaceall(out,"&","__amp__"); + Replaceall(out,"|","__or__"); + Replaceall(out,"(","__lparen__"); + Replaceall(out,")","__rparen__"); + Replaceall(out,"[","__lbrace__"); + Replaceall(out,"]","__rbrace__"); + Replaceall(out,"~","__bnot__"); + Replaceall(out,"=","__equals__"); + Replaceall(out,"/","__slash__"); + Replaceall(out,".","__dot__"); + return out; + } + + /* Benedikt Grundmann inspired --> Enum wrap styles */ + + int enumvalueDeclaration(Node *n) { + String *name = Getattr(n,"name"); + + if( const_enum && name && !Getattr(seen_enumvalues,name) ) { + Printf( f_enumtypes_value,"| `%s\n", name ); + Setattr(seen_enumvalues,name,"true"); + Setattr(n,"feature:immutable","1"); + + return constantWrapper(n); + } else return SWIG_OK; + } + + int enumDeclaration(Node *n) { + String *name = Getattr(n,"name"); + + if( name && !Getattr(seen_enums,name) ) { + const_enum = 1; + Printf( f_enum_to_int, "| `%s -> (match (y : c_enum_tag) with\n", name ); + Printf( f_int_to_enum, "| `%s -> C_enum (\n", name ); + Printf( f_mlbody, + "let _ = Callback.register \"%s_marker\" (`%s)\n", + name, name ); + Printf( f_enumtypes_type,"| `%s\n", name ); + Setattr(seen_enumvalues,name,"true"); + } + + int ret = Language::enumDeclaration(n); + + if( const_enum ) { + Printf( f_int_to_enum, "`int y)\n", name ); + Printf( f_enum_to_int, + "| `int (x : int) -> C_int x\n" + "| _ -> raise (Failure \"Unknown enum tag\"))\n" ); + } + + const_enum = 0; + + return ret; + } +}; + +/* ------------------------------------------------------------------------- + * swig_ocaml() - Instantiate module + * ------------------------------------------------------------------------- */ + +extern "C" Language * +swig_ocaml(void) { + return new OCAML(); +} + diff --git a/Source/Modules/overload.cxx b/Source/Modules/overload.cxx new file mode 100644 index 000000000..f62e63f93 --- /dev/null +++ b/Source/Modules/overload.cxx @@ -0,0 +1,338 @@ +/* ----------------------------------------------------------------------------- + * 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. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_overload_cxx[] = "$Header$"; + +#include "swigmod.h" + +#define MAX_OVERLOAD 256 + +extern int emit_num_required(ParmList *); + +/* ----------------------------------------------------------------------------- + * 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. + * ----------------------------------------------------------------------------- */ + +struct Overloaded { + Node *n; /* Node */ + int argc; /* Argument count */ + ParmList *parms; /* Parameters used for overload check */ + int error; /* Ambiguity error */ +}; + +List * +Swig_overload_rank(Node *n) { + 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")) { + 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 %s(%s) not supported (no type checking rule for '%s').\n", + Getattr(nodes[i].n,"name"),ParmList_str(Getattr(nodes[i].n,"parms")), + 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 %s(%s) not supported (no type checking rule for '%s').\n", + Getattr(nodes[j].n,"name"),ParmList_str(Getattr(nodes[j].n,"parms")), + 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 (t2 && !t1) 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)) { + SwigType_pop(dq1); + } + if (SwigType_isconst(d2)) { + SwigType_pop(dq2); + } + if (Strcmp(dq1,dq2) == 0) { + + if (SwigType_isconst(d1) && !SwigType_isconst(d2)) { + Overloaded t = nodes[i]; + nodes[i] = nodes[j]; + nodes[j] = t; + differ = 1; + if (!nodes[j].error) { + 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_protostr(nodes[j].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) { + 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_protostr(nodes[j].parms), + Getfile(nodes[i].n), Getline(nodes[i].n)); + } + nodes[j].error = 1; + } + } + Delete(dq1); + Delete(dq2); + } + } + if (!differ) { + if (!nodes[j].error) { + Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n), + "Overloaded %s(%s) is shadowed by %s(%s) at %s:%d.\n", + Getattr(nodes[j].n,"name"), ParmList_protostr(nodes[j].parms), + Getattr(nodes[i].n,"name"), ParmList_protostr(nodes[i].parms), + Getfile(nodes[i].n),Getline(nodes[i].n)); + nodes[j].error = 1; + } + } + } + } + } + } + List *result = NewList(); + { + int i; + for (i = 0; i < nnodes; i++) { + Append(result,nodes[i].n); + // Printf(stdout,"[ %d ] %s\n", i, ParmList_protostr(nodes[i].parms)); + // Swig_print_node(nodes[i].n); + } + } + return result; +} + +/* ----------------------------------------------------------------------------- + * 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. + * ----------------------------------------------------------------------------- */ + +static bool print_typecheck(String *f, int j, Parm *pj) +{ + char tmp[256]; + sprintf(tmp,"argv[%d]",j); + String *tm = Getattr(pj,"tmap:typecheck"); + if (tm) { + Replaceid(tm,Getattr(pj,"lname"),"_v"); + Replaceall(tm,"$input", tmp); + Printv(f,tm,"\n",NIL); + return true; + } + else + return false; +} + +String * +Swig_overload_dispatch(Node *n, const String_or_char *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); + 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 (num_arguments > *maxargs) *maxargs = num_arguments; + int varargs = emit_isvarargs(pi); + + if (!varargs) { + if (num_required == num_arguments) { + Printf(f,"if (argc == %d) {\n", num_required); + } else { + Printf(f,"if ((argc >= %d) && (argc <= %d)) {\n", num_required, num_arguments); + } + } else { + Printf(f,"if (argc >= %d) {\n", 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) { + Printf(f, "if (argc <= %d) {\n", j); + Printf(f, Char(fmt),Getattr(ni,"wrap:name")); + Printf(f, "}\n"); + } + if (print_typecheck(f, j, pj)) { + Printf(f, "if (_v) {\n"); + num_braces++; + } + Parm *pk = Getattr(pj,"tmap:in:next"); + if (pk) pj = pk; + else pj = nextSibling(pj); + j++; + } + Printf(f, Char(fmt),Getattr(ni,"wrap:name")); + /* 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; +} + + diff --git a/Source/Modules/perl5.cxx b/Source/Modules/perl5.cxx new file mode 100644 index 000000000..94191080d --- /dev/null +++ b/Source/Modules/perl5.cxx @@ -0,0 +1,1594 @@ +/* ---------------------------------------------------------------------------- + * perl5.cxx + * + * Generate Perl5 wrappers + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * Loic Dachary (loic@ceic.com) + * David Fletcher + * Gary Holt + * Jason Stewart (jason@openinformatics.com) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ------------------------------------------------------------------------- */ + +char cvsroot_perl5_cxx[] = "$Header$"; + +#include "swigmod.h" + +#ifndef MACSWIG +#include "swigconfig.h" +#endif + +static const char *usage = (char*)"\ +Perl5 Options (available with -perl5)\n\ + -ldflags - Print runtime libraries to link with\n\ + -static - Omit code related to dynamic loading.\n\ + -nopm - Do not generate the .pm file.\n\ + -proxy - Create proxy classes.\n\ + -const - Wrap constants as constants and not variables (implies -shadow).\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. + */ +static String *module = 0; + +/* + * fullmodule + * the fully namespace qualified name of the module, e.g. "XML::Xerces" + * 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 + */ +static String *fullmodule = 0; +/* + * cmodule + * the namespace of the internal glue code, set to the value of + * module with a 'c' appended + */ +static String *cmodule = 0; + +static String *command_tab = 0; +static String *constant_tab = 0; +static String *variable_tab = 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 is_static = 0; + +/* The following variables are used to manage Perl5 classes */ + +static int blessed = 0; /* 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 Hash *operators = 0; +static int have_operators = 0; + +class PERL5 : public Language { +public: + + /* 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; + + SWIG_library_directory("perl5"); + for (i = 1; i < argc; i++) { + if (argv[i]) { + if(strcmp(argv[i],"-package") == 0) { + Printf(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"); + SWIG_exit(EXIT_FAILURE); + } else if(strcmp(argv[i],"-interface") == 0) { + Printf(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"); + 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) { + is_static = 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],"-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],"-compat") == 0) { + compat = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-help") == 0) { + fputs(usage,stderr); + } else if (strcmp (argv[i], "-ldflags") == 0) { + printf("%s\n", SWIG_PERL_RUNTIME); + SWIG_exit (EXIT_SUCCESS); + } + } + } + + Preprocessor_define("SWIGPERL 1", 0); + 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_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + 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("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(""); + + 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_runtime); + + if (NoInclude) { + Printf(f_runtime,"#define SWIG_NOINCLUDE\n"); + } + + module = Copy(Getattr(n,"name")); + + /* If we're in blessed mode, change the package name to "packagec" */ + + if (blessed) { + cmodule = NewStringf("%sc",module); + } else { + cmodule = NewString(module); + } + fullmodule = NewString(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_file_dirname(outfile),pmfile); + if ((f_pm = NewFile(filen,"w")) == 0) { + Printf(stderr,"Unable to open %s\n", filen); + SWIG_exit (EXIT_FAILURE); + } + Swig_register_filebyname("pm",f_pm); + } + { + String *tmp = NewString(fullmodule); + Replaceall(tmp,":","_"); + Printf(f_header,"#define SWIG_init boot_%s\n\n", tmp); + Printf(f_header,"#define SWIG_name \"%s::boot_%s\"\n", cmodule, tmp); + Printf(f_header,"#define SWIG_prefix \"%s::\"\n", cmodule); + Delete(tmp); + } + + Printf(f_pm,"# This file was automatically generated by SWIG\n"); + Printf(f_pm,"package %s;\n",fullmodule); + + Printf(f_pm,"require Exporter;\n"); + if (!is_static) { + Printf(f_pm,"require DynaLoader;\n"); + Printf(f_pm,"@ISA = qw(Exporter DynaLoader);\n"); + } else { + Printf(f_pm,"@ISA = qw(Exporter);\n"); + } + + /* Start creating magic code */ + + Printv(magic, + "#ifdef PERL_OBJECT\n", + "#define MAGIC_CLASS _wrap_", module, "_var::\n", + "class _wrap_", module, "_var : public CPerlObj {\n", + "public:\n", + "#else\n", + "#define MAGIC_CLASS\n", + "#endif\n", + "SWIGCLASS_STATIC int swig_magic_readonly(pTHX_ SV *sv, MAGIC *mg) {\n", + tab4, "MAGIC_PPERL\n", + tab4, "sv = sv; mg = mg;\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); + + Printf(f_header,"%s\n", magic); + + String *type_table = NewString(""); + SwigType_emit_type_table(f_runtime,type_table); + + /* Patch the type table to reflect the names used by shadow classes */ + if (blessed) { + Node *cls; + for (cls = Firstitem(classlist); cls; cls = Nextitem(classlist)) { + if (Getattr(cls,"perl5:proxy")) { + SwigType *type = Copy(Getattr(cls,"classtype")); + SwigType_add_pointer(type); + String *mangle = NewStringf("\"%s\"", SwigType_manglestr(type)); + String *rep = NewStringf("\"%s\"", Getattr(cls,"perl5:proxy")); + Replaceall(type_table,mangle,rep); + Delete(mangle); + Delete(rep); + Delete(type); + } + } + } + + Printf(f_wrappers,"%s",type_table); + Delete(type_table); + + Printf(constant_tab,"{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}\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 (!is_static) { + Printf(f_pm,"bootstrap %s;\n", fullmodule); + } else { + String *tmp = NewString(fullmodule); + Replaceall(tmp,":","_"); + Printf(f_pm,"boot_%s();\n", tmp); + Delete(tmp); + } + Printf(f_pm,"%s",pragma_include); + Printf(f_pm,"package %s;\n", fullmodule); + Printf(f_pm,"@EXPORT = qw( %s);\n",exported); + + if (blessed) { + + Printv(base, + "\n# ---------- BASE METHODS -------------\n\n", + "package ", fullmodule, ";\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 '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",fullmodule); + 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",fullmodule); + Printf(f_pm,"%s",const_stubs); + } + + /* Emit variable stubs */ + + Printf(f_pm,"\n# ------- VARIABLE STUBS --------\n\n"); + Printf(f_pm,"package %s;\n\n",fullmodule); + Printf(f_pm,"%s",var_stubs); + } + + Printf(f_pm,"1;\n"); + Close(f_pm); + Delete(f_pm); + Delete(base); + + /* Close all of the files */ + Dump(f_header,f_runtime); + Dump(f_wrappers,f_runtime); + Wrapper_pretty_print(f_init,f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + Delete(f_runtime); + 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],target[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", NIL); + Printv(f->def, "char _swigmsg[SWIG_MAX_ERRMSG] = \"\";\n", NIL); + Printv(f->def, "const char *_swigerr = _swigmsg;\n","{\n",NIL); + + emit_args(d, 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"); + String *ln = Getattr(p,"lname"); + + /* Produce string representation of source and target arguments */ + sprintf(source,"ST(%d)",i); + sprintf(target,"%s", Char(ln)); + + 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 */ + 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"))) { + Replaceall(tm,"$source",Getattr(p,"lname")); + Replaceall(tm,"$target","ST(argvi)"); + Replaceall(tm,"$result","ST(argvi)"); + 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 */ + + emit_action(n,f); + + if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) { + Replaceall(tm,"$source","result"); + Replaceall(tm,"$target","ST(argvi)"); + Replaceall(tm,"$result", "ST(argvi)"); + 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 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 (Getattr(n,"feature:new")) { + if ((tm = Swig_typemap_lookup_new("newfree",n,"result",0))) { + Replaceall(tm,"$source","result"); + Printf(f->code,"%s\n",tm); + } + } + + if ((tm = Swig_typemap_lookup_new("ret",n,"result", 0))) { + Replaceall(tm,"$source","result"); + Printf(f->code,"%s\n", tm); + } + + Printf(f->code," XSRETURN(argvi);\n"); + Printf(f->code,"fail:\n"); + Printv(f->code,cleanup,NIL); + Printv(f->code,"(void) _swigerr;\n", NIL); + Printv(f->code,"}\n",NIL); + Printv(f->code,"croak(_swigerr);\n", NIL); + Printv(f->code,"}\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, ii; + String *dispatch = Swig_overload_dispatch(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"); + Replaceid(dispatch,"argc","items"); + for (ii = 0; ii < maxargs; ii++) { + char pat[128]; + char rep[128]; + sprintf(pat,"argv[%d]",ii); + sprintf(rep,"ST(%d)",ii); + Replaceall(dispatch,pat,rep); + } + 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)) { + int need_stub = 0; + String *func = NewString(""); + + /* We'll make a stub since we may need it anyways */ + + Printv(func, "sub ", iname, " {\n", + tab4, "my @args = @_;\n", + NIL); + + Printv(func, tab4, "my $result = ", cmodule, "::", iname, "(@args);\n", NIL); + + /* Now check to see what kind of return result was found. + * If this function is returning a result by 'value', SWIG did an + * implicit malloc/new. We'll mark the object like it was created + * in Perl so we can garbage collect it. */ + + if (is_shadow(d)) { + Printv(func, tab4, "return undef if (!defined($result));\n", NIL); + + /* If we're returning an object by value, put it's reference + into our local hash table */ + + if ((!SwigType_ispointer(d) && !SwigType_isreference(d)) || Getattr(n,"feature:new")) { + Printv(func, tab4, "$", is_shadow(d), "::OWNER{$result} = 1;\n", NIL); + } + + /* We're returning a Perl "object" of some kind. Turn it into a tied hash */ + Printv(func, + tab4, "my %resulthash;\n", + tab4, "tie %resulthash, ref($result), $result;\n", + tab4, "return bless \\%resulthash, ref($result);\n", + "}\n", + NIL); + + need_stub = 1; + } else { + /* Hmmm. This doesn't appear to be anything I know about */ + Printv(func, tab4, "return $result;\n", "}\n", NIL); + } + + /* Now check if we needed the stub. If so, emit it, otherwise + * Emit code to hack Perl's symbol table instead */ + + if (need_stub) { + Printf(func_stubs,"%s",func); + } else { + Printv(func_stubs,"*", iname, " = *", cmodule, "::", iname, ";\n", NIL); + } + Delete(func); + } + } + 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 *set_name = NewStringf("_wrap_set_%s", iname); + String *val_name = NewStringf("_wrap_val_%s", iname); + + if (!addSymbol(iname,n)) return SWIG_ERROR; + + getf = NewWrapper(); + setf = NewWrapper(); + + /* Create a Perl function for setting the variable value */ + + if (!Getattr(n,"feature:immutable")) { + Printf(setf->def,"SWIGCLASS_STATIC int %s(pTHX_ SV* sv, MAGIC *mg) {\n", set_name); + Printv(setf->code, + tab4, "MAGIC_PPERL\n", + tab4, "mg = mg;\n", + NIL); + + /* Check for a few typemaps */ + tm = Swig_typemap_lookup_new("varin",n,name,0); + if (tm) { + Replaceall(tm,"$source","sv"); + Replaceall(tm,"$target",name); + Replaceall(tm,"$input","sv"); + Printf(setf->code,"%s\n", tm); + } else { + Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, + "Unable to link with datatype %s (ignored).\n", SwigType_str(t,0)); + return SWIG_NOWRAP; + } + Printf(setf->code," return 1;\n}\n"); + Replaceall(setf->code,"$symname",iname); + Wrapper_print(setf,magic); + } + + /* Now write a function to evaluate the variable */ + + Printf(getf->def,"SWIGCLASS_STATIC int %s(pTHX_ SV *sv, MAGIC *mg) {\n", val_name); + Printv(getf->code, + tab4, "MAGIC_PPERL\n", + tab4, "mg = mg;\n", + NIL); + + if ((tm = Swig_typemap_lookup_new("varout",n,name,0))) { + Replaceall(tm,"$target","sv"); + Replaceall(tm,"$result","sv"); + Replaceall(tm,"$source",name); + Printf(getf->code,"%s\n", tm); + } else { + Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, + "Unable to link with datatype %s (ignored).\n", SwigType_str(t,0)); + return SWIG_NOWRAP; + } + Printf(getf->code," return 1;\n}\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 (Getattr(n,"feature:immutable")) { + Printv(variable_tab, tab4, "{ \"", cmodule, "::", iname, "\", MAGIC_CLASS swig_magic_readonly, MAGIC_CLASS ", val_name,",", tt, " },\n",NIL); + + } else { + Printv(variable_tab, tab4, "{ \"", cmodule, "::", iname, "\", MAGIC_CLASS ", set_name, ", MAGIC_CLASS ", val_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(set_name); + Delete(val_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 *value = 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_new("consttab",n,name,0))) { + Replaceall(tm,"$source",value); + Replaceall(tm,"$target",name); + Replaceall(tm,"$value",value); + Printf(constant_tab,"%s,\n", tm); + } else if ((tm = Swig_typemap_lookup_new("constcode", n, name, 0))) { + Replaceall(tm,"$source", value); + Replaceall(tm,"$target", name); + Replaceall(tm,"$value",value); + 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 (!Getattr(p,"ignore")) { + /* 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 (!Getattr(p,"ignore")) + Putc(',',temp); + } else { + p = nextSibling(p); + if (p) + if ((i>0) && (!Getattr(p,"ignore"))) + 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 */ + actualpackage = Getattr(clsmodule,"name"); + if ((!compat) && (!Strchr(symname,':'))) { + fullname = NewStringf("%s::%s",actualpackage,symname); + } else { + fullname = NewString(symname); + } + Setattr(n,"perl5:proxy", fullname); + } + + /* ------------------------------------------------------------ + * classDeclaration() + * ------------------------------------------------------------ */ + virtual int classDeclaration(Node *n) { + /* Do some work on the class name */ + 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",fullmodule,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"); + DOH *key; + for (key = Firstkey(operators); key; key = Nextkey(operators)) { + char *name = Char(key); + // fprintf(stderr,"found name: <%s>\n", name); + if (strstr(name, "operator_equal_to")) { + Printv(pm, tab4, "\"==\" => sub { $_[0]->operator_equal_to($_[1])},\n",NIL); + } else if (strstr(name, "operator_not_equal_to")) { + Printv(pm, tab4, "\"!=\" => sub { $_[0]->operator_not_equal_to($_[1])},\n",NIL); + } else if (strstr(name, "operator_assignment")) { + Printv(pm, tab4, "\"=\" => sub { $_[0]->operator_assignment($_[1])},\n",NIL); + } else { + fprintf(stderr,"Unknown operator: %s\n", name); + } + } + Printv(pm, tab4, "\"fallback\" => 1;\n",NIL); + } + /* If we are inheriting from a base class, set that up */ + + Printv(pm, "@ISA = qw( ",fullmodule, NIL); + + /* Handle inheritance */ + List *baselist = Getattr(n,"bases"); + if (baselist && Len(baselist)) { + Node *base = Firstitem(baselist); + while (base) { + String *bname = Getattr(base, "perl5:proxy"); + if (!bname) { + base = Nextitem(baselist); + continue; + } + Printv(pm," ", bname, NIL); + base = Nextitem(baselist); + } + } + Printf(pm, " );\n"); + + /* Dump out a hash table containing the pointers that we own */ + Printf(pm, "%%OWNER = ();\n"); + if (have_data_members) { + Printv(pm, + "%BLESSEDMEMBERS = (\n", blessedmembers, ");\n\n", + NIL); + } + 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", + tab4, "};\n\n", + "sub ACQUIRE {\n", + tab4, "my $self = shift;\n", + tab4, "my $ptr = tied(%$self);\n", + tab4, "$OWNER{$ptr} = 1;\n", + tab4, "};\n\n", + NIL); + + /* Only output the following methods if a class has member data */ + + if (have_data_members) { + + /* Output a FETCH method. This is actually common to all classes */ + Printv(pm, + "sub FETCH {\n", + tab4, "my ($self,$field) = @_;\n", + tab4, "my $member_func = \"swig_${field}_get\";\n", + tab4, "my $val = $self->$member_func();\n", + tab4, "if (exists $BLESSEDMEMBERS{$field}) {\n", + tab8, "return undef if (!defined($val));\n", + tab8, "my %retval;\n", + tab8, "tie %retval,$BLESSEDMEMBERS{$field},$val;\n", + tab8, "return bless \\%retval, $BLESSEDMEMBERS{$field};\n", + tab4, "}\n", + tab4, "return $val;\n", + "}\n\n", + NIL); + + /* Output a STORE method. This is also common to all classes (might move to base class) */ + + Printv(pm, + "sub STORE {\n", + tab4, "my ($self,$field,$newval) = @_;\n", + tab4, "my $member_func = \"swig_${field}_set\";\n", + tab4, "if (exists $BLESSEDMEMBERS{$field}) {\n", + tab8, "$self->$member_func(tied(%{$newval}));\n", + tab4, "} else {\n", + tab8, "$self->$member_func($newval);\n", + tab4, "}\n", + "}\n\n", + NIL); + } + Delete(operators); operators = 0; + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * memberfunctionHandler() + * ------------------------------------------------------------ */ + + virtual int memberfunctionHandler(Node *n) { + String *symname = Getattr(n,"sym:name"); + SwigType *t = Getattr(n,"type"); + + String *func; + int need_wrapper = 0; + + member_func = 1; + Language::memberfunctionHandler(n); + member_func = 0; + + if ((blessed) && (!Getattr(n,"sym:nextSibling"))) { + func = NewString(""); + + /* Now emit a Perl wrapper function around our member function, we might need + to patch up some arguments along the way */ + + if (Strstr(symname, "operator") == symname) { + if (Strstr(symname, "operator_equal_to")) { + DohSetInt(operators,"operator_equal_to",1); + have_operators = 1; + } else if (Strstr(symname, "operator_not_equal_to")) { + DohSetInt(operators,"operator_not_equal_to",1); + have_operators = 1; + } else if (Strstr(symname, "operator_assignment")) { + DohSetInt(operators,"operator_assignment",1); + have_operators = 1; + } else { + Printf(stderr,"Unknown operator: %s\n", symname); + } + // fprintf(stderr,"Found member_func operator: %s\n", symname); + } + + Printv(func, + "sub ", symname, " {\n", + tab4, "my @args = @_;\n", + NIL); + + /* Okay. We've made argument adjustments, now call into the package */ + + Printv(func, + tab4, "my $result = ", cmodule, "::", Swig_name_member(class_name,symname), + "(@args);\n", + NIL); + + /* Now check to see what kind of return result was found. + * If this function is returning a result by 'value', SWIG did an + * implicit malloc/new. We'll mark the object like it was created + * in Perl so we can garbage collect it. */ + + if (is_shadow(t)) { + Printv(func,tab4, "return undef if (!defined($result));\n", NIL); + + /* If we're returning an object by value, put it's reference + into our local hash table */ + + if ((!SwigType_ispointer(t) && !SwigType_isreference(t)) || Getattr(n,"feature:new")) { + Printv(func, tab4, "$", is_shadow(t), "::OWNER{$result} = 1; \n", NIL); + } + + /* We're returning a Perl "object" of some kind. Turn it into + a tied hash */ + + Printv(func, + tab4, "my %resulthash;\n", + tab4, "tie %resulthash, ref($result), $result;\n", + tab4, "return bless \\%resulthash, ref($result);\n", + "}\n", + NIL); + + need_wrapper = 1; + } else { + + /* Hmmm. This doesn't appear to be anything I know about so just + return it unmodified */ + + Printv(func, tab4,"return $result;\n", "}\n", NIL); + } + + if (need_wrapper) { + Printv(pcode,func,NIL); + } else { + Printv(pcode,"*",symname," = *", cmodule, "::", Swig_name_member(class_name,symname), ";\n", NIL); + } + Delete(func); + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * membervariableHandler() + * + * Adds an instance member. This is a little hairy because data members are + * really added with a tied-hash table that is attached to the object. + * + * On the low level, we will emit a pair of get/set functions to retrieve + * values just like before. These will then be encapsulated in a FETCH/STORE + * method associated with the tied-hash. + * + * In the event that a member is an object that we have already wrapped, then + * we need to retrieve the data a tied-hash as opposed to what SWIG normally + * returns. To determine this, we build an internal hash called 'BLESSEDMEMBERS' + * that contains the names and types of tied data members. If a member name + * is in the list, we tie it, otherwise, we just return the normal SWIG value. + * ----------------------------------------------------------------------------- */ + + 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 ((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 @args = @_;\n", NIL); + + Printv(pcode, + tab4, "my $self = ", cmodule, "::", Swig_name_construct(symname), "(@args);\n", + tab4, "return undef if (!defined($self));\n", + /* tab4, "bless $self, \"", fullclassname, "\";\n", */ + tab4, "$OWNER{$self} = 1;\n", + tab4, "my %retval;\n", + tab4, "tie %retval, \"", fullclassname, "\", $self;\n", + tab4, "return bless \\%retval, $pkg;\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) { + 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"); + SwigType *t = Getattr(n,"type"); + if (is_shadow(t)) { + Printv(pcode, + "sub ", symname, " {\n", + tab4, "my @args = @_;\n", + NIL); + + /* Okay. We've made argument adjustments, now call into the package */ + + Printv(pcode, + tab4, "my $result = ", cmodule, "::", Swig_name_member(class_name,symname), + "(@args);\n", + NIL); + + /* Now check to see what kind of return result was found. + * If this function is returning a result by 'value', SWIG did an + * implicit malloc/new. We'll mark the object like it was created + * in Perl so we can garbage collect it. */ + + Printv(pcode,tab4, "return undef if (!defined($result));\n", NIL); + + /* If we're returning an object by value, put it's reference + into our local hash table */ + + if ((!SwigType_ispointer(t) && !SwigType_isreference(t)) || Getattr(n,"feature:new")) { + Printv(pcode, tab4, "$", is_shadow(t), "::OWNER{$result} = 1; \n", NIL); + } + + /* We're returning a Perl "object" of some kind. Turn it into + a tied hash */ + + Printv(pcode, + tab4, "my %resulthash;\n", + tab4, "tie %resulthash, ref($result), $result;\n", + tab4, "return bless \\%resulthash, ref($result);\n", + "}\n", + NIL); + } else { + 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_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); + } + } + } + } else { + Printf(stderr,"%s : Line %d. Unrecognized pragma.\n", input_file,line_number); + } + } + } + return Language::pragmaDirective(n); + } +}; + +/* ----------------------------------------------------------------------------- + * swig_perl5() - Instantiate module + * ----------------------------------------------------------------------------- */ + +extern "C" Language * +swig_perl5(void) { + return new PERL5(); +} diff --git a/Source/Modules/php4.cxx b/Source/Modules/php4.cxx new file mode 100644 index 000000000..051e24601 --- /dev/null +++ b/Source/Modules/php4.cxx @@ -0,0 +1,2113 @@ +/* + * PHP4 Support + * + * Richard Palmer + * richard@magicality.org + * Nov 2001 + * + * Portions copyright Sun Microsystems (c) 2001 + * Tim Hockin + * + * Portions copyright Ananova Ltd (c) 2002 + * Sam Liddicott + * + */ + +char cvsroot_php4_cxx[] = "$Header$"; + +#include + +#include "swigmod.h" +#include "swigconfig.h" + +static const char *usage = (char*)"\ +PHP4 Options (available with -php4)\n\ + -cppext - cpp file extension (default to .cpp)\n\ + -proxy - Create proxy classes.\n\ + -dlname name - Set module prefix.\n\ + -make - Create simple makefile.\n\ + -phpfull - Create full make files.\n\ + -withincs libs - With -phpfull writes needed incs in config.m4\n\ + -withlibs libs - With -phpfull writes needed libs in config.m4\n\n\ + -withc libs - With -phpfull makes extra c files in Makefile.in\n\ + -withcxx libs - With -phpfull makes extra c++ files in Makefile.in\n\n"; + +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 *dlname = 0; +static String *withlibs = 0; +static String *withincs = 0; +static String *withc = 0; +static String *withcxx = 0; +static String *outfile = 0; + +//static char *package = 0; // Name of the package +static char *shadow_classname; + +static Wrapper *f_php; +static int gen_extra = 0; +static int gen_make = 0; + +static File *f_runtime = 0; +static File *f_h = 0; +static File *f_phpcode = 0; +static String *phpfilename =0; + +static String *s_header; +static String *s_wrappers; +static String *s_init; +static String *s_vinit; +static String *s_vdecl; +static String *s_cinit; +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; + +/* Variables for using PHP classes */ +static String *class_name = 0; +static String *realpackage = 0; +static String *package = 0; + +static Hash *shadow_get_vars; +static Hash *shadow_set_vars; +static String *shadow_classdef; +static String *shadow_code; +static int have_default_constructor = 0; +#define NATIVE_CONSTRUCTOR 1 +#define ALTERNATIVE_CONSTRUCTOR 2 +static int native_constructor=0; +static int destructor=0; +static int enum_flag = 0; // Set to 1 when wrapping an enum +static int static_flag = 0; // Set to 1 when wrapping a static functions or member variables +static int const_flag = 0; // Set to 1 when wrapping a const member variables +static int variable_wrapper_flag = 0; // Set to 1 when wrapping a member variable/enum/const +static int wrapping_member = 0; +static Hash *zend_types = 0; + +static String *shadow_enum_code = 0; +static String *php_enum_code = 0; +static String *all_shadow_extra_code = 0; + //Extra code for all shadow classes from %pragma +static String *this_shadow_extra_code = 0; + //Extra Code for current single shadow class freom %pragma +static String *all_shadow_import = 0; + //import for all shadow classes from %pragma +static String *this_shadow_import = 0; + //import for current shadow classes from %pragma +static String *module_baseclass = 0; + //inheritance for module class from %pragma +static String *all_shadow_baseclass = 0; + //inheritence for all shadow classes from %pragma +static String *this_shadow_baseclass = 0; + //inheritance for shadow class from %pragma and cpp_inherit +static String *this_shadow_multinherit = 0; +static int shadow = 1; + + +extern "C" { +static void (*r_prevtracefunc)(SwigType *t, String *mangled, String *clientdata) = 0; +} + +static const char *php_header = +"/*" +"\n +----------------------------------------------------------------------+" +"\n | PHP version 4.0 |" +"\n +----------------------------------------------------------------------+" +"\n | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group |" +"\n +----------------------------------------------------------------------+" +"\n | This source file is subject to version 2.02 of the PHP license, |" +"\n | that is bundled with this package in the file LICENSE, and is |" +"\n | available at through the world-wide-web at |" +"\n | http://www.php.net/license/2_02.txt. |" +"\n | If you did not receive a copy of the PHP license and are unable to |" +"\n | obtain it through the world-wide-web, please send a note to |" +"\n | license@php.net so we can mail you a copy immediately. |" +"\n +----------------------------------------------------------------------+" +"\n | Authors: |" +"\n | |" +"\n +----------------------------------------------------------------------+" +"\n */\n"; + +void +SwigPHP_emit_resource_registrations() { + DOH *key; + String *destructor=0; + String *classname=0; + String *shadow_classname=0; + + if (!zend_types) return; + key = Firstkey(zend_types); + + if (key) Printf(s_oinit,"\n/* Register resource destructors for pointer types */\n"); + while (key) if (1 /* is pointer type*/) { + Node *class_node; + if ((class_node=Getattr(zend_types,key))) { + // Write out destructor function header + Printf(s_wrappers,"/* NEW Destructor style */\nstatic ZEND_RSRC_DTOR_FUNC(_wrap_destroy%s) {\n",key); + + // write out body + if ((class_node!=NOTCLASS)) { + classname = Getattr(class_node,"name"); + if (! (shadow_classname = Getattr(class_node,"sym:name"))) shadow_classname=classname; + // Do we have a known destructor for this type? + if ((destructor = Getattr(class_node,"destructor"))) { + Printf(s_wrappers,"/* has destructor: %s */\n",destructor); + Printf(s_wrappers,"%s(rsrc, SWIGTYPE%s->name TSRMLS_CC);\n",destructor,key); + } else { + Printf(s_wrappers,"/* bah! No destructor for this wrapped class!! */\n"); + } + } else { + Printf(s_wrappers,"/* bah! No destructor for this simple type!! */\n"); + } + + // close function + Printf(s_wrappers,"}\n"); + + // declare le_swig_ to store php registration + Printf(s_vdecl,"static int le_swig_%s=0; /* handle for %s */\n", key, shadow_classname); + + // 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); + } + key = Nextkey(zend_types); + } +} + +class PHP4 : public Language { +public: + + /* Test to see if a type corresponds to something wrapped with a shadow class. */ + + String *is_shadow(SwigType *t) { + String *r = 0; + Node *n = classLookup(t); + if (n) { + 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 + } + } + return r; + } + + /* ----------------------------------------------------------------------------- + * get_pointer() + * ----------------------------------------------------------------------------- */ + void + get_pointer(char *iname, char *srcname, char *src, char *dest, + SwigType *t, String *f, char *ret) { + + SwigType_remember(t); + SwigType *lt = SwigType_ltype(t); + Printv(f, "if (SWIG_ConvertPtr(", src, ",(void **) ", dest, ",", NIL); + + /* If we're passing a void pointer, we give the pointer conversion a NULL + pointer, otherwise pass in the expected type. */ + + if (Cmp(lt,"p.void") == 0) { + Printf(f, " 0 ) < 0) {\n"); + } else { + Printv(f, "SWIGTYPE", SwigType_manglestr(t), ") < 0) {\n",NIL); + } + + Printv(f, + "zend_error(E_ERROR, \"Type error in ", srcname, " of ", iname, + " Expected %s\", SWIGTYPE", SwigType_manglestr(t), "->name);\n", ret, + ";\n", + "}\n", + NIL); + Delete(lt); + } + + /* ------------------------------------------------------------ + * main() + * ------------------------------------------------------------ */ + + virtual void main(int argc, char *argv[]) { + int i; + SWIG_library_directory("php4"); + SWIG_config_cppext("cpp"); + + for(i = 1; i < argc; i++) { + if (argv[i]) { + if(strcmp(argv[i], "-phpfull") == 0) { + gen_extra = 1; + Swig_mark_arg(i); + } else if(strcmp(argv[i], "-dlname") == 0) { + if (argv[i+1]) { + dlname = NewString(argv[i+1]); + Swig_mark_arg(i); + Swig_mark_arg(i+1); + i++; + } else { + Swig_arg_error(); + } + } else if(strcmp(argv[i], "-withlibs") == 0) { + if (argv[i+1]) { + withlibs = NewString(argv[i+1]); + Swig_mark_arg(i); + Swig_mark_arg(i+1); + i++; + } else { + Swig_arg_error(); + } + } else if(strcmp(argv[i], "-withincs") == 0) { + if (argv[i+1]) { + withincs = NewString(argv[i+1]); + Swig_mark_arg(i); + Swig_mark_arg(i+1); + i++; + } else { + Swig_arg_error(); + } + } else if(strcmp(argv[i], "-withc") == 0) { + if (argv[i+1]) { + withc = NewString(argv[i+1]); + Swig_mark_arg(i); + Swig_mark_arg(i+1); + i++; + } else { + Swig_arg_error(); + } + } else if(strcmp(argv[i], "-withcxx") == 0) { + if (argv[i+1]) { + withcxx = 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], "-make") == 0) { + gen_make = 1; + Swig_mark_arg(i); + } else if(strcmp(argv[i], "-help") == 0) { + fputs(usage, stderr); + } + } + } + + Preprocessor_define((void *) "SWIGPHP 1", 0); + Preprocessor_define((void *) "SWIGPHP4 1", 0); + Preprocessor_define ("SWIG_NO_OVERLOAD 1", 0); + SWIG_typemap_lang("php4"); + /* DB: Suggest using a language configuration file */ + SWIG_config_file("php4.swg"); + } + + void create_simple_make(void) { + File *f_make; + + f_make = NewFile((void *)"makefile", "w"); + if(CPlusPlus) + Printf(f_make, "CC=g++\n"); + else + Printf(f_make, "CC=gcc\n"); + + Printf(f_make, + "OBJS=%s_wrap.o\n" + "PROG=lib%s.so\n" + "CFLAGS=-fpic\n" + "LDFLAGS=-shared\n" + "PHP_INC=`php-config --includes`\n" + "EXTRA_INC=\n" + "EXTRA_LIB=\n\n", + module, module); + + Printf(f_make, + "$(PROG): $(OBJS)\n" + "\t$(CC) $(LDFLAGS) $(OBJS) -o $(PROG) $(EXTRA_LIB)\n\n" + "%%.o: %%.%s\n" + "\t$(CC) $(EXTRA_INC) $(PHP_INC) $(CFLAGS) -c $<\n", + (CPlusPlus?"cpp":"c")); + + Close(f_make); + } + + void create_extra_files(void) { + File *f_extra; + + static String *configm4=0; + static String *makefilein=0; + static String *credits=0; + + configm4=NewString(""); + Printv(configm4, Swig_file_dirname(outfile), "config.m4", NIL); + + makefilein=NewString(""); + Printv(makefilein, Swig_file_dirname(outfile), "Makefile.in", NIL); + + credits=NewString(""); + Printv(credits, Swig_file_dirname(outfile), "CREDITS", NIL); + + // are we a --with- or --enable- + int with=(withincs || withlibs)?1:0; + + // Note makefile.in only copes with one source file + // also withincs and withlibs only take one name each now + // the code they generate should be adapted to take multiple lines + + if(gen_extra) { + /* Write out Makefile.in */ + f_extra = NewFile(makefilein, "w"); + if (!f_extra) { + Printf(stderr,"Unable to open %s\n",makefilein); + SWIG_exit(EXIT_FAILURE); + } + + Printf(f_extra, + "# $Id$\n\n" + "LTLIBRARY_NAME = php_%s.la\n", + module); + + // CPP has more and different entires to C in Makefile.in + if (! CPlusPlus) Printf(f_extra,"LTLIBRARY_SOURCES = %s %s\n" + "LTLIBRARY_SOURCES_CPP = %s\n",Swig_file_filename(outfile),withc,withcxx); + else Printf(f_extra,"LTLIBRARY_SOURCES = %s\n" + "LTLIBRARY_SOURCES_CPP = %s %s\n" + "LTLIBRARY_OBJECTS_X = $(LTLIBRARY_SOURCES_CPP:.cpp=.lo) $(LTLIBRARY_SOURCES_CPP:.cxx=.lo)\n" + ,withc,Swig_file_filename(outfile),withcxx); + + Printf(f_extra,"LTLIBRARY_SHARED_NAME = php_%s.la\n" + "LTLIBRARY_SHARED_LIBADD = $(%(upper)s_SHARED_LIBADD)\n\n" + "include $(top_srcdir)/build/dynlib.mk\n", + module,module); + + Printf(f_extra,"\n# patch in .cxx support to php build system to work like .cpp\n" + ".SUFFIXES: .cxx\n\n" + ".cxx.o:\n" + " $(CXX_COMPILE) -c $<\n\n" + ".cxx.lo:\n" + " $(CXX_PHP_COMPILE)\n\n" + ".cxx.slo:\n" + " $(CXX_SHARED_COMPILE)\n\n"); + + Printf(f_extra,"\n# make it easy to test module\n" + "testmodule:\n" + " php -q -d extension_dir=modules %s\n\n",Swig_file_filename(phpfilename)); + Close(f_extra); + + /* Now config.m4 */ + // Note: # comments are OK in config.m4 if you don't mind them + // appearing in the final ./configure file + // (which can help with ./configure debugging) + + // NOTE2: phpize really ought to be able to write out a sample + // config.m4 based on some simple data, I'll take this up with + // the php folk! + f_extra = NewFile(configm4, "w"); + if (!f_extra) { + Printf(stderr, "Unable to open %s\n",configm4); + SWIG_exit(EXIT_FAILURE); + } + + Printf(f_extra, + "dnl $Id$\n" + "dnl ***********************************************************************\n" + "dnl ** THIS config.m4 is provided for PHPIZE and PHP's consumption NOT\n" + "dnl ** for any part of the rest of the %s build system\n" + "dnl ***********************************************************************\n\n" + ,module); + + if (! with) { // must be enable then + Printf(f_extra, + "PHP_ARG_ENABLE(%s, whether to enable %s support,\n" + "[ --enable-%s Enable %s support])\n\n", + module,module,module,module); + } else { + Printf(f_extra, + "PHP_ARG_WITH(%s, for %s support,\n" + "[ --with-%s[=DIR] Include %s support.])\n\n", + module,module,module,module); + // These tests try and file the library we need + Printf(f_extra,"dnl THESE TESTS try and find the library and header files\n" + "dnl your new php module needs. YOU MAY NEED TO EDIT THEM\n" + "dnl as written they assume your header files are all in the same place\n\n"); + + Printf(f_extra,"dnl ** are we looking for %s_lib.h or something else?\n",module); + if (withincs) Printf(f_extra,"HNAMES=\"%s\"\n\n",withincs); + else Printf(f_extra,"HNAMES=\"\"; # %s_lib.h ?\n\n",module); + + Printf(f_extra,"dnl ** Are we looking for lib%s.a or lib%s.so or something else?\n",module,module); + if (withlibs) Printf(f_extra,"LIBNAMES=\"%s\"\n\n",withlibs); + else Printf(f_extra,"LIBNAMES=\"\"; # lib_%s.so ?\n\n",withlibs); + Printf(f_extra,"dnl IF YOU KNOW one of the symbols in the library and you\n" + "dnl specify it below then we can have a link test to see if it works\n" + "LIBSYMBOL=\"\"\n\n"); + } + + // Now write out tests to find thing.. they may need to extend tests + Printf(f_extra,"if test \"$PHP_%(upper)s\" != \"no\"; then\n\n",module); + + // Ready for when we add libraries as we find them + Printf(f_extra," PHP_SUBST(%(upper)s_SHARED_LIBADD)\n\n",module); + + if (withlibs) { // find more than one library + Printf(f_extra," for LIBNAME in $LIBNAMES ; do\n"); + Printf(f_extra," LIBDIR=\"\"\n"); + // For each path element to try... + Printf(f_extra," for i in $PHP_%(upper)s $PHP_%(upper)s/lib /usr/lib /usr/local/lib ; do\n",module,module); + Printf(f_extra," if test -r $i/lib$LIBNAME.a -o -r $i/lib$LIBNAME.so ; then\n" + " LIBDIR=\"$i\"\n" + " break\n" + " fi\n" + " done\n\n"); + Printf(f_extra," dnl ** and $LIBDIR should be the library path\n" + " if test \"$LIBNAME\" != \"\" -a -z \"$LIBDIR\" ; then\n" + " AC_MSG_RESULT(Library files $LIBNAME not found)\n" + " AC_MSG_ERROR(Is the %s distribution installed properly?)\n" + " else\n" + " AC_MSG_RESULT(Library files $LIBNAME found in $LIBDIR)\n" + " PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $LIBDIR, %(upper)s_SHARED_LIBADD)\n" + " fi\n",module,module); + Printf(f_extra," done\n\n"); + } + + if (withincs) { // Find more than once include + Printf(f_extra," for HNAME in $HNAMES ; do\n"); + Printf(f_extra," INCDIR=\"\"\n"); + // For each path element to try... + Printf(f_extra," for i in $PHP_%(upper)s $PHP_%(upper)s/include $PHP_%(upper)s/includes $PHP_%(upper)s/inc $PHP_%(upper)s/incs /usr/local/include /usr/include; do\n",module,module,module,module,module); + // Try and find header files + Printf(f_extra," if test \"$HNAME\" != \"\" -a -r $i/$HNAME ; then\n" + " INCDIR=\"$i\"\n" + " break\n" + " fi\n" + " done\n\n"); + + Printf(f_extra, + " dnl ** Now $INCDIR should be the include file path\n" + " if test \"$HNAME\" != \"\" -a -z \"$INCDIR\" ; then\n" + " AC_MSG_RESULT(Include files $HNAME not found)\n" + " AC_MSG_ERROR(Is the %s distribution installed properly?)\n" + " else\n" + " AC_MSG_RESULT(Include files $HNAME found in $INCDIR)\n" + " PHP_ADD_INCLUDE($INCDIR)\n" + " fi\n\n",module); + Printf(f_extra," done\n\n"); + } + + if (CPlusPlus) Printf(f_extra, + " # As this is a C++ module..\n" + " PHP_REQUIRE_CXX\n" + " AC_CHECK_LIB(stdc++, cin)\n"); + + if (with) { + Printf(f_extra," if test \"$LIBSYMBOL\" != \"\" ; then\n" + " old_LIBS=\"$LIBS\"\n" + " LIBS=\"$LIBS -L$TEST_DIR/lib -lm -ldl\"\n" + " AC_CHECK_LIB($LIBNAME, $LIBSYMBOL, [AC_DEFINE(HAVE_TESTLIB,1, [ ])],\n" + " [AC_MSG_ERROR(wrong test lib version or lib not found)])\n" + " LIBS=\"$old_LIBS\"\n" + " fi\n\n"); + } + + Printf(f_extra," AC_DEFINE(HAVE_%(upper)s, 1, [ ])\n",module); + Printf(f_extra,"dnl AC_DEFINE_UNQUOTED(PHP_%(upper)s_DIR, \"$%(upper)s_DIR\", [ ])\n",module,module); + Printf(f_extra," PHP_EXTENSION(%s, $ext_shared)\n",module); + + // and thats all! + Printf(f_extra,"fi\n"); + + Close(f_extra); + + /* CREDITS */ + f_extra = NewFile(credits, "w"); + if (!f_extra) { + Printf(stderr,"Unable to open %s\n",credits); + SWIG_exit(EXIT_FAILURE); + } + Printf(f_extra, "%s\n", module); + Close(f_extra); + } + } + + /* ------------------------------------------------------------ + * top() + * ------------------------------------------------------------ */ + + virtual int top(Node *n) { + + String *filen; + String *s_type; + + /* Initialize all of the output files */ + outfile = Getattr(n,"outfile"); + + /* main output file */ + f_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + + Swig_banner(f_runtime); + + /* sections of the output file */ + s_init = NewString("/* init section */\n"); + s_header = NewString("/* header section */\n"); + s_wrappers = NewString("/* wrapper section */\n"); + s_type = NewString(""); + /* 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 = NewString(""); + + /* Register file targets with the SWIG file handler */ + Swig_register_filebyname("runtime",f_runtime); + Swig_register_filebyname("init",s_init); + Swig_register_filebyname("header",s_header); + Swig_register_filebyname("wrapper",s_wrappers); + + shadow_classdef = NewString(""); + shadow_code = NewString(""); + php_enum_code = NewString(""); + module_baseclass = NewString(""); + all_shadow_extra_code = NewString(""); + all_shadow_import = NewString(""); + all_shadow_baseclass = NewString(""); + + /* Set the module name */ + module = Copy(Getattr(n,"name")); + cap_module = NewStringf("%(upper)s",module); + + if(shadow) { + realpackage = module; + package = NewStringf("%sc", module); + } + + /* Set the dlname */ + if (!dlname) { +#if defined(_WIN32) || defined(__WIN32__) + dlname = NewStringf("%s.dll", module); +#else + dlname = NewStringf("%s.so", module); +#endif + } + + /* PHP module file */ + filen = NewString(""); + Printv(filen, Swig_file_dirname(outfile), module, ".php", NIL); + phpfilename = NewString(filen); + + f_phpcode = NewFile(filen, "w"); + if (!f_phpcode) { + Printf(stderr, "*** Can't open '%s'\n", filen); + SWIG_exit(EXIT_FAILURE); + } + + Printf(f_phpcode, "v)\n" + "#define %s_FETCH() zend_%s_globals *%s_globals " + "= ts_resource(%s_globals_id)\n" + "#else\n" + "#define %s_D\n" + "#define %s_DC\n" + "#define %s_C\n" + "#define %s_CC\n" + "#define %s_SG(v) (%s_globals.v)\n" + "#define %s_FETCH()\n" + "#endif\n\n" + "#endif /* PHP_%s_H */\n", + cap_module, module, module, cap_module, cap_module, cap_module, module, + cap_module, cap_module, cap_module, module, cap_module, module, module, + module, cap_module, cap_module, cap_module, cap_module, cap_module, module, + cap_module, cap_module); + + Close(f_h); + + Printf(s_header, "%s\n\n",all_cs_entry); + Printf(s_header, + "%s" + " {NULL, NULL, NULL}\n};\n\n" + "zend_module_entry %s_module_entry = {\n" + "#if ZEND_MODULE_API_NO > 20010900\n" + " STANDARD_MODULE_HEADER,\n" + "#endif\n" + " \"%s\",\n" + " %s_functions,\n" + " PHP_MINIT(%s),\n" + " PHP_MSHUTDOWN(%s),\n" + " PHP_RINIT(%s),\n" + " PHP_RSHUTDOWN(%s),\n" + " PHP_MINFO(%s),\n" + "#if ZEND_MODULE_API_NO > 20010900\n" + " NO_VERSION_YET,\n" + "#endif\n" + " STANDARD_MODULE_PROPERTIES\n" + "};\nzend_module_entry* SWIG_module_entry = &%s_module_entry;\n\n", + s_entry, module, module, module, module, module, module, module,module,module); + + String *type_table = NewString(""); + 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. + */ + + Printv(f_runtime, s_header, NIL); + + // Wrapper_print(f_c, s_wrappers); + Wrapper_print(f_php, s_wrappers); + + Printf(s_header, "/* end header section */\n"); + Printf(s_wrappers, "/* end wrapper section */\n"); + Printf(s_vdecl, "/* end vdecl subsection */\n"); + + Printv(f_runtime, s_vdecl, s_wrappers, s_init, NIL); + Delete(s_header); + Delete(s_wrappers); + Delete(s_init); + Delete(s_vdecl); + Close(f_runtime); + Printf(f_phpcode, "%s\n%s\n?>\n", pragma_incl, pragma_code); + Close(f_phpcode); + + create_extra_files(); + + if(!gen_extra && gen_make) + create_simple_make(); + + return SWIG_OK; + } + +/* Just need to append function names to function table to register with + PHP +*/ + + void create_command(char *cname, char *iname) { +// char *lower_cname = strdup(cname); +// char *c; + +// for(c = lower_cname; *c != '\0'; c++) { +// if(*c >= 'A' && *c <= 'Z') +// *c = *c + 32; +// } + + Printf(f_h, "ZEND_NAMED_FUNCTION(%s);\n", iname); + + // This is for the single main function_entry record + if (! cs_entry) Printf(s_entry, + " ZEND_NAMED_FE(%(lower)s,\n" + " %s, NULL)\n", cname,iname); + +// free(lower_cname); + } + + /* ------------------------------------------------------------ + * functionWrapper() + * ------------------------------------------------------------ */ + + virtual int functionWrapper(Node *n) { + char *name = GetChar(n,"name"); + char *iname = GetChar(n,"sym:name"); + SwigType *d = Getattr(n,"type"); + ParmList *l = Getattr(n,"parms"); + int newobject = (Getattr(n,"feature:new"))?1:0; + Parm *p; + char source[256],target[256],temp[256],argnum[32],args[32]; + int i,numopt; + String *tm; + Wrapper *f; + int num_saved = (Getattr(n,"feature:new"))?1:0; + String *cleanup, *outarg; + bool mvr=(shadow && variable_wrapper_flag && !enum_flag); + bool mvrset=0; + + if (!addSymbol(iname,n)) return SWIG_ERROR; + mvrset=(mvr && (strcmp(iname, Char(Swig_name_set(Swig_name_member(shadow_classname, name)))) == 0)); + + // if shadow and variable wrapper we want to snag the main contents + // of this function to stick in to the property handler.... + if (mvr) { //shadow && variable_wrapper_flag && !enum_flag) { + String *member_function_name = NewString(""); + String *php_function_name = NewString(iname); + if(strcmp(iname, Char(Swig_name_set(Swig_name_member(shadow_classname, name)))) == 0) { + Setattr(shadow_set_vars, php_function_name, name); + } + if(strcmp(iname, Char(Swig_name_get(Swig_name_member(shadow_classname, name)))) == 0) { + Setattr(shadow_get_vars, php_function_name, name); + } + Putc(toupper((int )*iname), member_function_name); + Printf(member_function_name, "%s", iname+1); + + cpp_func(Char(member_function_name), d, l, php_function_name); + + Delete(php_function_name); + Delete(member_function_name); + } + + outarg = cleanup = NULL; + f = NewWrapper(); + numopt = 0; + + outarg = NewString(""); + cleanup = NewString(""); + + // Special action for shadowing destructors under php. + // The real destructor is the resource list destructor, this is + // merely the thing that actually knows how to destroy... + + if (destructor) { + String *destructorname=NewString(""); + Printf(destructorname,"_%s",Swig_name_wrapper(iname)); + Setattr(classnode,"destructor",destructorname); + + Wrapper *df = NewWrapper(); + Printf(df->def,"/* This function is designed to be called by the zend list destructors to typecast and do the actual destruction */\n" + "void %s(zend_rsrc_list_entry *rsrc, const char *type_name TSRMLS_DC) {\n",destructorname); + + Wrapper_add_localv(df, "value", "swig_object_wrapper *value=(swig_object_wrapper *) rsrc->ptr", NIL); + Wrapper_add_localv(df, "ptr", "void *ptr=value->ptr", NIL); + Wrapper_add_localv(df, "newobject", "int newobject=value->newobject", NIL); + // Magic spell nicked from further down. + emit_args(d, l, df); + emit_attach_parmmaps(l,f); + + // Get type of first arg, thing to be destructed + // Skip ignored arguments + { + 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(df->code, + " efree(value);\n" + " if (! newobject) return; /* can't delete it! */\n" + " SWIG_ZTS_ConvertResourceData(ptr,rsrc->type,type_name,(void **) &arg1,SWIGTYPE%s TSRMLS_CC);\n" + " if (! arg1) zend_error(E_ERROR, \"%s resource already free'd\");\n" + ,SwigType_manglestr(pt), shadow_classname); + } + emit_action(n,df); + + Printf(df->code,"}\n"); + + Wrapper_print(df,s_wrappers); + } + + if (mvr) { // do prop[gs]et header + if (mvrset) Printf(f->def, "static int _wrap_%s(zend_property_reference *property_reference, pval *value) {\n",iname); + else Printf(f->def, "static pval _wrap_%s(zend_property_reference *property_reference) {\n",iname); + } else { // regular header + create_command(iname, Char(Swig_name_wrapper(iname))); + Printv(f->def, "ZEND_NAMED_FUNCTION(" , Swig_name_wrapper(iname), ") {\n", NIL); + } + + emit_args(d, l, f); + /* Attach standard typemaps */ + + emit_attach_parmmaps(l,f); + + int num_arguments = emit_num_arguments(l); + int num_required = emit_num_required(l); + numopt = num_arguments - num_required; + + // we do +1 because we are going to push in this_ptr as arg0 if present + // or do we need to? + + sprintf(args, "%s[%d]", "zval **args", num_arguments+1); + + Wrapper_add_local(f, "args",args); + Wrapper_add_localv(f, "argbase", "int argbase=0", NIL); + // 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 + + if (native_constructor) { + if (native_constructor==NATIVE_CONSTRUCTOR) Printf(f->code, "/* NATIVE Constructor */\nint self_constructor=1;\n"); + else Printf(f->code, "/* ALTERNATIVE Constructor */\n"); + } + + if (mvr && ! mvrset) { + Wrapper_add_local(f, "_return_value", "zval _return_value"); + Wrapper_add_local(f, "return_value", "zval *return_value=&_return_value"); + }; + + // only let this_ptr count as arg[-1] if we are not a constructor + // if we are a constructor and this_ptr is null we are called as a class + // method and can make one of us + if (! mvr && native_constructor==0) Printf(f->code, + "if (this_ptr && this_ptr->type==IS_OBJECT) {\n" + " /* fake this_ptr as first arg (till we can work out how to do it better */\n" + " argbase++;\n" + "}\n"); + + // I'd like to write out: + //" //args[argbase++]=&this_ptr;\n" + // but zend_get_parameters_array_ex can't then be told to leave + // the first slot alone, so we have to check whether or not to access + // this_ptr explicitly in each case where we normally just read args[] + + 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" + "if(arg_count<(%d-argbase) || arg_count>(%d-argbase))\n" + "\tWRONG_PARAM_COUNT;\n\n", + num_required, num_arguments); + + /* Verified args, retrieve them... */ + Printf(f->code, + "if(zend_get_parameters_array_ex(arg_count-argbase,args)!=SUCCESS)" + "\n\t\tWRONG_PARAM_COUNT;\n\n"); + + } else if (!mvr) { + Printf(f->code, + "if(((ZEND_NUM_ARGS() + argbase )!= %d) || (zend_get_parameters_array_ex(%d-argbase, args)" + "!= SUCCESS)) {\n" + "WRONG_PARAM_COUNT;\n}\n\n", + num_arguments, num_arguments); + } + + /* Now convert from php to C variables */ + // At this point, argcount if used is the number of deliberatly 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 the and not the first argument + // This may mean looking at Lang::memberfunctionhandler + + for (i = 0, p = l; i < num_arguments; i++) { + /* 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 (mvr) { // do we assert that numargs=2, that i<2 + if (i==0) sprintf(source,"&(property_reference->object)"); + else sprintf(source,"&value"); + } else { + // Do we fake this_ptr as arg0, or just possibly shift other args by 1 if we did fake? + if (i==0) sprintf(source, "((%d= (num_required)) + Printf(f->code,"\tif(arg_count > %d) {\n", i); + + Setattr(p,"emit:input", source); + + if ((tm = Getattr(p,"tmap:in"))) { + Replaceall(tm,"$target",target); + Replaceall(tm,"$source",source); + Replaceall(tm,"$input", source); + Printf(f->code,"%s\n",tm); + p = Getattr(p,"tmap:in:next"); + if (i >= num_required) { + Printf(f->code,"}\n"); + } + continue; + } else { + Printf(stderr,"%s : Line %d, Unable to use type %s as a function argument.\n", input_file, line_number, SwigType_str(pt,0)); + } + if (i>= num_required) + Printf(f->code,"\t}\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")); + 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"))) { + Replaceall(tm,"$source",Getattr(p,"lname")); + Replaceall(tm,"$input",Getattr(p,"lname")); + Replaceall(tm,"$target","return_value"); + Replaceall(tm,"$result","return_value"); + + String *in = Getattr(p,"emit:input"); + if (in) { + sprintf(temp,"_saved[%d]", num_saved); + Replaceall(tm,"$arg",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); + } + } + + // These are saved for argout again... + if(num_saved) { + sprintf(temp, "_saved[%d]",num_saved); + // Used to be zval *, perhaps above we should use * %s + Wrapper_add_localv(f,"_saved","zval **",temp,NIL); + } + + /* emit function call*/ + if (destructor) { + // If it is a registered resource (and it always should be) + // then destroy it the resource way + + Printf(f->code, + "/*if ((*args[0])->type==IS_RESOURCE) { */\n" + "/* Get zend list destructor to free it */\n" + "/* zend_list_delete(Z_LVAL_PP(args[0])); */\n" + "/* } else {*/ \n",name,name + ); + // but leave the old way in for as long as we accept strings as swig objects + emit_action(n,f); + Printf(f->code,"/*}*/\n"); + } else { + emit_action(n,f); + } + + if((tm = Swig_typemap_lookup((char*)"out",d,iname,(char*)"result",(char*)"result",(char*)"return_value",0))) { + 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); + // are we returning a wrapable object? + // I don't know if this test is comlete, I nicked it + if(is_shadow(d) && (SwigType_type(d) != T_ARRAY)) { + Printf(f->code,"/* Wrap this return value */\n"); + if (native_constructor==NATIVE_CONSTRUCTOR) { + Printf(f->code, "if (this_ptr) {\n/* NATIVE Constructor, use this_ptr */\n"); + Printf(f->code,"zval *_cPtr; MAKE_STD_ZVAL(_cPtr);\n" + "*_cPtr = *return_value;\n" + "INIT_ZVAL(*return_value);\n" + "add_property_zval(this_ptr,\"_cPtr\",_cPtr);\n" + "} else if (! this_ptr) ",shadow_classname); + } + { // THIS CODE only really needs writing out if the object to be returned + // Is being shadow-wrap-thingied + Printf(f->code, "{\n/* ALTERNATIVE Constructor, make an object wrapper */\n"); + // Make object + String *shadowrettype = NewString(""); + SwigToPhpType(d, iname, shadowrettype, shadow); + + Printf(f->code, + "zval *obj, *_cPtr;\n" + "MAKE_STD_ZVAL(obj);\n" + "MAKE_STD_ZVAL(_cPtr);\n" + "*_cPtr = *return_value;\n" + "INIT_ZVAL(*return_value);\n"); + + if (! shadow) { + Printf(f->code, + "*return_value=*_cPtr;\n"); + } else { + Printf(f->code, + "object_init_ex(obj,ptr_ce_swig_%s);\n" + "add_property_zval(obj,\"_cPtr\",_cPtr);\n" + "*return_value=*obj;\n", + shadowrettype); + } + Printf(f->code, "}\n"); + } + } // end of if-shadow lark + } else { + Printf(stderr,"%s: Line %d, Unable to use return type %s in function %s.\n", input_file, line_number, SwigType_str(d,0), name); + } + + if(outarg) + Printv(f->code,outarg,NIL); + + if(cleanup) + Printv(f->code,cleanup,NIL); + + // Whats this bit for? + if((tm = Swig_typemap_lookup((char*)"ret",d,iname,(char *)"result", (char*)"result",(char*)"",0))) { + Printf(f->code,"%s\n", tm); + } + + Replaceall(f->code,"$cleanup",cleanup); + Replaceall(f->code,"$symname",iname); + + if (mvr) { + if (! mvrset) Printf(f->code,"return _return_value;\n"); + else Printf(f->code,"return SUCCESS;\n"); + } + + Printf(f->code, "}\n"); + Wrapper_print(f,s_wrappers); + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * variableWrapper() + * ------------------------------------------------------------ */ + + virtual int OLDvariableWrapper(Node *n) { + char *name = GetChar(n,"name"); + char *iname = GetChar(n,"sym:name"); + SwigType *t = Getattr(n,"type"); + String *tm; + + if (!addSymbol(iname,n)) return SWIG_ERROR; + + SwigType_remember(t); + + /* First link C variables to PHP */ + + tm = Swig_typemap_lookup_new("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), name); + } + + /* Now generate PHP -> C sync blocks */ + tm = Swig_typemap_lookup_new("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), name); + } +*/ + /* Now generate C -> PHP sync blocks */ +/* + if(!Getattr(n,"feature:immutable")) { + + tm = Swig_typemap_lookup_new("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), name); + } + } +*/ + 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"); + char *value = GetChar(n,"value"); + + if (!addSymbol(iname,n)) return SWIG_ERROR; + + String *rval; + String *tm; + + SwigType_remember(type); + + switch(SwigType_type(type)) { + case T_STRING: + rval = NewStringf("\"%s\"", value); + break; + case T_CHAR: + rval = NewStringf("\'%s\'", value); + break; + default: + rval = NewString(value); + } + + if((tm = Swig_typemap_lookup_new("consttab", n, name, 0))) { + Replaceall(tm, "$source", value); + Replaceall(tm, "$target", name); + Replaceall(tm, "$value", value); + Printf(s_cinit, "%s\n", tm); + } + return SWIG_OK; + } + + /* + * PHP4::pragma() + * + * Pragma directive. + * + * %pragma(php4) code="String" # Includes a string in the .php file + * %pragma(php4) include="file.pl" # 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,"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 { + Printf(stderr, "%s : Line %d. Unrecognized pragma.\n", + input_file, line_number); + } + } + } + return Language::pragmaDirective(n); + } + + /* ------------------------------------------------------------ + * classDeclaration() + * ------------------------------------------------------------ */ + + virtual int classDeclaration(Node *n) { + 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"); + if(class_name) free(class_name); + class_name = Swig_copy_string(GetChar(n, "name")); + // 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 = Swig_copy_string(rename); + cs_entry = NewString(""); + Printf(cs_entry,"/* Function entries for %s */\n" + "static zend_function_entry %s_functions[] = {\n" + ,shadow_classname, shadow_classname); + + if(Strcmp(shadow_classname, module) == 0) { + Printf(stderr, "class name cannot be equal to module name: %s\n", shadow_classname); + SWIG_exit(1); + } + + Clear(shadow_classdef); + Clear(shadow_code); + + have_default_constructor = 0; + shadow_enum_code = NewString(""); + this_shadow_baseclass = NewString(""); + this_shadow_multinherit = NewString(""); + this_shadow_extra_code = NewString(""); + this_shadow_import = NewString(""); + + shadow_get_vars = NewHash(); + shadow_set_vars = NewHash(); + + /* Deal with inheritance */ + List *baselist = Getattr(n, "bases"); + + if(baselist) { + int class_count = 0; + Node *base = Firstitem(baselist); + + while(base && Getattr(base,"feature:ignore")) base = Nextitem(baselist); + + if (base && is_shadow(Getattr(base, "name"))) { + class_count++; + Printf(this_shadow_baseclass, "%s", Getattr(base, "name")); + } + + if (base) for(base = Nextitem(baselist); base; base = Nextitem(baselist)) { + if (Getattr(base,"feature:ignore")) continue; + if(is_shadow(Getattr(base, "name"))) { + class_count++; + Printf(this_shadow_multinherit, "%s ", Getattr(base, "name")); + } + } + + if(class_count > 1) Printf(stderr, "Error: %s inherits from multiple base classes(%s %s). Multiple inheritance is not directly supported by PHP4, SWIG may support it at some point in the future.\n", shadow_classname, base, this_shadow_multinherit); + } + + /* Write out class init code */ + Printf(s_vdecl,"static zend_class_entry ce_swig_%s;\n",shadow_classname); + Printf(s_vdecl,"static zend_class_entry* ptr_ce_swig_%s=NULL;\n",shadow_classname); + } + + classnode=n; + Language::classHandler(n); + classnode=0; + + if(shadow) { + DOH *key; + int gcount, scount; + String *s_propget=NewString(""); + String *s_propset=NewString(""); + List *baselist = Getattr(n, "bases"); + Node *base = NULL; + + // If no constructor was generated (abstract class) we had better + // generate a constructor that raises an error about instantiating + // abstract classes + if (! constructors || Getattr(n,"abstract")) { + // have to write out fake constructor which raises an error when called + abstractConstructorHandler(n); + } + + Printf(s_oinit,"/* Define class %s */\n" + "INIT_OVERLOADED_CLASS_ENTRY(ce_swig_%s,\"%(lower)s\",%s_functions," + "NULL,_wrap_propget_%s,_wrap_propset_%s);\n", + shadow_classname,shadow_classname,shadow_classname, + shadow_classname,shadow_classname,shadow_classname); + + // ******** Write property SET handlers + Printf(s_header,"static int _wrap_propset_%s(zend_property_reference *property_reference, pval *value);\n", shadow_classname); + Printf(s_propset,"static int _wrap_propset_%s(zend_property_reference *property_reference, pval *value) { \n" + " zval * _value;\n" + " zend_llist_element *element = property_reference->elements_list->head;\n" + " zend_overloaded_element *property=(zend_overloaded_element *)element->data;\n" + " if (_propset_%s(property_reference, value)==SUCCESS) return SUCCESS;\n" + " /* set it ourselves as it is %s */\n" + " MAKE_STD_ZVAL(_value);\n" + " *_value=*value;\n" + " INIT_PZVAL(_value);\n" + " zval_copy_ctor(_value);\n" + " return add_property_zval_ex(property_reference->object,Z_STRVAL_P(&(property->element)),1+Z_STRLEN_P(&(property->element)),_value);\n" + "}\n", shadow_classname, shadow_classname,shadow_classname); + Printf(s_header,"static int _propset_%s(zend_property_reference *property_reference, pval *value);\n", shadow_classname); + Printf(s_propset,"static int _propset_%s(zend_property_reference *property_reference, pval *value) {\n", shadow_classname); + + if (baselist) base=Firstitem(baselist); + else base=NULL; + while(base && Getattr(base,"feature:ignore")) base = Nextitem(baselist); + key = Firstkey(shadow_set_vars); + + // Print function header; we only need to find property name if there + // are properties for this class to look up... + if (key || ! base) { // or if we are base class and set it ourselves + Printf(s_propset," /* get the property name */\n" + " zend_llist_element *element = property_reference->elements_list->head;\n" + " zend_overloaded_element *property=(zend_overloaded_element *)element->data;\n" + " char *propname=Z_STRVAL_P(&(property->element));\n"); + } else { + if (base) { + Printf(s_propset," /* No extra properties for subclass %s */\n",shadow_classname); + } else { + Printf(s_propset," /* No properties for base class %s */\n",shadow_classname); + } + } + + scount=0; + while (key) { + if (scount++) Printf(s_propset," else"); + Printf(s_propset," if (strcmp(propname,\"%s\")==0) {\n" + " return _wrap_%s(property_reference, value);\n" + " }",Getattr(shadow_set_vars,key),key); + + key=Nextkey(shadow_set_vars); + } + + if (scount) Printf(s_propset," else"); + + // If there is a base class then chain it's handler else set directly + // try each base class handler, else set directly... + if (base) { + Printf(s_propset, " {\n /* chain to base class */\n"); + while(base) { + Printf(s_propset," if (_propset_%s(property_reference, value)==SUCCESS) return SUCCESS;\n", + GetChar(base, "sym:name")); + + base=Nextitem(baselist); + while (base && Getattr(base,"feature:ignore")) base=Nextitem(baselist); + } + Printf(s_propset," }\n"); + } + Printf(s_propset," return FAILURE;\n}\n\n"); + + // ******** Write property GET handlers + Printf(s_header,"static pval _wrap_propget_%s(zend_property_reference *property_reference);\n", shadow_classname); + Printf(s_propget,"static pval _wrap_propget_%s(zend_property_reference *property_reference) {\n" + " pval result;\n" + " pval **_result;\n" + " zend_llist_element *element = property_reference->elements_list->head;\n" + " zend_overloaded_element *property=(zend_overloaded_element *)element->data;\n" + " result.type = IS_NULL;\n" + " if (_propget_%s(property_reference, &result)==SUCCESS) return result;\n" + " /* return it ourselves */\n" + " if (zend_hash_find(Z_OBJPROP_P(property_reference->object),Z_STRVAL_P(&(property->element)),1+Z_STRLEN_P(&(property->element)),(void**)&_result)==SUCCESS) {\n" + " zval *_value;\n" + " MAKE_STD_ZVAL(_value);" + " *_value=**_result;\n" + " INIT_PZVAL(_value);\n" + " zval_copy_ctor(_value);\n" + " return *_value;\n" + " }\n" + " result.type = IS_NULL;\n" + " return result;\n" + "}\n", shadow_classname, shadow_classname); + Printf(s_header,"static int _propget_%s(zend_property_reference *property_reference, pval *value);\n", shadow_classname); + Printf(s_propget,"static int _propget_%s(zend_property_reference *property_reference, pval *value) {\n", shadow_classname); + + if (baselist) base=Firstitem(baselist); + else base=NULL; + while(base && Getattr(base,"feature:ignore")) base = Nextitem(baselist); + key = Firstkey(shadow_get_vars); + + // Print function header; we only need to find property name if there + // are properties for this class to look up... + if (key || !base ) { // or if we are base class... + Printf(s_propget," /* get the property name */\n" + " zend_llist_element *element = property_reference->elements_list->head;\n" + " zend_overloaded_element *property=(zend_overloaded_element *)element->data;\n" + " char *propname=Z_STRVAL_P(&(property->element));\n"); + } else { + if (base) { + Printf(s_propget," /* No extra properties for subclass %s */\n",shadow_classname); + } else { + Printf(s_propget," /* No properties for base class %s */\n",shadow_classname); + } + } + + gcount=0; + while (key) { + if (gcount++) Printf(s_propget," else"); + Printf(s_propget," if (strcmp(propname,\"%s\")==0) {\n" + " *value=_wrap_%s(property_reference);\n" + " return SUCCESS;\n" + " }",Getattr(shadow_get_vars,key),key); + + key=Nextkey(shadow_get_vars); + } + + if (gcount) Printf(s_propget," else"); + + // If there is a base class then chain it's handler else return null + if (base) { + Printf(s_propget, " {\n /* chain to base class */\n"); + while(base) { + Printf(s_propget," if (_propget_%s(property_reference, value)==SUCCESS) return SUCCESS;\n", + GetChar(base, "sym:name")); + + base=Nextitem(baselist); + while (base && Getattr(base,"feature:ignore")) base=Nextitem(baselist); + } + Printf(s_propget," }\n"); + } + Printf(s_propget," return FAILURE;\n}\n\n"); + + // wrappers generated now... + + // add wrappers to output code + Printf(s_wrappers,"/* property handler for class %s */\n",shadow_classname); + Printv(s_wrappers,s_propget,s_propset,NIL); + + // Save class in class table + if (baselist) base=Firstitem(baselist); + else base=NULL; + while(base && Getattr(base,"feature:ignore")) base = Nextitem(baselist); + + if (base) { + Printf(s_oinit,"if (! (ptr_ce_swig_%s=zend_register_internal_class_ex(&ce_swig_%s,&ce_swig_%s,NULL))) zend_error(E_ERROR,\"Error registering wrapper for class %s\");\n", + shadow_classname,shadow_classname,GetChar(base, "sym:name"), shadow_classname); + } else { + Printf(s_oinit,"if (! (ptr_ce_swig_%s=zend_register_internal_class_ex(&ce_swig_%s,NULL,NULL))) zend_error(E_ERROR,\"Error registering wrapper for class %s\");\n", + shadow_classname,shadow_classname, shadow_classname); + } + Printf(s_oinit,"\n"); + + + Printv(f_phpcode, shadow_classdef, shadow_code, NIL); + + // Write the enum initialisation code in a static block + // These are all the enums defined withing the c++ class. + + // PHP Needs to handle shadow enums properly still + if(strlen(Char(shadow_enum_code)) != 0 ) Printv(f_phpcode, "{\n /* enum */\n", shadow_enum_code, " }\n", NIL); + + free(shadow_classname); + shadow_classname = NULL; + + Delete(shadow_enum_code); shadow_enum_code = NULL; + Delete(this_shadow_baseclass); this_shadow_baseclass = NULL; + Delete(this_shadow_extra_code); this_shadow_extra_code = NULL; + Delete(this_shadow_import); this_shadow_import = NULL; + Delete(shadow_set_vars); shadow_set_vars = NULL; + Delete(shadow_get_vars); shadow_get_vars = NULL; + Delete(this_shadow_multinherit); this_shadow_multinherit = NULL; + + Printf(all_cs_entry,"%s { NULL, NULL, NULL}\n};\n",cs_entry); + //??delete cs_entry; + cs_entry=NULL; + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * memberfunctionHandler() + * ------------------------------------------------------------ */ + + virtual int memberfunctionHandler(Node *n) { + char *name = GetChar(n, "name"); + char *iname = GetChar(n, "sym:name"); + SwigType *t = Getattr(n, "type"); + ParmList *l = Getattr(n, "parms"); + + this->Language::memberfunctionHandler(n); + + if(shadow) { + char *realname = iname ? iname : name; + String *php_function_name = Swig_name_member(shadow_classname, realname); + + cpp_func(iname, t, l, realname, php_function_name); + + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * membervariableHandler() + * ------------------------------------------------------------ */ + + virtual int membervariableHandler(Node *n) { + + wrapping_member = 1; + variable_wrapper_flag = 1; + Language::membervariableHandler(n); + wrapping_member = 0; + variable_wrapper_flag = 0; + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * staticmemberfunctionHandler() + * ------------------------------------------------------------ */ + + virtual int staticmemberfunctionHandler(Node *n) { + char *name = GetChar(n, "name"); + char *iname = GetChar(n, "sym:name"); + + Language::staticmemberfunctionHandler(n); + + if(shadow) { + String *symname = Getattr(n, "sym:name"); + static_flag = 1; + char *realname = iname ? iname : name; + String *php_function_name = Swig_name_member(shadow_classname, realname); + cpp_func(Char(symname), Getattr(n, "type"), Getattr(n, "parms"), symname, php_function_name); + static_flag = 0; + } + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * staticmembervariableHandler() + * ------------------------------------------------------------ */ + + virtual int staticmembervariableHandler(Node *n) { + SwigType *d = Getattr(n, "type"); + char *iname = GetChar(n, "sym:name"); + char *name = GetChar(n, "name"); + String *static_name = NewStringf("%s::%s", class_name, name); +// String *use_class_name=SwigType_manglestr(SwigType_ltype(t)); + Wrapper *f; + + /* A temporary(!) hack for static member variables. + * Php currently supports class functions, but not class variables. + * Until it does, we convert a class variable to a class function + * that returns the current value of the variable. E.g. + * + * class Example { + * public: + * static int ncount; + * }; + * + * would be available in php as Example::ncount() + */ + static_flag = 1; + if(Getattr(n,"feature:immutable")) { + const_flag = 1; + } + cpp_func(iname, d, 0, iname); + static_flag = 0; + + create_command(iname, Char(Swig_name_wrapper(iname))); + + f = NewWrapper(); + + Printv(f->def, "ZEND_NAMED_FUNCTION(", Swig_name_wrapper(iname), ") {\n", NIL); + + /* If a argument is given we set the variable. Then we return + * the current value + */ + + Printf(f->code, + "zval **args[1];\n" + "int argcount;\n\n" + "argcount = ZEND_NUM_ARGS();\n" + "if(argcount > %d) WRONG_PARAM_COUNT;\n\n", (const_flag? 0 : 1)); + + if(!const_flag) { + Printf(f->code, "if(argcount) {\n"); + + Printf(f->code, "if(zend_get_parameters_array_ex(argcount, args) != SUCCESS) WRONG_PARAM_COUNT;\n"); + + switch(SwigType_type(d)) { + case T_BOOL: + case T_INT: + case T_SHORT: + case T_LONG: + case T_SCHAR: + case T_UINT: + case T_USHORT: + case T_ULONG: + case T_UCHAR: + Printf(f->code, + "convert_to_long_ex(args[0]);\n" + "%s = Z_LVAL_PP(args[0]);\n", static_name); + break; + case T_CHAR: + Printf(f->code, + "convert_to_string_ex(args[0]);\n" + "%s = estrdup(Z_STRVAL(args[0]));\n", static_name); + break; + case T_DOUBLE: + case T_FLOAT: + Printf(f->code, + "convert_to_double_ex(args[0]);\n" + "%s = Z_DVAL_PP(args[0]);\n", + static_name); + break; + case T_VOID: + break; + case T_USER: + Printf(f->code, "convert_to_string_ex(args[0]);\n"); + get_pointer(Char(iname), (char*)"variable", (char*)"args[0]", Char(static_name), d, f->code, (char *)"RETURN_FALSE"); + break; + case T_POINTER: + case T_ARRAY: + case T_REFERENCE: + Printf(f->code, "convert_to_string_ex(args[0]);\n"); + get_pointer(Char(iname), (char*)"variable", (char*)"args[0]", Char(static_name), d, f->code, (char*)"RETURN_FALSE"); + break; + default: + Printf(stderr,"%s : Line %d, Unable to use type %s as a class variable.\n", input_file, line_number, SwigType_str(d,0)); + break; + } + + Printf(f->code, "}\n\n"); + + } /* end of const_flag */ + + switch(SwigType_type(d)) { + case T_BOOL: + case T_INT: + case T_SHORT: + case T_LONG: + case T_SCHAR: + case T_UINT: + case T_USHORT: + case T_ULONG: + case T_UCHAR: + Printf(f->code, + "RETURN_LONG(%s);\n", static_name); + break; + case T_DOUBLE: + case T_FLOAT: + Printf(f->code, + "RETURN_DOUBLE(%s);\n", static_name); + break; + case T_CHAR: + Printf(f->code, + "{\nchar ctemp[2];\n" + "ctemp[0] = %s;\n" + "ctemp[1] = 0;\n" + "RETURN_STRING(ctemp, 1);\n}\n", + static_name); + break; + + case T_USER: + case T_POINTER: + Printf(f->code, + "SWIG_SetPointerZval(return_value, (void *)%s, " + "SWIGTYPE%s);\n", static_name, SwigType_manglestr(d)); + break; + case T_STRING: + Printf(f->code, "RETURN_STRING(%s, 1);\n", static_name); + break; + } + + + Printf(f->code, "}\n"); + + const_flag = 0; + + Wrapper_print(f, s_wrappers); + + return SWIG_OK; + } + + + void SwigToPhpType(SwigType *t, String_or_char *pname, String* php_type, int shadow_flag) { + char *ptype = 0; + + if(shadow_flag) + ptype = PhpTypeFromTypemap((char*)"pstype", t, pname,(char*)""); + if(!ptype) + ptype = PhpTypeFromTypemap((char*)"ptype",t,pname,(char*)""); + + + if(ptype) { + Printf(php_type, ptype); + free(ptype); + } + else { + /* Map type here */ + switch(SwigType_type(t)) { + case T_CHAR: + case T_SCHAR: + case T_UCHAR: + case T_SHORT: + case T_USHORT: + case T_INT: + case T_UINT: + case T_LONG: + case T_ULONG: + case T_FLOAT: + case T_DOUBLE: + case T_BOOL: + case T_STRING: + case T_VOID: + Printf(php_type, ""); + break; + case T_POINTER: + case T_REFERENCE: + case T_USER: + if(shadow_flag && is_shadow(t)) + Printf(php_type, Char(is_shadow(t))); + else + Printf(php_type, ""); + break; + case T_ARRAY: + /* TODO */ + break; + default: + Printf(stderr, "SwigToPhpType: unhandled data type: %s\n", SwigType_str(t,0)); + break; + } + } + } + + + char *PhpTypeFromTypemap(char *op, SwigType *t, String_or_char *pname, String_or_char *lname) { + String *tms; + char bigbuf[1024]; + char *tm; + char *c = bigbuf; + if(!(tms = Swig_typemap_lookup(op, t, pname, lname, (char*)"", (char*)"", NULL))) return NULL; + + tm = Char(tms); + while(*tm && (isspace(*tm) || *tm == '{')) tm++; + while(*tm && *tm != '}') *c++ = *tm++; + *c='\0'; + return Swig_copy_string(bigbuf); + } + + int abstractConstructorHandler(Node *n) { + char *iname = GetChar(n, "sym:name"); + if (shadow) { + Wrapper *f; + f = NewWrapper(); + + // constructor header + if (cs_entry) Printf(cs_entry, + " ZEND_NAMED_FE(%(lower)s,\n" + " _wrap_new_%s, NULL)\n", iname,iname); + // now constructor body + Printf(f_h, "ZEND_NAMED_FUNCTION(_wrap_new_%s);\n",iname); + Printf(f->def, "ZEND_NAMED_FUNCTION(_wrap_new_%s) {\n" + "zend_error(E_ERROR,\"Cannot create swig object type: %s as the underlying object is abstract\");\n" + "}\n\n", iname, iname); + Wrapper_print(f,s_wrappers); + DelWrapper(f); + } + return SWIG_OK; + } + /* ------------------------------------------------------------ + * constructorHandler() + * ------------------------------------------------------------ */ + + virtual int constructorHandler(Node *n) { + char *iname = GetChar(n, "sym:name"); + + if (shadow) native_constructor = (strcmp(iname, shadow_classname) == 0)?\ + NATIVE_CONSTRUCTOR:ALTERNATIVE_CONSTRUCTOR; + else native_constructor=0; + constructors++; + Language::constructorHandler(n); + + if(shadow) { + // But we also need one per wrapped-class + if (cs_entry) Printf(cs_entry, + " ZEND_NAMED_FE(%(lower)s,\n" + " _wrap_new_%s, NULL)\n", iname,iname); + } + + native_constructor = 0; + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * destructorHandler() + * ------------------------------------------------------------ */ + + virtual int destructorHandler(Node *n) { + char *iname = GetChar(n, "sym:name"); + + destructor=1; + Language::destructorHandler(n); + destructor=0; + + // we don't give user access to destructors, they have to unset var + // and let php dispose instead + if(0 && shadow) { + // But we also need one per wrapped-class + if (cs_entry) Printf(cs_entry, + " ZEND_NAMED_FE(_destroy_%(lower)s,\n" + " _wrap_delete_%s, NULL)\n", iname,iname); + } + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * memberconstantHandler() + * ------------------------------------------------------------ */ + + virtual int memberconstantHandler(Node *n) { + wrapping_member = 1; + Language::memberconstantHandler(n); + wrapping_member = 0; + return SWIG_OK; + } + + // This method is quite stale and ought to be factored out + void cpp_func(char *iname, SwigType *t, ParmList *l, String *php_function_name, String *handler_name = NULL) { + if(!shadow) return; + + // if they didn't provide a handler name, use the realname + if (! handler_name) handler_name=php_function_name; + + if(l) { + if(SwigType_type(Getattr(l, "type")) == T_VOID) { + l = nextSibling(l); + } + } + + // But we also need one per wrapped-class + // Printf(f_h, "x ZEND_NAMED_FUNCTION(%s);\n", Swig_name_wrapper(handler_name)); + if (cs_entry && !(variable_wrapper_flag && shadow)) Printf(cs_entry, + " ZEND_NAMED_FE(%(lower)s,\n" + " %s, NULL)\n", php_function_name,Swig_name_wrapper(handler_name)); + + if(variable_wrapper_flag) { return; } + + /* Workaround to overcome Getignore(p) not working - p does not always + * have the Getignore attribute set. Noticeable when cpp_func is called + * from cpp_member_func() + */ + + Wrapper *f = NewWrapper(); + emit_args(NULL, l, f); + DelWrapper(f); + + /*Workaround end */ + + } + +}; /* class PHP4 */ + +/* ----------------------------------------------------------------------------- + * swig_php() - Instantiate module + * ----------------------------------------------------------------------------- */ + +static PHP4 *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 PHP4::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); +} + +extern "C" Language * +swig_php(void) { + maininstance=new PHP4(); + if (! r_prevtracefunc) { + r_prevtracefunc=SwigType_remember_trace(typetrace); + } else { + Printf(stderr,"php4 Typetrace vector already saved!\n"); + assert(0); + } + return maininstance; +} + diff --git a/Source/Modules/pike.cxx b/Source/Modules/pike.cxx new file mode 100644 index 000000000..bcd51763e --- /dev/null +++ b/Source/Modules/pike.cxx @@ -0,0 +1,881 @@ +/*********************************************************************** + * Pike language module for SWIG + ***********************************************************************/ + +char cvsroot_pike_cxx[] = "$Header$"; + +#include "swigmod.h" +#ifndef MACSWIG +#include "swigconfig.h" +#endif + +class PIKE : public Language { +private: + + File *f_runtime; + File *f_header; + File *f_wrappers; + File *f_init; + 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_runtime = 0; + f_header = 0; + f_wrappers = 0; + f_init = 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], "-ldflags") == 0) { + printf("%s\n", SWIG_PIKE_RUNTIME); + SWIG_exit(EXIT_SUCCESS); + } + } + } + + /* 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_runtime = NewFile(outfile, "w"); + if (!f_runtime) { + Printf(stderr, "*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + 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("runtime", f_runtime); + Swig_register_filebyname("init", f_init); + + /* Standard stuff for the SWIG runtime section */ + Swig_banner(f_runtime); + if (NoInclude) { + Printf(f_runtime, "#define SWIG_NOINCLUDE\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_header, f_runtime); + Dump(f_wrappers, f_runtime); + Wrapper_pretty_print(f_init, f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + Delete(f_runtime); + + /* Done */ + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * 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 DOHString_or_char *name) { + String *s = Copy(name); + if (Strncmp(name, PrefixPlusUnderscore, Len(PrefixPlusUnderscore)) != 0) { + return s; + } + Replaceall(s, PrefixPlusUnderscore, ""); + return s; + } + + /* ------------------------------------------------------------ + * add_method() + * ------------------------------------------------------------ */ + + void add_method(Node *n, const DOHString_or_char *name, const DOHString_or_char *function, const DOHString_or_char *description) { + String *rename; + if (current != NO_CPP) { + rename = strip(name); + } else { + rename = NewString(name); + } + Printf(f_init, "ADD_FUNCTION(\"%s\", %s, tFunc(%s), 0);\n", rename, function, description); + 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(); + + /* Write code to extract function parameters. */ + emit_args(d, 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); + } + + 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, "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 */ + emit_action(n,f); + + /* Clear the return stack */ + Printf(f->code, "pop_n_elems(args);\n"); + + /* Return the function value */ + if (current == CONSTRUCTOR) { + Printv(f->code, "THIS = (void *) result;\n", NIL); + Printv(description, ", tVoid", NIL); + } else if (current == DESTRUCTOR) { + Printv(description, ", tVoid", NIL); + } else { + Wrapper_add_local(f, "resultobj", "struct object *resultobj"); + Printv(description, ", ", NIL); + if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) { + Replaceall(tm,"$source", "result"); + Replaceall(tm,"$target", "resultobj"); + Replaceall(tm,"$result", "resultobj"); + if (Getattr(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); + } + } + + /* 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 (Getattr(n,"feature:new")) { + if ((tm = Swig_typemap_lookup_new("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_new("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(n, iname, wname, description); + } else { + Setattr(n,"wrap:name", wname); + 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,"return %s(self,args);",&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, + "struct object *", wname, + "(struct object *self, struct object *args) {", + NULL); + + + Wrapper_add_local(f,"argc","INT32 argc"); + Printf(tmp,"struct object *argv[%d]", maxargs+1); + Wrapper_add_local(f,"argv",tmp); + Wrapper_add_local(f,"ii","INT32 ii"); + Printf(f->code,"argc = sizeof(args);\n"); + Printf(f->code,"for (ii = 0; (ii < argc) && (ii < %d); ii++) {\n",maxargs); + Printf(f->code,"argv[ii] = array_index(args,&argv[ii],ii);\n"); + Printf(f->code,"}\n"); + + Replaceall(dispatch,"$args","self,args"); + Printv(f->code,dispatch,"\n",NIL); + Printf(f->code,"No matching function for overloaded '%s'\n", symname); + Printf(f->code,"return NULL;\n"); + Printv(f->code,"}\n",NIL); + Wrapper_print(f,f_wrappers); + add_method(n,symname,wname,0); + + DelWrapper(f); + Delete(dispatch); + Delete(tmp); + Delete(wname); + } + + /* ------------------------------------------------------------ + * variableWrapper() + * ------------------------------------------------------------ */ + + virtual int variableWrapper(Node *n) { + // return Language::variableWrapper(n); + + String *name = Getattr(n,"name"); + String *iname = Getattr(n,"sym:name"); + SwigType *t = Getattr(n,"type"); + + String *wname; + // static int have_globals = 0; + String *tm; + Wrapper *getf, *setf; + + if (!addSymbol(iname,n)) return SWIG_ERROR; + + getf = NewWrapper(); + setf = NewWrapper(); + + wname = Swig_name_wrapper(iname); + + /* Create a function for setting the value of the variable */ + + Printf(setf->def,"static int %s_set(object *_val) {", wname); + if (!Getattr(n,"feature:immutable")) { + if ((tm = Swig_typemap_lookup_new("varin",n,name,0))) { + Replaceall(tm,"$source","_val"); + Replaceall(tm,"$target",name); + Replaceall(tm,"$input","_val"); + Printf(setf->code,"%s\n",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)); + } + Printf(setf->code," return 0;\n"); + } else { + /* Is a readonly variable. Issue an error */ + + Printv(setf->code, + tab4, "Variable $iname is read-only.\n", + tab4, "return 1;\n", + NIL); + + } + + Printf(setf->code,"}\n"); + Wrapper_print(setf,f_wrappers); + + /* Create a function for getting the value of a variable */ + Printf(getf->def,"static object *%s_get() {", wname); + Wrapper_add_local(getf,"pikeobj", "object *pyobj"); + if ((tm = Swig_typemap_lookup_new("varout",n,name,0))) { + Replaceall(tm,"$source",name); + Replaceall(tm,"$target","pikeobj"); + Replaceall(tm,"$result","pikeobj"); + Printf(getf->code,"%s\n", tm); + } else { + Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, + "Unable to link with type %s\n", SwigType_str(t,0)); + } + + Printf(getf->code," return pikeobj;\n}\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_get, %s_set);\n", iname, wname, wname); + + DelWrapper(setf); + DelWrapper(getf); + return SWIG_OK; + + } + + /* ------------------------------------------------------------ + * constantWrapper() + * ------------------------------------------------------------ */ + + virtual int constantWrapper(Node *n) { + + Swig_require(&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_new("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(n, 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_init, "start_new_program();\n"); + + /* Handle inheritance */ + List *baselist = Getattr(n,"bases"); + if (baselist && Len(baselist) > 0) { + Node *base = Firstitem(baselist); + while (base) { + char *basename = Char(Getattr(base,"name")); + if (SwigType_istemplate(basename)) { + basename = Char(SwigType_namestr(basename)); + } + SwigType *basetype = NewString(basename); + SwigType_add_pointer(basetype); + SwigType_remember(basetype); + String *basemangle = SwigType_manglestr(basetype); + Printf(f_init, "low_inherit((struct program *) SWIGTYPE%s->clientdata, 0, 0, 0, 0, 0);\n", basemangle); + Delete(basemangle); + Delete(basetype); + base = Nextitem(baselist); + } + } else { + Printf(f_init, "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 */ + Printf(f_init, "add_program_constant(\"%s\", pr = end_program(), 0);\n", symname); + + 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; + Node *n; + bool need_setter; + String *funcname; + + /* If at least one of them is mutable, we need a setter */ + need_setter = false; + n = Firstitem(membervariables); + while (n) { + if (!Getattr(n, "feature:immutable")) { + need_setter = true; + break; + } + n = Nextitem(membervariables); + } + + /* 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(sp[0-args].u.string);\n"); + + n = Firstitem(membervariables); + while (n) { + if (!Getattr(n, "feature:immutable")) { + name = Getattr(n, "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); + } + n = Nextitem(membervariables); + } + + /* 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(Firstitem(membervariables), "`->=", 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(sp[0-args].u.string);\n"); + + n = Firstitem(membervariables); + while (n) { + name = Getattr(n, "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); + n = Nextitem(membervariables); + } + + /* 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(Firstitem(membervariables), "`->", 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 + * ----------------------------------------------------------------------------- */ + +extern "C" Language * +swig_pike(void) { + return new PIKE(); +} + + + + + diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx new file mode 100644 index 000000000..6651ace92 --- /dev/null +++ b/Source/Modules/python.cxx @@ -0,0 +1,1268 @@ +/* ----------------------------------------------------------------------------- + * python.cxx + * + * Python module. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_python_cxx[] = "$Header$"; + +#include "swigmod.h" + +#ifndef MACSWIG +#include "swigconfig.h" +#endif + +#include + +#define PYSHADOW_MEMBER 0x2 + +static String *const_code = 0; +static String *shadow_methods = 0; +static String *module = 0; +static String *mainmodule = 0; +static String *interface = 0; +static String *global_name = 0; +static int shadow = 1; +static int use_kw = 0; + +static File *f_runtime = 0; +static File *f_header = 0; +static File *f_wrappers = 0; +static File *f_init = 0; +static File *f_shadow = 0; +static File *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; + +/* C++ Support + Shadow Classes */ + +static int have_constructor; +static int have_repr; +static String *real_classname; + +static const char *usage = (char *)"\ +Python Options (available with -python)\n\ + -ldflags - Print runtime libraries to link with\n\ + -globals name - Set name used to access C global variable ('cvar' by default).\n\ + -interface name - Set the lib name\n\ + -keyword - Use keyword arguments\n\ + -classic - Use classic classes only\n\ + -noexcept - No automatic exception handling.\n\ + -noproxy - Don't generate proxy classes. \n\n"; + +class PYTHON : public Language { +public: + + /* ------------------------------------------------------------ + * main() + * ------------------------------------------------------------ */ + + virtual void main(int argc, char *argv[]) { + + 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],"-noproxy") == 0)) { + shadow = 0; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-keyword") == 0) { + use_kw = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-classic") == 0) { + classic = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-help") == 0) { + fputs(usage,stderr); + } else if (strcmp (argv[i], "-ldflags") == 0) { + printf("%s\n", SWIG_PYTHON_RUNTIME); + SWIG_exit (EXIT_SUCCESS); + } + } + } + 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) { + + /* Initialize all of the output files */ + String *outfile = Getattr(n,"outfile"); + + f_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + 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("runtime",f_runtime); + Swig_register_filebyname("init",f_init); + + const_code = NewString(""); + shadow_methods = NewString(""); + methods = NewString(""); + + Swig_banner(f_runtime); + + Printf(f_runtime,"#define SWIGPYTHON\n"); + if (NoInclude) + Printf(f_runtime,"#define SWIG_NOINCLUDE\n"); + + /* Set module name */ + module = Copy(Getattr(n,"name")); + mainmodule = Getattr(n,"name"); + + char filen[256]; + + /* If shadow classing is enabled, we're going to change the module name to "_module" */ + if (shadow) { + sprintf(filen,"%s%s.py", Swig_file_dirname(outfile), 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 = NewFile(filen,"w")) == 0) { + Printf(stderr,"Unable to open %s\n", filen); + SWIG_exit (EXIT_FAILURE); + } + f_shadow_stubs = NewString(""); + + Swig_register_filebyname("shadow",f_shadow); + Swig_register_filebyname("python",f_shadow); + + Printv(f_shadow, + "# This file was created automatically by SWIG.\n", + "# Don't modify this file, modify the SWIG interface instead.\n", + "# This file is compatible with both classic and new-style classes.\n", + NIL); + + Printf(f_shadow,"import %s\n", module); + + // Python-2.2 object hack + + + Printv(f_shadow, + "def _swig_setattr(self,class_type,name,value):\n", + tab4, "if (name == \"this\"):\n", + tab4, tab4, "if isinstance(value, class_type):\n", + tab4, tab8, "self.__dict__[name] = value.this\n", + tab4, tab8, "if hasattr(value,\"thisown\"): self.__dict__[\"thisown\"] = value.thisown\n", + tab4, tab8, "del value.thisown\n", + tab4, tab8, "return\n", + // tab8, "if (name == \"this\") or (name == \"thisown\"): self.__dict__[name] = value; return\n", + tab4, "method = class_type.__swig_setmethods__.get(name,None)\n", + tab4, "if method: return method(self,value)\n", + tab4, "self.__dict__[name] = value\n\n", + NIL); + + Printv(f_shadow, + "def _swig_getattr(self,class_type,name):\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); + + if (!classic) { + Printv(f_shadow, + "import types\n", + "try:\n", + " _object = types.ObjectType\n", + " _newclass = 1\n", + "except AttributeError:\n", + " class _object : pass\n", + " _newclass = 0\n", + "\n\n", + NIL); + } + + // Include some information in the code + Printf(f_header,"\n/*-----------------------------------------------\n @(target):= %s.so\n\ + ------------------------------------------------*/\n", module); + + } + + Printf(f_header,"#define SWIG_init init%s\n\n", module); + 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"); + Printf(const_code,"static swig_const_info swig_const_table[] = {\n"); + Printf(methods,"static PyMethodDef SwigMethods[] = {\n"); + + /* emit code */ + Language::top(n); + + /* Close language module */ + Printf(methods,"\t { NULL, NULL }\n"); + Printf(methods,"};\n"); + Printf(f_wrappers,"%s\n",methods); + + SwigType_emit_type_table(f_runtime,f_wrappers); + + Printf(const_code, "{0}};\n"); + Printf(f_wrappers,"%s\n",const_code); + Printf(f_init,"}\n"); + + Printf(f_wrappers,"#ifdef __cplusplus\n"); + Printf(f_wrappers,"}\n"); + Printf(f_wrappers,"#endif\n"); + + if (shadow) { + Printv(f_shadow, f_shadow_stubs, "\n",NIL); + Close(f_shadow); + Delete(f_shadow); + } + + /* Close all of the files */ + Dump(f_header,f_runtime); + Dump(f_wrappers,f_runtime); + Wrapper_pretty_print(f_init,f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * importDirective() + * ------------------------------------------------------------ */ + + virtual int importDirective(Node *n) { + if (shadow) { + String *modname = Getattr(n,"module"); + if (modname) { + Printf(f_shadow,"import %s\n", modname); + } + } + return Language::importDirective(n); + } + + /* ------------------------------------------------------------ + * add_method() + * ------------------------------------------------------------ */ + + void add_method(String *name, String *function, int kw) { + if (!kw) + Printf(methods,"\t { (char *)\"%s\", %s, METH_VARARGS },\n", name, function); + else + Printf(methods,"\t { (char *)\"%s\", (PyCFunction) %s, METH_VARARGS | METH_KEYWORDS },\n", name, function); + } + + /* ------------------------------------------------------------ + * 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"); + + Parm *p; + int i; + char wname[256]; + 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 = (use_kw || Getattr(n,"feature:kwargs")) ? 1 : 0; + + 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(""); + + Wrapper_add_local(f,"resultobj", "PyObject *resultobj"); + + /* Write code to extract function parameters. */ + emit_args(d, 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); + varargs = emit_isvarargs(l); + + strcpy(wname,Char(Swig_name_wrapper(iname))); + if (overname) { + strcat(wname,Char(overname)); + } + + if (!allow_kwargs || Getattr(n,"sym:overloaded")) { + if (!varargs) { + Printv(f->def, + "static PyObject *", wname, + "(PyObject *self, PyObject *args) {", + NIL); + } else { + Printv(f->def, + "static PyObject *", wname, "__varargs__", + "(PyObject *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.\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, + "static PyObject *", wname, + "(PyObject *self, PyObject *args, PyObject *kwargs) {", + NIL); + } + if (!allow_kwargs) { + Printf(parse_args," if(!PyArg_ParseTuple(args,(char *)\""); + } else { + Printf(parse_args," if(!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)\""); + Printf(arglist,",kwnames"); + } + + /* Generate code for argument marshalling */ + + Printf(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"); + + sprintf(source,"obj%d",i); + + Putc(',',arglist); + if (i == num_required) Putc('|', parse_args); /* Optional argument separator */ + + /* Keyword argument handling */ + if (Len(pn)) { + Printf(kwargs,"\"%s\",", pn); + } else { + Printf(kwargs,"\"arg%d\",", i+1); + } + + /* Look for an input typemap */ + if ((tm = Getattr(p,"tmap:in"))) { + String *parse = Getattr(p,"tmap:in:parse"); + if (!parse) { + 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"); + } + + Putc('O',parse_args); + 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 { + Printf(parse_args,"%s",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; + } + p = nextSibling(p); + } + + /* finish argument marshalling */ + Printf(kwargs," NULL }"); + if (allow_kwargs) { + Printv(f->locals,tab4, "char *kwnames[] = ", kwargs, ";\n", NIL); + } + + Printf(parse_args,":%s\"", iname); + Printv(parse_args, + arglist, ")) goto 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 ((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 (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 */ + emit_action(n,f); + + /* This part below still needs cleanup */ + + /* Return the function value */ + if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) { + Replaceall(tm,"$source", "result"); + Replaceall(tm,"$target", "resultobj"); + Replaceall(tm,"$result", "resultobj"); + if (Getattr(n,"feature:new")) { + Replaceall(tm,"$owner","1"); + } 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); + } + + /* 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 (Getattr(n,"feature:new")) { + if ((tm = Swig_typemap_lookup_new("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_new("ret", n, "result", 0))) { + Replaceall(tm,"$source","result"); + Printf(f->code,"%s\n",tm); + } + + Printf(f->code," return resultobj;\n"); + + /* Error handling code */ + + Printf(f->code,"fail:\n"); + Printv(f->code,cleanup,NIL); + Printf(f->code,"return NULL;\n"); + 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); + + /* If varargs. Need to emit a varargs stub */ + if (varargs) { + DelWrapper(f); + f = NewWrapper(); + Printv(f->def, + "static 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); + Printf(f->code,"Py_XDECREF(newargs);\n"); + Printf(f->code,"Py_XDECREF(varargs);\n"); + Printf(f->code,"return resultobj;\n"); + Printf(f->code,"}\n"); + Wrapper_print(f,f_wrappers); + } + + Setattr(n,"wrap:name", wname); + + /* Now register the function with the interpreter. */ + if (!Getattr(n,"sym:overloaded")) { + add_method(iname, wname, allow_kwargs); + + /* Create a shadow for this function (if enabled and not in a member function) */ + if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) { + if (in_class) { + Printv(f_shadow_stubs,iname, " = ", module, ".", iname, "\n\n", NIL); + } else { + Printv(f_shadow,iname, " = ", module, ".", iname, "\n\n", NIL); + } + } + } else { + if (!Getattr(n,"sym:nextSibling")) { + dispatchFunction(n); + } + } + Delete(parse_args); + Delete(arglist); + Delete(get_pointers); + Delete(cleanup); + Delete(outarg); + Delete(kwargs); + DelWrapper(f); + 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(self,args);",&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, + "static 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); + Wrapper_add_local(f,"ii","int ii"); + Printf(f->code,"argc = PyObject_Length(args);\n"); + Printf(f->code,"for (ii = 0; (ii < argc) && (ii < %d); ii++) {\n",maxargs); + Printf(f->code,"argv[ii] = PyTuple_GetItem(args,ii);\n"); + Printf(f->code,"}\n"); + + Replaceall(dispatch,"$args","self,args"); + Printv(f->code,dispatch,"\n",NIL); + Printf(f->code,"PyErr_SetString(PyExc_TypeError,\"No matching function for overloaded '%s'\");\n", symname); + Printf(f->code,"return NULL;\n"); + Printv(f->code,"}\n",NIL); + Wrapper_print(f,f_wrappers); + add_method(symname,wname,0); + + /* Create a shadow for this function (if enabled and not in a member function) */ + if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) { + Printv(f_shadow_stubs,symname, " = ", module, ".", symname, "\n\n", NIL); + } + DelWrapper(f); + Delete(dispatch); + Delete(tmp); + Delete(wname); + } + + /* ------------------------------------------------------------ + * variableWrapper() + * ------------------------------------------------------------ */ + + virtual int variableWrapper(Node *n) { + + String *name = Getattr(n,"name"); + String *iname = Getattr(n,"sym:name"); + SwigType *t = Getattr(n,"type"); + + String *wname; + 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); + } + } + + if ((shadow) && (SwigType_isconst(t))) { + if (!in_class) { + Printf(f_shadow_stubs,"%s = %s.%s\n", iname, global_name, iname); + } + } + + wname = Swig_name_wrapper(iname); + + /* Create a function for setting the value of the variable */ + + Printf(setf->def,"static int %s_set(PyObject *_val) {", wname); + if (!Getattr(n,"feature:immutable")) { + if ((tm = Swig_typemap_lookup_new("varin",n,name,0))) { + Replaceall(tm,"$source","_val"); + Replaceall(tm,"$target",name); + Replaceall(tm,"$input","_val"); + Printf(setf->code,"%s\n",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)); + } + Printf(setf->code," return 0;\n"); + } else { + /* Is a readonly variable. Issue an error */ + Printv(setf->code, + tab4, "PyErr_SetString(PyExc_TypeError,\"Variable ", iname, + " is read-only.\");\n", + tab4, "return 1;\n", + NIL); + } + + Printf(setf->code,"}\n"); + Wrapper_print(setf,f_wrappers); + + /* Create a function for getting the value of a variable */ + Printf(getf->def,"static PyObject *%s_get() {", wname); + Wrapper_add_local(getf,"pyobj", "PyObject *pyobj"); + if ((tm = Swig_typemap_lookup_new("varout",n,name,0))) { + Replaceall(tm,"$source",name); + Replaceall(tm,"$target","pyobj"); + Replaceall(tm,"$result","pyobj"); + Printf(getf->code,"%s\n", tm); + } else { + Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, + "Unable to link with type %s\n", SwigType_str(t,0)); + } + + Printf(getf->code," return pyobj;\n}\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_get, %s_set);\n", iname, wname, wname); + + 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 *value = 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); + Printf(f_header, "static %s = %s;\n", SwigType_str(type,wname), value); + value = wname; + } + if ((tm = Swig_typemap_lookup_new("consttab",n,name,0))) { + Replaceall(tm,"$source",value); + Replaceall(tm,"$target",name); + Replaceall(tm,"$value", value); + Printf(const_code,"%s,\n", tm); + have_tm = 1; + } + if ((tm = Swig_typemap_lookup_new("constcode", n, name, 0))) { + Replaceall(tm,"$source",value); + Replaceall(tm,"$target",name); + Replaceall(tm,"$value",value); + Printf(f_init, "%s\n", 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 { + 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\n", NIL); + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * classDeclaration() + * ------------------------------------------------------------ */ + + virtual int classDeclaration(Node *n) { + String *importname; + Node *mod; + if (shadow) { + mod = Getattr(n,"module"); + if (mod) { + String *modname = Getattr(mod,"name"); + if (Strcmp(modname,mainmodule) != 0) { + importname = NewStringf("%s.%s", modname, Getattr(n,"sym:name")); + } else { + importname = NewString(Getattr(n,"sym:name")); + } + Setattr(n,"python:proxy",importname); + } + } + return Language::classDeclaration(n); + } + + /* ------------------------------------------------------------ + * classHandler() + * ------------------------------------------------------------ */ + + virtual int classHandler(Node *n) { + int oldclassic = classic; + + if (shadow) { + + /* Create new strings for building up a wrapper function */ + have_constructor = 0; + have_repr = 0; + + if (Getattr(n,"cplus:exceptionclass")) { + classic = 1; + } + if (Getattr(n,"feature:classic")) classic = 1; + + 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)) { + Node *base = Firstitem(baselist); + while (base) { + String *bname = Getattr(base, "python:proxy"); + if (!bname) { + base = Nextitem(baselist); + continue; + } + Printv(base_class,bname,NIL); + base = Nextitem(baselist); + if (base) { + Putc(',',base_class); + } + } + } + Printv(f_shadow,"class ", class_name, NIL); + + if (Len(base_class)) { + Printf(f_shadow,"(%s)", base_class); + } else { + if (!classic) { + Printf(f_shadow,"(_object)"); + } + } + Printf(f_shadow,":\n"); + + Printv(f_shadow,tab4,"__swig_setmethods__ = {}\n",NIL); + if (Len(base_class)) { + Printf(f_shadow,"%sfor _s in [%s]: __swig_setmethods__.update(_s.__swig_setmethods__)\n",tab4,base_class); + } + + Printv(f_shadow, + tab4, "__setattr__ = lambda self, name, value: _swig_setattr(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(_s.__swig_getmethods__)\n",tab4,base_class); + } + + Printv(f_shadow, + tab4, "__getattr__ = lambda self, name: _swig_getattr(self, ", class_name, ", name)\n", + NIL); + } + + /* Emit all of the members */ + + in_class = 1; + Language::classHandler(n); + in_class = 0; + + /* Complete the class */ + if (shadow) { + /* Generate a class registration function */ + { + SwigType *ct = NewStringf("p.%s", real_classname); + SwigType_remember(ct); + Printv(f_wrappers, + "static PyObject * ", class_name, "_swigregister(PyObject *self, PyObject *args) {\n", + tab4, "PyObject *obj;\n", + tab4, "if (!PyArg_ParseTuple(args,(char*)\"O\", &obj)) return NULL;\n", + tab4, "SWIG_TypeClientData(SWIGTYPE", SwigType_manglestr(ct),", obj);\n", + tab4, "Py_INCREF(obj);\n", + tab4, "return Py_BuildValue((char *)\"\");\n", + "}\n",NIL); + String *cname = NewStringf("%s_swigregister", class_name); + add_method(cname, cname, 0); + Delete(cname); + Delete(ct); + } + if (!have_constructor) { + Printv(f_shadow,tab4,"def __init__(self): raise RuntimeError, \"No constructor defined\"\n",NIL); + } + + if (!have_repr) { + /* Supply a repr method for this class */ + Printv(f_shadow, + tab4, "def __repr__(self):\n", + tab8, "return \"\" % (self.this,)\n", + NIL); + } + /* Now build the real class with a normal constructor */ + Printv(f_shadow, + "\nclass ", class_name, "Ptr(", class_name, "):\n", + tab4, "def __init__(self,this):\n", + tab8, "self.this = this\n", + tab8, "if not hasattr(self,\"thisown\"): self.thisown = 0\n", + // tab8,"try: self.this = this.this; self.thisown = getattr(this,'thisown',0); this.thisown=0\n", + // tab8,"except AttributeError: self.this = this\n" + tab8, "self.__class__ = ", class_name, "\n", + NIL); + + Printf(f_shadow,"%s.%s_swigregister(%sPtr)\n", module, class_name, class_name,0); + shadow_indent = 0; + Printf(f_shadow,"%s\n", f_shadow_stubs); + Clear(f_shadow_stubs); + } + classic = oldclassic; + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * 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 = (use_kw || Getattr(n,"feature:kwargs")) ? 1 : 0; + if (Strcmp(symname,"__repr__") == 0) + have_repr = 1; + + if (Getattr(n,"feature:shadow")) { + String *pycode = pythoncode(Getattr(n,"feature:shadow"),tab4); + Printv(f_shadow,pycode,"\n",NIL); + } else { + if (allow_kwargs && !Getattr(n,"sym:overloaded")) { + Printv(f_shadow,tab4, "def ", symname, "(*args, **kwargs): ", NIL); + Printv(f_shadow, "return apply(", module, ".", Swig_name_member(class_name,symname), ",args, kwargs)\n", NIL); + } else { + Printv(f_shadow, tab4, "def ", symname, "(*args): ", NIL); + Printv(f_shadow, "return apply(", module, ".", Swig_name_member(class_name,symname), ",args)\n",NIL); + } + } + } + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * staticmemberfunctionHandler() + * ------------------------------------------------------------ */ + + virtual int staticmemberfunctionHandler(Node *n) { + String *symname = Getattr(n,"sym:name"); + Language::staticmemberfunctionHandler(n); + if (shadow) { + Printv(f_shadow, tab4, "__swig_getmethods__[\"", symname, "\"] = lambda x: ", module, ".", Swig_name_member(class_name, symname), "\n", NIL); + if (!classic) { + Printv(f_shadow, tab4, "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; + + if (shadow) shadow = shadow | PYSHADOW_MEMBER; + Language::constructorHandler(n); + shadow = oldshadow; + + if (!Getattr(n,"sym:nextSibling")) { + if (shadow) { + int allow_kwargs = (use_kw || Getattr(n,"feature:kwargs")) ? 1 : 0; + if (!have_constructor) { + if (Getattr(n,"feature:shadow")) { + String *pycode = pythoncode(Getattr(n,"feature:shadow"),tab4); + Printv(f_shadow,pycode,"\n",NIL); + } else { + if ((allow_kwargs) && (!Getattr(n,"sym:overloaded"))) { + Printv(f_shadow, tab4, "def __init__(self,*args,**kwargs):\n", NIL); + Printv(f_shadow, tab8, "self.this = apply(", module, ".", Swig_name_construct(symname), ",args,kwargs)\n", NIL); + } else { + Printv(f_shadow, tab4, "def __init__(self,*args):\n",NIL); + Printv(f_shadow, tab8, "self.this = apply(", module, ".", Swig_name_construct(symname), ",args)\n", NIL); + } + Printv(f_shadow, + tab8, "self.thisown = 1\n", + NIL); + } + 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"),""); + Printv(f_shadow_stubs,pycode,"\n",NIL); + } else { + if ((allow_kwargs) && (!Getattr(n,"sym:overloaded"))) + Printv(f_shadow_stubs, "def ", symname, "(*args,**kwargs):\n", NIL); + else + Printv(f_shadow_stubs, "def ", symname, "(*args):\n", NIL); + + Printv(f_shadow_stubs, tab4, "val = apply(", NIL); + if ((allow_kwargs) && (!Getattr(n,"sym:overloaded"))) + Printv(f_shadow_stubs, module, ".", Swig_name_construct(symname), ",args,kwargs)\n", NIL); + else + Printv(f_shadow_stubs, module, ".", Swig_name_construct(symname), ",args)\n", NIL); + Printv(f_shadow_stubs,tab4, "val.thisown = 1\n", + tab4, "return val\n\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; + Language::destructorHandler(n); + shadow = oldshadow; + if (shadow) { + Printv(f_shadow, tab4, "def __del__(self, destroy= ", module, ".", Swig_name_destroy(symname), "):\n", NIL); + Printv(f_shadow, tab8, "try:\n", NIL); + Printv(f_shadow, tab4, tab8, "if self.thisown: destroy(self)\n", NIL); + Printv(f_shadow, tab8, "except: pass\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) { + int immutable = 0; + if (!Getattr(n,"feature:immutable")) { + Printv(f_shadow, tab4, "__swig_setmethods__[\"", symname, "\"] = ", module, ".", Swig_name_set(Swig_name_member(class_name,symname)), "\n", NIL); + } else { + immutable = 1; + } + Printv(f_shadow, tab4, "__swig_getmethods__[\"", symname, "\"] = ", module, ".", Swig_name_get(Swig_name_member(class_name,symname)),"\n", NIL); + + if (!classic) { + if (immutable) { + Printv(f_shadow,tab4,"if _newclass:", symname," = property(", module, ".", + Swig_name_get(Swig_name_member(class_name,symname)),")\n", NIL); + } else { + Printv(f_shadow,tab4,"if _newclass:", symname," = property(", + module, ".", Swig_name_get(Swig_name_member(class_name,symname)),",", + module, ".", Swig_name_set(Swig_name_member(class_name,symname)),")\n", NIL); + } + } + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * staticmembervariableHandler() + * ------------------------------------------------------------ */ + + virtual int staticmembervariableHandler(Node *n) { + String *symname; + SwigType *t; + + Language::staticmembervariableHandler(n); + if (shadow) { + t = Getattr(n,"type"); + symname = Getattr(n,"sym:name"); + if (SwigType_isconst(t) && !Getattr(n, "value")) { + Printf(f_shadow,"%s%s = %s.%s.%s\n", tab4, symname, module, global_name, Swig_name_member(class_name,symname)); + } + } + 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; + } + + /* ------------------------------------------------------------ + * pythoncode() - Output python code into the shadow file + * ------------------------------------------------------------ */ + + String *pythoncode(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 = DohSplit(temp,'\n',-1); + Delete(temp); + int initial = 0; + String *s; + + /* Get the initial indentation */ + for (s = Firstitem(clist); s; s = Nextitem(clist)) { + if (Len(s)) { + char *c = Char(s); + while (*c) { + if (!isspace(*c)) break; + initial++; + c++; + } + if (*c && !isspace(*c)) break; + else { + initial = 0; + } + } + } + while (s) { + if (Len(s) > initial) { + char *c = Char(s); + c += initial; + Printv(out,indent,c,"\n",NIL); + } else { + Printv(out,"\n",NIL); + } + s = Nextitem(clist); + } + Delete(clist); + return out; + } + + /* ------------------------------------------------------------ + * 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, "\n", NIL); + Delete(pycode); + } + } else { + Language::insertDirective(n); + } + return SWIG_OK; + } +}; + +/* ----------------------------------------------------------------------------- + * swig_python() - Instantiate module + * ----------------------------------------------------------------------------- */ + +extern "C" Language * +swig_python(void) { + return new PYTHON(); +} diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx new file mode 100644 index 000000000..f5f0a796a --- /dev/null +++ b/Source/Modules/ruby.cxx @@ -0,0 +1,1440 @@ +/******************************************************************** + * Ruby module for SWIG + * + * $Header$ + * + * Copyright (C) 2000 Network Applied Communication Laboratory, Inc. + * Copyright (C) 2000 Information-technology Promotion Agency, Japan + * + * Masaki Fukushima + * + ********************************************************************/ + +char cvsroot_ruby_cxx[] = "$Header$"; + +#include "swigmod.h" + +#ifndef MACSWIG +#include "swigconfig.h" +#endif + +#include +#include +#include /* 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 */ + String *vname; /* variable name */ + String *type; + String *prefix; + String *header; + String *init; + + int constructor_defined; + int destructor_defined; + + RClass() { + temp = NewString(""); + name = NewString(""); + cname = NewString(""); + mname = NewString(""); + vname = NewString(""); + type = NewString(""); + prefix = NewString(""); + header = NewString(""); + init = NewString(""); + constructor_defined = 0; + destructor_defined = 0; + } + + ~RClass() { + Delete(name); + Delete(cname); + Delete(vname); + Delete(mname); + Delete(type); + Delete(prefix); + Delete(header); + Delete(init); + Delete(temp); + } + + void set_name(const String_or_char *cn, const String_or_char *rn, const String_or_char *valn) { + Clear(cname); + Append(cname,cn); + Delete(mname); + mname = Swig_name_mangle(cname); + Clear(name); + Append(name,valn); + Clear(vname); + Printf(vname,"c%s.klass",name); + Clear(prefix); + Printv(prefix,(rn ? rn : cn), "_", NIL); + } + + char *strip(const String_or_char *s) { + Clear(temp); + Append(temp, s); + if (Strncmp(s, prefix, Len(prefix)) == 0) { + Replaceall(temp,prefix,""); + } + return Char(temp); + } +}; + + +#ifdef RUBY_SUPPORTS_KEYWORD_ARGS +static const char * +usage = "\ +Ruby Options (available with -ruby)\n\ + -ldflags - Print runtime libraries to link with\n\ + -feature name - Set feature name (used by `require')\n\ + -keyword - Use keyword arguments\n"; +#else +static const char * +usage = "\ +Ruby Options (available with -ruby)\n\ + -ldflags - Print runtime libraries to link with\n\ + -feature name - Set feature name (used by `require')\n"; +#endif + +#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; + int current; + Hash *classes; /* key=cname val=RClass */ + RClass *klass; /* Currently processing class */ + Hash *special_methods; /* Python style special method name table */ + File *f_runtime; + File *f_header; + File *f_wrappers; + File *f_init; + bool use_kw; + + // Wrap modes + enum { + NO_CPP, + MEMBER_FUNC, + CONSTRUCTOR_ALLOCATE, + CONSTRUCTOR_INITIALIZE, + DESTRUCTOR, + MEMBER_VAR, + CLASS_CONST, + STATIC_FUNC, + STATIC_VAR + }; + +public: + + /* --------------------------------------------------------------------- + * RUBY() + * + * Initialize member data + * --------------------------------------------------------------------- */ + + RUBY() { + module = 0; + modvar = 0; + feature = 0; + current = NO_CPP; + classes = 0; + klass = 0; + special_methods = 0; + f_runtime = 0; + f_header = 0; + f_wrappers = 0; + f_init = 0; + use_kw = false; + } + + /* --------------------------------------------------------------------- + * main() + * + * Parse command line options and initializes variables. + * --------------------------------------------------------------------- */ + + virtual void main(int argc, char *argv[]) { + + /* 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],"-feature") == 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],"-help") == 0) { + Printf(stderr,"%s\n", usage); + } else if (strcmp (argv[i],"-ldflags") == 0) { + printf("%s\n", SWIG_RUBY_RUNTIME); + SWIG_exit (EXIT_SUCCESS); + } else if (strcmp(argv[i],"-keyword") == 0) { + use_kw = true; + Swig_mark_arg(i); + } + } + } + + /* 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(); + } + + /* --------------------------------------------------------------------- + * top() + * --------------------------------------------------------------------- */ + + virtual int top(Node *n) { + + /* Initialize all of the output files */ + String *outfile = Getattr(n,"outfile"); + + f_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + 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("runtime",f_runtime); + Swig_register_filebyname("init",f_init); + + modvar = 0; + current = NO_CPP; + klass = 0; + classes = NewHash(); + special_methods = NewHash(); + + /* Python 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"); + + Swig_banner(f_runtime); + + if (NoInclude) { + Printf(f_runtime, "#define SWIG_NOINCLUDE\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"))); + + 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 */ + Printv(f_init, + "\n", + "#ifdef __cplusplus\n", + "extern \"C\"\n", + "#endif\n", + "void Init_", feature, "(void) {\n", + "int i;\n", + "\n", + NIL); + + Printv(f_init, tab4, "SWIG_InitRuntime();\n", NIL); + + /* Account for nested modules */ + List *modules = Split(module,':',INT_MAX); + if (modules != 0 && Len(modules) > 0) { + String *mv = 0; + String *m = Firstitem(modules); + while (m != 0) { + if (Len(m) > 0) { + if (mv != 0) { + Printv(f_init, tab4, modvar, + " = rb_define_module_under(", modvar, ", \"", m, "\");\n", NIL); + } else { + Printv(f_init, tab4, modvar, + " = rb_define_module(\"", m, "\");\n", NIL); + mv = NewString(modvar); + } + } + m = Nextitem(modules); + } + Delete(mv); + Delete(modules); + } + + Printv(f_init, + "\n", + "for (i = 0; swig_types_initial[i]; i++) {\n", + "swig_types[i] = SWIG_TypeRegister(swig_types_initial[i]);\n", + "SWIG_define_class(swig_types[i]);\n", + "}\n", + NIL); + Printf(f_init,"\n"); + + Language::top(n); + + /* Finish off our init function */ + Printf(f_init,"}\n"); + SwigType_emit_type_table(f_runtime,f_wrappers); + + /* Close all of the files */ + Dump(f_header,f_runtime); + Dump(f_wrappers,f_runtime); + Wrapper_pretty_print(f_init,f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + Delete(f_runtime); + return SWIG_OK; + } + + /* ----------------------------------------------------------------------------- + * importDirective() + * ----------------------------------------------------------------------------- */ + + virtual int importDirective(Node *n) { + String *modname = Getattr(n,"module"); + if (modname) { + Printf(f_init,"rb_require(\"%s\");\n", modname); + } + 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(""); + + /* Account for nested modules */ + List *modules = Split(mod_name,':',INT_MAX); + if (modules != 0 && Len(modules) > 0) { + String *last = 0; + String *m = Firstitem(modules); + while (m != 0) { + if (Len(m) > 0) { + String *cap = NewString(m); + (Char(cap))[0] = toupper((Char(cap))[0]); + if (last != 0) { + Append(module, "::"); + } + Append(module, cap); + last = m; + } + m = Nextitem(modules); + } + if (feature == 0) { + feature = Copy(last); + } + (Char(last))[0] = 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; + } + + /* --------------------------------------------------------------------- + * create_command(Node *n, char *iname) + * + * Creates a new command from a C function. + * iname = Name of function in scripting language + * --------------------------------------------------------------------- */ + + void create_command(Node *n, const String_or_char *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(""); + + switch (current) { + case MEMBER_FUNC: + Printv(klass->init, tab4, "rb_define_method(", klass->vname, ", \"", + iname, "\", ", wname, ", -1);\n", NIL); + break; + case CONSTRUCTOR_ALLOCATE: + Printv(s, tab4, "rb_define_singleton_method(", klass->vname, + ", \"new\", ", wname, ", -1);\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); + Replaceall(temp,"_set", "="); + Replaceall(temp,"_get", ""); + 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; + default: + Printv(s, tab4, "rb_define_module_function(", modvar, ", \"", + iname, "\", ", wname, ", -1);\n",NIL); + Printv(f_init,s,NIL); + break; + } + + /* Process the comma-separated list of aliases (if any) */ + String *aliasv = Getattr(n,"feature:alias"); + if (aliasv) { + List *aliases = Split(aliasv,',',INT_MAX); + if (aliases && Len(aliases) > 0) { + String *alias = Firstitem(aliases); + while (alias) { + if (Len(alias) > 0) { + Printv(klass->init, tab4, "rb_define_alias(", klass->vname, ", \"", alias, "\", \"", iname, "\");\n", NIL); + } + alias = Nextitem(aliases); + } + } + Delete(aliases); + } + + Delete(temp); + Delete(s); + Delete(wname); + } + + /* --------------------------------------------------------------------- + * marshalInputArgs(int numarg, int numreq, int start, 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 marshalInputArgs(ParmList *l, int numarg, int numreq, int start, String *kwargs, bool allow_kwargs, Wrapper *f) { + int i; + Parm *p; + String *tm; + char source[256], target[256]; + + int use_self = (current == MEMBER_FUNC || current == MEMBER_VAR) ? 1 : 0; + int varargs = emit_isvarargs(l); + + Printf(kwargs,"{ "); + for (i = 0, p = l; i < numarg; i++) { + + /* Skip ignored arguments */ + 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"); + + /* Produce string representation of source and target arguments */ + int selfp = (use_self && i == 0); + if (selfp) + strcpy(source,"self"); + else + sprintf(source,"argv[%d]",i-start); + + sprintf(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 */ + if ((tm = Getattr(p,"tmap:in"))) { + Replaceall(tm,"$target",ln); + Replaceall(tm,"$source",source); + Replaceall(tm,"$input",source); + Setattr(p,"emit:input",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); + } + 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"))) { + sprintf(source,"argv[%d]",i-start); + Replaceall(tm,"$input",source); + Setattr(p,"emit:input",source); + Printf(f->code,"if (argc > %d) {\n", i-start); + Printv(f->code,tm,"\n",NIL); + Printf(f->code,"}\n"); + } + } + } + + /* --------------------------------------------------------------------- + * 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"))) { + Replaceall(tm,"$source",Getattr(p,"lname")); + Printv(cleanup,tm,"\n",NIL); + p = Getattr(p,"tmap:freearg:next"); + } else { + p = nextSibling(p); + } + } + } + + /* --------------------------------------------------------------------- + * insertCleanupCode(ParmList *l, String *cleanup) + * + * 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, + * "mutators" 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 *symname = Copy(Getattr(n,"sym:name")); + SwigType *t = Getattr(n,"type"); + ParmList *l = Getattr(n,"parms"); + String *tm; + + int need_result = 0; + + /* Ruby needs no destructor wrapper */ + if (current == DESTRUCTOR) + return SWIG_NOWRAP; + + /* 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 (Getattr(n, "feature:predicate")) { + 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_args(t,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 = use_kw || Getattr(n,"feature:kwargs"); + + int start = (current == MEMBER_FUNC || current == MEMBER_VAR) ? 1 : 0; + + /* Now write the wrapper function itself */ + Printv(f->def, "static VALUE\n", wname, "(int argc, VALUE *argv, VALUE self) {", NIL); + + if (current != CONSTRUCTOR_ALLOCATE) { + if (!varargs) { + Printf(f->code,"if ((argc < %d) || (argc > %d))\n", numreq-start, numarg-start); + } else { + Printf(f->code,"if (argc < %d)\n", numreq-start); + } + Printf(f->code,"rb_raise(rb_eArgError, \"wrong # of arguments(%%d for %d)\",argc);\n",numreq-start); + } + + /* Now walk the function parameter list and generate code */ + /* to get arguments */ + if (current != CONSTRUCTOR_ALLOCATE) { + marshalInputArgs(l, numarg, numreq, start, kwargs, allow_kwargs, f); + } + + /* Insert constraint checking code */ + insertConstraintCheckingCode(l, f); + + /* Insert cleanup code */ + insertCleanupCode(l, cleanup); + + /* Insert argument output code */ + insertArgOutputCode(l, outarg, need_result); + + /* Now write code to make the function call */ + if (current != CONSTRUCTOR_ALLOCATE) { + if (current == CONSTRUCTOR_INITIALIZE) { + String *action = Getattr(n,"wrap:action"); + if (action) { + Append(action,"DATA_PTR(self) = result;"); + } + } + emit_action(n,f); + } + + int newobj = 0; + if (Getattr(n,"feature:new")) newobj = 1; + + /* Return value if necessary */ + if (SwigType_type(t) != T_VOID && current != CONSTRUCTOR_ALLOCATE && current != CONSTRUCTOR_INITIALIZE) { + need_result = 1; + if (Getattr(n, "feature:predicate")) { + Printv(f->code, tab4, "vresult = (result ? Qtrue : Qfalse);\n", NIL); + } else { + tm = Swig_typemap_lookup_new("out",n,"result",0); + if (tm) { + Replaceall(tm,"$result","vresult"); + Replaceall(tm,"$source","result"); + Replaceall(tm,"$target","vresult"); + Replaceall(tm,"$owner", newobj ? "1" : "0"); + Printv(f->code, tm, "\n", NIL); + } else { + Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, + "Unable to use return type %s.\n", SwigType_str(t,0)); + } + } + } + + /* 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, "rb_obj_call_init(vresult, argc, argv);\n"); + } else if (current == CONSTRUCTOR_INITIALIZE) { + need_result = 1; + // Printf(f->code, "DATA_PTR(self) = result;\n"); + } + + /* Dump argument output code; */ + Printv(f->code,outarg,NIL); + + /* Dump the argument cleanup code */ + if (current != CONSTRUCTOR_ALLOCATE) + Printv(f->code,cleanup,NIL); + + /* Look for any remaining cleanup. This processes the %new directive */ + if (newobj) { + tm = Swig_typemap_lookup_new("newfree",n,"result",0); + if (tm) { + Replaceall(tm,"$source","result"); + Printv(f->code,tm, "\n",NIL); + } + } + + /* Special processing on return value. */ + tm = Swig_typemap_lookup_new("ret",n,"result",0); + if (tm) { + Replaceall(tm,"$source","result"); + Printv(f->code,tm, NIL); + } + + /* Wrap things up (in a manner of speaking) */ + if (need_result) { + if (current == CONSTRUCTOR_ALLOCATE) { + Printv(f->code, tab4, "return vresult;\n}\n", NIL); + } else if (current == CONSTRUCTOR_INITIALIZE) { + Printv(f->code, tab4, "return self;\n}\n", NIL); + } else { + Wrapper_add_local(f,"vresult","VALUE vresult = Qnil"); + Printv(f->code, tab4, "return vresult;\n}\n", NIL); + } + } else { + Printv(f->code, tab4, "return Qnil;\n}\n", NIL); + } + + /* Substitute the cleanup code */ + Replaceall(f->code,"$cleanup",cleanup); + + /* 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 { + Setattr(n, "wrap:name", wname); + 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, + "static VALUE ", wname, + "(int nargs, VALUE *args, VALUE self) {", + NIL); + + Wrapper_add_local(f, "argc", "int argc"); + if (current == MEMBER_FUNC || current == MEMBER_VAR) { + 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) { + Printf(f->code, "argc = nargs + 1;\n"); + Printf(f->code, "argv[0] = self;\n"); + Printf(f->code, "for (ii = 1; (ii < argc) && (ii < %d); ii++) {\n", maxargs); + Printf(f->code, "argv[ii] = args[ii-1];\n"); + Printf(f->code, "}\n"); + } else { + Printf(f->code, "argc = nargs;\n"); + Printf(f->code, "for (ii = 0; (ii < argc) && (ii < %d); ii++) {\n", maxargs); + Printf(f->code, "argv[ii] = args[ii];\n"); + Printf(f->code, "}\n"); + } + + Replaceall(dispatch, "$args", "nargs, args, self"); + Printv(f->code, dispatch, "\n", NIL); + Printf(f->code, "rb_raise(rb_eArgError, \"No matching function for overloaded '%s'\");\n", symname); + Printf(f->code,"return Qnil;\n"); + 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) { + + 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 */ + getfname = NewString(Swig_name_get(iname)); + Printv(getf->def, "static VALUE\n", getfname, "(", NIL); + Printf(getf->def, "VALUE self"); + Printf(getf->def, ") {"); + Wrapper_add_local(getf,"_val","VALUE _val"); + + tm = Swig_typemap_lookup_new("varout",n, name, 0); + if (tm) { + Replaceall(tm,"$result","_val"); + Replaceall(tm,"$target","_val"); + Replaceall(tm,"$source",name); + Printv(getf->code,tm, NIL); + } 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}\n", NIL); + Wrapper_print(getf,f_wrappers); + + if (Getattr(n,"feature:immutable")) { + setfname = NewString("NULL"); + } else { + /* create setter */ + setfname = NewString(Swig_name_set(iname)); + Printv(setf->def, "static VALUE\n", setfname, "(VALUE self, ", NIL); + Printf(setf->def, "VALUE _val) {"); + + tm = Swig_typemap_lookup_new("varin",n,name,0); + if (tm) { + Replaceall(tm,"$input","_val"); + Replaceall(tm,"$source","_val"); + Replaceall(tm,"$target",name); + Printv(setf->code,tm,"\n",NIL); + } 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,"}\n"); + Wrapper_print(setf,f_wrappers); + } + + /* 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 (!Getattr(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 */ + Printv(s, + tab4, "rb_define_singleton_method(", modvar, ", \"", + iname, "\", ", getfname, ", 0);\n", + NIL); + if (!Getattr(n,"feature:immutable")) { + Printv(s, + tab4, "rb_define_singleton_method(", modvar, ", \"", + iname, "=\", ", setfname, ", 1);\n", + NIL); + } + Printv(f_init,s,NIL); + Delete(s); + break; + } + 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] = 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\n", reason); + + return name; + } + + /* --------------------------------------------------------------------- + * constantWrapper() + * --------------------------------------------------------------------- */ + + virtual int constantWrapper(Node *n) { + Swig_require(&n, "*sym:name", "type", "value", NIL); + + char *iname = GetChar(n,"sym:name"); + SwigType *type = Getattr(n,"type"); + char *value = GetChar(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_new("constant", 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) { + Replaceall(tm, "$module", klass->vname); + Printv(klass->init, tm, "\n", NIL); + } else { + Replaceall(tm,"$module", modvar); + 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) { + 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); + } + + /* ---------------------------------------------------------------------- + * classHandler() + * ---------------------------------------------------------------------- */ + + virtual int classHandler(Node *n) { + + 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); + 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(klass->header, "\nswig_class c", valid_name, ";\n", NIL); + Printv(klass->init, "\n", tab4, NIL); + Printv(klass->init, klass->vname, " = rb_define_class_under(", modvar, + ", \"", klass->name, "\", $super);\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 *) &c%s);\n", tm, valid_name); + Delete(tm); + Delete(tt); + Delete(valid_name); + + /* Process the comma-separated list of mixed-in module names (if any) */ + String *mixin = Getattr(n,"feature:mixin"); + if (mixin) { + List *modules = Split(mixin,',',INT_MAX); + if (modules && Len(modules) > 0) { + String *mod = Firstitem(modules); + while (mod) { + if (Len(mod) > 0) { + Printf(klass->init, "rb_include_module(%s, rb_eval_string(\"%s\"));\n", klass->vname, mod); + } + mod = Nextitem(modules); + } + } + Delete(modules); + } + + Printv(klass->init, "$allocator",NIL); + Printv(klass->init, "$initializer",NIL); + + Printv(klass->header, + "$freeproto", + NIL); + + Language::classHandler(n); + + /* Handle inheritance */ + List *baselist = Getattr(n,"bases"); + if (baselist && Len(baselist)) { + Node *base = Firstitem(baselist); + String *basename = Getattr(base,"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); + String *bmangle = SwigType_manglestr(btype); + Insert(bmangle,0,"((swig_class *) SWIGTYPE"); + Append(bmangle,"->clientdata)->klass"); + Replaceall(klass->init,"$super",bmangle); + Delete(bmangle); + Delete(btype); + } + + /* Warn about multiple inheritance if additional base class(es) listed */ + base = Nextitem(baselist); + while (base) { + basename = Getattr(n,"name"); + Swig_warning(WARN_RUBY_MULTIPLE_INHERITANCE, input_file, line_number, + "Warning for %s: Base %s ignored. Multiple inheritance is not supported in Ruby.\n", basename, basename); + base = Nextitem(baselist); + } + } + + /* Check to see if a %markfunc was specified */ + String *markfunc = Getattr(n, "feature:markfunc"); + if (markfunc) { + Printf(klass->init, "c%s.mark = (void (*)(void *)) %s;\n", klass->name, markfunc); + } else { + Printf(klass->init, "c%s.mark = 0;\n", klass->name); + } + + /* Check to see if a %freefunc was specified */ + String *freefunc = Getattr(n, "feature:freefunc"); + if (freefunc) { + Printf(klass->init, "c%s.destroy = (void (*)(void *)) %s;\n", klass->name, freefunc); + } else { + if (klass->destructor_defined) { + Printf(klass->init, "c%s.destroy = (void (*)(void *)) free_%s;\n", klass->name, klass->mname); + } + } + Replaceall(klass->header,"$freeproto", ""); + + Printv(f_header, klass->header,NIL); + + String *s = NewString(""); + Printv(s, tab4, "rb_undef_method(CLASS_OF(", klass->vname, + "), \"new\");\n", NIL); + Replaceall(klass->init,"$allocator", s); + Replaceall(klass->init,"$initializer", ""); + 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; + Language::memberfunctionHandler(n); + current = NO_CPP; + return SWIG_OK; + } + + /* --------------------------------------------------------------------- + * constructorHandler() + * + * Method for adding C++ member constructor + * -------------------------------------------------------------------- */ + + virtual int constructorHandler(Node *n) { + /* First wrap the new singleton method */ + current = CONSTRUCTOR_ALLOCATE; + Swig_name_register((String_or_char *) "construct", (String_or_char *) "%c_allocate"); + Language::constructorHandler(n); + + /* Now do the instance initialize method */ + current = CONSTRUCTOR_INITIALIZE; + Swig_name_register((String_or_char *) "construct", (String_or_char *) "new_%c"); + Language::constructorHandler(n); + + /* Done */ + Swig_name_unregister((String_or_char *) "construct"); + current = NO_CPP; + klass->constructor_defined = 1; + return SWIG_OK; + } + + /* --------------------------------------------------------------------- + * destructorHandler() + * -------------------------------------------------------------------- */ + + virtual int destructorHandler(Node *n) { + current = DESTRUCTOR; + Language::destructorHandler(n); + + String *freefunc = NewString(""); + String *freeproto = NewString(""); + String *freebody = NewString(""); + + Printv(freefunc, "free_", klass->mname, NIL); + Printv(freeproto, "static void ", freefunc, "(", klass->type, " *);\n", NIL); + Printv(freebody, "static void\n", + freefunc, "(", klass->type, " *", Swig_cparm_name(0,0), ") {\n", + tab4, NIL); + if (Extend) { + String *wrap = Getattr(n, "wrap:code"); + if (wrap) { + File *f_code = Swig_filebyname("header"); + if (f_code) { + Printv(f_code, wrap, NIL); + } + } + /* Printv(freebody, Swig_name_destroy(name), "(", Swig_cparm_name(0,0), ")", NIL); */ + Printv(freebody,Getattr(n,"wrap:action"), NIL); + } else { + /* When no extend mode, swig emits no destroy function. */ + if (CPlusPlus) + Printf(freebody, "delete %s", Swig_cparm_name(0,0)); + else + Printf(freebody, "free((char*) %s)", Swig_cparm_name(0,0)); + } + Printv(freebody, ";\n}\n", NIL); + + Replaceall(klass->header,"$freeproto", freeproto); + Printv(f_wrappers, freebody, NIL); + + klass->destructor_defined = 1; + current = NO_CPP; + Delete(freefunc); + Delete(freeproto); + Delete(freebody); + return SWIG_OK; + } + + /* --------------------------------------------------------------------- + * membervariableHandler() + * + * This creates a pair of functions to set/get the variable of a member. + * -------------------------------------------------------------------- */ + + virtual int + membervariableHandler(Node *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; + Language::memberconstantHandler(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; + } + +}; /* class RUBY */ + +/* ----------------------------------------------------------------------------- + * swig_ruby() - Instantiate module + * ----------------------------------------------------------------------------- */ + +extern "C" Language * +swig_ruby(void) { + return new 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 000000000..2a9f2dcc1 --- /dev/null +++ b/Source/Modules/s-exp.cxx @@ -0,0 +1,401 @@ +/* ----------------------------------------------------------------------------- + * s-exp.cxx + * + * A parse tree represented as Lisp s-expressions. + * + * Author(s) : Matthias Koeppe (mkoeppe@mail.math.uni-magdeburg.de) + * + * Copyright (C) 2002. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +/* Derived from xml.cxx 1.1.2.2 */ + +char cvsroot_s_exp_cxx[] = "$Header$"; +static const char *usage = "\ +S-Exp Options (available with -sexp)\n\ + -typemaplang lang - Typemap language.\n\n"; + +#include "swigmod.h" + +//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[]) { + 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, stderr ); + } + } + } + + 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"); + out = NewFile(outfile,"w"); + if (!out) + { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + } + Language::top(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 need_newline = false) + { + hanging_parens++; + if (need_newline) + print_lazy_whitespace(); + indent_level -= 2; + } + + void flush_parens() + { + int i; + if (hanging_parens) { + for (i = 0; i", 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 */ + String *k; + bool first; + for (k = Firstkey(obj), first = true; k; k = Nextkey(obj), first=false) { + if (!internal_key_p(k)) { + DOH *value = Getattr(obj, k); + flush_parens(); + if (!first) { + Printf(out, " "); + } + Sexp_print_as_keyword(k); + /* Print value */ + Sexp_print_value_of_key(value, k); + } + } + } + + 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); + return SWIG_OK; + } + +}; + + +extern "C" +{ + Language * swig_sexp( void ) + { + return new Sexp(); + } +} diff --git a/Source/Modules/swigmain.cxx b/Source/Modules/swigmain.cxx new file mode 100644 index 000000000..2048bb82c --- /dev/null +++ b/Source/Modules/swigmain.cxx @@ -0,0 +1,153 @@ +/******************************************************************************* + * 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. + * + * Author : David Beazley + * + * Department of Computer Science + * University of Chicago + * 1100 E 58th Street + * Chicago, IL 60637 + * beazley@cs.uchicago.edu + * + * Please read the file LICENSE for the copyright and terms by which SWIG + * can be used and distributed. + *******************************************************************************/ + +char cvsroot_swigmain_cxx[] = "$Header$"; + +#ifndef MACSWIG +#include "swigconfig.h" +#endif + +#include "swigmod.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_mzscheme(void); + Language *swig_java(void); + Language *swig_php(void); + Language *swig_ocaml(void); + Language *swig_pike(void); + Language *swig_sexp(void); + Language *swig_xml(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. */ + +swig_module modules[] = { + {"-guile", swig_guile, "Guile"}, + {"-java", swig_java, "Java"}, + {"-mzscheme", swig_mzscheme, "Mzscheme"}, + {"-ocaml", swig_ocaml, "Ocaml"}, + {"-perl", swig_perl5, "Perl"}, + {"-perl5", swig_perl5, 0}, + {"-php", swig_php, "PHP"}, + {"-php4", swig_php, 0}, + {"-pike", swig_pike, "Pike"}, + {"-python", swig_python, "Python"}, + {"-ruby", swig_ruby, "Ruby"}, + {"-sexp", swig_sexp, "Lisp S-Expressions"}, + {"-tcl", swig_tcl, "Tcl"}, + {"-tcl8", swig_tcl, 0}, + {"-xml", swig_xml, "XML"}, + {NULL, NULL, NULL} +}; + +#ifdef MACSWIG +#include +#include +#endif + +#ifndef SWIG_LANG +#define SWIG_LANG "-python" +#endif + +//----------------------------------------------------------------- +// main() +// +// Main program. Initializes the files and starts the parser. +//----------------------------------------------------------------- + + +int main(int argc, char **argv) { + int i; + Language *dl = 0; + ModuleFactory fac = 0; + + extern int SWIG_main(int, char **, Language *); + +#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) { + Printf(stderr,"Target Language Options:\n"); + for (int j = 0; modules[j].name; j++) { + if (modules[j].help) { + Printf(stderr," %-15s - Generate %s wrappers.\n", modules[j].name, modules[j].help); + } + } + Swig_mark_arg(i); + } + } + } + if (!dl) { + fac = Swig_find_module(SWIG_LANG); + if (fac) { + dl = (fac)(); + } + } + return SWIG_main(argc,argv,dl); +} + diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h new file mode 100644 index 000000000..2668b0cb5 --- /dev/null +++ b/Source/Modules/swigmod.h @@ -0,0 +1,255 @@ +/* ----------------------------------------------------------------------------- + * swigmod.h + * + * Main header file for SWIG modules + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1998-2000. The University of Chicago + * Copyright (C) 1995-1998. The University of Utah and The Regents of the + * University of California. + * + * See the file LICENSE for information on usage and redistribution. + * + * $Header$ + * ----------------------------------------------------------------------------- */ + +#include +#include +#include + +#include "swigver.h" + +extern "C" { +#include "swig.h" +extern Hash *Preprocessor_define(const String_or_char *str, int swigmacro); +} + +#include "swigwarn.h" + +#define NOT_VIRTUAL 0 +#define PLAIN_VIRTUAL 1 +#define PURE_VIRTUAL 2 + +extern char *input_file; +extern int line_number; +extern int start_line; +extern int CPlusPlus; // C++ mode +extern int Extend; // Extend mode +extern int NoInclude; // NoInclude flag +extern int Verbose; +extern int IsVirtual; +extern int ImportMode; +extern int NoExcept; // -no_except option + +/* Miscellaneous stuff */ + +#define tab2 " " +#define tab4 " " +#define tab8 " " + +class Dispatcher { + public: + + 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 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); +}; + +/************************************************************************ + * 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 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); + + /* Miscellaneous */ + + virtual int validIdentifier(String *s); /* valid identifier? */ + virtual int addSymbol(String *s, Node *n); /* Add symbol */ + virtual Node *symbolLookup(String *s); /* Symbol lookup */ + virtual Node *classLookup(SwigType *s); /* Class lookup */ + + protected: + /* Patch C++ pass-by-value */ + static void patch_parms(Parm *p); + + /* Allow overloaded functions */ + void allow_overloading(int val = 1); + + /* Allow multiple-input typemaps */ + void allow_multiple_input(int val = 1); + + /* Wrapping class query */ + int is_wrapping_class(); + + /* Return the node for the current class */ + Node *getCurrentClass() const; + + /* Return the real name of the current class */ + String *getClassName() const; + + /* Return the current class prefix */ + String *getClassPrefix() const; + + /* Fully qualified type name to use */ + String *getClassType() const; + + private: + Hash *symbols; + Hash *classtypes; + int overloading; + int multiinput; +}; + +extern int SWIG_main(int, char **, Language *); +extern void emit_args(SwigType *, ParmList *, Wrapper *f); +extern void SWIG_exit(int); /* use EXIT_{SUCCESS,FAILURE} */ +extern void SWIG_config_file(const String_or_char *); +extern void SWIG_config_cppext(const char *ext); + +extern "C" void SWIG_typemap_lang(const char *); +extern void SWIG_library_directory(const char *); +extern int emit_num_arguments(ParmList *); +extern int emit_num_required(ParmList *); +extern int emit_isvarargs(ParmList *); +extern void emit_attach_parmmaps(ParmList *, Wrapper *f); +extern void emit_action(Node *n, Wrapper *f); +extern List *Swig_overload_rank(Node *n); +extern String *Swig_overload_dispatch(Node *n, const String_or_char *fmt, int *); + + +extern "C" { + typedef Language *(*ModuleFactory)(void); +} + +extern void Swig_register_module(const char *name, ModuleFactory fac); +extern ModuleFactory Swig_find_module(const char *name); + +/* swig11.h ends here */ + + + + + + + + + diff --git a/Source/Modules/tcl8.cxx b/Source/Modules/tcl8.cxx new file mode 100644 index 000000000..0f9738715 --- /dev/null +++ b/Source/Modules/tcl8.cxx @@ -0,0 +1,832 @@ +/* ----------------------------------------------------------------------------- + * tcl8.cxx + * + * Tcl8.0 wrapper module. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_tcl8_cxx[] = "$Header$"; + +#include "swigmod.h" + +#ifndef MACSWIG +#include "swigconfig.h" +#endif + +static const char *usage = (char*)"\ +Tcl 8 Options (available with -tcl)\n\ + -ldflags - Print runtime libraries to link with\n\ + -prefix name - Set a prefix to be appended 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 int have_destructor; +static String *destructor_action = 0; +static String *version = (String *) "0.0"; +static String *class_name = 0; + +static File *f_header = 0; +static File *f_wrappers = 0; +static File *f_init = 0; +static File *f_runtime = 0; + +class TCL8 : public Language { +public: + + /* ------------------------------------------------------------ + * TCL8::main() + * ------------------------------------------------------------ */ + + virtual void main(int argc, char *argv[]) { + + SWIG_library_directory("tcl"); + + for (int i = 1; i < argc; i++) { + if (argv[i]) { + if (strcmp(argv[i],"-prefix") == 0) { + if (argv[i+1]) { + prefix = NewString(argv[i+1]); + Swig_mark_arg(i); + Swig_mark_arg(i+1); + i++; + } else Swig_arg_error(); + } else if (strcmp(argv[i],"-pkgversion") == 0) { + if (argv[i+1]) { + version = NewString(argv[i+1]); + Swig_mark_arg(i); + Swig_mark_arg(i+1); + i++; + } + } else if (strcmp(argv[i],"-namespace") == 0) { + nspace = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-help") == 0) { + fputs(usage,stderr); + } else if (strcmp (argv[i], "-ldflags") == 0) { + printf("%s\n", SWIG_TCL_RUNTIME); + SWIG_exit (EXIT_SUCCESS); + } + } + } + Preprocessor_define("SWIGTCL 1",0); + 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_runtime = NewFile(outfile,"w"); + if (!f_runtime) { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + 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("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_runtime); + + /* Include a Tcl configuration file */ + if (NoInclude) { + Printf(f_runtime,"#define SWIG_NOINCLUDE\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,"_"); + + /* 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"); + + /* Close all of the files */ + Printv(f_runtime, f_header, f_wrappers,NIL); + Wrapper_pretty_print(f_init,f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Close(f_runtime); + 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(); + String *wname = Swig_name_wrapper(iname); + if (overname) { + Append(wname, overname); + } + Setattr(n,"wrap:name",wname); + + Printv(f->def, + "static int\n ", wname, "(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {", + NIL); + + /* Print out variables for storing arguments. */ + emit_args(type,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,",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,",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 ((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 = parms; p;i++) { + if ((tm = Getattr(p,"tmap:argout"))) { + Replaceall(tm,"$source",Getattr(p,"lname")); + Replaceall(tm,"$target","(Tcl_GetObjResult(interp))"); + Replaceall(tm,"$result","(Tcl_GetObjResult(interp))"); + 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 */ + emit_action(n,f); + + /* Need to redo all of this code (eventually) */ + + /* Return value if necessary */ + if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) { + Replaceall(tm,"$source", "result"); + Replaceall(tm,"$target", "Tcl_GetObjResult(interp)"); + Replaceall(tm,"$result", "Tcl_GetObjResult(interp)"); + 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); + } + + /* 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 (Getattr(n,"feature:new")) { + if ((tm = Swig_typemap_lookup_new("newfree",n,"result",0))) { + Replaceall(tm,"$source","result"); + Printf(f->code,"%s\n", tm); + } + } + + if ((tm = Swig_typemap_lookup_new("ret",n,"result",0))) { + Replaceall(tm,"$source","result"); + Printf(f->code,"%s\n", tm); + } + 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, objv);",&maxargs); + + /* Generate a dispatch wrapper for all overloaded functions */ + + Wrapper *df = NewWrapper(); + String *dname = Swig_name_wrapper(iname); + + Printv(df->def, + "static int\n", dname, + "(ClientData clientData, 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 *getname = 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 */ + getf = NewWrapper(); + getname = Swig_name_wrapper(Swig_name_get(iname)); + Printv(getf->def,"static char *",getname,"(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) {",NIL); + Wrapper_add_local(getf,"value", "Tcl_Obj *value = 0"); + + if ((tm = Swig_typemap_lookup_new("varout",n,name,0))) { + Replaceall(tm,"$source", name); + Replaceall(tm,"$target","value"); + Replaceall(tm,"$result", "value"); + Printf(getf->code, "%s\n",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"); + Printf(getf->code,"}\n"); + Wrapper_print(getf,f_wrappers); + } else { + Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, + "Can't link to 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 (!Getattr(n,"feature:immutable")) { + setf = NewWrapper(); + setname = Swig_name_wrapper(Swig_name_set(iname)); + Printv(setf->def,"static char *",setname, "(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, 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_new("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) return NULL;\n"); + Printf(setf->code,"%s\n", tm); + Printf(setf->code,"return NULL;\n"); + Printf(setf->code,"}\n"); + if (setf) Wrapper_print(setf,f_wrappers); + } else { + Swig_warning(WARN_TYPEMAP_VARIN_UNDEF,input_file, line_number, + "Variable %s will be read-only without a varin typemap.\n", name); + readonly = 1; + } + DelWrapper(setf); + } + + Printv(var_tab, tab4,"{ SWIG_prefix \"", iname, "\", 0, (swig_variable_func) ", getname, ",", NIL); + if (readonly || Getattr(n,"feature:immutable")) { + static int readonlywrap = 0; + if (!readonlywrap) { + Wrapper *ro = NewWrapper(); + Printf(ro->def, "static const char *swig_readonly(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) {"); + Printv(ro->code, "return (char*) \"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) ", setname, "},\n",NIL); + } + Delete(setname); + Delete(getname); + 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 *value = 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_new("consttab",n,name,0))) { + Replaceall(tm,"$source",value); + Replaceall(tm,"$target",name); + Replaceall(tm,"$value",value); + Printf(const_tab,"%s,\n", tm); + } else if ((tm = Swig_typemap_lookup_new("constcode", n, name, 0))) { + Replaceall(tm,"$source", value); + Replaceall(tm,"$target", name); + Replaceall(tm,"$value",value); + 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; + } + + /* ------------------------------------------------------------ + * 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) { + + String *mangled_classname = 0; + String *real_classname = 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); + + 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, "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, 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(""); + List *baselist = Getattr(n,"bases"); + if (baselist && Len(baselist)) { + Node *base = Firstitem(baselist); + while (base) { + String *bname = Getattr(base, "name"); + if ((!bname) || Getattr(base,"feature:ignore") || (!Getattr(base,"module"))) { + base = Nextitem(baselist); + continue; + } + String *bmangle = Swig_name_mangle(bname); + Printv(f_wrappers,"extern swig_class _wrap_class_", bmangle, ";\n", NIL); + Printf(base_class,"&_wrap_class_%s",bmangle); + base = Nextitem(baselist); + Putc(',',base_class); + Delete(bmangle); + } + } + + Printv(f_wrappers,"static swig_class *swig_",mangled_classname,"_bases[] = {", base_class,"0};\n", NIL); + Delete(base_class); + + Printv(f_wrappers, "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(class_name))); + } 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 };\n", NIL); + Printv(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"); + + 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); + } + 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 (!Getattr(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"); + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * constructorHandler() + * ------------------------------------------------------------ */ + + virtual int constructorHandler(Node *n) { + Language::constructorHandler(n); + 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 = ParmList_len(l); + numopt = 0; /*check_numopt(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); + } +}; + +/* ---------------------------------------------------------------------- + * swig_tcl() - Instantiate module + * ---------------------------------------------------------------------- */ + +extern "C" Language * +swig_tcl(void) { + return new TCL8(); +} + + + + diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx new file mode 100644 index 000000000..3e4f74338 --- /dev/null +++ b/Source/Modules/typepass.cxx @@ -0,0 +1,966 @@ +/* ----------------------------------------------------------------------------- + * 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. + * + * This module also handles the %varargs directive by looking for + * "feature:varargs" and substituting ... with an alternative set of + * arguments. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1998-2002. The University of Chicago + * Copyright (C) 1995-1998. The University of Utah and The Regents of the + * University of California. + * + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_typepass_cxx[] = "$Header$"; + +#include "swigmod.h" + +struct normal_node { + Symtab *symtab; + Hash *typescope; + List *normallist; + normal_node *next; +}; + +static normal_node *patch_list = 0; + +class TypePass : public Dispatcher { + Node *inclass; + Node *module; + int importmode; + String *nsname; + Hash *classhash; + List *normalize; + + /* Normalize a type. Replaces type with fully qualified version */ + + void normalize_type(SwigType *ty) { + SwigType *qty; + /*qty = Swig_symbol_type_qualify(ty,0);*/ + /* if (SwigType_istemplate(ty)) { + qty = Swig_symbol_type_qualify(ty,0); + Clear(ty); + Append(ty,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); + 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); + SwigType *t; + for (t = Firstitem(nn->normallist); t; t = Nextitem(nn->normallist)) { + normalize_type(t); + } + Delete(nn->normallist); + np = nn->next; + delete(nn); + nn = np; + } + Swig_symbol_setscope(currentsym); + } + + /* generate C++ inheritance type-relationships */ + void cplus_inherit_types(Node *first, Node *cls, String *clsname, String *cast = 0) { + + if (first == cls) return; /* The Marcelo check */ + if (!cls) cls = first; + + 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(bname),Getline(bname),"'%s' is not a class. \n",bname); + } else { + Swig_warning(WARN_TYPE_INCOMPLETE,Getfile(bname),Getline(bname),"Base class '%s' is incomplete.\n", bname); + clsforward = 1; + } + bcls = 0; + } else { + if (Getattr(bcls,"typepass:visit")) { + if (!ilist) ilist = NewList(); + Append(ilist,bcls); + } else { + Swig_error(Getfile(bcls),Getline(bcls),"class '%s' must be defined before it is used as a base class.\n", bname); + } + } + } + break; + } + + if (tname) Delete(tname); + if (!bcls) { + if (!clsforward) { + if (!Getmeta(bname,"already_warned")) { + Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname),Getline(bname),"Nothing known about class '%s'. Ignored.\n", SwigType_namestr(bname)); + if (Strchr(bname,'<')) { + Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Maybe you forgot to instantiate '%s' using %%template.\n", SwigType_namestr(bname)); + } + Setmeta(bname,"already_warned","1"); + } + } + SwigType_inherit(clsname,bname, cast); + } + } + } + if (ilist) { + Setattr(cls,"bases",ilist); + } + } + 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); + 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 *s = Swig_symbol_current(); + Symtab *st = Getattr(cls,"symtab"); + Swig_symbol_setscope(st); + Swig_symbol_inherit(Getattr(bclass,"symtab")); + Swig_symbol_setscope(s); + + /* Recursively hit base classes */ + String *newcast = NewStringf("(%s *)%s", SwigType_namestr(Getattr(bclass,"name")), cast); + cplus_inherit_types(first,bclass,clsname, newcast); + Delete(newcast); + } + } + + /* Clean overloaded list. Removes templates, friends, ignored, and errors */ + + void clean_overloaded(Node *n) { + Node *nn = Getattr(n,"sym:overloaded"); + Node *first = 0; + int cnt = 0; + while (nn) { + if ((Strcmp(nodeType(nn),"template") == 0) || + (Getattr(nn,"feature:ignore")) || + (Getattr(nn,"error")) || + ((Strcmp(nodeType(nn),"using") == 0) && !firstChild(nn)) || + (checkAttribute(nn,"storage","friend"))) { + /* 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 ((Strcmp(nodeType(nn),"using") == 0)) { + /* A possibly dangerous parse tree hack. We're going to + cut the parse tree node out and stick in the resolved + using declarations */ + + Node *ps = Getattr(nn,"sym:previousSibling"); + Node *ns = Getattr(nn,"sym:nextSibling"); + Node *un = firstChild(nn); + Node *pn = un; + + if (!first) { + first = un; + } + while (pn) { + Node *ppn = Getattr(pn,"sym:nextSibling"); + Setattr(pn,"sym:overloaded",first); + Setattr(pn,"sym:overname", NewStringf("%s_%d", Getattr(nn,"sym:overname"), cnt++)); + if (ppn) pn = ppn; + else break; + } + if (ps) { + Setattr(ps,"sym:nextSibling",un); + Setattr(un,"sym:previousSibling",ps); + } + if (ns) { + Setattr(ns,"sym:previousSibling", pn); + Setattr(pn,"sym:nextSibling",ns); + } + if (!first) { + first = un; + Setattr(nn,"sym:overloaded",first); + } + } else { + if (!first) first = nn; + Setattr(nn,"sym:overloaded",first); + } + nn = Getattr(nn,"sym:nextSibling"); + } + if (!first || (first && !Getattr(first,"sym:nextSibling"))) { + Delattr(n,"sym:overloaded"); + } + } + +public: + + /* ------------------------------------------------------------ + * 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 ((!cn) || (Strcmp(nodeType(cn),"template") == 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 as '%s' at %s:%d.\n", + SwigType_namestr(name), SwigType_namestr(Getattr(cn,"name")), Getfile(cn), Getline(cn)); + 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); + } + 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); + 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); + } + 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 = 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); + } + + /* 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"); + } + + /* Search for var args */ + if (Getattr(n,"feature:varargs")) { + ParmList *v = Getattr(n,"feature:varargs"); + Parm *p = Getattr(n,"parms"); + Parm *pp = 0; + while (p) { + SwigType *t = Getattr(p,"type"); + if (Strcmp(t,"v(...)") == 0) { + if (pp) { + set_nextSibling(pp,Copy(v)); + } else { + Setattr(n,"parms", Copy(v)); + } + break; + } + pp = p; + p = nextSibling(p); + } + } + + /* 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 (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)) { + 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"); + } + + /* Search for var args */ + if (Getattr(n,"feature:varargs")) { + ParmList *v = Getattr(n,"feature:varargs"); + Parm *p = Getattr(n,"parms"); + Parm *pp = 0; + while (p) { + SwigType *t = Getattr(p,"type"); + if (Strcmp(t,"v(...)") == 0) { + if (pp) { + set_nextSibling(pp,Copy(v)); + } else { + Setattr(n,"parms", Copy(v)); + } + break; + } + pp = p; + p = nextSibling(p); + } + } + 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) { + SwigType *t = NewStringf("enum %s", name); + SwigType_typedef(t,name); + Delete(t); + } + 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)) { + 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); + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * 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 */ + + if (Getattr(n,"sym:symtab")) { + ns = Swig_symbol_clookup(Getattr(n,"uname"), Getattr(n,"sym:symtab")); + } else { + ns = 0; + } + if (!ns) { + if (!Getattr(n,"access") || ((Strcmp(Getattr(n,"access"),"public") == 0))) { + 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) && (!Getattr(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")) + || Getattr(c,"feature:ignore"))) { + + String *csymname = Getattr(c,"sym:name"); + if (!csymname || (Strcmp(csymname,symname) == 0)) { + /* Check for existence in overload list already */ + { + 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); + if (!Getattr(nn,"sym:name")) Setattr(nn,"sym:name", symname); + + if (!Getattr(nn,"feature:ignore")) { + Setattr(nn,"parms",CopyParmList(Getattr(c,"parms"))); + 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"); + } + } + } + } + } + } 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; + } +}; + +void Swig_process_types(Node *n) { + if (!n) return; + TypePass *t = new TypePass; + t->top(n); + delete t; +} + + + + + + + diff --git a/Source/Modules/xml.cxx b/Source/Modules/xml.cxx new file mode 100644 index 000000000..261f3e348 --- /dev/null +++ b/Source/Modules/xml.cxx @@ -0,0 +1,318 @@ +/* ----------------------------------------------------------------------------- + * Xml.cxx + * + * A web-base parse tree Xml using SWILL. This is an optional + * feature that's normally disabled. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 2002. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_xml_cxx[] = "$Header$"; +static const char *usage = "\ +XML Options (available with -xml)\n\ + -xml output.xml - Use output.xml as output file (extension .xml mandatory)\n\ + -xmllang lang - Typedef language.\n\n"; + +#include "swigmod.h" + +//static Node *view_top = 0; +static File *out = 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 = 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"); + if (!out) + { + Printf(stderr,"*** Can't open '%s'\n", 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, stderr ); + } + } + } + + /* Top of the parse tree */ + + virtual int top(Node *n) + { + if( out == 0 ) + { + String *outfile = Getattr(n,"outfile"); + Replaceall(outfile,"_wrap.cxx", ".xml"); + out = NewFile(outfile,"w"); + if (!out) + { + Printf(stderr,"*** Can't open '%s'\n", outfile); + SWIG_exit(EXIT_FAILURE); + } + } + Printf( out, " \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, "\n", ++id, obj ); + indent_level += 4; + + k = Firstkey(obj); + while (k) + { + 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 (Cmp(k,"typescope") == 0) + { + Xml_print_typescope( Getattr(obj,k) ); + } + else if (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))) + { + o = Str(Getattr(obj,k)); + Replaceall( k, ":", "_" ); + Replaceall( o, "<", "<" ); + Replaceall( o, "&", "&" ); + Replaceall( o, "\"", """ ); + Replaceall( o, "\\", "\\\\" ); + Printf(out,"\n", k, o, ++id, o ); + Delete(o); + } + else + { + o = Getattr(obj,k); + Replaceall( k, ":", "_" ); + Printf(out,"\n", k, o, ++id, o ); + } + } + k = Nextkey(obj); + } + indent_level -= 4; + print_indent(0); + Printf( out, "\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,"\n", nodeType(obj)); + } + + + void Xml_print_parmlist(ParmList *p) + { + + print_indent(0); + Printf( out, "\n", ++id, p ); + indent_level += 4; + while(p) + { + print_indent(0); + Printf( out, "\n", ++id ); + Xml_print_attributes( p ); + print_indent(0); + Printf( out, "\n" ); + p = nextSibling(p); + } + indent_level -= 4; + print_indent(0); + Printf( out, "\n" ); + } + + void Xml_print_baselist(List *p) + { + + print_indent(0); + Printf( out, "\n", ++id, p ); + indent_level += 4; + String *s; + for (s = Firstitem(p); s; s = Nextitem(p)) + { + print_indent(0); + Printf( out, "\n", s, ++id, s ); + } + indent_level -= 4; + print_indent(0); + Printf( out, "\n" ); + } + + void Xml_print_module(Node *p) + { + + print_indent(0); + Printf( out, "\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; + Node * n = Firstitem( p ); + while(n) + { + print_indent(0); + Printf( out, "<%ssitem id=\"%ld\" addr=\"%x\" >\n", markup, ++id, n ); + Xml_print_attributes( n ); + Printf( out, "\n", markup ); + print_indent(0); + Printf( out, " />\n" ); + n = Nextkey(p); + } + indent_level -= 4; + print_indent(0); + Printf( out, "\n", markup ); + } + +}; + + +extern "C" +{ + Language * swig_xml( void ) + { + return new XML(); + } +}