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