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 * xml.cxx
6 *
7 * An Xml parse tree generator.
8 * ----------------------------------------------------------------------------- */
9
10char cvsroot_xml_cxx[] = "$Id: xml.cxx 10898 2008-11-03 12:51:45Z wsfulton $";
11
12#include "swigmod.h"
13
14static const char *usage = "\
15XML Options (available with -xml)\n\
16     -xmllang <lang> - Typedef language\n\
17     -xmllite        - More lightweight version of XML\n\
18     ------\n\
19     deprecated (use -o): -xml <output.xml> - Use <output.xml> as output file (extension .xml mandatory)\n";
20
21static File *out = 0;
22static int xmllite = 0;
23
24
25class XML:public Language {
26public:
27
28  int indent_level;
29  long id;
30
31  XML() :indent_level(0) , id(0) {
32  }
33
34  virtual ~ XML() {
35  }
36
37  virtual void main(int argc, char *argv[]) {
38    SWIG_typemap_lang("xml");
39    for (int iX = 0; iX < argc; iX++) {
40      if (strcmp(argv[iX], "-xml") == 0) {
41	char *extension = 0;
42	if (iX + 1 >= argc)
43	  continue;
44	extension = argv[iX + 1] + strlen(argv[iX + 1]) - 4;
45	if (strcmp(extension, ".xml"))
46	  continue;
47	iX++;
48	Swig_mark_arg(iX);
49	String *outfile = NewString(argv[iX]);
50	out = NewFile(outfile, "w", SWIG_output_files());
51	if (!out) {
52	  FileErrorDisplay(outfile);
53	  SWIG_exit(EXIT_FAILURE);
54	}
55	continue;
56      }
57      if (strcmp(argv[iX], "-xmllang") == 0) {
58	Swig_mark_arg(iX);
59	iX++;
60	SWIG_typemap_lang(argv[iX]);
61	Swig_mark_arg(iX);
62	continue;
63      }
64      if (strcmp(argv[iX], "-help") == 0) {
65	fputs(usage, stdout);
66      }
67      if (strcmp(argv[iX], "-xmllite") == 0) {
68	Swig_mark_arg(iX);
69	xmllite = 1;
70      }
71    }
72
73    // Add a symbol to the parser for conditional compilation
74    Preprocessor_define("SWIGXML 1", 0);
75  }
76
77  /* Top of the parse tree */
78
79  virtual int top(Node *n) {
80    if (out == 0) {
81      String *outfile = Getattr(n, "outfile");
82      Replaceall(outfile, ".cxx", ".xml");
83      Replaceall(outfile, ".cpp", ".xml");
84      Replaceall(outfile, ".c", ".xml");
85      out = NewFile(outfile, "w", SWIG_output_files());
86      if (!out) {
87	FileErrorDisplay(outfile);
88	SWIG_exit(EXIT_FAILURE);
89      }
90    }
91    Printf(out, "<?xml version=\"1.0\" ?> \n");
92    Xml_print_tree(n);
93    return SWIG_OK;
94  }
95
96  void print_indent(int l) {
97    int i;
98    for (i = 0; i < indent_level; i++) {
99      Printf(out, " ");
100    }
101    if (l) {
102      Printf(out, " ");
103    }
104  }
105
106  void Xml_print_tree(DOH *obj) {
107    while (obj) {
108      Xml_print_node(obj);
109      obj = nextSibling(obj);
110    }
111  }
112
113  void Xml_print_attributes(Node *obj) {
114    String *k;
115    indent_level += 4;
116    print_indent(0);
117    Printf(out, "<attributelist id=\"%ld\" addr=\"%x\" >\n", ++id, obj);
118    indent_level += 4;
119    Iterator ki;
120    ki = First(obj);
121    while (ki.key) {
122      k = ki.key;
123      if ((Cmp(k, "nodeType") == 0)
124	  || (Cmp(k, "firstChild") == 0)
125	  || (Cmp(k, "lastChild") == 0)
126	  || (Cmp(k, "parentNode") == 0)
127	  || (Cmp(k, "nextSibling") == 0)
128	  || (Cmp(k, "previousSibling") == 0)
129	  || (*(Char(k)) == '$')) {
130	/* Do nothing */
131      } else if (Cmp(k, "module") == 0) {
132	Xml_print_module(Getattr(obj, k));
133      } else if (Cmp(k, "baselist") == 0) {
134	Xml_print_baselist(Getattr(obj, k));
135      } else if (!xmllite && Cmp(k, "typescope") == 0) {
136	Xml_print_typescope(Getattr(obj, k));
137      } else if (!xmllite && Cmp(k, "typetab") == 0) {
138	Xml_print_typetab(Getattr(obj, k));
139      } else if (Cmp(k, "kwargs") == 0) {
140	Xml_print_kwargs(Getattr(obj, k));
141      } else if (Cmp(k, "parms") == 0 || Cmp(k, "pattern") == 0) {
142	Xml_print_parmlist(Getattr(obj, k));
143      } else {
144	DOH *o;
145	print_indent(0);
146	if (DohIsString(Getattr(obj, k))) {
147	  String *ck = NewString(k);
148	  o = Str(Getattr(obj, k));
149	  Replaceall(ck, ":", "_");
150	  Replaceall(ck, "<", "&lt;");
151	  /* Do first to avoid aliasing errors. */
152	  Replaceall(o, "&", "&amp;");
153	  Replaceall(o, "<", "&lt;");
154	  Replaceall(o, "\"", "&quot;");
155	  Replaceall(o, "\\", "\\\\");
156	  Replaceall(o, "\n", "&#10;");
157	  Printf(out, "<attribute name=\"%s\" value=\"%s\" id=\"%ld\" addr=\"%x\" />\n", ck, o, ++id, o);
158	  Delete(o);
159	  Delete(ck);
160	} else {
161	  o = Getattr(obj, k);
162	  String *ck = NewString(k);
163	  Replaceall(ck, ":", "_");
164	  Printf(out, "<attribute name=\"%s\" value=\"%x\" id=\"%ld\" addr=\"%x\" />\n", ck, o, ++id, o);
165	  Delete(ck);
166	}
167      }
168      ki = Next(ki);
169    }
170    indent_level -= 4;
171    print_indent(0);
172    Printf(out, "</attributelist >\n");
173    indent_level -= 4;
174  }
175
176  void Xml_print_node(Node *obj) {
177    Node *cobj;
178
179    print_indent(0);
180    Printf(out, "<%s id=\"%ld\" addr=\"%x\" >\n", nodeType(obj), ++id, obj);
181    Xml_print_attributes(obj);
182    cobj = firstChild(obj);
183    if (cobj) {
184      indent_level += 4;
185      Printf(out, "\n");
186      Xml_print_tree(cobj);
187      indent_level -= 4;
188    } else {
189      print_indent(1);
190      Printf(out, "\n");
191    }
192    print_indent(0);
193    Printf(out, "</%s >\n", nodeType(obj));
194  }
195
196
197  void Xml_print_parmlist(ParmList *p) {
198
199    print_indent(0);
200    Printf(out, "<parmlist id=\"%ld\" addr=\"%x\" >\n", ++id, p);
201    indent_level += 4;
202    while (p) {
203      print_indent(0);
204      Printf(out, "<parm id=\"%ld\">\n", ++id);
205      Xml_print_attributes(p);
206      print_indent(0);
207      Printf(out, "</parm >\n");
208      p = nextSibling(p);
209    }
210    indent_level -= 4;
211    print_indent(0);
212    Printf(out, "</parmlist >\n");
213  }
214
215  void Xml_print_baselist(List *p) {
216
217    print_indent(0);
218    Printf(out, "<baselist id=\"%ld\" addr=\"%x\" >\n", ++id, p);
219    indent_level += 4;
220    Iterator s;
221    for (s = First(p); s.item; s = Next(s)) {
222      print_indent(0);
223      String *item_name = Xml_escape_string(s.item);
224      Printf(out, "<base name=\"%s\" id=\"%ld\" addr=\"%x\" />\n", item_name, ++id, s.item);
225      Delete(item_name);
226    }
227    indent_level -= 4;
228    print_indent(0);
229    Printf(out, "</baselist >\n");
230  }
231
232  String *Xml_escape_string(String *str) {
233    String *escaped_str = 0;
234    if (str) {
235      escaped_str = NewString(str);
236      Replaceall(escaped_str, "&", "&amp;");
237      Replaceall(escaped_str, "<", "&lt;");
238      Replaceall(escaped_str, "\"", "&quot;");
239      Replaceall(escaped_str, "\\", "\\\\");
240      Replaceall(escaped_str, "\n", "&#10;");
241    }
242    return escaped_str;
243  }
244
245  void Xml_print_module(Node *p) {
246
247    print_indent(0);
248    Printf(out, "<attribute name=\"module\" value=\"%s\" id=\"%ld\" addr=\"%x\" />\n", Getattr(p, "name"), ++id, p);
249  }
250
251  void Xml_print_kwargs(Hash *p) {
252    Xml_print_hash(p, "kwargs");
253  }
254
255  void Xml_print_typescope(Hash *p) {
256
257    Xml_print_hash(p, "typescope");
258  }
259
260  void Xml_print_typetab(Hash *p) {
261
262    Xml_print_hash(p, "typetab");
263  }
264
265
266  void Xml_print_hash(Hash *p, const char *markup) {
267
268    print_indent(0);
269    Printf(out, "<%s id=\"%ld\" addr=\"%x\" >\n", markup, ++id, p);
270    Xml_print_attributes(p);
271    indent_level += 4;
272    Iterator n = First(p);
273    while (n.key) {
274      print_indent(0);
275      Printf(out, "<%ssitem id=\"%ld\" addr=\"%x\" >\n", markup, ++id, n.item);
276      Xml_print_attributes(n.item);
277      print_indent(0);
278      Printf(out, "</%ssitem >\n", markup);
279      n = Next(n);
280    }
281    indent_level -= 4;
282    print_indent(0);
283    Printf(out, "</%s >\n", markup);
284  }
285
286};
287
288/* -----------------------------------------------------------------------------
289 * Swig_print_xml
290 *
291 * Dump an XML version of the parse tree.  This is different from using the -xml
292 * language module normally as it allows the real language module to process the
293 * tree first, possibly stuffing in new attributes, so the XML that is output ends
294 * up being a post-processing version of the tree.
295 * ----------------------------------------------------------------------------- */
296
297void Swig_print_xml(DOH *obj, String *filename) {
298  XML xml;
299  xmllite = 1;
300
301  if (!filename) {
302    out = stdout;
303  } else {
304    out = NewFile(filename, "w", SWIG_output_files());
305    if (!out) {
306      FileErrorDisplay(filename);
307      SWIG_exit(EXIT_FAILURE);
308    }
309  }
310
311  Printf(out, "<?xml version=\"1.0\" ?> \n");
312  xml.Xml_print_tree(obj);
313}
314
315static Language *new_swig_xml() {
316  return new XML();
317}
318extern "C" Language *swig_xml(void) {
319  return new_swig_xml();
320}
321