PageRenderTime 59ms CodeModel.GetById 26ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/Source/Modules/s-exp.cxx

#
C++ | 398 lines | 324 code | 40 blank | 34 comment | 97 complexity | 29c47c0866ed36c34cf4e7a73534f1c3 MD5 | raw file
  1/* ----------------------------------------------------------------------------- 
  2 * This file is part of SWIG, which is licensed as a whole under version 3 
  3 * (or any later version) of the GNU General Public License. Some additional
  4 * terms also apply to certain portions of SWIG. The full details of the SWIG
  5 * license and copyrights can be found in the LICENSE and COPYRIGHT files
  6 * included with the SWIG source code as distributed by the SWIG developers
  7 * and at http://www.swig.org/legal.html.
  8 *
  9 * s-exp.cxx
 10 *
 11 * A parse tree represented as Lisp s-expressions.
 12 * ----------------------------------------------------------------------------- */
 13
 14char cvsroot_s_exp_cxx[] = "$Id: s-exp.cxx 11876 2010-02-27 23:53:33Z wsfulton $";
 15
 16#include "swigmod.h"
 17#include "dohint.h"
 18
 19static const char *usage = "\
 20S-Exp Options (available with -sexp)\n\
 21     -typemaplang <lang> - Typemap language\n\n";
 22
 23//static Node *view_top = 0;
 24static File *out = 0;
 25
 26class Sexp:public Language {
 27public:
 28  int indent_level;
 29   Sexp():indent_level(0) {
 30  }
 31  
 32  virtual ~ Sexp() {
 33  }
 34
 35  virtual void main(int argc, char *argv[]) {
 36    // Add a symbol to the parser for conditional compilation
 37    Preprocessor_define("SWIGSEXP 1", 0);
 38
 39    SWIG_typemap_lang("sexp");
 40    for (int iX = 0; iX < argc; iX++) {
 41      if (strcmp(argv[iX], "-typemaplang") == 0) {
 42	Swig_mark_arg(iX);
 43	iX++;
 44	SWIG_typemap_lang(argv[iX]);
 45	Swig_mark_arg(iX);
 46	continue;
 47      }
 48      if (strcmp(argv[iX], "-help") == 0) {
 49	fputs(usage, stdout);
 50      }
 51    }
 52  }
 53
 54  DOHHash *print_circle_hash;
 55  int print_circle_count;
 56  int hanging_parens;
 57  bool need_whitespace;
 58  bool need_newline;
 59
 60  /* Top of the parse tree */
 61  virtual int top(Node *n) {
 62    if (out == 0) {
 63      String *outfile = Getattr(n, "outfile");
 64      Replaceall(outfile, "_wrap.cxx", ".lisp");
 65      Replaceall(outfile, "_wrap.c", ".lisp");
 66      out = NewFile(outfile, "w", SWIG_output_files());
 67      if (!out) {
 68	FileErrorDisplay(outfile);
 69	SWIG_exit(EXIT_FAILURE);
 70      }
 71    }
 72    String *f_sink = NewString("");
 73    Swig_register_filebyname("header", f_sink);
 74    Swig_register_filebyname("wrapper", f_sink);
 75    Swig_register_filebyname("begin", f_sink);
 76    Swig_register_filebyname("runtime", f_sink);
 77    Swig_register_filebyname("init", f_sink);
 78
 79    Swig_banner_target_lang(out, ";;;");
 80
 81    Language::top(n);
 82    Printf(out, "\n");
 83    Printf(out, ";;; Lisp parse tree produced by SWIG\n");
 84    print_circle_hash = DohNewHash();
 85    print_circle_count = 0;
 86    hanging_parens = 0;
 87    need_whitespace = 0;
 88    need_newline = 0;
 89    Sexp_print_node(n);
 90    flush_parens();
 91    return SWIG_OK;
 92  }
 93
 94  void print_indent() {
 95    int i;
 96    for (i = 0; i < indent_level; i++) {
 97      Printf(out, " ");
 98    }
 99  }
100
101  void open_paren(const String *oper) {
102    flush_parens();
103    Printf(out, "(");
104    if (oper)
105      Printf(out, "%s ", oper);
106    indent_level += 2;
107  }
108
109  void close_paren(bool neednewline = false) {
110    hanging_parens++;
111    if (neednewline)
112      print_lazy_whitespace();
113    indent_level -= 2;
114  }
115
116  void flush_parens() {
117    int i;
118    if (hanging_parens) {
119      for (i = 0; i < hanging_parens; i++)
120	Printf(out, ")");
121      hanging_parens = 0;
122      need_newline = true;
123      need_whitespace = true;
124    }
125    if (need_newline) {
126      Printf(out, "\n");
127      print_indent();
128      need_newline = false;
129      need_whitespace = false;
130    } else if (need_whitespace) {
131      Printf(out, " ");
132      need_whitespace = false;
133    }
134  }
135
136  void print_lazy_whitespace() {
137    need_whitespace = 1;
138  }
139
140  void print_lazy_newline() {
141    need_newline = 1;
142  }
143
144  bool internal_key_p(DOH *key) {
145    return ((Cmp(key, "nodeType") == 0)
146	    || (Cmp(key, "firstChild") == 0)
147	    || (Cmp(key, "lastChild") == 0)
148	    || (Cmp(key, "parentNode") == 0)
149	    || (Cmp(key, "nextSibling") == 0)
150	    || (Cmp(key, "previousSibling") == 0)
151	    || (Cmp(key, "csym:nextSibling") == 0)
152	    || (Cmp(key, "csym:previousSibling") == 0)
153	    || (Cmp(key, "typepass:visit") == 0)
154	    || (Cmp(key, "allocate:visit") == 0)
155	    || (*(Char(key)) == '$'));
156  }
157
158  bool boolean_key_p(DOH *key) {
159    return ((Cmp(key, "allocate:default_constructor") == 0)
160	    || (Cmp(key, "allocate:default_destructor") == 0)
161	    || (Cmp(key, "allows_typedef") == 0)
162	    || (Cmp(key, "feature:immutable") == 0));
163  }
164
165  bool list_key_p(DOH *key) {
166    return ((Cmp(key, "parms") == 0)
167	    || (Cmp(key, "baselist") == 0));
168  }
169
170  bool plist_key_p(DOH *key)
171      // true if KEY is the name of data that is a mapping from keys to
172      // values, which should be printed as a plist.
173  {
174    return ((Cmp(key, "typescope") == 0));
175  }
176
177  bool maybe_plist_key_p(DOH *key) {
178    return (Strncmp(key, "tmap:", 5) == 0);
179  }
180
181  bool print_circle(DOH *obj, bool list_p)
182      // We have a complex object, which might be referenced several
183      // times, or even recursively.  Use Lisp's reader notation for
184      // circular structures (#n#, #n=).
185      //
186      // An object can be printed in list-mode or object-mode; LIST_P toggles.
187      // return TRUE if OBJ still needs to be printed
188  {
189    flush_parens();
190    // Following is a silly hack.  It works around the limitation of
191    // DOH's hash tables that only work with string keys!
192    char address[32];
193    sprintf(address, "%p%c", obj, list_p ? 'L' : 'O');
194    DOH *placeholder = Getattr(print_circle_hash, address);
195    if (placeholder) {
196      Printv(out, placeholder, NIL);
197      return false;
198    } else {
199      String *placeholder = NewStringf("#%d#", ++print_circle_count);
200      Setattr(print_circle_hash, address, placeholder);
201      Printf(out, "#%d=", print_circle_count);
202      return true;
203    }
204  }
205
206  void Sexp_print_value_of_key(DOH *value, DOH *key) {
207    if ((Cmp(key, "parms") == 0) || (Cmp(key, "wrap:parms") == 0)
208	|| (Cmp(key, "kwargs") == 0) || (Cmp(key, "pattern") == 0))
209      Sexp_print_parms(value);
210    else if (plist_key_p(key))
211      Sexp_print_plist(value);
212    else if (maybe_plist_key_p(key)) {
213      if (DohIsMapping(value))
214	Sexp_print_plist(value);
215      else
216	Sexp_print_doh(value);
217    } else if (list_key_p(key))
218      Sexp_print_list(value);
219    else if (boolean_key_p(key))
220      Sexp_print_boolean(value);
221    else
222      Sexp_print_doh(value);
223  }
224
225  void Sexp_print_boolean(DOH *obj) {
226    flush_parens();
227    /* See DOH/Doh/base.c, DohGetInt() */
228    if (DohIsString(obj)) {
229      if (atoi(Char(obj)) != 0)
230	Printf(out, "t");
231      else
232	Printf(out, "nil");
233    } else
234      Printf(out, "nil");
235  }
236
237  void Sexp_print_list(DOH *obj) {
238    if (print_circle(obj, true)) {
239      open_paren(NIL);
240      for (; obj; obj = nextSibling(obj)) {
241	Sexp_print_doh(obj);
242	print_lazy_whitespace();
243      }
244      close_paren(true);
245    }
246  }
247
248  void Sexp_print_parms(DOH *obj) {
249    // print it as a list of plists
250    if (print_circle(obj, true)) {
251      open_paren(NIL);
252      for (; obj; obj = nextSibling(obj)) {
253	if (DohIsMapping(obj)) {
254	  Iterator k;
255	  open_paren(NIL);
256	  for (k = First(obj); k.key; k = Next(k)) {
257	    if (!internal_key_p(k.key)) {
258	      DOH *value = Getattr(obj, k.key);
259	      Sexp_print_as_keyword(k.key);
260	      Sexp_print_value_of_key(value, k.key);
261	      print_lazy_whitespace();
262	    }
263	  }
264	  close_paren(true);
265	} else
266	  Sexp_print_doh(obj);
267	print_lazy_whitespace();
268      }
269      close_paren(true);
270    }
271  }
272
273  void Sexp_print_doh(DOH *obj) {
274    flush_parens();
275    if (DohIsString(obj)) {
276      String *o = Str(obj);
277      Replaceall(o, "\\", "\\\\");
278      Replaceall(o, "\"", "\\\"");
279      Printf(out, "\"%s\"", o);
280      Delete(o);
281    } else {
282      if (print_circle(obj, false)) {
283	// Dispatch type
284	if (nodeType(obj)) {
285	  Sexp_print_node(obj);
286	}
287
288	else if (DohIsMapping(obj)) {
289	  Iterator k;
290	  open_paren(NIL);
291	  for (k = First(obj); k.key; k = Next(k)) {
292	    if (!internal_key_p(k.key)) {
293	      DOH *value = Getattr(obj, k.key);
294	      flush_parens();
295	      open_paren(NIL);
296	      Sexp_print_doh(k.key);
297	      Printf(out, " . ");
298	      Sexp_print_value_of_key(value, k.key);
299	      close_paren();
300	    }
301	  }
302	  close_paren();
303	} else if (strcmp(ObjType(obj)->objname, "List") == 0) {
304	  int i;
305	  open_paren(NIL);
306	  for (i = 0; i < Len(obj); i++) {
307	    DOH *item = Getitem(obj, i);
308	    Sexp_print_doh(item);
309	  }
310	  close_paren();
311	} else {
312	  // What is it?
313	  Printf(out, "#<DOH %s %x>", ObjType(obj)->objname, obj);
314	}
315      }
316    }
317  }
318
319  void Sexp_print_as_keyword(const DOH *k) {
320    /* Print key, replacing ":" with "-" because : is CL's package prefix */
321    flush_parens();
322    String *key = NewString(k);
323    Replaceall(key, ":", "-");
324    Replaceall(key, "_", "-");
325    Printf(out, ":%s ", key);
326    Delete(key);
327  }
328
329  void Sexp_print_plist_noparens(DOH *obj) {
330    /* attributes map names to objects */
331    Iterator k;
332    bool first;
333    for (k = First(obj), first = true; k.key; k = Next(k), first = false) {
334      if (!internal_key_p(k.key)) {
335	DOH *value = Getattr(obj, k.key);
336	flush_parens();
337	if (!first) {
338	  Printf(out, " ");
339	}
340	Sexp_print_as_keyword(k.key);
341	/* Print value */
342	Sexp_print_value_of_key(value, k.key);
343      }
344    }
345  }
346
347  void Sexp_print_plist(DOH *obj) {
348    flush_parens();
349    if (print_circle(obj, true)) {
350      open_paren(NIL);
351      Sexp_print_plist_noparens(obj);
352      close_paren();
353    }
354  }
355
356  void Sexp_print_attributes(Node *obj) {
357    Sexp_print_plist_noparens(obj);
358  }
359
360  void Sexp_print_node(Node *obj) {
361    Node *cobj;
362    open_paren(nodeType(obj));
363    /* A node has an attribute list... */
364    Sexp_print_attributes(obj);
365    /* ... and child nodes. */
366    cobj = firstChild(obj);
367    if (cobj) {
368      print_lazy_newline();
369      flush_parens();
370      Sexp_print_as_keyword("children");
371      open_paren(NIL);
372      for (; cobj; cobj = nextSibling(cobj)) {
373	Sexp_print_node(cobj);
374      }
375      close_paren();
376    }
377    close_paren();
378  }
379
380
381  virtual int functionWrapper(Node *n) {
382    ParmList *l = Getattr(n, "parms");
383    Wrapper *f = NewWrapper();
384    emit_attach_parmmaps(l, f);
385    Setattr(n, "wrap:parms", l);
386    DelWrapper(f);
387    return SWIG_OK;
388  }
389
390};
391
392
393static Language *new_swig_sexp() {
394  return new Sexp();
395}
396extern "C" Language *swig_sexp(void) {
397  return new_swig_sexp();
398}