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

/src/c/printer/write_ugly.d

https://gitlab.com/zimumavo/ecl
D | 468 lines | 446 code | 10 blank | 12 comment | 10 complexity | d0f3a5614a4db449676cff80a0e3e435 MD5 | raw file
  1. /* -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- */
  2. /* vim: set filetype=c tabstop=2 shiftwidth=2 expandtab: */
  3. /*
  4. * write_ugly.d - ugly printer
  5. *
  6. * Copyright (c) 1984 Taiichi Yuasa and Masami Hagiya
  7. * Copyright (c) 1990 Giuseppe Attardi
  8. * Copyright (c) 2001 Juan Jose Garcia Ripoll
  9. *
  10. * See file 'LICENSE' for the copyright details.
  11. *
  12. */
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #ifndef _MSC_VER
  17. # include <unistd.h>
  18. #endif
  19. #include <ecl/ecl.h>
  20. #include <ecl/internal.h>
  21. static void
  22. write_readable_pathname(cl_object path, cl_object stream)
  23. {
  24. cl_object l =
  25. cl_list(15, @'make-pathname',
  26. @':host', path->pathname.host,
  27. @':device', path->pathname.device,
  28. @':directory',
  29. _ecl_funcall2(@'ext::maybe-quote', path->pathname.directory),
  30. @':name', path->pathname.name,
  31. @':type', path->pathname.type,
  32. @':version', path->pathname.version,
  33. @':defaults', ECL_NIL);
  34. writestr_stream("#.", stream);
  35. si_write_object(l, stream);
  36. }
  37. static void
  38. write_pathname(cl_object path, cl_object stream)
  39. {
  40. cl_object namestring = ecl_namestring(path, 0);
  41. bool readably = ecl_print_readably();
  42. if (namestring == ECL_NIL) {
  43. if (readably) {
  44. write_readable_pathname(path, stream);
  45. return;
  46. }
  47. namestring = ecl_namestring(path, 1);
  48. if (namestring == ECL_NIL) {
  49. writestr_stream("#<Unprintable pathname>", stream);
  50. return;
  51. }
  52. }
  53. if (readably || ecl_print_escape())
  54. writestr_stream("#P", stream);
  55. si_write_ugly_object(namestring, stream);
  56. }
  57. static void
  58. write_integer(cl_object number, cl_object stream)
  59. {
  60. cl_object s = si_get_buffer_string();
  61. int print_base = ecl_print_base();
  62. si_integer_to_string(s, number,
  63. ecl_make_fixnum(print_base),
  64. ecl_symbol_value(@'*print-radix*'),
  65. ECL_T /* decimal syntax */);
  66. si_do_write_sequence(s, stream, ecl_make_fixnum(0), ECL_NIL);
  67. si_put_buffer_string(s);
  68. }
  69. void
  70. _ecl_write_fixnum(cl_fixnum i, cl_object stream)
  71. {
  72. cl_object s = si_get_buffer_string();
  73. si_integer_to_string(s, ecl_make_fixnum(i), ecl_make_fixnum(10), ECL_NIL, ECL_NIL);
  74. si_do_write_sequence(s, stream, ecl_make_fixnum(0), ECL_NIL);
  75. si_put_buffer_string(s);
  76. }
  77. static void
  78. write_ratio(cl_object r, cl_object stream)
  79. {
  80. cl_object s = si_get_buffer_string();
  81. int print_base = ecl_print_base();
  82. si_integer_to_string(s, r->ratio.num, ecl_make_fixnum(print_base),
  83. ecl_symbol_value(@'*print-radix*'),
  84. ECL_NIL /* decimal syntax */);
  85. ecl_string_push_extend(s, '/');
  86. si_integer_to_string(s, r->ratio.den,
  87. ecl_make_fixnum(print_base),
  88. ECL_NIL, ECL_NIL);
  89. si_do_write_sequence(s, stream, ecl_make_fixnum(0), ECL_NIL);
  90. si_put_buffer_string(s);
  91. }
  92. static void
  93. write_complex(cl_object x, cl_object stream)
  94. {
  95. writestr_stream("#C(", stream);
  96. si_write_ugly_object(x->complex.real, stream);
  97. ecl_write_char(' ', stream);
  98. si_write_ugly_object(x->complex.imag, stream);
  99. ecl_write_char(')', stream);
  100. }
  101. static void
  102. write_float(cl_object f, cl_object stream)
  103. {
  104. cl_object s = si_get_buffer_string();
  105. s = si_float_to_string_free(s, f, ecl_make_fixnum(-3), ecl_make_fixnum(8));
  106. si_do_write_sequence(s, stream, ecl_make_fixnum(0), ECL_NIL);
  107. si_put_buffer_string(s);
  108. }
  109. static void
  110. write_character(cl_object x, cl_object stream)
  111. {
  112. int i = ECL_CHAR_CODE(x);
  113. if (!ecl_print_escape() && !ecl_print_readably()) {
  114. ecl_write_char(i, stream);
  115. } else {
  116. writestr_stream("#\\", stream);
  117. if (i < 32 || i >= 127) {
  118. cl_object name = cl_char_name(ECL_CODE_CHAR(i));
  119. writestr_stream((char*)name->base_string.self, stream);
  120. } else {
  121. ecl_write_char(i, stream);
  122. }
  123. }
  124. }
  125. static void
  126. write_package(cl_object x, cl_object stream)
  127. {
  128. if (ecl_print_readably()) FEprint_not_readable(x);
  129. writestr_stream("#<", stream);
  130. si_write_ugly_object(x->pack.name, stream);
  131. writestr_stream(" package>", stream);
  132. }
  133. static void
  134. write_hashtable(cl_object x, cl_object stream)
  135. {
  136. if (ecl_print_readably() && !Null(ecl_symbol_value(@'*read-eval*'))) {
  137. cl_object make =
  138. cl_list(9, @'make-hash-table',
  139. @':size', cl_hash_table_size(x),
  140. @':rehash-size', cl_hash_table_rehash_size(x),
  141. @':rehash-threshold', cl_hash_table_rehash_threshold(x),
  142. @':test', cl_list(2, @'quote', cl_hash_table_test(x)));
  143. cl_object init =
  144. cl_list(3, @'ext::hash-table-fill', make,
  145. cl_list(2, @'quote', si_hash_table_content(x)));
  146. writestr_stream("#.", stream);
  147. si_write_ugly_object(init, stream);
  148. } else {
  149. _ecl_write_unreadable(x, "hash-table", ECL_NIL, stream);
  150. }
  151. }
  152. static void
  153. write_random(cl_object x, cl_object stream)
  154. {
  155. if (ecl_print_readably()) {
  156. writestr_stream("#$", stream);
  157. _ecl_write_vector(x->random.value, stream);
  158. } else {
  159. _ecl_write_unreadable(x->random.value, "random-state", ECL_NIL, stream);
  160. }
  161. }
  162. static void
  163. write_stream(cl_object x, cl_object stream)
  164. {
  165. const char *prefix;
  166. cl_object tag;
  167. union cl_lispunion str;
  168. #ifdef ECL_UNICODE
  169. ecl_character buffer[10];
  170. #else
  171. ecl_base_char buffer[10];
  172. #endif
  173. switch ((enum ecl_smmode)x->stream.mode) {
  174. case ecl_smm_input_file:
  175. prefix = "closed input file";
  176. tag = IO_STREAM_FILENAME(x);
  177. break;
  178. case ecl_smm_input:
  179. prefix = "closed input stream";
  180. tag = IO_STREAM_FILENAME(x);
  181. break;
  182. case ecl_smm_output_file:
  183. prefix = "closed output file";
  184. tag = IO_STREAM_FILENAME(x);
  185. break;
  186. case ecl_smm_output:
  187. prefix = "closed output stream";
  188. tag = IO_STREAM_FILENAME(x);
  189. break;
  190. #ifdef ECL_MS_WINDOWS_HOST
  191. case ecl_smm_input_wsock:
  192. prefix = "closed input win32 socket stream";
  193. tag = IO_STREAM_FILENAME(x);
  194. break;
  195. case ecl_smm_output_wsock:
  196. prefix = "closed output win32 socket stream";
  197. tag = IO_STREAM_FILENAME(x);
  198. break;
  199. case ecl_smm_io_wsock:
  200. prefix = "closed i/o win32 socket stream";
  201. tag = IO_STREAM_FILENAME(x);
  202. break;
  203. case ecl_smm_io_wcon:
  204. prefix = "closed i/o win32 console stream";
  205. tag = IO_STREAM_FILENAME(x);
  206. break;
  207. #endif
  208. case ecl_smm_io_file:
  209. prefix = "closed io file";
  210. tag = IO_STREAM_FILENAME(x);
  211. break;
  212. case ecl_smm_io:
  213. prefix = "closed io stream";
  214. tag = IO_STREAM_FILENAME(x);
  215. break;
  216. case ecl_smm_probe:
  217. prefix = "closed probe stream";
  218. tag = IO_STREAM_FILENAME(x);
  219. break;
  220. case ecl_smm_synonym:
  221. prefix = "closed synonym stream to";
  222. tag = SYNONYM_STREAM_SYMBOL(x);
  223. break;
  224. case ecl_smm_broadcast:
  225. prefix = "closed broadcast stream";
  226. tag = ECL_NIL;
  227. break;
  228. case ecl_smm_concatenated:
  229. prefix = "closed concatenated stream";
  230. tag = ECL_NIL;
  231. break;
  232. case ecl_smm_two_way:
  233. prefix = "closed two-way stream";
  234. tag = ECL_NIL;
  235. break;
  236. case ecl_smm_echo:
  237. prefix = "closed echo stream";
  238. tag = ECL_NIL;
  239. break;
  240. case ecl_smm_string_input: {
  241. cl_object text = x->stream.object0;
  242. cl_index ndx, l = ecl_length(text);
  243. for (ndx = 0; (ndx < 8) && (ndx < l); ndx++) {
  244. buffer[ndx] = ecl_char(text, ndx);
  245. }
  246. if (l > ndx) {
  247. buffer[ndx-1] = '.';
  248. buffer[ndx-2] = '.';
  249. buffer[ndx-3] = '.';
  250. }
  251. buffer[ndx++] = 0;
  252. prefix = "closed string-input stream from";
  253. tag = &str;
  254. #ifdef ECL_UNICODE
  255. tag->string.t = t_string;
  256. tag->string.self = buffer;
  257. #else
  258. tag->base_string.t = t_base_string;
  259. tag->base_string.self = buffer;
  260. #endif
  261. tag->base_string.dim = ndx;
  262. tag->base_string.fillp = ndx-1;
  263. break;
  264. }
  265. case ecl_smm_string_output:
  266. prefix = "closed string-output stream";
  267. tag = ECL_NIL;
  268. break;
  269. case ecl_smm_sequence_input:
  270. prefix = "closed sequence-input stream";
  271. tag = ECL_NIL;
  272. break;
  273. case ecl_smm_sequence_output:
  274. prefix = "closed sequence-output stream";
  275. tag = ECL_NIL;
  276. break;
  277. default:
  278. ecl_internal_error("illegal stream mode");
  279. }
  280. if (!x->stream.closed)
  281. prefix = prefix + 7;
  282. _ecl_write_unreadable(x, prefix, tag, stream);
  283. }
  284. static void
  285. write_instance(cl_object x, cl_object stream)
  286. {
  287. _ecl_funcall3(@'print-object', x, stream);
  288. }
  289. static void
  290. write_readtable(cl_object x, cl_object stream)
  291. {
  292. _ecl_write_unreadable(x, "readtable", ECL_NIL, stream);
  293. }
  294. static void
  295. write_cfun(cl_object x, cl_object stream)
  296. {
  297. _ecl_write_unreadable(x, "compiled-function", x->cfun.name, stream);
  298. }
  299. static void
  300. write_codeblock(cl_object x, cl_object stream)
  301. {
  302. _ecl_write_unreadable(x, "codeblock", x->cblock.name, stream);
  303. }
  304. static void
  305. write_cclosure(cl_object x, cl_object stream)
  306. {
  307. _ecl_write_unreadable(x, "compiled-closure", ECL_NIL, stream);
  308. }
  309. static void
  310. write_foreign(cl_object x, cl_object stream)
  311. {
  312. _ecl_write_unreadable(x, "foreign", x->foreign.tag, stream);
  313. }
  314. static void
  315. write_frame(cl_object x, cl_object stream)
  316. {
  317. _ecl_write_unreadable(x, "frame", ecl_make_fixnum(x->frame.size), stream);
  318. }
  319. static void
  320. write_weak_pointer(cl_object x, cl_object stream)
  321. {
  322. _ecl_write_unreadable(x, "weak-pointer", ECL_NIL, stream);
  323. }
  324. #ifdef ECL_THREADS
  325. static void
  326. write_process(cl_object x, cl_object stream)
  327. {
  328. _ecl_write_unreadable(x, "process", x->process.name, stream);
  329. }
  330. static void
  331. write_lock(cl_object x, cl_object stream)
  332. {
  333. const char *prefix = x->lock.recursive?
  334. "lock" : "lock (nonrecursive)";
  335. _ecl_write_unreadable(x, prefix, x->lock.name, stream);
  336. }
  337. static void
  338. write_rwlock(cl_object x, cl_object stream)
  339. {
  340. _ecl_write_unreadable(x, "rwlock", x->rwlock.name, stream);
  341. }
  342. static void
  343. write_condition_variable(cl_object x, cl_object stream)
  344. {
  345. _ecl_write_unreadable(x, "semaphore", ECL_NIL, stream);
  346. }
  347. static void
  348. write_semaphore(cl_object x, cl_object stream)
  349. {
  350. _ecl_write_unreadable(x, "semaphore", ECL_NIL, stream);
  351. }
  352. static void
  353. write_barrier(cl_object x, cl_object stream)
  354. {
  355. _ecl_write_unreadable(x, "barrier", ECL_NIL, stream);
  356. }
  357. static void
  358. write_mailbox(cl_object x, cl_object stream)
  359. {
  360. _ecl_write_unreadable(x, "mailbox", ECL_NIL, stream);
  361. }
  362. #endif /* ECL_THREADS */
  363. static void
  364. write_illegal(cl_object x, cl_object stream)
  365. {
  366. _ecl_write_unreadable(x, "illegal pointer", ECL_NIL, stream);
  367. }
  368. typedef void (*printer)(cl_object x, cl_object stream);
  369. static printer dispatch[FREE+1] = {
  370. 0 /* t_start = 0 */,
  371. _ecl_write_list, /* t_list = 1 */
  372. write_character, /* t_character = 2 */
  373. write_integer, /* t_fixnum = 3 */
  374. write_integer, /* t_bignum = 4 */
  375. write_ratio, /* t_ratio */
  376. /* write_float, */ /* t_shortfloat */
  377. write_float, /* t_singlefloat */
  378. write_float, /* t_doublefloat */
  379. #ifdef ECL_LONG_FLOAT
  380. write_float, /* t_longfloat */
  381. #endif
  382. write_complex, /* t_complex */
  383. _ecl_write_symbol, /* t_symbol */
  384. write_package, /* t_package */
  385. write_hashtable, /* t_hashtable */
  386. _ecl_write_array, /* t_array */
  387. _ecl_write_vector, /* t_vector */
  388. #ifdef ECL_UNICODE
  389. _ecl_write_string, /* t_string */
  390. #endif
  391. _ecl_write_base_string, /* t_base_string */
  392. _ecl_write_bitvector, /* t_bitvector */
  393. write_stream, /* t_stream */
  394. write_random, /* t_random */
  395. write_readtable, /* t_readtable */
  396. write_pathname, /* t_pathname */
  397. _ecl_write_bytecodes, /* t_bytecodes */
  398. _ecl_write_bclosure, /* t_bclosure */
  399. write_cfun, /* t_cfun */
  400. write_cfun, /* t_cfunfixed */
  401. write_cclosure, /* t_cclosure */
  402. write_instance, /* t_instance */
  403. #ifdef ECL_THREADS
  404. write_process, /* t_process */
  405. write_lock, /* t_lock */
  406. write_rwlock, /* t_rwlock */
  407. write_condition_variable, /* t_condition_variable */
  408. write_semaphore, /* t_semaphore */
  409. write_barrier, /* t_barrier */
  410. write_mailbox, /* t_mailbox */
  411. #endif
  412. write_codeblock, /* t_codeblock */
  413. write_foreign, /* t_foreign */
  414. write_frame, /* t_frame */
  415. write_weak_pointer, /* t_weak_pointer */
  416. #ifdef ECL_SSE2
  417. _ecl_write_sse, /* t_sse_pack */
  418. #endif
  419. /* t_end */
  420. };
  421. cl_object
  422. si_write_ugly_object(cl_object x, cl_object stream)
  423. {
  424. if (x == OBJNULL) {
  425. if (ecl_print_readably())
  426. FEprint_not_readable(x);
  427. writestr_stream("#<OBJNULL>", stream);
  428. } else {
  429. int t = ecl_t_of(x);
  430. printer f = (t >= t_end)? write_illegal : dispatch[t];
  431. f(x, stream);
  432. }
  433. @(return x);
  434. }