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