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