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