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