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