summaryrefslogtreecommitdiff
path: root/Source/Swig/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Swig/tree.c')
-rw-r--r--Source/Swig/tree.c376
1 files changed, 376 insertions, 0 deletions
diff --git a/Source/Swig/tree.c b/Source/Swig/tree.c
new file mode 100644
index 0000000..877b624
--- /dev/null
+++ b/Source/Swig/tree.c
@@ -0,0 +1,376 @@
+/* -----------------------------------------------------------------------------
+ * See the LICENSE file for information on copyright, usage and redistribution
+ * of SWIG, and the README file for authors - http://www.swig.org/release.html.
+ *
+ * tree.c
+ *
+ * This file provides some general purpose functions for manipulating
+ * parse trees.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_tree_c[] = "$Id: tree.c 11080 2009-01-24 13:15:51Z bhy $";
+
+#include "swig.h"
+#include <stdarg.h>
+#include <assert.h>
+
+/* -----------------------------------------------------------------------------
+ * 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_print_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) > 80) {
+ trunc = "...";
+ }
+ Printf(stdout, "%-12s - \"%(escape)-0.80s%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);
+}
+
+/* -----------------------------------------------------------------------------
+ * prependChild()
+ *
+ * Prepends a new child to a node
+ * ----------------------------------------------------------------------------- */
+
+void prependChild(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);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * removeNode()
+ *
+ * Removes a node from the parse tree. Detaches it from its parent's child list.
+ * ----------------------------------------------------------------------------- */
+
+void removeNode(Node *n) {
+ Node *parent;
+ Node *prev;
+ Node *next;
+
+ parent = parentNode(n);
+ if (!parent) return;
+
+ 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);
+ }
+ }
+
+ /* Delete attributes */
+ Delattr(n,"parentNode");
+ Delattr(n,"nextSibling");
+ Delattr(n,"prevSibling");
+}
+
+/* -----------------------------------------------------------------------------
+ * 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;
+}
+
+/* -----------------------------------------------------------------------------
+ * checkAttribute()
+ * ----------------------------------------------------------------------------- */
+
+int checkAttribute(Node *n, const_String_or_char_ptr name, const_String_or_char_ptr 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.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_require(const char *ns, Node *n, ...) {
+ va_list ap;
+ char *name;
+ DOH *obj;
+
+ 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 */
+ Setattr(n, NewStringf("%s:%s", ns, name), obj);
+ }
+ name = va_arg(ap, char *);
+ }
+ va_end(ap);
+
+ /* Save the view */
+ {
+ String *view = Getattr(n, "view");
+ if (view) {
+ if (Strcmp(view, ns) != 0) {
+ Setattr(n, NewStringf("%s:view", ns), view);
+ Setattr(n, "view", ns);
+ }
+ } else {
+ Setattr(n, "view", ns);
+ }
+ }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * 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 ?.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_save(const char *ns, Node *n, ...) {
+ va_list ap;
+ char *name;
+ DOH *obj;
+
+ 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 */
+ if (Setattr(n, NewStringf("%s:%s", ns, name), 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) {
+ Setattr(n, NewStringf("%s:view", ns), view);
+ Setattr(n, "view", ns);
+ }
+ } else {
+ Setattr(n, "view", ns);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_restore()
+ * Restores attributes saved by a previous call to Swig_require() or Swig_save().
+ * ----------------------------------------------------------------------------- */
+
+void Swig_restore(Node *n) {
+ String *temp;
+ int len;
+ List *l;
+ String *ns;
+ Iterator ki;
+
+ ns = Getattr(n, "view");
+ assert(ns);
+
+ l = NewList();
+
+ temp = NewStringf("%s:", ns);
+ len = Len(temp);
+
+ for (ki = First(n); ki.key; ki = Next(ki)) {
+ if (Strncmp(temp, 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);
+ Delete(temp);
+}