The great merge

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@4141 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Dave Beazley 2002-11-30 22:01:28 +00:00
commit 516036631c
1508 changed files with 125983 additions and 44037 deletions

View file

@ -11,40 +11,19 @@
* ----------------------------------------------------------------------------- */
#include "swig.h"
#include <stdarg.h>
#include <assert.h>
static char cvsroot[] = "$Header$";
/* Hash table mapping tag names to handler functions */
static Hash *rules = 0;
static int debug_emit = 0;
char cvsroot_tree_c[] = "$Header$";
/* -----------------------------------------------------------------------------
* Swig_next()
* Swig_prev()
*
* Return next/prev node in a parse tree
* ----------------------------------------------------------------------------- */
DOH *Swig_next(DOH *obj) {
return Getnext(obj);
}
DOH *Swig_prev(DOH *obj) {
return Getprev(obj);
}
void Swig_debug_emit(int n) {
debug_emit = n;
}
/* -----------------------------------------------------------------------------
* Swig_dump_tags()
* Swig_print_tags()
*
* Dump the tag structure of a parse tree to standard output
* ----------------------------------------------------------------------------- */
void
Swig_dump_tags(DOH *obj, DOH *root) {
Swig_print_tags(DOH *obj, DOH *root) {
DOH *croot, *newroot;
DOH *cobj;
@ -52,22 +31,21 @@ Swig_dump_tags(DOH *obj, DOH *root) {
else croot = root;
while (obj) {
Printf(stdout,"%s . %s (%s:%d)\n", croot, Getattr(obj,"tag"), Getfile(obj), Getline(obj));
cobj = Getattr(obj,"child");
Printf(stdout,"%s . %s (%s:%d)\n", croot, nodeType(obj), Getfile(obj), Getline(obj));
cobj = firstChild(obj);
if (cobj) {
newroot = NewStringf("%s . %s",croot,Getattr(obj,"tag"));
Swig_dump_tags(cobj,newroot);
newroot = NewStringf("%s . %s",croot,nodeType(obj));
Swig_print_tags(cobj,newroot);
Delete(newroot);
}
obj = Swig_next(obj);
obj = nextSibling(obj);
}
if (!root)
Delete(croot);
}
/* -----------------------------------------------------------------------------
* Swig_dump_tree()
* Swig_print_tree()
*
* Dump the tree structure of a parse tree to standard output
* ----------------------------------------------------------------------------- */
@ -85,429 +63,339 @@ static void print_indent(int l) {
}
}
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);
/* -----------------------------------------------------------------------------
* Swig_dump_node(Node *n)
* ----------------------------------------------------------------------------- */
void
Swig_print_node(Node *obj) {
String *k;
Node *cobj;
print_indent(0);
Printf(stdout,"+++ %s ----------------------------------------\n", nodeType(obj));
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) {
print_indent(2);
Printf(stdout,"%-12s - %s\n", k, ParmList_protostr(Getattr(obj,k)));
} else {
DOH *o;
char *trunc = "";
print_indent(2);
if (DohIsString(Getattr(obj,k))) {
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()
*
* Adds a new rule to the tree walking code.
* ----------------------------------------------------------------------------- */
void
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);
}
}
/* -----------------------------------------------------------------------------
* Swig_add_rules()
*
* Add a complete set of rules to the rule system
* ----------------------------------------------------------------------------- */
void
Swig_add_rules(SwigRule ruleset[]) {
int i = 0;
while (ruleset[i].name) {
Swig_add_rule(ruleset[i].name, ruleset[i].action);
i++;
}
}
/* -----------------------------------------------------------------------------
* Swig_clear_rules()
*
* Clears all of the existing rules
* ----------------------------------------------------------------------------- */
void
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, const String_or_char *tagname) {
String *tag;
char *tc;
char *tnc;
tag = Getattr(obj,"tag");
assert(tag);
tnc = Char(tag);
tc = 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()
*
* 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) {
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");
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++;
Printf(stdout,"%-12s - 0x%x\n", k, Getattr(obj,k));
}
}
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);
/* 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);
}
k = Nextkey(obj);
}
cobj = firstChild(obj);
if (cobj) {
indent_level += 6;
Printf(stdout,"\n");
Swig_print_tree(cobj);
indent_level -= 6;
} else {
print_indent(1);
Printf(stdout,"\n");
}
return SWIG_NORULE;
}
/* -----------------------------------------------------------------------------
* Swig_emit_all()
*
* Emit all of the nodes at this level.
* ----------------------------------------------------------------------------- */
int
Swig_emit_all(DOH *obj, void *clientdata) {
int ret;
void
Swig_print_tree(DOH *obj) {
while (obj) {
ret = Swig_emit(obj,clientdata);
if (ret < 0) return ret;
obj = Swig_next(obj);
Swig_print_node(obj);
obj = nextSibling(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_node_cut(DOH *obj) {
DOH *parent;
DOH *next;
DOH *prev;
parent = Getattr(obj,"parent");
assert(parent);
next = Getattr(obj,"next");
prev = Getattr(obj,"prev");
DohIncref(obj); /* Make sure object doesn't go away */
Delattr(obj,"parent"); /* Disassociate from my parent */
if (!next && !prev) {
/* Well, this is a single child. Guess we'll just tell the parent that their child is gone */
Delattr(parent,"child");
return;
}
/* If no next node, then this must be at the end of a list */
if (!next) {
Delattr(prev,"next"); /* Break the 'next' link in the previous node */
Delattr(obj,"prev"); /* Break my link back to the previous object */
return;
}
/* No previous node. This must be the beginning of a list */
if (!prev) {
Delattr(next,"prev"); /* Break the 'prev' link of the next node */
Setattr(parent,"child",next); /* Update parent to point at next node */
Delattr(obj,"next"); /* Break my link to the next object */
return;
}
/* In the middle of a list someplace */
Setattr(prev,"next",next); /* Update previous node to my next node */
Setattr(next,"prev",prev); /* Update next node to my previous node */
Delattr(obj,"next");
Delattr(obj,"prev");
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_node_append_child()
* appendChild()
*
* Appends a new child to a node
* ----------------------------------------------------------------------------- */
void
Swig_node_append_child(DOH *node, DOH *chd) {
DOH *c;
DOH *pc;
c = Getattr(node,"child");
if (!c) {
Setattr(node,"child",chd);
Setattr(chd,"parent",node);
return;
appendChild(Node *node, Node *chd) {
Node *lc;
if (!chd) return;
lc = lastChild(node);
if (!lc) {
set_firstChild(node,chd);
} else {
set_nextSibling(lc,chd);
set_previousSibling(chd,lc);
}
while (c) {
pc = c;
c = Getnext(c);
while (chd) {
lc = chd;
set_parentNode(chd,node);
chd = nextSibling(chd);
}
Setattr(pc,"next",chd);
Setattr(chd,"prev",pc);
Setattr(chd,"parent",node);
set_lastChild(node,lc);
}
/* -----------------------------------------------------------------------------
* Swig_count_nodes()
* deleteNode()
*
* Count number of nodes at this level
* Deletes a node.
* ----------------------------------------------------------------------------- */
int Swig_count_nodes(DOH *node) {
int n = 0;
while (node) {
n++;
node = Getnext(node);
void
deleteNode(Node *n) {
Node *parent;
Node *prev;
Node *next;
parent = parentNode(n);
prev = previousSibling(n);
next = nextSibling(n);
if (prev) {
set_nextSibling(prev,next);
} else {
if (parent) {
set_firstChild(parent,next);
}
}
if (next) {
set_previousSibling(next,prev);
} else {
if (parent) {
set_lastChild(parent,prev);
}
}
return n;
}
/* -----------------------------------------------------------------------------
* copyNode()
*
* Copies a node, but only copies simple attributes (no lists, hashes).
* ----------------------------------------------------------------------------- */
Node *
copyNode(Node *n) {
String *key;
DOH *v;
Node *c = NewHash();
for (key = Firstkey(n); key; key = Nextkey(n)) {
v = Getattr(n,key);
if (DohIsString(v)) {
Setattr(c,key,Copy(v));
}
}
Setfile(c,Getfile(n));
Setline(c,Getline(n));
return c;
}
/* -----------------------------------------------------------------------------
* Swig_tag_nodes()
*
* Tags a collection of nodes with an attribute. Used by the parser to mark
* subtypes with extra information.
* ----------------------------------------------------------------------------- */
void
Swig_tag_nodes(Node *n, const String_or_char *attrname, DOH *value) {
while (n) {
Setattr(n,attrname,value);
Swig_tag_nodes(firstChild(n),attrname, value);
n = nextSibling(n);
}
}
int
checkAttribute(Node *n, const String_or_char *name, const String_or_char *value) {
String *v;
v = Getattr(n,name);
if (!v) return 0;
if (Cmp(v,value) == 0) return 1;
return 0;
}
/* -----------------------------------------------------------------------------
* Swig_require()
* ----------------------------------------------------------------------------- */
#define MAX_SWIG_STACK 256
static Hash *attr_stack[MAX_SWIG_STACK];
static Node **nodeptr_stack[MAX_SWIG_STACK];
static Node *node_stack[MAX_SWIG_STACK];
static int stackp = 0;
static int stack_direction = 0;
static void set_direction(int n, int *x) {
if (n == 1) {
set_direction(0,&n);
} else {
if (&n < x) {
stack_direction = -1; /* Stack grows down */
} else {
stack_direction = 1; /* Stack grows up */
}
}
}
int
Swig_require(Node **nptr, ...) {
va_list ap;
char *name;
DOH *obj;
DOH *frame = 0;
Node *n = *nptr;
va_start(ap, nptr);
name = va_arg(ap, char *);
while (name) {
int newref = 0;
int opt = 0;
if (*name == '*') {
newref = 1;
name++;
} else if (*name == '?') {
newref = 1;
opt = 1;
name++;
}
obj = Getattr(n,name);
if (!opt && !obj) {
Printf(stderr,"%s:%d. Fatal error (Swig_require). Missing attribute '%s' in node '%s'.\n",
Getfile(n), Getline(n), name, nodeType(n));
assert(obj);
}
if (!obj) obj = DohNone;
if (newref) {
if (!attr_stack[stackp]) {
attr_stack[stackp]= NewHash();
}
frame = attr_stack[stackp];
if (Setattr(frame,name,obj)) {
Printf(stderr,"Swig_require('%s'): Warning, attribute '%s' was already saved.\n", nodeType(n), name);
}
}
name = va_arg(ap, char *);
}
va_end(ap);
if (frame) {
/* This is a sanity check to make sure no one is saving data, but not restoring it */
if (stackp > 0) {
int e = 0;
if (!stack_direction) set_direction(1,0);
if (stack_direction < 0) {
if ((((char *) nptr) >= ((char *) nodeptr_stack[stackp-1])) && (n != node_stack[stackp-1])) e = 1;
} else {
if ((((char *) nptr) <= ((char *) nodeptr_stack[stackp-1])) && (n != node_stack[stackp-1])) e = 1;
}
if (e) {
Printf(stderr,
"Swig_require('%s'): Fatal memory management error. If you are seeing this\n\
message. It means that the target language module is not managing its memory\n\
correctly. A handler for '%s' probably forgot to call Swig_restore().\n\
Please report this problem to swig-dev@cs.uchicago.edu.\n", nodeType(n), nodeType(node_stack[stackp-1]));
assert(0);
}
}
nodeptr_stack[stackp] = nptr;
node_stack[stackp] = n;
stackp++;
}
return 1;
}
int
Swig_save(Node **nptr, ...) {
va_list ap;
char *name;
DOH *obj;
DOH *frame;
Node *n = *nptr;
if ((stackp > 0) && (nodeptr_stack[stackp-1] == nptr)) {
frame = attr_stack[stackp-1];
} else {
if (stackp > 0) {
int e = 0;
if (!stack_direction) set_direction(1,0);
if (stack_direction < 0) {
if ((((char *) nptr) >= ((char *) nodeptr_stack[stackp-1])) && (n != node_stack[stackp-1])) e = 1;
} else {
if ((((char *) nptr) <= ((char *) nodeptr_stack[stackp-1])) && (n != node_stack[stackp-1])) e = 1;
}
if (e) {
Printf(stderr,
"Swig_save('%s'): Fatal memory management error. If you are seeing this\n\
message. It means that the target language module is not managing its memory\n\
correctly. A handler for '%s' probably forgot to call Swig_restore().\n\
Please report this problem to swig-dev@cs.uchicago.edu.\n", nodeType(n), nodeType(node_stack[stackp-1]));
assert(0);
}
}
attr_stack[stackp] = NewHash();
nodeptr_stack[stackp] = nptr;
node_stack[stackp] = n;
frame = attr_stack[stackp];
stackp++;
}
va_start(ap, nptr);
name = va_arg(ap, char *);
while (name) {
if (*name == '*') {
name++;
} else if (*name == '?') {
name++;
}
obj = Getattr(n,name);
if (!obj) {
obj = DohNone;
}
if (Setattr(frame,name,obj)) {
Printf(stderr,"Swig_save('%s'): Warning, attribute '%s' was already saved.\n", nodeType(n), name);
}
name = va_arg(ap, char *);
}
va_end(ap);
return 1;
}
void
Swig_restore(Node **nptr) {
String *key;
Hash *frame;
Node *n = *nptr;
assert(stackp > 0);
if (!(nptr==nodeptr_stack[stackp-1])) {
Printf(stderr,
"Swig_restore('%s'): Fatal memory management error. If you are seeing this\n\
message. It means that the target language module is not managing its memory\n\
correctly. A handler for '%s' probably forgot to call Swig_restore().\n\
Please report this problem to swig-dev@cs.uchicago.edu.\n", nodeType(n), nodeType(node_stack[stackp-1]));
assert(0);
}
stackp--;
frame = attr_stack[stackp];
nodeptr_stack[stackp] = 0;
node_stack[stackp] = 0;
for (key = Firstkey(frame); key; key = Nextkey(frame)) {
DOH *obj = Getattr(frame,key);
if (obj != DohNone) {
Setattr(n,key,obj);
} else {
Delattr(n,key);
}
Delattr(frame,key);
}
}