PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/Source/Modules/s-exp.cxx

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