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