import source from 1.3.40
[external/swig.git] / Source / Swig / tree.c
1 /* -----------------------------------------------------------------------------
2  * See the LICENSE file for information on copyright, usage and redistribution
3  * of SWIG, and the README file for authors - http://www.swig.org/release.html.
4  *
5  * tree.c
6  *
7  * This file provides some general purpose functions for manipulating
8  * parse trees.
9  * ----------------------------------------------------------------------------- */
10
11 char cvsroot_tree_c[] = "$Id: tree.c 11080 2009-01-24 13:15:51Z bhy $";
12
13 #include "swig.h"
14 #include <stdarg.h>
15 #include <assert.h>
16
17 /* -----------------------------------------------------------------------------
18  * Swig_print_tags()
19  *
20  * Dump the tag structure of a parse tree to standard output
21  * ----------------------------------------------------------------------------- */
22
23 void Swig_print_tags(DOH *obj, DOH *root) {
24   DOH *croot, *newroot;
25   DOH *cobj;
26
27   if (!root)
28     croot = NewStringEmpty();
29   else
30     croot = root;
31
32   while (obj) {
33     Printf(stdout, "%s . %s (%s:%d)\n", croot, nodeType(obj), Getfile(obj), Getline(obj));
34     cobj = firstChild(obj);
35     if (cobj) {
36       newroot = NewStringf("%s . %s", croot, nodeType(obj));
37       Swig_print_tags(cobj, newroot);
38       Delete(newroot);
39     }
40     obj = nextSibling(obj);
41   }
42   if (!root)
43     Delete(croot);
44 }
45
46 static int indent_level = 0;
47
48 static void print_indent(int l) {
49   int i;
50   for (i = 0; i < indent_level; i++) {
51     fputc(' ', stdout);
52   }
53   if (l) {
54     fputc('|', stdout);
55     fputc(' ', stdout);
56   }
57 }
58
59
60 /* -----------------------------------------------------------------------------
61  * Swig_print_node(Node *n)
62  * ----------------------------------------------------------------------------- */
63
64 void Swig_print_node(Node *obj) {
65   Iterator ki;
66   Node *cobj;
67
68   print_indent(0);
69   Printf(stdout, "+++ %s ----------------------------------------\n", nodeType(obj));
70   ki = First(obj);
71   while (ki.key) {
72     String *k = ki.key;
73     if ((Cmp(k, "nodeType") == 0) || (Cmp(k, "firstChild") == 0) || (Cmp(k, "lastChild") == 0) ||
74         (Cmp(k, "parentNode") == 0) || (Cmp(k, "nextSibling") == 0) || (Cmp(k, "previousSibling") == 0) || (*(Char(k)) == '$')) {
75       /* Do nothing */
76     } else if (Cmp(k, "parms") == 0) {
77       print_indent(2);
78       Printf(stdout, "%-12s - %s\n", k, ParmList_protostr(Getattr(obj, k)));
79     } else {
80       DOH *o;
81       char *trunc = "";
82       print_indent(2);
83       if (DohIsString(Getattr(obj, k))) {
84         o = Str(Getattr(obj, k));
85         if (Len(o) > 80) {
86           trunc = "...";
87         }
88         Printf(stdout, "%-12s - \"%(escape)-0.80s%s\"\n", k, o, trunc);
89         Delete(o);
90       } else {
91         Printf(stdout, "%-12s - 0x%x\n", k, Getattr(obj, k));
92       }
93     }
94     ki = Next(ki);
95   }
96   cobj = firstChild(obj);
97   if (cobj) {
98     indent_level += 6;
99     Printf(stdout, "\n");
100     Swig_print_tree(cobj);
101     indent_level -= 6;
102   } else {
103     print_indent(1);
104     Printf(stdout, "\n");
105   }
106 }
107
108 /* -----------------------------------------------------------------------------
109  * Swig_print_tree()
110  *
111  * Dump the tree structure of a parse tree to standard output
112  * ----------------------------------------------------------------------------- */
113
114 void Swig_print_tree(DOH *obj) {
115   while (obj) {
116     Swig_print_node(obj);
117     obj = nextSibling(obj);
118   }
119 }
120
121 /* -----------------------------------------------------------------------------
122  * appendChild()
123  *
124  * Appends a new child to a node
125  * ----------------------------------------------------------------------------- */
126
127 void appendChild(Node *node, Node *chd) {
128   Node *lc;
129
130   if (!chd)
131     return;
132
133   lc = lastChild(node);
134   if (!lc) {
135     set_firstChild(node, chd);
136   } else {
137     set_nextSibling(lc, chd);
138     set_previousSibling(chd, lc);
139   }
140   while (chd) {
141     lc = chd;
142     set_parentNode(chd, node);
143     chd = nextSibling(chd);
144   }
145   set_lastChild(node, lc);
146 }
147
148 /* -----------------------------------------------------------------------------
149  * prependChild()
150  *
151  * Prepends a new child to a node
152  * ----------------------------------------------------------------------------- */
153
154 void prependChild(Node *node, Node *chd) {
155   Node *fc;
156
157   if (!chd)
158     return;
159
160   fc = firstChild(node);
161   if (fc) {
162     set_nextSibling(chd, fc);
163     set_previousSibling(fc, chd);
164   }
165   set_firstChild(node, chd);
166   while (chd) {
167     set_parentNode(chd, node);
168     chd = nextSibling(chd);
169   }
170 }
171
172 /* -----------------------------------------------------------------------------
173  * removeNode()
174  *
175  * Removes a node from the parse tree.  Detaches it from its parent's child list.
176  * ----------------------------------------------------------------------------- */
177
178 void removeNode(Node *n) {
179   Node *parent;
180   Node *prev;
181   Node *next;
182
183   parent = parentNode(n);
184   if (!parent) return;
185
186   prev = previousSibling(n);
187   next = nextSibling(n);
188   if (prev) {
189     set_nextSibling(prev, next);
190   } else {
191     if (parent) {
192       set_firstChild(parent, next);
193     }
194   }
195   if (next) {
196     set_previousSibling(next, prev);
197   } else {
198     if (parent) {
199       set_lastChild(parent, prev);
200     }
201   }
202
203   /* Delete attributes */
204   Delattr(n,"parentNode");
205   Delattr(n,"nextSibling");
206   Delattr(n,"prevSibling");
207 }
208
209 /* -----------------------------------------------------------------------------
210  * copyNode()
211  *
212  * Copies a node, but only copies simple attributes (no lists, hashes).
213  * ----------------------------------------------------------------------------- */
214
215 Node *copyNode(Node *n) {
216   Iterator ki;
217   Node *c = NewHash();
218   for (ki = First(n); ki.key; ki = Next(ki)) {
219     if (DohIsString(ki.item)) {
220       Setattr(c, ki.key, Copy(ki.item));
221     }
222   }
223   Setfile(c, Getfile(n));
224   Setline(c, Getline(n));
225   return c;
226 }
227
228 /* -----------------------------------------------------------------------------
229  * checkAttribute()
230  * ----------------------------------------------------------------------------- */
231
232 int checkAttribute(Node *n, const_String_or_char_ptr name, const_String_or_char_ptr value) {
233   String *v = Getattr(n, name);
234   return v ? Equal(v, value) : 0;
235 }
236
237 /* -----------------------------------------------------------------------------
238  * Swig_require()
239  * ns   - namespace for the view name for saving any attributes under
240  * n    - node
241  * ...  - list of attribute names of type char*
242  * This method checks that the attribute names exist in the node n and asserts if
243  * not. Assert will only occur unless the attribute is optional. An attribute is
244  * optional if it is prefixed by ?, eg "?value". If the attribute name is prefixed
245  * by * or ?, eg "*value" then a copy of the attribute is saved. The saved
246  * attributes will be restored on a subsequent call to Swig_restore(). All the
247  * saved attributes are saved in the view namespace (prefixed by ns).
248  * This function can be called more than once with different namespaces.
249  * ----------------------------------------------------------------------------- */
250
251 void Swig_require(const char *ns, Node *n, ...) {
252   va_list ap;
253   char *name;
254   DOH *obj;
255
256   va_start(ap, n);
257   name = va_arg(ap, char *);
258   while (name) {
259     int newref = 0;
260     int opt = 0;
261     if (*name == '*') {
262       newref = 1;
263       name++;
264     } else if (*name == '?') {
265       newref = 1;
266       opt = 1;
267       name++;
268     }
269     obj = Getattr(n, name);
270     if (!opt && !obj) {
271       Printf(stderr, "%s:%d. Fatal error (Swig_require).  Missing attribute '%s' in node '%s'.\n", Getfile(n), Getline(n), name, nodeType(n));
272       assert(obj);
273     }
274     if (!obj)
275       obj = DohNone;
276     if (newref) {
277       /* Save a copy of the attribute */
278       Setattr(n, NewStringf("%s:%s", ns, name), obj);
279     }
280     name = va_arg(ap, char *);
281   }
282   va_end(ap);
283
284   /* Save the view */
285   {
286     String *view = Getattr(n, "view");
287     if (view) {
288       if (Strcmp(view, ns) != 0) {
289         Setattr(n, NewStringf("%s:view", ns), view);
290         Setattr(n, "view", ns);
291       }
292     } else {
293       Setattr(n, "view", ns);
294     }
295   }
296 }
297
298
299 /* -----------------------------------------------------------------------------
300  * Swig_save()
301  * Same as Swig_require(), but all attribute names are optional and all attributes
302  * are saved, ie behaves as if all the attribute names were prefixed by ?.
303  * ----------------------------------------------------------------------------- */
304
305 void Swig_save(const char *ns, Node *n, ...) {
306   va_list ap;
307   char *name;
308   DOH *obj;
309
310   va_start(ap, n);
311   name = va_arg(ap, char *);
312   while (name) {
313     if (*name == '*') {
314       name++;
315     } else if (*name == '?') {
316       name++;
317     }
318     obj = Getattr(n, name);
319     if (!obj)
320       obj = DohNone;
321
322     /* Save a copy of the attribute */
323     if (Setattr(n, NewStringf("%s:%s", ns, name), obj)) {
324       Printf(stderr, "Swig_save('%s','%s'): Warning, attribute '%s' was already saved.\n", ns, nodeType(n), name);
325     }
326     name = va_arg(ap, char *);
327   }
328   va_end(ap);
329
330   /* Save the view */
331   {
332     String *view = Getattr(n, "view");
333     if (view) {
334       if (Strcmp(view, ns) != 0) {
335         Setattr(n, NewStringf("%s:view", ns), view);
336         Setattr(n, "view", ns);
337       }
338     } else {
339       Setattr(n, "view", ns);
340     }
341   }
342 }
343
344 /* -----------------------------------------------------------------------------
345  * Swig_restore()
346  * Restores attributes saved by a previous call to Swig_require() or Swig_save().
347  * ----------------------------------------------------------------------------- */
348
349 void Swig_restore(Node *n) {
350   String *temp;
351   int len;
352   List *l;
353   String *ns;
354   Iterator ki;
355
356   ns = Getattr(n, "view");
357   assert(ns);
358
359   l = NewList();
360
361   temp = NewStringf("%s:", ns);
362   len = Len(temp);
363
364   for (ki = First(n); ki.key; ki = Next(ki)) {
365     if (Strncmp(temp, ki.key, len) == 0) {
366       Append(l, ki.key);
367     }
368   }
369   for (ki = First(l); ki.item; ki = Next(ki)) {
370     DOH *obj = Getattr(n, ki.item);
371     Setattr(n, Char(ki.item) + len, obj);
372     Delattr(n, ki.item);
373   }
374   Delete(l);
375   Delete(temp);
376 }