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