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