Substantial changes for new module system.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@908 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Dave Beazley 2000-10-02 03:04:25 +00:00
commit 5c39b4bc22
12 changed files with 1007 additions and 845 deletions

View file

@ -6,9 +6,9 @@ srcdir = @srcdir@
VPATH = @srcdir@
SRCS = map.c wrapfunc.c naming.c tree.c stype.c scanner.c include.c getopt.c misc.c \
parms.c cwrap.c typemap.c
parms.c cwrap.c typemap.c module.c
OBJS = map.o wrapfunc.o naming.o tree.o stype.o scanner.o include.o getopt.o misc.o \
parms.o cwrap.o typemap.o
parms.o cwrap.o typemap.o module.o
prefix = @prefix@
exec_prefix = @exec_prefix@

View file

@ -60,6 +60,18 @@ Swig_mark_arg(int n) {
marked[n] = 1;
}
/* -----------------------------------------------------------------------------
* Swig_check_marked()
*
* Checks to see if argument has been picked up.
* ----------------------------------------------------------------------------- */
int
Swig_check_marked(int n) {
assert((n>=0) && (n < numargs));
return marked[n];
}
/* -----------------------------------------------------------------------------
* Swig_check_options()
*

View file

@ -21,6 +21,26 @@ static List *directories = 0; /* List of include directories */
static String *lastpath = 0; /* Last file that was included */
static int bytes_read = 0; /* Bytes read */
static String *swiglib = 0; /* Location of SWIG library */
/* -----------------------------------------------------------------------------
* Swig_swiglib_set()
* Swig_swiglib_get()
*
* Set the location of the SWIG library. This isn't really used, by the
* include mechanism, but rather as a query interface for language modules.
* ----------------------------------------------------------------------------- */
void
Swig_swiglib_set(const String_or_char *sl) {
swiglib = NewString(sl);
}
String *
Swig_swiglib_get() {
return swiglib;
}
/* -----------------------------------------------------------------------------
* Swig_add_directory()
*

166
SWIG/Source/Swig/module.c Normal file
View file

@ -0,0 +1,166 @@
/* -----------------------------------------------------------------------------
* module.c
*
* This file implements the SWIG module system. Modules are simply
* pieces of code that manipulate tree objects. Each module is defined
* by 4 quantities:
*
* - Module name (used to select the module on the command line)
* - init function (called with the SWIG command line options).
* - start function (called to launch the module)
* - start tag (starting tag expected by the module)
*
* Currently modules must be statically linked with SWIG. However, it
* is anticipated that the module system may eventually support
* dynamic loading.
*
* 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.
* ----------------------------------------------------------------------------- */
#include "swig.h"
static char cvsroot[] = "$Header$";
struct Module {
String *modname;
int (*initfunc)(int argc, char **argv);
DOH *(*startfunc)(DOH *);
String *starttag;
struct Module *next;
};
static Module *Modules = 0;
static Hash *LoadedModules = 0;
/* -----------------------------------------------------------------------------
* Swig_register_module()
*
* Register a new module with the system
* ----------------------------------------------------------------------------- */
void
Swig_register_module(const String_or_char *modname, const String_or_char *starttag,
int (*initfunc)(int argc, char **argv),
DOH *(*startfunc)(DOH *))
{
Module *m;
m = (Module *) malloc(sizeof(Module));
m->modname = NewString(modname);
m->starttag = NewString(starttag);
m->initfunc = initfunc;
m->startfunc = startfunc;
m->next = Modules;
Modules = m;
}
/* -----------------------------------------------------------------------------
* Swig_load_module()
*
* Load a module. Returns the module object.
* ----------------------------------------------------------------------------- */
Module *
Swig_load_module(const String_or_char *modname) {
Module *m;
m = Modules;
while (m) {
if (Cmp(m->modname, modname) == 0) {
/* Create a new entry in the loaded modules table */
List *ml;
if (!LoadedModules) LoadedModules = NewHash();
ml = Getattr(LoadedModules,m->starttag);
if (!ml) {
ml = NewList();
Setattr(LoadedModules,m->starttag,ml);
}
Append(ml,NewVoid(m,0));
return m;
}
m = m->next;
}
return 0;
}
/* -----------------------------------------------------------------------------
* Swig_init_module()
*
* Initialize a module
* ----------------------------------------------------------------------------- */
int Swig_init_module(Module *m, int argc, char **argv) {
return (*m->initfunc)(argc,argv);
}
/* -----------------------------------------------------------------------------
* Swig_start_module()
*
* Start a module
* ----------------------------------------------------------------------------- */
DOH *
Swig_start_module(Module *m, DOH *obj) {
return (*m->startfunc)(obj);
}
/* -----------------------------------------------------------------------------
* Swig_run_modules()
*
* Given a tree node. This function tries to run it through all of the loaded
* modules. This works by looking at the "tag" attribute of the node and
* searching for a loaded module that can handle that tag. If no module can be
* found, processing stops and an error is generated.
*
* If more than one module can work on a given tag, those modules will be
* executed one after the other. Caveat: if one of those modules outputs
* a different type of tree, processing immediately stops.
* ----------------------------------------------------------------------------- */
DOH *Swig_run_modules(DOH *node) {
String *tag;
List *ml;
DOH *newnode;
String *newtag;
int i;
tag = Getattr(node,"tag");
if (!tag) {
Printf(stderr,"Whoa. No tag attribute on node passed to Swig_module_run.\n");
exit(EXIT_FAILURE);
}
/* Get the set of modules that can respond to this node */
while (node) {
if (!LoadedModules) {
Printf(stderr,"No modules loaded.\n");
return 0;
}
ml = Getattr(LoadedModules,tag);
if ((!ml) || (Len(ml) == 0)) {
Printf(stderr,"No module for object '%s'\n", tag);
return 0;
}
newnode = 0;
newtag = 0;
for (i = 0; i < Len(ml); i++) {
Module *m;
m = (Module *) Data(Getitem(ml,i));
assert(m);
newnode = (*m->startfunc)(node);
if (!newnode) return 0; /* Done */
newtag = Getattr(newnode,"tag");
if (!newtag) {
Printf(stderr,"Fatal error. Module '%s' returns untagged object.\n", m->modname);
exit(EXIT_FAILURE);
}
if (Cmp(newtag,tag)) break; /* Tag is different. Oh well */
}
if (Cmp(newtag,tag) == 0) break; /* Hmmm. The tag is the same but we already did everything */
node = newnode;
tag = newtag;
}
return 0;
}

