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