bc: switch to SA_RESTART signal handling
[oweals/busybox.git] / miscutils / bc.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
4  * Copyright (c) 2018 Gavin D. Howard and contributors.
5  *
6  * ** Automatically generated from https://github.com/gavinhoward/bc **
7  * **        Do not edit unless you know what you are doing.         **
8  */
9 //config:config BC
10 //config:       bool "bc (45 kb; 49 kb when combined with dc)"
11 //config:       default y
12 //config:       help
13 //config:       bc is a command-line, arbitrary-precision calculator with a
14 //config:       Turing-complete language. See the GNU bc manual
15 //config:       (https://www.gnu.org/software/bc/manual/bc.html) and bc spec
16 //config:       (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
17 //config:       for details.
18 //config:
19 //config:       This bc has four differences to the GNU bc:
20 //config:
21 //config:         1) The period (.) can also be used as a shortcut for "last", as in
22 //config:            the BSD bc.
23 //config:         2) Arrays are copied before being passed as arguments to
24 //config:            functions. This behavior is required by the bc spec.
25 //config:         3) Arrays can be passed to the builtin "length" function to get
26 //config:            the number of elements currently in the array. The following
27 //config:            example prints "1":
28 //config:
29 //config:              a[0] = 0
30 //config:              length(a[])
31 //config:
32 //config:         4) The precedence of the boolean "not" operator (!) is equal to
33 //config:            that of the unary minus (-), or negation, operator. This still
34 //config:            allows POSIX-compliant scripts to work while somewhat
35 //config:            preserving expected behavior (versus C) and making parsing
36 //config:            easier.
37 //config:
38 //config:       Options:
39 //config:
40 //config:         -i  --interactive  force interactive mode
41 //config:         -l  --mathlib      use predefined math routines:
42 //config:
43 //config:                              s(expr)  =  sine of expr in radians
44 //config:                              c(expr)  =  cosine of expr in radians
45 //config:                              a(expr)  =  arctangent of expr, returning
46 //config:                                          radians
47 //config:                              l(expr)  =  natural log of expr
48 //config:                              e(expr)  =  raises e to the power of expr
49 //config:                              j(n, x)  =  Bessel function of integer order
50 //config:                                          n of x
51 //config:
52 //config:         -q  --quiet        don't print version and copyright.
53 //config:         -s  --standard     error if any non-POSIX extensions are used.
54 //config:         -w  --warn         warn if any non-POSIX extensions are used.
55 //config:         -v  --version      print version and copyright and exit.
56 //config:
57 //config:       Long options are only available if FEATURE_BC_LONG_OPTIONS is
58 //config:       enabled.
59 //config:
60 //config:config DC
61 //config:       bool "dc (38 kb; 49 kb when combined with bc)"
62 //config:       default y
63 //config:       help
64 //config:       dc is a reverse-polish notation command-line calculator which
65 //config:       supports unlimited precision arithmetic. See the FreeBSD man page
66 //config:       (https://www.unix.com/man-page/FreeBSD/1/dc/) and GNU dc manual
67 //config:       (https://www.gnu.org/software/bc/manual/dc-1.05/html_mono/dc.html)
68 //config:       for details.
69 //config:
70 //config:       This dc has a few differences from the two above:
71 //config:
72 //config:         1) When printing a byte stream (command "P"), this bc follows what
73 //config:            the FreeBSD dc does.
74 //config:         2) This dc implements the GNU extensions for divmod ("~") and
75 //config:            modular exponentiation ("|").
76 //config:         3) This dc implements all FreeBSD extensions, except for "J" and
77 //config:            "M".
78 //config:         4) Like the FreeBSD dc, this dc supports extended registers.
79 //config:            However, they are implemented differently. When it encounters
80 //config:            whitespace where a register should be, it skips the whitespace.
81 //config:            If the character following is not a lowercase letter, an error
82 //config:            is issued. Otherwise, the register name is parsed by the
83 //config:            following regex:
84 //config:
85 //config:              [a-z][a-z0-9_]*
86 //config:
87 //config:            This generally means that register names will be surrounded by
88 //config:            whitespace.
89 //config:
90 //config:            Examples:
91 //config:
92 //config:              l idx s temp L index S temp2 < do_thing
93 //config:
94 //config:            Also note that, like the FreeBSD dc, extended registers are not
95 //config:            allowed unless the "-x" option is given.
96 //config:
97 //config:config FEATURE_BC_SIGNALS
98 //config:       bool "Enable bc/dc signal handling"
99 //config:       default y
100 //config:       depends on BC || DC
101 //config:       help
102 //config:       Enable signal handling for bc and dc.
103 //config:
104 //config:config FEATURE_BC_LONG_OPTIONS
105 //config:       bool "Enable bc/dc long options"
106 //config:       default y
107 //config:       depends on BC || DC
108 //config:       help
109 //config:       Enable long options for bc and dc.
110
111 //applet:IF_BC(APPLET(bc, BB_DIR_USR_BIN, BB_SUID_DROP))
112 //applet:IF_DC(APPLET(dc, BB_DIR_USR_BIN, BB_SUID_DROP))
113
114 //kbuild:lib-$(CONFIG_BC) += bc.o
115 //kbuild:lib-$(CONFIG_DC) += bc.o
116
117 //See www.gnu.org/software/bc/manual/bc.html
118 //usage:#define bc_trivial_usage
119 //usage:       "[-sqli] FILE..."
120 //usage:
121 //usage:#define bc_full_usage "\n"
122 //usage:     "\nArbitrary precision calculator"
123 //usage:     "\n"
124 //usage:     "\n        -i      Interactive"
125 //usage:     "\n        -l      Load standard math library"
126 //usage:     "\n        -s      Be POSIX compatible"
127 //usage:     "\n        -q      Quiet"
128 //usage:     "\n        -w      Warn if extensions are used"
129 ///////:     "\n        -v      Version"
130 //usage:
131 //usage:#define bc_example_usage
132 //usage:       "3 + 4.129\n"
133 //usage:       "1903 - 2893\n"
134 //usage:       "-129 * 213.28935\n"
135 //usage:       "12 / -1932\n"
136 //usage:       "12 % 12\n"
137 //usage:       "34 ^ 189\n"
138 //usage:       "scale = 13\n"
139 //usage:       "ibase = 2\n"
140 //usage:       "obase = A\n"
141 //usage:
142 //usage:#define dc_trivial_usage
143 //usage:       "EXPRESSION..."
144 //usage:
145 //usage:#define dc_full_usage "\n\n"
146 //usage:       "Tiny RPN calculator. Operations:\n"
147 //usage:       "+, add, -, sub, *, mul, /, div, %, mod, ^, exp, ~, divmod, |, "
148 //usage:       "modular exponentiation,\n"
149 //usage:       "p - print top of the stack (without popping),\n"
150 //usage:       "f - print entire stack,\n"
151 //usage:       "k - pop the value and set the precision.\n"
152 //usage:       "i - pop the value and set input radix.\n"
153 //usage:       "o - pop the value and set output radix.\n"
154 //usage:       "Examples: 'dc 2 2 add p' -> 4, 'dc 8 8 mul 2 2 + / p' -> 16"
155 //usage:
156 //usage:#define dc_example_usage
157 //usage:       "$ dc 2 2 + p\n"
158 //usage:       "4\n"
159 //usage:       "$ dc 8 8 \\* 2 2 + / p\n"
160 //usage:       "16\n"
161 //usage:       "$ dc 0 1 and p\n"
162 //usage:       "0\n"
163 //usage:       "$ dc 0 1 or p\n"
164 //usage:       "1\n"
165 //usage:       "$ echo 72 9 div 8 mul p | dc\n"
166 //usage:       "64\n"
167
168 #include "libbb.h"
169
170 typedef enum BcStatus {
171         BC_STATUS_SUCCESS = 0,
172         BC_STATUS_FAILURE = 1,
173         BC_STATUS_PARSE_EMPTY_EXP = 2, // bc_parse_expr() uses this
174 } BcStatus;
175
176 #define BC_VEC_INVALID_IDX ((size_t) -1)
177 #define BC_VEC_START_CAP (1 << 5)
178
179 typedef void (*BcVecFree)(void *);
180
181 typedef struct BcVec {
182         char *v;
183         size_t len;
184         size_t cap;
185         size_t size;
186         BcVecFree dtor;
187 } BcVec;
188
189 #define bc_vec_pop(v) (bc_vec_npop((v), 1))
190 #define bc_vec_top(v) (bc_vec_item_rev((v), 0))
191
192 #define bc_map_init(v) (bc_vec_init((v), sizeof(BcId), bc_id_free))
193
194 typedef signed char BcDig;
195
196 typedef struct BcNum {
197         BcDig *restrict num;
198         size_t rdx;
199         size_t len;
200         size_t cap;
201         bool neg;
202 } BcNum;
203
204 #define BC_NUM_MIN_BASE ((unsigned long) 2)
205 #define BC_NUM_MAX_IBASE ((unsigned long) 16)
206 #define BC_NUM_DEF_SIZE (16)
207 #define BC_NUM_PRINT_WIDTH (69)
208
209 #define BC_NUM_KARATSUBA_LEN (32)
210
211 #define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg))
212 #define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1)
213 #define BC_NUM_INT(n) ((n)->len - (n)->rdx)
214 #define BC_NUM_AREQ(a, b) \
215         (BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1)
216 #define BC_NUM_MREQ(a, b, scale) \
217         (BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX((scale), (a)->rdx + (b)->rdx) + 1)
218
219 typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t);
220 typedef void (*BcNumDigitOp)(size_t, size_t, bool, size_t *, size_t);
221
222 static void bc_num_init(BcNum *n, size_t req);
223 static void bc_num_expand(BcNum *n, size_t req);
224 static void bc_num_copy(BcNum *d, BcNum *s);
225 static void bc_num_free(void *num);
226
227 static BcStatus bc_num_ulong(BcNum *n, unsigned long *result);
228 static void bc_num_ulong2num(BcNum *n, unsigned long val);
229
230 static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale);
231 static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale);
232 static BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale);
233 static BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale);
234 static BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale);
235 static BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale);
236 static BcStatus bc_num_sqrt(BcNum *a, BcNum *b, size_t scale);
237 static BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d,
238                               size_t scale);
239
240 typedef enum BcInst {
241
242 #if ENABLE_BC
243         BC_INST_INC_PRE,
244         BC_INST_DEC_PRE,
245         BC_INST_INC_POST,
246         BC_INST_DEC_POST,
247 #endif
248
249         BC_INST_NEG,
250
251         BC_INST_POWER,
252         BC_INST_MULTIPLY,
253         BC_INST_DIVIDE,
254         BC_INST_MODULUS,
255         BC_INST_PLUS,
256         BC_INST_MINUS,
257
258         BC_INST_REL_EQ,
259         BC_INST_REL_LE,
260         BC_INST_REL_GE,
261         BC_INST_REL_NE,
262         BC_INST_REL_LT,
263         BC_INST_REL_GT,
264
265         BC_INST_BOOL_NOT,
266         BC_INST_BOOL_OR,
267         BC_INST_BOOL_AND,
268
269 #if ENABLE_BC
270         BC_INST_ASSIGN_POWER,
271         BC_INST_ASSIGN_MULTIPLY,
272         BC_INST_ASSIGN_DIVIDE,
273         BC_INST_ASSIGN_MODULUS,
274         BC_INST_ASSIGN_PLUS,
275         BC_INST_ASSIGN_MINUS,
276 #endif
277         BC_INST_ASSIGN,
278
279         BC_INST_NUM,
280         BC_INST_VAR,
281         BC_INST_ARRAY_ELEM,
282         BC_INST_ARRAY,
283
284         BC_INST_SCALE_FUNC,
285         BC_INST_IBASE,
286         BC_INST_SCALE,
287         BC_INST_LAST,
288         BC_INST_LENGTH,
289         BC_INST_READ,
290         BC_INST_OBASE,
291         BC_INST_SQRT,
292
293         BC_INST_PRINT,
294         BC_INST_PRINT_POP,
295         BC_INST_STR,
296         BC_INST_PRINT_STR,
297
298 #if ENABLE_BC
299         BC_INST_JUMP,
300         BC_INST_JUMP_ZERO,
301
302         BC_INST_CALL,
303
304         BC_INST_RET,
305         BC_INST_RET0,
306
307         BC_INST_HALT,
308 #endif
309
310         BC_INST_POP,
311         BC_INST_POP_EXEC,
312
313 #if ENABLE_DC
314         BC_INST_MODEXP,
315         BC_INST_DIVMOD,
316
317         BC_INST_EXECUTE,
318         BC_INST_EXEC_COND,
319
320         BC_INST_ASCIIFY,
321         BC_INST_PRINT_STREAM,
322
323         BC_INST_PRINT_STACK,
324         BC_INST_CLEAR_STACK,
325         BC_INST_STACK_LEN,
326         BC_INST_DUPLICATE,
327         BC_INST_SWAP,
328
329         BC_INST_LOAD,
330         BC_INST_PUSH_VAR,
331         BC_INST_PUSH_TO_VAR,
332
333         BC_INST_QUIT,
334         BC_INST_NQUIT,
335
336         BC_INST_INVALID = -1,
337 #endif
338
339 } BcInst;
340
341 typedef struct BcId {
342         char *name;
343         size_t idx;
344 } BcId;
345
346 typedef struct BcFunc {
347         BcVec code;
348         BcVec labels;
349         size_t nparams;
350         BcVec autos;
351 } BcFunc;
352
353 typedef enum BcResultType {
354
355         BC_RESULT_TEMP,
356
357         BC_RESULT_VAR,
358         BC_RESULT_ARRAY_ELEM,
359         BC_RESULT_ARRAY,
360
361         BC_RESULT_STR,
362
363         BC_RESULT_IBASE,
364         BC_RESULT_SCALE,
365         BC_RESULT_LAST,
366
367         // These are between to calculate ibase, obase, and last from instructions.
368         BC_RESULT_CONSTANT,
369         BC_RESULT_ONE,
370
371         BC_RESULT_OBASE,
372
373 } BcResultType;
374
375 typedef union BcResultData {
376         BcNum n;
377         BcVec v;
378         BcId id;
379 } BcResultData;
380
381 typedef struct BcResult {
382         BcResultType t;
383         BcResultData d;
384 } BcResult;
385
386 typedef struct BcInstPtr {
387         size_t func;
388         size_t idx;
389         size_t len;
390 } BcInstPtr;
391
392 static void bc_array_expand(BcVec *a, size_t len);
393 static int bc_id_cmp(const void *e1, const void *e2);
394
395 // BC_LEX_NEG is not used in lexing; it is only for parsing.
396 typedef enum BcLexType {
397
398         BC_LEX_EOF,
399         BC_LEX_INVALID,
400
401         BC_LEX_OP_INC,
402         BC_LEX_OP_DEC,
403
404         BC_LEX_NEG,
405
406         BC_LEX_OP_POWER,
407         BC_LEX_OP_MULTIPLY,
408         BC_LEX_OP_DIVIDE,
409         BC_LEX_OP_MODULUS,
410         BC_LEX_OP_PLUS,
411         BC_LEX_OP_MINUS,
412
413         BC_LEX_OP_REL_EQ,
414         BC_LEX_OP_REL_LE,
415         BC_LEX_OP_REL_GE,
416         BC_LEX_OP_REL_NE,
417         BC_LEX_OP_REL_LT,
418         BC_LEX_OP_REL_GT,
419
420         BC_LEX_OP_BOOL_NOT,
421         BC_LEX_OP_BOOL_OR,
422         BC_LEX_OP_BOOL_AND,
423
424         BC_LEX_OP_ASSIGN_POWER,
425         BC_LEX_OP_ASSIGN_MULTIPLY,
426         BC_LEX_OP_ASSIGN_DIVIDE,
427         BC_LEX_OP_ASSIGN_MODULUS,
428         BC_LEX_OP_ASSIGN_PLUS,
429         BC_LEX_OP_ASSIGN_MINUS,
430         BC_LEX_OP_ASSIGN,
431
432         BC_LEX_NLINE,
433         BC_LEX_WHITESPACE,
434
435         BC_LEX_LPAREN,
436         BC_LEX_RPAREN,
437
438         BC_LEX_LBRACKET,
439         BC_LEX_COMMA,
440         BC_LEX_RBRACKET,
441
442         BC_LEX_LBRACE,
443         BC_LEX_SCOLON,
444         BC_LEX_RBRACE,
445
446         BC_LEX_STR,
447         BC_LEX_NAME,
448         BC_LEX_NUMBER,
449
450         BC_LEX_KEY_AUTO,
451         BC_LEX_KEY_BREAK,
452         BC_LEX_KEY_CONTINUE,
453         BC_LEX_KEY_DEFINE,
454         BC_LEX_KEY_ELSE,
455         BC_LEX_KEY_FOR,
456         BC_LEX_KEY_HALT,
457         BC_LEX_KEY_IBASE,
458         BC_LEX_KEY_IF,
459         BC_LEX_KEY_LAST,
460         BC_LEX_KEY_LENGTH,
461         BC_LEX_KEY_LIMITS,
462         BC_LEX_KEY_OBASE,
463         BC_LEX_KEY_PRINT,
464         BC_LEX_KEY_QUIT,
465         BC_LEX_KEY_READ,
466         BC_LEX_KEY_RETURN,
467         BC_LEX_KEY_SCALE,
468         BC_LEX_KEY_SQRT,
469         BC_LEX_KEY_WHILE,
470
471 #if ENABLE_DC
472         BC_LEX_EQ_NO_REG,
473         BC_LEX_OP_MODEXP,
474         BC_LEX_OP_DIVMOD,
475
476         BC_LEX_COLON,
477         BC_LEX_ELSE,
478         BC_LEX_EXECUTE,
479         BC_LEX_PRINT_STACK,
480         BC_LEX_CLEAR_STACK,
481         BC_LEX_STACK_LEVEL,
482         BC_LEX_DUPLICATE,
483         BC_LEX_SWAP,
484         BC_LEX_POP,
485
486         BC_LEX_ASCIIFY,
487         BC_LEX_PRINT_STREAM,
488
489         BC_LEX_STORE_IBASE,
490         BC_LEX_STORE_SCALE,
491         BC_LEX_LOAD,
492         BC_LEX_LOAD_POP,
493         BC_LEX_STORE_PUSH,
494         BC_LEX_STORE_OBASE,
495         BC_LEX_PRINT_POP,
496         BC_LEX_NQUIT,
497         BC_LEX_SCALE_FACTOR,
498 #endif
499
500 } BcLexType;
501
502 struct BcLex;
503 typedef BcStatus (*BcLexNext)(struct BcLex *);
504
505 typedef struct BcLex {
506
507         const char *buf;
508         size_t i;
509         size_t line;
510         const char *f;
511         size_t len;
512         bool newline;
513
514         struct {
515                 BcLexType t;
516                 BcLexType last;
517                 BcVec v;
518         } t;
519
520         BcLexNext next;
521
522 } BcLex;
523
524 #define BC_PARSE_STREND ((char) UCHAR_MAX)
525
526 #define bc_parse_push(p, i) (bc_vec_pushByte(&(p)->func->code, (char) (i)))
527 #define bc_parse_updateFunc(p, f) \
528         ((p)->func = bc_vec_item(&G.prog.fns, ((p)->fidx = (f))))
529
530 #define BC_PARSE_REL (1 << 0)
531 #define BC_PARSE_PRINT (1 << 1)
532 #define BC_PARSE_NOCALL (1 << 2)
533 #define BC_PARSE_NOREAD (1 << 3)
534 #define BC_PARSE_ARRAY (1 << 4)
535
536 #define BC_PARSE_TOP_FLAG_PTR(parse) ((uint8_t *) bc_vec_top(&(parse)->flags))
537 #define BC_PARSE_TOP_FLAG(parse) (*(BC_PARSE_TOP_FLAG_PTR(parse)))
538
539 #define BC_PARSE_FLAG_FUNC_INNER (1 << 0)
540 #define BC_PARSE_FUNC_INNER(parse) \
541         (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_FUNC_INNER)
542
543 #define BC_PARSE_FLAG_FUNC (1 << 1)
544 #define BC_PARSE_FUNC(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_FUNC)
545
546 #define BC_PARSE_FLAG_BODY (1 << 2)
547 #define BC_PARSE_BODY(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_BODY)
548
549 #define BC_PARSE_FLAG_LOOP (1 << 3)
550 #define BC_PARSE_LOOP(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_LOOP)
551
552 #define BC_PARSE_FLAG_LOOP_INNER (1 << 4)
553 #define BC_PARSE_LOOP_INNER(parse) \
554         (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_LOOP_INNER)
555
556 #define BC_PARSE_FLAG_IF (1 << 5)
557 #define BC_PARSE_IF(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_IF)
558
559 #define BC_PARSE_FLAG_ELSE (1 << 6)
560 #define BC_PARSE_ELSE(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_ELSE)
561
562 #define BC_PARSE_FLAG_IF_END (1 << 7)
563 #define BC_PARSE_IF_END(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_IF_END)
564
565 #define BC_PARSE_CAN_EXEC(parse)                                             \
566         (!(BC_PARSE_TOP_FLAG(parse) &                                            \
567            (BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_BODY | \
568             BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER | BC_PARSE_FLAG_IF |   \
569             BC_PARSE_FLAG_ELSE | BC_PARSE_FLAG_IF_END)))
570
571 typedef struct BcOp {
572         char prec;
573         bool left;
574 } BcOp;
575
576 typedef struct BcParseNext {
577         uint32_t len;
578         BcLexType tokens[4];
579 } BcParseNext;
580
581 #define BC_PARSE_NEXT_TOKENS(...) .tokens = { __VA_ARGS__ }
582 #define BC_PARSE_NEXT(a, ...)                         \
583         {                                                 \
584                 .len = (a), BC_PARSE_NEXT_TOKENS(__VA_ARGS__) \
585         }
586
587 struct BcParse;
588
589 struct BcProgram;
590
591 typedef BcStatus (*BcParseParse)(struct BcParse *);
592
593 typedef struct BcParse {
594
595         BcParseParse parse;
596
597         BcLex l;
598
599         BcVec flags;
600
601         BcVec exits;
602         BcVec conds;
603
604         BcVec ops;
605
606         BcFunc *func;
607         size_t fidx;
608
609         size_t nbraces;
610         bool auto_part;
611
612 } BcParse;
613
614 #if ENABLE_BC
615
616 typedef struct BcLexKeyword {
617         const char name[9];
618         const char len;
619         const bool posix;
620 } BcLexKeyword;
621
622 #define BC_LEX_KW_ENTRY(a, b, c)            \
623         {                                       \
624                 .name = a, .len = (b), .posix = (c) \
625         }
626
627 static BcStatus bc_lex_token(BcLex *l);
628
629 #define BC_PARSE_TOP_OP(p) (*((BcLexType *) bc_vec_top(&(p)->ops)))
630 #define BC_PARSE_LEAF(p, rparen)                                \
631         (((p) >= BC_INST_NUM && (p) <= BC_INST_SQRT) || (rparen) || \
632          (p) == BC_INST_INC_POST || (p) == BC_INST_DEC_POST)
633
634 // We can calculate the conversion between tokens and exprs by subtracting the
635 // position of the first operator in the lex enum and adding the position of the
636 // first in the expr enum. Note: This only works for binary operators.
637 #define BC_PARSE_TOKEN_INST(t) ((char) ((t) -BC_LEX_NEG + BC_INST_NEG))
638
639 static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next);
640
641 #endif // ENABLE_BC
642
643 #if ENABLE_DC
644
645 #define DC_PARSE_BUF_LEN ((int) (sizeof(uint32_t) * CHAR_BIT))
646
647 static BcStatus dc_lex_token(BcLex *l);
648
649 static BcStatus dc_parse_expr(BcParse *p, uint8_t flags);
650
651 #endif // ENABLE_DC
652
653 typedef struct BcProgram {
654
655         size_t len;
656         size_t scale;
657
658         BcNum ib;
659         size_t ib_t;
660         BcNum ob;
661         size_t ob_t;
662
663         BcNum hexb;
664
665 #if ENABLE_DC
666         BcNum strmb;
667 #endif
668
669         BcVec results;
670         BcVec stack;
671
672         BcVec fns;
673         BcVec fn_map;
674
675         BcVec vars;
676         BcVec var_map;
677
678         BcVec arrs;
679         BcVec arr_map;
680
681         BcVec strs;
682         BcVec consts;
683
684         const char *file;
685
686         BcNum last;
687         BcNum zero;
688         BcNum one;
689
690         size_t nchars;
691
692 } BcProgram;
693
694 #define BC_PROG_STACK(s, n) ((s)->len >= ((size_t) n))
695
696 #define BC_PROG_MAIN (0)
697 #define BC_PROG_READ (1)
698
699 #if ENABLE_DC
700 #define BC_PROG_REQ_FUNCS (2)
701 #endif
702
703 #define BC_PROG_STR(n) (!(n)->num && !(n)->cap)
704 #define BC_PROG_NUM(r, n) \
705         ((r)->t != BC_RESULT_ARRAY && (r)->t != BC_RESULT_STR && !BC_PROG_STR(n))
706
707 typedef unsigned long (*BcProgramBuiltIn)(BcNum *);
708
709 static void bc_program_addFunc(char *name, size_t *idx);
710 static void bc_program_reset(void);
711
712 #define BC_FLAG_X (1 << 0)
713 #define BC_FLAG_W (1 << 1)
714 #define BC_FLAG_V (1 << 2)
715 #define BC_FLAG_S (1 << 3)
716 #define BC_FLAG_Q (1 << 4)
717 #define BC_FLAG_L (1 << 5)
718 #define BC_FLAG_I (1 << 6)
719
720 #define BC_MAX(a, b) ((a) > (b) ? (a) : (b))
721 #define BC_MIN(a, b) ((a) < (b) ? (a) : (b))
722
723 #define BC_MAX_OBASE  ((unsigned) 999)
724 #define BC_MAX_DIM    ((unsigned) INT_MAX)
725 #define BC_MAX_SCALE  ((unsigned) UINT_MAX)
726 #define BC_MAX_STRING ((unsigned) UINT_MAX - 1)
727 #define BC_MAX_NAME   BC_MAX_STRING
728 #define BC_MAX_NUM    BC_MAX_STRING
729 #define BC_MAX_EXP    ((unsigned long) LONG_MAX)
730 #define BC_MAX_VARS   ((unsigned long) SIZE_MAX - 1)
731
732 struct globals {
733         smallint ttyin;
734         smallint eof;
735         char sbgn;
736         char send;
737
738         BcParse prs;
739         BcProgram prog;
740
741         BcVec files;
742
743         char *env_args;
744 } FIX_ALIASING;
745 #define G (*ptr_to_globals)
746 #define INIT_G() do { \
747         SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
748 } while (0)
749 #define G_posix (ENABLE_BC && (option_mask32 & BC_FLAG_S))
750 #define G_warn  (ENABLE_BC && (option_mask32 & BC_FLAG_W))
751 #define G_exreg (ENABLE_DC && (option_mask32 & BC_FLAG_X))
752 #define G_interrupt (ENABLE_FEATURE_BC_SIGNALS ? bb_got_signal : 0)
753
754
755 #define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b'))
756
757 static void bc_vm_info(void);
758
759 #if ENABLE_BC
760 static const BcLexKeyword bc_lex_kws[20] = {
761         BC_LEX_KW_ENTRY("auto", 4, true),
762         BC_LEX_KW_ENTRY("break", 5, true),
763         BC_LEX_KW_ENTRY("continue", 8, false),
764         BC_LEX_KW_ENTRY("define", 6, true),
765         BC_LEX_KW_ENTRY("else", 4, false),
766         BC_LEX_KW_ENTRY("for", 3, true),
767         BC_LEX_KW_ENTRY("halt", 4, false),
768         BC_LEX_KW_ENTRY("ibase", 5, true),
769         BC_LEX_KW_ENTRY("if", 2, true),
770         BC_LEX_KW_ENTRY("last", 4, false),
771         BC_LEX_KW_ENTRY("length", 6, true),
772         BC_LEX_KW_ENTRY("limits", 6, false),
773         BC_LEX_KW_ENTRY("obase", 5, true),
774         BC_LEX_KW_ENTRY("print", 5, false),
775         BC_LEX_KW_ENTRY("quit", 4, true),
776         BC_LEX_KW_ENTRY("read", 4, false),
777         BC_LEX_KW_ENTRY("return", 6, true),
778         BC_LEX_KW_ENTRY("scale", 5, true),
779         BC_LEX_KW_ENTRY("sqrt", 4, true),
780         BC_LEX_KW_ENTRY("while", 5, true),
781 };
782
783 // This is an array that corresponds to token types. An entry is
784 // true if the token is valid in an expression, false otherwise.
785 static const bool bc_parse_exprs[] = {
786         false, false, true, true, true, true, true, true, true, true, true, true,
787         true, true, true, true, true, true, true, true, true, true, true, true,
788         true, true, true, false, false, true, true, false, false, false, false,
789         false, false, false, true, true, false, false, false, false, false, false,
790         false, true, false, true, true, true, true, false, false, true, false, true,
791         true, false,
792 };
793
794 // This is an array of data for operators that correspond to token types.
795 static const BcOp bc_parse_ops[] = {
796         { 0, false }, { 0, false },
797         { 1, false },
798         { 2, false },
799         { 3, true }, { 3, true }, { 3, true },
800         { 4, true }, { 4, true },
801         { 6, true }, { 6, true }, { 6, true }, { 6, true }, { 6, true }, { 6, true },
802         { 1, false },
803         { 7, true }, { 7, true },
804         { 5, false }, { 5, false }, { 5, false }, { 5, false }, { 5, false },
805         { 5, false }, { 5, false },
806 };
807
808 // These identify what tokens can come after expressions in certain cases.
809 static const BcParseNext bc_parse_next_expr =
810         BC_PARSE_NEXT(4, BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_RBRACE, BC_LEX_EOF);
811 static const BcParseNext bc_parse_next_param =
812         BC_PARSE_NEXT(2, BC_LEX_RPAREN, BC_LEX_COMMA);
813 static const BcParseNext bc_parse_next_print =
814         BC_PARSE_NEXT(4, BC_LEX_COMMA, BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_EOF);
815 static const BcParseNext bc_parse_next_rel = BC_PARSE_NEXT(1, BC_LEX_RPAREN);
816 static const BcParseNext bc_parse_next_elem = BC_PARSE_NEXT(1, BC_LEX_RBRACKET);
817 static const BcParseNext bc_parse_next_for = BC_PARSE_NEXT(1, BC_LEX_SCOLON);
818 static const BcParseNext bc_parse_next_read =
819         BC_PARSE_NEXT(2, BC_LEX_NLINE, BC_LEX_EOF);
820 #endif // ENABLE_BC
821
822 #if ENABLE_DC
823 static const BcLexType dc_lex_regs[] = {
824         BC_LEX_OP_REL_EQ, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_NE,
825         BC_LEX_OP_REL_LT, BC_LEX_OP_REL_GT, BC_LEX_SCOLON, BC_LEX_COLON,
826         BC_LEX_ELSE, BC_LEX_LOAD, BC_LEX_LOAD_POP, BC_LEX_OP_ASSIGN,
827         BC_LEX_STORE_PUSH,
828 };
829
830 static const size_t dc_lex_regs_len = sizeof(dc_lex_regs) / sizeof(BcLexType);
831
832 static const BcLexType dc_lex_tokens[] = {
833         BC_LEX_OP_MODULUS, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_LPAREN,
834         BC_LEX_INVALID, BC_LEX_OP_MULTIPLY, BC_LEX_OP_PLUS, BC_LEX_INVALID,
835         BC_LEX_OP_MINUS, BC_LEX_INVALID, BC_LEX_OP_DIVIDE,
836         BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID,
837         BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID,
838         BC_LEX_INVALID, BC_LEX_INVALID,
839         BC_LEX_COLON, BC_LEX_SCOLON, BC_LEX_OP_REL_GT, BC_LEX_OP_REL_EQ,
840         BC_LEX_OP_REL_LT, BC_LEX_KEY_READ, BC_LEX_INVALID,
841         BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID,
842         BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_EQ_NO_REG, BC_LEX_INVALID,
843         BC_LEX_KEY_IBASE, BC_LEX_INVALID, BC_LEX_KEY_SCALE, BC_LEX_LOAD_POP,
844         BC_LEX_INVALID, BC_LEX_OP_BOOL_NOT, BC_LEX_KEY_OBASE, BC_LEX_PRINT_STREAM,
845         BC_LEX_NQUIT, BC_LEX_POP, BC_LEX_STORE_PUSH, BC_LEX_INVALID, BC_LEX_INVALID,
846         BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_SCALE_FACTOR, BC_LEX_INVALID,
847         BC_LEX_KEY_LENGTH, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID,
848         BC_LEX_OP_POWER, BC_LEX_NEG, BC_LEX_INVALID,
849         BC_LEX_ASCIIFY, BC_LEX_INVALID, BC_LEX_CLEAR_STACK, BC_LEX_DUPLICATE,
850         BC_LEX_ELSE, BC_LEX_PRINT_STACK, BC_LEX_INVALID, BC_LEX_INVALID,
851         BC_LEX_STORE_IBASE, BC_LEX_INVALID, BC_LEX_STORE_SCALE, BC_LEX_LOAD,
852         BC_LEX_INVALID, BC_LEX_PRINT_POP, BC_LEX_STORE_OBASE, BC_LEX_KEY_PRINT,
853         BC_LEX_KEY_QUIT, BC_LEX_SWAP, BC_LEX_OP_ASSIGN, BC_LEX_INVALID,
854         BC_LEX_INVALID, BC_LEX_KEY_SQRT, BC_LEX_INVALID, BC_LEX_EXECUTE,
855         BC_LEX_INVALID, BC_LEX_STACK_LEVEL,
856         BC_LEX_LBRACE, BC_LEX_OP_MODEXP, BC_LEX_INVALID, BC_LEX_OP_DIVMOD,
857         BC_LEX_INVALID
858 };
859
860 static const BcInst dc_parse_insts[] = {
861         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE,
862         BC_INST_INVALID, BC_INST_POWER, BC_INST_MULTIPLY, BC_INST_DIVIDE,
863         BC_INST_MODULUS, BC_INST_PLUS, BC_INST_MINUS,
864         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
865         BC_INST_INVALID, BC_INST_INVALID,
866         BC_INST_BOOL_NOT, BC_INST_INVALID, BC_INST_INVALID,
867         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
868         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
869         BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GT, BC_INST_INVALID,
870         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE,
871         BC_INST_INVALID, BC_INST_INVALID,
872         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
873         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
874         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_IBASE,
875         BC_INST_INVALID, BC_INST_INVALID, BC_INST_LENGTH, BC_INST_INVALID,
876         BC_INST_OBASE, BC_INST_PRINT, BC_INST_QUIT, BC_INST_INVALID,
877         BC_INST_INVALID, BC_INST_SCALE, BC_INST_SQRT, BC_INST_INVALID,
878         BC_INST_REL_EQ, BC_INST_MODEXP, BC_INST_DIVMOD, BC_INST_INVALID,
879         BC_INST_INVALID, BC_INST_EXECUTE, BC_INST_PRINT_STACK, BC_INST_CLEAR_STACK,
880         BC_INST_STACK_LEN, BC_INST_DUPLICATE, BC_INST_SWAP, BC_INST_POP,
881         BC_INST_ASCIIFY, BC_INST_PRINT_STREAM, BC_INST_INVALID, BC_INST_INVALID,
882         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
883         BC_INST_PRINT, BC_INST_NQUIT, BC_INST_SCALE_FUNC,
884 };
885 #endif // ENABLE_DC
886
887 static const BcNumBinaryOp bc_program_ops[] = {
888         bc_num_pow, bc_num_mul, bc_num_div, bc_num_mod, bc_num_add, bc_num_sub,
889 };
890
891 static const char bc_program_stdin_name[] = "<stdin>";
892
893 #if ENABLE_BC
894 static const char *bc_lib_name = "gen/lib.bc";
895
896 static const char bc_lib[] = {
897   115,99,97,108,101,61,50,48,10,100,101,102,105,110,101,32,101,40,120,41,123,
898   10,9,97,117,116,111,32,98,44,115,44,110,44,114,44,100,44,105,44,112,44,102,
899   44,118,10,9,98,61,105,98,97,115,101,10,9,105,98,97,115,101,61,65,10,9,105,102,
900   40,120,60,48,41,123,10,9,9,110,61,49,10,9,9,120,61,45,120,10,9,125,10,9,115,
901   61,115,99,97,108,101,10,9,114,61,54,43,115,43,48,46,52,52,42,120,10,9,115,99,
902   97,108,101,61,115,99,97,108,101,40,120,41,43,49,10,9,119,104,105,108,101,40,
903   120,62,49,41,123,10,9,9,100,43,61,49,10,9,9,120,47,61,50,10,9,9,115,99,97,108,
904   101,43,61,49,10,9,125,10,9,115,99,97,108,101,61,114,10,9,114,61,120,43,49,10,
905   9,112,61,120,10,9,102,61,118,61,49,10,9,102,111,114,40,105,61,50,59,118,33,
906   61,48,59,43,43,105,41,123,10,9,9,112,42,61,120,10,9,9,102,42,61,105,10,9,9,
907   118,61,112,47,102,10,9,9,114,43,61,118,10,9,125,10,9,119,104,105,108,101,40,
908   40,100,45,45,41,33,61,48,41,114,42,61,114,10,9,115,99,97,108,101,61,115,10,
909   9,105,98,97,115,101,61,98,10,9,105,102,40,110,33,61,48,41,114,101,116,117,114,
910   110,40,49,47,114,41,10,9,114,101,116,117,114,110,40,114,47,49,41,10,125,10,
911   100,101,102,105,110,101,32,108,40,120,41,123,10,9,97,117,116,111,32,98,44,115,
912   44,114,44,112,44,97,44,113,44,105,44,118,10,9,98,61,105,98,97,115,101,10,9,
913   105,98,97,115,101,61,65,10,9,105,102,40,120,60,61,48,41,123,10,9,9,114,61,40,
914   49,45,49,48,94,115,99,97,108,101,41,47,49,10,9,9,105,98,97,115,101,61,98,10,
915   9,9,114,101,116,117,114,110,40,114,41,10,9,125,10,9,115,61,115,99,97,108,101,
916   10,9,115,99,97,108,101,43,61,54,10,9,112,61,50,10,9,119,104,105,108,101,40,
917   120,62,61,50,41,123,10,9,9,112,42,61,50,10,9,9,120,61,115,113,114,116,40,120,
918   41,10,9,125,10,9,119,104,105,108,101,40,120,60,61,48,46,53,41,123,10,9,9,112,
919   42,61,50,10,9,9,120,61,115,113,114,116,40,120,41,10,9,125,10,9,114,61,97,61,
920   40,120,45,49,41,47,40,120,43,49,41,10,9,113,61,97,42,97,10,9,118,61,49,10,9,
921   102,111,114,40,105,61,51,59,118,33,61,48,59,105,43,61,50,41,123,10,9,9,97,42,
922   61,113,10,9,9,118,61,97,47,105,10,9,9,114,43,61,118,10,9,125,10,9,114,42,61,
923   112,10,9,115,99,97,108,101,61,115,10,9,105,98,97,115,101,61,98,10,9,114,101,
924   116,117,114,110,40,114,47,49,41,10,125,10,100,101,102,105,110,101,32,115,40,
925   120,41,123,10,9,97,117,116,111,32,98,44,115,44,114,44,110,44,97,44,113,44,105,
926   10,9,98,61,105,98,97,115,101,10,9,105,98,97,115,101,61,65,10,9,115,61,115,99,
927   97,108,101,10,9,115,99,97,108,101,61,49,46,49,42,115,43,50,10,9,97,61,97,40,
928   49,41,10,9,105,102,40,120,60,48,41,123,10,9,9,110,61,49,10,9,9,120,61,45,120,
929   10,9,125,10,9,115,99,97,108,101,61,48,10,9,113,61,40,120,47,97,43,50,41,47,
930   52,10,9,120,61,120,45,52,42,113,42,97,10,9,105,102,40,113,37,50,33,61,48,41,
931   120,61,45,120,10,9,115,99,97,108,101,61,115,43,50,10,9,114,61,97,61,120,10,
932   9,113,61,45,120,42,120,10,9,102,111,114,40,105,61,51,59,97,33,61,48,59,105,
933   43,61,50,41,123,10,9,9,97,42,61,113,47,40,105,42,40,105,45,49,41,41,10,9,9,
934   114,43,61,97,10,9,125,10,9,115,99,97,108,101,61,115,10,9,105,98,97,115,101,
935   61,98,10,9,105,102,40,110,33,61,48,41,114,101,116,117,114,110,40,45,114,47,
936   49,41,10,9,114,101,116,117,114,110,40,114,47,49,41,10,125,10,100,101,102,105,
937   110,101,32,99,40,120,41,123,10,9,97,117,116,111,32,98,44,115,10,9,98,61,105,
938   98,97,115,101,10,9,105,98,97,115,101,61,65,10,9,115,61,115,99,97,108,101,10,
939   9,115,99,97,108,101,42,61,49,46,50,10,9,120,61,115,40,50,42,97,40,49,41,43,
940   120,41,10,9,115,99,97,108,101,61,115,10,9,105,98,97,115,101,61,98,10,9,114,
941   101,116,117,114,110,40,120,47,49,41,10,125,10,100,101,102,105,110,101,32,97,
942   40,120,41,123,10,9,97,117,116,111,32,98,44,115,44,114,44,110,44,97,44,109,44,
943   116,44,102,44,105,44,117,10,9,98,61,105,98,97,115,101,10,9,105,98,97,115,101,
944   61,65,10,9,110,61,49,10,9,105,102,40,120,60,48,41,123,10,9,9,110,61,45,49,10,
945   9,9,120,61,45,120,10,9,125,10,9,105,102,40,120,61,61,49,41,123,10,9,9,105,102,
946   40,115,99,97,108,101,60,54,53,41,123,10,9,9,9,114,101,116,117,114,110,40,46,
947   55,56,53,51,57,56,49,54,51,51,57,55,52,52,56,51,48,57,54,49,53,54,54,48,56,
948   52,53,56,49,57,56,55,53,55,50,49,48,52,57,50,57,50,51,52,57,56,52,51,55,55,
949   54,52,53,53,50,52,51,55,51,54,49,52,56,48,47,110,41,10,9,9,125,10,9,125,10,
950   9,105,102,40,120,61,61,46,50,41,123,10,9,9,105,102,40,115,99,97,108,101,60,
951   54,53,41,123,10,9,9,9,114,101,116,117,114,110,40,46,49,57,55,51,57,53,53,53,
952   57,56,52,57,56,56,48,55,53,56,51,55,48,48,52,57,55,54,53,49,57,52,55,57,48,
953   50,57,51,52,52,55,53,56,53,49,48,51,55,56,55,56,53,50,49,48,49,53,49,55,54,
954   56,56,57,52,48,50,47,110,41,10,9,9,125,10,9,125,10,9,115,61,115,99,97,108,101,
955   10,9,105,102,40,120,62,46,50,41,123,10,9,9,115,99,97,108,101,43,61,53,10,9,
956   9,97,61,97,40,46,50,41,10,9,125,10,9,115,99,97,108,101,61,115,43,51,10,9,119,
957   104,105,108,101,40,120,62,46,50,41,123,10,9,9,109,43,61,49,10,9,9,120,61,40,
958   120,45,46,50,41,47,40,49,43,46,50,42,120,41,10,9,125,10,9,114,61,117,61,120,
959   10,9,102,61,45,120,42,120,10,9,116,61,49,10,9,102,111,114,40,105,61,51,59,116,
960   33,61,48,59,105,43,61,50,41,123,10,9,9,117,42,61,102,10,9,9,116,61,117,47,105,
961   10,9,9,114,43,61,116,10,9,125,10,9,115,99,97,108,101,61,115,10,9,105,98,97,
962   115,101,61,98,10,9,114,101,116,117,114,110,40,40,109,42,97,43,114,41,47,110,
963   41,10,125,10,100,101,102,105,110,101,32,106,40,110,44,120,41,123,10,9,97,117,
964   116,111,32,98,44,115,44,111,44,97,44,105,44,118,44,102,10,9,98,61,105,98,97,
965   115,101,10,9,105,98,97,115,101,61,65,10,9,115,61,115,99,97,108,101,10,9,115,
966   99,97,108,101,61,48,10,9,110,47,61,49,10,9,105,102,40,110,60,48,41,123,10,9,
967   9,110,61,45,110,10,9,9,105,102,40,110,37,50,61,61,49,41,111,61,49,10,9,125,
968   10,9,97,61,49,10,9,102,111,114,40,105,61,50,59,105,60,61,110,59,43,43,105,41,
969   97,42,61,105,10,9,115,99,97,108,101,61,49,46,53,42,115,10,9,97,61,40,120,94,
970   110,41,47,50,94,110,47,97,10,9,114,61,118,61,49,10,9,102,61,45,120,42,120,47,
971   52,10,9,115,99,97,108,101,61,115,99,97,108,101,43,108,101,110,103,116,104,40,
972   97,41,45,115,99,97,108,101,40,97,41,10,9,102,111,114,40,105,61,49,59,118,33,
973   61,48,59,43,43,105,41,123,10,9,9,118,61,118,42,102,47,105,47,40,110,43,105,
974   41,10,9,9,114,43,61,118,10,9,125,10,9,115,99,97,108,101,61,115,10,9,105,98,
975   97,115,101,61,98,10,9,105,102,40,111,33,61,48,41,97,61,45,97,10,9,114,101,116,
976   117,114,110,40,97,42,114,47,49,41,10,125,10,0
977 };
978 #endif // ENABLE_BC
979
980 static void fflush_and_check(void)
981 {
982         fflush_all();
983         if (ferror(stdout) || ferror(stderr))
984                 bb_perror_msg_and_die("output error");
985 }
986
987 static void quit(void) NORETURN;
988 static void quit(void)
989 {
990         if (ferror(stdin))
991                 bb_perror_msg_and_die("input error");
992         fflush_and_check();
993         exit(0);
994 }
995
996 static int bc_error(const char *fmt, ...)
997 {
998         va_list p;
999
1000         va_start(p, fmt);
1001         bb_verror_msg(fmt, p, NULL);
1002         va_end(p);
1003         if (!G.ttyin)
1004                 exit(1);
1005         return BC_STATUS_FAILURE;
1006 }
1007
1008 static int bc_posix_error(const char *fmt, ...)
1009 {
1010         va_list p;
1011
1012         if (!(option_mask32 & (BC_FLAG_S|BC_FLAG_W)))
1013                 return BC_STATUS_SUCCESS;
1014
1015         va_start(p, fmt);
1016         bb_verror_msg(fmt, p, NULL);
1017         va_end(p);
1018
1019         // Do we treat non-POSIX constructs as errors?
1020         if (!(option_mask32 & BC_FLAG_S))
1021                 return BC_STATUS_SUCCESS; // no, it's a warning
1022         if (!G.ttyin)
1023                 exit(1);
1024         return BC_STATUS_FAILURE;
1025 }
1026
1027 static void bc_vec_grow(BcVec *v, size_t n)
1028 {
1029         size_t cap = v->cap * 2;
1030         while (cap < v->len + n) cap *= 2;
1031         v->v = xrealloc(v->v, v->size * cap);
1032         v->cap = cap;
1033 }
1034
1035 static void bc_vec_init(BcVec *v, size_t esize, BcVecFree dtor)
1036 {
1037         v->size = esize;
1038         v->cap = BC_VEC_START_CAP;
1039         v->len = 0;
1040         v->dtor = dtor;
1041         v->v = xmalloc(esize * BC_VEC_START_CAP);
1042 }
1043
1044 static void bc_vec_expand(BcVec *v, size_t req)
1045 {
1046         if (v->cap < req) {
1047                 v->v = xrealloc(v->v, v->size * req);
1048                 v->cap = req;
1049         }
1050 }
1051
1052 static void bc_vec_npop(BcVec *v, size_t n)
1053 {
1054         if (!v->dtor)
1055                 v->len -= n;
1056         else {
1057                 size_t len = v->len - n;
1058                 while (v->len > len) v->dtor(v->v + (v->size * --v->len));
1059         }
1060 }
1061
1062 static void bc_vec_push(BcVec *v, const void *data)
1063 {
1064         if (v->len + 1 > v->cap) bc_vec_grow(v, 1);
1065         memmove(v->v + (v->size * v->len), data, v->size);
1066         v->len += 1;
1067 }
1068
1069 static void bc_vec_pushByte(BcVec *v, char data)
1070 {
1071         bc_vec_push(v, &data);
1072 }
1073
1074 static void bc_vec_pushAt(BcVec *v, const void *data, size_t idx)
1075 {
1076         if (idx == v->len)
1077                 bc_vec_push(v, data);
1078         else {
1079
1080                 char *ptr;
1081
1082                 if (v->len == v->cap) bc_vec_grow(v, 1);
1083
1084                 ptr = v->v + v->size * idx;
1085
1086                 memmove(ptr + v->size, ptr, v->size * (v->len++ - idx));
1087                 memmove(ptr, data, v->size);
1088         }
1089 }
1090
1091 static void bc_vec_string(BcVec *v, size_t len, const char *str)
1092 {
1093         bc_vec_npop(v, v->len);
1094         bc_vec_expand(v, len + 1);
1095         memcpy(v->v, str, len);
1096         v->len = len;
1097
1098         bc_vec_pushByte(v, '\0');
1099 }
1100
1101 static void bc_vec_concat(BcVec *v, const char *str)
1102 {
1103         size_t len;
1104
1105         if (v->len == 0) bc_vec_pushByte(v, '\0');
1106
1107         len = v->len + strlen(str);
1108
1109         if (v->cap < len) bc_vec_grow(v, len - v->len);
1110         strcat(v->v, str);
1111
1112         v->len = len;
1113 }
1114
1115 static void *bc_vec_item(const BcVec *v, size_t idx)
1116 {
1117         return v->v + v->size * idx;
1118 }
1119
1120 static void *bc_vec_item_rev(const BcVec *v, size_t idx)
1121 {
1122         return v->v + v->size * (v->len - idx - 1);
1123 }
1124
1125 static void bc_vec_free(void *vec)
1126 {
1127         BcVec *v = (BcVec *) vec;
1128         bc_vec_npop(v, v->len);
1129         free(v->v);
1130 }
1131
1132 static size_t bc_map_find(const BcVec *v, const void *ptr)
1133 {
1134         size_t low = 0, high = v->len;
1135
1136         while (low < high) {
1137
1138                 size_t mid = (low + high) / 2;
1139                 BcId *id = bc_vec_item(v, mid);
1140                 int result = bc_id_cmp(ptr, id);
1141
1142                 if (result == 0)
1143                         return mid;
1144                 else if (result < 0)
1145                         high = mid;
1146                 else
1147                         low = mid + 1;
1148         }
1149
1150         return low;
1151 }
1152
1153 static int bc_map_insert(BcVec *v, const void *ptr, size_t *i)
1154 {
1155         size_t n = *i = bc_map_find(v, ptr);
1156
1157         if (n == v->len)
1158                 bc_vec_push(v, ptr);
1159         else if (!bc_id_cmp(ptr, bc_vec_item(v, n)))
1160                 return 0; // "was not inserted"
1161         else
1162                 bc_vec_pushAt(v, ptr, n);
1163         return 1; // "was inserted"
1164 }
1165
1166 static size_t bc_map_index(const BcVec *v, const void *ptr)
1167 {
1168         size_t i = bc_map_find(v, ptr);
1169         if (i >= v->len) return BC_VEC_INVALID_IDX;
1170         return bc_id_cmp(ptr, bc_vec_item(v, i)) ? BC_VEC_INVALID_IDX : i;
1171 }
1172
1173 static BcStatus bc_read_line(BcVec *vec, const char *prompt)
1174 {
1175         bool bad_chars;
1176
1177         do {
1178                 int i;
1179                 char c;
1180
1181                 bad_chars = 0;
1182                 bc_vec_npop(vec, vec->len);
1183
1184                 fflush_and_check();
1185 #if ENABLE_FEATURE_BC_SIGNALS
1186                 if (bb_got_signal) { // ^C was pressed
1187  intr:
1188                         bb_got_signal = 0; // resets G_interrupt to zero
1189                         fputs(IS_BC
1190                                 ? "\ninterrupt (type \"quit\" to exit)\n"
1191                                 : "\ninterrupt (type \"q\" to exit)\n"
1192                                 , stderr);
1193                 }
1194 #endif
1195                 if (G.ttyin && !G_posix)
1196                         fputs(prompt, stderr);
1197
1198 #if ENABLE_FEATURE_BC_SIGNALS
1199                 errno = 0;
1200 #endif
1201                 do {
1202                         i = fgetc(stdin);
1203                         if (i == EOF) {
1204 #if ENABLE_FEATURE_BC_SIGNALS
1205                                 // Both conditions appear simultaneously, check both just in case
1206                                 if (errno == EINTR || bb_got_signal) {
1207                                         // ^C was pressed
1208                                         clearerr(stdin);
1209                                         goto intr;
1210                                 }
1211 #endif
1212                                 if (ferror(stdin))
1213                                         quit(); // this emits error message
1214                                 G.eof = 1;
1215                                 // Note: EOF does not append '\n', therefore:
1216                                 // printf 'print 123\n' | bc - works
1217                                 // printf 'print 123' | bc   - fails (syntax error)
1218                                 break;
1219                         }
1220
1221                         if ((i < ' ' && i != '\t' && i != '\r' && i != '\n') // also allow '\v' '\f'?
1222                          || i > 0x7e
1223                         ) {
1224                                 // Bad chars on this line, ignore entire line
1225                                 bc_error("illegal character 0x%02x", i);
1226                                 bad_chars = 1;
1227                         }
1228                         c = (char) i;
1229                         bc_vec_push(vec, &c);
1230                 } while (i != '\n');
1231         } while (bad_chars);
1232
1233         bc_vec_pushByte(vec, '\0');
1234
1235         return BC_STATUS_SUCCESS;
1236 }
1237
1238 static char* bc_read_file(const char *path)
1239 {
1240         char *buf;
1241         size_t size = ((size_t) -1);
1242         size_t i;
1243
1244         buf = xmalloc_open_read_close(path, &size);
1245
1246         for (i = 0; i < size; ++i) {
1247                 char c = buf[i];
1248                 if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'?
1249                  || c > 0x7e
1250                 ) {
1251                         free(buf);
1252                         buf = NULL;
1253                         break;
1254                 }
1255         }
1256
1257         return buf;
1258 }
1259
1260 static void bc_args(int argc, char **argv)
1261 {
1262         unsigned opts;
1263         int i;
1264
1265         GETOPT_RESET();
1266 #if ENABLE_FEATURE_BC_LONG_OPTIONS
1267         opts = getopt32long(argv, "xwvsqli",
1268                 "extended-register\0" No_argument "x"
1269                 "warn\0"              No_argument "w"
1270                 "version\0"           No_argument "v"
1271                 "standard\0"          No_argument "s"
1272                 "quiet\0"             No_argument "q"
1273                 "mathlib\0"           No_argument "l"
1274                 "interactive\0"       No_argument "i"
1275         );
1276 #else
1277         opts = getopt32(argv, "xwvsqli");
1278 #endif
1279         if (getenv("POSIXLY_CORRECT"))
1280                 option_mask32 |= BC_FLAG_S;
1281
1282         if (opts & BC_FLAG_V) bc_vm_info();
1283         // should not be necessary, getopt32() handles this??
1284         //if (argv[optind] && !strcmp(argv[optind], "--")) ++optind;
1285
1286         for (i = optind; i < argc; ++i)
1287                 bc_vec_push(&G.files, argv + i);
1288 }
1289
1290 static void bc_num_setToZero(BcNum *n, size_t scale)
1291 {
1292         n->len = 0;
1293         n->neg = false;
1294         n->rdx = scale;
1295 }
1296
1297 static void bc_num_zero(BcNum *n)
1298 {
1299         bc_num_setToZero(n, 0);
1300 }
1301
1302 static void bc_num_one(BcNum *n)
1303 {
1304         bc_num_setToZero(n, 0);
1305         n->len = 1;
1306         n->num[0] = 1;
1307 }
1308
1309 static void bc_num_ten(BcNum *n)
1310 {
1311         bc_num_setToZero(n, 0);
1312         n->len = 2;
1313         n->num[0] = 0;
1314         n->num[1] = 1;
1315 }
1316
1317 static void bc_num_subArrays(BcDig *restrict a, BcDig *restrict b,
1318                                  size_t len)
1319 {
1320         size_t i, j;
1321         for (i = 0; i < len; ++i) {
1322                 for (a[i] -= b[i], j = 0; a[i + j] < 0;) {
1323                         a[i + j++] += 10;
1324                         a[i + j] -= 1;
1325                 }
1326         }
1327 }
1328
1329 static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len)
1330 {
1331         size_t i;
1332         int c = 0;
1333         for (i = len - 1; i < len && !(c = a[i] - b[i]); --i);
1334         return BC_NUM_NEG(i + 1, c < 0);
1335 }
1336
1337 static ssize_t bc_num_cmp(BcNum *a, BcNum *b)
1338 {
1339         size_t i, min, a_int, b_int, diff;
1340         BcDig *max_num, *min_num;
1341         bool a_max, neg = false;
1342         ssize_t cmp;
1343
1344         if (a == b) return 0;
1345         if (a->len == 0) return BC_NUM_NEG(!!b->len, !b->neg);
1346         if (b->len == 0) return BC_NUM_NEG(1, a->neg);
1347         if (a->neg) {
1348                 if (b->neg)
1349                         neg = true;
1350                 else
1351                         return -1;
1352         }
1353         else if (b->neg)
1354                 return 1;
1355
1356         a_int = BC_NUM_INT(a);
1357         b_int = BC_NUM_INT(b);
1358         a_int -= b_int;
1359         a_max = (a->rdx > b->rdx);
1360
1361         if (a_int != 0) return (ssize_t) a_int;
1362
1363         if (a_max) {
1364                 min = b->rdx;
1365                 diff = a->rdx - b->rdx;
1366                 max_num = a->num + diff;
1367                 min_num = b->num;
1368         }
1369         else {
1370                 min = a->rdx;
1371                 diff = b->rdx - a->rdx;
1372                 max_num = b->num + diff;
1373                 min_num = a->num;
1374         }
1375
1376         cmp = bc_num_compare(max_num, min_num, b_int + min);
1377         if (cmp != 0) return BC_NUM_NEG(cmp, (!a_max) != neg);
1378
1379         for (max_num -= diff, i = diff - 1; i < diff; --i) {
1380                 if (max_num[i]) return BC_NUM_NEG(1, (!a_max) != neg);
1381         }
1382
1383         return 0;
1384 }
1385
1386 static void bc_num_truncate(BcNum *n, size_t places)
1387 {
1388         if (places == 0) return;
1389
1390         n->rdx -= places;
1391
1392         if (n->len != 0) {
1393                 n->len -= places;
1394                 memmove(n->num, n->num + places, n->len * sizeof(BcDig));
1395         }
1396 }
1397
1398 static void bc_num_extend(BcNum *n, size_t places)
1399 {
1400         size_t len = n->len + places;
1401
1402         if (places != 0) {
1403
1404                 if (n->cap < len) bc_num_expand(n, len);
1405
1406                 memmove(n->num + places, n->num, sizeof(BcDig) * n->len);
1407                 memset(n->num, 0, sizeof(BcDig) * places);
1408
1409                 n->len += places;
1410                 n->rdx += places;
1411         }
1412 }
1413
1414 static void bc_num_clean(BcNum *n)
1415 {
1416         while (n->len > 0 && n->num[n->len - 1] == 0) --n->len;
1417         if (n->len == 0)
1418                 n->neg = false;
1419         else if (n->len < n->rdx)
1420                 n->len = n->rdx;
1421 }
1422
1423 static void bc_num_retireMul(BcNum *n, size_t scale, bool neg1, bool neg2)
1424 {
1425         if (n->rdx < scale)
1426                 bc_num_extend(n, scale - n->rdx);
1427         else
1428                 bc_num_truncate(n, n->rdx - scale);
1429
1430         bc_num_clean(n);
1431         if (n->len != 0) n->neg = !neg1 != !neg2;
1432 }
1433
1434 static void bc_num_split(BcNum *restrict n, size_t idx, BcNum *restrict a,
1435                          BcNum *restrict b)
1436 {
1437         if (idx < n->len) {
1438
1439                 b->len = n->len - idx;
1440                 a->len = idx;
1441                 a->rdx = b->rdx = 0;
1442
1443                 memcpy(b->num, n->num + idx, b->len * sizeof(BcDig));
1444                 memcpy(a->num, n->num, idx * sizeof(BcDig));
1445         }
1446         else {
1447                 bc_num_zero(b);
1448                 bc_num_copy(a, n);
1449         }
1450
1451         bc_num_clean(a);
1452         bc_num_clean(b);
1453 }
1454
1455 static BcStatus bc_num_shift(BcNum *n, size_t places)
1456 {
1457         if (places == 0 || n->len == 0) return BC_STATUS_SUCCESS;
1458         if (places + n->len > BC_MAX_NUM)
1459                 return bc_error("number too long: must be [1, BC_NUM_MAX]");
1460
1461         if (n->rdx >= places)
1462                 n->rdx -= places;
1463         else {
1464                 bc_num_extend(n, places - n->rdx);
1465                 n->rdx = 0;
1466         }
1467
1468         bc_num_clean(n);
1469
1470         return BC_STATUS_SUCCESS;
1471 }
1472
1473 static BcStatus bc_num_inv(BcNum *a, BcNum *b, size_t scale)
1474 {
1475         BcNum one;
1476         BcDig num[2];
1477
1478         one.cap = 2;
1479         one.num = num;
1480         bc_num_one(&one);
1481
1482         return bc_num_div(&one, a, b, scale);
1483 }
1484
1485 static BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub)
1486 {
1487         BcDig *ptr, *ptr_a, *ptr_b, *ptr_c;
1488         size_t i, max, min_rdx, min_int, diff, a_int, b_int;
1489         int carry, in;
1490
1491         // Because this function doesn't need to use scale (per the bc spec),
1492         // I am hijacking it to say whether it's doing an add or a subtract.
1493
1494         if (a->len == 0) {
1495                 bc_num_copy(c, b);
1496                 if (sub && c->len) c->neg = !c->neg;
1497                 return BC_STATUS_SUCCESS;
1498         }
1499         else if (b->len == 0) {
1500                 bc_num_copy(c, a);
1501                 return BC_STATUS_SUCCESS;
1502         }
1503
1504         c->neg = a->neg;
1505         c->rdx = BC_MAX(a->rdx, b->rdx);
1506         min_rdx = BC_MIN(a->rdx, b->rdx);
1507         c->len = 0;
1508
1509         if (a->rdx > b->rdx) {
1510                 diff = a->rdx - b->rdx;
1511                 ptr = a->num;
1512                 ptr_a = a->num + diff;
1513                 ptr_b = b->num;
1514         }
1515         else {
1516                 diff = b->rdx - a->rdx;
1517                 ptr = b->num;
1518                 ptr_a = a->num;
1519                 ptr_b = b->num + diff;
1520         }
1521
1522         for (ptr_c = c->num, i = 0; i < diff; ++i, ++c->len) ptr_c[i] = ptr[i];
1523
1524         ptr_c += diff;
1525         a_int = BC_NUM_INT(a);
1526         b_int = BC_NUM_INT(b);
1527
1528         if (a_int > b_int) {
1529                 min_int = b_int;
1530                 max = a_int;
1531                 ptr = ptr_a;
1532         }
1533         else {
1534                 min_int = a_int;
1535                 max = b_int;
1536                 ptr = ptr_b;
1537         }
1538
1539         for (carry = 0, i = 0; i < min_rdx + min_int; ++i, ++c->len) {
1540                 in = ((int) ptr_a[i]) + ((int) ptr_b[i]) + carry;
1541                 carry = in / 10;
1542                 ptr_c[i] = (BcDig)(in % 10);
1543         }
1544
1545         for (; i < max + min_rdx; ++i, ++c->len) {
1546                 in = ((int) ptr[i]) + carry;
1547                 carry = in / 10;
1548                 ptr_c[i] = (BcDig)(in % 10);
1549         }
1550
1551         if (carry != 0) c->num[c->len++] = (BcDig) carry;
1552
1553         return BC_STATUS_SUCCESS; // can't make void, see bc_num_binary()
1554 }
1555
1556 static BcStatus bc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub)
1557 {
1558         ssize_t cmp;
1559         BcNum *minuend, *subtrahend;
1560         size_t start;
1561         bool aneg, bneg, neg;
1562
1563         // Because this function doesn't need to use scale (per the bc spec),
1564         // I am hijacking it to say whether it's doing an add or a subtract.
1565
1566         if (a->len == 0) {
1567                 bc_num_copy(c, b);
1568                 if (sub && c->len) c->neg = !c->neg;
1569                 return BC_STATUS_SUCCESS;
1570         }
1571         else if (b->len == 0) {
1572                 bc_num_copy(c, a);
1573                 return BC_STATUS_SUCCESS;
1574         }
1575
1576         aneg = a->neg;
1577         bneg = b->neg;
1578         a->neg = b->neg = false;
1579
1580         cmp = bc_num_cmp(a, b);
1581
1582         a->neg = aneg;
1583         b->neg = bneg;
1584
1585         if (cmp == 0) {
1586                 bc_num_setToZero(c, BC_MAX(a->rdx, b->rdx));
1587                 return BC_STATUS_SUCCESS;
1588         }
1589         else if (cmp > 0) {
1590                 neg = a->neg;
1591                 minuend = a;
1592                 subtrahend = b;
1593         }
1594         else {
1595                 neg = b->neg;
1596                 if (sub) neg = !neg;
1597                 minuend = b;
1598                 subtrahend = a;
1599         }
1600
1601         bc_num_copy(c, minuend);
1602         c->neg = neg;
1603
1604         if (c->rdx < subtrahend->rdx) {
1605                 bc_num_extend(c, subtrahend->rdx - c->rdx);
1606                 start = 0;
1607         }
1608         else
1609                 start = c->rdx - subtrahend->rdx;
1610
1611         bc_num_subArrays(c->num + start, subtrahend->num, subtrahend->len);
1612
1613         bc_num_clean(c);
1614
1615         return BC_STATUS_SUCCESS; // can't make void, see bc_num_binary()
1616 }
1617
1618 static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b,
1619                          BcNum *restrict c)
1620 {
1621         BcStatus s;
1622         int carry;
1623         size_t i, j, len, max = BC_MAX(a->len, b->len), max2 = (max + 1) / 2;
1624         BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp;
1625         bool aone = BC_NUM_ONE(a);
1626
1627         if (a->len == 0 || b->len == 0) {
1628                 bc_num_zero(c);
1629                 return BC_STATUS_SUCCESS;
1630         }
1631         else if (aone || BC_NUM_ONE(b)) {
1632                 bc_num_copy(c, aone ? b : a);
1633                 return BC_STATUS_SUCCESS;
1634         }
1635
1636         if (a->len + b->len < BC_NUM_KARATSUBA_LEN ||
1637             a->len < BC_NUM_KARATSUBA_LEN || b->len < BC_NUM_KARATSUBA_LEN)
1638         {
1639                 bc_num_expand(c, a->len + b->len + 1);
1640
1641                 memset(c->num, 0, sizeof(BcDig) * c->cap);
1642                 c->len = carry = len = 0;
1643
1644                 for (i = 0; i < b->len; ++i) {
1645
1646                         for (j = 0; j < a->len; ++j) {
1647                                 int in = (int) c->num[i + j];
1648                                 in += ((int) a->num[j]) * ((int) b->num[i]) + carry;
1649                                 carry = in / 10;
1650                                 c->num[i + j] = (BcDig)(in % 10);
1651                         }
1652
1653                         c->num[i + j] += (BcDig) carry;
1654                         len = BC_MAX(len, i + j + !!carry);
1655                         carry = 0;
1656                 }
1657
1658                 c->len = len;
1659
1660                 return BC_STATUS_SUCCESS;
1661         }
1662
1663         bc_num_init(&l1, max);
1664         bc_num_init(&h1, max);
1665         bc_num_init(&l2, max);
1666         bc_num_init(&h2, max);
1667         bc_num_init(&m1, max);
1668         bc_num_init(&m2, max);
1669         bc_num_init(&z0, max);
1670         bc_num_init(&z1, max);
1671         bc_num_init(&z2, max);
1672         bc_num_init(&temp, max + max);
1673
1674         bc_num_split(a, max2, &l1, &h1);
1675         bc_num_split(b, max2, &l2, &h2);
1676
1677         s = bc_num_add(&h1, &l1, &m1, 0);
1678         if (s) goto err;
1679         s = bc_num_add(&h2, &l2, &m2, 0);
1680         if (s) goto err;
1681
1682         s = bc_num_k(&h1, &h2, &z0);
1683         if (s) goto err;
1684         s = bc_num_k(&m1, &m2, &z1);
1685         if (s) goto err;
1686         s = bc_num_k(&l1, &l2, &z2);
1687         if (s) goto err;
1688
1689         s = bc_num_sub(&z1, &z0, &temp, 0);
1690         if (s) goto err;
1691         s = bc_num_sub(&temp, &z2, &z1, 0);
1692         if (s) goto err;
1693
1694         s = bc_num_shift(&z0, max2 * 2);
1695         if (s) goto err;
1696         s = bc_num_shift(&z1, max2);
1697         if (s) goto err;
1698         s = bc_num_add(&z0, &z1, &temp, 0);
1699         if (s) goto err;
1700         s = bc_num_add(&temp, &z2, c, 0);
1701
1702 err:
1703         bc_num_free(&temp);
1704         bc_num_free(&z2);
1705         bc_num_free(&z1);
1706         bc_num_free(&z0);
1707         bc_num_free(&m2);
1708         bc_num_free(&m1);
1709         bc_num_free(&h2);
1710         bc_num_free(&l2);
1711         bc_num_free(&h1);
1712         bc_num_free(&l1);
1713         return s;
1714 }
1715
1716 static BcStatus bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
1717 {
1718         BcStatus s;
1719         BcNum cpa, cpb;
1720         size_t maxrdx = BC_MAX(a->rdx, b->rdx);
1721
1722         scale = BC_MAX(scale, a->rdx);
1723         scale = BC_MAX(scale, b->rdx);
1724         scale = BC_MIN(a->rdx + b->rdx, scale);
1725         maxrdx = BC_MAX(maxrdx, scale);
1726
1727         bc_num_init(&cpa, a->len);
1728         bc_num_init(&cpb, b->len);
1729
1730         bc_num_copy(&cpa, a);
1731         bc_num_copy(&cpb, b);
1732         cpa.neg = cpb.neg = false;
1733
1734         s = bc_num_shift(&cpa, maxrdx);
1735         if (s) goto err;
1736         s = bc_num_shift(&cpb, maxrdx);
1737         if (s) goto err;
1738         s = bc_num_k(&cpa, &cpb, c);
1739         if (s) goto err;
1740
1741         maxrdx += scale;
1742         bc_num_expand(c, c->len + maxrdx);
1743
1744         if (c->len < maxrdx) {
1745                 memset(c->num + c->len, 0, (c->cap - c->len) * sizeof(BcDig));
1746                 c->len += maxrdx;
1747         }
1748
1749         c->rdx = maxrdx;
1750         bc_num_retireMul(c, scale, a->neg, b->neg);
1751
1752 err:
1753         bc_num_free(&cpb);
1754         bc_num_free(&cpa);
1755         return s;
1756 }
1757
1758 static BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
1759 {
1760         BcStatus s = BC_STATUS_SUCCESS;
1761         BcDig *n, *p, q;
1762         size_t len, end, i;
1763         BcNum cp;
1764         bool zero = true;
1765
1766         if (b->len == 0)
1767                 return bc_error("divide by zero");
1768         else if (a->len == 0) {
1769                 bc_num_setToZero(c, scale);
1770                 return BC_STATUS_SUCCESS;
1771         }
1772         else if (BC_NUM_ONE(b)) {
1773                 bc_num_copy(c, a);
1774                 bc_num_retireMul(c, scale, a->neg, b->neg);
1775                 return BC_STATUS_SUCCESS;
1776         }
1777
1778         bc_num_init(&cp, BC_NUM_MREQ(a, b, scale));
1779         bc_num_copy(&cp, a);
1780         len = b->len;
1781
1782         if (len > cp.len) {
1783                 bc_num_expand(&cp, len + 2);
1784                 bc_num_extend(&cp, len - cp.len);
1785         }
1786
1787         if (b->rdx > cp.rdx) bc_num_extend(&cp, b->rdx - cp.rdx);
1788         cp.rdx -= b->rdx;
1789         if (scale > cp.rdx) bc_num_extend(&cp, scale - cp.rdx);
1790
1791         if (b->rdx == b->len) {
1792                 for (i = 0; zero && i < len; ++i) zero = !b->num[len - i - 1];
1793                 len -= i - 1;
1794         }
1795
1796         if (cp.cap == cp.len) bc_num_expand(&cp, cp.len + 1);
1797
1798         // We want an extra zero in front to make things simpler.
1799         cp.num[cp.len++] = 0;
1800         end = cp.len - len;
1801
1802         bc_num_expand(c, cp.len);
1803
1804         bc_num_zero(c);
1805         memset(c->num + end, 0, (c->cap - end) * sizeof(BcDig));
1806         c->rdx = cp.rdx;
1807         c->len = cp.len;
1808         p = b->num;
1809
1810         for (i = end - 1; !s && i < end; --i) {
1811                 n = cp.num + i;
1812                 for (q = 0; (!s && n[len] != 0) || bc_num_compare(n, p, len) >= 0; ++q)
1813                         bc_num_subArrays(n, p, len);
1814                 c->num[i] = q;
1815         }
1816
1817         bc_num_retireMul(c, scale, a->neg, b->neg);
1818         bc_num_free(&cp);
1819
1820         return BC_STATUS_SUCCESS; // can't make void, see bc_num_binary()
1821 }
1822
1823 static BcStatus bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c,
1824                          BcNum *restrict d, size_t scale, size_t ts)
1825 {
1826         BcStatus s;
1827         BcNum temp;
1828         bool neg;
1829
1830         if (b->len == 0)
1831                 return bc_error("divide by zero");
1832
1833         if (a->len == 0) {
1834                 bc_num_setToZero(d, ts);
1835                 return BC_STATUS_SUCCESS;
1836         }
1837
1838         bc_num_init(&temp, d->cap);
1839         bc_num_d(a, b, c, scale);
1840
1841         if (scale != 0) scale = ts;
1842
1843         s = bc_num_m(c, b, &temp, scale);
1844         if (s) goto err;
1845         s = bc_num_sub(a, &temp, d, scale);
1846         if (s) goto err;
1847
1848         if (ts > d->rdx && d->len) bc_num_extend(d, ts - d->rdx);
1849
1850         neg = d->neg;
1851         bc_num_retireMul(d, ts, a->neg, b->neg);
1852         d->neg = neg;
1853
1854 err:
1855         bc_num_free(&temp);
1856         return s;
1857 }
1858
1859 static BcStatus bc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
1860 {
1861         BcStatus s;
1862         BcNum c1;
1863         size_t ts = BC_MAX(scale + b->rdx, a->rdx), len = BC_NUM_MREQ(a, b, ts);
1864
1865         bc_num_init(&c1, len);
1866         s = bc_num_r(a, b, &c1, c, scale, ts);
1867         bc_num_free(&c1);
1868
1869         return s;
1870 }
1871
1872 static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
1873 {
1874         BcStatus s = BC_STATUS_SUCCESS;
1875         BcNum copy;
1876         unsigned long pow;
1877         size_t i, powrdx, resrdx;
1878         bool neg, zero;
1879
1880         if (b->rdx) return bc_error("non integer number");
1881
1882         if (b->len == 0) {
1883                 bc_num_one(c);
1884                 return BC_STATUS_SUCCESS;
1885         }
1886         else if (a->len == 0) {
1887                 bc_num_setToZero(c, scale);
1888                 return BC_STATUS_SUCCESS;
1889         }
1890         else if (BC_NUM_ONE(b)) {
1891                 if (!b->neg)
1892                         bc_num_copy(c, a);
1893                 else
1894                         s = bc_num_inv(a, c, scale);
1895                 return s;
1896         }
1897
1898         neg = b->neg;
1899         b->neg = false;
1900
1901         s = bc_num_ulong(b, &pow);
1902         if (s) return s;
1903
1904         bc_num_init(&copy, a->len);
1905         bc_num_copy(&copy, a);
1906
1907         if (!neg) scale = BC_MIN(a->rdx * pow, BC_MAX(scale, a->rdx));
1908
1909         b->neg = neg;
1910
1911         for (powrdx = a->rdx; !(pow & 1); pow >>= 1) {
1912                 powrdx <<= 1;
1913                 s = bc_num_mul(&copy, &copy, &copy, powrdx);
1914                 if (s) goto err;
1915         }
1916
1917         bc_num_copy(c, &copy);
1918
1919         for (resrdx = powrdx, pow >>= 1; pow != 0; pow >>= 1) {
1920
1921                 powrdx <<= 1;
1922                 s = bc_num_mul(&copy, &copy, &copy, powrdx);
1923                 if (s) goto err;
1924
1925                 if (pow & 1) {
1926                         resrdx += powrdx;
1927                         s = bc_num_mul(c, &copy, c, resrdx);
1928                         if (s) goto err;
1929                 }
1930         }
1931
1932         if (neg) {
1933                 s = bc_num_inv(c, c, scale);
1934                 if (s) goto err;
1935         }
1936
1937         if (c->rdx > scale) bc_num_truncate(c, c->rdx - scale);
1938
1939         // We can't use bc_num_clean() here.
1940         for (zero = true, i = 0; zero && i < c->len; ++i) zero = !c->num[i];
1941         if (zero) bc_num_setToZero(c, scale);
1942
1943 err:
1944         bc_num_free(&copy);
1945         return s;
1946 }
1947
1948 static BcStatus bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
1949                               BcNumBinaryOp op, size_t req)
1950 {
1951         BcStatus s;
1952         BcNum num2, *ptr_a, *ptr_b;
1953         bool init = false;
1954
1955         if (c == a) {
1956                 ptr_a = &num2;
1957                 memcpy(ptr_a, c, sizeof(BcNum));
1958                 init = true;
1959         }
1960         else
1961                 ptr_a = a;
1962
1963         if (c == b) {
1964                 ptr_b = &num2;
1965                 if (c != a) {
1966                         memcpy(ptr_b, c, sizeof(BcNum));
1967                         init = true;
1968                 }
1969         }
1970         else
1971                 ptr_b = b;
1972
1973         if (init)
1974                 bc_num_init(c, req);
1975         else
1976                 bc_num_expand(c, req);
1977
1978         s = op(ptr_a, ptr_b, c, scale);
1979
1980         if (init) bc_num_free(&num2);
1981
1982         return s;
1983 }
1984
1985 static bool bc_num_strValid(const char *val, size_t base)
1986 {
1987         BcDig b;
1988         bool small, radix = false;
1989         size_t i, len = strlen(val);
1990
1991         if (!len) return true;
1992
1993         small = base <= 10;
1994         b = (BcDig)(small ? base + '0' : base - 10 + 'A');
1995
1996         for (i = 0; i < len; ++i) {
1997
1998                 BcDig c = val[i];
1999
2000                 if (c == '.') {
2001
2002                         if (radix) return false;
2003
2004                         radix = true;
2005                         continue;
2006                 }
2007
2008                 if (c < '0' || (small && c >= b) || (c > '9' && (c < 'A' || c >= b)))
2009                         return false;
2010         }
2011
2012         return true;
2013 }
2014
2015 static void bc_num_parseDecimal(BcNum *n, const char *val)
2016 {
2017         size_t len, i;
2018         const char *ptr;
2019         bool zero = true;
2020
2021         for (i = 0; val[i] == '0'; ++i);
2022
2023         val += i;
2024         len = strlen(val);
2025         bc_num_zero(n);
2026
2027         if (len != 0) {
2028                 for (i = 0; zero && i < len; ++i) zero = val[i] == '0' || val[i] == '.';
2029                 bc_num_expand(n, len);
2030         }
2031
2032         ptr = strchr(val, '.');
2033
2034         // Explicitly test for NULL here to produce either a 0 or 1.
2035         n->rdx = (size_t)((ptr != NULL) * ((val + len) - (ptr + 1)));
2036
2037         if (!zero) {
2038                 for (i = len - 1; i < len; ++n->len, i -= 1 + (i && val[i - 1] == '.'))
2039                         n->num[n->len] = val[i] - '0';
2040         }
2041 }
2042
2043 static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base)
2044 {
2045         BcStatus s;
2046         BcNum temp, mult, result;
2047         BcDig c = '\0';
2048         bool zero = true;
2049         unsigned long v;
2050         size_t i, digits, len = strlen(val);
2051
2052         bc_num_zero(n);
2053
2054         for (i = 0; zero && i < len; ++i) zero = (val[i] == '.' || val[i] == '0');
2055         if (zero) return;
2056
2057         bc_num_init(&temp, BC_NUM_DEF_SIZE);
2058         bc_num_init(&mult, BC_NUM_DEF_SIZE);
2059
2060         for (i = 0; i < len; ++i) {
2061
2062                 c = val[i];
2063                 if (c == '.') break;
2064
2065                 v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10);
2066
2067                 s = bc_num_mul(n, base, &mult, 0);
2068                 if (s) goto int_err;
2069                 bc_num_ulong2num(&temp, v);
2070                 s = bc_num_add(&mult, &temp, n, 0);
2071                 if (s) goto int_err;
2072         }
2073
2074         if (i == len) {
2075                 c = val[i];
2076                 if (c == 0) goto int_err;
2077         }
2078
2079         bc_num_init(&result, base->len);
2080         bc_num_zero(&result);
2081         bc_num_one(&mult);
2082
2083         for (i += 1, digits = 0; i < len; ++i, ++digits) {
2084
2085                 c = val[i];
2086                 if (c == 0) break;
2087
2088                 v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10);
2089
2090                 s = bc_num_mul(&result, base, &result, 0);
2091                 if (s) goto err;
2092                 bc_num_ulong2num(&temp, v);
2093                 s = bc_num_add(&result, &temp, &result, 0);
2094                 if (s) goto err;
2095                 s = bc_num_mul(&mult, base, &mult, 0);
2096                 if (s) goto err;
2097         }
2098
2099         s = bc_num_div(&result, &mult, &result, digits);
2100         if (s) goto err;
2101         s = bc_num_add(n, &result, n, digits);
2102         if (s) goto err;
2103
2104         if (n->len != 0) {
2105                 if (n->rdx < digits) bc_num_extend(n, digits - n->rdx);
2106         }
2107         else
2108                 bc_num_zero(n);
2109
2110 err:
2111         bc_num_free(&result);
2112 int_err:
2113         bc_num_free(&mult);
2114         bc_num_free(&temp);
2115 }
2116
2117 static void bc_num_printNewline(size_t *nchars, size_t line_len)
2118 {
2119         if (*nchars == line_len - 1) {
2120                 bb_putchar('\\');
2121                 bb_putchar('\n');
2122                 *nchars = 0;
2123         }
2124 }
2125
2126 #if ENABLE_DC
2127 static void bc_num_printChar(size_t num, size_t width, bool radix,
2128                              size_t *nchars, size_t line_len)
2129 {
2130         (void) radix, (void) line_len;
2131         bb_putchar((char) num);
2132         *nchars = *nchars + width;
2133 }
2134 #endif
2135
2136 static void bc_num_printDigits(size_t num, size_t width, bool radix,
2137                                size_t *nchars, size_t line_len)
2138 {
2139         size_t exp, pow;
2140
2141         bc_num_printNewline(nchars, line_len);
2142         bb_putchar(radix ? '.' : ' ');
2143         ++(*nchars);
2144
2145         bc_num_printNewline(nchars, line_len);
2146         for (exp = 0, pow = 1; exp < width - 1; ++exp, pow *= 10)
2147                 continue;
2148
2149         for (exp = 0; exp < width; pow /= 10, ++(*nchars), ++exp) {
2150                 size_t dig;
2151                 bc_num_printNewline(nchars, line_len);
2152                 dig = num / pow;
2153                 num -= dig * pow;
2154                 bb_putchar(((char) dig) + '0');
2155         }
2156 }
2157
2158 static void bc_num_printHex(size_t num, size_t width, bool radix,
2159                             size_t *nchars, size_t line_len)
2160 {
2161         if (radix) {
2162                 bc_num_printNewline(nchars, line_len);
2163                 bb_putchar('.');
2164                 *nchars += 1;
2165         }
2166
2167         bc_num_printNewline(nchars, line_len);
2168         bb_putchar(bb_hexdigits_upcase[num]);
2169         *nchars = *nchars + width;
2170 }
2171
2172 static void bc_num_printDecimal(BcNum *n, size_t *nchars, size_t len)
2173 {
2174         size_t i, rdx = n->rdx - 1;
2175
2176         if (n->neg) bb_putchar('-');
2177         (*nchars) += n->neg;
2178
2179         for (i = n->len - 1; i < n->len; --i)
2180                 bc_num_printHex((size_t) n->num[i], 1, i == rdx, nchars, len);
2181 }
2182
2183 static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width,
2184                                 size_t *nchars, size_t len, BcNumDigitOp print)
2185 {
2186         BcStatus s;
2187         BcVec stack;
2188         BcNum intp, fracp, digit, frac_len;
2189         unsigned long dig, *ptr;
2190         size_t i;
2191         bool radix;
2192
2193         if (n->len == 0) {
2194                 print(0, width, false, nchars, len);
2195                 return BC_STATUS_SUCCESS;
2196         }
2197
2198         bc_vec_init(&stack, sizeof(long), NULL);
2199         bc_num_init(&intp, n->len);
2200         bc_num_init(&fracp, n->rdx);
2201         bc_num_init(&digit, width);
2202         bc_num_init(&frac_len, BC_NUM_INT(n));
2203         bc_num_copy(&intp, n);
2204         bc_num_one(&frac_len);
2205
2206         bc_num_truncate(&intp, intp.rdx);
2207         s = bc_num_sub(n, &intp, &fracp, 0);
2208         if (s) goto err;
2209
2210         while (intp.len != 0) {
2211                 s = bc_num_divmod(&intp, base, &intp, &digit, 0);
2212                 if (s) goto err;
2213                 s = bc_num_ulong(&digit, &dig);
2214                 if (s) goto err;
2215                 bc_vec_push(&stack, &dig);
2216         }
2217
2218         for (i = 0; i < stack.len; ++i) {
2219                 ptr = bc_vec_item_rev(&stack, i);
2220                 print(*ptr, width, false, nchars, len);
2221         }
2222
2223         if (!n->rdx) goto err;
2224
2225         for (radix = true; frac_len.len <= n->rdx; radix = false) {
2226                 s = bc_num_mul(&fracp, base, &fracp, n->rdx);
2227                 if (s) goto err;
2228                 s = bc_num_ulong(&fracp, &dig);
2229                 if (s) goto err;
2230                 bc_num_ulong2num(&intp, dig);
2231                 s = bc_num_sub(&fracp, &intp, &fracp, 0);
2232                 if (s) goto err;
2233                 print(dig, width, radix, nchars, len);
2234                 s = bc_num_mul(&frac_len, base, &frac_len, 0);
2235                 if (s) goto err;
2236         }
2237
2238 err:
2239         bc_num_free(&frac_len);
2240         bc_num_free(&digit);
2241         bc_num_free(&fracp);
2242         bc_num_free(&intp);
2243         bc_vec_free(&stack);
2244         return s;
2245 }
2246
2247 static BcStatus bc_num_printBase(BcNum *n, BcNum *base, size_t base_t,
2248                                  size_t *nchars, size_t line_len)
2249 {
2250         BcStatus s;
2251         size_t width, i;
2252         BcNumDigitOp print;
2253         bool neg = n->neg;
2254
2255         if (neg) bb_putchar('-');
2256         (*nchars) += neg;
2257
2258         n->neg = false;
2259
2260         if (base_t <= BC_NUM_MAX_IBASE) {
2261                 width = 1;
2262                 print = bc_num_printHex;
2263         }
2264         else {
2265                 for (i = base_t - 1, width = 0; i != 0; i /= 10, ++width);
2266                 print = bc_num_printDigits;
2267         }
2268
2269         s = bc_num_printNum(n, base, width, nchars, line_len, print);
2270         n->neg = neg;
2271
2272         return s;
2273 }
2274
2275 #if ENABLE_DC
2276 static BcStatus bc_num_stream(BcNum *n, BcNum *base, size_t *nchars, size_t len)
2277 {
2278         return bc_num_printNum(n, base, 1, nchars, len, bc_num_printChar);
2279 }
2280 #endif
2281
2282 static void bc_num_init(BcNum *n, size_t req)
2283 {
2284         req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
2285         memset(n, 0, sizeof(BcNum));
2286         n->num = xmalloc(req);
2287         n->cap = req;
2288 }
2289
2290 static void bc_num_expand(BcNum *n, size_t req)
2291 {
2292         req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
2293         if (req > n->cap) {
2294                 n->num = xrealloc(n->num, req);
2295                 n->cap = req;
2296         }
2297 }
2298
2299 static void bc_num_free(void *num)
2300 {
2301         free(((BcNum *) num)->num);
2302 }
2303
2304 static void bc_num_copy(BcNum *d, BcNum *s)
2305 {
2306         if (d != s) {
2307                 bc_num_expand(d, s->cap);
2308                 d->len = s->len;
2309                 d->neg = s->neg;
2310                 d->rdx = s->rdx;
2311                 memcpy(d->num, s->num, sizeof(BcDig) * d->len);
2312         }
2313 }
2314
2315 static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base,
2316                              size_t base_t)
2317 {
2318         if (!bc_num_strValid(val, base_t))
2319                 return bc_error("bad number string");
2320
2321         if (base_t == 10)
2322                 bc_num_parseDecimal(n, val);
2323         else
2324                 bc_num_parseBase(n, val, base);
2325
2326         return BC_STATUS_SUCCESS;
2327 }
2328
2329 static BcStatus bc_num_print(BcNum *n, BcNum *base, size_t base_t, bool newline,
2330                              size_t *nchars, size_t line_len)
2331 {
2332         BcStatus s = BC_STATUS_SUCCESS;
2333
2334         bc_num_printNewline(nchars, line_len);
2335
2336         if (n->len == 0) {
2337                 bb_putchar('0');
2338                 ++(*nchars);
2339         }
2340         else if (base_t == 10)
2341                 bc_num_printDecimal(n, nchars, line_len);
2342         else
2343                 s = bc_num_printBase(n, base, base_t, nchars, line_len);
2344
2345         if (newline) {
2346                 bb_putchar('\n');
2347                 *nchars = 0;
2348         }
2349
2350         return s;
2351 }
2352
2353 static BcStatus bc_num_ulong(BcNum *n, unsigned long *result)
2354 {
2355         size_t i;
2356         unsigned long pow;
2357
2358         if (n->neg) return bc_error("negative number");
2359
2360         for (*result = 0, pow = 1, i = n->rdx; i < n->len; ++i) {
2361
2362                 unsigned long prev = *result, powprev = pow;
2363
2364                 *result += ((unsigned long) n->num[i]) * pow;
2365                 pow *= 10;
2366
2367                 if (*result < prev || pow < powprev)
2368                         return bc_error("overflow");
2369         }
2370
2371         return BC_STATUS_SUCCESS;
2372 }
2373
2374 static void bc_num_ulong2num(BcNum *n, unsigned long val)
2375 {
2376         size_t len;
2377         BcDig *ptr;
2378         unsigned long i;
2379
2380         bc_num_zero(n);
2381
2382         if (val == 0) return;
2383
2384         for (len = 1, i = ULONG_MAX; i != 0; i /= 10, ++len) bc_num_expand(n, len);
2385         for (ptr = n->num, i = 0; val; ++i, ++n->len, val /= 10) ptr[i] = val % 10;
2386 }
2387
2388 static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2389 {
2390         BcNumBinaryOp op = (!a->neg == !b->neg) ? bc_num_a : bc_num_s;
2391         (void) scale;
2392         return bc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b));
2393 }
2394
2395 static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2396 {
2397         BcNumBinaryOp op = (!a->neg == !b->neg) ? bc_num_s : bc_num_a;
2398         (void) scale;
2399         return bc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b));
2400 }
2401
2402 static BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2403 {
2404         size_t req = BC_NUM_MREQ(a, b, scale);
2405         return bc_num_binary(a, b, c, scale, bc_num_m, req);
2406 }
2407
2408 static BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2409 {
2410         size_t req = BC_NUM_MREQ(a, b, scale);
2411         return bc_num_binary(a, b, c, scale, bc_num_d, req);
2412 }
2413
2414 static BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2415 {
2416         size_t req = BC_NUM_MREQ(a, b, scale);
2417         return bc_num_binary(a, b, c, scale, bc_num_rem, req);
2418 }
2419
2420 static BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2421 {
2422         return bc_num_binary(a, b, c, scale, bc_num_p, a->len * b->len + 1);
2423 }
2424
2425 static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale)
2426 {
2427         BcStatus s;
2428         BcNum num1, num2, half, f, fprime, *x0, *x1, *temp;
2429         size_t pow, len, digs, digs1, resrdx, req, times = 0;
2430         ssize_t cmp = 1, cmp1 = SSIZE_MAX, cmp2 = SSIZE_MAX;
2431
2432         req = BC_MAX(scale, a->rdx) + ((BC_NUM_INT(a) + 1) >> 1) + 1;
2433         bc_num_expand(b, req);
2434
2435         if (a->len == 0) {
2436                 bc_num_setToZero(b, scale);
2437                 return BC_STATUS_SUCCESS;
2438         }
2439         else if (a->neg)
2440                 return bc_error("negative number");
2441         else if (BC_NUM_ONE(a)) {
2442                 bc_num_one(b);
2443                 bc_num_extend(b, scale);
2444                 return BC_STATUS_SUCCESS;
2445         }
2446
2447         scale = BC_MAX(scale, a->rdx) + 1;
2448         len = a->len + scale;
2449
2450         bc_num_init(&num1, len);
2451         bc_num_init(&num2, len);
2452         bc_num_init(&half, BC_NUM_DEF_SIZE);
2453
2454         bc_num_one(&half);
2455         half.num[0] = 5;
2456         half.rdx = 1;
2457
2458         bc_num_init(&f, len);
2459         bc_num_init(&fprime, len);
2460
2461         x0 = &num1;
2462         x1 = &num2;
2463
2464         bc_num_one(x0);
2465         pow = BC_NUM_INT(a);
2466
2467         if (pow) {
2468
2469                 if (pow & 1)
2470                         x0->num[0] = 2;
2471                 else
2472                         x0->num[0] = 6;
2473
2474                 pow -= 2 - (pow & 1);
2475
2476                 bc_num_extend(x0, pow);
2477
2478                 // Make sure to move the radix back.
2479                 x0->rdx -= pow;
2480         }
2481
2482         x0->rdx = digs = digs1 = 0;
2483         resrdx = scale + 2;
2484         len = BC_NUM_INT(x0) + resrdx - 1;
2485
2486         while (cmp != 0 || digs < len) {
2487
2488                 s = bc_num_div(a, x0, &f, resrdx);
2489                 if (s) goto err;
2490                 s = bc_num_add(x0, &f, &fprime, resrdx);
2491                 if (s) goto err;
2492                 s = bc_num_mul(&fprime, &half, x1, resrdx);
2493                 if (s) goto err;
2494
2495                 cmp = bc_num_cmp(x1, x0);
2496                 digs = x1->len - (unsigned long long) llabs(cmp);
2497
2498                 if (cmp == cmp2 && digs == digs1)
2499                         times += 1;
2500                 else
2501                         times = 0;
2502
2503                 resrdx += times > 4;
2504
2505                 cmp2 = cmp1;
2506                 cmp1 = cmp;
2507                 digs1 = digs;
2508
2509                 temp = x0;
2510                 x0 = x1;
2511                 x1 = temp;
2512         }
2513
2514         bc_num_copy(b, x0);
2515         scale -= 1;
2516         if (b->rdx > scale) bc_num_truncate(b, b->rdx - scale);
2517
2518 err:
2519         bc_num_free(&fprime);
2520         bc_num_free(&f);
2521         bc_num_free(&half);
2522         bc_num_free(&num2);
2523         bc_num_free(&num1);
2524         return s;
2525 }
2526
2527 static BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d,
2528                               size_t scale)
2529 {
2530         BcStatus s;
2531         BcNum num2, *ptr_a;
2532         bool init = false;
2533         size_t ts = BC_MAX(scale + b->rdx, a->rdx), len = BC_NUM_MREQ(a, b, ts);
2534
2535         if (c == a) {
2536                 memcpy(&num2, c, sizeof(BcNum));
2537                 ptr_a = &num2;
2538                 bc_num_init(c, len);
2539                 init = true;
2540         }
2541         else {
2542                 ptr_a = a;
2543                 bc_num_expand(c, len);
2544         }
2545
2546         s = bc_num_r(ptr_a, b, c, d, scale, ts);
2547
2548         if (init) bc_num_free(&num2);
2549
2550         return s;
2551 }
2552
2553 #if ENABLE_DC
2554 static BcStatus bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d)
2555 {
2556         BcStatus s;
2557         BcNum base, exp, two, temp;
2558
2559         if (c->len == 0)
2560                 return bc_error("divide by zero");
2561         if (a->rdx || b->rdx || c->rdx)
2562                 return bc_error("non integer number");
2563         if (b->neg)
2564                 return bc_error("negative number");
2565
2566         bc_num_expand(d, c->len);
2567         bc_num_init(&base, c->len);
2568         bc_num_init(&exp, b->len);
2569         bc_num_init(&two, BC_NUM_DEF_SIZE);
2570         bc_num_init(&temp, b->len);
2571
2572         bc_num_one(&two);
2573         two.num[0] = 2;
2574         bc_num_one(d);
2575
2576         s = bc_num_rem(a, c, &base, 0);
2577         if (s) goto err;
2578         bc_num_copy(&exp, b);
2579
2580         while (exp.len != 0) {
2581
2582                 s = bc_num_divmod(&exp, &two, &exp, &temp, 0);
2583                 if (s) goto err;
2584
2585                 if (BC_NUM_ONE(&temp)) {
2586                         s = bc_num_mul(d, &base, &temp, 0);
2587                         if (s) goto err;
2588                         s = bc_num_rem(&temp, c, d, 0);
2589                         if (s) goto err;
2590                 }
2591
2592                 s = bc_num_mul(&base, &base, &temp, 0);
2593                 if (s) goto err;
2594                 s = bc_num_rem(&temp, c, &base, 0);
2595                 if (s) goto err;
2596         }
2597
2598 err:
2599         bc_num_free(&temp);
2600         bc_num_free(&two);
2601         bc_num_free(&exp);
2602         bc_num_free(&base);
2603         return s;
2604 }
2605 #endif // ENABLE_DC
2606
2607 static int bc_id_cmp(const void *e1, const void *e2)
2608 {
2609         return strcmp(((const BcId *) e1)->name, ((const BcId *) e2)->name);
2610 }
2611
2612 static void bc_id_free(void *id)
2613 {
2614         free(((BcId *) id)->name);
2615 }
2616
2617 static BcStatus bc_func_insert(BcFunc *f, char *name, bool var)
2618 {
2619         BcId a;
2620         size_t i;
2621
2622         for (i = 0; i < f->autos.len; ++i) {
2623                 if (strcmp(name, ((BcId *) bc_vec_item(&f->autos, i))->name) == 0)
2624                         return bc_error("function parameter or auto var has the same name as another");
2625         }
2626
2627         a.idx = var;
2628         a.name = name;
2629
2630         bc_vec_push(&f->autos, &a);
2631
2632         return BC_STATUS_SUCCESS;
2633 }
2634
2635 static void bc_func_init(BcFunc *f)
2636 {
2637         bc_vec_init(&f->code, sizeof(char), NULL);
2638         bc_vec_init(&f->autos, sizeof(BcId), bc_id_free);
2639         bc_vec_init(&f->labels, sizeof(size_t), NULL);
2640         f->nparams = 0;
2641 }
2642
2643 static void bc_func_free(void *func)
2644 {
2645         BcFunc *f = (BcFunc *) func;
2646         bc_vec_free(&f->code);
2647         bc_vec_free(&f->autos);
2648         bc_vec_free(&f->labels);
2649 }
2650
2651 static void bc_array_init(BcVec *a, bool nums)
2652 {
2653         if (nums)
2654                 bc_vec_init(a, sizeof(BcNum), bc_num_free);
2655         else
2656                 bc_vec_init(a, sizeof(BcVec), bc_vec_free);
2657         bc_array_expand(a, 1);
2658 }
2659
2660 static void bc_array_copy(BcVec *d, const BcVec *s)
2661 {
2662         size_t i;
2663
2664         bc_vec_npop(d, d->len);
2665         bc_vec_expand(d, s->cap);
2666         d->len = s->len;
2667
2668         for (i = 0; i < s->len; ++i) {
2669                 BcNum *dnum = bc_vec_item(d, i), *snum = bc_vec_item(s, i);
2670                 bc_num_init(dnum, snum->len);
2671                 bc_num_copy(dnum, snum);
2672         }
2673 }
2674
2675 static void bc_array_expand(BcVec *a, size_t len)
2676 {
2677         BcResultData data;
2678
2679         if (a->size == sizeof(BcNum) && a->dtor == bc_num_free) {
2680                 while (len > a->len) {
2681                         bc_num_init(&data.n, BC_NUM_DEF_SIZE);
2682                         bc_vec_push(a, &data.n);
2683                 }
2684         }
2685         else {
2686                 while (len > a->len) {
2687                         bc_array_init(&data.v, true);
2688                         bc_vec_push(a, &data.v);
2689                 }
2690         }
2691 }
2692
2693 static void bc_string_free(void *string)
2694 {
2695         free(*((char **) string));
2696 }
2697
2698 #if ENABLE_DC
2699 static void bc_result_copy(BcResult *d, BcResult *src)
2700 {
2701         d->t = src->t;
2702
2703         switch (d->t) {
2704
2705                 case BC_RESULT_TEMP:
2706                 case BC_RESULT_IBASE:
2707                 case BC_RESULT_SCALE:
2708                 case BC_RESULT_OBASE:
2709                 {
2710                         bc_num_init(&d->d.n, src->d.n.len);
2711                         bc_num_copy(&d->d.n, &src->d.n);
2712                         break;
2713                 }
2714
2715                 case BC_RESULT_VAR:
2716                 case BC_RESULT_ARRAY:
2717                 case BC_RESULT_ARRAY_ELEM:
2718                 {
2719                         d->d.id.name = xstrdup(src->d.id.name);
2720                         break;
2721                 }
2722
2723                 case BC_RESULT_CONSTANT:
2724                 case BC_RESULT_LAST:
2725                 case BC_RESULT_ONE:
2726                 case BC_RESULT_STR:
2727                 {
2728                         memcpy(&d->d.n, &src->d.n, sizeof(BcNum));
2729                         break;
2730                 }
2731         }
2732 }
2733 #endif // ENABLE_DC
2734
2735 static void bc_result_free(void *result)
2736 {
2737         BcResult *r = (BcResult *) result;
2738
2739         switch (r->t) {
2740
2741                 case BC_RESULT_TEMP:
2742                 case BC_RESULT_IBASE:
2743                 case BC_RESULT_SCALE:
2744                 case BC_RESULT_OBASE:
2745                 {
2746                         bc_num_free(&r->d.n);
2747                         break;
2748                 }
2749
2750                 case BC_RESULT_VAR:
2751                 case BC_RESULT_ARRAY:
2752                 case BC_RESULT_ARRAY_ELEM:
2753                 {
2754                         free(r->d.id.name);
2755                         break;
2756                 }
2757
2758                 default:
2759                 {
2760                         // Do nothing.
2761                         break;
2762                 }
2763         }
2764 }
2765
2766 static void bc_lex_lineComment(BcLex *l)
2767 {
2768         l->t.t = BC_LEX_WHITESPACE;
2769         while (l->i < l->len && l->buf[l->i++] != '\n');
2770         --l->i;
2771 }
2772
2773 static void bc_lex_whitespace(BcLex *l)
2774 {
2775         char c;
2776         l->t.t = BC_LEX_WHITESPACE;
2777         for (c = l->buf[l->i]; c != '\n' && isspace(c); c = l->buf[++l->i]);
2778 }
2779
2780 static BcStatus bc_lex_number(BcLex *l, char start)
2781 {
2782         const char *buf = l->buf + l->i;
2783         size_t len, hits = 0, bslashes = 0, i = 0, j;
2784         char c = buf[i];
2785         bool last_pt, pt = start == '.';
2786
2787         last_pt = pt;
2788         l->t.t = BC_LEX_NUMBER;
2789
2790         while (c != 0 && (isdigit(c) || (c >= 'A' && c <= 'F') ||
2791                           (c == '.' && !pt) || (c == '\\' && buf[i + 1] == '\n')))
2792         {
2793                 if (c != '\\') {
2794                         last_pt = c == '.';
2795                         pt = pt || last_pt;
2796                 }
2797                 else {
2798                         ++i;
2799                         bslashes += 1;
2800                 }
2801
2802                 c = buf[++i];
2803         }
2804
2805         len = i + 1 * !last_pt - bslashes * 2;
2806         if (len > BC_MAX_NUM)
2807                 return bc_error("number too long: must be [1, BC_NUM_MAX]");
2808
2809         bc_vec_npop(&l->t.v, l->t.v.len);
2810         bc_vec_expand(&l->t.v, len + 1);
2811         bc_vec_push(&l->t.v, &start);
2812
2813         for (buf -= 1, j = 1; j < len + hits * 2; ++j) {
2814
2815                 c = buf[j];
2816
2817                 // If we have hit a backslash, skip it. We don't have
2818                 // to check for a newline because it's guaranteed.
2819                 if (hits < bslashes && c == '\\') {
2820                         ++hits;
2821                         ++j;
2822                         continue;
2823                 }
2824
2825                 bc_vec_push(&l->t.v, &c);
2826         }
2827
2828         bc_vec_pushByte(&l->t.v, '\0');
2829         l->i += i;
2830
2831         return BC_STATUS_SUCCESS;
2832 }
2833
2834 static BcStatus bc_lex_name(BcLex *l)
2835 {
2836         size_t i = 0;
2837         const char *buf = l->buf + l->i - 1;
2838         char c = buf[i];
2839
2840         l->t.t = BC_LEX_NAME;
2841
2842         while ((c >= 'a' && c <= 'z') || isdigit(c) || c == '_') c = buf[++i];
2843
2844         if (i > BC_MAX_STRING)
2845                 return bc_error("name too long: must be [1, BC_NAME_MAX]");
2846         bc_vec_string(&l->t.v, i, buf);
2847
2848         // Increment the index. We minus 1 because it has already been incremented.
2849         l->i += i - 1;
2850
2851         return BC_STATUS_SUCCESS;
2852 }
2853
2854 static void bc_lex_init(BcLex *l, BcLexNext next)
2855 {
2856         l->next = next;
2857         bc_vec_init(&l->t.v, sizeof(char), NULL);
2858 }
2859
2860 static void bc_lex_free(BcLex *l)
2861 {
2862         bc_vec_free(&l->t.v);
2863 }
2864
2865 static void bc_lex_file(BcLex *l, const char *file)
2866 {
2867         l->line = 1;
2868         l->newline = false;
2869         l->f = file;
2870 }
2871
2872 static BcStatus bc_lex_next(BcLex *l)
2873 {
2874         BcStatus s;
2875
2876         l->t.last = l->t.t;
2877         if (l->t.last == BC_LEX_EOF) return bc_error("end of file");
2878
2879         l->line += l->newline;
2880         l->t.t = BC_LEX_EOF;
2881
2882         l->newline = (l->i == l->len);
2883         if (l->newline) return BC_STATUS_SUCCESS;
2884
2885         // Loop until failure or we don't have whitespace. This
2886         // is so the parser doesn't get inundated with whitespace.
2887         do {
2888                 s = l->next(l);
2889         } while (!s && l->t.t == BC_LEX_WHITESPACE);
2890
2891         return s;
2892 }
2893
2894 static BcStatus bc_lex_text(BcLex *l, const char *text)
2895 {
2896         l->buf = text;
2897         l->i = 0;
2898         l->len = strlen(text);
2899         l->t.t = l->t.last = BC_LEX_INVALID;
2900         return bc_lex_next(l);
2901 }
2902
2903 #if ENABLE_BC
2904 static BcStatus bc_lex_identifier(BcLex *l)
2905 {
2906         BcStatus s;
2907         size_t i;
2908         const char *buf = l->buf + l->i - 1;
2909
2910         for (i = 0; i < sizeof(bc_lex_kws) / sizeof(bc_lex_kws[0]); ++i) {
2911
2912                 unsigned long len = (unsigned long) bc_lex_kws[i].len;
2913
2914                 if (strncmp(buf, bc_lex_kws[i].name, len) == 0) {
2915
2916                         l->t.t = BC_LEX_KEY_AUTO + (BcLexType) i;
2917
2918                         if (!bc_lex_kws[i].posix) {
2919                                 s = bc_posix_error("POSIX does not allow the following keyword:"); // bc_lex_kws[i].name
2920                                 if (s) return s;
2921                         }
2922
2923                         // We minus 1 because the index has already been incremented.
2924                         l->i += len - 1;
2925                         return BC_STATUS_SUCCESS;
2926                 }
2927         }
2928
2929         s = bc_lex_name(l);
2930         if (s) return s;
2931
2932         if (l->t.v.len - 1 > 1)
2933                 s = bc_posix_error("POSIX only allows one character names; the following is bad:"); // buf
2934
2935         return s;
2936 }
2937
2938 static BcStatus bc_lex_string(BcLex *l)
2939 {
2940         size_t len, nls = 0, i = l->i;
2941         char c;
2942
2943         l->t.t = BC_LEX_STR;
2944
2945         for (c = l->buf[i]; c != 0 && c != '"'; c = l->buf[++i]) nls += (c == '\n');
2946
2947         if (c == '\0') {
2948                 l->i = i;
2949                 return bc_error("string end could not be found");
2950         }
2951
2952         len = i - l->i;
2953         if (len > BC_MAX_STRING)
2954                 return bc_error("string too long: must be [1, BC_STRING_MAX]");
2955         bc_vec_string(&l->t.v, len, l->buf + l->i);
2956
2957         l->i = i + 1;
2958         l->line += nls;
2959
2960         return BC_STATUS_SUCCESS;
2961 }
2962
2963 static void bc_lex_assign(BcLex *l, BcLexType with, BcLexType without)
2964 {
2965         if (l->buf[l->i] == '=') {
2966                 ++l->i;
2967                 l->t.t = with;
2968         }
2969         else
2970                 l->t.t = without;
2971 }
2972
2973 static BcStatus bc_lex_comment(BcLex *l)
2974 {
2975         size_t i, nls = 0;
2976         const char *buf = l->buf;
2977
2978         l->t.t = BC_LEX_WHITESPACE;
2979         i = ++l->i;
2980         for (;;) {
2981                 char c = buf[i];
2982  check_star:
2983                 if (c == '*') {
2984                         c = buf[++i];
2985                         if (c == '/')
2986                                 break;
2987                         goto check_star;
2988                 }
2989                 if (c == '\0') {
2990                         l->i = i;
2991                         return bc_error("comment end could not be found");
2992                 }
2993                 nls += (c == '\n');
2994                 i++;
2995         }
2996
2997         l->i = i + 1;
2998         l->line += nls;
2999
3000         return BC_STATUS_SUCCESS;
3001 }
3002
3003 static BcStatus bc_lex_token(BcLex *l)
3004 {
3005         BcStatus s = BC_STATUS_SUCCESS;
3006         char c = l->buf[l->i++], c2;
3007
3008         // This is the workhorse of the lexer.
3009         switch (c) {
3010
3011                 case '\0':
3012                 case '\n':
3013                 {
3014                         l->newline = true;
3015                         l->t.t = !c ? BC_LEX_EOF : BC_LEX_NLINE;
3016                         break;
3017                 }
3018
3019                 case '\t':
3020                 case '\v':
3021                 case '\f':
3022                 case '\r':
3023                 case ' ':
3024                 {
3025                         bc_lex_whitespace(l);
3026                         break;
3027                 }
3028
3029                 case '!':
3030                 {
3031                         bc_lex_assign(l, BC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT);
3032
3033                         if (l->t.t == BC_LEX_OP_BOOL_NOT) {
3034                                 s = bc_posix_error("POSIX does not allow boolean operators; the following is bad:"); // "!"
3035                                 if (s) return s;
3036                         }
3037
3038                         break;
3039                 }
3040
3041                 case '"':
3042                 {
3043                         s = bc_lex_string(l);
3044                         break;
3045                 }
3046
3047                 case '#':
3048                 {
3049                         s = bc_posix_error("POSIX does not allow '#' script comments");
3050                         if (s) return s;
3051
3052                         bc_lex_lineComment(l);
3053
3054                         break;
3055                 }
3056
3057                 case '%':
3058                 {
3059                         bc_lex_assign(l, BC_LEX_OP_ASSIGN_MODULUS, BC_LEX_OP_MODULUS);
3060                         break;
3061                 }
3062
3063                 case '&':
3064                 {
3065                         c2 = l->buf[l->i];
3066                         if (c2 == '&') {
3067
3068                                 s = bc_posix_error("POSIX does not allow boolean operators; the following is bad:"); // "&&"
3069                                 if (s) return s;
3070
3071                                 ++l->i;
3072                                 l->t.t = BC_LEX_OP_BOOL_AND;
3073                         }
3074                         else {
3075                                 l->t.t = BC_LEX_INVALID;
3076                                 s = bc_error("bad character '%c'", '&');
3077                         }
3078
3079                         break;
3080                 }
3081
3082                 case '(':
3083                 case ')':
3084                 {
3085                         l->t.t = (BcLexType)(c - '(' + BC_LEX_LPAREN);
3086                         break;
3087                 }
3088
3089                 case '*':
3090                 {
3091                         bc_lex_assign(l, BC_LEX_OP_ASSIGN_MULTIPLY, BC_LEX_OP_MULTIPLY);
3092                         break;
3093                 }
3094
3095                 case '+':
3096                 {
3097                         c2 = l->buf[l->i];
3098                         if (c2 == '+') {
3099                                 ++l->i;
3100                                 l->t.t = BC_LEX_OP_INC;
3101                         }
3102                         else
3103                                 bc_lex_assign(l, BC_LEX_OP_ASSIGN_PLUS, BC_LEX_OP_PLUS);
3104                         break;
3105                 }
3106
3107                 case ',':
3108                 {
3109                         l->t.t = BC_LEX_COMMA;
3110                         break;
3111                 }
3112
3113                 case '-':
3114                 {
3115                         c2 = l->buf[l->i];
3116                         if (c2 == '-') {
3117                                 ++l->i;
3118                                 l->t.t = BC_LEX_OP_DEC;
3119                         }
3120                         else
3121                                 bc_lex_assign(l, BC_LEX_OP_ASSIGN_MINUS, BC_LEX_OP_MINUS);
3122                         break;
3123                 }
3124
3125                 case '.':
3126                 {
3127                         if (isdigit(l->buf[l->i]))
3128                                 s = bc_lex_number(l, c);
3129                         else {
3130                                 l->t.t = BC_LEX_KEY_LAST;
3131                                 s = bc_posix_error("POSIX does not allow a period ('.') as a shortcut for the last result");
3132                         }
3133                         break;
3134                 }
3135
3136                 case '/':
3137                 {
3138                         c2 = l->buf[l->i];
3139                         if (c2 == '*')
3140                                 s = bc_lex_comment(l);
3141                         else
3142                                 bc_lex_assign(l, BC_LEX_OP_ASSIGN_DIVIDE, BC_LEX_OP_DIVIDE);
3143                         break;
3144                 }
3145
3146                 case '0':
3147                 case '1':
3148                 case '2':
3149                 case '3':
3150                 case '4':
3151                 case '5':
3152                 case '6':
3153                 case '7':
3154                 case '8':
3155                 case '9':
3156                 case 'A':
3157                 case 'B':
3158                 case 'C':
3159                 case 'D':
3160                 case 'E':
3161                 case 'F':
3162                 {
3163                         s = bc_lex_number(l, c);
3164                         break;
3165                 }
3166
3167                 case ';':
3168                 {
3169                         l->t.t = BC_LEX_SCOLON;
3170                         break;
3171                 }
3172
3173                 case '<':
3174                 {
3175                         bc_lex_assign(l, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_LT);
3176                         break;
3177                 }
3178
3179                 case '=':
3180                 {
3181                         bc_lex_assign(l, BC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN);
3182                         break;
3183                 }
3184
3185                 case '>':
3186                 {
3187                         bc_lex_assign(l, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_GT);
3188                         break;
3189                 }
3190
3191                 case '[':
3192                 case ']':
3193                 {
3194                         l->t.t = (BcLexType)(c - '[' + BC_LEX_LBRACKET);
3195                         break;
3196                 }
3197
3198                 case '\\':
3199                 {
3200                         if (l->buf[l->i] == '\n') {
3201                                 l->t.t = BC_LEX_WHITESPACE;
3202                                 ++l->i;
3203                         }
3204                         else
3205                                 s = bc_error("bad character '%c'", c);
3206                         break;
3207                 }
3208
3209                 case '^':
3210                 {
3211                         bc_lex_assign(l, BC_LEX_OP_ASSIGN_POWER, BC_LEX_OP_POWER);
3212                         break;
3213                 }
3214
3215                 case 'a':
3216                 case 'b':
3217                 case 'c':
3218                 case 'd':
3219                 case 'e':
3220                 case 'f':
3221                 case 'g':
3222                 case 'h':
3223                 case 'i':
3224                 case 'j':
3225                 case 'k':
3226                 case 'l':
3227                 case 'm':
3228                 case 'n':
3229                 case 'o':
3230                 case 'p':
3231                 case 'q':
3232                 case 'r':
3233                 case 's':
3234                 case 't':
3235                 case 'u':
3236                 case 'v':
3237                 case 'w':
3238                 case 'x':
3239                 case 'y':
3240                 case 'z':
3241                 {
3242                         s = bc_lex_identifier(l);
3243                         break;
3244                 }
3245
3246                 case '{':
3247                 case '}':
3248                 {
3249                         l->t.t = (BcLexType)(c - '{' + BC_LEX_LBRACE);
3250                         break;
3251                 }
3252
3253                 case '|':
3254                 {
3255                         c2 = l->buf[l->i];
3256
3257                         if (c2 == '|') {
3258                                 s = bc_posix_error("POSIX does not allow boolean operators; the following is bad:"); // "||"
3259                                 if (s) return s;
3260
3261                                 ++l->i;
3262                                 l->t.t = BC_LEX_OP_BOOL_OR;
3263                         }
3264                         else {
3265                                 l->t.t = BC_LEX_INVALID;
3266                                 s = bc_error("bad character '%c'", c);
3267                         }
3268
3269                         break;
3270                 }
3271
3272                 default:
3273                 {
3274                         l->t.t = BC_LEX_INVALID;
3275                         s = bc_error("bad character '%c'", c);
3276                         break;
3277                 }
3278         }
3279
3280         return s;
3281 }
3282 #endif // ENABLE_BC
3283
3284 #if ENABLE_DC
3285 static BcStatus dc_lex_register(BcLex *l)
3286 {
3287         BcStatus s = BC_STATUS_SUCCESS;
3288
3289         if (isspace(l->buf[l->i - 1])) {
3290                 bc_lex_whitespace(l);
3291                 ++l->i;
3292                 if (!G_exreg)
3293                         s = bc_error("extended register");
3294                 else
3295                         s = bc_lex_name(l);
3296         }
3297         else {
3298                 bc_vec_npop(&l->t.v, l->t.v.len);
3299                 bc_vec_pushByte(&l->t.v, l->buf[l->i - 1]);
3300                 bc_vec_pushByte(&l->t.v, '\0');
3301                 l->t.t = BC_LEX_NAME;
3302         }
3303
3304         return s;
3305 }
3306
3307 static BcStatus dc_lex_string(BcLex *l)
3308 {
3309         size_t depth = 1, nls = 0, i = l->i;
3310         char c;
3311
3312         l->t.t = BC_LEX_STR;
3313         bc_vec_npop(&l->t.v, l->t.v.len);
3314
3315         for (c = l->buf[i]; c != 0 && depth; c = l->buf[++i]) {
3316
3317                 depth += (c == '[' && (i == l->i || l->buf[i - 1] != '\\'));
3318                 depth -= (c == ']' && (i == l->i || l->buf[i - 1] != '\\'));
3319                 nls += (c == '\n');
3320
3321                 if (depth) bc_vec_push(&l->t.v, &c);
3322         }
3323
3324         if (c == '\0') {
3325                 l->i = i;
3326                 return bc_error("string end could not be found");
3327         }
3328
3329         bc_vec_pushByte(&l->t.v, '\0');
3330         if (i - l->i > BC_MAX_STRING)
3331                 return bc_error("string too long: must be [1, BC_STRING_MAX]");
3332
3333         l->i = i;
3334         l->line += nls;
3335
3336         return BC_STATUS_SUCCESS;
3337 }
3338
3339 static BcStatus dc_lex_token(BcLex *l)
3340 {
3341         BcStatus s = BC_STATUS_SUCCESS;
3342         char c = l->buf[l->i++], c2;
3343         size_t i;
3344
3345         for (i = 0; i < dc_lex_regs_len; ++i) {
3346                 if (l->t.last == dc_lex_regs[i]) return dc_lex_register(l);
3347         }
3348
3349         if (c >= '%' && c <= '~' &&
3350             (l->t.t = dc_lex_tokens[(c - '%')]) != BC_LEX_INVALID)
3351         {
3352                 return s;
3353         }
3354
3355         // This is the workhorse of the lexer.
3356         switch (c) {
3357
3358                 case '\0':
3359                 {
3360                         l->t.t = BC_LEX_EOF;
3361                         break;
3362                 }
3363
3364                 case '\n':
3365                 case '\t':
3366                 case '\v':
3367                 case '\f':
3368                 case '\r':
3369                 case ' ':
3370                 {
3371                         l->newline = (c == '\n');
3372                         bc_lex_whitespace(l);
3373                         break;
3374                 }
3375
3376                 case '!':
3377                 {
3378                         c2 = l->buf[l->i];
3379
3380                         if (c2 == '=')
3381                                 l->t.t = BC_LEX_OP_REL_NE;
3382                         else if (c2 == '<')
3383                                 l->t.t = BC_LEX_OP_REL_LE;
3384                         else if (c2 == '>')
3385                                 l->t.t = BC_LEX_OP_REL_GE;
3386                         else
3387                                 return bc_error("bad character '%c'", c);
3388
3389                         ++l->i;
3390                         break;
3391                 }
3392
3393                 case '#':
3394                 {
3395                         bc_lex_lineComment(l);
3396                         break;
3397                 }
3398
3399                 case '.':
3400                 {
3401                         if (isdigit(l->buf[l->i]))
3402                                 s = bc_lex_number(l, c);
3403                         else
3404                                 s = bc_error("bad character '%c'", c);
3405                         break;
3406                 }
3407
3408                 case '0':
3409                 case '1':
3410                 case '2':
3411                 case '3':
3412                 case '4':
3413                 case '5':
3414                 case '6':
3415                 case '7':
3416                 case '8':
3417                 case '9':
3418                 case 'A':
3419                 case 'B':
3420                 case 'C':
3421                 case 'D':
3422                 case 'E':
3423                 case 'F':
3424                 {
3425                         s = bc_lex_number(l, c);
3426                         break;
3427                 }
3428
3429                 case '[':
3430                 {
3431                         s = dc_lex_string(l);
3432                         break;
3433                 }
3434
3435                 default:
3436                 {
3437                         l->t.t = BC_LEX_INVALID;
3438                         s = bc_error("bad character '%c'", c);
3439                         break;
3440                 }
3441         }
3442
3443         return s;
3444 }
3445 #endif // ENABLE_DC
3446
3447 static void bc_parse_addFunc(BcParse *p, char *name, size_t *idx)
3448 {
3449         bc_program_addFunc(name, idx);
3450         p->func = bc_vec_item(&G.prog.fns, p->fidx);
3451 }
3452
3453 static void bc_parse_pushName(BcParse *p, char *name)
3454 {
3455         size_t i = 0, len = strlen(name);
3456
3457         for (; i < len; ++i) bc_parse_push(p, name[i]);
3458         bc_parse_push(p, BC_PARSE_STREND);
3459
3460         free(name);
3461 }
3462
3463 static void bc_parse_pushIndex(BcParse *p, size_t idx)
3464 {
3465         unsigned char amt, i, nums[sizeof(size_t)];
3466
3467         for (amt = 0; idx; ++amt) {
3468                 nums[amt] = (char) idx;
3469                 idx = (idx & ((unsigned long) ~(UCHAR_MAX))) >> sizeof(char) * CHAR_BIT;
3470         }
3471
3472         bc_parse_push(p, amt);
3473         for (i = 0; i < amt; ++i) bc_parse_push(p, nums[i]);
3474 }
3475
3476 static void bc_parse_number(BcParse *p, BcInst *prev, size_t *nexs)
3477 {
3478         char *num = xstrdup(p->l.t.v.v);
3479         size_t idx = G.prog.consts.len;
3480
3481         bc_vec_push(&G.prog.consts, &num);
3482
3483         bc_parse_push(p, BC_INST_NUM);
3484         bc_parse_pushIndex(p, idx);
3485
3486         ++(*nexs);
3487         (*prev) = BC_INST_NUM;
3488 }
3489
3490 static BcStatus bc_parse_text(BcParse *p, const char *text)
3491 {
3492         BcStatus s;
3493
3494         p->func = bc_vec_item(&G.prog.fns, p->fidx);
3495
3496         if (!text[0] && !BC_PARSE_CAN_EXEC(p)) {
3497                 p->l.t.t = BC_LEX_INVALID;
3498                 s = p->parse(p);
3499                 if (s) return s;
3500                 if (!BC_PARSE_CAN_EXEC(p))
3501                         return bc_error("file is not executable");
3502         }
3503
3504         return bc_lex_text(&p->l, text);
3505 }
3506
3507 // Called when bc/dc_parse_parse() detects a failure,
3508 // resets parsing structures.
3509 static void bc_parse_reset(BcParse *p)
3510 {
3511         if (p->fidx != BC_PROG_MAIN) {
3512
3513                 p->func->nparams = 0;
3514                 bc_vec_npop(&p->func->code, p->func->code.len);
3515                 bc_vec_npop(&p->func->autos, p->func->autos.len);
3516                 bc_vec_npop(&p->func->labels, p->func->labels.len);
3517
3518                 bc_parse_updateFunc(p, BC_PROG_MAIN);
3519         }
3520
3521         p->l.i = p->l.len;
3522         p->l.t.t = BC_LEX_EOF;
3523         p->auto_part = (p->nbraces = 0);
3524
3525         bc_vec_npop(&p->flags, p->flags.len - 1);
3526         bc_vec_npop(&p->exits, p->exits.len);
3527         bc_vec_npop(&p->conds, p->conds.len);
3528         bc_vec_npop(&p->ops, p->ops.len);
3529
3530         bc_program_reset();
3531 }
3532
3533 static void bc_parse_free(BcParse *p)
3534 {
3535         bc_vec_free(&p->flags);
3536         bc_vec_free(&p->exits);
3537         bc_vec_free(&p->conds);
3538         bc_vec_free(&p->ops);
3539         bc_lex_free(&p->l);
3540 }
3541
3542 static void bc_parse_create(BcParse *p, size_t func,
3543                             BcParseParse parse, BcLexNext next)
3544 {
3545         memset(p, 0, sizeof(BcParse));
3546
3547         bc_lex_init(&p->l, next);
3548         bc_vec_init(&p->flags, sizeof(uint8_t), NULL);
3549         bc_vec_init(&p->exits, sizeof(BcInstPtr), NULL);
3550         bc_vec_init(&p->conds, sizeof(size_t), NULL);
3551         bc_vec_pushByte(&p->flags, 0);
3552         bc_vec_init(&p->ops, sizeof(BcLexType), NULL);
3553
3554         p->parse = parse;
3555         // p->auto_part = p->nbraces = 0; - already is
3556         bc_parse_updateFunc(p, func);
3557 }
3558
3559 #if ENABLE_BC
3560 static BcStatus bc_parse_else(BcParse *p);
3561 static BcStatus bc_parse_stmt(BcParse *p);
3562
3563 static BcStatus bc_parse_operator(BcParse *p, BcLexType type, size_t start,
3564                                   size_t *nexprs, bool next)
3565 {
3566         BcStatus s = BC_STATUS_SUCCESS;
3567         BcLexType t;
3568         char l, r = bc_parse_ops[type - BC_LEX_OP_INC].prec;
3569         bool left = bc_parse_ops[type - BC_LEX_OP_INC].left;
3570
3571         while (p->ops.len > start) {
3572
3573                 t = BC_PARSE_TOP_OP(p);
3574                 if (t == BC_LEX_LPAREN) break;
3575
3576                 l = bc_parse_ops[t - BC_LEX_OP_INC].prec;
3577                 if (l >= r && (l != r || !left)) break;
3578
3579                 bc_parse_push(p, BC_PARSE_TOKEN_INST(t));
3580                 bc_vec_pop(&p->ops);
3581                 *nexprs -= t != BC_LEX_OP_BOOL_NOT && t != BC_LEX_NEG;
3582         }
3583
3584         bc_vec_push(&p->ops, &type);
3585         if (next) s = bc_lex_next(&p->l);
3586
3587         return s;
3588 }
3589
3590 static BcStatus bc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs)
3591 {
3592         BcLexType top;
3593
3594         if (p->ops.len <= ops_bgn)
3595                 return bc_error("bad expression");
3596         top = BC_PARSE_TOP_OP(p);
3597
3598         while (top != BC_LEX_LPAREN) {
3599
3600                 bc_parse_push(p, BC_PARSE_TOKEN_INST(top));
3601
3602                 bc_vec_pop(&p->ops);
3603                 *nexs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG;
3604
3605                 if (p->ops.len <= ops_bgn)
3606                         return bc_error("bad expression");
3607                 top = BC_PARSE_TOP_OP(p);
3608         }
3609
3610         bc_vec_pop(&p->ops);
3611
3612         return bc_lex_next(&p->l);
3613 }
3614
3615 static BcStatus bc_parse_params(BcParse *p, uint8_t flags)
3616 {
3617         BcStatus s;
3618         bool comma = false;
3619         size_t nparams;
3620
3621         s = bc_lex_next(&p->l);
3622         if (s) return s;
3623
3624         for (nparams = 0; p->l.t.t != BC_LEX_RPAREN; ++nparams) {
3625
3626                 flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY;
3627                 s = bc_parse_expr(p, flags, bc_parse_next_param);
3628                 if (s) return s;
3629
3630                 comma = p->l.t.t == BC_LEX_COMMA;
3631                 if (comma) {
3632                         s = bc_lex_next(&p->l);
3633                         if (s) return s;
3634                 }
3635         }
3636
3637         if (comma) return bc_error("bad token");
3638         bc_parse_push(p, BC_INST_CALL);
3639         bc_parse_pushIndex(p, nparams);
3640
3641         return BC_STATUS_SUCCESS;
3642 }
3643
3644 static BcStatus bc_parse_call(BcParse *p, char *name, uint8_t flags)
3645 {
3646         BcStatus s;
3647         BcId entry, *entry_ptr;
3648         size_t idx;
3649
3650         entry.name = name;
3651
3652         s = bc_parse_params(p, flags);
3653         if (s) goto err;
3654
3655         if (p->l.t.t != BC_LEX_RPAREN) {
3656                 s = bc_error("bad token");
3657                 goto err;
3658         }
3659
3660         idx = bc_map_index(&G.prog.fn_map, &entry);
3661
3662         if (idx == BC_VEC_INVALID_IDX) {
3663                 name = xstrdup(entry.name);
3664                 bc_parse_addFunc(p, name, &idx);
3665                 idx = bc_map_index(&G.prog.fn_map, &entry);
3666                 free(entry.name);
3667         }
3668         else
3669                 free(name);
3670
3671         entry_ptr = bc_vec_item(&G.prog.fn_map, idx);
3672         bc_parse_pushIndex(p, entry_ptr->idx);
3673
3674         return bc_lex_next(&p->l);
3675
3676 err:
3677         free(name);
3678         return s;
3679 }
3680
3681 static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags)
3682 {
3683         BcStatus s;
3684         char *name;
3685
3686         name = xstrdup(p->l.t.v.v);
3687         s = bc_lex_next(&p->l);
3688         if (s) goto err;
3689
3690         if (p->l.t.t == BC_LEX_LBRACKET) {
3691
3692                 s = bc_lex_next(&p->l);
3693                 if (s) goto err;
3694
3695                 if (p->l.t.t == BC_LEX_RBRACKET) {
3696
3697                         if (!(flags & BC_PARSE_ARRAY)) {
3698                                 s = bc_error("bad expression");
3699                                 goto err;
3700                         }
3701
3702                         *type = BC_INST_ARRAY;
3703                 }
3704                 else {
3705
3706                         *type = BC_INST_ARRAY_ELEM;
3707
3708                         flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
3709                         s = bc_parse_expr(p, flags, bc_parse_next_elem);
3710                         if (s) goto err;
3711                 }
3712
3713                 s = bc_lex_next(&p->l);
3714                 if (s) goto err;
3715                 bc_parse_push(p, *type);
3716                 bc_parse_pushName(p, name);
3717         }
3718         else if (p->l.t.t == BC_LEX_LPAREN) {
3719
3720                 if (flags & BC_PARSE_NOCALL) {
3721                         s = bc_error("bad token");
3722                         goto err;
3723                 }
3724
3725                 *type = BC_INST_CALL;
3726                 s = bc_parse_call(p, name, flags);
3727         }
3728         else {
3729                 *type = BC_INST_VAR;
3730                 bc_parse_push(p, BC_INST_VAR);
3731                 bc_parse_pushName(p, name);
3732         }
3733
3734         return s;
3735
3736 err:
3737         free(name);
3738         return s;
3739 }
3740
3741 static BcStatus bc_parse_read(BcParse *p)
3742 {
3743         BcStatus s;
3744
3745         s = bc_lex_next(&p->l);
3746         if (s) return s;
3747         if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token");
3748
3749         s = bc_lex_next(&p->l);
3750         if (s) return s;
3751         if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token");
3752
3753         bc_parse_push(p, BC_INST_READ);
3754
3755         return bc_lex_next(&p->l);
3756 }
3757
3758 static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags,
3759                                  BcInst *prev)
3760 {
3761         BcStatus s;
3762
3763         s = bc_lex_next(&p->l);
3764         if (s) return s;
3765         if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token");
3766
3767         flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY;
3768
3769         s = bc_lex_next(&p->l);
3770         if (s) return s;
3771
3772         s = bc_parse_expr(p, flags, bc_parse_next_rel);
3773         if (s) return s;
3774
3775         if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token");
3776
3777         *prev = (type == BC_LEX_KEY_LENGTH) ? BC_INST_LENGTH : BC_INST_SQRT;
3778         bc_parse_push(p, *prev);
3779
3780         return bc_lex_next(&p->l);
3781 }
3782
3783 static BcStatus bc_parse_scale(BcParse *p, BcInst *type, uint8_t flags)
3784 {
3785         BcStatus s;
3786
3787         s = bc_lex_next(&p->l);
3788         if (s) return s;
3789
3790         if (p->l.t.t != BC_LEX_LPAREN) {
3791                 *type = BC_INST_SCALE;
3792                 bc_parse_push(p, BC_INST_SCALE);
3793                 return BC_STATUS_SUCCESS;
3794         }
3795
3796         *type = BC_INST_SCALE_FUNC;
3797         flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
3798
3799         s = bc_lex_next(&p->l);
3800         if (s) return s;
3801
3802         s = bc_parse_expr(p, flags, bc_parse_next_rel);
3803         if (s) return s;
3804         if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token");
3805         bc_parse_push(p, BC_INST_SCALE_FUNC);
3806
3807         return bc_lex_next(&p->l);
3808 }
3809
3810 static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr,
3811                                 size_t *nexprs, uint8_t flags)
3812 {
3813         BcStatus s;
3814         BcLexType type;
3815         char inst;
3816         BcInst etype = *prev;
3817
3818         if (etype == BC_INST_VAR || etype == BC_INST_ARRAY_ELEM ||
3819             etype == BC_INST_SCALE || etype == BC_INST_LAST ||
3820             etype == BC_INST_IBASE || etype == BC_INST_OBASE)
3821         {
3822                 *prev = inst = BC_INST_INC_POST + (p->l.t.t != BC_LEX_OP_INC);
3823                 bc_parse_push(p, inst);
3824                 s = bc_lex_next(&p->l);
3825         }
3826         else {
3827
3828                 *prev = inst = BC_INST_INC_PRE + (p->l.t.t != BC_LEX_OP_INC);
3829                 *paren_expr = true;
3830
3831                 s = bc_lex_next(&p->l);
3832                 if (s) return s;
3833                 type = p->l.t.t;
3834
3835                 // Because we parse the next part of the expression
3836                 // right here, we need to increment this.
3837                 *nexprs = *nexprs + 1;
3838
3839                 switch (type) {
3840
3841                         case BC_LEX_NAME:
3842                         {
3843                                 s = bc_parse_name(p, prev, flags | BC_PARSE_NOCALL);
3844                                 break;
3845                         }
3846
3847                         case BC_LEX_KEY_IBASE:
3848                         case BC_LEX_KEY_LAST:
3849                         case BC_LEX_KEY_OBASE:
3850                         {
3851                                 bc_parse_push(p, type - BC_LEX_KEY_IBASE + BC_INST_IBASE);
3852                                 s = bc_lex_next(&p->l);
3853                                 break;
3854                         }
3855
3856                         case BC_LEX_KEY_SCALE:
3857                         {
3858                                 s = bc_lex_next(&p->l);
3859                                 if (s) return s;
3860                                 if (p->l.t.t == BC_LEX_LPAREN)
3861                                         s = bc_error("bad token");
3862                                 else
3863                                         bc_parse_push(p, BC_INST_SCALE);
3864                                 break;
3865                         }
3866
3867                         default:
3868                         {
3869                                 s = bc_error("bad token");
3870                                 break;
3871                         }
3872                 }
3873
3874                 if (!s) bc_parse_push(p, inst);
3875         }
3876
3877         return s;
3878 }
3879
3880 static BcStatus bc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn,
3881                                bool rparen, size_t *nexprs)
3882 {
3883         BcStatus s;
3884         BcLexType type;
3885         BcInst etype = *prev;
3886
3887         s = bc_lex_next(&p->l);
3888         if (s) return s;
3889
3890         type = rparen || etype == BC_INST_INC_POST || etype == BC_INST_DEC_POST ||
3891                        (etype >= BC_INST_NUM && etype <= BC_INST_SQRT) ?
3892                    BC_LEX_OP_MINUS :
3893                    BC_LEX_NEG;
3894         *prev = BC_PARSE_TOKEN_INST(type);
3895
3896         // We can just push onto the op stack because this is the largest
3897         // precedence operator that gets pushed. Inc/dec does not.
3898         if (type != BC_LEX_OP_MINUS)
3899                 bc_vec_push(&p->ops, &type);
3900         else
3901                 s = bc_parse_operator(p, type, ops_bgn, nexprs, false);
3902
3903         return s;
3904 }
3905
3906 static BcStatus bc_parse_string(BcParse *p, char inst)
3907 {
3908         char *str = xstrdup(p->l.t.v.v);
3909
3910         bc_parse_push(p, BC_INST_STR);
3911         bc_parse_pushIndex(p, G.prog.strs.len);
3912         bc_vec_push(&G.prog.strs, &str);
3913         bc_parse_push(p, inst);
3914
3915         return bc_lex_next(&p->l);
3916 }
3917
3918 static BcStatus bc_parse_print(BcParse *p)
3919 {
3920         BcStatus s;
3921         BcLexType type;
3922         bool comma = false;
3923
3924         s = bc_lex_next(&p->l);
3925         if (s) return s;
3926
3927         type = p->l.t.t;
3928
3929         if (type == BC_LEX_SCOLON || type == BC_LEX_NLINE)
3930                 return bc_error("bad print statement");
3931
3932         while (!s && type != BC_LEX_SCOLON && type != BC_LEX_NLINE) {
3933
3934                 if (type == BC_LEX_STR)
3935                         s = bc_parse_string(p, BC_INST_PRINT_POP);
3936                 else {
3937                         s = bc_parse_expr(p, 0, bc_parse_next_print);
3938                         if (s) return s;
3939                         bc_parse_push(p, BC_INST_PRINT_POP);
3940                 }
3941
3942                 if (s) return s;
3943
3944                 comma = p->l.t.t == BC_LEX_COMMA;
3945                 if (comma) s = bc_lex_next(&p->l);
3946                 type = p->l.t.t;
3947         }
3948
3949         if (s) return s;
3950         if (comma) return bc_error("bad token");
3951
3952         return bc_lex_next(&p->l);
3953 }
3954
3955 static BcStatus bc_parse_return(BcParse *p)
3956 {
3957         BcStatus s;
3958         BcLexType t;
3959         bool paren;
3960
3961         if (!BC_PARSE_FUNC(p)) return bc_error("bad token");
3962
3963         s = bc_lex_next(&p->l);
3964         if (s) return s;
3965
3966         t = p->l.t.t;
3967         paren = t == BC_LEX_LPAREN;
3968
3969         if (t == BC_LEX_NLINE || t == BC_LEX_SCOLON)
3970                 bc_parse_push(p, BC_INST_RET0);
3971         else {
3972
3973                 s = bc_parse_expr(p, 0, bc_parse_next_expr);
3974                 if (s && s != BC_STATUS_PARSE_EMPTY_EXP)
3975                         return s;
3976
3977                 if (s == BC_STATUS_PARSE_EMPTY_EXP) {
3978                         bc_parse_push(p, BC_INST_RET0);
3979                         s = bc_lex_next(&p->l);
3980                         if (s) return s;
3981                 }
3982
3983                 if (!paren || p->l.t.last != BC_LEX_RPAREN) {
3984                         s = bc_posix_error("POSIX requires parentheses around return expressions");
3985                         if (s) return s;
3986                 }
3987
3988                 bc_parse_push(p, BC_INST_RET);
3989         }
3990
3991         return s;
3992 }
3993
3994 static BcStatus bc_parse_endBody(BcParse *p, bool brace)
3995 {
3996         BcStatus s = BC_STATUS_SUCCESS;
3997
3998         if (p->flags.len <= 1 || (brace && p->nbraces == 0))
3999                 return bc_error("bad token");
4000
4001         if (brace) {
4002
4003                 if (p->l.t.t == BC_LEX_RBRACE) {
4004                         if (!p->nbraces) return bc_error("bad token");
4005                         --p->nbraces;
4006                         s = bc_lex_next(&p->l);
4007                         if (s) return s;
4008                 }
4009                 else
4010                         return bc_error("bad token");
4011         }
4012
4013         if (BC_PARSE_IF(p)) {
4014
4015                 uint8_t *flag_ptr;
4016
4017                 while (p->l.t.t == BC_LEX_NLINE) {
4018                         s = bc_lex_next(&p->l);
4019                         if (s) return s;
4020                 }
4021
4022                 bc_vec_pop(&p->flags);
4023
4024                 flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
4025                 *flag_ptr = (*flag_ptr | BC_PARSE_FLAG_IF_END);
4026
4027                 if (p->l.t.t == BC_LEX_KEY_ELSE) s = bc_parse_else(p);
4028         }
4029         else if (BC_PARSE_ELSE(p)) {
4030
4031                 BcInstPtr *ip;
4032                 size_t *label;
4033
4034                 bc_vec_pop(&p->flags);
4035
4036                 ip = bc_vec_top(&p->exits);
4037                 label = bc_vec_item(&p->func->labels, ip->idx);
4038                 *label = p->func->code.len;
4039
4040                 bc_vec_pop(&p->exits);
4041         }
4042         else if (BC_PARSE_FUNC_INNER(p)) {
4043                 bc_parse_push(p, BC_INST_RET0);
4044                 bc_parse_updateFunc(p, BC_PROG_MAIN);
4045                 bc_vec_pop(&p->flags);
4046         }
4047         else {
4048
4049                 BcInstPtr *ip = bc_vec_top(&p->exits);
4050                 size_t *label = bc_vec_top(&p->conds);
4051
4052                 bc_parse_push(p, BC_INST_JUMP);
4053                 bc_parse_pushIndex(p, *label);
4054
4055                 label = bc_vec_item(&p->func->labels, ip->idx);
4056                 *label = p->func->code.len;
4057
4058                 bc_vec_pop(&p->flags);
4059                 bc_vec_pop(&p->exits);
4060                 bc_vec_pop(&p->conds);
4061         }
4062
4063         return s;
4064 }
4065
4066 static void bc_parse_startBody(BcParse *p, uint8_t flags)
4067 {
4068         uint8_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
4069         flags |= (*flag_ptr & (BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_LOOP));
4070         flags |= BC_PARSE_FLAG_BODY;
4071         bc_vec_push(&p->flags, &flags);
4072 }
4073
4074 static void bc_parse_noElse(BcParse *p)
4075 {
4076         BcInstPtr *ip;
4077         size_t *label;
4078         uint8_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
4079
4080         *flag_ptr = (*flag_ptr & ~(BC_PARSE_FLAG_IF_END));
4081
4082         ip = bc_vec_top(&p->exits);
4083         label = bc_vec_item(&p->func->labels, ip->idx);
4084         *label = p->func->code.len;
4085
4086         bc_vec_pop(&p->exits);
4087 }
4088
4089 static BcStatus bc_parse_if(BcParse *p)
4090 {
4091         BcStatus s;
4092         BcInstPtr ip;
4093
4094         s = bc_lex_next(&p->l);
4095         if (s) return s;
4096         if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token");
4097
4098         s = bc_lex_next(&p->l);
4099         if (s) return s;
4100         s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel);
4101         if (s) return s;
4102         if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token");
4103
4104         s = bc_lex_next(&p->l);
4105         if (s) return s;
4106         bc_parse_push(p, BC_INST_JUMP_ZERO);
4107
4108         ip.idx = p->func->labels.len;
4109         ip.func = ip.len = 0;
4110
4111         bc_parse_pushIndex(p, ip.idx);
4112         bc_vec_push(&p->exits, &ip);
4113         bc_vec_push(&p->func->labels, &ip.idx);
4114         bc_parse_startBody(p, BC_PARSE_FLAG_IF);
4115
4116         return BC_STATUS_SUCCESS;
4117 }
4118
4119 static BcStatus bc_parse_else(BcParse *p)
4120 {
4121         BcInstPtr ip;
4122
4123         if (!BC_PARSE_IF_END(p)) return bc_error("bad token");
4124
4125         ip.idx = p->func->labels.len;
4126         ip.func = ip.len = 0;
4127
4128         bc_parse_push(p, BC_INST_JUMP);
4129         bc_parse_pushIndex(p, ip.idx);
4130
4131         bc_parse_noElse(p);
4132
4133         bc_vec_push(&p->exits, &ip);
4134         bc_vec_push(&p->func->labels, &ip.idx);
4135         bc_parse_startBody(p, BC_PARSE_FLAG_ELSE);
4136
4137         return bc_lex_next(&p->l);
4138 }
4139
4140 static BcStatus bc_parse_while(BcParse *p)
4141 {
4142         BcStatus s;
4143         BcInstPtr ip;
4144
4145         s = bc_lex_next(&p->l);
4146         if (s) return s;
4147         if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token");
4148         s = bc_lex_next(&p->l);
4149         if (s) return s;
4150
4151         ip.idx = p->func->labels.len;
4152
4153         bc_vec_push(&p->func->labels, &p->func->code.len);
4154         bc_vec_push(&p->conds, &ip.idx);
4155
4156         ip.idx = p->func->labels.len;
4157         ip.func = 1;
4158         ip.len = 0;
4159
4160         bc_vec_push(&p->exits, &ip);
4161         bc_vec_push(&p->func->labels, &ip.idx);
4162
4163         s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel);
4164         if (s) return s;
4165         if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token");
4166         s = bc_lex_next(&p->l);
4167         if (s) return s;
4168
4169         bc_parse_push(p, BC_INST_JUMP_ZERO);
4170         bc_parse_pushIndex(p, ip.idx);
4171         bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER);
4172
4173         return BC_STATUS_SUCCESS;
4174 }
4175
4176 static BcStatus bc_parse_for(BcParse *p)
4177 {
4178         BcStatus s;
4179         BcInstPtr ip;
4180         size_t cond_idx, exit_idx, body_idx, update_idx;
4181
4182         s = bc_lex_next(&p->l);
4183         if (s) return s;
4184         if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token");
4185         s = bc_lex_next(&p->l);
4186         if (s) return s;
4187
4188         if (p->l.t.t != BC_LEX_SCOLON)
4189                 s = bc_parse_expr(p, 0, bc_parse_next_for);
4190         else
4191                 s = bc_posix_error("POSIX does not allow an empty init expression in a for loop");
4192
4193         if (s) return s;
4194         if (p->l.t.t != BC_LEX_SCOLON) return bc_error("bad token");
4195         s = bc_lex_next(&p->l);
4196         if (s) return s;
4197
4198         cond_idx = p->func->labels.len;
4199         update_idx = cond_idx + 1;
4200         body_idx = update_idx + 1;
4201         exit_idx = body_idx + 1;
4202
4203         bc_vec_push(&p->func->labels, &p->func->code.len);
4204
4205         if (p->l.t.t != BC_LEX_SCOLON)
4206                 s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_for);
4207         else
4208                 s = bc_posix_error("POSIX does not allow an empty condition expression in a for loop");
4209
4210         if (s) return s;
4211         if (p->l.t.t != BC_LEX_SCOLON) return bc_error("bad token");
4212
4213         s = bc_lex_next(&p->l);
4214         if (s) return s;
4215
4216         bc_parse_push(p, BC_INST_JUMP_ZERO);
4217         bc_parse_pushIndex(p, exit_idx);
4218         bc_parse_push(p, BC_INST_JUMP);
4219         bc_parse_pushIndex(p, body_idx);
4220
4221         ip.idx = p->func->labels.len;
4222
4223         bc_vec_push(&p->conds, &update_idx);
4224         bc_vec_push(&p->func->labels, &p->func->code.len);
4225
4226         if (p->l.t.t != BC_LEX_RPAREN)
4227                 s = bc_parse_expr(p, 0, bc_parse_next_rel);
4228         else
4229                 s = bc_posix_error("POSIX does not allow an empty update expression in a for loop");
4230
4231         if (s) return s;
4232
4233         if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token");
4234         bc_parse_push(p, BC_INST_JUMP);
4235         bc_parse_pushIndex(p, cond_idx);
4236         bc_vec_push(&p->func->labels, &p->func->code.len);
4237
4238         ip.idx = exit_idx;
4239         ip.func = 1;
4240         ip.len = 0;
4241
4242         bc_vec_push(&p->exits, &ip);
4243         bc_vec_push(&p->func->labels, &ip.idx);
4244         bc_lex_next(&p->l);
4245         bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER);
4246
4247         return BC_STATUS_SUCCESS;
4248 }
4249
4250 static BcStatus bc_parse_loopExit(BcParse *p, BcLexType type)
4251 {
4252         BcStatus s;
4253         size_t i;
4254         BcInstPtr *ip;
4255
4256         if (!BC_PARSE_LOOP(p)) return bc_error("bad token");
4257
4258         if (type == BC_LEX_KEY_BREAK) {
4259
4260                 if (p->exits.len == 0) return bc_error("bad token");
4261
4262                 i = p->exits.len - 1;
4263                 ip = bc_vec_item(&p->exits, i);
4264
4265                 while (!ip->func && i < p->exits.len) ip = bc_vec_item(&p->exits, i--);
4266                 if (i >= p->exits.len && !ip->func) return bc_error("bad token");
4267
4268                 i = ip->idx;
4269         }
4270         else
4271                 i = *((size_t *) bc_vec_top(&p->conds));
4272
4273         bc_parse_push(p, BC_INST_JUMP);
4274         bc_parse_pushIndex(p, i);
4275
4276         s = bc_lex_next(&p->l);
4277         if (s) return s;
4278
4279         if (p->l.t.t != BC_LEX_SCOLON && p->l.t.t != BC_LEX_NLINE)
4280                 return bc_error("bad token");
4281
4282         return bc_lex_next(&p->l);
4283 }
4284
4285 static BcStatus bc_parse_func(BcParse *p)
4286 {
4287         BcStatus s;
4288         bool var, comma = false;
4289         uint8_t flags;
4290         char *name;
4291
4292         s = bc_lex_next(&p->l);
4293         if (s) return s;
4294         if (p->l.t.t != BC_LEX_NAME)
4295                 return bc_error("bad function definition");
4296
4297         name = xstrdup(p->l.t.v.v);
4298         bc_parse_addFunc(p, name, &p->fidx);
4299
4300         s = bc_lex_next(&p->l);
4301         if (s) return s;
4302         if (p->l.t.t != BC_LEX_LPAREN)
4303                 return bc_error("bad function definition");
4304         s = bc_lex_next(&p->l);
4305         if (s) return s;
4306
4307         while (p->l.t.t != BC_LEX_RPAREN) {
4308
4309                 if (p->l.t.t != BC_LEX_NAME)
4310                         return bc_error("bad function definition");
4311
4312                 ++p->func->nparams;
4313
4314                 name = xstrdup(p->l.t.v.v);
4315                 s = bc_lex_next(&p->l);
4316                 if (s) goto err;
4317
4318                 var = p->l.t.t != BC_LEX_LBRACKET;
4319
4320                 if (!var) {
4321
4322                         s = bc_lex_next(&p->l);
4323                         if (s) goto err;
4324
4325                         if (p->l.t.t != BC_LEX_RBRACKET) {
4326                                 s = bc_error("bad function definition");
4327                                 goto err;
4328                         }
4329
4330                         s = bc_lex_next(&p->l);
4331                         if (s) goto err;
4332                 }
4333
4334                 comma = p->l.t.t == BC_LEX_COMMA;
4335                 if (comma) {
4336                         s = bc_lex_next(&p->l);
4337                         if (s) goto err;
4338                 }
4339
4340                 s = bc_func_insert(p->func, name, var);
4341                 if (s) goto err;
4342         }
4343
4344         if (comma) return bc_error("bad function definition");
4345
4346         flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_BODY;
4347         bc_parse_startBody(p, flags);
4348
4349         s = bc_lex_next(&p->l);
4350         if (s) return s;
4351
4352         if (p->l.t.t != BC_LEX_LBRACE)
4353                 s = bc_posix_error("POSIX requires the left brace be on the same line as the function header");
4354
4355         return s;
4356
4357 err:
4358         free(name);
4359         return s;
4360 }
4361
4362 static BcStatus bc_parse_auto(BcParse *p)
4363 {
4364         BcStatus s;
4365         bool comma, var, one;
4366         char *name;
4367
4368         if (!p->auto_part) return bc_error("bad token");
4369         s = bc_lex_next(&p->l);
4370         if (s) return s;
4371
4372         p->auto_part = comma = false;
4373         one = p->l.t.t == BC_LEX_NAME;
4374
4375         while (p->l.t.t == BC_LEX_NAME) {
4376
4377                 name = xstrdup(p->l.t.v.v);
4378                 s = bc_lex_next(&p->l);
4379                 if (s) goto err;
4380
4381                 var = p->l.t.t != BC_LEX_LBRACKET;
4382                 if (!var) {
4383
4384                         s = bc_lex_next(&p->l);
4385                         if (s) goto err;
4386
4387                         if (p->l.t.t != BC_LEX_RBRACKET) {
4388                                 s = bc_error("bad function definition");
4389                                 goto err;
4390                         }
4391
4392                         s = bc_lex_next(&p->l);
4393                         if (s) goto err;
4394                 }
4395
4396                 comma = p->l.t.t == BC_LEX_COMMA;
4397                 if (comma) {
4398                         s = bc_lex_next(&p->l);
4399                         if (s) goto err;
4400                 }
4401
4402                 s = bc_func_insert(p->func, name, var);
4403                 if (s) goto err;
4404         }
4405
4406         if (comma) return bc_error("bad function definition");
4407         if (!one) return bc_error("no auto variable found");
4408
4409         if (p->l.t.t != BC_LEX_NLINE && p->l.t.t != BC_LEX_SCOLON)
4410                 return bc_error("bad token");
4411
4412         return bc_lex_next(&p->l);
4413
4414 err:
4415         free(name);
4416         return s;
4417 }
4418
4419 static BcStatus bc_parse_body(BcParse *p, bool brace)
4420 {
4421         BcStatus s = BC_STATUS_SUCCESS;
4422         uint8_t *flag_ptr = bc_vec_top(&p->flags);
4423
4424         *flag_ptr &= ~(BC_PARSE_FLAG_BODY);
4425
4426         if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) {
4427
4428                 if (!brace) return bc_error("bad token");
4429                 p->auto_part = p->l.t.t != BC_LEX_KEY_AUTO;
4430
4431                 if (!p->auto_part) {
4432                         s = bc_parse_auto(p);
4433                         if (s) return s;
4434                 }
4435
4436                 if (p->l.t.t == BC_LEX_NLINE) s = bc_lex_next(&p->l);
4437         }
4438         else {
4439                 s = bc_parse_stmt(p);
4440                 if (!s && !brace) s = bc_parse_endBody(p, false);
4441         }
4442
4443         return s;
4444 }
4445
4446 static BcStatus bc_parse_stmt(BcParse *p)
4447 {
4448         BcStatus s = BC_STATUS_SUCCESS;
4449
4450         switch (p->l.t.t) {
4451
4452                 case BC_LEX_NLINE:
4453                 {
4454                         return bc_lex_next(&p->l);
4455                 }
4456
4457                 case BC_LEX_KEY_ELSE:
4458                 {
4459                         p->auto_part = false;
4460                         break;
4461                 }
4462
4463                 case BC_LEX_LBRACE:
4464                 {
4465                         if (!BC_PARSE_BODY(p)) return bc_error("bad token");
4466
4467                         ++p->nbraces;
4468                         s = bc_lex_next(&p->l);
4469                         if (s) return s;
4470
4471                         return bc_parse_body(p, true);
4472                 }
4473
4474                 case BC_LEX_KEY_AUTO:
4475                 {
4476                         return bc_parse_auto(p);
4477                 }
4478
4479                 default:
4480                 {
4481                         p->auto_part = false;
4482
4483                         if (BC_PARSE_IF_END(p)) {
4484                                 bc_parse_noElse(p);
4485                                 return BC_STATUS_SUCCESS;
4486                         }
4487                         else if (BC_PARSE_BODY(p))
4488                                 return bc_parse_body(p, false);
4489
4490                         break;
4491                 }
4492         }
4493
4494         switch (p->l.t.t) {
4495
4496                 case BC_LEX_OP_INC:
4497                 case BC_LEX_OP_DEC:
4498                 case BC_LEX_OP_MINUS:
4499                 case BC_LEX_OP_BOOL_NOT:
4500                 case BC_LEX_LPAREN:
4501                 case BC_LEX_NAME:
4502                 case BC_LEX_NUMBER:
4503                 case BC_LEX_KEY_IBASE:
4504                 case BC_LEX_KEY_LAST:
4505                 case BC_LEX_KEY_LENGTH:
4506                 case BC_LEX_KEY_OBASE:
4507                 case BC_LEX_KEY_READ:
4508                 case BC_LEX_KEY_SCALE:
4509                 case BC_LEX_KEY_SQRT:
4510                 {
4511                         s = bc_parse_expr(p, BC_PARSE_PRINT, bc_parse_next_expr);
4512                         break;
4513                 }
4514
4515                 case BC_LEX_KEY_ELSE:
4516                 {
4517                         s = bc_parse_else(p);
4518                         break;
4519                 }
4520
4521                 case BC_LEX_SCOLON:
4522                 {
4523                         while (!s && p->l.t.t == BC_LEX_SCOLON) s = bc_lex_next(&p->l);
4524                         break;
4525                 }
4526
4527                 case BC_LEX_RBRACE:
4528                 {
4529                         s = bc_parse_endBody(p, true);
4530                         break;
4531                 }
4532
4533                 case BC_LEX_STR:
4534                 {
4535                         s = bc_parse_string(p, BC_INST_PRINT_STR);
4536                         break;
4537                 }
4538
4539                 case BC_LEX_KEY_BREAK:
4540                 case BC_LEX_KEY_CONTINUE:
4541                 {
4542                         s = bc_parse_loopExit(p, p->l.t.t);
4543                         break;
4544                 }
4545
4546                 case BC_LEX_KEY_FOR:
4547                 {
4548                         s = bc_parse_for(p);
4549                         break;
4550                 }
4551
4552                 case BC_LEX_KEY_HALT:
4553                 {
4554                         bc_parse_push(p, BC_INST_HALT);
4555                         s = bc_lex_next(&p->l);
4556                         break;
4557                 }
4558
4559                 case BC_LEX_KEY_IF:
4560                 {
4561                         s = bc_parse_if(p);
4562                         break;
4563                 }
4564
4565                 case BC_LEX_KEY_LIMITS:
4566                 {
4567                         // "limits" is a compile-time command,
4568                         // the output is produced at _parse time_.
4569                         s = bc_lex_next(&p->l);
4570                         if (s) return s;
4571                         printf("BC_BASE_MAX     = %u\n", BC_MAX_OBASE);
4572                         printf("BC_DIM_MAX      = %u\n", BC_MAX_DIM);
4573                         printf("BC_SCALE_MAX    = %u\n", BC_MAX_SCALE);
4574                         printf("BC_STRING_MAX   = %u\n", BC_MAX_STRING);
4575                         printf("BC_NAME_MAX     = %u\n", BC_MAX_NAME);
4576                         printf("BC_NUM_MAX      = %u\n", BC_MAX_NUM);
4577                         printf("MAX Exponent    = %lu\n", BC_MAX_EXP);
4578                         printf("Number of vars  = %lu\n", BC_MAX_VARS);
4579                         break;
4580                 }
4581
4582                 case BC_LEX_KEY_PRINT:
4583                 {
4584                         s = bc_parse_print(p);
4585                         break;
4586                 }
4587
4588                 case BC_LEX_KEY_QUIT:
4589                 {
4590                         // "quit" is a compile-time command. For example,
4591                         // "if (0 == 1) quit" terminates when parsing the statement,
4592                         // not when it is executed
4593                         quit();
4594                 }
4595
4596                 case BC_LEX_KEY_RETURN:
4597                 {
4598                         s = bc_parse_return(p);
4599                         break;
4600                 }
4601
4602                 case BC_LEX_KEY_WHILE:
4603                 {
4604                         s = bc_parse_while(p);
4605                         break;
4606                 }
4607
4608                 default:
4609                 {
4610                         s = bc_error("bad token");
4611                         break;
4612                 }
4613         }
4614
4615         return s;
4616 }
4617
4618 static BcStatus bc_parse_parse(BcParse *p)
4619 {
4620         BcStatus s;
4621
4622         if (p->l.t.t == BC_LEX_EOF)
4623                 s = p->flags.len > 0 ? bc_error("block end could not be found") : bc_error("end of file");
4624         else if (p->l.t.t == BC_LEX_KEY_DEFINE) {
4625                 if (!BC_PARSE_CAN_EXEC(p)) return bc_error("bad token");
4626                 s = bc_parse_func(p);
4627         }
4628         else
4629                 s = bc_parse_stmt(p);
4630
4631         if (s || G_interrupt) {
4632                 bc_parse_reset(p);
4633                 s = BC_STATUS_FAILURE;
4634         }
4635
4636         return s;
4637 }
4638
4639 static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
4640 {
4641         BcStatus s = BC_STATUS_SUCCESS;
4642         BcInst prev = BC_INST_PRINT;
4643         BcLexType top, t = p->l.t.t;
4644         size_t nexprs = 0, ops_bgn = p->ops.len;
4645         uint32_t i, nparens, nrelops;
4646         bool paren_first, paren_expr, rprn, done, get_token, assign, bin_last;
4647
4648         paren_first = p->l.t.t == BC_LEX_LPAREN;
4649         nparens = nrelops = 0;
4650         paren_expr = rprn = done = get_token = assign = false;
4651         bin_last = true;
4652
4653         for (; !G_interrupt && !s && !done && bc_parse_exprs[t]; t = p->l.t.t) {
4654                 switch (t) {
4655
4656                         case BC_LEX_OP_INC:
4657                         case BC_LEX_OP_DEC:
4658                         {
4659                                 s = bc_parse_incdec(p, &prev, &paren_expr, &nexprs, flags);
4660                                 rprn = get_token = bin_last = false;
4661                                 break;
4662                         }
4663
4664                         case BC_LEX_OP_MINUS:
4665                         {
4666                                 s = bc_parse_minus(p, &prev, ops_bgn, rprn, &nexprs);
4667                                 rprn = get_token = false;
4668                                 bin_last = prev == BC_INST_MINUS;
4669                                 break;
4670                         }
4671
4672                         case BC_LEX_OP_ASSIGN_POWER:
4673                         case BC_LEX_OP_ASSIGN_MULTIPLY:
4674                         case BC_LEX_OP_ASSIGN_DIVIDE:
4675                         case BC_LEX_OP_ASSIGN_MODULUS:
4676                         case BC_LEX_OP_ASSIGN_PLUS:
4677                         case BC_LEX_OP_ASSIGN_MINUS:
4678                         case BC_LEX_OP_ASSIGN:
4679                         {
4680                                 if (prev != BC_INST_VAR && prev != BC_INST_ARRAY_ELEM &&
4681                                     prev != BC_INST_SCALE && prev != BC_INST_IBASE &&
4682                                     prev != BC_INST_OBASE && prev != BC_INST_LAST)
4683                                 {
4684                                         s = bc_error("bad assignment:"
4685                                                 " left side must be scale,"
4686                                                 " ibase, obase, last, var,"
4687                                                 " or array element"
4688                                         );
4689                                         break;
4690                                 }
4691                         }
4692                         // Fallthrough.
4693                         case BC_LEX_OP_POWER:
4694                         case BC_LEX_OP_MULTIPLY:
4695                         case BC_LEX_OP_DIVIDE:
4696                         case BC_LEX_OP_MODULUS:
4697                         case BC_LEX_OP_PLUS:
4698                         case BC_LEX_OP_REL_EQ:
4699                         case BC_LEX_OP_REL_LE:
4700                         case BC_LEX_OP_REL_GE:
4701                         case BC_LEX_OP_REL_NE:
4702                         case BC_LEX_OP_REL_LT:
4703                         case BC_LEX_OP_REL_GT:
4704                         case BC_LEX_OP_BOOL_NOT:
4705                         case BC_LEX_OP_BOOL_OR:
4706                         case BC_LEX_OP_BOOL_AND:
4707                         {
4708                                 if (((t == BC_LEX_OP_BOOL_NOT) != bin_last)
4709                                  || (t != BC_LEX_OP_BOOL_NOT && prev == BC_INST_BOOL_NOT)
4710                                 ) {
4711                                         return bc_error("bad expression");
4712                                 }
4713
4714                                 nrelops += t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT;
4715                                 prev = BC_PARSE_TOKEN_INST(t);
4716                                 s = bc_parse_operator(p, t, ops_bgn, &nexprs, true);
4717                                 rprn = get_token = false;
4718                                 bin_last = t != BC_LEX_OP_BOOL_NOT;
4719
4720                                 break;
4721                         }
4722
4723                         case BC_LEX_LPAREN:
4724                         {
4725                                 if (BC_PARSE_LEAF(prev, rprn))
4726                                         return bc_error("bad expression");
4727                                 ++nparens;
4728                                 paren_expr = rprn = bin_last = false;
4729                                 get_token = true;
4730                                 bc_vec_push(&p->ops, &t);
4731
4732                                 break;
4733                         }
4734
4735                         case BC_LEX_RPAREN:
4736                         {
4737                                 if (bin_last || prev == BC_INST_BOOL_NOT)
4738                                         return bc_error("bad expression");
4739
4740                                 if (nparens == 0) {
4741                                         s = BC_STATUS_SUCCESS;
4742                                         done = true;
4743                                         get_token = false;
4744                                         break;
4745                                 }
4746                                 else if (!paren_expr)
4747                                         return BC_STATUS_PARSE_EMPTY_EXP;
4748
4749                                 --nparens;
4750                                 paren_expr = rprn = true;
4751                                 get_token = bin_last = false;
4752
4753                                 s = bc_parse_rightParen(p, ops_bgn, &nexprs);
4754
4755                                 break;
4756                         }
4757
4758                         case BC_LEX_NAME:
4759                         {
4760                                 if (BC_PARSE_LEAF(prev, rprn))
4761                                         return bc_error("bad expression");
4762                                 paren_expr = true;
4763                                 rprn = get_token = bin_last = false;
4764                                 s = bc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL);
4765                                 ++nexprs;
4766
4767                                 break;
4768                         }
4769
4770                         case BC_LEX_NUMBER:
4771                         {
4772                                 if (BC_PARSE_LEAF(prev, rprn))
4773                                         return bc_error("bad expression");
4774                                 bc_parse_number(p, &prev, &nexprs);
4775                                 paren_expr = get_token = true;
4776                                 rprn = bin_last = false;
4777
4778                                 break;
4779                         }
4780
4781                         case BC_LEX_KEY_IBASE:
4782                         case BC_LEX_KEY_LAST:
4783                         case BC_LEX_KEY_OBASE:
4784                         {
4785                                 if (BC_PARSE_LEAF(prev, rprn))
4786                                         return bc_error("bad expression");
4787                                 prev = (char) (t - BC_LEX_KEY_IBASE + BC_INST_IBASE);
4788                                 bc_parse_push(p, (char) prev);
4789
4790                                 paren_expr = get_token = true;
4791                                 rprn = bin_last = false;
4792                                 ++nexprs;
4793
4794                                 break;
4795                         }
4796
4797                         case BC_LEX_KEY_LENGTH:
4798                         case BC_LEX_KEY_SQRT:
4799                         {
4800                                 if (BC_PARSE_LEAF(prev, rprn))
4801                                         return bc_error("bad expression");
4802                                 s = bc_parse_builtin(p, t, flags, &prev);
4803                                 paren_expr = true;
4804                                 rprn = get_token = bin_last = false;
4805                                 ++nexprs;
4806
4807                                 break;
4808                         }
4809
4810                         case BC_LEX_KEY_READ:
4811                         {
4812                                 if (BC_PARSE_LEAF(prev, rprn))
4813                                         return bc_error("bad expression");
4814                                 else if (flags & BC_PARSE_NOREAD)
4815                                         s = bc_error("read() call inside of a read() call");
4816                                 else
4817                                         s = bc_parse_read(p);
4818
4819                                 paren_expr = true;
4820                                 rprn = get_token = bin_last = false;
4821                                 ++nexprs;
4822                                 prev = BC_INST_READ;
4823
4824                                 break;
4825                         }
4826
4827                         case BC_LEX_KEY_SCALE:
4828                         {
4829                                 if (BC_PARSE_LEAF(prev, rprn))
4830                                         return bc_error("bad expression");
4831                                 s = bc_parse_scale(p, &prev, flags);
4832                                 paren_expr = true;
4833                                 rprn = get_token = bin_last = false;
4834                                 ++nexprs;
4835                                 prev = BC_INST_SCALE;
4836
4837                                 break;
4838                         }
4839
4840                         default:
4841                         {
4842                                 s = bc_error("bad token");
4843                                 break;
4844                         }
4845                 }
4846
4847                 if (!s && get_token) s = bc_lex_next(&p->l);
4848         }
4849
4850         if (s) return s;
4851         if (G_interrupt) return BC_STATUS_FAILURE; // ^C: stop parsing
4852
4853         while (p->ops.len > ops_bgn) {
4854
4855                 top = BC_PARSE_TOP_OP(p);
4856                 assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN;
4857
4858                 if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN)
4859                         return bc_error("bad expression");
4860
4861                 bc_parse_push(p, BC_PARSE_TOKEN_INST(top));
4862
4863                 nexprs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG;
4864                 bc_vec_pop(&p->ops);
4865         }
4866
4867         if (prev == BC_INST_BOOL_NOT || nexprs != 1)
4868                 return bc_error("bad expression");
4869
4870         for (i = 0; i < next.len; ++i)
4871                 if (t == next.tokens[i])
4872                         goto ok;
4873         return bc_error("bad expression");
4874  ok:
4875
4876         if (!(flags & BC_PARSE_REL) && nrelops) {
4877                 s = bc_posix_error("POSIX does not allow comparison operators outside if or loops");
4878                 if (s) return s;
4879         }
4880         else if ((flags & BC_PARSE_REL) && nrelops > 1) {
4881                 s = bc_posix_error("POSIX requires exactly one comparison operator per condition");
4882                 if (s) return s;
4883         }
4884
4885         if (flags & BC_PARSE_PRINT) {
4886                 if (paren_first || !assign) bc_parse_push(p, BC_INST_PRINT);
4887                 bc_parse_push(p, BC_INST_POP);
4888         }
4889
4890         return s;
4891 }
4892
4893 static void bc_parse_init(BcParse *p, size_t func)
4894 {
4895         bc_parse_create(p, func, bc_parse_parse, bc_lex_token);
4896 }
4897
4898 static BcStatus bc_parse_expression(BcParse *p, uint8_t flags)
4899 {
4900         return bc_parse_expr(p, flags, bc_parse_next_read);
4901 }
4902 #endif // ENABLE_BC
4903
4904 #if ENABLE_DC
4905 static BcStatus dc_parse_register(BcParse *p)
4906 {
4907         BcStatus s;
4908         char *name;
4909
4910         s = bc_lex_next(&p->l);
4911         if (s) return s;
4912         if (p->l.t.t != BC_LEX_NAME) return bc_error("bad token");
4913
4914         name = xstrdup(p->l.t.v.v);
4915         bc_parse_pushName(p, name);
4916
4917         return s;
4918 }
4919
4920 static BcStatus dc_parse_string(BcParse *p)
4921 {
4922         char *str, *name, b[DC_PARSE_BUF_LEN + 1];
4923         size_t idx, len = G.prog.strs.len;
4924
4925         sprintf(b, "%0*zu", DC_PARSE_BUF_LEN, len);
4926         name = xstrdup(b);
4927
4928         str = xstrdup(p->l.t.v.v);
4929         bc_parse_push(p, BC_INST_STR);
4930         bc_parse_pushIndex(p, len);
4931         bc_vec_push(&G.prog.strs, &str);
4932         bc_parse_addFunc(p, name, &idx);
4933
4934         return bc_lex_next(&p->l);
4935 }
4936
4937 static BcStatus dc_parse_mem(BcParse *p, uint8_t inst, bool name, bool store)
4938 {
4939         BcStatus s;
4940
4941         bc_parse_push(p, inst);
4942         if (name) {
4943                 s = dc_parse_register(p);
4944                 if (s) return s;
4945         }
4946
4947         if (store) {
4948                 bc_parse_push(p, BC_INST_SWAP);
4949                 bc_parse_push(p, BC_INST_ASSIGN);
4950                 bc_parse_push(p, BC_INST_POP);
4951         }
4952
4953         return bc_lex_next(&p->l);
4954 }
4955
4956 static BcStatus dc_parse_cond(BcParse *p, uint8_t inst)
4957 {
4958         BcStatus s;
4959
4960         bc_parse_push(p, inst);
4961         bc_parse_push(p, BC_INST_EXEC_COND);
4962
4963         s = dc_parse_register(p);
4964         if (s) return s;
4965
4966         s = bc_lex_next(&p->l);
4967         if (s) return s;
4968
4969         if (p->l.t.t == BC_LEX_ELSE) {
4970                 s = dc_parse_register(p);
4971                 if (s) return s;
4972                 s = bc_lex_next(&p->l);
4973         }
4974         else
4975                 bc_parse_push(p, BC_PARSE_STREND);
4976
4977         return s;
4978 }
4979
4980 static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags)
4981 {
4982         BcStatus s = BC_STATUS_SUCCESS;
4983         BcInst prev;
4984         uint8_t inst;
4985         bool assign, get_token = false;
4986
4987         switch (t) {
4988
4989                 case BC_LEX_OP_REL_EQ:
4990                 case BC_LEX_OP_REL_LE:
4991                 case BC_LEX_OP_REL_GE:
4992                 case BC_LEX_OP_REL_NE:
4993                 case BC_LEX_OP_REL_LT:
4994                 case BC_LEX_OP_REL_GT:
4995                 {
4996                         s = dc_parse_cond(p, t - BC_LEX_OP_REL_EQ + BC_INST_REL_EQ);
4997                         break;
4998                 }
4999
5000                 case BC_LEX_SCOLON:
5001                 case BC_LEX_COLON:
5002                 {
5003                         s = dc_parse_mem(p, BC_INST_ARRAY_ELEM, true, t == BC_LEX_COLON);
5004                         break;
5005                 }
5006
5007                 case BC_LEX_STR:
5008                 {
5009                         s = dc_parse_string(p);
5010                         break;
5011                 }
5012
5013                 case BC_LEX_NEG:
5014                 case BC_LEX_NUMBER:
5015                 {
5016                         if (t == BC_LEX_NEG) {
5017                                 s = bc_lex_next(&p->l);
5018                                 if (s) return s;
5019                                 if (p->l.t.t != BC_LEX_NUMBER)
5020                                         return bc_error("bad token");
5021                         }
5022
5023                         bc_parse_number(p, &prev, &p->nbraces);
5024
5025                         if (t == BC_LEX_NEG) bc_parse_push(p, BC_INST_NEG);
5026                         get_token = true;
5027
5028                         break;
5029                 }
5030
5031                 case BC_LEX_KEY_READ:
5032                 {
5033                         if (flags & BC_PARSE_NOREAD)
5034                                 s = bc_error("read() call inside of a read() call");
5035                         else
5036                                 bc_parse_push(p, BC_INST_READ);
5037                         get_token = true;
5038                         break;
5039                 }
5040
5041                 case BC_LEX_OP_ASSIGN:
5042                 case BC_LEX_STORE_PUSH:
5043                 {
5044                         assign = t == BC_LEX_OP_ASSIGN;
5045                         inst = assign ? BC_INST_VAR : BC_INST_PUSH_TO_VAR;
5046                         s = dc_parse_mem(p, inst, true, assign);
5047                         break;
5048                 }
5049
5050                 case BC_LEX_LOAD:
5051                 case BC_LEX_LOAD_POP:
5052                 {
5053                         inst = t == BC_LEX_LOAD_POP ? BC_INST_PUSH_VAR : BC_INST_LOAD;
5054                         s = dc_parse_mem(p, inst, true, false);
5055                         break;
5056                 }
5057
5058                 case BC_LEX_STORE_IBASE:
5059                 case BC_LEX_STORE_SCALE:
5060                 case BC_LEX_STORE_OBASE:
5061                 {
5062                         inst = t - BC_LEX_STORE_IBASE + BC_INST_IBASE;
5063                         s = dc_parse_mem(p, inst, false, true);
5064                         break;
5065                 }
5066
5067                 default:
5068                 {
5069                         s = bc_error("bad token");
5070                         get_token = true;
5071                         break;
5072                 }
5073         }
5074
5075         if (!s && get_token) s = bc_lex_next(&p->l);
5076
5077         return s;
5078 }
5079
5080 static BcStatus dc_parse_expr(BcParse *p, uint8_t flags)
5081 {
5082         BcStatus s = BC_STATUS_SUCCESS;
5083         BcInst inst;
5084         BcLexType t;
5085
5086         if (flags & BC_PARSE_NOCALL) p->nbraces = G.prog.results.len;
5087
5088         for (t = p->l.t.t; !s && t != BC_LEX_EOF; t = p->l.t.t) {
5089
5090                 inst = dc_parse_insts[t];
5091
5092                 if (inst != BC_INST_INVALID) {
5093                         bc_parse_push(p, inst);
5094                         s = bc_lex_next(&p->l);
5095                 }
5096                 else
5097                         s = dc_parse_token(p, t, flags);
5098         }
5099
5100         if (!s && p->l.t.t == BC_LEX_EOF && (flags & BC_PARSE_NOCALL))
5101                 bc_parse_push(p, BC_INST_POP_EXEC);
5102
5103         return s;
5104 }
5105
5106 static BcStatus dc_parse_parse(BcParse *p)
5107 {
5108         BcStatus s;
5109
5110         if (p->l.t.t == BC_LEX_EOF)
5111                 s = bc_error("end of file");
5112         else
5113                 s = dc_parse_expr(p, 0);
5114
5115         if (s || G_interrupt) {
5116                 bc_parse_reset(p);
5117                 s = BC_STATUS_FAILURE;
5118         }
5119
5120         return s;
5121 }
5122
5123 static void dc_parse_init(BcParse *p, size_t func)
5124 {
5125         bc_parse_create(p, func, dc_parse_parse, dc_lex_token);
5126 }
5127 #endif // ENABLE_DC
5128
5129 static void common_parse_init(BcParse *p, size_t func)
5130 {
5131         if (IS_BC) {
5132                 bc_parse_init(p, func);
5133         } else {
5134                 dc_parse_init(p, func);
5135         }
5136 }
5137
5138 static BcStatus common_parse_expr(BcParse *p, uint8_t flags)
5139 {
5140         if (IS_BC) {
5141                 return bc_parse_expression(p, flags);
5142         } else {
5143                 return dc_parse_expr(p, flags);
5144         }
5145 }
5146
5147 static BcVec* bc_program_search(char *id, bool var)
5148 {
5149         BcId e, *ptr;
5150         BcVec *v, *map;
5151         size_t i;
5152         BcResultData data;
5153         int new;
5154
5155         v = var ? &G.prog.vars : &G.prog.arrs;
5156         map = var ? &G.prog.var_map : &G.prog.arr_map;
5157
5158         e.name = id;
5159         e.idx = v->len;
5160         new = bc_map_insert(map, &e, &i); // 1 if insertion was successful
5161
5162         if (new) {
5163                 bc_array_init(&data.v, var);
5164                 bc_vec_push(v, &data.v);
5165         }
5166
5167         ptr = bc_vec_item(map, i);
5168         if (new) ptr->name = xstrdup(e.name);
5169         return bc_vec_item(v, ptr->idx);
5170 }
5171
5172 static BcStatus bc_program_num(BcResult *r, BcNum **num, bool hex)
5173 {
5174         BcStatus s = BC_STATUS_SUCCESS;
5175
5176         switch (r->t) {
5177
5178                 case BC_RESULT_STR:
5179                 case BC_RESULT_TEMP:
5180                 case BC_RESULT_IBASE:
5181                 case BC_RESULT_SCALE:
5182                 case BC_RESULT_OBASE:
5183                 {
5184                         *num = &r->d.n;
5185                         break;
5186                 }
5187
5188                 case BC_RESULT_CONSTANT:
5189                 {
5190                         char **str = bc_vec_item(&G.prog.consts, r->d.id.idx);
5191                         size_t base_t, len = strlen(*str);
5192                         BcNum *base;
5193
5194                         bc_num_init(&r->d.n, len);
5195
5196                         hex = hex && len == 1;
5197                         base = hex ? &G.prog.hexb : &G.prog.ib;
5198                         base_t = hex ? BC_NUM_MAX_IBASE : G.prog.ib_t;
5199                         s = bc_num_parse(&r->d.n, *str, base, base_t);
5200
5201                         if (s) {
5202                                 bc_num_free(&r->d.n);
5203                                 return s;
5204                         }
5205
5206                         *num = &r->d.n;
5207                         r->t = BC_RESULT_TEMP;
5208
5209                         break;
5210                 }
5211
5212                 case BC_RESULT_VAR:
5213                 case BC_RESULT_ARRAY:
5214                 case BC_RESULT_ARRAY_ELEM:
5215                 {
5216                         BcVec *v;
5217
5218                         v = bc_program_search(r->d.id.name, r->t == BC_RESULT_VAR);
5219
5220                         if (r->t == BC_RESULT_ARRAY_ELEM) {
5221                                 v = bc_vec_top(v);
5222                                 if (v->len <= r->d.id.idx) bc_array_expand(v, r->d.id.idx + 1);
5223                                 *num = bc_vec_item(v, r->d.id.idx);
5224                         }
5225                         else
5226                                 *num = bc_vec_top(v);
5227
5228                         break;
5229                 }
5230
5231                 case BC_RESULT_LAST:
5232                 {
5233                         *num = &G.prog.last;
5234                         break;
5235                 }
5236
5237                 case BC_RESULT_ONE:
5238                 {
5239                         *num = &G.prog.one;
5240                         break;
5241                 }
5242         }
5243
5244         return s;
5245 }
5246
5247 static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln,
5248                                      BcResult **r, BcNum **rn, bool assign)
5249 {
5250         BcStatus s;
5251         bool hex;
5252         BcResultType lt, rt;
5253
5254         if (!BC_PROG_STACK(&G.prog.results, 2))
5255                 return bc_error("stack has too few elements");
5256
5257         *r = bc_vec_item_rev(&G.prog.results, 0);
5258         *l = bc_vec_item_rev(&G.prog.results, 1);
5259
5260         lt = (*l)->t;
5261         rt = (*r)->t;
5262         hex = assign && (lt == BC_RESULT_IBASE || lt == BC_RESULT_OBASE);
5263
5264         s = bc_program_num(*l, ln, false);
5265         if (s) return s;
5266         s = bc_program_num(*r, rn, hex);
5267         if (s) return s;
5268
5269         // We run this again under these conditions in case any vector has been
5270         // reallocated out from under the BcNums or arrays we had.
5271         if (lt == rt && (lt == BC_RESULT_VAR || lt == BC_RESULT_ARRAY_ELEM)) {
5272                 s = bc_program_num(*l, ln, false);
5273                 if (s) return s;
5274         }
5275
5276         if (!BC_PROG_NUM((*l), (*ln)) && (!assign || (*l)->t != BC_RESULT_VAR))
5277                 return bc_error("variable is wrong type");
5278         if (!assign && !BC_PROG_NUM((*r), (*ln)))
5279                 return bc_error("variable is wrong type");
5280
5281         return s;
5282 }
5283
5284 static void bc_program_binOpRetire(BcResult *r)
5285 {
5286         r->t = BC_RESULT_TEMP;
5287         bc_vec_pop(&G.prog.results);
5288         bc_vec_pop(&G.prog.results);
5289         bc_vec_push(&G.prog.results, r);
5290 }
5291
5292 static BcStatus bc_program_prep(BcResult **r, BcNum **n)
5293 {
5294         BcStatus s;
5295
5296         if (!BC_PROG_STACK(&G.prog.results, 1))
5297                 return bc_error("stack has too few elements");
5298         *r = bc_vec_top(&G.prog.results);
5299
5300         s = bc_program_num(*r, n, false);
5301         if (s) return s;
5302
5303         if (!BC_PROG_NUM((*r), (*n)))
5304                 return bc_error("variable is wrong type");
5305
5306         return s;
5307 }
5308
5309 static void bc_program_retire(BcResult *r, BcResultType t)
5310 {
5311         r->t = t;
5312         bc_vec_pop(&G.prog.results);
5313         bc_vec_push(&G.prog.results, r);
5314 }
5315
5316 static BcStatus bc_program_op(char inst)
5317 {
5318         BcStatus s;
5319         BcResult *opd1, *opd2, res;
5320         BcNum *n1, *n2 = NULL;
5321
5322         s = bc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false);
5323         if (s) return s;
5324         bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
5325
5326         s = bc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, G.prog.scale);
5327         if (s) goto err;
5328         bc_program_binOpRetire(&res);
5329
5330         return s;
5331
5332 err:
5333         bc_num_free(&res.d.n);
5334         return s;
5335 }
5336
5337 static BcStatus bc_program_read(void)
5338 {
5339         BcStatus s;
5340         BcParse parse;
5341         BcVec buf;
5342         BcInstPtr ip;
5343         size_t i;
5344         BcFunc *f = bc_vec_item(&G.prog.fns, BC_PROG_READ);
5345
5346         for (i = 0; i < G.prog.stack.len; ++i) {
5347                 BcInstPtr *ip_ptr = bc_vec_item(&G.prog.stack, i);
5348                 if (ip_ptr->func == BC_PROG_READ)
5349                         return bc_error("read() call inside of a read() call");
5350         }
5351
5352         bc_vec_npop(&f->code, f->code.len);
5353         bc_vec_init(&buf, sizeof(char), NULL);
5354
5355         s = bc_read_line(&buf, "read> ");
5356         if (s) goto io_err;
5357
5358         common_parse_init(&parse, BC_PROG_READ);
5359         bc_lex_file(&parse.l, bc_program_stdin_name);
5360
5361         s = bc_parse_text(&parse, buf.v);
5362         if (s) goto exec_err;
5363         s = common_parse_expr(&parse, BC_PARSE_NOREAD);
5364         if (s) goto exec_err;
5365
5366         if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != BC_LEX_EOF) {
5367                 s = bc_error("bad read() expression");
5368                 goto exec_err;
5369         }
5370
5371         ip.func = BC_PROG_READ;
5372         ip.idx = 0;
5373         ip.len = G.prog.results.len;
5374
5375         // Update this pointer, just in case.
5376         f = bc_vec_item(&G.prog.fns, BC_PROG_READ);
5377
5378         bc_vec_pushByte(&f->code, BC_INST_POP_EXEC);
5379         bc_vec_push(&G.prog.stack, &ip);
5380
5381 exec_err:
5382         bc_parse_free(&parse);
5383 io_err:
5384         bc_vec_free(&buf);
5385         return s;
5386 }
5387
5388 static size_t bc_program_index(char *code, size_t *bgn)
5389 {
5390         char amt = code[(*bgn)++], i = 0;
5391         size_t res = 0;
5392
5393         for (; i < amt; ++i, ++(*bgn))
5394                 res |= (((size_t)((int) code[*bgn]) & UCHAR_MAX) << (i * CHAR_BIT));
5395
5396         return res;
5397 }
5398
5399 static char *bc_program_name(char *code, size_t *bgn)
5400 {
5401         size_t i;
5402         char c, *s, *str = code + *bgn, *ptr = strchr(str, BC_PARSE_STREND);
5403
5404         s = xmalloc(ptr - str + 1);
5405         c = code[(*bgn)++];
5406
5407         for (i = 0; c != 0 && c != BC_PARSE_STREND; c = code[(*bgn)++], ++i)
5408                 s[i] = c;
5409
5410         s[i] = '\0';
5411
5412         return s;
5413 }
5414
5415 static void bc_program_printString(const char *str, size_t *nchars)
5416 {
5417         size_t i, len = strlen(str);
5418
5419 #if ENABLE_DC
5420         if (len == 0) {
5421                 bb_putchar('\0');
5422                 return;
5423         }
5424 #endif
5425
5426         for (i = 0; i < len; ++i, ++(*nchars)) {
5427
5428                 int c = str[i];
5429
5430                 if (c != '\\' || i == len - 1)
5431                         bb_putchar(c);
5432                 else {
5433
5434                         c = str[++i];
5435
5436                         switch (c) {
5437
5438                                 case 'a':
5439                                 {
5440                                         bb_putchar('\a');
5441                                         break;
5442                                 }
5443
5444                                 case 'b':
5445                                 {
5446                                         bb_putchar('\b');
5447                                         break;
5448                                 }
5449
5450                                 case '\\':
5451                                 case 'e':
5452                                 {
5453                                         bb_putchar('\\');
5454                                         break;
5455                                 }
5456
5457                                 case 'f':
5458                                 {
5459                                         bb_putchar('\f');
5460                                         break;
5461                                 }
5462
5463                                 case 'n':
5464                                 {
5465                                         bb_putchar('\n');
5466                                         *nchars = SIZE_MAX;
5467                                         break;
5468                                 }
5469
5470                                 case 'r':
5471                                 {
5472                                         bb_putchar('\r');
5473                                         break;
5474                                 }
5475
5476                                 case 'q':
5477                                 {
5478                                         bb_putchar('"');
5479                                         break;
5480                                 }
5481
5482                                 case 't':
5483                                 {
5484                                         bb_putchar('\t');
5485                                         break;
5486                                 }
5487
5488                                 default:
5489                                 {
5490                                         // Just print the backslash and following character.
5491                                         bb_putchar('\\');
5492                                         ++(*nchars);
5493                                         bb_putchar(c);
5494                                         break;
5495                                 }
5496                         }
5497                 }
5498         }
5499 }
5500
5501 static BcStatus bc_program_print(char inst, size_t idx)
5502 {
5503         BcStatus s = BC_STATUS_SUCCESS;
5504         BcResult *r;
5505         size_t len, i;
5506         char *str;
5507         BcNum *num = NULL;
5508         bool pop = inst != BC_INST_PRINT;
5509
5510         if (!BC_PROG_STACK(&G.prog.results, idx + 1))
5511                 return bc_error("stack has too few elements");
5512
5513         r = bc_vec_item_rev(&G.prog.results, idx);
5514         s = bc_program_num(r, &num, false);
5515         if (s) return s;
5516
5517         if (BC_PROG_NUM(r, num)) {
5518                 s = bc_num_print(num, &G.prog.ob, G.prog.ob_t, !pop, &G.prog.nchars, G.prog.len);
5519                 if (!s) bc_num_copy(&G.prog.last, num);
5520         }
5521         else {
5522
5523                 idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx;
5524                 str = *((char **) bc_vec_item(&G.prog.strs, idx));
5525
5526                 if (inst == BC_INST_PRINT_STR) {
5527                         for (i = 0, len = strlen(str); i < len; ++i) {
5528                                 char c = str[i];
5529                                 bb_putchar(c);
5530                                 if (c == '\n') G.prog.nchars = SIZE_MAX;
5531                                 ++G.prog.nchars;
5532                         }
5533                 }
5534                 else {
5535                         bc_program_printString(str, &G.prog.nchars);
5536                         if (inst == BC_INST_PRINT) bb_putchar('\n');
5537                 }
5538         }
5539
5540         if (!s && pop) bc_vec_pop(&G.prog.results);
5541
5542         return s;
5543 }
5544
5545 static BcStatus bc_program_negate(void)
5546 {
5547         BcStatus s;
5548         BcResult res, *ptr;
5549         BcNum *num = NULL;
5550
5551         s = bc_program_prep(&ptr, &num);
5552         if (s) return s;
5553
5554         bc_num_init(&res.d.n, num->len);
5555         bc_num_copy(&res.d.n, num);
5556         if (res.d.n.len) res.d.n.neg = !res.d.n.neg;
5557
5558         bc_program_retire(&res, BC_RESULT_TEMP);
5559
5560         return s;
5561 }
5562
5563 static BcStatus bc_program_logical(char inst)
5564 {
5565         BcStatus s;
5566         BcResult *opd1, *opd2, res;
5567         BcNum *n1, *n2;
5568         bool cond = 0;
5569         ssize_t cmp;
5570
5571         s = bc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false);
5572         if (s) return s;
5573         bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
5574
5575         if (inst == BC_INST_BOOL_AND)
5576                 cond = bc_num_cmp(n1, &G.prog.zero) && bc_num_cmp(n2, &G.prog.zero);
5577         else if (inst == BC_INST_BOOL_OR)
5578                 cond = bc_num_cmp(n1, &G.prog.zero) || bc_num_cmp(n2, &G.prog.zero);
5579         else {
5580
5581                 cmp = bc_num_cmp(n1, n2);
5582
5583                 switch (inst) {
5584
5585                         case BC_INST_REL_EQ:
5586                         {
5587                                 cond = cmp == 0;
5588                                 break;
5589                         }
5590
5591                         case BC_INST_REL_LE:
5592                         {
5593                                 cond = cmp <= 0;
5594                                 break;
5595                         }
5596
5597                         case BC_INST_REL_GE:
5598                         {
5599                                 cond = cmp >= 0;
5600                                 break;
5601                         }
5602
5603                         case BC_INST_REL_NE:
5604                         {
5605                                 cond = cmp != 0;
5606                                 break;
5607                         }
5608
5609                         case BC_INST_REL_LT:
5610                         {
5611                                 cond = cmp < 0;
5612                                 break;
5613                         }
5614
5615                         case BC_INST_REL_GT:
5616                         {
5617                                 cond = cmp > 0;
5618                                 break;
5619                         }
5620                 }
5621         }
5622
5623         (cond ? bc_num_one : bc_num_zero)(&res.d.n);
5624
5625         bc_program_binOpRetire(&res);
5626
5627         return s;
5628 }
5629
5630 #if ENABLE_DC
5631 static BcStatus bc_program_assignStr(BcResult *r, BcVec *v,
5632                                      bool push)
5633 {
5634         BcNum n2;
5635         BcResult res;
5636
5637         memset(&n2, 0, sizeof(BcNum));
5638         n2.rdx = res.d.id.idx = r->d.id.idx;
5639         res.t = BC_RESULT_STR;
5640
5641         if (!push) {
5642                 if (!BC_PROG_STACK(&G.prog.results, 2))
5643                         return bc_error("stack has too few elements");
5644                 bc_vec_pop(v);
5645                 bc_vec_pop(&G.prog.results);
5646         }
5647
5648         bc_vec_pop(&G.prog.results);
5649
5650         bc_vec_push(&G.prog.results, &res);
5651         bc_vec_push(v, &n2);
5652
5653         return BC_STATUS_SUCCESS;
5654 }
5655 #endif // ENABLE_DC
5656
5657 static BcStatus bc_program_copyToVar(char *name, bool var)
5658 {
5659         BcStatus s;
5660         BcResult *ptr, r;
5661         BcVec *v;
5662         BcNum *n;
5663
5664         if (!BC_PROG_STACK(&G.prog.results, 1))
5665                 return bc_error("stack has too few elements");
5666
5667         ptr = bc_vec_top(&G.prog.results);
5668         if ((ptr->t == BC_RESULT_ARRAY) != !var)
5669                 return bc_error("variable is wrong type");
5670         v = bc_program_search(name, var);
5671
5672 #if ENABLE_DC
5673         if (ptr->t == BC_RESULT_STR && !var)
5674                 return bc_error("variable is wrong type");
5675         if (ptr->t == BC_RESULT_STR) return bc_program_assignStr(ptr, v, true);
5676 #endif
5677
5678         s = bc_program_num(ptr, &n, false);
5679         if (s) return s;
5680
5681         // Do this once more to make sure that pointers were not invalidated.
5682         v = bc_program_search(name, var);
5683
5684         if (var) {
5685                 bc_num_init(&r.d.n, BC_NUM_DEF_SIZE);
5686                 bc_num_copy(&r.d.n, n);
5687         }
5688         else {
5689                 bc_array_init(&r.d.v, true);
5690                 bc_array_copy(&r.d.v, (BcVec *) n);
5691         }
5692
5693         bc_vec_push(v, &r.d);
5694         bc_vec_pop(&G.prog.results);
5695
5696         return s;
5697 }
5698
5699 static BcStatus bc_program_assign(char inst)
5700 {
5701         BcStatus s;
5702         BcResult *left, *right, res;
5703         BcNum *l = NULL, *r = NULL;
5704         unsigned long val, max;
5705         bool assign = inst == BC_INST_ASSIGN, ib, sc;
5706
5707         s = bc_program_binOpPrep(&left, &l, &right, &r, assign);
5708         if (s) return s;
5709
5710         ib = left->t == BC_RESULT_IBASE;
5711         sc = left->t == BC_RESULT_SCALE;
5712
5713 #if ENABLE_DC
5714
5715         if (right->t == BC_RESULT_STR) {
5716
5717                 BcVec *v;
5718
5719                 if (left->t != BC_RESULT_VAR)
5720                         return bc_error("variable is wrong type");
5721                 v = bc_program_search(left->d.id.name, true);
5722
5723                 return bc_program_assignStr(right, v, false);
5724         }
5725 #endif
5726
5727         if (left->t == BC_RESULT_CONSTANT || left->t == BC_RESULT_TEMP)
5728                 return bc_error("bad assignment:"
5729                                 " left side must be scale,"
5730                                 " ibase, obase, last, var,"
5731                                 " or array element"
5732                 );
5733
5734 #if ENABLE_BC
5735         if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &G.prog.zero))
5736                 return bc_error("divide by zero");
5737
5738         if (assign)
5739                 bc_num_copy(l, r);
5740         else
5741                 s = bc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale);
5742
5743         if (s) return s;
5744 #else
5745         bc_num_copy(l, r);
5746 #endif
5747
5748         if (ib || sc || left->t == BC_RESULT_OBASE) {
5749                 static const char *const msg[] = {
5750                         "bad ibase; must be [2, 16]",           //BC_RESULT_IBASE
5751                         "bad scale; must be [0, BC_SCALE_MAX]", //BC_RESULT_SCALE
5752                         "?1",                                   //BC_RESULT_LAST
5753                         "?2",                                   //BC_RESULT_CONSTANT
5754                         "?3",                                   //BC_RESULT_ONE
5755                         "bad obase; must be [2, BC_BASE_MAX]",  //BC_RESULT_OBASE
5756                 };
5757                 size_t *ptr;
5758
5759                 s = bc_num_ulong(l, &val);
5760                 if (s)
5761                         return s;
5762                 s = left->t - BC_RESULT_IBASE;
5763                 if (sc) {
5764                         max = BC_MAX_SCALE;
5765                         ptr = &G.prog.scale;
5766                 }
5767                 else {
5768                         if (val < BC_NUM_MIN_BASE)
5769                                 return bc_error(msg[s]);
5770                         max = ib ? BC_NUM_MAX_IBASE : BC_MAX_OBASE;
5771                         ptr = ib ? &G.prog.ib_t : &G.prog.ob_t;
5772                 }
5773
5774                 if (val > max)
5775                         return bc_error(msg[s]);
5776                 if (!sc)
5777                         bc_num_copy(ib ? &G.prog.ib : &G.prog.ob, l);
5778
5779                 *ptr = (size_t) val;
5780                 s = BC_STATUS_SUCCESS;
5781         }
5782
5783         bc_num_init(&res.d.n, l->len);
5784         bc_num_copy(&res.d.n, l);
5785         bc_program_binOpRetire(&res);
5786
5787         return s;
5788 }
5789
5790 #if !ENABLE_DC
5791 #define bc_program_pushVar(code, bgn, pop, copy) \
5792         bc_program_pushVar(code, bgn)
5793 // for bc, 'pop' and 'copy' are always false
5794 #endif
5795 static BcStatus bc_program_pushVar(char *code, size_t *bgn,
5796                                    bool pop, bool copy)
5797 {
5798         BcStatus s = BC_STATUS_SUCCESS;
5799         BcResult r;
5800         char *name = bc_program_name(code, bgn);
5801
5802         r.t = BC_RESULT_VAR;
5803         r.d.id.name = name;
5804
5805 #if ENABLE_DC
5806         {
5807                 BcVec *v = bc_program_search(name, true);
5808                 BcNum *num = bc_vec_top(v);
5809
5810                 if (pop || copy) {
5811
5812                         if (!BC_PROG_STACK(v, 2 - copy)) {
5813                                 free(name);
5814                                 return bc_error("stack has too few elements");
5815                         }
5816
5817                         free(name);
5818                         name = NULL;
5819
5820                         if (!BC_PROG_STR(num)) {
5821
5822                                 r.t = BC_RESULT_TEMP;
5823
5824                                 bc_num_init(&r.d.n, BC_NUM_DEF_SIZE);
5825                                 bc_num_copy(&r.d.n, num);
5826                         }
5827                         else {
5828                                 r.t = BC_RESULT_STR;
5829                                 r.d.id.idx = num->rdx;
5830                         }
5831
5832                         if (!copy) bc_vec_pop(v);
5833                 }
5834         }
5835 #endif // ENABLE_DC
5836
5837         bc_vec_push(&G.prog.results, &r);
5838
5839         return s;
5840 }
5841
5842 static BcStatus bc_program_pushArray(char *code, size_t *bgn,
5843                                      char inst)
5844 {
5845         BcStatus s = BC_STATUS_SUCCESS;
5846         BcResult r;
5847         BcNum *num;
5848
5849         r.d.id.name = bc_program_name(code, bgn);
5850
5851         if (inst == BC_INST_ARRAY) {
5852                 r.t = BC_RESULT_ARRAY;
5853                 bc_vec_push(&G.prog.results, &r);
5854         }
5855         else {
5856
5857                 BcResult *operand;
5858                 unsigned long temp;
5859
5860                 s = bc_program_prep(&operand, &num);
5861                 if (s) goto err;
5862                 s = bc_num_ulong(num, &temp);
5863                 if (s) goto err;
5864
5865                 if (temp > BC_MAX_DIM) {
5866                         s = bc_error("array too long; must be [1, BC_DIM_MAX]");
5867                         goto err;
5868                 }
5869
5870                 r.d.id.idx = (size_t) temp;
5871                 bc_program_retire(&r, BC_RESULT_ARRAY_ELEM);
5872         }
5873
5874 err:
5875         if (s) free(r.d.id.name);
5876         return s;
5877 }
5878
5879 #if ENABLE_BC
5880 static BcStatus bc_program_incdec(char inst)
5881 {
5882         BcStatus s;
5883         BcResult *ptr, res, copy;
5884         BcNum *num = NULL;
5885         char inst2 = inst;
5886
5887         s = bc_program_prep(&ptr, &num);
5888         if (s) return s;
5889
5890         if (inst == BC_INST_INC_POST || inst == BC_INST_DEC_POST) {
5891                 copy.t = BC_RESULT_TEMP;
5892                 bc_num_init(&copy.d.n, num->len);
5893                 bc_num_copy(&copy.d.n, num);
5894         }
5895
5896         res.t = BC_RESULT_ONE;
5897         inst = inst == BC_INST_INC_PRE || inst == BC_INST_INC_POST ?
5898                    BC_INST_ASSIGN_PLUS :
5899                    BC_INST_ASSIGN_MINUS;
5900
5901         bc_vec_push(&G.prog.results, &res);
5902         bc_program_assign(inst);
5903
5904         if (inst2 == BC_INST_INC_POST || inst2 == BC_INST_DEC_POST) {
5905                 bc_vec_pop(&G.prog.results);
5906                 bc_vec_push(&G.prog.results, &copy);
5907         }
5908
5909         return s;
5910 }
5911
5912 static BcStatus bc_program_call(char *code, size_t *idx)
5913 {
5914         BcStatus s = BC_STATUS_SUCCESS;
5915         BcInstPtr ip;
5916         size_t i, nparams = bc_program_index(code, idx);
5917         BcFunc *func;
5918         BcId *a;
5919         BcResultData param;
5920         BcResult *arg;
5921
5922         ip.idx = 0;
5923         ip.func = bc_program_index(code, idx);
5924         func = bc_vec_item(&G.prog.fns, ip.func);
5925
5926         if (func->code.len == 0) {
5927                 return bc_error("undefined function");
5928         }
5929         if (nparams != func->nparams) {
5930                 return bc_error("function has %u parameters, but called with %u", func->nparams, nparams);
5931         }
5932         ip.len = G.prog.results.len - nparams;
5933
5934         for (i = 0; i < nparams; ++i) {
5935
5936                 a = bc_vec_item(&func->autos, nparams - 1 - i);
5937                 arg = bc_vec_top(&G.prog.results);
5938
5939                 if ((!a->idx) != (arg->t == BC_RESULT_ARRAY) || arg->t == BC_RESULT_STR)
5940                         return bc_error("variable is wrong type");
5941
5942                 s = bc_program_copyToVar(a->name, a->idx);
5943                 if (s) return s;
5944         }
5945
5946         for (; i < func->autos.len; ++i) {
5947                 BcVec *v;
5948
5949                 a = bc_vec_item(&func->autos, i);
5950                 v = bc_program_search(a->name, a->idx);
5951
5952                 if (a->idx) {
5953                         bc_num_init(&param.n, BC_NUM_DEF_SIZE);
5954                         bc_vec_push(v, &param.n);
5955                 }
5956                 else {
5957                         bc_array_init(&param.v, true);
5958                         bc_vec_push(v, &param.v);
5959                 }
5960         }
5961
5962         bc_vec_push(&G.prog.stack, &ip);
5963
5964         return BC_STATUS_SUCCESS;
5965 }
5966
5967 static BcStatus bc_program_return(char inst)
5968 {
5969         BcStatus s;
5970         BcResult res;
5971         BcFunc *f;
5972         size_t i;
5973         BcInstPtr *ip = bc_vec_top(&G.prog.stack);
5974
5975         if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET))
5976                 return bc_error("stack has too few elements");
5977
5978         f = bc_vec_item(&G.prog.fns, ip->func);
5979         res.t = BC_RESULT_TEMP;
5980
5981         if (inst == BC_INST_RET) {
5982
5983                 BcNum *num;
5984                 BcResult *operand = bc_vec_top(&G.prog.results);
5985
5986                 s = bc_program_num(operand, &num, false);
5987                 if (s) return s;
5988                 bc_num_init(&res.d.n, num->len);
5989                 bc_num_copy(&res.d.n, num);
5990         }
5991         else {
5992                 bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
5993                 bc_num_zero(&res.d.n);
5994         }
5995
5996         // We need to pop arguments as well, so this takes that into account.
5997         for (i = 0; i < f->autos.len; ++i) {
5998
5999                 BcVec *v;
6000                 BcId *a = bc_vec_item(&f->autos, i);
6001
6002                 v = bc_program_search(a->name, a->idx);
6003                 bc_vec_pop(v);
6004         }
6005
6006         bc_vec_npop(&G.prog.results, G.prog.results.len - ip->len);
6007         bc_vec_push(&G.prog.results, &res);
6008         bc_vec_pop(&G.prog.stack);
6009
6010         return BC_STATUS_SUCCESS;
6011 }
6012 #endif // ENABLE_BC
6013
6014 static unsigned long bc_program_scale(BcNum *n)
6015 {
6016         return (unsigned long) n->rdx;
6017 }
6018
6019 static unsigned long bc_program_len(BcNum *n)
6020 {
6021         unsigned long len = n->len;
6022         size_t i;
6023
6024         if (n->rdx != n->len) return len;
6025         for (i = n->len - 1; i < n->len && n->num[i] == 0; --len, --i);
6026
6027         return len;
6028 }
6029
6030 static BcStatus bc_program_builtin(char inst)
6031 {
6032         BcStatus s;
6033         BcResult *opnd;
6034         BcNum *num = NULL;
6035         BcResult res;
6036         bool len = inst == BC_INST_LENGTH;
6037
6038         if (!BC_PROG_STACK(&G.prog.results, 1))
6039                 return bc_error("stack has too few elements");
6040         opnd = bc_vec_top(&G.prog.results);
6041
6042         s = bc_program_num(opnd, &num, false);
6043         if (s) return s;
6044
6045 #if ENABLE_DC
6046         if (!BC_PROG_NUM(opnd, num) && !len)
6047                 return bc_error("variable is wrong type");
6048 #endif
6049
6050         bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
6051
6052         if (inst == BC_INST_SQRT) s = bc_num_sqrt(num, &res.d.n, G.prog.scale);
6053 #if ENABLE_BC
6054         else if (len != 0 && opnd->t == BC_RESULT_ARRAY) {
6055                 bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len);
6056         }
6057 #endif
6058 #if ENABLE_DC
6059         else if (len != 0 && !BC_PROG_NUM(opnd, num)) {
6060
6061                 char **str;
6062                 size_t idx = opnd->t == BC_RESULT_STR ? opnd->d.id.idx : num->rdx;
6063
6064                 str = bc_vec_item(&G.prog.strs, idx);
6065                 bc_num_ulong2num(&res.d.n, strlen(*str));
6066         }
6067 #endif
6068         else {
6069                 BcProgramBuiltIn f = len ? bc_program_len : bc_program_scale;
6070                 bc_num_ulong2num(&res.d.n, f(num));
6071         }
6072
6073         bc_program_retire(&res, BC_RESULT_TEMP);
6074
6075         return s;
6076 }
6077
6078 #if ENABLE_DC
6079 static BcStatus bc_program_divmod(void)
6080 {
6081         BcStatus s;
6082         BcResult *opd1, *opd2, res, res2;
6083         BcNum *n1, *n2 = NULL;
6084
6085         s = bc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false);
6086         if (s) return s;
6087
6088         bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
6089         bc_num_init(&res2.d.n, n2->len);
6090
6091         s = bc_num_divmod(n1, n2, &res2.d.n, &res.d.n, G.prog.scale);
6092         if (s) goto err;
6093
6094         bc_program_binOpRetire(&res2);
6095         res.t = BC_RESULT_TEMP;
6096         bc_vec_push(&G.prog.results, &res);
6097
6098         return s;
6099
6100 err:
6101         bc_num_free(&res2.d.n);
6102         bc_num_free(&res.d.n);
6103         return s;
6104 }
6105
6106 static BcStatus bc_program_modexp(void)
6107 {
6108         BcStatus s;
6109         BcResult *r1, *r2, *r3, res;
6110         BcNum *n1, *n2, *n3;
6111
6112         if (!BC_PROG_STACK(&G.prog.results, 3))
6113                 return bc_error("stack has too few elements");
6114         s = bc_program_binOpPrep(&r2, &n2, &r3, &n3, false);
6115         if (s) return s;
6116
6117         r1 = bc_vec_item_rev(&G.prog.results, 2);
6118         s = bc_program_num(r1, &n1, false);
6119         if (s) return s;
6120         if (!BC_PROG_NUM(r1, n1))
6121                 return bc_error("variable is wrong type");
6122
6123         // Make sure that the values have their pointers updated, if necessary.
6124         if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) {
6125
6126                 if (r1->t == r2->t) {
6127                         s = bc_program_num(r2, &n2, false);
6128                         if (s) return s;
6129                 }
6130
6131                 if (r1->t == r3->t) {
6132                         s = bc_program_num(r3, &n3, false);
6133                         if (s) return s;
6134                 }
6135         }
6136
6137         bc_num_init(&res.d.n, n3->len);
6138         s = bc_num_modexp(n1, n2, n3, &res.d.n);
6139         if (s) goto err;
6140
6141         bc_vec_pop(&G.prog.results);
6142         bc_program_binOpRetire(&res);
6143
6144         return s;
6145
6146 err:
6147         bc_num_free(&res.d.n);
6148         return s;
6149 }
6150
6151 static void bc_program_stackLen(void)
6152 {
6153         BcResult res;
6154         size_t len = G.prog.results.len;
6155
6156         res.t = BC_RESULT_TEMP;
6157
6158         bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
6159         bc_num_ulong2num(&res.d.n, len);
6160         bc_vec_push(&G.prog.results, &res);
6161 }
6162
6163 static BcStatus bc_program_asciify(void)
6164 {
6165         BcStatus s;
6166         BcResult *r, res;
6167         BcNum *num = NULL, n;
6168         char *str, *str2, c;
6169         size_t len = G.prog.strs.len, idx;
6170         unsigned long val;
6171
6172         if (!BC_PROG_STACK(&G.prog.results, 1))
6173                 return bc_error("stack has too few elements");
6174         r = bc_vec_top(&G.prog.results);
6175
6176         s = bc_program_num(r, &num, false);
6177         if (s) return s;
6178
6179         if (BC_PROG_NUM(r, num)) {
6180
6181                 bc_num_init(&n, BC_NUM_DEF_SIZE);
6182                 bc_num_copy(&n, num);
6183                 bc_num_truncate(&n, n.rdx);
6184
6185                 s = bc_num_mod(&n, &G.prog.strmb, &n, 0);
6186                 if (s) goto num_err;
6187                 s = bc_num_ulong(&n, &val);
6188                 if (s) goto num_err;
6189
6190                 c = (char) val;
6191
6192                 bc_num_free(&n);
6193         }
6194         else {
6195                 idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx;
6196                 str2 = *((char **) bc_vec_item(&G.prog.strs, idx));
6197                 c = str2[0];
6198         }
6199
6200         str = xmalloc(2);
6201         str[0] = c;
6202         str[1] = '\0';
6203
6204         str2 = xstrdup(str);
6205         bc_program_addFunc(str2, &idx);
6206
6207         if (idx != len + BC_PROG_REQ_FUNCS) {
6208
6209                 for (idx = 0; idx < G.prog.strs.len; ++idx) {
6210                         if (!strcmp(*((char **) bc_vec_item(&G.prog.strs, idx)), str)) {
6211                                 len = idx;
6212                                 break;
6213                         }
6214                 }
6215
6216                 free(str);
6217         }
6218         else
6219                 bc_vec_push(&G.prog.strs, &str);
6220
6221         res.t = BC_RESULT_STR;
6222         res.d.id.idx = len;
6223         bc_vec_pop(&G.prog.results);
6224         bc_vec_push(&G.prog.results, &res);
6225
6226         return BC_STATUS_SUCCESS;
6227
6228 num_err:
6229         bc_num_free(&n);
6230         return s;
6231 }
6232
6233 static BcStatus bc_program_printStream(void)
6234 {
6235         BcStatus s;
6236         BcResult *r;
6237         BcNum *n = NULL;
6238         size_t idx;
6239         char *str;
6240
6241         if (!BC_PROG_STACK(&G.prog.results, 1))
6242                 return bc_error("stack has too few elements");
6243         r = bc_vec_top(&G.prog.results);
6244
6245         s = bc_program_num(r, &n, false);
6246         if (s) return s;
6247
6248         if (BC_PROG_NUM(r, n))
6249                 s = bc_num_stream(n, &G.prog.strmb, &G.prog.nchars, G.prog.len);
6250         else {
6251                 idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : n->rdx;
6252                 str = *((char **) bc_vec_item(&G.prog.strs, idx));
6253                 printf("%s", str);
6254         }
6255
6256         return s;
6257 }
6258
6259 static BcStatus bc_program_nquit(void)
6260 {
6261         BcStatus s;
6262         BcResult *opnd;
6263         BcNum *num = NULL;
6264         unsigned long val;
6265
6266         s = bc_program_prep(&opnd, &num);
6267         if (s) return s;
6268         s = bc_num_ulong(num, &val);
6269         if (s) return s;
6270
6271         bc_vec_pop(&G.prog.results);
6272
6273         if (G.prog.stack.len < val)
6274                 return bc_error("stack has too few elements");
6275         if (G.prog.stack.len == val)
6276                 quit();
6277
6278         bc_vec_npop(&G.prog.stack, val);
6279
6280         return s;
6281 }
6282
6283 static BcStatus bc_program_execStr(char *code, size_t *bgn,
6284                                    bool cond)
6285 {
6286         BcStatus s = BC_STATUS_SUCCESS;
6287         BcResult *r;
6288         char **str;
6289         BcFunc *f;
6290         BcParse prs;
6291         BcInstPtr ip;
6292         size_t fidx, sidx;
6293         BcNum *n;
6294         bool exec;
6295
6296         if (!BC_PROG_STACK(&G.prog.results, 1))
6297                 return bc_error("stack has too few elements");
6298
6299         r = bc_vec_top(&G.prog.results);
6300
6301         if (cond) {
6302
6303                 char *name, *then_name = bc_program_name(code, bgn), *else_name = NULL;
6304
6305                 if (code[*bgn] == BC_PARSE_STREND)
6306                         (*bgn) += 1;
6307                 else
6308                         else_name = bc_program_name(code, bgn);
6309
6310                 exec = r->d.n.len != 0;
6311
6312                 if (exec)
6313                         name = then_name;
6314                 else if (else_name != NULL) {
6315                         exec = true;
6316                         name = else_name;
6317                 }
6318
6319                 if (exec) {
6320                         BcVec *v;
6321                         v = bc_program_search(name, true);
6322                         n = bc_vec_top(v);
6323                 }
6324
6325                 free(then_name);
6326                 free(else_name);
6327
6328                 if (!exec) goto exit;
6329                 if (!BC_PROG_STR(n)) {
6330                         s = bc_error("variable is wrong type");
6331                         goto exit;
6332                 }
6333
6334                 sidx = n->rdx;
6335         }
6336         else {
6337
6338                 if (r->t == BC_RESULT_STR)
6339                         sidx = r->d.id.idx;
6340                 else if (r->t == BC_RESULT_VAR) {
6341                         s = bc_program_num(r, &n, false);
6342                         if (s || !BC_PROG_STR(n)) goto exit;
6343                         sidx = n->rdx;
6344                 }
6345                 else
6346                         goto exit;
6347         }
6348
6349         fidx = sidx + BC_PROG_REQ_FUNCS;
6350
6351         str = bc_vec_item(&G.prog.strs, sidx);
6352         f = bc_vec_item(&G.prog.fns, fidx);
6353
6354         if (f->code.len == 0) {
6355                 common_parse_init(&prs, fidx);
6356                 s = bc_parse_text(&prs, *str);
6357                 if (s) goto err;
6358                 s = common_parse_expr(&prs, BC_PARSE_NOCALL);
6359                 if (s) goto err;
6360
6361                 if (prs.l.t.t != BC_LEX_EOF) {
6362                         s = bc_error("bad expression");
6363                         goto err;
6364                 }
6365
6366                 bc_parse_free(&prs);
6367         }
6368
6369         ip.idx = 0;
6370         ip.len = G.prog.results.len;
6371         ip.func = fidx;
6372
6373         bc_vec_pop(&G.prog.results);
6374         bc_vec_push(&G.prog.stack, &ip);
6375
6376         return BC_STATUS_SUCCESS;
6377
6378 err:
6379         bc_parse_free(&prs);
6380         f = bc_vec_item(&G.prog.fns, fidx);
6381         bc_vec_npop(&f->code, f->code.len);
6382 exit:
6383         bc_vec_pop(&G.prog.results);
6384         return s;
6385 }
6386 #endif // ENABLE_DC
6387
6388 static void bc_program_pushGlobal(char inst)
6389 {
6390         BcResult res;
6391         unsigned long val;
6392
6393         res.t = inst - BC_INST_IBASE + BC_RESULT_IBASE;
6394         if (inst == BC_INST_IBASE)
6395                 val = (unsigned long) G.prog.ib_t;
6396         else if (inst == BC_INST_SCALE)
6397                 val = (unsigned long) G.prog.scale;
6398         else
6399                 val = (unsigned long) G.prog.ob_t;
6400
6401         bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
6402         bc_num_ulong2num(&res.d.n, val);
6403         bc_vec_push(&G.prog.results, &res);
6404 }
6405
6406 static void bc_program_addFunc(char *name, size_t *idx)
6407 {
6408         BcId entry, *entry_ptr;
6409         BcFunc f;
6410         int inserted;
6411
6412         entry.name = name;
6413         entry.idx = G.prog.fns.len;
6414
6415         inserted = bc_map_insert(&G.prog.fn_map, &entry, idx);
6416         if (!inserted) free(name);
6417
6418         entry_ptr = bc_vec_item(&G.prog.fn_map, *idx);
6419         *idx = entry_ptr->idx;
6420
6421         if (!inserted) {
6422
6423                 BcFunc *func = bc_vec_item(&G.prog.fns, entry_ptr->idx);
6424
6425                 // We need to reset these, so the function can be repopulated.
6426                 func->nparams = 0;
6427                 bc_vec_npop(&func->autos, func->autos.len);
6428                 bc_vec_npop(&func->code, func->code.len);
6429                 bc_vec_npop(&func->labels, func->labels.len);
6430         }
6431         else {
6432                 bc_func_init(&f);
6433                 bc_vec_push(&G.prog.fns, &f);
6434         }
6435 }
6436
6437 // Called when parsing or execution detects a failure,
6438 // resets execution structures.
6439 static void bc_program_reset(void)
6440 {
6441         BcFunc *f;
6442         BcInstPtr *ip;
6443
6444         bc_vec_npop(&G.prog.stack, G.prog.stack.len - 1);
6445         bc_vec_npop(&G.prog.results, G.prog.results.len);
6446
6447         f = bc_vec_item(&G.prog.fns, 0);
6448         ip = bc_vec_top(&G.prog.stack);
6449         ip->idx = f->code.len;
6450
6451         // If !tty, no need to check for ^C: we don't have ^C handler,
6452         // we would be killed by a signal and won't reach this place
6453 }
6454
6455 static BcStatus bc_program_exec(void)
6456 {
6457         BcStatus s = BC_STATUS_SUCCESS;
6458         size_t idx;
6459         BcResult r, *ptr;
6460         BcNum *num;
6461         BcInstPtr *ip = bc_vec_top(&G.prog.stack);
6462         BcFunc *func = bc_vec_item(&G.prog.fns, ip->func);
6463         char *code = func->code.v;
6464         bool cond = false;
6465
6466         while (!s && ip->idx < func->code.len) {
6467
6468                 char inst = code[(ip->idx)++];
6469
6470                 switch (inst) {
6471
6472 #if ENABLE_BC
6473                         case BC_INST_JUMP_ZERO:
6474                         {
6475                                 s = bc_program_prep(&ptr, &num);
6476                                 if (s) return s;
6477                                 cond = !bc_num_cmp(num, &G.prog.zero);
6478                                 bc_vec_pop(&G.prog.results);
6479                         }
6480                         // Fallthrough.
6481                         case BC_INST_JUMP:
6482                         {
6483                                 size_t *addr;
6484                                 idx = bc_program_index(code, &ip->idx);
6485                                 addr = bc_vec_item(&func->labels, idx);
6486                                 if (inst == BC_INST_JUMP || cond) ip->idx = *addr;
6487                                 break;
6488                         }
6489
6490                         case BC_INST_CALL:
6491                         {
6492                                 s = bc_program_call(code, &ip->idx);
6493                                 break;
6494                         }
6495
6496                         case BC_INST_INC_PRE:
6497                         case BC_INST_DEC_PRE:
6498                         case BC_INST_INC_POST:
6499                         case BC_INST_DEC_POST:
6500                         {
6501                                 s = bc_program_incdec(inst);
6502                                 break;
6503                         }
6504
6505                         case BC_INST_HALT:
6506                         {
6507                                 quit();
6508                                 break;
6509                         }
6510
6511                         case BC_INST_RET:
6512                         case BC_INST_RET0:
6513                         {
6514                                 s = bc_program_return(inst);
6515                                 break;
6516                         }
6517
6518                         case BC_INST_BOOL_OR:
6519                         case BC_INST_BOOL_AND:
6520 #endif // ENABLE_BC
6521                         case BC_INST_REL_EQ:
6522                         case BC_INST_REL_LE:
6523                         case BC_INST_REL_GE:
6524                         case BC_INST_REL_NE:
6525                         case BC_INST_REL_LT:
6526                         case BC_INST_REL_GT:
6527                         {
6528                                 s = bc_program_logical(inst);
6529                                 break;
6530                         }
6531
6532                         case BC_INST_READ:
6533                         {
6534                                 s = bc_program_read();
6535                                 break;
6536                         }
6537
6538                         case BC_INST_VAR:
6539                         {
6540                                 s = bc_program_pushVar(code, &ip->idx, false, false);
6541                                 break;
6542                         }
6543
6544                         case BC_INST_ARRAY_ELEM:
6545                         case BC_INST_ARRAY:
6546                         {
6547                                 s = bc_program_pushArray(code, &ip->idx, inst);
6548                                 break;
6549                         }
6550
6551                         case BC_INST_LAST:
6552                         {
6553                                 r.t = BC_RESULT_LAST;
6554                                 bc_vec_push(&G.prog.results, &r);
6555                                 break;
6556                         }
6557
6558                         case BC_INST_IBASE:
6559                         case BC_INST_SCALE:
6560                         case BC_INST_OBASE:
6561                         {
6562                                 bc_program_pushGlobal(inst);
6563                                 break;
6564                         }
6565
6566                         case BC_INST_SCALE_FUNC:
6567                         case BC_INST_LENGTH:
6568                         case BC_INST_SQRT:
6569                         {
6570                                 s = bc_program_builtin(inst);
6571                                 break;
6572                         }
6573
6574                         case BC_INST_NUM:
6575                         {
6576                                 r.t = BC_RESULT_CONSTANT;
6577                                 r.d.id.idx = bc_program_index(code, &ip->idx);
6578                                 bc_vec_push(&G.prog.results, &r);
6579                                 break;
6580                         }
6581
6582                         case BC_INST_POP:
6583                         {
6584                                 if (!BC_PROG_STACK(&G.prog.results, 1))
6585                                         s = bc_error("stack has too few elements");
6586                                 else
6587                                         bc_vec_pop(&G.prog.results);
6588                                 break;
6589                         }
6590
6591                         case BC_INST_POP_EXEC:
6592                         {
6593                                 bc_vec_pop(&G.prog.stack);
6594                                 break;
6595                         }
6596
6597                         case BC_INST_PRINT:
6598                         case BC_INST_PRINT_POP:
6599                         case BC_INST_PRINT_STR:
6600                         {
6601                                 s = bc_program_print(inst, 0);
6602                                 break;
6603                         }
6604
6605                         case BC_INST_STR:
6606                         {
6607                                 r.t = BC_RESULT_STR;
6608                                 r.d.id.idx = bc_program_index(code, &ip->idx);
6609                                 bc_vec_push(&G.prog.results, &r);
6610                                 break;
6611                         }
6612
6613                         case BC_INST_POWER:
6614                         case BC_INST_MULTIPLY:
6615                         case BC_INST_DIVIDE:
6616                         case BC_INST_MODULUS:
6617                         case BC_INST_PLUS:
6618                         case BC_INST_MINUS:
6619                         {
6620                                 s = bc_program_op(inst);
6621                                 break;
6622                         }
6623
6624                         case BC_INST_BOOL_NOT:
6625                         {
6626                                 s = bc_program_prep(&ptr, &num);
6627                                 if (s) return s;
6628
6629                                 bc_num_init(&r.d.n, BC_NUM_DEF_SIZE);
6630                                 (!bc_num_cmp(num, &G.prog.zero) ? bc_num_one : bc_num_zero)(&r.d.n);
6631                                 bc_program_retire(&r, BC_RESULT_TEMP);
6632
6633                                 break;
6634                         }
6635
6636                         case BC_INST_NEG:
6637                         {
6638                                 s = bc_program_negate();
6639                                 break;
6640                         }
6641
6642 #if ENABLE_BC
6643                         case BC_INST_ASSIGN_POWER:
6644                         case BC_INST_ASSIGN_MULTIPLY:
6645                         case BC_INST_ASSIGN_DIVIDE:
6646                         case BC_INST_ASSIGN_MODULUS:
6647                         case BC_INST_ASSIGN_PLUS:
6648                         case BC_INST_ASSIGN_MINUS:
6649 #endif
6650                         case BC_INST_ASSIGN:
6651                         {
6652                                 s = bc_program_assign(inst);
6653                                 break;
6654                         }
6655 #if ENABLE_DC
6656                         case BC_INST_MODEXP:
6657                         {
6658                                 s = bc_program_modexp();
6659                                 break;
6660                         }
6661
6662                         case BC_INST_DIVMOD:
6663                         {
6664                                 s = bc_program_divmod();
6665                                 break;
6666                         }
6667
6668                         case BC_INST_EXECUTE:
6669                         case BC_INST_EXEC_COND:
6670                         {
6671                                 cond = inst == BC_INST_EXEC_COND;
6672                                 s = bc_program_execStr(code, &ip->idx, cond);
6673                                 break;
6674                         }
6675
6676                         case BC_INST_PRINT_STACK:
6677                         {
6678                                 for (idx = 0; !s && idx < G.prog.results.len; ++idx)
6679                                         s = bc_program_print(BC_INST_PRINT, idx);
6680                                 break;
6681                         }
6682
6683                         case BC_INST_CLEAR_STACK:
6684                         {
6685                                 bc_vec_npop(&G.prog.results, G.prog.results.len);
6686                                 break;
6687                         }
6688
6689                         case BC_INST_STACK_LEN:
6690                         {
6691                                 bc_program_stackLen();
6692                                 break;
6693                         }
6694
6695                         case BC_INST_DUPLICATE:
6696                         {
6697                                 if (!BC_PROG_STACK(&G.prog.results, 1))
6698                                         return bc_error("stack has too few elements");
6699                                 ptr = bc_vec_top(&G.prog.results);
6700                                 bc_result_copy(&r, ptr);
6701                                 bc_vec_push(&G.prog.results, &r);
6702                                 break;
6703                         }
6704
6705                         case BC_INST_SWAP:
6706                         {
6707                                 BcResult *ptr2;
6708
6709                                 if (!BC_PROG_STACK(&G.prog.results, 2))
6710                                         return bc_error("stack has too few elements");
6711
6712                                 ptr = bc_vec_item_rev(&G.prog.results, 0);
6713                                 ptr2 = bc_vec_item_rev(&G.prog.results, 1);
6714                                 memcpy(&r, ptr, sizeof(BcResult));
6715                                 memcpy(ptr, ptr2, sizeof(BcResult));
6716                                 memcpy(ptr2, &r, sizeof(BcResult));
6717
6718                                 break;
6719                         }
6720
6721                         case BC_INST_ASCIIFY:
6722                         {
6723                                 s = bc_program_asciify();
6724                                 break;
6725                         }
6726
6727                         case BC_INST_PRINT_STREAM:
6728                         {
6729                                 s = bc_program_printStream();
6730                                 break;
6731                         }
6732
6733                         case BC_INST_LOAD:
6734                         case BC_INST_PUSH_VAR:
6735                         {
6736                                 bool copy = inst == BC_INST_LOAD;
6737                                 s = bc_program_pushVar(code, &ip->idx, true, copy);
6738                                 break;
6739                         }
6740
6741                         case BC_INST_PUSH_TO_VAR:
6742                         {
6743                                 char *name = bc_program_name(code, &ip->idx);
6744                                 s = bc_program_copyToVar(name, true);
6745                                 free(name);
6746                                 break;
6747                         }
6748
6749                         case BC_INST_QUIT:
6750                         {
6751                                 if (G.prog.stack.len <= 2)
6752                                         quit();
6753                                 bc_vec_npop(&G.prog.stack, 2);
6754                                 break;
6755                         }
6756
6757                         case BC_INST_NQUIT:
6758                         {
6759                                 s = bc_program_nquit();
6760                                 break;
6761                         }
6762 #endif // ENABLE_DC
6763                 }
6764
6765                 if (s || G_interrupt) {
6766                         bc_program_reset();
6767                         break;
6768                 }
6769
6770                 // If the stack has changed, pointers may be invalid.
6771                 ip = bc_vec_top(&G.prog.stack);
6772                 func = bc_vec_item(&G.prog.fns, ip->func);
6773                 code = func->code.v;
6774         }
6775
6776         return s;
6777 }
6778
6779 static void bc_vm_info(void)
6780 {
6781         printf("%s "BB_VER"\n"
6782                 "Copyright (c) 2018 Gavin D. Howard and contributors\n"
6783                 "Report bugs at: https://github.com/gavinhoward/bc\n"
6784                 "This is free software with ABSOLUTELY NO WARRANTY\n"
6785         , applet_name);
6786 }
6787
6788 #if ENABLE_BC
6789 static void bc_vm_envArgs(void)
6790 {
6791         static const char* const bc_args_env_name = "BC_ENV_ARGS";
6792
6793         BcVec v;
6794         char *env_args = getenv(bc_args_env_name), *buf;
6795
6796         if (!env_args) return;
6797
6798         G.env_args = xstrdup(env_args);
6799         buf = G.env_args;
6800
6801         bc_vec_init(&v, sizeof(char *), NULL);
6802         bc_vec_push(&v, &bc_args_env_name);
6803
6804         while (*buf != 0) {
6805                 if (!isspace(*buf)) {
6806                         bc_vec_push(&v, &buf);
6807                         while (*buf != 0 && !isspace(*buf)) ++buf;
6808                         if (*buf != 0) (*(buf++)) = '\0';
6809                 }
6810                 else
6811                         ++buf;
6812         }
6813
6814         bc_args((int) v.len, (char **) v.v);
6815
6816         bc_vec_free(&v);
6817 }
6818 #endif // ENABLE_BC
6819
6820 static size_t bc_vm_envLen(const char *var)
6821 {
6822         char *lenv = getenv(var);
6823         size_t i, len = BC_NUM_PRINT_WIDTH;
6824         int num;
6825
6826         if (!lenv) return len;
6827
6828         len = strlen(lenv);
6829
6830         for (num = 1, i = 0; num && i < len; ++i) num = isdigit(lenv[i]);
6831         if (num) {
6832                 len = (size_t) atoi(lenv) - 1;
6833                 if (len < 2 || len >= INT32_MAX) len = BC_NUM_PRINT_WIDTH;
6834         }
6835         else
6836                 len = BC_NUM_PRINT_WIDTH;
6837
6838         return len;
6839 }
6840
6841 static BcStatus bc_vm_process(const char *text)
6842 {
6843         BcStatus s = bc_parse_text(&G.prs, text);
6844
6845         if (s) return s;
6846
6847         while (G.prs.l.t.t != BC_LEX_EOF) {
6848                 s = G.prs.parse(&G.prs);
6849                 if (s) return s;
6850         }
6851
6852         if (BC_PARSE_CAN_EXEC(&G.prs)) {
6853                 s = bc_program_exec();
6854                 fflush_and_check();
6855                 if (s)
6856                         bc_program_reset();
6857         }
6858
6859         return s;
6860 }
6861
6862 static BcStatus bc_vm_file(const char *file)
6863 {
6864         BcStatus s;
6865         char *data;
6866         BcFunc *main_func;
6867         BcInstPtr *ip;
6868
6869         G.prog.file = file;
6870         data = bc_read_file(file);
6871         if (!data) return bc_error("file '%s' is not text", file);
6872
6873         bc_lex_file(&G.prs.l, file);
6874         s = bc_vm_process(data);
6875         if (s) goto err;
6876
6877         main_func = bc_vec_item(&G.prog.fns, BC_PROG_MAIN);
6878         ip = bc_vec_item(&G.prog.stack, 0);
6879
6880         if (main_func->code.len < ip->idx)
6881                 s = bc_error("file '%s' is not executable", file);
6882
6883 err:
6884         free(data);
6885         return s;
6886 }
6887
6888 static BcStatus bc_vm_stdin(void)
6889 {
6890         BcStatus s;
6891         BcVec buf, buffer;
6892         size_t len, i, str = 0;
6893         bool comment = false;
6894
6895         G.prog.file = bc_program_stdin_name;
6896         bc_lex_file(&G.prs.l, bc_program_stdin_name);
6897
6898         bc_vec_init(&buffer, sizeof(char), NULL);
6899         bc_vec_init(&buf, sizeof(char), NULL);
6900         bc_vec_pushByte(&buffer, '\0');
6901
6902         // This loop is complex because the vm tries not to send any lines that end
6903         // with a backslash to the parser. The reason for that is because the parser
6904         // treats a backslash+newline combo as whitespace, per the bc spec. In that
6905         // case, and for strings and comments, the parser will expect more stuff.
6906         while (!G.eof && (s = bc_read_line(&buf, ">>> ")) == BC_STATUS_SUCCESS) {
6907
6908                 char *string = buf.v;
6909
6910                 len = buf.len - 1;
6911
6912                 if (len == 1) {
6913                         if (str && buf.v[0] == G.send)
6914                                 str -= 1;
6915                         else if (buf.v[0] == G.sbgn)
6916                                 str += 1;
6917                 }
6918                 else if (len > 1 || comment) {
6919
6920                         for (i = 0; i < len; ++i) {
6921
6922                                 bool notend = len > i + 1;
6923                                 char c = string[i];
6924
6925                                 if (i - 1 > len || string[i - 1] != '\\') {
6926                                         if (G.sbgn == G.send)
6927                                                 str ^= c == G.sbgn;
6928                                         else if (c == G.send)
6929                                                 str -= 1;
6930                                         else if (c == G.sbgn)
6931                                                 str += 1;
6932                                 }
6933
6934                                 if (c == '/' && notend && !comment && string[i + 1] == '*') {
6935                                         comment = true;
6936                                         break;
6937                                 }
6938                                 else if (c == '*' && notend && comment && string[i + 1] == '/')
6939                                         comment = false;
6940                         }
6941
6942                         if (str || comment || string[len - 2] == '\\') {
6943                                 bc_vec_concat(&buffer, buf.v);
6944                                 continue;
6945                         }
6946                 }
6947
6948                 bc_vec_concat(&buffer, buf.v);
6949                 s = bc_vm_process(buffer.v);
6950                 if (s) {
6951                         fflush_and_check();
6952                         fputs("ready for more input\n", stderr);
6953                 }
6954
6955                 bc_vec_npop(&buffer, buffer.len);
6956         }
6957
6958         if (str) {
6959                 s = bc_error("string end could not be found");
6960         }
6961         else if (comment) {
6962                 s = bc_error("comment end could not be found");
6963         }
6964
6965         bc_vec_free(&buf);
6966         bc_vec_free(&buffer);
6967         return s;
6968 }
6969
6970 static BcStatus bc_vm_exec(void)
6971 {
6972         BcStatus s = BC_STATUS_SUCCESS;
6973         size_t i;
6974
6975 #if ENABLE_BC
6976         if (option_mask32 & BC_FLAG_L) {
6977
6978                 bc_lex_file(&G.prs.l, bc_lib_name);
6979                 s = bc_parse_text(&G.prs, bc_lib);
6980
6981                 while (!s && G.prs.l.t.t != BC_LEX_EOF)
6982                         s = G.prs.parse(&G.prs);
6983
6984                 if (s) return s;
6985                 s = bc_program_exec();
6986                 if (s) return s;
6987         }
6988 #endif
6989
6990         for (i = 0; !s && i < G.files.len; ++i)
6991                 s = bc_vm_file(*((char **) bc_vec_item(&G.files, i)));
6992         if (s) {
6993                 fflush_and_check();
6994                 fputs("ready for more input\n", stderr);
6995         }
6996
6997         if (IS_BC || !G.files.len)
6998                 s = bc_vm_stdin();
6999         if (!s && !BC_PARSE_CAN_EXEC(&G.prs))
7000                 s = bc_vm_process("");
7001
7002         return s;
7003 }
7004
7005 #if ENABLE_FEATURE_CLEAN_UP
7006 static void bc_program_free()
7007 {
7008         bc_num_free(&G.prog.ib);
7009         bc_num_free(&G.prog.ob);
7010         bc_num_free(&G.prog.hexb);
7011 # if ENABLE_DC
7012         bc_num_free(&G.prog.strmb);
7013 # endif
7014         bc_vec_free(&G.prog.fns);
7015         bc_vec_free(&G.prog.fn_map);
7016         bc_vec_free(&G.prog.vars);
7017         bc_vec_free(&G.prog.var_map);
7018         bc_vec_free(&G.prog.arrs);
7019         bc_vec_free(&G.prog.arr_map);
7020         bc_vec_free(&G.prog.strs);
7021         bc_vec_free(&G.prog.consts);
7022         bc_vec_free(&G.prog.results);
7023         bc_vec_free(&G.prog.stack);
7024         bc_num_free(&G.prog.last);
7025         bc_num_free(&G.prog.zero);
7026         bc_num_free(&G.prog.one);
7027 }
7028
7029 static void bc_vm_free(void)
7030 {
7031         bc_vec_free(&G.files);
7032         bc_program_free();
7033         bc_parse_free(&G.prs);
7034         free(G.env_args);
7035 }
7036 #endif
7037
7038 static void bc_program_init(size_t line_len)
7039 {
7040         size_t idx;
7041         BcInstPtr ip;
7042
7043         /* memset(&G.prog, 0, sizeof(G.prog)); - already is */
7044         memset(&ip, 0, sizeof(BcInstPtr));
7045
7046         /* G.prog.nchars = G.prog.scale = 0; - already is */
7047         G.prog.len = line_len;
7048
7049         bc_num_init(&G.prog.ib, BC_NUM_DEF_SIZE);
7050         bc_num_ten(&G.prog.ib);
7051         G.prog.ib_t = 10;
7052
7053         bc_num_init(&G.prog.ob, BC_NUM_DEF_SIZE);
7054         bc_num_ten(&G.prog.ob);
7055         G.prog.ob_t = 10;
7056
7057         bc_num_init(&G.prog.hexb, BC_NUM_DEF_SIZE);
7058         bc_num_ten(&G.prog.hexb);
7059         G.prog.hexb.num[0] = 6;
7060
7061 #if ENABLE_DC
7062         bc_num_init(&G.prog.strmb, BC_NUM_DEF_SIZE);
7063         bc_num_ulong2num(&G.prog.strmb, UCHAR_MAX + 1);
7064 #endif
7065
7066         bc_num_init(&G.prog.last, BC_NUM_DEF_SIZE);
7067         bc_num_zero(&G.prog.last);
7068
7069         bc_num_init(&G.prog.zero, BC_NUM_DEF_SIZE);
7070         bc_num_zero(&G.prog.zero);
7071
7072         bc_num_init(&G.prog.one, BC_NUM_DEF_SIZE);
7073         bc_num_one(&G.prog.one);
7074
7075         bc_vec_init(&G.prog.fns, sizeof(BcFunc), bc_func_free);
7076         bc_map_init(&G.prog.fn_map);
7077
7078         bc_program_addFunc(xstrdup("(main)"), &idx);
7079         bc_program_addFunc(xstrdup("(read)"), &idx);
7080
7081         bc_vec_init(&G.prog.vars, sizeof(BcVec), bc_vec_free);
7082         bc_map_init(&G.prog.var_map);
7083
7084         bc_vec_init(&G.prog.arrs, sizeof(BcVec), bc_vec_free);
7085         bc_map_init(&G.prog.arr_map);
7086
7087         bc_vec_init(&G.prog.strs, sizeof(char *), bc_string_free);
7088         bc_vec_init(&G.prog.consts, sizeof(char *), bc_string_free);
7089         bc_vec_init(&G.prog.results, sizeof(BcResult), bc_result_free);
7090         bc_vec_init(&G.prog.stack, sizeof(BcInstPtr), NULL);
7091         bc_vec_push(&G.prog.stack, &ip);
7092 }
7093
7094 static void bc_vm_init(const char *env_len)
7095 {
7096         size_t len = bc_vm_envLen(env_len);
7097
7098         bc_vec_init(&G.files, sizeof(char *), NULL);
7099
7100         if (IS_BC) {
7101                 bc_vm_envArgs();
7102         }
7103
7104         bc_program_init(len);
7105         if (IS_BC) {
7106                 bc_parse_init(&G.prs, BC_PROG_MAIN);
7107         } else {
7108                 dc_parse_init(&G.prs, BC_PROG_MAIN);
7109         }
7110 }
7111
7112 static BcStatus bc_vm_run(int argc, char *argv[],
7113                           const char *env_len)
7114 {
7115         BcStatus st;
7116
7117         bc_vm_init(env_len);
7118         bc_args(argc, argv);
7119
7120         G.ttyin = isatty(0);
7121
7122         if (G.ttyin) {
7123 #if ENABLE_FEATURE_BC_SIGNALS
7124                 // With SA_RESTART, most system calls will restart
7125                 // (IOW: they won't fail with EINTR).
7126                 // In particular, this means ^C won't cause
7127                 // stdout to get into "error state" if SIGINT hits
7128                 // within write() syscall.
7129                 // The downside is that ^C while line input is taken
7130                 // will only be handled after [Enter] since read()
7131                 // from stdin is not interrupted by ^C either,
7132                 // it restarts, thus fgetc() does not return on ^C.
7133                 signal_SA_RESTART_empty_mask(SIGINT, record_signo);
7134
7135                 // Without SA_RESTART, this exhibits a bug:
7136                 // "while (1) print 1" and try ^C-ing it.
7137                 // Intermittently, instead of returning to input line,
7138                 // you'll get "output error: Interrupted system call"
7139                 // and exit.
7140                 //signal_no_SA_RESTART_empty_mask(SIGINT, record_signo);
7141 #endif
7142                 if (!(option_mask32 & BC_FLAG_Q))
7143                         bc_vm_info();
7144         }
7145         st = bc_vm_exec();
7146
7147 #if ENABLE_FEATURE_CLEAN_UP
7148         bc_vm_free();
7149 #endif
7150         return st;
7151 }
7152
7153 #if ENABLE_BC
7154 int bc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
7155 int bc_main(int argc, char **argv)
7156 {
7157         INIT_G();
7158         G.sbgn = G.send = '"';
7159
7160         return bc_vm_run(argc, argv, "BC_LINE_LENGTH");
7161 }
7162 #endif
7163
7164 #if ENABLE_DC
7165 int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
7166 int dc_main(int argc, char **argv)
7167 {
7168         INIT_G();
7169         G.sbgn = '[';
7170         G.send = ']';
7171
7172         return bc_vm_run(argc, argv, "DC_LINE_LENGTH");
7173 }
7174 #endif