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