View file

@ -68,6 +68,8 @@ extern int Swig_insert_file(const String_or_char *name, File *outfile);
extern int Swig_bytes_read();
extern void Swig_register_filebyname(const String_or_char *name, File *outfile);
extern File *Swig_filebyname(const String_or_char *name);
extern void Swig_swiglib_set(const String_or_char *name);
extern String *Swig_swiglib_get();
#define OUTFILE(x) Swig_filebyname(x)
@ -77,6 +79,7 @@ extern File *Swig_filebyname(const String_or_char *name);
extern void Swig_init_args(int argc, char **argv);
extern void Swig_mark_arg(int n);
extern int Swig_check_marked(int n);
extern void Swig_check_options();
extern void Swig_arg_error();
@ -221,19 +224,39 @@ extern String *ParmList_protostr(ParmList *);
/* --- Parse tree support --- */
typedef struct {
char *name;
const char *name;
int (*action)(DOH *obj, void *clientdata);
} SwigRule;
extern void Swig_dump_tags(DOH *obj, DOH *root);
extern void Swig_add_rule(String_or_char *, int (*action)(DOH *, void *));
#define SWIG_OK 1
#define SWIG_NORULE 0
#define SWIG_ERROR -1
extern void Swig_add_rule(const String_or_char *, int (*action)(DOH *, void *));
extern void Swig_add_rules(SwigRule ruleset[]);
extern void Swig_clear_rules();
extern int Swig_tag_check(DOH *obj, String_or_char *tagname);
extern int Swig_emit(DOH *obj, void *clientdata);
extern void Swig_cut_node(DOH *obj);
extern int Swig_emit_all(DOH *obj, void *clientdata);
extern void Swig_set_callback(DOH *obj, void (*cb)(void *clientdata), void *clientdata);
extern void (*Swig_set_trace(DOH *obj, void (*cb)(DOH *, DOH *), DOH *arg))(DOH *, DOH *);
extern void Swig_remove_trace(DOH *obj);
extern void Swig_node_cut(DOH *obj);
extern void Swig_node_insert(DOH *node, DOH *newnode);
extern void Swig_node_temporary(DOH *node);
extern void Swig_node_ignore(DOH *node);
extern int Swig_count_nodes(DOH *node);
extern DOH *Swig_next(DOH *obj);
extern DOH *Swig_prev(DOH *obj);
/* Debugging of parse trees */
extern void Swig_debug_emit(int);
extern void Swig_dump_tags(DOH *obj, DOH *root);
extern void Swig_dump_tree(DOH *obj);
extern void Swig_dump_rules();
/* -- Wrapper function Object */
typedef struct {
@ -349,6 +372,18 @@ extern Wrapper *Swig_cvarget_wrapper(String_or_char *varname,
String_or_char *code);
/* --- Module loader and handler --- */
typedef struct Module Module;
extern void Swig_register_module(const String_or_char *modname, const String_or_char *starttag,
int (*initfunc)(int, char **),
DOH *(*startfunc)(DOH *));
extern Module *Swig_load_module(const String_or_char *modname);
extern int Swig_init_module(Module *m, int argc, char **argv);
extern DOH *Swig_start_module(Module *m, DOH *obj);
extern DOH *Swig_run_modules(DOH *node);
/* --- Legacy Typemap API (somewhat simplified) --- */
extern void Swig_typemap_init();
@ -385,6 +420,9 @@ extern void Swig_except_clear();
#define Getnext(x) Getattr(x,"next")
#define Setnext(x,n) Setattr(x,"next",n)
#define Getchild(x) Getattr(x,"child")
extern int Swig_main(int argc, char *argv[]);
#endif

View file

@ -14,7 +14,9 @@
static char cvsroot[] = "$Header$";
/* Hash table mapping tag names to handler functions */
static Hash *rules = 0;
static int debug_emit = 0;
/* -----------------------------------------------------------------------------
* Swig_next()
@ -31,6 +33,10 @@ DOH *Swig_prev(DOH *obj) {
return Getattr(obj,"prev");
}
void Swig_debug_emit(int n) {
debug_emit = n;
}
/* -----------------------------------------------------------------------------
* Swig_dump_tags()
*
@ -46,10 +52,10 @@ Swig_dump_tags(DOH *obj, DOH *root) {
else croot = root;
while (obj) {
Printf(stdout,"%s.%s\n", croot, Getattr(obj,"tag"));
Printf(stdout,"%s . %s\n", croot, Getattr(obj,"tag"));
cobj = Getattr(obj,"child");
if (cobj) {
newroot = NewStringf("%s.%s",croot,Getattr(obj,"tag"));
newroot = NewStringf("%s . %s",croot,Getattr(obj,"tag"));
Swig_dump_tags(cobj,newroot);
Delete(newroot);
}
@ -59,6 +65,72 @@ Swig_dump_tags(DOH *obj, DOH *root) {
Delete(croot);
}
/* -----------------------------------------------------------------------------
* Swig_dump_tree()
*
* Dump the tree structure of a parse tree to standard output
* ----------------------------------------------------------------------------- */
static int indent_level = 0;
static void print_indent(int l) {
int i;
for (i = 0; i < indent_level; i++) {
fputc(' ', stdout);
}
if (l) {
fputc('|', stdout);
fputc(' ', stdout);
}
}
void
Swig_dump_tree(DOH *obj) {
DOH *k;
DOH *cobj;
while (obj) {
print_indent(0);
Printf(stdout,"+++ %s ----------------------------------------\n", Getattr(obj,"tag"));
k = Firstkey(obj);
while (k) {
if ((Cmp(k,"tag") == 0) || (Cmp(k,"child") == 0) ||
(Cmp(k,"parent") == 0) || (Cmp(k,"next") == 0) ||
(Cmp(k,"prev") == 0)) {
/* Do nothing */
} else if (Cmp(k,"parms") == 0) {
print_indent(2);
Printf(stdout,"%-12s - %s\n", k, ParmList_protostr(Getattr(obj,k)));
} else {
DOH *o;
char *trunc = "";
print_indent(2);
o = Str(Getattr(obj,k));
if (Len(o) > 40) {
trunc = "...";
}
Printf(stdout,"%-12s - \"%(escape)-0.40s%s\"\n", k, o, trunc);
Delete(o);
}
k = Nextkey(obj);
}
cobj = Getattr(obj,"child");
if (cobj) {
indent_level += 6;
Printf(stdout,"\n");
Swig_dump_tree(cobj);
indent_level -= 6;
} else {
print_indent(1);
Printf(stdout,"\n");
}
obj = Swig_next(obj);
}
}
/* -----------------------------------------------------------------------------
* Swig_add_rule()
*
@ -66,13 +138,17 @@ Swig_dump_tags(DOH *obj, DOH *root) {
* ----------------------------------------------------------------------------- */
void
Swig_add_rule(String_or_char *name, int (*action)(DOH *node, void *clientdata))
Swig_add_rule(const String_or_char *name, int (*action)(DOH *node, void *clientdata))
{
if (!rules) rules = NewHash();
if (action)
Setattr(rules,name,NewVoid((void *) action,0));
else
Delattr(rules,name);
if (debug_emit) {
Printf(stderr,"Swig_add_rule : '%s' -> %x\n", name, action);
}
}
/* -----------------------------------------------------------------------------
@ -101,48 +177,234 @@ Swig_clear_rules()
{
if (rules) Delete(rules);
rules = NewHash();
if (debug_emit) {
Printf(stderr,"Swig_clear_rules :\n");
}
}
/* -----------------------------------------------------------------------------
* Swig_dump_rules()
*
* Print out debugging information for the rules
* ----------------------------------------------------------------------------- */
void
Swig_dump_rules() {
String *key;
Printf(stdout,"SWIG emit rules:::\n");
if (!rules) {
Printf(stdout," No rules defined.\n");
return;
}
key = Firstkey(rules);
while (key) {
Printf(stdout," '%-15s' -> %x\n", key, GetVoid(rules,key));
key = Nextkey(rules);
}
}
/* -----------------------------------------------------------------------------
* Swig_tag_check()
*
* Checks the tag name of an object taking into account namespace issues.
* For example, a check of "function" will match any object with a tag
* of the form "xxx:function" whereas a check of "c:function" will check
* for a more exact match. Returns 1 if a match is found, 0 otherwise
* ----------------------------------------------------------------------------- */
int
Swig_tag_check(DOH *obj, String_or_char *tagname) {
String *tag;
char *tc;
char *tnc;
tag = Getattr(obj,"tag");
assert(tag);
tc = Char(tag);
tnc = Char(tagname);
while (tnc) {
if (strcmp(tc,tnc) == 0) return 1;
tnc = strchr(tnc,':');
if (tnc) tnc++;
}
return 0;
}
/* -----------------------------------------------------------------------------
* Swig_set_callback()
*
* Sets a parser callback function for a node.
* ----------------------------------------------------------------------------- */
void
Swig_set_callback(DOH *obj, void (*cb)(void *clientdata), void *clientdata) {
SetVoid(obj,"-callback-",(void *)cb);
if (clientdata)
SetVoid(obj,"-callbackarg-", clientdata);
}
/* -----------------------------------------------------------------------------
* Swig_set_trace()
*
* Sets a tracing function on a parse tree node. Returns the old tracing
* function (if any).
* ----------------------------------------------------------------------------- */
void (*Swig_set_trace(DOH *obj, void (*cb)(DOH *, DOH *), DOH *arg))(DOH *, DOH *) {
void (*old)(DOH *,DOH *);
old = (void (*)(DOH *, DOH *)) GetVoid(obj,"-trace-");
SetVoid(obj,"-trace-", (void *) cb);
if (arg)
Setattr(obj,"-tracearg-", arg);
return old;
}
/* -----------------------------------------------------------------------------
* Swig_remove_trace()
*
* Removes the tracing function from a parse tree node
* ----------------------------------------------------------------------------- */
void
Swig_remove_trace(DOH *obj) {
Delattr(obj,"-trace-");
Delattr(obj,"-tracearg-");
}
/* -----------------------------------------------------------------------------
* Swig_node_temporary()
*
* Sets a node as being temporary (deleted immediately after it is emitted)
* ----------------------------------------------------------------------------- */
void Swig_node_temporary(DOH *obj) {
SetInt(obj,"-temp-",1);
}
/* -----------------------------------------------------------------------------
* Swig_node_ignore()
*
* Causes a node to be ignored
* ----------------------------------------------------------------------------- */
void Swig_node_ignore(DOH *obj) {
SetInt(obj,"-ignore-",1);
}
/* -----------------------------------------------------------------------------
* int Swig_emit()
*
* Emit an action for a specific object
* This function calls the handler function (if any) for an object.
* ----------------------------------------------------------------------------- */
int
Swig_emit(DOH *obj, void *clientdata) {
DOH *tag;
DOH *actionobj;
char *tc;
int (*action)(DOH *obj, void *clientdata);
void (*callback)(void *clientdata);
void (*tracefunc)(DOH *obj, DOH *arg);
int ret;
assert(obj);
if (!rules) return -1;
while (obj) {
if (!rules) {
Printf(stderr,"No rules defined in Swig_emit()!\n");
return SWIG_ERROR;
}
if (obj) {
if (Getattr(obj,"-ignore-")) return SWIG_OK;
tag = Getattr(obj,"tag");
actionobj = Getattr(rules,tag);
assert(tag);
tc = Char(tag);
while(tc) {
actionobj = Getattr(rules,tc);
if (actionobj) {
if (debug_emit) {
Printf(stderr,"Swig_emit : Matched tag '%s' -> rule '%s'\n", tag, tc);
}
/* Check for user tracing -- traces occur before any handlers are called */
tracefunc = (void (*)(DOH *, DOH *)) GetVoid(obj,"-trace-");
if (tracefunc) {
DOH *tobj = Getattr(obj,"-tracearg-");
(*tracefunc)(obj,tobj);
}
action = (int (*)(DOH *, void *)) Data(actionobj);
ret = (*action)(obj,clientdata);
/* Check for a parser callback */
callback = (void (*)(void *clientdata)) GetVoid(obj,"-callback-");
if (callback) {
void *cbarg;
cbarg = GetVoid(obj,"-callbackarg-");
(*callback)(cbarg);
Delattr(obj,"-callback-");
Delattr(obj,"-callbackarg-");
}
return ret;
} else {
tc = strchr(tc,':');
if (tc) tc++;
}
}
actionobj = Getattr(rules,"*");
if (actionobj) {
if (debug_emit) {
Printf(stderr,"Swig_emit : Matched tag '%s' -> rule '*'\n", tag);
}
/* Check for user tracing -- traces occur before any handlers are called */
tracefunc = (void (*)(DOH *, DOH *)) GetVoid(obj,"-trace-");
if (tracefunc) {
DOH *tobj = Getattr(obj,"-tracearg-");
(*tracefunc)(obj,tobj);
}
action = (int (*)(DOH *, void *)) Data(actionobj);
ret = (*action)(obj,clientdata);
if (ret < 0) return -1;
} else {
Printf(stderr,"warning: no action defined for '%s'\n", tag);
/* Check for a parser callback */
callback = (void (*)(void *clientdata)) GetVoid(obj,"-callback-");
if (callback) {
void *cbarg;
cbarg = GetVoid(obj,"-callbackarg-");
(*callback)(cbarg);
Delattr(obj,"-callback-");
Delattr(obj,"-callbackarg-");
}
return ret;
}
if (debug_emit) {
Printf(stderr,"Swig_emit : No rule defined for tag '%s'\n", tag);
}
obj = Swig_next(obj);
}
return 0;
return SWIG_NORULE;
}
/* -----------------------------------------------------------------------------
* Swig_cut_node(DOH *obj)
* Swig_emit_all()
*
* Emit all of the nodes at this level.
* ----------------------------------------------------------------------------- */
int
Swig_emit_all(DOH *obj, void *clientdata) {
int ret;
while (obj) {
ret = Swig_emit(obj,clientdata);
if (ret < 0) return ret;
obj = Swig_next(obj);
}
return SWIG_OK;
}
/* -----------------------------------------------------------------------------
* Swig_node_cut()
*
* This function cuts an object out of a parse tree. To do this, the object
* MUST be properly initialized with "next", "prev", and "parent" attributes.
* ----------------------------------------------------------------------------- */
void Swig_cut_node(DOH *obj) {
void Swig_node_cut(DOH *obj) {
DOH *parent;
DOH *next;
DOH *prev;
@ -156,7 +418,7 @@ void Swig_cut_node(DOH *obj) {
Delattr(obj,"parent"); /* Disassociate from my parent */
if (!next && !prev) {
/* Well, this is a single child. Guess we'll just update the parent their child is gone */
/* Well, this is a single child. Guess we'll just tell the parent that their child is gone */
Delattr(parent,"child");
return;
}
@ -184,8 +446,43 @@ void Swig_cut_node(DOH *obj) {
return;
}
/* -----------------------------------------------------------------------------
* Swig_node_insert()
*
* Inserts a node after a given node. The node to be inserted should be
* isolated (no parent, no siblings, etc...).
* ----------------------------------------------------------------------------- */
void
Swig_node_insert(DOH *node, DOH *newnode) {
DOH *next;
next = Getattr(node,"next");
if (next) {
Setattr(newnode,"next", next);
Setattr(next,"prev", newnode);
}
Setattr(node,"next",newnode);
Setattr(newnode,"prev", node);
Setattr(newnode,"parent", Getattr(node,"parent"));
}
/* -----------------------------------------------------------------------------
* Swig_count_nodes()
*
* Count number of nodes at this level
* ----------------------------------------------------------------------------- */
int Swig_count_nodes(DOH *node) {
int n = 0;
while (node) {
n++;
node = Getnext(node);
}
return n;
}