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