PageRenderTime 65ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 2ms

/src/io.d

https://github.com/ynd/clisp-branch--ynd-devel
D | 10545 lines | 7316 code | 301 blank | 2928 comment | 1225 complexity | cbabd0b1128037aa0e6ab8460976b564 MD5 | raw file
Possible License(s): LGPL-2.0, GPL-2.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Input/Output for CLISP
  3. * Bruno Haible 1990-2005
  4. * Marcus Daniels 11.3.1997
  5. * Sam Steingold 1998-2008
  6. * German comments translated into English: Stefan Kain 2001-06-12
  7. */
  8. #include "lispbibl.c"
  9. #include "arilev0.c" /* for Division in pr_uint */
  10. /* IO_DEBUG must be undefined in the code comitted to CVS */
  11. /* #define IO_DEBUG 0 */
  12. #ifdef IO_DEBUG
  13. #define PPH_OUT(label,stream) \
  14. do { printf(#label "[%d]: [",__LINE__); \
  15. nobject_out(stdout,stream); \
  16. printf("]\n"); } while(0)
  17. #else
  18. #define PPH_OUT(l,s)
  19. #endif
  20. /* ========================================================================
  21. Readtable-functions
  22. ======================================================================== */
  23. /* Maximum size of linear per-character arrays. */
  24. #define small_char_code_limit 0x100UL
  25. /* Tables indexed by characters.
  26. allocate_perchar_table()
  27. perchar_table_get(table,c)
  28. perchar_table_put(table,c,value)
  29. copy_perchar_table(table) */
  30. #if (small_char_code_limit < char_code_limit)
  31. /* A simple-vector of small_char_code_limit+1 elements, the last entry being
  32. a hash table for the non-base characters. */
  33. local object allocate_perchar_table (void) {
  34. /* Allocate the hash table.
  35. (MAKE-HASH-TABLE :KEY-TYPE 'CHARACTER
  36. :VALUE-TYPE '(OR FUNCTION SIMPLE-VECTOR)
  37. :TEST 'FASTHASH-EQ :WARN-IF-NEEDS-REHASH-AFTER-GC T) */
  38. pushSTACK(S(Ktest)); pushSTACK(S(fasthash_eq));
  39. pushSTACK(S(Kwarn_if_needs_rehash_after_gc)); pushSTACK(T);
  40. funcall(L(make_hash_table),4);
  41. pushSTACK(value1);
  42. /* Allocate the simple-vector. */
  43. var object table = allocate_vector(small_char_code_limit+1);
  44. TheSvector(table)->data[small_char_code_limit] = popSTACK();
  45. return table;
  46. }
  47. local object perchar_table_get (object table, chart c) {
  48. if (as_cint(c) < small_char_code_limit) {
  49. return TheSvector(table)->data[as_cint(c)];
  50. } else {
  51. var object value = gethash(code_char(c),
  52. TheSvector(table)->data[small_char_code_limit],
  53. false);
  54. return (eq(value,nullobj) ? NIL : value);
  55. }
  56. }
  57. local void perchar_table_put (object table, chart c, object value) {
  58. if (as_cint(c) < small_char_code_limit) {
  59. TheSvector(table)->data[as_cint(c)] = value;
  60. } else {
  61. shifthash(TheSvector(table)->data[small_char_code_limit],
  62. code_char(c),value,true);
  63. }
  64. }
  65. local object copy_perchar_table (object table) {
  66. pushSTACK(copy_svector(table));
  67. /* Allocate a new hash table.
  68. (MAKE-HASH-TABLE :KEY-TYPE 'CHARACTER
  69. :VALUE-TYPE '(OR FUNCTION SIMPLE-VECTOR)
  70. :TEST 'FASTHASH-EQ :WARN-IF-NEEDS-REHASH-AFTER-GC T) */
  71. pushSTACK(S(Ktest)); pushSTACK(S(fasthash_eq));
  72. pushSTACK(S(Kwarn_if_needs_rehash_after_gc)); pushSTACK(T);
  73. funcall(L(make_hash_table),4);
  74. pushSTACK(value1);
  75. /* stack layout: table, newht. */
  76. map_hashtable(TheSvector(STACK_1)->data[small_char_code_limit],
  77. key,value,{ shifthash(STACK_(0+1),key,value,true); });
  78. var object newht = popSTACK();
  79. var object table1 = popSTACK();
  80. TheSvector(table1)->data[small_char_code_limit] = newht;
  81. return table1;
  82. }
  83. #else
  84. /* A simple-vector of char_code_limit elements. */
  85. #define allocate_perchar_table() allocate_vector(char_code_limit)
  86. #define perchar_table_get(table,c) TheSvector(table)->data[(uintP)as_cint(c)]
  87. #define perchar_table_put(table,c,value) (TheSvector(table)->data[(uintP)as_cint(c)] = (value))
  88. #define copy_perchar_table(table) copy_svector(table)
  89. #endif
  90. /* Structure of Readtables (cf. LISPBIBL.D):
  91. readtable_syntax_table
  92. bitvector consisting of char_code_limit bytes: for each character the
  93. syntaxcode is assigned
  94. readtable_macro_table
  95. a vector with char_code_limit elements: for each character
  96. either (if the character is not a read-macro)
  97. NIL
  98. or (if the character is a dispatch-macro)
  99. a vector with char_code_limit functions/NILs,
  100. or (if the character is a read-macro defined by a function)
  101. the function, which is called, when the character is read.
  102. readtable_case
  103. a fixnum in {0,1,2,3}
  104. meaning of case (in sync with CONSTOBJ.D!): */
  105. #define case_upcase 0
  106. #define case_downcase 1
  107. #define case_preserve 2
  108. #define case_invert 3
  109. /* meaning of the entries in the syntax_table: */
  110. #define syntax_illegal 0 /* unprintable, excluding whitespace */
  111. #define syntax_single_esc 1 /* '\' (Single Escape) */
  112. #define syntax_multi_esc 2 /* '|' (Multiple Escape) */
  113. #define syntax_constituent 3 /* the rest (Constituent) */
  114. #define syntax_whitespace 4 /* TAB,LF,FF,CR,' ' (Whitespace) */
  115. #define syntax_eof 5 /* EOF */
  116. #define syntax_t_macro 6 /* '()'"' (Terminating Macro) */
  117. #define syntax_nt_macro 7 /* '#' (Non-Terminating Macro) */
  118. /* <= syntax_constituent : if an object starts with such a character, it's a
  119. token. (syntax_illegal will deliver an error then.)
  120. >= syntax_t_macro : macro-character. if an object starts like that:
  121. call read-macro function.
  122. Syntax tables, indexed by characters.
  123. allocate_syntax_table()
  124. syntax_table_get(table,c)
  125. syntax_table_put(table,c,value)
  126. syntax_table_put can trigger GC */
  127. #if (small_char_code_limit < char_code_limit)
  128. /* A cons, consisting of a simple-bit-vector with small_char_code_limit
  129. bytes, and a hash table mapping characters to fixnums. Characters not
  130. found in the hash table are assumed to have the syntax code
  131. (graphic_char_p(ch) ? syntax_constituent : syntax_illegal). */
  132. local object allocate_syntax_table (void) {
  133. /* Allocate the hash table.
  134. (MAKE-HASH-TABLE :KEY-TYPE 'CHARACTER
  135. :VALUE-TYPE 'FIXNUM
  136. :TEST 'FASTHASH-EQ :WARN-IF-NEEDS-REHASH-AFTER-GC T) */
  137. pushSTACK(S(Ktest)); pushSTACK(S(fasthash_eq));
  138. pushSTACK(S(Kwarn_if_needs_rehash_after_gc)); pushSTACK(T);
  139. funcall(L(make_hash_table),4);
  140. pushSTACK(value1);
  141. /* Allocate the simple-bit-vector. */
  142. pushSTACK(allocate_bit_vector(Atype_8Bit,small_char_code_limit));
  143. var object new_cons = allocate_cons();
  144. Car(new_cons) = popSTACK();
  145. Cdr(new_cons) = popSTACK();
  146. return new_cons;
  147. }
  148. local uintB syntax_table_get_notinline (object table, chart c) {
  149. var object val = gethash(code_char(c),Cdr(table),false);
  150. if (!eq(val,nullobj))
  151. return posfixnum_to_V(val);
  152. else
  153. return (graphic_char_p(c) ? syntax_constituent : syntax_illegal);
  154. }
  155. local inline uintB syntax_table_get (object table, chart c) {
  156. return (as_cint(c) < small_char_code_limit
  157. ? TheSbvector(Car(table))->data[as_cint(c)]
  158. : syntax_table_get_notinline(table,c));
  159. }
  160. local maygc void syntax_table_put_notinline (object table, chart c, uintB value)
  161. {
  162. shifthash(Cdr(table),code_char(c),fixnum(value),true);
  163. }
  164. local inline maygc void syntax_table_put (object table, chart c, uintB value) {
  165. if (as_cint(c) < small_char_code_limit)
  166. TheSbvector(Car(table))->data[as_cint(c)] = value;
  167. else
  168. syntax_table_put_notinline(table,c,value);
  169. }
  170. #else
  171. /* A simple-bit-vector with char_code_limit bytes. */
  172. #define allocate_syntax_table() \
  173. allocate_bit_vector(Atype_8Bit,char_code_limit)
  174. #define syntax_table_get(table,c) \
  175. TheSbvector(table)->data[as_cint(c)]
  176. #define syntax_table_put(table,c,value) \
  177. (TheSbvector(table)->data[as_cint(c)] = (value))
  178. #endif
  179. #define syntax_readtable_get(rt,c) \
  180. syntax_table_get(TheReadtable(rt)->readtable_syntax_table,c)
  181. #define syntax_readtable_put(rt,c,v) \
  182. syntax_table_put(TheReadtable(rt)->readtable_syntax_table,c,v)
  183. /* standard(original) syntaxtable(readtable) for read characters: */
  184. local const uintB orig_syntax_table [small_char_code_limit] = {
  185. #define illg syntax_illegal
  186. #define sesc syntax_single_esc
  187. #define mesc syntax_multi_esc
  188. #define cnst syntax_constituent
  189. #define whsp syntax_whitespace
  190. #define tmac syntax_t_macro
  191. #define nmac syntax_nt_macro
  192. illg,illg,illg,illg,illg,illg,illg,illg, /* chr(0) upto chr(7) */
  193. cnst,whsp,whsp,illg,whsp,whsp,illg,illg, /* chr(8) upto chr(15) */
  194. illg,illg,illg,illg,illg,illg,illg,illg, /* chr(16) upto chr(23) */
  195. illg,illg,illg,illg,illg,illg,illg,illg, /* chr(24) upto chr(31) */
  196. whsp,cnst,tmac,nmac,cnst,cnst,cnst,tmac, /* ' !"#$%&'' */
  197. tmac,tmac,cnst,cnst,tmac,cnst,cnst,cnst, /* '()*+,-./' */
  198. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst, /* '01234567' */
  199. cnst,cnst,cnst,tmac,cnst,cnst,cnst,cnst, /* '89:;<=>?' */
  200. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst, /* '@ABCDEFG' */
  201. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst, /* 'HIJKLMNO' */
  202. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst, /* 'PQRSTUVW' */
  203. cnst,cnst,cnst,cnst,sesc,cnst,cnst,cnst, /* 'XYZ[\]^_' */
  204. tmac,cnst,cnst,cnst,cnst,cnst,cnst,cnst, /* '`abcdefg' */
  205. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst, /* 'hijklmno' */
  206. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst, /* 'pqrstuvw' */
  207. cnst,cnst,cnst,cnst,mesc,cnst,cnst,cnst, /* 'xyz{|}~',chr(127) */
  208. #if defined(UNICODE) || defined(ISOLATIN_CHS) || defined(HPROMAN8_CHS)
  209. illg,illg,illg,illg,illg,illg,illg,illg,
  210. illg,illg,illg,illg,illg,illg,illg,illg,
  211. illg,illg,illg,illg,illg,illg,illg,illg,
  212. illg,illg,illg,illg,illg,illg,illg,illg,
  213. whsp,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  214. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  215. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  216. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  217. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  218. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  219. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  220. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  221. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  222. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  223. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  224. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  225. #elif defined(NEXTSTEP_CHS)
  226. whsp,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  227. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  228. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  229. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  230. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  231. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  232. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  233. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  234. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  235. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  236. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  237. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  238. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  239. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  240. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  241. cnst,cnst,cnst,cnst,cnst,cnst,cnst,cnst,
  242. #else /* defined(ASCII_CHS) && !defined(UNICODE) */
  243. illg,illg,illg,illg,illg,illg,illg,illg,
  244. illg,illg,illg,illg,illg,illg,illg,illg,
  245. illg,illg,illg,illg,illg,illg,illg,illg,
  246. illg,illg,illg,illg,illg,illg,illg,illg,
  247. illg,illg,illg,illg,illg,illg,illg,illg,
  248. illg,illg,illg,illg,illg,illg,illg,illg,
  249. illg,illg,illg,illg,illg,illg,illg,illg,
  250. illg,illg,illg,illg,illg,illg,illg,illg,
  251. illg,illg,illg,illg,illg,illg,illg,illg,
  252. illg,illg,illg,illg,illg,illg,illg,illg,
  253. illg,illg,illg,illg,illg,illg,illg,illg,
  254. illg,illg,illg,illg,illg,illg,illg,illg,
  255. illg,illg,illg,illg,illg,illg,illg,illg,
  256. illg,illg,illg,illg,illg,illg,illg,illg,
  257. illg,illg,illg,illg,illg,illg,illg,illg,
  258. illg,illg,illg,illg,illg,illg,illg,illg,
  259. #endif
  260. #undef illg
  261. #undef sesc
  262. #undef mesc
  263. #undef cnst
  264. #undef whsp
  265. #undef tmac
  266. #undef nmac
  267. };
  268. #if (small_char_code_limit < char_code_limit)
  269. #define orig_syntax_table_get(c) \
  270. (as_cint(c) < small_char_code_limit \
  271. ? orig_syntax_table[as_cint(c)] \
  272. : (graphic_char_p(c) ? syntax_constituent : syntax_illegal))
  273. #else
  274. #define orig_syntax_table_get(c) orig_syntax_table[as_cint(c)]
  275. #endif
  276. /* UP: returns the standard (original) readtable.
  277. orig_readtable()
  278. < result: standard(original) readtable
  279. can trigger GC */
  280. local maygc object orig_readtable (void) {
  281. { /* initialize the syntax-table: */
  282. var object s_table = allocate_syntax_table(); /* new bitvector */
  283. pushSTACK(s_table); /* save */
  284. /* and fill with the original: */
  285. #if (small_char_code_limit < char_code_limit)
  286. s_table = Car(s_table);
  287. #endif
  288. var const uintB * ptr1 = &orig_syntax_table[0];
  289. var uintB* ptr2 = &TheSbvector(s_table)->data[0];
  290. var uintC count;
  291. dotimesC(count,small_char_code_limit, { *ptr2++ = *ptr1++; } );
  292. }
  293. { /* initialize dispatch-macro '#': */
  294. var object d_table = allocate_perchar_table(); /* new vector */
  295. pushSTACK(d_table); /* save */
  296. /* and add the sub-character-functions for '#': */
  297. var gcv_object_t* table = &TheSvector(d_table)->data[0];
  298. table['\''] = L(function_reader);
  299. table['|'] = L(comment_reader);
  300. table['\\'] = L(char_reader);
  301. table['B'] = L(binary_reader);
  302. table['O'] = L(octal_reader);
  303. table['X'] = L(hexadecimal_reader);
  304. table['R'] = L(radix_reader);
  305. table['C'] = L(complex_reader);
  306. table[':'] = L(uninterned_reader);
  307. table['*'] = L(bit_vector_reader);
  308. table['('] = L(vector_reader);
  309. table['A'] = L(array_reader);
  310. table['.'] = L(read_eval_reader);
  311. table[','] = L(load_eval_reader);
  312. table['='] = L(label_definition_reader);
  313. table['#'] = L(label_reference_reader);
  314. table['<'] = L(not_readable_reader);
  315. table[')'] = L(syntax_error_reader);
  316. table[' '] = L(syntax_error_reader); /* #\Space */
  317. table[NL] = L(syntax_error_reader); /* #\Newline = 10 = #\Linefeed */
  318. table[BS] = L(syntax_error_reader); /* #\Backspace */
  319. table[TAB] = L(syntax_error_reader); /* #\Tab */
  320. table[CR] = L(syntax_error_reader); /* #\Return */
  321. table[PG] = L(syntax_error_reader); /* #\Page */
  322. table[RUBOUT] = L(syntax_error_reader); /* #\Rubout */
  323. table['+'] = L(feature_reader);
  324. table['-'] = L(not_feature_reader);
  325. table['S'] = L(structure_reader);
  326. table['Y'] = L(closure_reader);
  327. table['"'] = L(clisp_pathname_reader);
  328. table['P'] = L(ansi_pathname_reader);
  329. }
  330. { /* initialize READ-macros: */
  331. var object m_table = allocate_perchar_table(); /* new NIL-filled vector */
  332. /* and add the macro-characters: */
  333. var gcv_object_t* table = &TheSvector(m_table)->data[0];
  334. table['('] = L(lpar_reader);
  335. table[')'] = L(rpar_reader);
  336. table['"'] = L(string_reader);
  337. table['\''] = L(quote_reader);
  338. table['#'] = popSTACK(); /* dispatch-vector for '#' */
  339. table[';'] = L(line_comment_reader);
  340. table['`'] = S(backquote_reader); /* cf. BACKQUOTE.LISP */
  341. table[','] = S(comma_reader); /* cf. BACKQUOTE.LISP */
  342. pushSTACK(m_table); /* save */
  343. }
  344. { /* build readtable: */
  345. var object readtable = allocate_readtable(); /* new readtable */
  346. TheReadtable(readtable)->readtable_macro_table = popSTACK(); /* m_table */
  347. TheReadtable(readtable)->readtable_syntax_table = popSTACK(); /* s_table */
  348. TheReadtable(readtable)->readtable_case = fixnum(case_upcase); /* :UPCASE */
  349. return readtable;
  350. }
  351. }
  352. /* UP: copies a readtable
  353. copy_readtable_contents(from_readtable,to_readtable)
  354. > from-readtable
  355. > to-readtable
  356. < result : to-Readtable with same content
  357. can trigger GC */
  358. local maygc object copy_readtable_contents (object from_readtable,
  359. object to_readtable) {
  360. /* copy the case-slot: */
  361. TheReadtable(to_readtable)->readtable_case =
  362. TheReadtable(from_readtable)->readtable_case;
  363. { /* copy the syntaxtable: */
  364. var object stable1;
  365. var object stable2;
  366. #if (small_char_code_limit < char_code_limit)
  367. pushSTACK(to_readtable);
  368. pushSTACK(from_readtable);
  369. /* Allocate a new hash table.
  370. (MAKE-HASH-TABLE :KEY-TYPE 'CHARACTER
  371. :VALUE-TYPE 'FIXNUM
  372. :TEST 'FASTHASH-EQ :WARN-IF-NEEDS-REHASH-AFTER-GC T) */
  373. pushSTACK(S(Ktest)); pushSTACK(S(fasthash_eq));
  374. pushSTACK(S(Kwarn_if_needs_rehash_after_gc)); pushSTACK(T);
  375. funcall(L(make_hash_table),4);
  376. pushSTACK(value1);
  377. /* stack layout: to-readtable, from-readtable, newht. */
  378. map_hashtable(Cdr(TheReadtable(STACK_1)->readtable_syntax_table),ch,entry,
  379. { shifthash(STACK_(0+1),ch,entry,true); });
  380. {
  381. var object newht = popSTACK();
  382. from_readtable = popSTACK();
  383. to_readtable = popSTACK();
  384. stable1 = Car(TheReadtable(from_readtable)->readtable_syntax_table);
  385. stable2 = TheReadtable(to_readtable)->readtable_syntax_table;
  386. Cdr(stable2) = newht;
  387. stable2 = Car(stable2);
  388. }
  389. #else
  390. stable1 = TheReadtable(from_readtable)->readtable_syntax_table;
  391. stable2 = TheReadtable(to_readtable)->readtable_syntax_table;
  392. #endif
  393. var const uintB* ptr1 = &TheSbvector(stable1)->data[0];
  394. var uintB* ptr2 = &TheSbvector(stable2)->data[0];
  395. var uintC count;
  396. dotimesC(count,small_char_code_limit, { *ptr2++ = *ptr1++; } );
  397. }
  398. /* copy the macro-table: */
  399. pushSTACK(to_readtable); /* save to-readtable */
  400. {
  401. var object mtable1 = TheReadtable(from_readtable)->readtable_macro_table;
  402. var object mtable2 = TheReadtable(to_readtable)->readtable_macro_table;
  403. var uintL i;
  404. for (i = 0; i < small_char_code_limit; i++) {
  405. /* copy entry number i: */
  406. var object entry = TheSvector(mtable1)->data[i];
  407. if (simple_vector_p(entry)) {
  408. /* simple-vector is copied element for element: */
  409. pushSTACK(mtable1); pushSTACK(mtable2);
  410. entry = copy_perchar_table(entry);
  411. mtable2 = popSTACK(); mtable1 = popSTACK();
  412. }
  413. TheSvector(mtable2)->data[i] = entry;
  414. }
  415. #if (small_char_code_limit < char_code_limit)
  416. pushSTACK(mtable2);
  417. pushSTACK(mtable1);
  418. /* Allocate a new hash table.
  419. (MAKE-HASH-TABLE :KEY-TYPE 'CHARACTER
  420. :VALUE-TYPE '(OR FUNCTION SIMPLE-VECTOR)
  421. :TEST 'FASTHASH-EQ :WARN-IF-NEEDS-REHASH-AFTER-GC T) */
  422. pushSTACK(S(Ktest)); pushSTACK(S(fasthash_eq));
  423. pushSTACK(S(Kwarn_if_needs_rehash_after_gc)); pushSTACK(T);
  424. funcall(L(make_hash_table),4);
  425. mtable1 = STACK_0;
  426. STACK_0 = value1;
  427. /* stack layout: mtable2, newht. */
  428. map_hashtable(TheSvector(mtable1)->data[small_char_code_limit],ch,entry, {
  429. if (simple_vector_p(entry))
  430. entry = copy_perchar_table(entry);
  431. shifthash(STACK_(0+1),ch,entry,true);
  432. });
  433. TheSvector(STACK_1)->data[small_char_code_limit] = STACK_0;
  434. skipSTACK(2);
  435. #endif
  436. }
  437. return popSTACK(); /* to-readtable as result */
  438. }
  439. /* UP: copies a readtable
  440. copy_readtable(readtable)
  441. > readtable: Readtable
  442. < result: copy of readtable, semantically equivalent
  443. can trigger GC */
  444. local maygc object copy_readtable (object from_readtable) {
  445. pushSTACK(from_readtable); /* save */
  446. pushSTACK(allocate_syntax_table()); /* new empty syntaxtable */
  447. pushSTACK(allocate_perchar_table()); /* new empty macro-table */
  448. var object to_readtable = allocate_readtable(); /* new readtable */
  449. /* fill: */
  450. TheReadtable(to_readtable)->readtable_macro_table = popSTACK();
  451. TheReadtable(to_readtable)->readtable_syntax_table = popSTACK();
  452. /* and copy content: */
  453. return copy_readtable_contents(popSTACK(),to_readtable);
  454. }
  455. /* error at wrong value of *READTABLE*
  456. error_bad_readtable(); */
  457. nonreturning_function(local, error_bad_readtable, (void)) {
  458. /* correct *READTABLE*: */
  459. var object sym = S(readtablestern); /* Symbol *READTABLE* */
  460. var object oldvalue = Symbol_value(sym);
  461. Symbol_value(sym) = O(standard_readtable); /* := CL standard readtable */
  462. /* and report the error: */
  463. pushSTACK(oldvalue); /* TYPE-ERROR slot DATUM */
  464. pushSTACK(S(readtable)); /* TYPE-ERROR slot EXPECTED-TYPE */
  465. pushSTACK(sym);
  466. error(type_error,
  467. GETTEXT("The value of ~S was not a readtable. It has been reset."));
  468. }
  469. /* Macro: fetches the current readtable.
  470. get_readtable(readtable =);
  471. < readtable : the current readtable */
  472. #if 0
  473. #define get_readtable(assignment) \
  474. { if (!readtablep(Symbol_value(S(readtablestern)))) \
  475. { error_bad_readtable(); } \
  476. assignment Symbol_value(S(readtablestern)); }
  477. #else /* or (optimized): */
  478. #define get_readtable(assignment) \
  479. { if (!(orecordp(Symbol_value(S(readtablestern))) \
  480. && (Record_type( assignment Symbol_value(S(readtablestern)) ) \
  481. == Rectype_Readtable))) \
  482. { error_bad_readtable(); }}
  483. #endif
  484. /* =======================================================================
  485. Initialization
  486. ======================================================================= */
  487. /* UP: Initializes the reader.
  488. init_reader();
  489. can trigger GC */
  490. global maygc void init_reader (void) {
  491. /* initialize *READ-BASE*: */
  492. define_variable(S(read_base),fixnum(10)); /* *READ-BASE* := 10 */
  493. /* initialize *READ-SUPPRESS*: */
  494. define_variable(S(read_suppress),NIL); /* *READ-SUPPRESS* := NIL */
  495. /* initialize *READ-EVAL*: */
  496. define_variable(S(read_eval),T); /* *READ-EVAL* := T */
  497. /* initialize *READING-ARRAY* */
  498. define_variable(S(reading_array),NIL); /* *READING-ARRAY* := NIL */
  499. /* initialize *READING-STRUCT* */
  500. define_variable(S(reading_struct),NIL); /* *READING-STRUCT* := NIL */
  501. { /* initialize *READTABLE*: */
  502. var object readtable = orig_readtable();
  503. O(standard_readtable) = readtable; /* that is the standard-readtable, */
  504. readtable = copy_readtable(readtable); /* one copy of it */
  505. define_variable(S(readtablestern),readtable); /* =: *READTABLE* */
  506. }
  507. /* initialize token_buff_1 and token_buff_2: */
  508. O(token_buff_1) = NIL;
  509. /* token_buff_1 and token_buff_2 will be initialized
  510. with a semi-simple-string and a semi-simple-byte-vector
  511. at the first call of get_buffers (see below).
  512. Displaced-String initialisieren:
  513. new array (with data-vector NIL), Displaced, rank=1 */
  514. O(displaced_string) =
  515. allocate_iarray(bit(arrayflags_displaced_bit)|
  516. bit(arrayflags_dispoffset_bit)|
  517. Atype_Char,
  518. 1,
  519. Array_type_string);
  520. }
  521. /* (SYS::%DEFIO dispatch-reader vector-index) post-initialises the I/O. */
  522. LISPFUNN(defio,2) {
  523. O(dispatch_reader) = STACK_1;
  524. O(dispatch_reader_index) = STACK_0;
  525. VALUES0; skipSTACK(2);
  526. }
  527. /* ======================================================================
  528. LISP - Functions for readtables
  529. ====================================================================== */
  530. /* error, if argument is no Readtable.
  531. check_readtable(obj);
  532. > obj: possibly erroneous Argument
  533. can trigger GC */
  534. local maygc object check_readtable (object obj) {
  535. while (!readtablep(obj)) {
  536. pushSTACK(NIL); /* no PLACE */
  537. pushSTACK(obj); /* TYPE-ERROR slot DATUM */
  538. pushSTACK(S(readtable)); /* TYPE-ERROR slot EXPECTED-TYPE */
  539. pushSTACK(S(readtable)); pushSTACK(obj);
  540. pushSTACK(TheSubr(subr_self)->name);
  541. check_value(type_error,GETTEXT("~S: argument ~S is not a ~S"));
  542. obj = value1;
  543. }
  544. return obj;
  545. }
  546. LISPFUN(copy_readtable,seclass_read,0,2,norest,nokey,0,NIL)
  547. { /* (COPY-READTABLE [from-readtable [to-readtable]]), CLTL p. 361 */
  548. var object from_readtable = STACK_1;
  549. if (!boundp(from_readtable)) {
  550. /* no arguments are given */
  551. get_readtable(from_readtable=); /* current readtable */
  552. VALUES1(copy_readtable(from_readtable));
  553. } else {
  554. if (nullp(from_readtable))
  555. /* instead of NIL take the standard-readtable */
  556. from_readtable = STACK_1 = O(standard_readtable);
  557. else /* check from-readtable: */
  558. from_readtable = STACK_1 = check_readtable(from_readtable);
  559. /* from-readtable is OK */
  560. var object to_readtable = STACK_0;
  561. if (missingp(to_readtable))
  562. /* copy from-readtable, without to-readtable */
  563. VALUES1(copy_readtable(from_readtable));
  564. else { /* check to-readtable and perform the copying: */
  565. to_readtable = check_readtable(to_readtable);
  566. from_readtable = STACK_1; /* restore: check_readtable() may cons */
  567. VALUES1(copy_readtable_contents(from_readtable,to_readtable));
  568. }
  569. }
  570. skipSTACK(2);
  571. }
  572. LISPFUN(set_syntax_from_char,seclass_default,2,2,norest,nokey,0,NIL)
  573. { /* (SET-SYNTAX-FROM-CHAR to-char from-char [to-readtable [from-readtable]]),
  574. CLTL p. 361 */
  575. var chart to_char = char_code(check_char(STACK_3));
  576. var chart from_char = char_code(check_char(STACK_2));
  577. var object to_readtable = STACK_1;
  578. /* check to-readtable: */
  579. if (!boundp(to_readtable)) { /* default is the current readtable */
  580. get_readtable(to_readtable=STACK_1=);
  581. } else
  582. to_readtable = STACK_1 = check_readtable(to_readtable);
  583. /* check from-readtable: */
  584. var object from_readtable = STACK_0;
  585. if (missingp(from_readtable)) { /* default is the standard-readtable */
  586. STACK_0 = from_readtable = O(standard_readtable);
  587. } else {
  588. STACK_0 = from_readtable = check_readtable(from_readtable);
  589. to_readtable = STACK_1; /* restore: check_readtable() may cons */
  590. }
  591. /* now to_char, from_char, to_readtable, from_readtable are OK. */
  592. /* copy syntaxcode: */
  593. syntax_readtable_put(to_readtable,to_char,
  594. syntax_readtable_get(from_readtable,from_char));
  595. /* copy macro-function/vector: */
  596. var object entry =
  597. perchar_table_get(TheReadtable(STACK_0)->readtable_macro_table,from_char);
  598. if (simple_vector_p(entry))
  599. /* if entry is a simple-vector, it must be copied: */
  600. entry = copy_perchar_table(entry);
  601. perchar_table_put(TheReadtable(STACK_1)->readtable_macro_table,to_char,entry);
  602. VALUES1(T);
  603. skipSTACK(4);
  604. }
  605. /* UP: checks an optional readtable-argument,
  606. with default = current readtable.
  607. > readtable: Argument
  608. < result: readtable
  609. can trigger GC */
  610. local maygc object test_readtable_arg (object readtable) {
  611. if (!boundp(readtable)) {
  612. get_readtable(readtable=); /* the current readtable is default */
  613. } else
  614. readtable = check_readtable(readtable);
  615. return readtable;
  616. }
  617. /* UP: checks an optional readtable-argument,
  618. with default = current readtable, nil = standard-readtable.
  619. > readtable: Argument
  620. < result: readtable
  621. can trigger GC */
  622. local maygc object test_readtable_null_arg (object readtable) {
  623. if (!boundp(readtable)) {
  624. get_readtable(readtable=); /* the current readtable is default */
  625. } else if (nullp(readtable)) {
  626. readtable = O(standard_readtable); /* respectively the standard-readtable */
  627. } else
  628. readtable = check_readtable(readtable);
  629. return readtable;
  630. }
  631. /* UP: checks the next-to-last optional argument of
  632. SET-MACRO-CHARACTER and MAKE-DISPATCH-MACRO-CHARACTER.
  633. > arg: non-terminating-p - Argument
  634. < result: new syntaxcode */
  635. local uintB test_nontermp_arg (object arg) {
  636. if (missingp(arg))
  637. return syntax_t_macro; /* terminating is default */
  638. else
  639. return syntax_nt_macro; /* non-terminating-p given and /= NIL */
  640. }
  641. LISPFUN(set_macro_character,seclass_default,2,2,norest,nokey,0,NIL)
  642. { /* (SET-MACRO-CHARACTER char function [non-terminating-p [readtable]]),
  643. CLTL p. 362 */
  644. var chart c = char_code(check_char(STACK_3));
  645. { /* check function and convert into an object of type FUNCTION: */
  646. var object function = coerce_function(STACK_2);
  647. if (cclosurep(function)
  648. && eq(TheCclosure(function)->clos_codevec,
  649. TheCclosure(O(dispatch_reader))->clos_codevec)) {
  650. var object vector =
  651. TheCclosure(function)->clos_consts[posfixnum_to_V(O(dispatch_reader_index))];
  652. if (simple_vector_p(vector)) {
  653. /* It's a clone of #'dispatch-reader. Pull out the vector. */
  654. function = copy_perchar_table(vector);
  655. }
  656. }
  657. STACK_2 = function;
  658. }
  659. var object readtable = test_readtable_arg(popSTACK()); /* readtable */
  660. var uintB syntaxcode = test_nontermp_arg(popSTACK()); /* new syntaxcode */
  661. STACK_1 = readtable;
  662. /* set syntaxcode: */
  663. syntax_table_put(TheReadtable(readtable)->readtable_syntax_table,c,syntaxcode);
  664. /* add macrodefinition: */
  665. perchar_table_put(TheReadtable(STACK_1)->readtable_macro_table,c,STACK_0);
  666. VALUES1(T);
  667. skipSTACK(2);
  668. }
  669. LISPFUN(get_macro_character,seclass_read,1,1,norest,nokey,0,NIL)
  670. { /* (GET-MACRO-CHARACTER char [readtable]), CLTL p. 362 */
  671. var chart c = char_code(check_char(STACK_1));
  672. var object readtable = test_readtable_null_arg(STACK_0); /* Readtable */
  673. skipSTACK(2);
  674. /* Test the Syntaxcode: */
  675. var object nontermp = NIL; /* non-terminating-p Flag */
  676. switch (syntax_readtable_get(readtable,c)) {
  677. case syntax_nt_macro: { nontermp = T; }
  678. case syntax_t_macro: { /* nontermp = NIL; */
  679. /* c is a macro-character. */
  680. var object entry =
  681. perchar_table_get(TheReadtable(readtable)->readtable_macro_table,c);
  682. if (simple_vector_p(entry)) {
  683. /* c is a dispatch-macro-character. */
  684. if (nullp(O(dispatch_reader))) {
  685. /* Shouldn't happen (bootstrapping problem). */
  686. pushSTACK(code_char(c));
  687. pushSTACK(TheSubr(subr_self)->name);
  688. error(error_condition,GETTEXT("~S: ~S is a dispatch macro character"));
  689. }
  690. /* Clone #'dispatch-reader. */
  691. pushSTACK(copy_perchar_table(entry));
  692. var object newclos = allocate_cclosure_copy(O(dispatch_reader));
  693. do_cclosure_copy(newclos,O(dispatch_reader));
  694. TheCclosure(newclos)->clos_consts[posfixnum_to_V(O(dispatch_reader_index))] = popSTACK();
  695. value1 = newclos;
  696. } else
  697. value1 = entry;
  698. } break;
  699. default: /* nontermp = NIL; */
  700. value1 = NIL; break;
  701. }
  702. value2 = nontermp; mv_count=2; /* nontermp as second value */
  703. }
  704. LISPFUN(make_dispatch_macro_character,seclass_default,1,2,norest,nokey,0,NIL)
  705. { /* (MAKE-DISPATCH-MACRO-CHARACTER char [non-terminating-p [readtable]]),
  706. CLTL p. 363 */
  707. var object readtable = test_readtable_arg(STACK_0); /* Readtable */
  708. var uintB syntaxcode = test_nontermp_arg(STACK_1); /* new syntaxcode */
  709. STACK_1 = readtable;
  710. var chart c = char_code(check_char(STACK_2));
  711. /* fetch new (empty) dispatch-macro-table: */
  712. STACK_0 = allocate_perchar_table(); /* vector, filled with NIL */
  713. /* store everything in the readtable: */
  714. /* syntaxcode into syntax-table: */
  715. syntax_table_put(TheReadtable(STACK_1)->readtable_syntax_table,c,syntaxcode);
  716. /* new dispatch-macro-table into the macrodefinition table: */
  717. perchar_table_put(TheReadtable(STACK_1)->readtable_macro_table,c,STACK_0);
  718. VALUES1(T);
  719. skipSTACK(3);
  720. }
  721. /* UP: checks the arguments disp-char and sub-char.
  722. > in STACK: *(argsp STACKop 1) = disp-char, *(argsp STACKop 0) = sub-char
  723. > STACK_0: readtable
  724. < result: the dispatch-macro-table for disp-char,
  725. nullobj if sub-char is a digit.
  726. can trigger GC */
  727. local maygc object test_disp_sub_char (gcv_object_t* argsp) {
  728. var object sub_ch = check_char(*(argsp STACKop 0)); /* sub-char */
  729. retry_disp_ch:
  730. var object disp_ch = check_char(*(argsp STACKop 1)); /* disp-char */
  731. var chart disp_c = char_code(disp_ch);
  732. var object entry =
  733. perchar_table_get(TheReadtable(STACK_0)->readtable_macro_table,disp_c);
  734. if (!simple_vector_p(entry)) {
  735. pushSTACK(NIL); /* no PLACE */
  736. pushSTACK(disp_ch);
  737. pushSTACK(TheSubr(subr_self)->name);
  738. check_value(error_condition,GETTEXT("~S: ~S is not a dispatch macro character"));
  739. *(argsp STACKop 1) = value1;
  740. goto retry_disp_ch;
  741. }
  742. /* disp-char is a dispatching-macro-character, entry is the vector. */
  743. var cint sub_c = as_cint(up_case(char_code(sub_ch))); /* convert sub-char into upper case */
  744. if ((sub_c >= '0') && (sub_c <= '9')) /* digit */
  745. return nullobj;
  746. else /* valid sub-char */
  747. return entry;
  748. }
  749. LISPFUN(set_dispatch_macro_character,seclass_default,3,1,norest,nokey,0,NIL)
  750. { /* (SET-DISPATCH-MACRO-CHARACTER disp-char sub-char function [readtable]),
  751. CLTL p. 364 */
  752. /* check function and convert it into an object of Type FUNCTION: */
  753. STACK_1 = coerce_function(STACK_1);
  754. STACK_0 = test_readtable_arg(STACK_0); /* Readtable */
  755. var object dm_table = test_disp_sub_char(&STACK_2);
  756. if (eq(dm_table,nullobj)) {
  757. pushSTACK(STACK_2); /* sub-char, TYPE-ERROR slot DATUM */
  758. pushSTACK(O(type_not_digit)); /* TYPE-ERROR slot EXPECTED-TYPE */
  759. pushSTACK(STACK_(2+2));
  760. pushSTACK(TheSubr(subr_self)->name);
  761. error(type_error,GETTEXT("~S: digit ~C not allowed as sub-char"));
  762. } else {
  763. /* add function to the dispatch-macro-table */
  764. perchar_table_put(dm_table,up_case(char_code(STACK_2)),STACK_1);
  765. VALUES1(T); skipSTACK(4);
  766. }
  767. }
  768. LISPFUN(get_dispatch_macro_character,seclass_read,2,1,norest,nokey,0,NIL)
  769. { /* (GET-DISPATCH-MACRO-CHARACTER disp-char sub-char [readtable]),
  770. CLTL p. 364 */
  771. STACK_0 = test_readtable_null_arg(STACK_0); /* readtable */
  772. var object dm_table = test_disp_sub_char(&STACK_1);
  773. VALUES1(eq(dm_table,nullobj) ? NIL /* NIL or Function as value */
  774. : perchar_table_get(dm_table,up_case(char_code(STACK_1))));
  775. skipSTACK(3);
  776. }
  777. #define RTCase(rt) ((uintW)posfixnum_to_V(TheReadtable(rt)->readtable_case))
  778. LISPFUNN(readtable_case,1)
  779. { /* (READTABLE-CASE readtable), CLTL2 S. 549 */
  780. var object readtable = check_readtable(popSTACK()); /* Readtable */
  781. VALUES1((&O(rtcase_0))[RTCase(readtable)]);
  782. }
  783. LISPFUNN(set_readtable_case,2)
  784. { /* (SYSTEM::SET-READTABLE-CASE readtable value), CLTL2 p. 549 */
  785. var object value = popSTACK();
  786. retry_readtable_case:
  787. /* convert symbol value into an index by searching in table O(rtcase..): */
  788. var const gcv_object_t* ptr = &O(rtcase_0);
  789. var uintC rtcase = 0;
  790. var uintC count = 4;
  791. while (count--) {
  792. if (eq(*ptr,value))
  793. goto found;
  794. ptr++; rtcase++;
  795. };
  796. { /* invalid value */
  797. pushSTACK(NIL); /* no PLACE */
  798. pushSTACK(value); /* TYPE-ERROR slot DATUM */
  799. pushSTACK(O(type_rtcase)); /* TYPE-ERROR slot EXPECTED-TYPE */
  800. pushSTACK(O(rtcase_3)); pushSTACK(O(rtcase_2));
  801. pushSTACK(O(rtcase_1)); pushSTACK(O(rtcase_0));
  802. pushSTACK(value);
  803. pushSTACK(S(set_readtable_case));
  804. check_value(type_error,GETTEXT("~S: new value ~S should be ~S, ~S, ~S or ~S."));
  805. value = value1;
  806. }
  807. goto retry_readtable_case;
  808. found: /* found in table */
  809. var object readtable = check_readtable(popSTACK()); /* readtable */
  810. TheReadtable(readtable)->readtable_case = fixnum(rtcase);
  811. VALUES1(*ptr);
  812. }
  813. /* ======================================================================
  814. some auxiliary routines and macros for READ and PRINT
  815. ====================================================================== */
  816. /* UP: fetches the value of a symbol. must be fixnum >=2, <=36.
  817. get_base(symbol)
  818. > symbol: Symbol
  819. < result: value of the Symbols, >=2, <=36. */
  820. local uintL get_base (object symbol) {
  821. var object value = Symbol_value(symbol);
  822. var uintV intvalue;
  823. if (posfixnump(value)
  824. && (intvalue = posfixnum_to_V(value),
  825. ((intvalue >= 2) && (intvalue <= 36)))) {
  826. return intvalue;
  827. } else {
  828. Symbol_value(symbol) = fixnum(10);
  829. pushSTACK(value); /* TYPE-ERROR slot DATUM */
  830. pushSTACK(O(type_radix)); /* TYPE-ERROR slot EXPECTED-TYPE */
  831. pushSTACK(value);
  832. pushSTACK(symbol);
  833. error(type_error,
  834. GETTEXT("The value of ~S should be an integer between 2 and 36, not ~S.\n"
  835. "It has been reset to 10."));
  836. }
  837. }
  838. /* UP: fetches the value of *PRINT-BASE*
  839. get_print_base()
  840. < uintL result: >=2, <=36 */
  841. #define get_print_base() \
  842. (!nullpSv(print_readably) ? 10 : get_base(S(print_base)))
  843. /* UP: fetches the value of *READ-BASE*
  844. get_read_base()
  845. < uintL result: >=2, <=36 */
  846. #define get_read_base() get_base(S(read_base))
  847. /* ======================================================================
  848. R E A D
  849. ====================================================================== */
  850. /* Characters are read one by one.
  851. Their syntax codes are determined by use the readtable, cf. CLTL table 22-1.
  852. Syntax code 'constituent' starts a new (extended) token.
  853. For every character in the token, its attribute a_xxxx is looked up by use
  854. of the attribute table, cf. CLTL table 22-3.
  855. O(token_buff_1) is a semi-simple-string, which contains the characters of
  856. the currently read extended-token.
  857. O(token_buff_2) is a semi-simple-byte-vektor, which contains the attributes
  858. of the currently read extended-token.
  859. Both have the same length (in characters respectively bytes).
  860. Special objects, that can be returned by READ:
  861. eof_value: special object, that indicates EOF
  862. dot_value: auxiliary value for the detection of single dots
  863. ------------------------ READ on character-level ---------------------------
  864. error, if read object is not a character:
  865. error_charread(ch,&stream); */
  866. nonreturning_function(local, error_charread, (object ch, const gcv_object_t* stream_)) {
  867. pushSTACK(*stream_); /* STREAM-ERROR slot STREAM */
  868. pushSTACK(ch); /* Character */
  869. pushSTACK(*stream_); /* Stream */
  870. pushSTACK(S(read));
  871. error(stream_error,
  872. GETTEXT("~S from ~S: character read should be a character: ~S"));
  873. }
  874. /* UP: Reads a character and calculates its syntaxcode.
  875. read_char_syntax(ch=,scode=,&stream);
  876. > stream: Stream
  877. < stream: Stream
  878. < object ch: Character or eof_value
  879. < uintWL scode: Syntaxcode (from the current readtable) respectively syntax_eof
  880. can trigger GC */
  881. #define read_char_syntax(ch_assignment,scode_assignment,stream_) \
  882. { var object ch0 = read_char(stream_); /* read character */ \
  883. ch_assignment ch0; \
  884. if (eq(ch0,eof_value)) /* EOF ? */ \
  885. { scode_assignment syntax_eof; } \
  886. else { /* Check for character: */ \
  887. if (!charp(ch0)) { error_charread(ch0,stream_); } \
  888. {var object readtable; \
  889. get_readtable(readtable = ); \
  890. scode_assignment /* fetch syntaxcode from table */ \
  891. syntax_readtable_get(readtable,char_code(ch0)); \
  892. }}}
  893. /* error-message at EOF outside of objects
  894. error_eof_outside(&stream);
  895. > stream: Stream */
  896. nonreturning_function(local, error_eof_outside, (const gcv_object_t* stream_)) {
  897. pushSTACK(*stream_); /* STREAM-ERROR slot STREAM */
  898. pushSTACK(*stream_); /* Stream */
  899. pushSTACK(S(read));
  900. error(end_of_file,GETTEXT("~S: input stream ~S has reached its end"));
  901. }
  902. /* error-message at EOF inside of objects
  903. error_eof_inside(&stream);
  904. > stream: Stream */
  905. nonreturning_function(local, error_eof_inside, (const gcv_object_t* stream_)) {
  906. pushSTACK(*stream_); /* STREAM-ERROR slot STREAM */
  907. if (posfixnump(Symbol_value(S(read_line_number)))) { /* check SYS::*READ-LINE-NUMBER* */
  908. pushSTACK(Symbol_value(S(read_line_number))); /* line-number */
  909. pushSTACK(*stream_); /* Stream */
  910. pushSTACK(S(read));
  911. error(end_of_file,GETTEXT("~S: input stream ~S ends within an object. Last opening parenthesis probably in line ~S."));
  912. } else {
  913. pushSTACK(*stream_); /* Stream */
  914. pushSTACK(S(read));
  915. error(end_of_file,GETTEXT("~S: input stream ~S ends within an object"));
  916. }
  917. }
  918. /* error-message at EOF, according to *READ-RECURSIVE-P*
  919. error_eof(&stream);
  920. > stream: Stream */
  921. nonreturning_function(local, error_eof, (const gcv_object_t* stream_)) {
  922. if (!nullpSv(read_recursive_p)) /* *READ-RECURSIVE-P* /= NIL ? */
  923. error_eof_inside(stream_);
  924. else
  925. error_eof_outside(stream_);
  926. }
  927. /* UP: read up to the next non-whitespace-character, without consuming it
  928. At EOF --> Error.
  929. wpeek_char_syntax(ch=,scode=,&stream);
  930. > stream: Stream
  931. < stream: Stream
  932. < object ch: next character
  933. < uintWL scode: its syntaxcode
  934. can trigger GC */
  935. #define wpeek_char_syntax(ch_assignment,scode_assignment,stream_) \
  936. { while (1) { \
  937. object ch0 = read_char(stream_); /* read Character */ \
  938. if (eq(ch0,eof_value)) { error_eof(stream_); } /* EOF -> Error */ \
  939. /* check for Character: */ \
  940. if (!charp(ch0)) { error_charread(ch0,stream_); } \
  941. {var object readtable; \
  942. get_readtable(readtable = ); \
  943. if (!((scode_assignment /* fetch Syntaxcode from table */ \
  944. syntax_readtable_get(readtable,char_code(ch0))) \
  945. == syntax_whitespace)) \
  946. /* no Whitespace -> push back last read character */ \
  947. { unread_char(stream_,ch0); ch_assignment ch0; break; } \
  948. }}}
  949. /* UP: read up to the next non-whitespace-character, without consuming it.
  950. wpeek_char_eof(&stream)
  951. > stream: Stream
  952. < stream: Stream
  953. < result: next character or eof_value
  954. can trigger GC */
  955. local maygc object wpeek_char_eof (const gcv_object_t* stream_) {
  956. while (1) {
  957. var object ch = peek_char(stream_); /* peek character */
  958. if (eq(ch,eof_value)) /* EOF ? */
  959. return ch;
  960. /* check for Character: */
  961. if (!charp(ch))
  962. error_charread(ch,stream_);
  963. var object readtable;
  964. get_readtable(readtable = );
  965. if (!(( /* fetch Syntaxcode from table */
  966. syntax_readtable_get(readtable,char_code(ch)))
  967. == syntax_whitespace))
  968. return ch;
  969. read_char(stream_); /* drop the last (whitespace) character */
  970. }
  971. }
  972. /* ------------------- READ at token-level -------------------------------
  973. read_token and test_potential_number_syntax, test_number_syntax need
  974. the attributes according to CLTL table 22-3.
  975. During test_potential_number_syntax attributes are transformed,
  976. a_digit partially into a_alpha or a_letter or a_expo_m.
  977. meaning of the entries in attribute_table: */
  978. #define a_illg 0 /* illegal constituent */
  979. #define a_pack_m 1 /* ':' = Package-marker */
  980. #define a_alpha 2 /* character without special property (alphabetic) */
  981. #define a_escaped 3 /* character without special property, not subject to case conversion */
  982. #define a_ratio 4 /* '/' */
  983. #define a_dot 5 /* '.' */
  984. #define a_plus 6 /* '+' */
  985. #define a_minus 7 /* '-' */
  986. #define a_extens 8 /* '_^' extension characters */
  987. #define a_digit 9 /* '0123456789' */
  988. #define a_letterdigit 10 /* 'A'-'Z','a'-'z' less than base, not 'esfdlESFDL' */
  989. #define a_expodigit 11 /* 'esfdlESFDL' less than base */
  990. #define a_letter 12 /* 'A'-'Z','a'-'z', not 'esfdlESFDL' */
  991. #define a_expo_m 13 /* 'esfdlESFDL' */
  992. /* >= a_letter - 'A'-'Z','a'-'z'
  993. >= a_digit - '0123456789','A'-'Z','a'-'z'
  994. >= a_ratio - what a potential number must consist of */
  995. /* attribute-table for constituents, first interpretation:
  996. note: first, 0-9,A-Z,a-z are interpreted as a_digit or a_expo_m,
  997. then (if no integer can be deduced out of token), a_digit
  998. is interpreted as a_alpha (alphabetic) above of *READ-BASE*. */
  999. local const uintB attribute_table[small_char_code_limit] = {
  1000. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, /* chr(0) upto chr(7) */
  1001. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, /* chr(8) upto chr(15) */
  1002. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, /* chr(16) upto chr(23) */
  1003. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, /* chr(24) upto chr(31) */
  1004. a_illg, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, /* ' !"#$%&'' */
  1005. a_alpha, a_alpha, a_alpha, a_plus, a_alpha, a_minus, a_dot, a_ratio, /* '()*+,-./' */
  1006. a_digit, a_digit, a_digit, a_digit, a_digit, a_digit, a_digit, a_digit, /* '01234567' */
  1007. a_digit, a_digit, a_pack_m,a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, /* '89:;<=>?' */
  1008. a_alpha, a_letter,a_letter,a_letter,a_expo_m,a_expo_m,a_expo_m,a_letter, /* '@ABCDEFG' */
  1009. a_letter,a_letter,a_letter,a_letter,a_expo_m,a_letter,a_letter,a_letter, /* 'HIJKLMNO' */
  1010. a_letter,a_letter,a_letter,a_expo_m,a_letter,a_letter,a_letter,a_letter, /* 'PQRSTUVW' */
  1011. a_letter,a_letter,a_letter,a_alpha, a_alpha, a_alpha, a_extens,a_extens, /* 'XYZ[\]^_' */
  1012. a_alpha, a_letter,a_letter,a_letter,a_expo_m,a_expo_m,a_expo_m,a_letter, /* '`abcdefg' */
  1013. a_letter,a_letter,a_letter,a_letter,a_expo_m,a_letter,a_letter,a_letter, /* 'hijklmno' */
  1014. a_letter,a_letter,a_letter,a_expo_m,a_letter,a_letter,a_letter,a_letter, /* 'pqrstuvw' */
  1015. a_letter,a_letter,a_letter,a_alpha, a_alpha, a_alpha, a_alpha, /* 'xyz{|}~' */
  1016. #if defined(UNICODE) || defined(ISOLATIN_CHS) || defined(HPROMAN8_CHS)
  1017. a_illg,
  1018. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1019. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1020. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1021. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1022. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1023. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1024. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1025. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1026. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1027. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1028. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1029. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1030. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1031. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1032. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1033. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1034. #elif defined(NEXTSTEP_CHS)
  1035. a_illg,
  1036. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1037. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1038. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1039. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1040. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1041. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1042. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1043. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1044. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1045. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1046. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1047. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1048. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1049. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1050. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1051. a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha, a_alpha,
  1052. #else /* defined(ASCII_CHS) && !defined(UNICODE) */
  1053. a_illg,
  1054. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1055. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1056. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1057. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1058. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1059. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1060. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1061. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1062. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1063. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1064. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1065. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1066. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1067. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1068. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1069. a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg, a_illg,
  1070. #endif
  1071. };
  1072. /* Returns the attribute code for a character code.
  1073. attribute_of(c)
  1074. > chart c: character code
  1075. < uintB result: attribute code */
  1076. #if (small_char_code_limit < char_code_limit) /* i.e. defined(UNICODE) */
  1077. #define attribute_of(c) \
  1078. (uintB)(as_cint(c) < small_char_code_limit \
  1079. ? attribute_table[as_cint(c)] \
  1080. : (graphic_char_p(c) ? a_alpha : a_illg))
  1081. #else
  1082. #define attribute_of(c) attribute_table[as_cint(c)]
  1083. #endif
  1084. /* Flag. indicates, if a single-escape- or multiple-escape-character
  1085. occurred in the last read token: */
  1086. local bool token_escape_flag;
  1087. /* UP: delivers two buffers.
  1088. if two buffers are available in the reservoir O(token_buff_1), O(token_buff_2),
  1089. they are extracted. Otherwise new ones are allocated.
  1090. If the buffers are not needed anymore, they can be written back to
  1091. O(token_buff_1) and O(token_buff_2).
  1092. < STACK_1: a Semi-Simple String with Fill-Pointer 0
  1093. < STACK_0: a Semi-Simple Byte-Vector with Fill-Pointer 0
  1094. < STACK: decreased by 2
  1095. can trigger GC */
  1096. local maygc void get_buffers (void) {
  1097. /* Mechanism:
  1098. O(token_buff_1) and O(token_buff_2) hold a Semi-Simple-String
  1099. and a Semi-Simple-Byte-Vector, which are extracted if necessary (and marked
  1100. with O(tokeā€¦

Large files files are truncated, but you can click here to view the full file