swig/Source/Swig/tree.c
Marcelo Matus 55005e98ee Move rename/namewarn engine from parser.y to naming.c. The code was getting
too large to be in the parser.

Centralize the swig keys to avoid replication and wrong spellings.

Use more HashGetAttr where possible and other speed improvements
to compensate for the extra work introduced by the new rename/namewarn
mechanism.


git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@8170 626c5289-ae23-0410-ae9c-e8d60b6d4f22
2006-01-02 04:33:19 +00:00

412 lines
10 KiB
C

/* -----------------------------------------------------------------------------
* tree.c
*
* This file provides some general purpose functions for manipulating
* parse trees.
*
* 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"
#include <stdarg.h>
#include <assert.h>
char cvsroot_tree_c[] = "$Header$";
/* -----------------------------------------------------------------------------
* Swig_print_tags()
*
* Dump the tag structure of a parse tree to standard output
* ----------------------------------------------------------------------------- */
void
Swig_print_tags(DOH *obj, DOH *root) {
DOH *croot, *newroot;
DOH *cobj;
if (!root) croot = NewStringEmpty();
else croot = root;
while (obj) {
Printf(stdout,"%s . %s (%s:%d)\n", croot, nodeType(obj), Getfile(obj), Getline(obj));
cobj = firstChild(obj);
if (cobj) {
newroot = NewStringf("%s . %s",croot,nodeType(obj));
Swig_print_tags(cobj,newroot);
Delete(newroot);
}
obj = nextSibling(obj);
}
if (!root)
Delete(croot);
}
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);
}
}
/* -----------------------------------------------------------------------------
* Swig_dump_node(Node *n)
* ----------------------------------------------------------------------------- */
void
Swig_print_node(Node *obj) {
Iterator ki;
Node *cobj;
print_indent(0);
Printf(stdout,"+++ %s ----------------------------------------\n", nodeType(obj));
ki = First(obj);
while (ki.key) {
String *k = ki.key;
if ((Cmp(k,"nodeType") == 0) || (Cmp(k,"firstChild") == 0) || (Cmp(k,"lastChild") == 0) ||
(Cmp(k,"parentNode") == 0) || (Cmp(k,"nextSibling") == 0) ||
(Cmp(k,"previousSibling") == 0) || (*(Char(k)) == '$')) {
/* Do nothing */
} else if (Cmp(k,"parms") == 0) {
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);
} else {
Printf(stdout,"%-12s - 0x%x\n", k, Getattr(obj,k));
}
}
ki = Next(ki);
}
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");
}
}
/* -----------------------------------------------------------------------------
* Swig_print_tree()
*
* Dump the tree structure of a parse tree to standard output
* ----------------------------------------------------------------------------- */
void
Swig_print_tree(DOH *obj) {
while (obj) {
Swig_print_node(obj);
obj = nextSibling(obj);
}
}
/* -----------------------------------------------------------------------------
* appendChild()
*
* Appends a new child to a node
* ----------------------------------------------------------------------------- */
void
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 (chd) {
lc = chd;
set_parentNode(chd,node);
chd = nextSibling(chd);
}
set_lastChild(node,lc);
}
/* -----------------------------------------------------------------------------
* preppendChild()
*
* Preppends a new child to a node
* ----------------------------------------------------------------------------- */
void
preppendChild(Node *node, Node *chd) {
Node *fc;
if (!chd) return;
fc = firstChild(node);
if (fc) {
set_nextSibling(chd,fc);
set_previousSibling(fc,chd);
}
set_firstChild(node,chd);
while (chd) {
set_parentNode(chd,node);
chd = nextSibling(chd);
}
}
/* -----------------------------------------------------------------------------
* deleteNode()
*
* Deletes a 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);
}
}
}
/* -----------------------------------------------------------------------------
* copyNode()
*
* Copies a node, but only copies simple attributes (no lists, hashes).
* ----------------------------------------------------------------------------- */
Node *
copyNode(Node *n) {
Iterator ki;
Node *c = NewHash();
for (ki = First(n); ki.key; ki = Next(ki)) {
if (DohIsString(ki.item)) {
Setattr(c,ki.key,Copy(ki.item));
}
}
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);
}
}
/* -----------------------------------------------------------------------------
* checkAttribute()
* ----------------------------------------------------------------------------- */
int
checkAttribute(Node *n, const String_or_char *name, const String_or_char *value) {
String *v = Getattr(n,name);
return v ? Equal(v,value) : 0;
}
/* -----------------------------------------------------------------------------
* Swig_require()
* ns - namespace for the view name for saving any attributes under
* n - node
* ... - list of attribute names of type char*
* This method checks that the attribute names exist in the node n and asserts if
* not. Assert will only occur unless the attribute is optional. An attribute is
* optional if it is prefixed by ?, eg "?value". If the attribute name is prefixed
* by * or ?, eg "*value" then a copy of the attribute is saved. The saved
* attributes will be restored on a subsequent call to Swig_restore(). All the
* saved attributes are saved in the view namespace (prefixed by ns).
* This function can be called more than once with different namespaces.
* ----------------------------------------------------------------------------- */
int
Swig_require(const char *ns, Node *n, ...) {
va_list ap;
char *name;
DOH *obj;
char temp[512];
va_start(ap, n);
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) {
/* Save a copy of the attribute */
strcpy(temp,ns);
strcat(temp,":");
strcat(temp,name);
Setattr(n,temp,obj);
}
name = va_arg(ap, char *);
}
va_end(ap);
/* Save the view */
{
String *view = Getattr(n,"view");
if (view) {
if (Strcmp(view,ns) != 0) {
strcpy(temp,ns);
strcat(temp,":view");
Setattr(n,temp,view);
Setattr(n,"view",ns);
}
} else {
Setattr(n,"view",ns);
}
}
return 1;
}
/* -----------------------------------------------------------------------------
* Swig_save()
* Same as Swig_require(), but all attribute names are optional and all attributes
* are saved, ie behaves as if all the attribute names were prefixed by ?.
* ----------------------------------------------------------------------------- */
int
Swig_save(const char *ns, Node *n, ...) {
va_list ap;
char *name;
DOH *obj;
char temp[512];
va_start(ap, n);
name = va_arg(ap, char *);
while (name) {
if (*name == '*') {
name++;
} else if (*name == '?') {
name++;
}
obj = Getattr(n,name);
if (!obj) obj = DohNone;
/* Save a copy of the attribute */
strcpy(temp,ns);
strcat(temp,":");
strcat(temp,name);
if (Setattr(n,temp,obj)) {
Printf(stderr,"Swig_save('%s','%s'): Warning, attribute '%s' was already saved.\n", ns, nodeType(n), name);
}
name = va_arg(ap, char *);
}
va_end(ap);
/* Save the view */
{
String *view = Getattr(n,"view");
if (view) {
if (Strcmp(view,ns) != 0) {
strcpy(temp,ns);
strcat(temp,":view");
Setattr(n,temp,view);
Setattr(n,"view",ns);
}
} else {
Setattr(n,"view",ns);
}
}
return 1;
}
/* -----------------------------------------------------------------------------
* Swig_restore()
* Restores attributes saved by a previous call to Swig_require() or Swig_save().
* ----------------------------------------------------------------------------- */
void
Swig_restore(Node *n) {
char temp[512];
int len;
List *l;
String *ns;
Iterator ki;
ns = Getattr(n,"view");
assert(ns);
l = NewList();
strcpy(temp,Char(ns));
strcat(temp,":");
len = strlen(temp);
for (ki = First(n); ki.key; ki = Next(ki)) {
if (strncmp(temp,Char(ki.key),len) == 0) {
Append(l,ki.key);
}
}
for (ki = First(l); ki.item; ki = Next(ki)) {
DOH *obj = Getattr(n,ki.item);
Setattr(n,Char(ki.item)+len,obj);
Delattr(n,ki.item);
}
Delete(l);
}