git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@516 626c5289-ae23-0410-ae9c-e8d60b6d4f22
191 lines
5.1 KiB
C
191 lines
5.1 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"
|
|
|
|
static char cvsroot[] = "$Header$";
|
|
|
|
static DOHHash *rules = 0;
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_next()
|
|
* Swig_prev()
|
|
*
|
|
* Return next/prev node in a parse tree
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
DOH *Swig_next(DOH *obj) {
|
|
return Getattr(obj,"next");
|
|
}
|
|
|
|
DOH *Swig_prev(DOH *obj) {
|
|
return Getattr(obj,"prev");
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_dump_tags()
|
|
*
|
|
* Dump the tag structure of a parse tree to standard output
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
void
|
|
Swig_dump_tags(DOH *obj, DOH *root) {
|
|
DOH *croot, *newroot;
|
|
DOH *cobj;
|
|
|
|
if (!root) croot = NewString("");
|
|
else croot = root;
|
|
|
|
while (obj) {
|
|
Printf(stdout,"%s.%s\n", croot, Getattr(obj,"tag"));
|
|
cobj = Getattr(obj,"child");
|
|
if (cobj) {
|
|
newroot = NewStringf("%s.%s",croot,Getattr(obj,"tag"));
|
|
Swig_dump_tags(cobj,newroot);
|
|
Delete(newroot);
|
|
}
|
|
obj = Swig_next(obj);
|
|
}
|
|
if (!root)
|
|
Delete(croot);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_add_rule()
|
|
*
|
|
* Adds a new rule to the tree walking code.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
void
|
|
Swig_add_rule(DOHString_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);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* 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();
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* int Swig_emit()
|
|
*
|
|
* Emit an action for a specific object
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
int
|
|
Swig_emit(DOH *obj, void *clientdata) {
|
|
DOH *tag;
|
|
DOH *actionobj;
|
|
int (*action)(DOH *obj, void *clientdata);
|
|
|
|
int ret;
|
|
|
|
assert(obj);
|
|
|
|
if (!rules) return -1;
|
|
while (obj) {
|
|
tag = Getattr(obj,"tag");
|
|
actionobj = Getattr(rules,tag);
|
|
if (actionobj) {
|
|
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);
|
|
}
|
|
obj = Swig_next(obj);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_cut_node(DOH *obj)
|
|
*
|
|
* 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) {
|
|
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 update the parent 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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|