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 * browser.cxx
6 *
7 * A web-base parse tree browser using SWILL.   This is an optional
8 * feature that's normally disabled.
9 * ----------------------------------------------------------------------------- */
10
11char cvsroot_browser_cxx[] = "$Id: browser.cxx 10003 2007-10-17 21:42:11Z wsfulton $";
12
13#include "swigmod.h"
14
15#ifdef SWIG_SWILL
16extern "C" {
17#include "swill.h"
18} static FILE *out = 0;
19static Node *view_top = 0;
20
21class Browser:public Dispatcher {
22  void show_checkbox(Node *t, Node *n) {
23    int v = 0;
24    if (Getmeta(n, "visible")) {
25      v = 1;
26    }
27    if (v) {
28      Printf(out, "<a name=\"n%x\"></a>[<a href=\"hide.html?node=0x%x&hn=0x%x#n%x\">-</a>] ", n, t, n, n);
29    } else {
30      Printf(out, "<a name=\"n%x\"></a>[<a href=\"show.html?node=0x%x&hn=0x%x#n%x\">+</a>] ", n, t, n, n);
31    }
32  }
33  void show_attributes(Node *obj) {
34    if (!Getmeta(obj, "visible"))
35      return;
36    String *os = NewString("");
37    String *k;
38    Iterator ki;
39    ki = First(obj);
40    while (ki.key) {
41      k = ki.key;
42      if ((Cmp(k, "nodeType") == 0) || (Cmp(k, "firstChild") == 0) || (Cmp(k, "lastChild") == 0) ||
43	  (Cmp(k, "parentNode") == 0) || (Cmp(k, "nextSibling") == 0) || (Cmp(k, "previousSibling") == 0) || (*(Char(k)) == '$')) {
44	/* Do nothing */
45      } else if (Cmp(k, "parms") == 0) {
46	String *o = NewString("");
47	Printf(o, "%s", ParmList_protostr(Getattr(obj, k)));
48	Replaceall(o, "&", "&amp;");
49	Replaceall(o, "<", "&lt;");
50	Replaceall(o, ">", "&gt;");
51	Printf(os, "<a href=\"data.html?n=0x%x\">?</a> %-12s - %s\n", Getattr(obj, k), k, o);
52	Delete(o);
53      } else {
54	DOH *o;
55	char *trunc = "";
56	if (DohIsString(Getattr(obj, k))) {
57	  o = Str(Getattr(obj, k));
58	  if (Len(o) > 70) {
59	    trunc = "...";
60	  }
61	  Replaceall(o, "&", "&amp;");
62	  Replaceall(o, "<", "&lt;");
63	  Printf(os, "<a href=\"data.html?n=0x%x\">?</a> %-12s - \"%(escape)-0.70s%s\"\n", Getattr(obj, k), k, o, trunc);
64	  Delete(o);
65	} else {
66	  Printf(os, "<a href=\"data.html?n=0x%x\">?</a> %-12s - 0x%x\n", Getattr(obj, k), k, Getattr(obj, k));
67	}
68      }
69      ki = Next(ki);
70    }
71    Printf(out, "<FONT color=\"#660000\"><pre>\n%s</pre></FONT>\n", Char(os));
72    Delete(os);
73  }
74
75public:
76  virtual int emit_one(Node *n) {
77    char *tag = Char(nodeType(n));
78    char *file = Char(Getfile(n));
79    int line = Getline(n);
80    char *name = GetChar(n, "name");
81
82    show_checkbox(view_top, n);
83    Printf(out, "<b><a href=\"index.html?node=0x%x\">%s</a></b>", n, tag);
84    if (name) {
85      Printf(out, " (%s)", name);
86    }
87    Printf(out, ".  %s:%d\n", file, line);
88    Printf(out, "<br>");
89    Dispatcher::emit_one(n);
90    return SWIG_OK;
91  }
92  virtual int emit_children(Node *n) {
93    if (Getmeta(n, "visible")) {
94      Printf(out, "<blockquote>\n");
95      Dispatcher::emit_children(n);
96      Printf(out, "</blockquote>\n");
97    }
98    return SWIG_OK;
99  }
100  virtual int defaultHandler(Node *n) {
101    show_attributes(n);
102    return SWIG_OK;
103  }
104  virtual int top(Node *n) {
105    show_attributes(n);
106    emit_children(n);
107    return SWIG_OK;
108  }
109  virtual int includeDirective(Node *n) {
110    show_attributes(n);
111    emit_children(n);
112    return SWIG_OK;
113  }
114  virtual int importDirective(Node *n) {
115    show_attributes(n);
116    emit_children(n);
117    return SWIG_OK;
118  }
119
120  virtual int extendDirective(Node *n) {
121    show_attributes(n);
122    emit_children(n);
123    return SWIG_OK;
124  }
125  virtual int classDeclaration(Node *n) {
126    show_attributes(n);
127    emit_children(n);
128    return SWIG_OK;
129  }
130
131  virtual int templateDeclaration(Node *n) {
132    show_attributes(n);
133    emit_children(n);
134    return SWIG_OK;
135  }
136
137  virtual int enumDeclaration(Node *n) {
138    show_attributes(n);
139    emit_children(n);
140    return SWIG_OK;
141  }
142  virtual int typemapDirective(Node *n) {
143    show_attributes(n);
144    emit_children(n);
145    return SWIG_OK;
146  }
147  virtual int namespaceDeclaration(Node *n) {
148    show_attributes(n);
149    emit_children(n);
150    return SWIG_OK;
151  }
152  virtual int usingDeclaration(Node *n) {
153    show_attributes(n);
154    emit_children(n);
155    return SWIG_OK;
156  }
157
158};
159
160static int browser_exit = 0;
161static Node *tree_top = 0;
162static Browser *browse = 0;
163
164/* ----------------------------------------------------------------------
165 * exit_handler()      - Force the browser to exit
166 * ---------------------------------------------------------------------- */
167
168void exit_handler(FILE *f) {
169  browser_exit = 1;
170  Printf(f, "Terminated.\n");
171}
172
173/* ----------------------------------------------------------------------
174 * node_handler()      - Generate information about a specific node
175 * ---------------------------------------------------------------------- */
176
177static void display(FILE *f, Node *n) {
178  /* Print standard HTML header */
179
180  Printf(f, "<HTML><HEAD><TITLE>SWIG-%s</TITLE></HEAD><BODY BGCOLOR=\"#ffffff\">\n", Swig_package_version());
181  Printf(f, "<b>SWIG-%s</b><br>\n", Swig_package_version());
182  Printf(f, "[ <a href=\"exit.html\">Exit</a> ]");
183  Printf(f, " [ <a href=\"index.html?node=0x%x\">Top</a> ]", tree_top);
184  if (n != tree_top) {
185    Printf(f, " [ <a href=\"index.html?node=0x%x\">Up</a> ]", parentNode(n));
186  }
187  Printf(f, " [ <a href=\"symbol.html\">Symbols</a> ]");
188  Printf(f, "<br><hr><p>\n");
189
190  out = f;
191
192  browse->emit_one(n);
193
194  /* Print standard footer */
195  Printf(f, "<br><hr></BODY></HTML>\n");
196
197}
198
199void node_handler(FILE *f) {
200  Node *n = 0;
201  if (!swill_getargs("p(node)", &n)) {
202    n = tree_top;
203  }
204  view_top = n;
205  display(f, n);
206}
207
208
209/* ----------------------------------------------------------------------
210 * hide_handler()      - Hide a node
211 * ---------------------------------------------------------------------- */
212
213void hide_handler(FILE *f) {
214  Node *n = 0;
215  if (!swill_getargs("p(hn)", &n)) {
216    n = 0;
217  }
218  if (n) {
219    Delmeta(n, "visible");
220  }
221  node_handler(f);
222}
223
224void show_handler(FILE *f) {
225  Node *n = 0;
226  if (!swill_getargs("p(hn)", &n)) {
227    n = 0;
228  }
229  if (n) {
230    Setmeta(n, "visible", "1");
231  }
232  node_handler(f);
233}
234
235void raw_data(FILE *out, Node *obj) {
236  if (!obj)
237    return;
238  if (DohIsMapping(obj)) {
239    String *k;
240    Iterator ki;
241    String *os = NewString("");
242    Printf(os, "Hash {\n");
243    ki = First(obj);
244    while (ki.key) {
245      k = ki.key;
246      DOH *o;
247      const char *trunc = "";
248      if (DohIsString(Getattr(obj, k))) {
249	o = Str(Getattr(obj, k));
250	if (Len(o) > 70) {
251	  trunc = "...";
252	}
253	Replaceall(o, "<", "&lt;");
254	Printf(os, "    <a href=\"data.html?n=0x%x\">?</a> %-12s - \"%(escape)-0.70s%s\"\n", Getattr(obj, k), k, o, trunc);
255	Delete(o);
256      } else {
257	Printf(os, "    <a href=\"data.html?n=0x%x\">?</a> %-12s - 0x%x\n", Getattr(obj, k), k, Getattr(obj, k));
258      }
259      ki = Next(ki);
260    }
261    Printf(os, "}\n");
262    Printf(out, "<FONT color=\"#660000\"><pre>\n%s</pre></FONT>\n", Char(os));
263    Delete(os);
264  } else if (DohIsString(obj)) {
265    String *o = Str(obj);
266    Replaceall(o, "<", "&lt;");
267    Printf(out, "<FONT color=\"#660000\"><pre>\n%s</pre></FONT>\n", Char(o));
268    Delete(o);
269  } else if (DohIsSequence(obj)) {
270    int i;
271    String *os = NewString("");
272    Printf(os, "List [\n");
273    for (i = 0; i < Len(obj); i++) {
274      DOH *o = Getitem(obj, i);
275      const char *trunc = "";
276      if (DohIsString(o)) {
277	String *s = Str(o);
278	if (Len(s) > 70) {
279	  trunc = "...";
280	}
281	Replaceall(o, "<", "&lt;");
282	Printf(os, "    <a href=\"data.html?n=0x%x\">?</a> [%d] - \"%(escape)-0.70s%s\"\n", o, i, s, trunc);
283	Delete(s);
284      } else {
285	Printf(os, "    <a href=\"data.html?n=0x%x\">?</a> [%d] - 0x%x\n", o, i, o);
286      }
287    }
288    Printf(os, "\n]\n");
289    Printf(out, "<FONT color=\"#660000\"><pre>\n%s</pre></FONT>\n", Char(os));
290    Delete(os);
291  }
292}
293
294void data_handler(FILE *f) {
295  DOH *n = 0;
296  if (!swill_getargs("p(n)", &n)) {
297    n = 0;
298  }
299  Printf(f, "<HTML><HEAD><TITLE>SWIG-%s</TITLE></HEAD><BODY BGCOLOR=\"#ffffff\">\n", Swig_package_version());
300  Printf(f, "<b>SWIG-%s</b><br>\n", Swig_package_version());
301  Printf(f, "[ <a href=\"exit.html\">Exit</a> ]");
302  Printf(f, " [ <a href=\"index.html?node=0x%x\">Top</a> ]", tree_top);
303  Printf(f, "<br><hr><p>\n");
304  if (n) {
305    raw_data(f, n);
306  }
307  /* Print standard footer */
308  Printf(f, "<br><hr></BODY></HTML>\n");
309}
310
311void symbol_handler(FILE *f) {
312  Symtab *sym;
313  char *name = 0;
314
315  Printf(f, "<HTML><HEAD><TITLE>SWIG-%s</TITLE></HEAD><BODY BGCOLOR=\"#ffffff\">\n", Swig_package_version());
316  Printf(f, "<b>SWIG-%s</b><br>\n", Swig_package_version());
317  Printf(f, "[ <a href=\"exit.html\">Exit</a> ]");
318  Printf(f, " [ <a href=\"index.html?node=0x%x\">Top</a> ]", tree_top);
319  Printf(f, " [ <a href=\"symbol.html\">Symbols</a> ]");
320  Printf(f, "<br><hr><p>\n");
321
322  if (!swill_getargs("p(sym)|s(name)", &sym, &name)) {
323    sym = Swig_symbol_getscope("");
324    name = 0;
325  }
326  if (!sym) {
327    Printf(f, "No symbol table specified!\n");
328    return;
329  }
330  {
331    String *q = Swig_symbol_qualifiedscopename(sym);
332    if (!Len(q)) {
333      Printf(f, "<b>Symbol table: :: (global)</b><br>\n");
334    } else {
335      Printf(f, "<b>Symbol table: %s</b><br>\n", q);
336    }
337    Delete(q);
338  }
339
340  fprintf(f, "<p><form action=\"symbol.html\" method=GET>\n");
341  fprintf(f, "Symbol lookup: <input type=text name=name size=40></input><br>\n");
342  fprintf(f, "<input type=hidden name=sym value=\"0x%x\">\n", sym);
343  fprintf(f, "Submit : <input type=submit></input>\n");
344  fprintf(f, "</form>");
345
346  if (name) {
347    Node *n = Swig_symbol_clookup(name, sym);
348    Printf(f, "Symbol '%s':\n", name);
349    Printf(f, "<blockquote>\n");
350    if (!n) {
351      Printf(f, "Not defined!\n");
352    } else {
353      raw_data(f, n);
354    }
355    Printf(f, "</blockquote>\n");
356  }
357
358  Printf(f, "<p><b>Nested scopes</b><br>\n");
359  Printf(f, "<blockquote><pre>\n");
360  {
361    Hash *h;
362    h = firstChild(sym);
363    while (h) {
364      Printf(f, "<a href=\"symbol.html?sym=0x%x\">%s</a>\n", h, Getattr(h, "name"));
365      h = nextSibling(h);
366    }
367  }
368  Printf(f, "</pre></blockquote>\n");
369
370  Printf(f, "<p><b>Symbol table contents</b></br>\n");
371  raw_data(f, Getattr(sym, "symtab"));
372  Printf(f, "<br><hr></BODY></HTML>\n");
373
374}
375#endif
376
377void Swig_browser(Node *top, int port) {
378#ifdef SWIG_SWILL
379  int sport;
380  browser_exit = 0;
381
382  /* Initialize the server */
383  sport = swill_init(port);
384  if (sport < 0) {
385    Printf(stderr, "Couldn't open socket on port %d. Sorry.\n", port);
386    return;
387  }
388  browse = new Browser();
389  Setmeta(top, "visible", "1");
390  tree_top = top;
391
392  Printf(stderr, "SWIG: Tree browser listening on port %d\n", sport);
393
394  swill_handle("exit.html", exit_handler, 0);
395  swill_handle("index.html", node_handler, 0);
396  swill_handle("hide.html", hide_handler, 0);
397  swill_handle("show.html", show_handler, 0);
398  swill_handle("data.html", data_handler, 0);
399  swill_handle("symbol.html", symbol_handler, 0);
400  swill_netscape("index.html");
401
402  while (!browser_exit) {
403    swill_serve();
404  }
405  Printf(stderr, "Browser terminated.\n");
406  swill_close();
407  delete browse;
408  return;
409#else
410  (void) top;
411  (void) port;
412#endif
413}
414