PageRenderTime 52ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

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

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