io.cpp 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131
  1. /* Definitions for high-level IO functions.
  2. This file is part of khipu.
  3. khipu is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  13. #include <cctype>
  14. #include <cstdlib>
  15. #include <cstdio>
  16. #include <cstdarg>
  17. #include <cerrno>
  18. #include <new>
  19. #include "khipu.hpp"
  20. #include "utils/chmask.hpp"
  21. #include "utils/raw_acc.hpp"
  22. KP_DECLS_BEGIN
  23. static inline exception
  24. raise_eos (interpreter *interp)
  25. {
  26. return (interp->raise ("parse-error", "read: premature end of input"));
  27. }
  28. enum
  29. {
  30. TOK_NONE,
  31. TOK_OPEN,
  32. TOK_CLOSE,
  33. TOK_DOT,
  34. TOK_SYM,
  35. TOK_NUM,
  36. TOK_CHAR,
  37. TOK_COMMA,
  38. TOK_COMMAAT,
  39. TOK_COMMADOT,
  40. TOK_BQ,
  41. TOK_QUOTE,
  42. TOK_SHARPDOT,
  43. TOK_LABEL,
  44. TOK_BACKREF,
  45. TOK_SHARPQUOTE,
  46. TOK_SHARPOPEN,
  47. TOK_OPENB,
  48. TOK_CLOSEB,
  49. TOK_OPENBRACE,
  50. TOK_CLOSEBRACE,
  51. TOK_SHARPSYM,
  52. TOK_GENSYM,
  53. TOK_DQUOTE,
  54. TOK_SHARPDQUOT
  55. };
  56. static inline bool
  57. symchar_p (int c)
  58. {
  59. static const char SPEC_CHS[] = "()[]{}'\";`,\\| \f\n\r\t\v";
  60. return (!memchr (SPEC_CHS, c, sizeof (SPEC_CHS) - 1));
  61. }
  62. static result<bool>
  63. numtok_p (interpreter *interp, char *tok, int len)
  64. {
  65. if (*tok == '\0')
  66. return (false);
  67. else if (len == 4 && (memcmp (tok, "-INF", 4) == 0 ||
  68. memcmp (tok, "+INF", 4) == 0))
  69. {
  70. interp->retval = *tok == '-' ? FLT_NINF : FLT_PINF;
  71. return (true);
  72. }
  73. else if (len == 3 && memcmp (tok, "NaN", 3) == 0)
  74. {
  75. interp->retval = FLT_QNAN;
  76. return (true);
  77. }
  78. num_info info;
  79. if (tok[len - 1] == '.')
  80. tok[len++] = '0';
  81. if (parse_num (interp, tok, len, info) < 0)
  82. return (false);
  83. else if (info.type == typecode::INT)
  84. {
  85. int slen = info.dec_end - info.dec_start;
  86. int rl = invbsize (info.radix, slen) + 1;
  87. if (rl == 1)
  88. { // May fit in a fixint.
  89. intptr_t uval = strtoui1 (tok + info.dec_start, slen, info.radix);
  90. intptr_t val = info.sign ? -uval : uval;
  91. interp->retval = intobj (interp, val);
  92. }
  93. else
  94. {
  95. bigint *lp = as_bigint (alloc_bigint (interp, rl));
  96. lp->len = strtoui (lp->data, tok + info.dec_start, slen, info.radix);
  97. #ifdef KP_ARCH_WIDE
  98. interp->retval = lp->as_obj () | (info.sign ? SIGN_BIT : 0);
  99. #else
  100. if (info.sign)
  101. lp->len = -lp->len;
  102. interp->retval = lp->as_obj ();
  103. #endif
  104. }
  105. return (true);
  106. }
  107. // info.type == typecode::FLOAT
  108. int expo, slen = info.frac_end - info.dec_start - 1;
  109. if (info.expo_start != 0)
  110. {
  111. uint32_t uev;
  112. if (invbsize (info.radix, len - info.expo_start) > 1 ||
  113. (uev = strtoui1 (&tok[info.expo_start], len -
  114. info.expo_start, info.radix)) >
  115. 0x7fffffffu + info.expo_sign)
  116. return (interp->raise ("arith-error", "exponent "
  117. "too large in floating point value"));
  118. expo = info.expo_sign ? -(int)uev : uev;
  119. }
  120. else
  121. expo = 0;
  122. if (info.frac_end != 0)
  123. expo -= info.frac_end - info.dec_end - info.got_dot;
  124. /* The maximum number of limbs to be used by 'strtolf' is the
  125. * sum of the limbs needed by the mantissa and radix^exponent,
  126. * given that it may end up multiplying them. */
  127. int nlimbs = invbsize (info.radix, slen) +
  128. invbsize (info.radix, abs (expo)) + 2;
  129. tmp_allocator ta { interp };
  130. limb_t *mp = (limb_t *)ta.alloc (nlimbs * sizeof (*mp));
  131. memset (mp, 0, nlimbs * sizeof (*mp));
  132. int ret = strtolf (interp, tok, len, info, expo, mp);
  133. int b2exp = (expo - ret) * LIMB_BITS;
  134. if (b2exp >= DBL_MIN_EXP && b2exp <= DBL_MAX_EXP)
  135. { // See if we can fit it in a double.
  136. double dbl = uitodbl (mp, ret, expo);
  137. if (!finf_p (dbl))
  138. {
  139. interp->retval = fltobj::make (interp,
  140. info.sign ? -dbl : dbl);
  141. return (true);
  142. }
  143. }
  144. bigfloat *fp = as_bigfloat (alloc_bigfloat (interp, ret));
  145. memcpy (fp->data, mp, (fp->len = ret) * sizeof (*fp->data));
  146. fp->expo = expo;
  147. #ifdef KP_ARCH_WIDE
  148. interp->retval = fp->as_obj () | (info.sign ? SIGN_BIT : 0);
  149. #else
  150. if (info.sign)
  151. fp->len = -fp->len;
  152. interp->retval = fp->as_obj ();
  153. #endif
  154. return (true);
  155. }
  156. static const struct
  157. {
  158. const char *name;
  159. uint32_t value;
  160. } CHAR_NAMES[] =
  161. {
  162. { "lf", '\n' },
  163. { "tab", '\t' },
  164. { "sp", ' ' },
  165. { "nil", '\0' },
  166. { "bell", '\a' },
  167. { "back", '\b' },
  168. { "ret", '\r' },
  169. { "vtab", '\v' }
  170. };
  171. const char* chobj_repr (uint32_t ch)
  172. {
  173. for (size_t i = 0; i < KP_NELEM (CHAR_NAMES); ++i)
  174. if (ch == CHAR_NAMES[i].value)
  175. return (CHAR_NAMES[i].name);
  176. return (nullptr);
  177. }
  178. reader::reader (interpreter *ip, object input, package *pkg) :
  179. interp (ip), pairs_valref (ip), ipkg (pkg)
  180. {
  181. this->pairs.local_init (this->stpairs, KP_NELEM (this->stpairs));
  182. this->pair_cnt = 0;
  183. for (uint32_t i = 0; i < this->pairs.len; ++i)
  184. this->pairs.data[i] = UNBOUND;
  185. this->bufmax = KP_NELEM (this->stbuf);
  186. this->bufp = this->stbuf;
  187. this->take ();
  188. this->src = as_stream (input);
  189. *this->pairs_valref = this->pairs.as_obj ();
  190. if (!this->ipkg)
  191. this->ipkg = as_package (ip->xpkg);
  192. }
  193. void reader::take ()
  194. {
  195. this->toktype = TOK_NONE;
  196. this->bufcnt = 0;
  197. }
  198. void reader::push_ch (const schar& ch)
  199. {
  200. if (this->bufcnt + ch.len >= this->bufmax)
  201. {
  202. int nsize = (int)upsize (this->bufcnt + ch.len + 1);
  203. char *nbuf = (char *)xmalloc (nsize);
  204. memcpy (nbuf, this->bufp, this->bufcnt);
  205. if (this->bufp != this->stbuf)
  206. xfree (this->bufp);
  207. this->bufp = nbuf;
  208. this->bufmax = nsize;
  209. }
  210. fscpy (this->bufp + this->bufcnt, ch.buf, ch.len);
  211. this->bufcnt += ch.len;
  212. }
  213. result<bool> reader::read_token (schar& ch, int digs)
  214. {
  215. bool first = true;
  216. int esc_p = 0, sym_p = 0;
  217. while (true)
  218. {
  219. if (!first)
  220. {
  221. bool rv = KP_TRY (this->src->sgetc (this->interp, ch));
  222. if (!rv)
  223. goto term;
  224. }
  225. first = false;
  226. if (ch.uc == '|')
  227. esc_p ^= (sym_p = 1);
  228. else if (ch.uc == '\\')
  229. {
  230. sym_p = 1;
  231. bool rv = KP_TRY (this->src->sgetc (this->interp, ch));
  232. if (!rv)
  233. goto term;
  234. this->push_ch (ch);
  235. }
  236. else if (!esc_p && (!symchar_p (ch.uc) &&
  237. (!digs || isdigit (ch.uc))))
  238. break;
  239. else
  240. this->push_ch (ch);
  241. }
  242. this->src->ungetuc (ch.buf, ch.len);
  243. term:
  244. this->bufp[this->bufcnt] = '\0';
  245. return (sym_p != 0);
  246. }
  247. void reader::expand ()
  248. {
  249. object *p2 = (object *)xmalloc (this->pairs.len * 2);
  250. copy_objs (p2, this->pairs.data, this->pairs.len);
  251. this->pairs.len *= 2;
  252. if (this->pairs.data != this->stpairs)
  253. xfree (this->pairs.data);
  254. this->pairs.data = p2;
  255. }
  256. object reader::getlbl (object lbl) const
  257. {
  258. for (uint32_t i = 0; i < this->pair_cnt; i += 2)
  259. if (this->pairs.data[i] == lbl)
  260. return (this->pairs.data[i + 1]);
  261. return (UNBOUND);
  262. }
  263. object* reader::putlbl (object lbl)
  264. {
  265. for (uint32_t i = 0; i < this->pair_cnt; i += 2)
  266. if (this->pairs.data[i] == UNBOUND)
  267. {
  268. this->pairs.data[i] = lbl;
  269. return (&this->pairs.data[i + 1]);
  270. }
  271. else if (this->pairs.data[i] == lbl)
  272. return (&this->pairs.data[i + 1]);
  273. if (this->pair_cnt == this->pairs.len)
  274. this->expand ();
  275. this->pairs.data[this->pair_cnt++] = lbl;
  276. return (&this->pairs.data[this->pair_cnt]);
  277. }
  278. result<bool> reader::nextc (schar& ch)
  279. {
  280. do
  281. {
  282. bool rv = KP_TRY (this->src->sgetc (this->interp, ch));
  283. if (!rv)
  284. return (false);
  285. else if (ch.uc == ';')
  286. do
  287. {
  288. rv = KP_TRY (this->src->sgetc (this->interp, ch));
  289. if (!rv)
  290. return (false);
  291. }
  292. while (ch.uc != '\n');
  293. if (ch.uc == '\n')
  294. ++this->lineno;
  295. }
  296. while (isspace (ch.uc));
  297. return (true);
  298. }
  299. static inline bool
  300. check_symname (interpreter *interp, const char *name, int len)
  301. {
  302. num_info info;
  303. return (parse_num (interp, name, len, info) < 0);
  304. }
  305. static result<void>
  306. update_pkg_expr (interpreter *interp, const char *sname,
  307. const char *uptr, const char *uend, object& out)
  308. {
  309. valref key = KP_TRY (symbol::make_kword (interp, uptr, uend - uptr));
  310. if (out == UNBOUND)
  311. {
  312. out = KP_TRY (KP_CALL (interp, list_fct,
  313. intern (interp, sname, (uptr - sname) - 2), *key));
  314. }
  315. else
  316. {
  317. *key = KP_TRY (cons::make (interp, *key, NIL));
  318. out = KP_TRY (cons::make (interp, out, *key));
  319. }
  320. return (0);
  321. }
  322. static result<object>
  323. make_pkg_expr (interpreter *interp, object name, object ipkg)
  324. {
  325. /* Transform a symbol name of the kind 'a::b::c' into its equivalent
  326. * expression: ((a :b) :c).
  327. * This is required when the symbol can't be resolved at read-time,
  328. * and is therefore delegated to a runtime lookup. */
  329. const char *sname = str_cdata (name);
  330. int len = as_str(name)->nbytes;
  331. valref ret (interp, UNBOUND), key (interp, UNBOUND);
  332. while (true)
  333. {
  334. auto uptr = (const char *)memchr (sname, ':', len);
  335. if (!uptr)
  336. { // Last name - Append and we're out.
  337. *key = KP_TRY (symbol::make_kword (interp, sname, len));
  338. *key = KP_TRY (cons::make (interp, *key, NIL));
  339. *ret = KP_TRY (cons::make (interp, *ret, *key));
  340. break;
  341. }
  342. else if (uptr[1] != *uptr)
  343. return (interp->raise ("parse-error",
  344. KP_SPRINTF (interp,
  345. "read: invalid symbol name: %Q",
  346. name)));
  347. auto u2 = (const char *)memchr (uptr + 2, ':', (sname + len - 2) - uptr);
  348. if (!u2)
  349. {
  350. KP_VTRY (update_pkg_expr (interp, sname, uptr + 2,
  351. sname + len, *ret));
  352. break;
  353. }
  354. else if (u2[1] != *u2)
  355. return (interp->raise ("parse-error",
  356. KP_SPRINTF (interp,
  357. "read: invalid symbol name: %Q",
  358. name)));
  359. KP_VTRY (update_pkg_expr (interp, sname, uptr + 2, u2, *ret));
  360. len -= (u2 + 2) - sname;
  361. sname = u2 + 2;
  362. }
  363. kp_return (*ret);
  364. }
  365. result<void> reader::handle_sym (object pkg, object name)
  366. {
  367. valref xpkg (interp, pkg), tmp (interp, UNBOUND);
  368. const char *sname = str_cdata (name);
  369. int len = as_str(name)->nbytes;
  370. auto ip = this->interp;
  371. while (true)
  372. {
  373. auto uptr = (const char *)memchr (sname, ':', len);
  374. if (!uptr)
  375. {
  376. KP_VTRY (intern (this->interp, sname, len, as_package (*xpkg)));
  377. return (0);
  378. }
  379. else if (uptr[1] != *uptr ||
  380. !check_symname (interp, sname, uptr - sname))
  381. return (ip->raise ("parse-error",
  382. KP_SPRINTF (ip, "read: invalid symbol name: %Q",
  383. name)));
  384. *tmp = find_sym (interp, *xpkg, sname, uptr - sname);
  385. *tmp = !symbol_p (*tmp) ? UNBOUND : symval (*tmp);
  386. if (package_p (*tmp))
  387. // Still reachable at read-time - Update the current package.
  388. *xpkg = *tmp;
  389. else
  390. {
  391. KP_VTRY (make_pkg_expr (interp, name, *xpkg));
  392. return (0);
  393. }
  394. len -= (uptr + 2) - sname;
  395. sname = uptr + 2;
  396. }
  397. }
  398. result<uint32_t> reader::peek ()
  399. {
  400. schar ch;
  401. bool rv;
  402. if (this->toktype != TOK_NONE)
  403. return (this->toktype);
  404. rv = KP_TRY (this->nextc (ch));
  405. if (!rv)
  406. return (TOK_NONE);
  407. switch (ch.uc)
  408. {
  409. #define DISPATCH(ch, tok) \
  410. case ch: \
  411. this->toktype = TOK_##tok; \
  412. break
  413. DISPATCH ('(', OPEN);
  414. DISPATCH (')', CLOSE);
  415. DISPATCH ('[', OPENB);
  416. DISPATCH (']', CLOSEB);
  417. DISPATCH ('{', OPENBRACE);
  418. DISPATCH ('}', CLOSEBRACE);
  419. DISPATCH ('\'', QUOTE);
  420. DISPATCH ('`', BQ);
  421. DISPATCH (',', COMMA);
  422. DISPATCH ('"', DQUOTE);
  423. DISPATCH ('\\', CHAR);
  424. case '#':
  425. {
  426. rv = KP_TRY (this->src->sgetc (this->interp, ch));
  427. if (!rv)
  428. return (this->interp->raise ("parse-error",
  429. "read: invalid read macro"));
  430. else if (ch.uc == '.')
  431. this->toktype = TOK_SHARPDOT;
  432. else if (ch.uc == '\'')
  433. this->toktype = TOK_SHARPQUOTE;
  434. else if (ch.uc == '(')
  435. this->toktype = TOK_SHARPOPEN;
  436. else if (ch.uc == '<')
  437. return (this->interp->raise ("parse-error",
  438. "read: unreadable object"));
  439. else if (ch.uc == ':')
  440. {
  441. rv = KP_TRY (this->src->sgetc (this->interp, ch));
  442. if (!rv)
  443. return (raise_eos (this->interp));
  444. KP_VTRY (this->read_token (ch, 0));
  445. bool rv = KP_TRY (numtok_p (this->interp, this->bufp,
  446. this->bufcnt));
  447. if (rv)
  448. return (this->interp->raise ("parse-error",
  449. "read: invalid syntax after #: "
  450. "reader macro"));
  451. this->toktype = TOK_SYM;
  452. valref tmp = KP_TRY (alloc_sym (interp));
  453. symname(*tmp) = KP_TRY (string::make (this->interp, this->bufp,
  454. this->bufcnt));
  455. }
  456. else if (isdigit (ch.uc))
  457. {
  458. KP_VTRY (this->read_token (ch, 1),
  459. this->src->sgetc (this->interp, ch));
  460. if (ch.uc == '#')
  461. this->toktype = TOK_BACKREF;
  462. else if (ch.uc == '=')
  463. this->toktype = TOK_LABEL;
  464. else
  465. return (this->interp->raise ("parse-error",
  466. "read: invalid label"));
  467. errno = 0;
  468. char *endp;
  469. long xv = strtol (bufp, &endp, 10);
  470. if (*endp != '\0' || errno != 0)
  471. return (this->interp->raise ("parse-error",
  472. "read: invalid label"));
  473. this->interp->retval = fixint (xv);
  474. }
  475. else if (ch.uc == '!')
  476. {
  477. do
  478. KP_VTRY (this->src->sgetc (this->interp, ch));
  479. while (ch.uc != UEOF && ch.uc != '\n');
  480. return (this->peek ());
  481. }
  482. else if (ch.uc == '"')
  483. this->toktype = TOK_SHARPDQUOT;
  484. else if (ch.uc == '|')
  485. {
  486. for (int lvl = 1 ; ; )
  487. {
  488. KP_VTRY (this->src->sgetc (this->interp, ch));
  489. got_hashp:
  490. if (ch.uc == UEOF)
  491. return (raise_eos (this->interp));
  492. else if (ch.uc == '|')
  493. {
  494. KP_VTRY (this->src->sgetc (this->interp, ch));
  495. if (ch.uc == '#')
  496. {
  497. if (--lvl == 0)
  498. break;
  499. continue;
  500. }
  501. goto got_hashp;
  502. }
  503. else if (ch.uc == '#')
  504. {
  505. KP_VTRY (this->src->sgetc (this->interp, ch));
  506. if (ch.uc == '|')
  507. ++lvl;
  508. else
  509. goto got_hashp;
  510. }
  511. }
  512. return (this->peek ());
  513. }
  514. else if (ch.uc == '\\')
  515. { // #\x => (intern ',(symname x))
  516. object sym = KP_TRY (this->read_sexpr (UNBOUND));
  517. if (!symbol_p (sym))
  518. return (this->interp->raise ("type-error",
  519. "expected a symbol after "
  520. "read macro #\\"));
  521. valref tmp (interp, sym);
  522. KP_VTRY (alloc_cons (this->interp, 2));
  523. xcar(this->interp->alval) = symbol::quote;
  524. xcadr(this->interp->alval) = symname (*tmp);
  525. *tmp = this->interp->alval;
  526. KP_VTRY (alloc_cons (this->interp, 2));
  527. xcar(this->interp->alval) = KP_TRY (intern (this->interp,
  528. "intern", 6));
  529. xcadr(this->interp->alval) = *tmp;
  530. this->interp->retval = this->interp->alval;
  531. this->toktype = TOK_SYM;
  532. }
  533. else
  534. return (this->interp->raise ("parse-error",
  535. "read: unknown read macro"));
  536. break;
  537. }
  538. default:
  539. // Number or symbol.
  540. rv = KP_TRY (this->read_token (ch, 0));
  541. if (!rv)
  542. {
  543. if (*this->bufp == '.' && this->bufp[1] == '\0')
  544. return (this->toktype = TOK_DOT);
  545. bool rv = KP_TRY (numtok_p (this->interp, this->bufp,
  546. this->bufcnt));
  547. if (rv)
  548. return (this->toktype = TOK_NUM);
  549. }
  550. this->toktype = TOK_SYM;
  551. if (*this->bufp == ':')
  552. {
  553. if (this->bufcnt > 1 && this->bufp[1] == ':')
  554. {
  555. local_varobj<string> nm;
  556. nm.local_init (this->bufp + 2);
  557. KP_VTRY (this->handle_sym (root_package, nm.as_obj ()));
  558. }
  559. else
  560. KP_VTRY (symbol::make_kword (this->interp, this->bufp + 1));
  561. }
  562. else
  563. {
  564. local_varobj<string> nm;
  565. nm.local_init (this->bufp);
  566. KP_VTRY (this->handle_sym (this->ipkg->as_obj (), nm.as_obj ()));
  567. }
  568. break;
  569. }
  570. #undef DISPATCH
  571. return (this->toktype);
  572. }
  573. result<object> reader::read_array (object lbl)
  574. {
  575. object dummy, *dstp = lbl != UNBOUND ? this->putlbl (lbl) : &dummy;
  576. raw_acc<array> ar (3);
  577. *dstp = ar.as_obj ();
  578. while (true)
  579. {
  580. uint32_t rv = KP_TRY (this->peek ());
  581. if (rv == TOK_CLOSEB)
  582. break;
  583. else if (!this->readable_p ())
  584. return (raise_eos (this->interp));
  585. object obj = KP_TRY (this->read_sexpr (UNBOUND));
  586. ar.add_obj (obj);
  587. }
  588. this->take ();
  589. this->interp->retval = ar.as_obj ();
  590. array *ap = ar.release ();
  591. if (ap->len > 0)
  592. gc_register (this->interp, ap, sizeof (*ap) + ar.alloc);
  593. else
  594. {
  595. xfree (ap);
  596. this->interp->retval = deref (alloc_array (this->interp, 0));
  597. }
  598. return (this->interp->retval);
  599. }
  600. result<object> reader::read_table (object)
  601. {
  602. sp_guard sg (this->interp);
  603. // Push equality and hash functions.
  604. KP_VTRY (this->interp->push (NIL),
  605. this->interp->push (NIL));
  606. while (true)
  607. {
  608. uint32_t rv = KP_TRY (this->peek ());
  609. if (rv == TOK_CLOSEBRACE)
  610. break;
  611. else if (!this->readable_p ())
  612. return (raise_eos (this->interp));
  613. object obj = KP_TRY (this->read_sexpr (UNBOUND));
  614. KP_VTRY (this->interp->push (obj));
  615. }
  616. this->take ();
  617. return (table_fct (this->interp, this->interp->stack + sg.sp,
  618. this->interp->stklen () - sg.sp));
  619. }
  620. result<object> reader::read_tuple (object lbl)
  621. {
  622. object dummy, *dstp = lbl != UNBOUND ? this->putlbl (lbl) : &dummy;
  623. valref key (interp, NIL), ret = KP_TRY (alloc_tuple (this->interp, NIL));
  624. *dstp = *ret;
  625. while (true)
  626. {
  627. uint32_t rv = KP_TRY (this->peek ());
  628. if (rv == TOK_CLOSE)
  629. break;
  630. else if (!this->readable_p ())
  631. return (raise_eos (this->interp));
  632. *key = KP_TRY (this->read_sexpr (UNBOUND));
  633. KP_VTRY (tuple_put (interp, *ret, *key, false));
  634. }
  635. this->take ();
  636. kp_return (*ret);
  637. }
  638. static inline int
  639. escape_char (int ch)
  640. {
  641. if (ch == 'n')
  642. return ('\n');
  643. else if (ch == 't')
  644. return ('\t');
  645. else if (ch == 'r')
  646. return ('\r');
  647. else if (ch == 'a')
  648. return ('\a');
  649. else if (ch == 'b')
  650. return ('\b');
  651. else if (ch == '\\' || ch == '"')
  652. return (ch);
  653. else if (ch == '0')
  654. return (0);
  655. else
  656. return (-1);
  657. }
  658. static inline exception
  659. raise_eilseq (interpreter *interp, const char *seq)
  660. {
  661. char buf[100];
  662. sprintf (buf, "read: invalid escape sequence: %s", seq);
  663. return (interp->raise ("parse-error", buf));
  664. }
  665. result<object> reader::read_bvector ()
  666. {
  667. raw_acc<bvector> bv (8);
  668. char ebuf[8];
  669. for (ebuf[0] = '\\' ; ; )
  670. {
  671. int byte = KP_TRY (this->src->getb (this->interp));
  672. if (byte < 0)
  673. return (raise_eos (this->interp));
  674. else if (byte == '"')
  675. break;
  676. else if (byte == '\\')
  677. {
  678. int b1 = 0, b2 = 0;
  679. byte = KP_TRY (this->src->getb (this->interp));
  680. if (byte < 0)
  681. return (raise_eos (this->interp));
  682. else if (byte == 'x')
  683. {
  684. b1 = KP_TRY (this->src->getb (this->interp));
  685. b2 = KP_TRY (this->src->getb (this->interp));
  686. if ((b1 | b2) < 0)
  687. return (raise_eos (this->interp));
  688. else if (!isxdigit (b1) || !isxdigit (b2))
  689. {
  690. ebuf[1] = 'x', ebuf[2] = b1;
  691. ebuf[3] = b2, ebuf[4] = 0;
  692. return (raise_eilseq (this->interp, ebuf));
  693. }
  694. byte = (b1 - '0') * 16 + (b2 - '0');
  695. }
  696. else if ((byte = escape_char (byte)) < 0)
  697. {
  698. ebuf[1] = byte, ebuf[2] = 0;
  699. return (raise_eilseq (this->interp, ebuf));
  700. }
  701. }
  702. #ifdef KP_LITTLE_ENDIAN
  703. bv.add_data (&byte, 1);
  704. #else
  705. unsigned char ub = (unsigned char)byte;
  706. bv.add_data (&ub, 1);
  707. #endif
  708. }
  709. bvector *ret = bv.release ();
  710. if (ret->nbytes > 0)
  711. {
  712. this->interp->retval = ret->as_obj ();
  713. ret->data[ret->nbytes] = 0;
  714. gc_register (this->interp, ret, sizeof (*ret) + bv.alloc);
  715. }
  716. else
  717. {
  718. xfree (ret);
  719. this->interp->retval = deref (alloc_bvector (this->interp, 0));
  720. }
  721. return (this->interp->retval);
  722. }
  723. result<object> reader::read_str ()
  724. {
  725. raw_acc<string> str (8);
  726. char buf[16];
  727. as_str(str.as_obj ())->hval = 0;
  728. as_str(str.as_obj ())->len = 0;
  729. for (buf[0] = '\\' ; ; )
  730. {
  731. schar ch;
  732. bool rv = KP_TRY (this->src->sgetc (this->interp, ch));
  733. if (!rv)
  734. return (raise_eos (this->interp));
  735. else if (ch.uc == '"')
  736. break;
  737. else if (ch.uc == '\\')
  738. {
  739. int n;
  740. rv = KP_TRY (this->src->sgetc (this->interp, ch));
  741. if (!rv)
  742. return (raise_eos (this->interp));
  743. else if ((ch.uc == 'x' && (n = 2)) ||
  744. (ch.uc == 'u' && (n = 4)) ||
  745. (ch.uc == 'U' && (n = 8)))
  746. {
  747. buf[1] = ch.uc;
  748. for (int i = 0; i < n; ++i)
  749. {
  750. rv = KP_TRY (this->src->sgetc (this->interp, ch));
  751. if (!rv)
  752. return (raise_eos (this->interp));
  753. buf[2 + i] = *ch.buf;
  754. if (!isxdigit (*ch.buf))
  755. {
  756. buf[3 + i] = 0;
  757. return (raise_eilseq (this->interp, buf));
  758. }
  759. }
  760. buf[2 + n] = 0;
  761. ch.uc = strtol (&buf[2], nullptr, 16);
  762. if (ch.uc > MAX_CHAR)
  763. return (raise_eilseq (this->interp, buf));
  764. ch.len = u32tou8 ((unsigned char *)ch.buf, ch.uc);
  765. }
  766. else
  767. {
  768. if ((n = escape_char (ch.uc)) < 0)
  769. {
  770. buf[1] = 'X', buf[2 + ch.len] = 0;
  771. memcpy (&buf[2], ch.buf, ch.len);
  772. return (raise_eilseq (this->interp, buf));
  773. }
  774. *ch.buf = n, ch.len = 1;
  775. }
  776. }
  777. str.add_data (ch.buf, ch.len);
  778. ++as_str(str.as_obj ())->len;
  779. }
  780. string *sp = str.release ();
  781. if (sp->len > 0)
  782. {
  783. sp->vo_full |= FLAGS_CONST;
  784. this->interp->retval = sp->as_obj ();
  785. sp->data[sp->nbytes] = '\0';
  786. gc_register (this->interp, sp, sizeof (*sp) + str.alloc);
  787. }
  788. else
  789. {
  790. xfree (sp);
  791. this->interp->retval = deref (alloc_str (this->interp, 0));
  792. }
  793. return (this->interp->retval);
  794. }
  795. result<object> reader::read_char ()
  796. {
  797. schar cv;
  798. auto ip = this->interp;
  799. for (bool got = false ; ; got = true)
  800. {
  801. schar tmp;
  802. bool rv = KP_TRY (this->src->sgetc (this->interp, tmp));
  803. if (!rv)
  804. return (raise_eos (this->interp));
  805. else if (tmp.uc <= 0x7f && !symchar_p (tmp.uc) && got)
  806. {
  807. this->src->ungetuc (tmp.buf, tmp.len);
  808. this->bufp[this->bufcnt] = '\0';
  809. break;
  810. }
  811. else if (!isspace (tmp.uc) && (symchar_p (tmp.uc) || !got))
  812. {
  813. if (!got)
  814. cv = tmp;
  815. this->push_ch (tmp);
  816. }
  817. else if (!got)
  818. return (ip->raise ("parse-error", "read: empty character designator"));
  819. else
  820. {
  821. this->bufp[this->bufcnt] = '\0';
  822. break;
  823. }
  824. }
  825. local_varobj<string> sn;
  826. if (this->bufp[1] == '\0')
  827. ;
  828. else if (cv.uc == 'u' || cv.uc == 'U' || cv.uc == 'x')
  829. {
  830. long rv = strtol (this->bufp + 1, 0, 16);
  831. if (errno != 0 || rv >= (long)MAX_CHAR)
  832. return (ip->raise ("parse-error", "read: invalid unicode constant"));
  833. cv.uc = (uint32_t)rv;
  834. }
  835. else if (cv.uc >= 'a' && cv.uc <= 'z')
  836. {
  837. cv.uc = ~0u;
  838. for (size_t i = 0; i < KP_NELEM (CHAR_NAMES); ++i)
  839. if (strcmp (this->bufp, CHAR_NAMES[i].name) == 0)
  840. {
  841. cv.uc = CHAR_NAMES[i].value;
  842. break;
  843. }
  844. if (cv.uc == ~0u)
  845. {
  846. sn.local_init (this->bufp);
  847. return (ip->raise ("parse-error",
  848. KP_SPRINTF (ip, "read: unknown character: \\%Q",
  849. sn.as_obj ())));
  850. }
  851. }
  852. else
  853. {
  854. sn.local_init (this->bufp);
  855. return (ip->raise ("parse-error",
  856. KP_SPRINTF (ip, "read: unknown character: \\%Q",
  857. sn.as_obj ())));
  858. }
  859. this->take ();
  860. kp_return (charobj (cv.uc));
  861. }
  862. result<object> reader::read_list (object lbl)
  863. {
  864. object dummy, *dstp = lbl != UNBOUND ? this->putlbl (lbl) : &dummy;
  865. valref lr (this->interp, NIL), elem (this->interp);
  866. bool dot = false;
  867. uint32_t tok = KP_TRY (this->peek ());
  868. if (tok == TOK_CLOSE)
  869. {
  870. this->take ();
  871. kp_return (*dstp = NIL);
  872. }
  873. else if (tok == TOK_SHARPQUOTE)
  874. {
  875. KP_VTRY (intern (this->interp, "apply", 5));
  876. *lr = KP_TRY (cons::make (this->interp, this->interp->retval, *lr));
  877. this->take ();
  878. }
  879. tok = KP_TRY (this->peek ());
  880. while (tok != TOK_CLOSE)
  881. {
  882. *elem = KP_TRY (this->read_sexpr (UNBOUND));
  883. *lr = KP_TRY (cons::make (this->interp, *elem, *lr));
  884. tok = KP_TRY (this->peek ());
  885. if (tok == TOK_DOT)
  886. {
  887. this->take ();
  888. *elem = KP_TRY (this->read_sexpr (UNBOUND));
  889. tok = KP_TRY (this->peek ());
  890. if (tok != TOK_CLOSE)
  891. return (this->interp->raise ("parse-error",
  892. "read: elements follow dot in list"));
  893. dot = true;
  894. break;
  895. }
  896. else if (!this->readable_p ())
  897. return (raise_eos (this->interp));
  898. }
  899. this->take ();
  900. if (dot)
  901. { *lr = KP_TRY (nrevconc (this->interp, *lr, *elem)); }
  902. else
  903. { *lr = KP_TRY (nreverse_L (this->interp, *lr)); }
  904. kp_return (*dstp = *lr);
  905. }
  906. // Backquote implementation.
  907. static bool
  908. bq_member (object elem, object lst)
  909. {
  910. for (; cons_p (lst); lst = xcdr (lst))
  911. if (xcar (lst) == elem)
  912. return (true);
  913. return (false);
  914. }
  915. static inline exception
  916. bq_nonlist_splice_err (interpreter *interp, bool dot)
  917. {
  918. char errmsg[] = "read: the syntax `,@form is invalid";
  919. if (dot)
  920. errmsg[19] = '.';
  921. return (interp->raise ("parse-error", errmsg));
  922. }
  923. result<object> reader::read_comma (object lbl)
  924. {
  925. if (this->bq_level <= 0)
  926. return (this->interp->raise ("parse-error",
  927. "read: more commas than backquotes"));
  928. this->unquoted = true;
  929. --this->bq_level;
  930. schar next;
  931. object head = symbol::comma;
  932. bool rv = KP_TRY (this->src->sgetc (this->interp, next));
  933. if (!rv)
  934. return (raise_eos (this->interp));
  935. else if (*next.buf == '@')
  936. head = symbol::comma_at;
  937. else if (*next.buf == '.')
  938. head = symbol::comma_dot;
  939. else
  940. this->src->ungetuc (next.buf, next.len);
  941. object obj = KP_TRY (this->read_sexpr (UNBOUND));
  942. KP_VTRY (alloc_cons (this->interp, 2));
  943. xcar(this->interp->alval) = head;
  944. xcadr(this->interp->alval) = obj;
  945. if (lbl != UNBOUND)
  946. *this->putlbl(lbl) = this->interp->alval;
  947. ++this->bq_level;
  948. kp_return (this->interp->alval);
  949. }
  950. result<object> reader::read_bq (object lbl)
  951. {
  952. bool prev = this->unquoted;
  953. this->unquoted = false;
  954. ++this->bq_level;
  955. object obj = KP_TRY (this->read_sexpr (UNBOUND));
  956. if (cons_p (obj))
  957. {
  958. object head = xcar (obj), tst = symbol::comma_at;
  959. if (head == symbol::comma_at || head == symbol::comma_dot)
  960. return (bq_nonlist_splice_err (interp, head == symbol::comma_dot));
  961. else if (bq_member (tst, obj) ||
  962. bq_member (tst = symbol::comma_dot, obj))
  963. {
  964. char errmsg[] = "read: the syntax `( ... . ,@form) is invalid";
  965. if (tst == symbol::comma_dot)
  966. errmsg[27] = '.';
  967. return (this->interp->raise ("parse-error", errmsg));
  968. }
  969. }
  970. else if (this->unquoted &&
  971. !(array_p (obj) || table_p (obj) || tuple_p (obj)))
  972. return (this->interp->raise ("parse-error",
  973. "read: unquote outside sequence"));
  974. KP_VTRY (alloc_cons (this->interp, 2));
  975. xcar(this->interp->alval) = symbol::backquote;
  976. xcadr(this->interp->alval) = obj;
  977. if (lbl != UNBOUND)
  978. *this->putlbl(lbl) = this->interp->alval;
  979. this->unquoted = prev;
  980. --this->bq_level;
  981. kp_return (this->interp->alval);
  982. }
  983. static const object BQ_NCONCABLE = fixint (0) | EXTRA_BIT;
  984. static result<object>
  985. bq_list (interpreter *interp, object form1)
  986. {
  987. return (KP_CALL (interp, list_fct, intern (interp, "list", 4), form1));
  988. }
  989. static result<object>
  990. bq_transform (interpreter *interp, object form)
  991. {
  992. if (!cons_p (form))
  993. {
  994. valref tmp = KP_TRY (expand_bq (interp, form));
  995. return (bq_list (interp, *tmp));
  996. }
  997. valref tmp (interp, xcar (form));
  998. if (*tmp == symbol::comma)
  999. {
  1000. KP_VTRY (bq_list (interp, *tmp = xcadr (form)));
  1001. return (interp->retval);
  1002. }
  1003. else if (*tmp == symbol::comma_at)
  1004. kp_return (xcadr (form));
  1005. else if (*tmp == symbol::comma_dot)
  1006. {
  1007. KP_VTRY (KP_CALL (interp, list_fct, BQ_NCONCABLE, xcadr (form)));
  1008. return (interp->retval);
  1009. }
  1010. else if (*tmp == symbol::backquote)
  1011. {
  1012. *tmp = KP_TRY (KP_CALL (interp, list_fct, symbol::backquote,
  1013. expand_bq (interp, xcadr (form))));
  1014. KP_VTRY (bq_list (interp, *tmp));
  1015. return (interp->retval);
  1016. }
  1017. else
  1018. {
  1019. *tmp = KP_TRY (expand_bq (interp, form));
  1020. KP_VTRY (bq_list (interp, *tmp));
  1021. return (interp->retval);
  1022. }
  1023. }
  1024. static result<object>
  1025. bq_expand_list (interpreter *interp, object forms)
  1026. {
  1027. valref ret (interp, NIL), tmp (interp, forms), tail (interp);
  1028. while (*tmp != NIL)
  1029. {
  1030. KP_VTRY (bq_transform (interp, xcar (*tmp)));
  1031. *ret = KP_TRY (cons::make (interp, interp->retval, *ret));
  1032. *tail = xcdr (*tmp);
  1033. if (*tail == NIL)
  1034. break;
  1035. else if (!xcons_p (*tail))
  1036. {
  1037. object tx = KP_TRY (KP_CALL (interp, list_fct,
  1038. symbol::backquote, *tail));
  1039. *ret = KP_TRY (cons::make (interp, tx, *ret));
  1040. break;
  1041. }
  1042. else if (xcar (*tail) == symbol::comma)
  1043. {
  1044. *ret = KP_TRY (cons::make (interp, xcadr (*tail), *ret));
  1045. break;
  1046. }
  1047. else if (xcar (*tail) == symbol::comma_at ||
  1048. xcar (*tail) == symbol::comma_dot)
  1049. return (bq_nonlist_splice_err (interp,
  1050. xcar (*tail) == symbol::comma_dot));
  1051. else
  1052. *tmp = *tail;
  1053. }
  1054. kp_return (*ret);
  1055. }
  1056. static inline bool
  1057. bq_splicing_p (interpreter *interp, object form)
  1058. {
  1059. valref tmp (interp, form);
  1060. while (true)
  1061. {
  1062. if (!xcons_p (*tmp))
  1063. return (false);
  1064. else if (xcar (*tmp) == symbol::comma)
  1065. *tmp = xcadr (*tmp);
  1066. else
  1067. break;
  1068. }
  1069. *tmp = xcar (*tmp);
  1070. return (*tmp == symbol::comma_at || *tmp == symbol::comma_dot);
  1071. }
  1072. static inline result<object>
  1073. bq_non_splicing (interpreter *interp, object form)
  1074. {
  1075. if (!bq_splicing_p (interp, form))
  1076. kp_return (form);
  1077. return (KP_CALL (interp, list_fct, intern (interp, "concat", 6), form));
  1078. }
  1079. static inline bool
  1080. bq_cons_test (interpreter *interp, object form)
  1081. {
  1082. return (xcons_p (form) && xcar (form) == symbol::quote &&
  1083. xcons_p (xcdr (form)) && xcddr (form) == NIL &&
  1084. !bq_splicing_p (interp, xcadr (form)));
  1085. }
  1086. static result<object>
  1087. bq_cons (interpreter *interp, object f1, object f2)
  1088. {
  1089. valref op = KP_TRY (intern (interp,
  1090. bq_splicing_p (interp, f1) ? "list*" : "cons"));
  1091. valref t2 (interp, f2), t1 (interp, f1);
  1092. if (atom_p (*t2))
  1093. return (KP_CALL (interp, list_fct, *op, *t1, *t2));
  1094. object tmp = KP_TRY (intern (interp, "list", 4));
  1095. if (xcar (*t2) == tmp)
  1096. return (KP_CALL (interp, list_star, xcar (*t2), *t1, xcdr (*t2)));
  1097. else if (bq_cons_test (interp, *t2) && bq_cons_test (interp, *t1))
  1098. return (KP_CALL (interp, list_fct, symbol::quote,
  1099. cons::make (interp, xcadr (*t1), xcadr (*t2))));
  1100. else
  1101. return (KP_CALL (interp, list_fct, *op, *t1, *t2));
  1102. }
  1103. static result<object>
  1104. bq_append (interpreter *interp, object f1, object f2)
  1105. {
  1106. valref t1 (interp, f1), t2 (interp, f2), aux (interp, NIL);
  1107. if (*t1 == NIL)
  1108. kp_return (*t2);
  1109. else if (*t2 == NIL)
  1110. kp_return (*t1);
  1111. object tmp = KP_TRY (intern (interp, "list", 4));
  1112. if (xcons_p (*t1) && xcar (*t1) == tmp)
  1113. {
  1114. tmp = KP_TRY (last_L (interp, *t1));
  1115. if (xcdr (tmp) == NIL)
  1116. {
  1117. *t2 = KP_TRY (bq_non_splicing (interp, *t2));
  1118. if (xcdr (*t1) == NIL)
  1119. kp_return (*t2);
  1120. else if (xcddr (*t1) == NIL)
  1121. {
  1122. *t2 = KP_TRY (bq_cons (interp, *t1 = xcadr (*t1), *t2));
  1123. kp_return (*t2);
  1124. }
  1125. else
  1126. {
  1127. *t1 = xcdr (*t1), *t2 = KP_TRY (cons::make (interp, *t2, NIL));
  1128. *t1 = KP_TRY (add_LL (interp, *t1, *t2));
  1129. *t2 = KP_TRY (intern (interp, "list*", 5));
  1130. return (cons::make (interp, *t2, *t1));
  1131. }
  1132. }
  1133. }
  1134. if (bq_cons_test (interp, *t1) && xcons_p (*aux = xcadr (*t1)))
  1135. {
  1136. tmp = KP_TRY (last_L (interp, *aux));
  1137. if (xcdr (tmp) == NIL && xcar (*aux) != symbol::comma)
  1138. {
  1139. *t2 = KP_TRY (bq_non_splicing (interp, *t2));
  1140. valref lst = KP_TRY (reverse_L (interp, *aux));
  1141. for (*aux = *t2; *lst != NIL; *lst = xcdr (*lst))
  1142. {
  1143. *t1 = KP_TRY (KP_CALL (interp, list_fct,
  1144. symbol::quote, xcar (*lst)));
  1145. *aux = KP_TRY (bq_cons (interp, *t1, *aux));
  1146. }
  1147. kp_return (*aux);
  1148. }
  1149. }
  1150. *aux = KP_TRY (intern (interp, "concat", 6));
  1151. if (xcons_p (*t2) && xcar (*t2) == *aux)
  1152. return (KP_CALL (interp, list_star, *aux, *t1, xcdr (*t2)));
  1153. else
  1154. return (KP_CALL (interp, list_fct, intern (interp, "concat", 6), *t1, *t2));
  1155. }
  1156. static result<object>
  1157. bq_nconc (interpreter *interp, object f1, object f2)
  1158. {
  1159. valref t2 (interp, f2);
  1160. if (f1 == NIL)
  1161. kp_return (f2);
  1162. else if (f2 == NIL)
  1163. kp_return (f1);
  1164. valref lst = KP_TRY (intern (interp, "nconcat", 7));
  1165. auto fn = list_fct;
  1166. if (xcons_p (*t2) && xcar (*t2) == *lst)
  1167. *t2 = xcdr (*t2), fn = list_star;
  1168. return (KP_CALL (interp, fn, *lst, f1, *t2));
  1169. }
  1170. static result<object>
  1171. bq_append_multi (interpreter *interp, object forms)
  1172. {
  1173. if (forms == NIL)
  1174. kp_return (forms);
  1175. bool nc = false;
  1176. valref tf (interp, forms), res (interp, NIL),
  1177. f1 (interp, xcar (*tf)), tmp (interp, NIL);
  1178. if (xcons_p (*f1) && xcar (*f1) == BQ_NCONCABLE)
  1179. *res = xcadr (*tf), nc = true;
  1180. else
  1181. *res = *f1;
  1182. for (*tf = xcdr (*tf); *tf != NIL; )
  1183. {
  1184. *f1 = xcar (*tf);
  1185. if (xcons_p (*f1) && xcar (*f1) == BQ_NCONCABLE)
  1186. {
  1187. *f1 = xcadr (*f1);
  1188. if (!nc && bq_splicing_p (interp, *res))
  1189. { *tmp = KP_TRY (KP_CALL (interp, list_fct,
  1190. intern (interp, "concat", 6), *res)); }
  1191. else
  1192. *tmp = *res;
  1193. *res = KP_TRY (bq_nconc (interp, *f1, *tmp));
  1194. }
  1195. else
  1196. {
  1197. if (nc && bq_splicing_p (interp, *res))
  1198. { *tmp = KP_TRY (KP_CALL (interp, list_fct,
  1199. intern (interp, "nconcat", 7), *res)); }
  1200. else
  1201. *tmp = *res;
  1202. *res = KP_TRY (bq_append (interp, *f1, *tmp));
  1203. }
  1204. nc = false;
  1205. *tf = xcdr (*tf);
  1206. }
  1207. return (bq_non_splicing (interp, *res));
  1208. }
  1209. static result<object>
  1210. seq_to_cons (interpreter *interp, object seq)
  1211. {
  1212. if (array_p (seq))
  1213. {
  1214. const array *ap = as_array (seq);
  1215. if (ap->len == 0)
  1216. kp_return (NIL);
  1217. KP_VTRY (alloc_cons (interp, ap->len, ap->data, nullptr));
  1218. kp_return (interp->alval);
  1219. }
  1220. else if (table_p (seq))
  1221. {
  1222. valref tmp (interp, NIL);
  1223. for (table::iterator it (interp, seq); it.valid (); ++it)
  1224. { *tmp = KP_TRY (KP_CALL (interp, list_star, it.val (),
  1225. it.key (), *tmp)); }
  1226. return (nreverse_L (interp, *tmp));
  1227. }
  1228. else if (tuple_p (seq))
  1229. {
  1230. valref tmp (interp, NIL);
  1231. for (tuple::iterator it (interp, seq); it.valid (); ++it)
  1232. { *tmp = KP_TRY (cons::make (interp, *it, *tmp)); }
  1233. return (nreverse_L (interp, *tmp));
  1234. }
  1235. kp_return (UNBOUND);
  1236. }
  1237. result<object> expand_bq (interpreter *interp, object form)
  1238. {
  1239. if (form == NIL)
  1240. kp_return (NIL);
  1241. else if (xcons_p (form))
  1242. {
  1243. object tmp = xcar (form);
  1244. if (tmp == symbol::comma)
  1245. kp_return (xcadr (form));
  1246. else if (tmp == symbol::comma_at || tmp == symbol::comma_dot)
  1247. return (bq_nonlist_splice_err (interp, tmp == symbol::comma_dot));
  1248. else if (tmp == symbol::backquote)
  1249. return (KP_CALL (interp, list_fct, symbol::backquote,
  1250. expand_bq (interp, xcadr (form))));
  1251. else
  1252. {
  1253. valref exp = KP_TRY (bq_expand_list (interp, form));
  1254. return (bq_append_multi (interp, *exp));
  1255. }
  1256. }
  1257. else
  1258. {
  1259. valref tmp = KP_TRY (seq_to_cons (interp, form));
  1260. if (*tmp == UNBOUND)
  1261. {
  1262. if (!nksymbol_p (form) && !cons_p (form))
  1263. kp_return (form);
  1264. return (KP_CALL (interp, list_fct, symbol::quote, form));
  1265. }
  1266. *tmp = KP_TRY (expand_bq (interp, *tmp));
  1267. valref app = KP_TRY (intern (interp, "apply", 5));
  1268. if (array_p (form))
  1269. return (KP_CALL (interp, list_fct, *app,
  1270. intern (interp, "array", 5), *tmp));
  1271. else if (table_p (form))
  1272. return (KP_CALL (interp, list_fct, *app,
  1273. intern (interp, "table", 5), NIL, NIL, *tmp));
  1274. else
  1275. return (KP_CALL (interp, list_fct, *app,
  1276. intern (interp, "tuple", 5), NIL, *tmp));
  1277. }
  1278. }
  1279. result<object> reader::read_sexpr (object lbl)
  1280. {
  1281. uint32_t tok = KP_TRY (this->peek ());
  1282. auto ip = this->interp;
  1283. object obj;
  1284. this->take ();
  1285. switch (tok)
  1286. {
  1287. case TOK_NONE:
  1288. kp_return (EOS);
  1289. case TOK_CLOSE:
  1290. return (ip->raise ("parse-error", "read: unexpected ')'"));
  1291. case TOK_CLOSEB:
  1292. return (ip->raise ("parse-error", "read: unexpected ']'"));
  1293. case TOK_CLOSEBRACE:
  1294. return (ip->raise ("parse-error", "read: unexpected '}'"));
  1295. case TOK_DOT:
  1296. return (ip->raise ("parse-error", "read: unexpected '.'"));
  1297. case TOK_SYM:
  1298. case TOK_NUM:
  1299. return (ip->retval);
  1300. case TOK_QUOTE:
  1301. obj = KP_TRY (this->read_sexpr (UNBOUND));
  1302. KP_VTRY (alloc_cons (ip, 2));
  1303. xcar(ip->alval) = symbol::quote;
  1304. xcadr(ip->alval) = obj;
  1305. if (lbl != UNBOUND)
  1306. *this->putlbl(lbl) = ip->alval;
  1307. kp_return (ip->alval);
  1308. case TOK_BQ:
  1309. return (this->read_bq (lbl));
  1310. case TOK_COMMA:
  1311. return (this->read_comma (lbl));
  1312. case TOK_OPEN:
  1313. return (this->read_list (lbl));
  1314. case TOK_DQUOTE:
  1315. return (this->read_str ());
  1316. case TOK_OPENB:
  1317. return (this->read_array (lbl));
  1318. case TOK_OPENBRACE:
  1319. return (this->read_table (lbl));
  1320. case TOK_SHARPOPEN:
  1321. return (this->read_tuple (lbl));
  1322. case TOK_SHARPDQUOT:
  1323. return (this->read_bvector ());
  1324. case TOK_CHAR:
  1325. return (this->read_char ());
  1326. case TOK_SHARPQUOTE:
  1327. {
  1328. obj = KP_TRY (this->read_sexpr (UNBOUND));
  1329. if (!nksymbol_p (obj) && !cons_p (obj))
  1330. return (ip->raise ("parse-error",
  1331. "read: #' must be used with a symbol or list"));
  1332. valref whole = KP_TRY (alloc_cons (ip, 3));
  1333. xcar(*whole) = KP_TRY (intern (ip, "fct", 3));
  1334. // Set arglist.
  1335. xcadr(*whole) = KP_TRY (alloc_cons (ip));
  1336. xcar(xcadr (*whole)) = KP_TRY (gensym (ip, 0, 0));
  1337. // Set body.
  1338. object body = xcar(xcddr (*whole)) = KP_TRY (alloc_cons (ip, 3));
  1339. xcar(body) = KP_TRY (intern (ip, "apply", 5));
  1340. xcadr(body) = obj;
  1341. xcar(xcddr (body)) = xcar (xcadr (*whole));
  1342. kp_return (*whole);
  1343. }
  1344. case TOK_SHARPDOT:
  1345. {
  1346. object obj = KP_TRY (this->read_sexpr (UNBOUND));
  1347. return (eval (ip, obj));
  1348. }
  1349. case TOK_LABEL:
  1350. if (this->getlbl (ip->retval) != UNBOUND)
  1351. return (ip->raise ("parse-error",
  1352. KP_SPRINTF (ip, "read: label %Q redefined",
  1353. ip->retval)));
  1354. obj = ip->retval;
  1355. KP_TRY (this->read_sexpr (UNBOUND));
  1356. *this->putlbl(obj) = KP_TRY (this->read_sexpr (UNBOUND));
  1357. return (ip->retval);
  1358. case TOK_BACKREF:
  1359. obj = ip->retval;
  1360. if ((ip->retval = this->getlbl (obj)) == UNBOUND)
  1361. return (ip->raise ("parse-error",
  1362. KP_SPRINTF (ip, "read: undefined label %Q", obj)));
  1363. return (ip->retval);
  1364. }
  1365. return (ip->retval);
  1366. }
  1367. result<object> reader::read_sexpr ()
  1368. {
  1369. auto ret = this->read_sexpr (UNBOUND);
  1370. if (ret.error_p ())
  1371. {
  1372. this->src->discard ();
  1373. this->take ();
  1374. }
  1375. return (ret);
  1376. }
  1377. reader::~reader ()
  1378. {
  1379. if (this->pairs.data != this->stpairs)
  1380. xfree (this->pairs.data);
  1381. if (this->bufp != this->stbuf)
  1382. xfree (this->bufp);
  1383. }
  1384. // String interpolation.
  1385. static result<int64_t>
  1386. read_fail (interpreter *, stream&, void *, uint64_t)
  1387. {
  1388. return (0);
  1389. }
  1390. static result<object>
  1391. read_from_cstr (interpreter *interp, const void *s, int len, const char **endp)
  1392. {
  1393. stream instrm;
  1394. bvector bv;
  1395. bv.vo_type = typecode::BVECTOR;
  1396. bv.nbytes = len;
  1397. instrm.rdbuf.init ((char *)s, len);
  1398. instrm.cookie = 0, instrm.ilock = UNBOUND;
  1399. instrm.bvec = bv.as_obj ();
  1400. instrm.pos = fixint (0);
  1401. instrm.vo_full = 0;
  1402. instrm.vo_type = typecode::STREAM;
  1403. stream::xops ops;
  1404. ops.read = read_fail;
  1405. instrm.ops = &ops;
  1406. instrm.io_flags = STRM_UTF8 | STRM_READ | STRM_NOLOCK;
  1407. reader rd (interp, instrm.as_obj ());
  1408. object ret = KP_TRY (rd.read_sexpr (UNBOUND));
  1409. if (ret != EOS)
  1410. {
  1411. if (instrm.rdbuf.left () == 0)
  1412. *endp = nullptr;
  1413. else if (isspace (*instrm.rdbuf.curr))
  1414. {
  1415. schar ch;
  1416. KP_VTRY (rd.nextc (ch));
  1417. instrm.ungetuc (ch.buf, ch.len);
  1418. *endp = instrm.rdbuf.curr;
  1419. }
  1420. else
  1421. *endp = instrm.rdbuf.curr;
  1422. }
  1423. return (ret);
  1424. }
  1425. static inline const char*
  1426. xmemchr (const void *p, int ch, size_t len)
  1427. {
  1428. return ((const char *)memchr (p, ch, len));
  1429. }
  1430. static int
  1431. sanitize_fmt (const char *p1, const char *p2)
  1432. {
  1433. chmask mask ("0123456789.$'");
  1434. for (; p1 != p2; ++p1)
  1435. if (!mask.tst (*p1))
  1436. return (*p1);
  1437. return (-1);
  1438. }
  1439. result<object> expand_str (interpreter *interp, object str)
  1440. {
  1441. string *sp = as_str (str);
  1442. auto start = (const char *)sp->data;
  1443. int nb = sp->nbytes;
  1444. auto ptr = xmemchr (start, '$', nb);
  1445. if (!ptr)
  1446. kp_return (str);
  1447. stream *ns = KP_TRY (strstream (interp, deref (alloc_str (interp, 0)),
  1448. STRM_WRITE | STRM_NOLOCK));
  1449. KP_VTRY (ns->write (interp, start, ptr - start));
  1450. valref outs (interp, ns->as_obj ()), args (interp, NIL), elem (interp);
  1451. while (true)
  1452. {
  1453. if (ptr[1] == '$')
  1454. {
  1455. KP_VTRY (ns->putb (interp, '$'));
  1456. const char *tp = xmemchr (ptr += 2, '$', nb -= 2);
  1457. if (!tp)
  1458. {
  1459. KP_VTRY (ns->write (interp, ptr, sp->nbytes - (ptr - start)));
  1460. break;
  1461. }
  1462. KP_VTRY (ns->write (interp, ptr, tp - ptr));
  1463. nb -= tp - ptr, ptr = tp;
  1464. continue;
  1465. }
  1466. const char *p1 = xmemchr (ptr + 1, '{', nb - (ptr + 1 - start));
  1467. if (!p1)
  1468. return (interp->raise ("arg-error", "invalid format string "
  1469. "(expected '{' after '$')"));
  1470. nb = sp->nbytes - (int)(p1 - start);
  1471. const char *p2 = nullptr;
  1472. *elem = KP_TRY (read_from_cstr (interp, p1 + 1, nb - 1, &p2));
  1473. if (!p2 || *p2 != '}')
  1474. return (interp->raise ("arg-error", "invalid format string "
  1475. "(unbalanced '{}' specifiers)"));
  1476. else if (*elem == EOS)
  1477. return (interp->raise ("arg-error", "invalid format string "
  1478. "(incomplete argument inside '${}')"));
  1479. *args = KP_TRY (cons::make (interp, *elem, *args));
  1480. {
  1481. int ch = sanitize_fmt (ptr + 1, p1);
  1482. if (ch >= 0)
  1483. {
  1484. char buf[100];
  1485. sprintf (buf, "invalid format specifier: got %c", (char)ch);
  1486. return (interp->raise ("arg-error", buf));
  1487. }
  1488. }
  1489. KP_VTRY (ns->write (interp, ptr, p1 - ptr - 1),
  1490. ns->write (interp, "%Q", 2));
  1491. ptr = p2 + 1;
  1492. nb = sp->nbytes - (ptr - start);
  1493. ptr = xmemchr (ptr, '$', nb);
  1494. if (!ptr)
  1495. {
  1496. KP_VTRY (ns->write (interp, p2 + 1, nb));
  1497. break;
  1498. }
  1499. KP_VTRY (ns->write (interp, p2 + 1, ptr - p2 - 1));
  1500. }
  1501. if (*args == NIL)
  1502. // Simple string.
  1503. return (sstream_get (interp, ns));
  1504. *args = KP_TRY (nreverse_L (interp, *args));
  1505. // The format string must be quoted so that it's not re-evaluated.
  1506. *elem = KP_TRY (sstream_get (interp, ns));
  1507. *elem = KP_TRY (KP_CALL (interp, list_fct, symbol::quote, *elem));
  1508. *args = KP_TRY (cons::make (interp, *elem, *args));
  1509. *elem = KP_TRY (intern (interp, "%fmt-str"));
  1510. *args = KP_TRY (cons::make (interp, *elem, *args));
  1511. kp_return (*args);
  1512. }
  1513. static result<object>
  1514. backquote_fct (interpreter *interp, object *argv, int)
  1515. {
  1516. return (expand_bq (interp, *argv));
  1517. }
  1518. // (De)serialization definitions.
  1519. pack_cache::pack_cache (interpreter *interp) : ref (interp)
  1520. {
  1521. for (size_t i = 0; i < KP_NELEM (this->st_tab); ++i)
  1522. this->st_tab[i] = UNBOUND;
  1523. this->l_obj.data = this->st_tab;
  1524. this->l_obj.len = (uint32_t)KP_NELEM (this->st_tab);
  1525. this->n_elem = this->n_old = 0;
  1526. this->evict = true;
  1527. *this->ref = this->l_obj.as_obj ();
  1528. }
  1529. static uint32_t
  1530. id_hash (interpreter *interp, object obj)
  1531. {
  1532. int itp = itype (obj);
  1533. switch (itp)
  1534. {
  1535. case typecode::INT:
  1536. case typecode::BIGINT:
  1537. case typecode::FLOAT:
  1538. case typecode::BIGFLOAT:
  1539. case typecode::CHAR:
  1540. return (deref (xhash (interp, obj)));
  1541. default:
  1542. if (itp != typecode::CONS && as_varobj(obj)->flagged_p (FLAGS_CONST))
  1543. return (deref (xhash (interp, obj)));
  1544. return (hash_addr (obj));
  1545. }
  1546. }
  1547. static inline bool
  1548. id_equal (interpreter *interp, object x, object y)
  1549. {
  1550. int t1 = itype (x), t2 = itype (y);
  1551. if (t1 != t2)
  1552. return (false);
  1553. switch (t1)
  1554. {
  1555. case typecode::INT:
  1556. case typecode::BIGINT:
  1557. case typecode::FLOAT:
  1558. case typecode::BIGFLOAT:
  1559. case typecode::CHAR:
  1560. return (deref (equal (interp, x, y)));
  1561. default:
  1562. if (t1 != typecode::CONS &&
  1563. as_varobj(x)->flagged_p (FLAGS_CONST) &&
  1564. as_varobj(y)->flagged_p (FLAGS_CONST))
  1565. return (deref (equal (interp, x, y)));
  1566. return (x == y);
  1567. }
  1568. }
  1569. uint32_t pack_cache::size () const
  1570. {
  1571. return (len_a (*this->ref) / 2);
  1572. }
  1573. object* pack_cache::data ()
  1574. {
  1575. return (as_array(*this->ref)->data);
  1576. }
  1577. static object*
  1578. pcache_getptr (interpreter *interp, pack_cache& cache,
  1579. object key, object mask)
  1580. {
  1581. uint32_t nprobe = 1, idx = id_hash (interp, key) & (cache.size () - 1);
  1582. for (mask = ~mask ; ; )
  1583. {
  1584. object *p = cache.data () + idx * 2;
  1585. if ((*p & mask) == UNBOUND || id_equal (interp, *p & ~EXTRA_BIT, key))
  1586. return (p);
  1587. idx = (idx + nprobe++) & (cache.size () - 1);
  1588. }
  1589. }
  1590. object pack_cache::get (interpreter *interp, object key)
  1591. {
  1592. object *ptr = pcache_getptr (interp, *this, key, 0);
  1593. if (*ptr == UNBOUND)
  1594. return (*ptr);
  1595. else if ((*ptr & EXTRA_BIT) == 0)
  1596. {
  1597. *ptr |= EXTRA_BIT;
  1598. ++this->n_old;
  1599. }
  1600. return (ptr[1]);
  1601. }
  1602. static void
  1603. pcache_cleanup (pack_cache& cache)
  1604. {
  1605. object *data = cache.data ();
  1606. for (uint32_t i = 0; i < cache.l_obj.len; i += 2)
  1607. if (data[i] != UNBOUND && (data[i] & EXTRA_BIT) == 0)
  1608. {
  1609. data[i] = data[i + 1] = UNBOUND | EXTRA_BIT;
  1610. --cache.n_elem;
  1611. }
  1612. }
  1613. static result<void>
  1614. pcache_resize (interpreter *interp, pack_cache& cache)
  1615. {
  1616. uint32_t nsize = cache.size () * 2;
  1617. object *data = cache.data ();
  1618. valref nv = KP_TRY (alloc_array (interp, nsize * 2));
  1619. for (uint32_t i = 0; i < nsize; i += 2)
  1620. {
  1621. object obj = data[i];
  1622. if ((obj & ~EXTRA_BIT) == UNBOUND)
  1623. continue;
  1624. uint32_t nprobe = 1, idx = id_hash (interp, obj) & (nsize - 1);
  1625. while (true)
  1626. {
  1627. if (xaref (*nv, idx * 2) == UNBOUND)
  1628. {
  1629. xaref(*nv, idx * 2 + 0) = obj;
  1630. xaref(*nv, idx * 2 + 1) = data[i + 1];
  1631. break;
  1632. }
  1633. idx = (idx + nprobe++) & (nsize - 1);
  1634. }
  1635. }
  1636. *cache.ref = *nv;
  1637. return (0);
  1638. }
  1639. static const uint32_t CLEANUP_THRESHOLD = 10 * 1024;
  1640. result<void> pack_cache::put (interpreter *interp, object key, object val)
  1641. {
  1642. object *ptr = pcache_getptr (interp, *this, key, EXTRA_BIT);
  1643. if (*ptr != UNBOUND)
  1644. return (0);
  1645. ptr[0] = key, ptr[1] = val;
  1646. if (++this->n_elem * 100 <= this->size () * 75)
  1647. ;
  1648. else if (this->evict && this->n_elem > CLEANUP_THRESHOLD)
  1649. pcache_cleanup (*this);
  1650. else
  1651. return (pcache_resize (interp, *this));
  1652. return (0);
  1653. }
  1654. pack_info::pack_info (interpreter *interp) :
  1655. map (interp), offset (interp), errmsg (nullptr)
  1656. {
  1657. }
  1658. result<void> pack_info::init (interpreter *interp, bool use_cache)
  1659. {
  1660. if (use_cache)
  1661. {
  1662. this->cache = new (this->pcache.ptr ()) pack_cache (interp);
  1663. object base = deref (alloc_bvector (interp, 0));
  1664. this->bstream = KP_TRY (bvstream (interp, base, STRM_RDWR | STRM_NOLOCK));
  1665. }
  1666. else
  1667. {
  1668. this->cache = nullptr;
  1669. *this->map = KP_TRY (KP_CALL (interp, table_fct, NIL, NIL));
  1670. }
  1671. return (0);
  1672. }
  1673. result<void> pack_info::add_mapping (interpreter *interp, object key, object val)
  1674. {
  1675. if (this->cache)
  1676. return (this->cache->put (interp, key, val));
  1677. valref tmp (interp, val);
  1678. object ret = KP_TRY (table_get (interp, *this->map, key, UNBOUND, false));
  1679. if (ret == UNBOUND)
  1680. KP_VTRY (table_put (interp, *this->map, key, *tmp, false));
  1681. return (0);
  1682. }
  1683. object pack_info::get (interpreter *interp, object obj)
  1684. {
  1685. return (this->cache ? this->cache->get (interp, obj) :
  1686. deref (table_get (interp, *this->map, obj,
  1687. UNBOUND, false)));
  1688. }
  1689. void pack_info::touch (interpreter *interp, int offset)
  1690. {
  1691. if (offset < 0)
  1692. return;
  1693. deref (this->bstream->flush (interp));
  1694. as_bvector(this->bstream->extra)->data[offset] |= 0x80;
  1695. }
  1696. result<int64_t> xpack (interpreter *interp, stream *strm,
  1697. object obj, object *map, size_t nmap)
  1698. {
  1699. pack_info info { interp };
  1700. KP_VTRY (info.init (interp, true));
  1701. for (size_t i = 0; i < nmap; i += 2)
  1702. KP_VTRY (info.add_mapping (interp, map[i] | EXTRA_BIT, map[i + 1]));
  1703. int64_t rv = KP_TRY (xpack (interp, info.bstream, obj, info));
  1704. if (rv < 0 || info.bstream->err_p ())
  1705. return (-1);
  1706. uint32_t nsz;
  1707. unsigned char *data = bvstream_data (info.bstream, nsz);
  1708. auto ret = strm->write (interp, data, nsz);
  1709. deref (info.bstream->close (interp));
  1710. return (ret);
  1711. }
  1712. result<void> print_backtrace (interpreter *interp, uint32_t frame,
  1713. stream *strmp, io_info& info)
  1714. {
  1715. KP_VTRY (strmp->write (interp, "Backtrace:\n", 11));
  1716. object tr = KP_TRY (interp->stacktrace (frame));
  1717. if (tr == NIL)
  1718. {
  1719. KP_VTRY (strmp->write (interp, " #<top-level>\n\n", 16));
  1720. return (0);
  1721. }
  1722. uint32_t idx = 0;
  1723. info.flags |= io_info::FLG_SAFE;
  1724. for (cons::iterator it (interp, tr); it.valid (); ++it)
  1725. {
  1726. char sbuf[64];
  1727. object vec = *it;
  1728. uint32_t vl;
  1729. KP_VTRY (strmp->write (interp, sbuf, sprintf (sbuf, " %d: (", idx++)));
  1730. if (!array_p (vec) || (vl = len_a (vec)) == 0)
  1731. {
  1732. KP_VTRY (strmp->write (interp, "???" ")", 4));
  1733. continue;
  1734. }
  1735. object caller = xaref (vec, 0);
  1736. if (fct_p (caller))
  1737. {
  1738. object nm = fct_name (caller);
  1739. if (nm == NIL)
  1740. KP_VTRY (strmp->write (interp, "#:fct", 5));
  1741. else
  1742. KP_VTRY (xwrite (interp, strmp, nm, info));
  1743. }
  1744. else
  1745. KP_VTRY (strmp->write (interp, "???", 3));
  1746. for (uint32_t i = 1; i < vl; ++i)
  1747. {
  1748. KP_VTRY (strmp->putb (interp, ' '),
  1749. xwrite (interp, strmp, xaref (vec, i), info));
  1750. }
  1751. KP_VTRY (strmp->write (interp, ")\n", 2));
  1752. }
  1753. KP_VTRY (strmp->putb (interp, '\n'));
  1754. info.flags &= ~io_info::FLG_SAFE;
  1755. return (0);
  1756. }
  1757. void write_exc (interpreter *interp, stream *strm, object exc, io_info& info)
  1758. {
  1759. if (write_S(interp, strm, type_name (type (exc)), info).error_p () ||
  1760. strm->write(interp, ": ", 2).error_p () ||
  1761. xwrite(interp, strm, exc, info).error_p ())
  1762. {
  1763. static const char msg[] = "failed to write raised value";
  1764. deref (strm->write (interp, msg, sizeof (msg) - 1));
  1765. }
  1766. }
  1767. static int
  1768. do_init_io (interpreter *interp)
  1769. {
  1770. int ret = init_op::call_deps (interp, &init_symbols);
  1771. if (ret != init_op::result_ok)
  1772. return (ret);
  1773. static native_function backquote_macro;
  1774. auto *bp = ensure_mask (&backquote_macro);
  1775. bp->vo_full = function_base::native_flag;
  1776. bp->vo_type = typecode::FCT;
  1777. bp->fct = backquote_fct;
  1778. bp->min_argc = bp->max_argc = 1;
  1779. auto rs = intern (interp, "backquote");
  1780. if (rs.error_p ())
  1781. return (init_op::result_failed);
  1782. object sym = bp->name = deref (rs);
  1783. symval(sym) = bp->as_obj ();
  1784. as_symbol(sym)->set_flag (symbol::ctv_flag);
  1785. return (ret);
  1786. }
  1787. init_op init_io (do_init_io, "io");
  1788. KP_DECLS_END