bf0cbc39747a226847d0ce8b0036a2a3e111d0b4
[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 #ifdef ENABLE_DC
177         BC_STATUS_LEX_EXTENDED_REG,
178 #endif // ENABLE_DC
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 #ifdef 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 // ENABLE_BC
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 #ifdef ENABLE_BC
245 #define BC_ERR_IDX_POSIX (6)
246 #endif // ENABLE_BC
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 #ifdef ENABLE_BC
318         BC_INST_INC_PRE,
319         BC_INST_DEC_PRE,
320         BC_INST_INC_POST,
321         BC_INST_DEC_POST,
322 #endif // ENABLE_BC
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 #ifdef 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 // ENABLE_BC
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 #ifdef 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 // ENABLE_BC
384
385         BC_INST_POP,
386         BC_INST_POP_EXEC,
387
388 #ifdef 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 // ENABLE_DC
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 #ifdef 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 // ENABLE_DC
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 #ifdef 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 // ENABLE_BC
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 #ifdef ENABLE_DC
750         BcNum strmb;
751 #endif // ENABLE_DC
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 #ifdef ENABLE_DC
787 #define BC_PROG_REQ_FUNCS (2)
788 #endif // ENABLE_DC
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 // ENABLE_FEATURE_BC_SIGNALS
856         const char *help;
857         bool bc;
858
859 } BcGlobals;
860
861 #ifdef ENABLE_BC
862 static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line,
863                                  const char *msg);
864 #endif // ENABLE_BC
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 #ifdef 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 // ENABLE_FEATURE_BC_SIGNALS
883 #endif // ENABLE_BC
884
885 #ifdef 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 // ENABLE_FEATURE_BC_SIGNALS
890 #endif // ENABLE_DC
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 #ifdef ENABLE_BC
911         "POSIX",
912 #endif // ENABLE_BC
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 #ifdef ENABLE_DC
919         BC_ERR_IDX_LEX,
920 #endif // ENABLE_DC
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 #ifdef ENABLE_DC
926         BC_ERR_IDX_MATH,
927 #endif // ENABLE_DC
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 #ifdef 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 // ENABLE_BC
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 #ifdef ENABLE_DC
955         "extended register",
956 #endif // ENABLE_DC
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 #ifdef 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 // ENABLE_BC
1009
1010 };
1011
1012 static const char bc_func_main[] = "(main)";
1013 static const char bc_func_read[] = "(read)";
1014
1015 #ifdef 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 #ifdef 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 char bc_num_hex_digits[] = "0123456789ABCDEF";
1144
1145 static const BcNumBinaryOp bc_program_ops[] = {
1146         bc_num_pow, bc_num_mul, bc_num_div, bc_num_mod, bc_num_add, bc_num_sub,
1147 };
1148
1149 static const char bc_program_stdin_name[] = "<stdin>";
1150 static const char bc_program_ready_msg[] = "ready for more input\n";
1151
1152 #ifdef ENABLE_BC
1153 static const char *bc_lib_name = "gen/lib.bc";
1154
1155 static const char bc_lib[] = {
1156   115,99,97,108,101,61,50,48,10,100,101,102,105,110,101,32,101,40,120,41,123,
1157   10,9,97,117,116,111,32,98,44,115,44,110,44,114,44,100,44,105,44,112,44,102,
1158   44,118,10,9,98,61,105,98,97,115,101,10,9,105,98,97,115,101,61,65,10,9,105,102,
1159   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,
1160   61,115,99,97,108,101,10,9,114,61,54,43,115,43,48,46,52,52,42,120,10,9,115,99,
1161   97,108,101,61,115,99,97,108,101,40,120,41,43,49,10,9,119,104,105,108,101,40,
1162   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,
1163   101,43,61,49,10,9,125,10,9,115,99,97,108,101,61,114,10,9,114,61,120,43,49,10,
1164   9,112,61,120,10,9,102,61,118,61,49,10,9,102,111,114,40,105,61,50,59,118,33,
1165   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,
1166   118,61,112,47,102,10,9,9,114,43,61,118,10,9,125,10,9,119,104,105,108,101,40,
1167   40,100,45,45,41,33,61,48,41,114,42,61,114,10,9,115,99,97,108,101,61,115,10,
1168   9,105,98,97,115,101,61,98,10,9,105,102,40,110,33,61,48,41,114,101,116,117,114,
1169   110,40,49,47,114,41,10,9,114,101,116,117,114,110,40,114,47,49,41,10,125,10,
1170   100,101,102,105,110,101,32,108,40,120,41,123,10,9,97,117,116,111,32,98,44,115,
1171   44,114,44,112,44,97,44,113,44,105,44,118,10,9,98,61,105,98,97,115,101,10,9,
1172   105,98,97,115,101,61,65,10,9,105,102,40,120,60,61,48,41,123,10,9,9,114,61,40,
1173   49,45,49,48,94,115,99,97,108,101,41,47,49,10,9,9,105,98,97,115,101,61,98,10,
1174   9,9,114,101,116,117,114,110,40,114,41,10,9,125,10,9,115,61,115,99,97,108,101,
1175   10,9,115,99,97,108,101,43,61,54,10,9,112,61,50,10,9,119,104,105,108,101,40,
1176   120,62,61,50,41,123,10,9,9,112,42,61,50,10,9,9,120,61,115,113,114,116,40,120,
1177   41,10,9,125,10,9,119,104,105,108,101,40,120,60,61,48,46,53,41,123,10,9,9,112,
1178   42,61,50,10,9,9,120,61,115,113,114,116,40,120,41,10,9,125,10,9,114,61,97,61,
1179   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,
1180   102,111,114,40,105,61,51,59,118,33,61,48,59,105,43,61,50,41,123,10,9,9,97,42,
1181   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,
1182   112,10,9,115,99,97,108,101,61,115,10,9,105,98,97,115,101,61,98,10,9,114,101,
1183   116,117,114,110,40,114,47,49,41,10,125,10,100,101,102,105,110,101,32,115,40,
1184   120,41,123,10,9,97,117,116,111,32,98,44,115,44,114,44,110,44,97,44,113,44,105,
1185   10,9,98,61,105,98,97,115,101,10,9,105,98,97,115,101,61,65,10,9,115,61,115,99,
1186   97,108,101,10,9,115,99,97,108,101,61,49,46,49,42,115,43,50,10,9,97,61,97,40,
1187   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,
1188   10,9,125,10,9,115,99,97,108,101,61,48,10,9,113,61,40,120,47,97,43,50,41,47,
1189   52,10,9,120,61,120,45,52,42,113,42,97,10,9,105,102,40,113,37,50,33,61,48,41,
1190   120,61,45,120,10,9,115,99,97,108,101,61,115,43,50,10,9,114,61,97,61,120,10,
1191   9,113,61,45,120,42,120,10,9,102,111,114,40,105,61,51,59,97,33,61,48,59,105,
1192   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,
1193   114,43,61,97,10,9,125,10,9,115,99,97,108,101,61,115,10,9,105,98,97,115,101,
1194   61,98,10,9,105,102,40,110,33,61,48,41,114,101,116,117,114,110,40,45,114,47,
1195   49,41,10,9,114,101,116,117,114,110,40,114,47,49,41,10,125,10,100,101,102,105,
1196   110,101,32,99,40,120,41,123,10,9,97,117,116,111,32,98,44,115,10,9,98,61,105,
1197   98,97,115,101,10,9,105,98,97,115,101,61,65,10,9,115,61,115,99,97,108,101,10,
1198   9,115,99,97,108,101,42,61,49,46,50,10,9,120,61,115,40,50,42,97,40,49,41,43,
1199   120,41,10,9,115,99,97,108,101,61,115,10,9,105,98,97,115,101,61,98,10,9,114,
1200   101,116,117,114,110,40,120,47,49,41,10,125,10,100,101,102,105,110,101,32,97,
1201   40,120,41,123,10,9,97,117,116,111,32,98,44,115,44,114,44,110,44,97,44,109,44,
1202   116,44,102,44,105,44,117,10,9,98,61,105,98,97,115,101,10,9,105,98,97,115,101,
1203   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,
1204   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,
1205   40,115,99,97,108,101,60,54,53,41,123,10,9,9,9,114,101,116,117,114,110,40,46,
1206   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,
1207   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,
1208   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,
1209   9,105,102,40,120,61,61,46,50,41,123,10,9,9,105,102,40,115,99,97,108,101,60,
1210   54,53,41,123,10,9,9,9,114,101,116,117,114,110,40,46,49,57,55,51,57,53,53,53,
1211   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,
1212   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,
1213   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,
1214   10,9,105,102,40,120,62,46,50,41,123,10,9,9,115,99,97,108,101,43,61,53,10,9,
1215   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,
1216   104,105,108,101,40,120,62,46,50,41,123,10,9,9,109,43,61,49,10,9,9,120,61,40,
1217   120,45,46,50,41,47,40,49,43,46,50,42,120,41,10,9,125,10,9,114,61,117,61,120,
1218   10,9,102,61,45,120,42,120,10,9,116,61,49,10,9,102,111,114,40,105,61,51,59,116,
1219   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,
1220   10,9,9,114,43,61,116,10,9,125,10,9,115,99,97,108,101,61,115,10,9,105,98,97,
1221   115,101,61,98,10,9,114,101,116,117,114,110,40,40,109,42,97,43,114,41,47,110,
1222   41,10,125,10,100,101,102,105,110,101,32,106,40,110,44,120,41,123,10,9,97,117,
1223   116,111,32,98,44,115,44,111,44,97,44,105,44,118,44,102,10,9,98,61,105,98,97,
1224   115,101,10,9,105,98,97,115,101,61,65,10,9,115,61,115,99,97,108,101,10,9,115,
1225   99,97,108,101,61,48,10,9,110,47,61,49,10,9,105,102,40,110,60,48,41,123,10,9,
1226   9,110,61,45,110,10,9,9,105,102,40,110,37,50,61,61,49,41,111,61,49,10,9,125,
1227   10,9,97,61,49,10,9,102,111,114,40,105,61,50,59,105,60,61,110,59,43,43,105,41,
1228   97,42,61,105,10,9,115,99,97,108,101,61,49,46,53,42,115,10,9,97,61,40,120,94,
1229   110,41,47,50,94,110,47,97,10,9,114,61,118,61,49,10,9,102,61,45,120,42,120,47,
1230   52,10,9,115,99,97,108,101,61,115,99,97,108,101,43,108,101,110,103,116,104,40,
1231   97,41,45,115,99,97,108,101,40,97,41,10,9,102,111,114,40,105,61,49,59,118,33,
1232   61,48,59,43,43,105,41,123,10,9,9,118,61,118,42,102,47,105,47,40,110,43,105,
1233   41,10,9,9,114,43,61,118,10,9,125,10,9,115,99,97,108,101,61,115,10,9,105,98,
1234   97,115,101,61,98,10,9,105,102,40,111,33,61,48,41,97,61,45,97,10,9,114,101,116,
1235   117,114,110,40,97,42,114,47,49,41,10,125,10,0
1236 };
1237 #endif // ENABLE_BC
1238
1239 static void bc_vec_grow(BcVec *v, size_t n)
1240 {
1241         size_t cap = v->cap * 2;
1242         while (cap < v->len + n) cap *= 2;
1243         v->v = xrealloc(v->v, v->size * cap);
1244         v->cap = cap;
1245 }
1246
1247 static void bc_vec_init(BcVec *v, size_t esize, BcVecFree dtor)
1248 {
1249         v->size = esize;
1250         v->cap = BC_VEC_START_CAP;
1251         v->len = 0;
1252         v->dtor = dtor;
1253         v->v = xmalloc(esize * BC_VEC_START_CAP);
1254 }
1255
1256 static void bc_vec_expand(BcVec *v, size_t req)
1257 {
1258         if (v->cap < req) {
1259                 v->v = xrealloc(v->v, v->size * req);
1260                 v->cap = req;
1261         }
1262 }
1263
1264 static void bc_vec_npop(BcVec *v, size_t n)
1265 {
1266         if (!v->dtor)
1267                 v->len -= n;
1268         else {
1269                 size_t len = v->len - n;
1270                 while (v->len > len) v->dtor(v->v + (v->size * --v->len));
1271         }
1272 }
1273
1274 static void bc_vec_push(BcVec *v, const void *data)
1275 {
1276         if (v->len + 1 > v->cap) bc_vec_grow(v, 1);
1277         memmove(v->v + (v->size * v->len), data, v->size);
1278         v->len += 1;
1279 }
1280
1281 static void bc_vec_pushByte(BcVec *v, char data)
1282 {
1283         bc_vec_push(v, &data);
1284 }
1285
1286 static void bc_vec_pushAt(BcVec *v, const void *data, size_t idx)
1287 {
1288         if (idx == v->len)
1289                 bc_vec_push(v, data);
1290         else {
1291
1292                 char *ptr;
1293
1294                 if (v->len == v->cap) bc_vec_grow(v, 1);
1295
1296                 ptr = v->v + v->size * idx;
1297
1298                 memmove(ptr + v->size, ptr, v->size * (v->len++ - idx));
1299                 memmove(ptr, data, v->size);
1300         }
1301 }
1302
1303 static void bc_vec_string(BcVec *v, size_t len, const char *str)
1304 {
1305         bc_vec_npop(v, v->len);
1306         bc_vec_expand(v, len + 1);
1307         memcpy(v->v, str, len);
1308         v->len = len;
1309
1310         bc_vec_pushByte(v, '\0');
1311 }
1312
1313 static void bc_vec_concat(BcVec *v, const char *str)
1314 {
1315         size_t len;
1316
1317         if (v->len == 0) bc_vec_pushByte(v, '\0');
1318
1319         len = v->len + strlen(str);
1320
1321         if (v->cap < len) bc_vec_grow(v, len - v->len);
1322         strcat(v->v, str);
1323
1324         v->len = len;
1325 }
1326
1327 static void *bc_vec_item(const BcVec *v, size_t idx)
1328 {
1329         return v->v + v->size * idx;
1330 }
1331
1332 static void *bc_vec_item_rev(const BcVec *v, size_t idx)
1333 {
1334         return v->v + v->size * (v->len - idx - 1);
1335 }
1336
1337 static void bc_vec_free(void *vec)
1338 {
1339         BcVec *v = (BcVec *) vec;
1340         bc_vec_npop(v, v->len);
1341         free(v->v);
1342 }
1343
1344 static size_t bc_map_find(const BcVec *v, const void *ptr)
1345 {
1346         size_t low = 0, high = v->len;
1347
1348         while (low < high) {
1349
1350                 size_t mid = (low + high) / 2;
1351                 BcId *id = bc_vec_item(v, mid);
1352                 int result = bc_id_cmp(ptr, id);
1353
1354                 if (result == 0)
1355                         return mid;
1356                 else if (result < 0)
1357                         high = mid;
1358                 else
1359                         low = mid + 1;
1360         }
1361
1362         return low;
1363 }
1364
1365 static BcStatus bc_map_insert(BcVec *v, const void *ptr, size_t *i)
1366 {
1367         BcStatus s = BC_STATUS_SUCCESS;
1368
1369         *i = bc_map_find(v, ptr);
1370
1371         if (*i == v->len)
1372                 bc_vec_push(v, ptr);
1373         else if (!bc_id_cmp(ptr, bc_vec_item(v, *i)))
1374                 s = BC_STATUS_VEC_ITEM_EXISTS;
1375         else
1376                 bc_vec_pushAt(v, ptr, *i);
1377
1378         return s;
1379 }
1380
1381 static size_t bc_map_index(const BcVec *v, const void *ptr)
1382 {
1383         size_t i = bc_map_find(v, ptr);
1384         if (i >= v->len) return BC_VEC_INVALID_IDX;
1385         return bc_id_cmp(ptr, bc_vec_item(v, i)) ? BC_VEC_INVALID_IDX : i;
1386 }
1387
1388 static BcStatus bc_read_line(BcVec *vec, const char *prompt)
1389 {
1390         int i;
1391         signed char c = 0;
1392
1393         if (bcg.ttyin && !bcg.posix) {
1394                 bc_vm_puts(prompt, stderr);
1395                 bc_vm_fflush(stderr);
1396         }
1397
1398         bc_vec_npop(vec, vec->len);
1399
1400         while (c != '\n') {
1401
1402                 i = fgetc(stdin);
1403
1404                 if (i == EOF) {
1405
1406 #if ENABLE_FEATURE_BC_SIGNALS
1407                         if (errno == EINTR) {
1408
1409                                 bcg.sigc = bcg.sig;
1410                                 bcg.signe = 0;
1411
1412                                 if (bcg.ttyin) {
1413                                         bc_vm_puts(bc_program_ready_msg, stderr);
1414                                         if (!bcg.posix) bc_vm_puts(prompt, stderr);
1415                                         bc_vm_fflush(stderr);
1416                                 }
1417
1418                                 continue;
1419                         }
1420 #endif // ENABLE_FEATURE_BC_SIGNALS
1421
1422                         return BC_STATUS_IO_ERR;
1423                 }
1424
1425                 c = (signed char) i;
1426                 if (i > UCHAR_MAX || BC_READ_BIN_CHAR(c)) return BC_STATUS_BIN_FILE;
1427                 bc_vec_push(vec, &c);
1428         }
1429
1430         bc_vec_pushByte(vec, '\0');
1431
1432         return BC_STATUS_SUCCESS;
1433 }
1434
1435 static BcStatus bc_read_file(const char *path, char **buf)
1436 {
1437         BcStatus s = BC_STATUS_BIN_FILE;
1438         size_t size = ((size_t) -1), read;
1439
1440         *buf = xmalloc_open_read_close(path, &size);
1441
1442         for (read = 0; read < size; ++read) {
1443                 if (BC_READ_BIN_CHAR((*buf)[read])) 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 // ENABLE_FEATURE_BC_LONG_OPTIONS
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 // ENABLE_FEATURE_BC_LONG_OPTIONS
1477         *flags = getopt32(argv, bc_args_opt);
1478 #endif // ENABLE_FEATURE_BC_LONG_OPTIONS
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 #ifdef 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 // ENABLE_DC
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, div;
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
2360         for (exp = 0; exp < width; pow /= 10, ++(*nchars), ++exp) {
2361                 bc_num_printNewline(nchars, line_len);
2362                 div = num / pow;
2363                 num -= div * pow;
2364                 bc_vm_putchar(((char) div) + '0');
2365         }
2366 }
2367
2368 static void bc_num_printHex(size_t num, size_t width, bool radix,
2369                             size_t *nchars, size_t line_len)
2370 {
2371         if (radix) {
2372                 bc_num_printNewline(nchars, line_len);
2373                 bc_vm_putchar('.');
2374                 *nchars += 1;
2375         }
2376
2377         bc_num_printNewline(nchars, line_len);
2378         bc_vm_putchar(bc_num_hex_digits[num]);
2379         *nchars = *nchars + width;
2380 }
2381
2382 static void bc_num_printDecimal(BcNum *n, size_t *nchars, size_t len)
2383 {
2384         size_t i, rdx = n->rdx - 1;
2385
2386         if (n->neg) bc_vm_putchar('-');
2387         (*nchars) += n->neg;
2388
2389         for (i = n->len - 1; i < n->len; --i)
2390                 bc_num_printHex((size_t) n->num[i], 1, i == rdx, nchars, len);
2391 }
2392
2393 static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width,
2394                                 size_t *nchars, size_t len, BcNumDigitOp print)
2395 {
2396         BcStatus s;
2397         BcVec stack;
2398         BcNum intp, fracp, digit, frac_len;
2399         unsigned long dig, *ptr;
2400         size_t i;
2401         bool radix;
2402
2403         if (n->len == 0) {
2404                 print(0, width, false, nchars, len);
2405                 return BC_STATUS_SUCCESS;
2406         }
2407
2408         bc_vec_init(&stack, sizeof(long), NULL);
2409         bc_num_init(&intp, n->len);
2410         bc_num_init(&fracp, n->rdx);
2411         bc_num_init(&digit, width);
2412         bc_num_init(&frac_len, BC_NUM_INT(n));
2413         bc_num_copy(&intp, n);
2414         bc_num_one(&frac_len);
2415
2416         bc_num_truncate(&intp, intp.rdx);
2417         s = bc_num_sub(n, &intp, &fracp, 0);
2418         if (s) goto err;
2419
2420         while (intp.len != 0) {
2421                 s = bc_num_divmod(&intp, base, &intp, &digit, 0);
2422                 if (s) goto err;
2423                 s = bc_num_ulong(&digit, &dig);
2424                 if (s) goto err;
2425                 bc_vec_push(&stack, &dig);
2426         }
2427
2428         for (i = 0; i < stack.len; ++i) {
2429                 ptr = bc_vec_item_rev(&stack, i);
2430                 print(*ptr, width, false, nchars, len);
2431         }
2432
2433         if (!n->rdx) goto err;
2434
2435         for (radix = true; frac_len.len <= n->rdx; radix = false) {
2436                 s = bc_num_mul(&fracp, base, &fracp, n->rdx);
2437                 if (s) goto err;
2438                 s = bc_num_ulong(&fracp, &dig);
2439                 if (s) goto err;
2440                 s = bc_num_ulong2num(&intp, dig);
2441                 if (s) goto err;
2442                 s = bc_num_sub(&fracp, &intp, &fracp, 0);
2443                 if (s) goto err;
2444                 print(dig, width, radix, nchars, len);
2445                 s = bc_num_mul(&frac_len, base, &frac_len, 0);
2446                 if (s) goto err;
2447         }
2448
2449 err:
2450         bc_num_free(&frac_len);
2451         bc_num_free(&digit);
2452         bc_num_free(&fracp);
2453         bc_num_free(&intp);
2454         bc_vec_free(&stack);
2455         return s;
2456 }
2457
2458 static BcStatus bc_num_printBase(BcNum *n, BcNum *base, size_t base_t,
2459                                  size_t *nchars, size_t line_len)
2460 {
2461         BcStatus s;
2462         size_t width, i;
2463         BcNumDigitOp print;
2464         bool neg = n->neg;
2465
2466         if (neg) bc_vm_putchar('-');
2467         (*nchars) += neg;
2468
2469         n->neg = false;
2470
2471         if (base_t <= BC_NUM_MAX_IBASE) {
2472                 width = 1;
2473                 print = bc_num_printHex;
2474         }
2475         else {
2476                 for (i = base_t - 1, width = 0; i != 0; i /= 10, ++width);
2477                 print = bc_num_printDigits;
2478         }
2479
2480         s = bc_num_printNum(n, base, width, nchars, line_len, print);
2481         n->neg = neg;
2482
2483         return s;
2484 }
2485
2486 #ifdef ENABLE_DC
2487 static BcStatus bc_num_stream(BcNum *n, BcNum *base, size_t *nchars, size_t len)
2488 {
2489         return bc_num_printNum(n, base, 1, nchars, len, bc_num_printChar);
2490 }
2491 #endif // ENABLE_DC
2492
2493 static void bc_num_init(BcNum *n, size_t req)
2494 {
2495         req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
2496         memset(n, 0, sizeof(BcNum));
2497         n->num = xmalloc(req);
2498         n->cap = req;
2499 }
2500
2501 static void bc_num_expand(BcNum *n, size_t req)
2502 {
2503         req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
2504         if (req > n->cap) {
2505                 n->num = xrealloc(n->num, req);
2506                 n->cap = req;
2507         }
2508 }
2509
2510 static void bc_num_free(void *num)
2511 {
2512         free(((BcNum *) num)->num);
2513 }
2514
2515 static void bc_num_copy(BcNum *d, BcNum *s)
2516 {
2517         if (d != s) {
2518                 bc_num_expand(d, s->cap);
2519                 d->len = s->len;
2520                 d->neg = s->neg;
2521                 d->rdx = s->rdx;
2522                 memcpy(d->num, s->num, sizeof(BcDig) * d->len);
2523         }
2524 }
2525
2526 static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base,
2527                              size_t base_t)
2528 {
2529         if (!bc_num_strValid(val, base_t)) return BC_STATUS_MATH_BAD_STRING;
2530
2531         if (base_t == 10)
2532                 bc_num_parseDecimal(n, val);
2533         else
2534                 bc_num_parseBase(n, val, base);
2535
2536         return BC_STATUS_SUCCESS;
2537 }
2538
2539 static BcStatus bc_num_print(BcNum *n, BcNum *base, size_t base_t, bool newline,
2540                              size_t *nchars, size_t line_len)
2541 {
2542         BcStatus s = BC_STATUS_SUCCESS;
2543
2544         bc_num_printNewline(nchars, line_len);
2545
2546         if (n->len == 0) {
2547                 bc_vm_putchar('0');
2548                 ++(*nchars);
2549         }
2550         else if (base_t == 10)
2551                 bc_num_printDecimal(n, nchars, line_len);
2552         else
2553                 s = bc_num_printBase(n, base, base_t, nchars, line_len);
2554
2555         if (newline) {
2556                 bc_vm_putchar('\n');
2557                 *nchars = 0;
2558         }
2559
2560         return s;
2561 }
2562
2563 static BcStatus bc_num_ulong(BcNum *n, unsigned long *result)
2564 {
2565         size_t i;
2566         unsigned long pow;
2567
2568         if (n->neg) return BC_STATUS_MATH_NEGATIVE;
2569
2570         for (*result = 0, pow = 1, i = n->rdx; i < n->len; ++i) {
2571
2572                 unsigned long prev = *result, powprev = pow;
2573
2574                 *result += ((unsigned long) n->num[i]) * pow;
2575                 pow *= 10;
2576
2577                 if (*result < prev || pow < powprev) return BC_STATUS_MATH_OVERFLOW;
2578         }
2579
2580         return BC_STATUS_SUCCESS;
2581 }
2582
2583 static BcStatus bc_num_ulong2num(BcNum *n, unsigned long val)
2584 {
2585         size_t len;
2586         BcDig *ptr;
2587         unsigned long i;
2588
2589         bc_num_zero(n);
2590
2591         if (val == 0) return BC_STATUS_SUCCESS;
2592
2593         for (len = 1, i = ULONG_MAX; i != 0; i /= 10, ++len) bc_num_expand(n, len);
2594         for (ptr = n->num, i = 0; val; ++i, ++n->len, val /= 10) ptr[i] = val % 10;
2595
2596         return BC_STATUS_SUCCESS;
2597 }
2598
2599 static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2600 {
2601         BcNumBinaryOp op = (!a->neg == !b->neg) ? bc_num_a : bc_num_s;
2602         (void) scale;
2603         return bc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b));
2604 }
2605
2606 static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2607 {
2608         BcNumBinaryOp op = (!a->neg == !b->neg) ? bc_num_s : bc_num_a;
2609         (void) scale;
2610         return bc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b));
2611 }
2612
2613 static BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2614 {
2615         size_t req = BC_NUM_MREQ(a, b, scale);
2616         return bc_num_binary(a, b, c, scale, bc_num_m, req);
2617 }
2618
2619 static BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2620 {
2621         size_t req = BC_NUM_MREQ(a, b, scale);
2622         return bc_num_binary(a, b, c, scale, bc_num_d, req);
2623 }
2624
2625 static BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2626 {
2627         size_t req = BC_NUM_MREQ(a, b, scale);
2628         return bc_num_binary(a, b, c, scale, bc_num_rem, req);
2629 }
2630
2631 static BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2632 {
2633         return bc_num_binary(a, b, c, scale, bc_num_p, a->len * b->len + 1);
2634 }
2635
2636 static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale)
2637 {
2638         BcStatus s;
2639         BcNum num1, num2, half, f, fprime, *x0, *x1, *temp;
2640         size_t pow, len, digs, digs1, resrdx, req, times = 0;
2641         ssize_t cmp = 1, cmp1 = SSIZE_MAX, cmp2 = SSIZE_MAX;
2642
2643         req = BC_MAX(scale, a->rdx) + ((BC_NUM_INT(a) + 1) >> 1) + 1;
2644         bc_num_expand(b, req);
2645
2646         if (a->len == 0) {
2647                 bc_num_setToZero(b, scale);
2648                 return BC_STATUS_SUCCESS;
2649         }
2650         else if (a->neg)
2651                 return BC_STATUS_MATH_NEGATIVE;
2652         else if (BC_NUM_ONE(a)) {
2653                 bc_num_one(b);
2654                 bc_num_extend(b, scale);
2655                 return BC_STATUS_SUCCESS;
2656         }
2657
2658         scale = BC_MAX(scale, a->rdx) + 1;
2659         len = a->len + scale;
2660
2661         bc_num_init(&num1, len);
2662         bc_num_init(&num2, len);
2663         bc_num_init(&half, BC_NUM_DEF_SIZE);
2664
2665         bc_num_one(&half);
2666         half.num[0] = 5;
2667         half.rdx = 1;
2668
2669         bc_num_init(&f, len);
2670         bc_num_init(&fprime, len);
2671
2672         x0 = &num1;
2673         x1 = &num2;
2674
2675         bc_num_one(x0);
2676         pow = BC_NUM_INT(a);
2677
2678         if (pow) {
2679
2680                 if (pow & 1)
2681                         x0->num[0] = 2;
2682                 else
2683                         x0->num[0] = 6;
2684
2685                 pow -= 2 - (pow & 1);
2686
2687                 bc_num_extend(x0, pow);
2688
2689                 // Make sure to move the radix back.
2690                 x0->rdx -= pow;
2691         }
2692
2693         x0->rdx = digs = digs1 = 0;
2694         resrdx = scale + 2;
2695         len = BC_NUM_INT(x0) + resrdx - 1;
2696
2697         while (!bcg.signe && (cmp != 0 || digs < len)) {
2698
2699                 s = bc_num_div(a, x0, &f, resrdx);
2700                 if (s) goto err;
2701                 s = bc_num_add(x0, &f, &fprime, resrdx);
2702                 if (s) goto err;
2703                 s = bc_num_mul(&fprime, &half, x1, resrdx);
2704                 if (s) goto err;
2705
2706                 cmp = bc_num_cmp(x1, x0);
2707                 digs = x1->len - (unsigned long long) llabs(cmp);
2708
2709                 if (cmp == cmp2 && digs == digs1)
2710                         times += 1;
2711                 else
2712                         times = 0;
2713
2714                 resrdx += times > 4;
2715
2716                 cmp2 = cmp1;
2717                 cmp1 = cmp;
2718                 digs1 = digs;
2719
2720                 temp = x0;
2721                 x0 = x1;
2722                 x1 = temp;
2723         }
2724
2725         if (bcg.signe) {
2726                 s = BC_STATUS_EXEC_SIGNAL;
2727                 goto err;
2728         }
2729
2730         bc_num_copy(b, x0);
2731         scale -= 1;
2732         if (b->rdx > scale) bc_num_truncate(b, b->rdx - scale);
2733
2734 err:
2735         bc_num_free(&fprime);
2736         bc_num_free(&f);
2737         bc_num_free(&half);
2738         bc_num_free(&num2);
2739         bc_num_free(&num1);
2740         return s;
2741 }
2742
2743 static BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d,
2744                               size_t scale)
2745 {
2746         BcStatus s;
2747         BcNum num2, *ptr_a;
2748         bool init = false;
2749         size_t ts = BC_MAX(scale + b->rdx, a->rdx), len = BC_NUM_MREQ(a, b, ts);
2750
2751         if (c == a) {
2752                 memcpy(&num2, c, sizeof(BcNum));
2753                 ptr_a = &num2;
2754                 bc_num_init(c, len);
2755                 init = true;
2756         }
2757         else {
2758                 ptr_a = a;
2759                 bc_num_expand(c, len);
2760         }
2761
2762         s = bc_num_r(ptr_a, b, c, d, scale, ts);
2763
2764         if (init) bc_num_free(&num2);
2765
2766         return s;
2767 }
2768
2769 #ifdef ENABLE_DC
2770 static BcStatus bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d)
2771 {
2772         BcStatus s;
2773         BcNum base, exp, two, temp;
2774
2775         if (c->len == 0) return BC_STATUS_MATH_DIVIDE_BY_ZERO;
2776         if (a->rdx || b->rdx || c->rdx) return BC_STATUS_MATH_NON_INTEGER;
2777         if (b->neg) return BC_STATUS_MATH_NEGATIVE;
2778
2779         bc_num_expand(d, c->len);
2780         bc_num_init(&base, c->len);
2781         bc_num_init(&exp, b->len);
2782         bc_num_init(&two, BC_NUM_DEF_SIZE);
2783         bc_num_init(&temp, b->len);
2784
2785         bc_num_one(&two);
2786         two.num[0] = 2;
2787         bc_num_one(d);
2788
2789         s = bc_num_rem(a, c, &base, 0);
2790         if (s) goto err;
2791         bc_num_copy(&exp, b);
2792
2793         while (exp.len != 0) {
2794
2795                 s = bc_num_divmod(&exp, &two, &exp, &temp, 0);
2796                 if (s) goto err;
2797
2798                 if (BC_NUM_ONE(&temp)) {
2799                         s = bc_num_mul(d, &base, &temp, 0);
2800                         if (s) goto err;
2801                         s = bc_num_rem(&temp, c, d, 0);
2802                         if (s) goto err;
2803                 }
2804
2805                 s = bc_num_mul(&base, &base, &temp, 0);
2806                 if (s) goto err;
2807                 s = bc_num_rem(&temp, c, &base, 0);
2808                 if (s) goto err;
2809         }
2810
2811 err:
2812         bc_num_free(&temp);
2813         bc_num_free(&two);
2814         bc_num_free(&exp);
2815         bc_num_free(&base);
2816         return s;
2817 }
2818 #endif // ENABLE_DC
2819
2820 static int bc_id_cmp(const void *e1, const void *e2)
2821 {
2822         return strcmp(((const BcId *) e1)->name, ((const BcId *) e2)->name);
2823 }
2824
2825 static void bc_id_free(void *id)
2826 {
2827         free(((BcId *) id)->name);
2828 }
2829
2830 static BcStatus bc_func_insert(BcFunc *f, char *name, bool var)
2831 {
2832         BcId a;
2833         size_t i;
2834
2835         for (i = 0; i < f->autos.len; ++i) {
2836                 if (!strcmp(name, ((BcId *) bc_vec_item(&f->autos, i))->name))
2837                         return BC_STATUS_PARSE_DUPLICATE_LOCAL;
2838         }
2839
2840         a.idx = var;
2841         a.name = name;
2842
2843         bc_vec_push(&f->autos, &a);
2844
2845         return BC_STATUS_SUCCESS;
2846 }
2847
2848 static void bc_func_init(BcFunc *f)
2849 {
2850         bc_vec_init(&f->code, sizeof(char), NULL);
2851         bc_vec_init(&f->autos, sizeof(BcId), bc_id_free);
2852         bc_vec_init(&f->labels, sizeof(size_t), NULL);
2853         f->nparams = 0;
2854 }
2855
2856 static void bc_func_free(void *func)
2857 {
2858         BcFunc *f = (BcFunc *) func;
2859         bc_vec_free(&f->code);
2860         bc_vec_free(&f->autos);
2861         bc_vec_free(&f->labels);
2862 }
2863
2864 static void bc_array_init(BcVec *a, bool nums)
2865 {
2866         if (nums)
2867                 bc_vec_init(a, sizeof(BcNum), bc_num_free);
2868         else
2869                 bc_vec_init(a, sizeof(BcVec), bc_vec_free);
2870         bc_array_expand(a, 1);
2871 }
2872
2873 static void bc_array_copy(BcVec *d, const BcVec *s)
2874 {
2875         size_t i;
2876
2877         bc_vec_npop(d, d->len);
2878         bc_vec_expand(d, s->cap);
2879         d->len = s->len;
2880
2881         for (i = 0; i < s->len; ++i) {
2882                 BcNum *dnum = bc_vec_item(d, i), *snum = bc_vec_item(s, i);
2883                 bc_num_init(dnum, snum->len);
2884                 bc_num_copy(dnum, snum);
2885         }
2886 }
2887
2888 static void bc_array_expand(BcVec *a, size_t len)
2889 {
2890         BcResultData data;
2891
2892         if (a->size == sizeof(BcNum) && a->dtor == bc_num_free) {
2893                 while (len > a->len) {
2894                         bc_num_init(&data.n, BC_NUM_DEF_SIZE);
2895                         bc_vec_push(a, &data.n);
2896                 }
2897         }
2898         else {
2899                 while (len > a->len) {
2900                         bc_array_init(&data.v, true);
2901                         bc_vec_push(a, &data.v);
2902                 }
2903         }
2904 }
2905
2906 static void bc_string_free(void *string)
2907 {
2908         free(*((char **) string));
2909 }
2910
2911 #ifdef ENABLE_DC
2912 static void bc_result_copy(BcResult *d, BcResult *src)
2913 {
2914         d->t = src->t;
2915
2916         switch (d->t) {
2917
2918                 case BC_RESULT_TEMP:
2919                 case BC_RESULT_IBASE:
2920                 case BC_RESULT_SCALE:
2921                 case BC_RESULT_OBASE:
2922                 {
2923                         bc_num_init(&d->d.n, src->d.n.len);
2924                         bc_num_copy(&d->d.n, &src->d.n);
2925                         break;
2926                 }
2927
2928                 case BC_RESULT_VAR:
2929                 case BC_RESULT_ARRAY:
2930                 case BC_RESULT_ARRAY_ELEM:
2931                 {
2932                         d->d.id.name = xstrdup(src->d.id.name);
2933                         break;
2934                 }
2935
2936                 case BC_RESULT_CONSTANT:
2937                 case BC_RESULT_LAST:
2938                 case BC_RESULT_ONE:
2939                 case BC_RESULT_STR:
2940                 {
2941                         memcpy(&d->d.n, &src->d.n, sizeof(BcNum));
2942                         break;
2943                 }
2944         }
2945 }
2946 #endif // ENABLE_DC
2947
2948 static void bc_result_free(void *result)
2949 {
2950         BcResult *r = (BcResult *) result;
2951
2952         switch (r->t) {
2953
2954                 case BC_RESULT_TEMP:
2955                 case BC_RESULT_IBASE:
2956                 case BC_RESULT_SCALE:
2957                 case BC_RESULT_OBASE:
2958                 {
2959                         bc_num_free(&r->d.n);
2960                         break;
2961                 }
2962
2963                 case BC_RESULT_VAR:
2964                 case BC_RESULT_ARRAY:
2965                 case BC_RESULT_ARRAY_ELEM:
2966                 {
2967                         free(r->d.id.name);
2968                         break;
2969                 }
2970
2971                 default:
2972                 {
2973                         // Do nothing.
2974                         break;
2975                 }
2976         }
2977 }
2978
2979 static void bc_lex_lineComment(BcLex *l)
2980 {
2981         l->t.t = BC_LEX_WHITESPACE;
2982         while (l->i < l->len && l->buf[l->i++] != '\n');
2983         --l->i;
2984 }
2985
2986 static void bc_lex_whitespace(BcLex *l)
2987 {
2988         char c;
2989         l->t.t = BC_LEX_WHITESPACE;
2990         for (c = l->buf[l->i]; c != '\n' && isspace(c); c = l->buf[++l->i]);
2991 }
2992
2993 static BcStatus bc_lex_number(BcLex *l, char start)
2994 {
2995         const char *buf = l->buf + l->i;
2996         size_t len, hits = 0, bslashes = 0, i = 0, j;
2997         char c = buf[i];
2998         bool last_pt, pt = start == '.';
2999
3000         last_pt = pt;
3001         l->t.t = BC_LEX_NUMBER;
3002
3003         while (c != 0 && (isdigit(c) || (c >= 'A' && c <= 'F') ||
3004                           (c == '.' && !pt) || (c == '\\' && buf[i + 1] == '\n')))
3005         {
3006                 if (c != '\\') {
3007                         last_pt = c == '.';
3008                         pt = pt || last_pt;
3009                 }
3010                 else {
3011                         ++i;
3012                         bslashes += 1;
3013                 }
3014
3015                 c = buf[++i];
3016         }
3017
3018         len = i + 1 * !last_pt - bslashes * 2;
3019         if (len > BC_MAX_NUM) return BC_STATUS_EXEC_NUM_LEN;
3020
3021         bc_vec_npop(&l->t.v, l->t.v.len);
3022         bc_vec_expand(&l->t.v, len + 1);
3023         bc_vec_push(&l->t.v, &start);
3024
3025         for (buf -= 1, j = 1; j < len + hits * 2; ++j) {
3026
3027                 c = buf[j];
3028
3029                 // If we have hit a backslash, skip it. We don't have
3030                 // to check for a newline because it's guaranteed.
3031                 if (hits < bslashes && c == '\\') {
3032                         ++hits;
3033                         ++j;
3034                         continue;
3035                 }
3036
3037                 bc_vec_push(&l->t.v, &c);
3038         }
3039
3040         bc_vec_pushByte(&l->t.v, '\0');
3041         l->i += i;
3042
3043         return BC_STATUS_SUCCESS;
3044 }
3045
3046 static BcStatus bc_lex_name(BcLex *l)
3047 {
3048         size_t i = 0;
3049         const char *buf = l->buf + l->i - 1;
3050         char c = buf[i];
3051
3052         l->t.t = BC_LEX_NAME;
3053
3054         while ((c >= 'a' && c <= 'z') || isdigit(c) || c == '_') c = buf[++i];
3055
3056         if (i > BC_MAX_STRING) return BC_STATUS_EXEC_NAME_LEN;
3057         bc_vec_string(&l->t.v, i, buf);
3058
3059         // Increment the index. We minus 1 because it has already been incremented.
3060         l->i += i - 1;
3061
3062         return BC_STATUS_SUCCESS;
3063 }
3064
3065 static void bc_lex_init(BcLex *l, BcLexNext next)
3066 {
3067         l->next = next;
3068         bc_vec_init(&l->t.v, sizeof(char), NULL);
3069 }
3070
3071 static void bc_lex_free(BcLex *l)
3072 {
3073         bc_vec_free(&l->t.v);
3074 }
3075
3076 static void bc_lex_file(BcLex *l, const char *file)
3077 {
3078         l->line = 1;
3079         l->newline = false;
3080         l->f = file;
3081 }
3082
3083 static BcStatus bc_lex_next(BcLex *l)
3084 {
3085         BcStatus s;
3086
3087         l->t.last = l->t.t;
3088         if (l->t.last == BC_LEX_EOF) return BC_STATUS_LEX_EOF;
3089
3090         l->line += l->newline;
3091         l->t.t = BC_LEX_EOF;
3092
3093         l->newline = (l->i == l->len);
3094         if (l->newline) return BC_STATUS_SUCCESS;
3095
3096         // Loop until failure or we don't have whitespace. This
3097         // is so the parser doesn't get inundated with whitespace.
3098         do {
3099                 s = l->next(l);
3100         } while (!s && l->t.t == BC_LEX_WHITESPACE);
3101
3102         return s;
3103 }
3104
3105 static BcStatus bc_lex_text(BcLex *l, const char *text)
3106 {
3107         l->buf = text;
3108         l->i = 0;
3109         l->len = strlen(text);
3110         l->t.t = l->t.last = BC_LEX_INVALID;
3111         return bc_lex_next(l);
3112 }
3113
3114 #ifdef ENABLE_BC
3115 static BcStatus bc_lex_identifier(BcLex *l)
3116 {
3117         BcStatus s;
3118         size_t i;
3119         const char *buf = l->buf + l->i - 1;
3120
3121         for (i = 0; i < sizeof(bc_lex_kws) / sizeof(bc_lex_kws[0]); ++i) {
3122
3123                 unsigned long len = (unsigned long) bc_lex_kws[i].len;
3124
3125                 if (strncmp(buf, bc_lex_kws[i].name, len) == 0) {
3126
3127                         l->t.t = BC_LEX_KEY_AUTO + (BcLexType) i;
3128
3129                         if (!bc_lex_kws[i].posix) {
3130                                 s = bc_vm_posixError(BC_STATUS_POSIX_BAD_KW, l->f, l->line,
3131                                                      bc_lex_kws[i].name);
3132                                 if (s) return s;
3133                         }
3134
3135                         // We minus 1 because the index has already been incremented.
3136                         l->i += len - 1;
3137                         return BC_STATUS_SUCCESS;
3138                 }
3139         }
3140
3141         s = bc_lex_name(l);
3142         if (s) return s;
3143
3144         if (l->t.v.len - 1 > 1)
3145                 s = bc_vm_posixError(BC_STATUS_POSIX_NAME_LEN, l->f, l->line, buf);
3146
3147         return s;
3148 }
3149
3150 static BcStatus bc_lex_string(BcLex *l)
3151 {
3152         size_t len, nls = 0, i = l->i;
3153         char c;
3154
3155         l->t.t = BC_LEX_STR;
3156
3157         for (c = l->buf[i]; c != 0 && c != '"'; c = l->buf[++i]) nls += (c == '\n');
3158
3159         if (c == '\0') {
3160                 l->i = i;
3161                 return BC_STATUS_LEX_NO_STRING_END;
3162         }
3163
3164         len = i - l->i;
3165         if (len > BC_MAX_STRING) return BC_STATUS_EXEC_STRING_LEN;
3166         bc_vec_string(&l->t.v, len, l->buf + l->i);
3167
3168         l->i = i + 1;
3169         l->line += nls;
3170
3171         return BC_STATUS_SUCCESS;
3172 }
3173
3174 static void bc_lex_assign(BcLex *l, BcLexType with, BcLexType without)
3175 {
3176         if (l->buf[l->i] == '=') {
3177                 ++l->i;
3178                 l->t.t = with;
3179         }
3180         else
3181                 l->t.t = without;
3182 }
3183
3184 static BcStatus bc_lex_comment(BcLex *l)
3185 {
3186         size_t i, nls = 0;
3187         const char *buf = l->buf;
3188         bool end = false;
3189         char c;
3190
3191         l->t.t = BC_LEX_WHITESPACE;
3192
3193         for (i = ++l->i; !end; i += !end) {
3194
3195                 for (c = buf[i]; c != '*' && c != 0; c = buf[++i]) nls += (c == '\n');
3196
3197                 if (c == 0 || buf[i + 1] == '\0') {
3198                         l->i = i;
3199                         return BC_STATUS_LEX_NO_COMMENT_END;
3200                 }
3201
3202                 end = buf[i + 1] == '/';
3203         }
3204
3205         l->i = i + 2;
3206         l->line += nls;
3207
3208         return BC_STATUS_SUCCESS;
3209 }
3210
3211 static BcStatus bc_lex_token(BcLex *l)
3212 {
3213         BcStatus s = BC_STATUS_SUCCESS;
3214         char c = l->buf[l->i++], c2;
3215
3216         // This is the workhorse of the lexer.
3217         switch (c) {
3218
3219                 case '\0':
3220                 case '\n':
3221                 {
3222                         l->newline = true;
3223                         l->t.t = !c ? BC_LEX_EOF : BC_LEX_NLINE;
3224                         break;
3225                 }
3226
3227                 case '\t':
3228                 case '\v':
3229                 case '\f':
3230                 case '\r':
3231                 case ' ':
3232                 {
3233                         bc_lex_whitespace(l);
3234                         break;
3235                 }
3236
3237                 case '!':
3238                 {
3239                         bc_lex_assign(l, BC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT);
3240
3241                         if (l->t.t == BC_LEX_OP_BOOL_NOT) {
3242                                 s = bc_vm_posixError(BC_STATUS_POSIX_BOOL, l->f, l->line, "!");
3243                                 if (s) return s;
3244                         }
3245
3246                         break;
3247                 }
3248
3249                 case '"':
3250                 {
3251                         s = bc_lex_string(l);
3252                         break;
3253                 }
3254
3255                 case '#':
3256                 {
3257                         s = bc_vm_posixError(BC_STATUS_POSIX_COMMENT, l->f, l->line, NULL);
3258                         if (s) return s;
3259
3260                         bc_lex_lineComment(l);
3261
3262                         break;
3263                 }
3264
3265                 case '%':
3266                 {
3267                         bc_lex_assign(l, BC_LEX_OP_ASSIGN_MODULUS, BC_LEX_OP_MODULUS);
3268                         break;
3269                 }
3270
3271                 case '&':
3272                 {
3273                         c2 = l->buf[l->i];
3274                         if (c2 == '&') {
3275
3276                                 s = bc_vm_posixError(BC_STATUS_POSIX_BOOL, l->f, l->line, "&&");
3277                                 if (s) return s;
3278
3279                                 ++l->i;
3280                                 l->t.t = BC_LEX_OP_BOOL_AND;
3281                         }
3282                         else {
3283                                 l->t.t = BC_LEX_INVALID;
3284                                 s = BC_STATUS_LEX_BAD_CHAR;
3285                         }
3286
3287                         break;
3288                 }
3289
3290                 case '(':
3291                 case ')':
3292                 {
3293                         l->t.t = (BcLexType)(c - '(' + BC_LEX_LPAREN);
3294                         break;
3295                 }
3296
3297                 case '*':
3298                 {
3299                         bc_lex_assign(l, BC_LEX_OP_ASSIGN_MULTIPLY, BC_LEX_OP_MULTIPLY);
3300                         break;
3301                 }
3302
3303                 case '+':
3304                 {
3305                         c2 = l->buf[l->i];
3306                         if (c2 == '+') {
3307                                 ++l->i;
3308                                 l->t.t = BC_LEX_OP_INC;
3309                         }
3310                         else
3311                                 bc_lex_assign(l, BC_LEX_OP_ASSIGN_PLUS, BC_LEX_OP_PLUS);
3312                         break;
3313                 }
3314
3315                 case ',':
3316                 {
3317                         l->t.t = BC_LEX_COMMA;
3318                         break;
3319                 }
3320
3321                 case '-':
3322                 {
3323                         c2 = l->buf[l->i];
3324                         if (c2 == '-') {
3325                                 ++l->i;
3326                                 l->t.t = BC_LEX_OP_DEC;
3327                         }
3328                         else
3329                                 bc_lex_assign(l, BC_LEX_OP_ASSIGN_MINUS, BC_LEX_OP_MINUS);
3330                         break;
3331                 }
3332
3333                 case '.':
3334                 {
3335                         if (isdigit(l->buf[l->i]))
3336                                 s = bc_lex_number(l, c);
3337                         else {
3338                                 l->t.t = BC_LEX_KEY_LAST;
3339                                 s = bc_vm_posixError(BC_STATUS_POSIX_DOT, l->f, l->line, NULL);
3340                         }
3341                         break;
3342                 }
3343
3344                 case '/':
3345                 {
3346                         c2 = l->buf[l->i];
3347                         if (c2 == '*')
3348                                 s = bc_lex_comment(l);
3349                         else
3350                                 bc_lex_assign(l, BC_LEX_OP_ASSIGN_DIVIDE, BC_LEX_OP_DIVIDE);
3351                         break;
3352                 }
3353
3354                 case '0':
3355                 case '1':
3356                 case '2':
3357                 case '3':
3358                 case '4':
3359                 case '5':
3360                 case '6':
3361                 case '7':
3362                 case '8':
3363                 case '9':
3364                 case 'A':
3365                 case 'B':
3366                 case 'C':
3367                 case 'D':
3368                 case 'E':
3369                 case 'F':
3370                 {
3371                         s = bc_lex_number(l, c);
3372                         break;
3373                 }
3374
3375                 case ';':
3376                 {
3377                         l->t.t = BC_LEX_SCOLON;
3378                         break;
3379                 }
3380
3381                 case '<':
3382                 {
3383                         bc_lex_assign(l, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_LT);
3384                         break;
3385                 }
3386
3387                 case '=':
3388                 {
3389                         bc_lex_assign(l, BC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN);
3390                         break;
3391                 }
3392
3393                 case '>':
3394                 {
3395                         bc_lex_assign(l, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_GT);
3396                         break;
3397                 }
3398
3399                 case '[':
3400                 case ']':
3401                 {
3402                         l->t.t = (BcLexType)(c - '[' + BC_LEX_LBRACKET);
3403                         break;
3404                 }
3405
3406                 case '\\':
3407                 {
3408                         if (l->buf[l->i] == '\n') {
3409                                 l->t.t = BC_LEX_WHITESPACE;
3410                                 ++l->i;
3411                         }
3412                         else
3413                                 s = BC_STATUS_LEX_BAD_CHAR;
3414                         break;
3415                 }
3416
3417                 case '^':
3418                 {
3419                         bc_lex_assign(l, BC_LEX_OP_ASSIGN_POWER, BC_LEX_OP_POWER);
3420                         break;
3421                 }
3422
3423                 case 'a':
3424                 case 'b':
3425                 case 'c':
3426                 case 'd':
3427                 case 'e':
3428                 case 'f':
3429                 case 'g':
3430                 case 'h':
3431                 case 'i':
3432                 case 'j':
3433                 case 'k':
3434                 case 'l':
3435                 case 'm':
3436                 case 'n':
3437                 case 'o':
3438                 case 'p':
3439                 case 'q':
3440                 case 'r':
3441                 case 's':
3442                 case 't':
3443                 case 'u':
3444                 case 'v':
3445                 case 'w':
3446                 case 'x':
3447                 case 'y':
3448                 case 'z':
3449                 {
3450                         s = bc_lex_identifier(l);
3451                         break;
3452                 }
3453
3454                 case '{':
3455                 case '}':
3456                 {
3457                         l->t.t = (BcLexType)(c - '{' + BC_LEX_LBRACE);
3458                         break;
3459                 }
3460
3461                 case '|':
3462                 {
3463                         c2 = l->buf[l->i];
3464
3465                         if (c2 == '|') {
3466
3467                                 s = bc_vm_posixError(BC_STATUS_POSIX_BOOL, l->f, l->line, "||");
3468                                 if (s) return s;
3469
3470                                 ++l->i;
3471                                 l->t.t = BC_LEX_OP_BOOL_OR;
3472                         }
3473                         else {
3474                                 l->t.t = BC_LEX_INVALID;
3475                                 s = BC_STATUS_LEX_BAD_CHAR;
3476                         }
3477
3478                         break;
3479                 }
3480
3481                 default:
3482                 {
3483                         l->t.t = BC_LEX_INVALID;
3484                         s = BC_STATUS_LEX_BAD_CHAR;
3485                         break;
3486                 }
3487         }
3488
3489         return s;
3490 }
3491 #endif // ENABLE_BC
3492
3493 #ifdef ENABLE_DC
3494 static BcStatus dc_lex_register(BcLex *l)
3495 {
3496         BcStatus s = BC_STATUS_SUCCESS;
3497
3498         if (isspace(l->buf[l->i - 1])) {
3499                 bc_lex_whitespace(l);
3500                 ++l->i;
3501                 if (!bcg.exreg)
3502                         s = BC_STATUS_LEX_EXTENDED_REG;
3503                 else
3504                         s = bc_lex_name(l);
3505         }
3506         else {
3507                 bc_vec_npop(&l->t.v, l->t.v.len);
3508                 bc_vec_pushByte(&l->t.v, l->buf[l->i - 1]);
3509                 bc_vec_pushByte(&l->t.v, '\0');
3510                 l->t.t = BC_LEX_NAME;
3511         }
3512
3513         return s;
3514 }
3515
3516 static BcStatus dc_lex_string(BcLex *l)
3517 {
3518         size_t depth = 1, nls = 0, i = l->i;
3519         char c;
3520
3521         l->t.t = BC_LEX_STR;
3522         bc_vec_npop(&l->t.v, l->t.v.len);
3523
3524         for (c = l->buf[i]; c != 0 && depth; c = l->buf[++i]) {
3525
3526                 depth += (c == '[' && (i == l->i || l->buf[i - 1] != '\\'));
3527                 depth -= (c == ']' && (i == l->i || l->buf[i - 1] != '\\'));
3528                 nls += (c == '\n');
3529
3530                 if (depth) bc_vec_push(&l->t.v, &c);
3531         }
3532
3533         if (c == '\0') {
3534                 l->i = i;
3535                 return BC_STATUS_LEX_NO_STRING_END;
3536         }
3537
3538         bc_vec_pushByte(&l->t.v, '\0');
3539         if (i - l->i > BC_MAX_STRING) return BC_STATUS_EXEC_STRING_LEN;
3540
3541         l->i = i;
3542         l->line += nls;
3543
3544         return BC_STATUS_SUCCESS;
3545 }
3546
3547 static BcStatus dc_lex_token(BcLex *l)
3548 {
3549         BcStatus s = BC_STATUS_SUCCESS;
3550         char c = l->buf[l->i++], c2;
3551         size_t i;
3552
3553         for (i = 0; i < dc_lex_regs_len; ++i) {
3554                 if (l->t.last == dc_lex_regs[i]) return dc_lex_register(l);
3555         }
3556
3557         if (c >= '%' && c <= '~' &&
3558             (l->t.t = dc_lex_tokens[(c - '%')]) != BC_LEX_INVALID)
3559         {
3560                 return s;
3561         }
3562
3563         // This is the workhorse of the lexer.
3564         switch (c) {
3565
3566                 case '\0':
3567                 {
3568                         l->t.t = BC_LEX_EOF;
3569                         break;
3570                 }
3571
3572                 case '\n':
3573                 case '\t':
3574                 case '\v':
3575                 case '\f':
3576                 case '\r':
3577                 case ' ':
3578                 {
3579                         l->newline = (c == '\n');
3580                         bc_lex_whitespace(l);
3581                         break;
3582                 }
3583
3584                 case '!':
3585                 {
3586                         c2 = l->buf[l->i];
3587
3588                         if (c2 == '=')
3589                                 l->t.t = BC_LEX_OP_REL_NE;
3590                         else if (c2 == '<')
3591                                 l->t.t = BC_LEX_OP_REL_LE;
3592                         else if (c2 == '>')
3593                                 l->t.t = BC_LEX_OP_REL_GE;
3594                         else
3595                                 return BC_STATUS_LEX_BAD_CHAR;
3596
3597                         ++l->i;
3598                         break;
3599                 }
3600
3601                 case '#':
3602                 {
3603                         bc_lex_lineComment(l);
3604                         break;
3605                 }
3606
3607                 case '.':
3608                 {
3609                         if (isdigit(l->buf[l->i]))
3610                                 s = bc_lex_number(l, c);
3611                         else
3612                                 s = BC_STATUS_LEX_BAD_CHAR;
3613                         break;
3614                 }
3615
3616                 case '0':
3617                 case '1':
3618                 case '2':
3619                 case '3':
3620                 case '4':
3621                 case '5':
3622                 case '6':
3623                 case '7':
3624                 case '8':
3625                 case '9':
3626                 case 'A':
3627                 case 'B':
3628                 case 'C':
3629                 case 'D':
3630                 case 'E':
3631                 case 'F':
3632                 {
3633                         s = bc_lex_number(l, c);
3634                         break;
3635                 }
3636
3637                 case '[':
3638                 {
3639                         s = dc_lex_string(l);
3640                         break;
3641                 }
3642
3643                 default:
3644                 {
3645                         l->t.t = BC_LEX_INVALID;
3646                         s = BC_STATUS_LEX_BAD_CHAR;
3647                         break;
3648                 }
3649         }
3650
3651         return s;
3652 }
3653 #endif // ENABLE_DC
3654
3655 static void bc_parse_addFunc(BcParse *p, char *name, size_t *idx)
3656 {
3657         bc_program_addFunc(p->prog, name, idx);
3658         p->func = bc_vec_item(&p->prog->fns, p->fidx);
3659 }
3660
3661 static void bc_parse_pushName(BcParse *p, char *name)
3662 {
3663         size_t i = 0, len = strlen(name);
3664
3665         for (; i < len; ++i) bc_parse_push(p, name[i]);
3666         bc_parse_push(p, BC_PARSE_STREND);
3667
3668         free(name);
3669 }
3670
3671 static void bc_parse_pushIndex(BcParse *p, size_t idx)
3672 {
3673         unsigned char amt, i, nums[sizeof(size_t)];
3674
3675         for (amt = 0; idx; ++amt) {
3676                 nums[amt] = (char) idx;
3677                 idx = (idx & ((unsigned long) ~(UCHAR_MAX))) >> sizeof(char) * CHAR_BIT;
3678         }
3679
3680         bc_parse_push(p, amt);
3681         for (i = 0; i < amt; ++i) bc_parse_push(p, nums[i]);
3682 }
3683
3684 static void bc_parse_number(BcParse *p, BcInst *prev, size_t *nexs)
3685 {
3686         char *num = xstrdup(p->l.t.v.v);
3687         size_t idx = p->prog->consts.len;
3688
3689         bc_vec_push(&p->prog->consts, &num);
3690
3691         bc_parse_push(p, BC_INST_NUM);
3692         bc_parse_pushIndex(p, idx);
3693
3694         ++(*nexs);
3695         (*prev) = BC_INST_NUM;
3696 }
3697
3698 static BcStatus bc_parse_text(BcParse *p, const char *text)
3699 {
3700         BcStatus s;
3701
3702         p->func = bc_vec_item(&p->prog->fns, p->fidx);
3703
3704         if (!strcmp(text, "") && !BC_PARSE_CAN_EXEC(p)) {
3705                 p->l.t.t = BC_LEX_INVALID;
3706                 s = p->parse(p);
3707                 if (s) return s;
3708                 if (!BC_PARSE_CAN_EXEC(p)) return BC_STATUS_EXEC_FILE_NOT_EXECUTABLE;
3709         }
3710
3711         return bc_lex_text(&p->l, text);
3712 }
3713
3714 static BcStatus bc_parse_reset(BcParse *p, BcStatus s)
3715 {
3716         if (p->fidx != BC_PROG_MAIN) {
3717
3718                 p->func->nparams = 0;
3719                 bc_vec_npop(&p->func->code, p->func->code.len);
3720                 bc_vec_npop(&p->func->autos, p->func->autos.len);
3721                 bc_vec_npop(&p->func->labels, p->func->labels.len);
3722
3723                 bc_parse_updateFunc(p, BC_PROG_MAIN);
3724         }
3725
3726         p->l.i = p->l.len;
3727         p->l.t.t = BC_LEX_EOF;
3728         p->auto_part = (p->nbraces = 0);
3729
3730         bc_vec_npop(&p->flags, p->flags.len - 1);
3731         bc_vec_npop(&p->exits, p->exits.len);
3732         bc_vec_npop(&p->conds, p->conds.len);
3733         bc_vec_npop(&p->ops, p->ops.len);
3734
3735         return bc_program_reset(p->prog, s);
3736 }
3737
3738 static void bc_parse_free(BcParse *p)
3739 {
3740         bc_vec_free(&p->flags);
3741         bc_vec_free(&p->exits);
3742         bc_vec_free(&p->conds);
3743         bc_vec_free(&p->ops);
3744         bc_lex_free(&p->l);
3745 }
3746
3747 static void bc_parse_create(BcParse *p, BcProgram *prog, size_t func,
3748                             BcParseParse parse, BcLexNext next)
3749 {
3750         memset(p, 0, sizeof(BcParse));
3751
3752         bc_lex_init(&p->l, next);
3753         bc_vec_init(&p->flags, sizeof(uint8_t), NULL);
3754         bc_vec_init(&p->exits, sizeof(BcInstPtr), NULL);
3755         bc_vec_init(&p->conds, sizeof(size_t), NULL);
3756         bc_vec_pushByte(&p->flags, 0);
3757         bc_vec_init(&p->ops, sizeof(BcLexType), NULL);
3758
3759         p->parse = parse;
3760         p->prog = prog;
3761         p->auto_part = (p->nbraces = 0);
3762         bc_parse_updateFunc(p, func);
3763 }
3764
3765 #ifdef ENABLE_BC
3766 static BcStatus bc_parse_else(BcParse *p);
3767 static BcStatus bc_parse_stmt(BcParse *p);
3768
3769 static BcStatus bc_parse_operator(BcParse *p, BcLexType type, size_t start,
3770                                   size_t *nexprs, bool next)
3771 {
3772         BcStatus s = BC_STATUS_SUCCESS;
3773         BcLexType t;
3774         char l, r = bc_parse_ops[type - BC_LEX_OP_INC].prec;
3775         bool left = bc_parse_ops[type - BC_LEX_OP_INC].left;
3776
3777         while (p->ops.len > start) {
3778
3779                 t = BC_PARSE_TOP_OP(p);
3780                 if (t == BC_LEX_LPAREN) break;
3781
3782                 l = bc_parse_ops[t - BC_LEX_OP_INC].prec;
3783                 if (l >= r && (l != r || !left)) break;
3784
3785                 bc_parse_push(p, BC_PARSE_TOKEN_INST(t));
3786                 bc_vec_pop(&p->ops);
3787                 *nexprs -= t != BC_LEX_OP_BOOL_NOT && t != BC_LEX_NEG;
3788         }
3789
3790         bc_vec_push(&p->ops, &type);
3791         if (next) s = bc_lex_next(&p->l);
3792
3793         return s;
3794 }
3795
3796 static BcStatus bc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs)
3797 {
3798         BcLexType top;
3799
3800         if (p->ops.len <= ops_bgn) return BC_STATUS_PARSE_BAD_EXP;
3801         top = BC_PARSE_TOP_OP(p);
3802
3803         while (top != BC_LEX_LPAREN) {
3804
3805                 bc_parse_push(p, BC_PARSE_TOKEN_INST(top));
3806
3807                 bc_vec_pop(&p->ops);
3808                 *nexs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG;
3809
3810                 if (p->ops.len <= ops_bgn) return BC_STATUS_PARSE_BAD_EXP;
3811                 top = BC_PARSE_TOP_OP(p);
3812         }
3813
3814         bc_vec_pop(&p->ops);
3815
3816         return bc_lex_next(&p->l);
3817 }
3818
3819 static BcStatus bc_parse_params(BcParse *p, uint8_t flags)
3820 {
3821         BcStatus s;
3822         bool comma = false;
3823         size_t nparams;
3824
3825         s = bc_lex_next(&p->l);
3826         if (s) return s;
3827
3828         for (nparams = 0; p->l.t.t != BC_LEX_RPAREN; ++nparams) {
3829
3830                 flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY;
3831                 s = bc_parse_expr(p, flags, bc_parse_next_param);
3832                 if (s) return s;
3833
3834                 comma = p->l.t.t == BC_LEX_COMMA;
3835                 if (comma) {
3836                         s = bc_lex_next(&p->l);
3837                         if (s) return s;
3838                 }
3839         }
3840
3841         if (comma) return BC_STATUS_PARSE_BAD_TOKEN;
3842         bc_parse_push(p, BC_INST_CALL);
3843         bc_parse_pushIndex(p, nparams);
3844
3845         return BC_STATUS_SUCCESS;
3846 }
3847
3848 static BcStatus bc_parse_call(BcParse *p, char *name, uint8_t flags)
3849 {
3850         BcStatus s;
3851         BcId entry, *entry_ptr;
3852         size_t idx;
3853
3854         entry.name = name;
3855
3856         s = bc_parse_params(p, flags);
3857         if (s) goto err;
3858
3859         if (p->l.t.t != BC_LEX_RPAREN) {
3860                 s = BC_STATUS_PARSE_BAD_TOKEN;
3861                 goto err;
3862         }
3863
3864         idx = bc_map_index(&p->prog->fn_map, &entry);
3865
3866         if (idx == BC_VEC_INVALID_IDX) {
3867                 name = xstrdup(entry.name);
3868                 bc_parse_addFunc(p, name, &idx);
3869                 idx = bc_map_index(&p->prog->fn_map, &entry);
3870                 free(entry.name);
3871         }
3872         else
3873                 free(name);
3874
3875         entry_ptr = bc_vec_item(&p->prog->fn_map, idx);
3876         bc_parse_pushIndex(p, entry_ptr->idx);
3877
3878         return bc_lex_next(&p->l);
3879
3880 err:
3881         free(name);
3882         return s;
3883 }
3884
3885 static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags)
3886 {
3887         BcStatus s;
3888         char *name;
3889
3890         name = xstrdup(p->l.t.v.v);
3891         s = bc_lex_next(&p->l);
3892         if (s) goto err;
3893
3894         if (p->l.t.t == BC_LEX_LBRACKET) {
3895
3896                 s = bc_lex_next(&p->l);
3897                 if (s) goto err;
3898
3899                 if (p->l.t.t == BC_LEX_RBRACKET) {
3900
3901                         if (!(flags & BC_PARSE_ARRAY)) {
3902                                 s = BC_STATUS_PARSE_BAD_EXP;
3903                                 goto err;
3904                         }
3905
3906                         *type = BC_INST_ARRAY;
3907                 }
3908                 else {
3909
3910                         *type = BC_INST_ARRAY_ELEM;
3911
3912                         flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
3913                         s = bc_parse_expr(p, flags, bc_parse_next_elem);
3914                         if (s) goto err;
3915                 }
3916
3917                 s = bc_lex_next(&p->l);
3918                 if (s) goto err;
3919                 bc_parse_push(p, *type);
3920                 bc_parse_pushName(p, name);
3921         }
3922         else if (p->l.t.t == BC_LEX_LPAREN) {
3923
3924                 if (flags & BC_PARSE_NOCALL) {
3925                         s = BC_STATUS_PARSE_BAD_TOKEN;
3926                         goto err;
3927                 }
3928
3929                 *type = BC_INST_CALL;
3930                 s = bc_parse_call(p, name, flags);
3931         }
3932         else {
3933                 *type = BC_INST_VAR;
3934                 bc_parse_push(p, BC_INST_VAR);
3935                 bc_parse_pushName(p, name);
3936         }
3937
3938         return s;
3939
3940 err:
3941         free(name);
3942         return s;
3943 }
3944
3945 static BcStatus bc_parse_read(BcParse *p)
3946 {
3947         BcStatus s;
3948
3949         s = bc_lex_next(&p->l);
3950         if (s) return s;
3951         if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN;
3952
3953         s = bc_lex_next(&p->l);
3954         if (s) return s;
3955         if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN;
3956
3957         bc_parse_push(p, BC_INST_READ);
3958
3959         return bc_lex_next(&p->l);
3960 }
3961
3962 static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags,
3963                                  BcInst *prev)
3964 {
3965         BcStatus s;
3966
3967         s = bc_lex_next(&p->l);
3968         if (s) return s;
3969         if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN;
3970
3971         flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY;
3972
3973         s = bc_lex_next(&p->l);
3974         if (s) return s;
3975
3976         s = bc_parse_expr(p, flags, bc_parse_next_rel);
3977         if (s) return s;
3978
3979         if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN;
3980
3981         *prev = (type == BC_LEX_KEY_LENGTH) ? BC_INST_LENGTH : BC_INST_SQRT;
3982         bc_parse_push(p, *prev);
3983
3984         return bc_lex_next(&p->l);
3985 }
3986
3987 static BcStatus bc_parse_scale(BcParse *p, BcInst *type, uint8_t flags)
3988 {
3989         BcStatus s;
3990
3991         s = bc_lex_next(&p->l);
3992         if (s) return s;
3993
3994         if (p->l.t.t != BC_LEX_LPAREN) {
3995                 *type = BC_INST_SCALE;
3996                 bc_parse_push(p, BC_INST_SCALE);
3997                 return BC_STATUS_SUCCESS;
3998         }
3999
4000         *type = BC_INST_SCALE_FUNC;
4001         flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
4002
4003         s = bc_lex_next(&p->l);
4004         if (s) return s;
4005
4006         s = bc_parse_expr(p, flags, bc_parse_next_rel);
4007         if (s) return s;
4008         if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN;
4009         bc_parse_push(p, BC_INST_SCALE_FUNC);
4010
4011         return bc_lex_next(&p->l);
4012 }
4013
4014 static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr,
4015                                 size_t *nexprs, uint8_t flags)
4016 {
4017         BcStatus s;
4018         BcLexType type;
4019         char inst;
4020         BcInst etype = *prev;
4021
4022         if (etype == BC_INST_VAR || etype == BC_INST_ARRAY_ELEM ||
4023             etype == BC_INST_SCALE || etype == BC_INST_LAST ||
4024             etype == BC_INST_IBASE || etype == BC_INST_OBASE)
4025         {
4026                 *prev = inst = BC_INST_INC_POST + (p->l.t.t != BC_LEX_OP_INC);
4027                 bc_parse_push(p, inst);
4028                 s = bc_lex_next(&p->l);
4029         }
4030         else {
4031
4032                 *prev = inst = BC_INST_INC_PRE + (p->l.t.t != BC_LEX_OP_INC);
4033                 *paren_expr = true;
4034
4035                 s = bc_lex_next(&p->l);
4036                 if (s) return s;
4037                 type = p->l.t.t;
4038
4039                 // Because we parse the next part of the expression
4040                 // right here, we need to increment this.
4041                 *nexprs = *nexprs + 1;
4042
4043                 switch (type) {
4044
4045                         case BC_LEX_NAME:
4046                         {
4047                                 s = bc_parse_name(p, prev, flags | BC_PARSE_NOCALL);
4048                                 break;
4049                         }
4050
4051                         case BC_LEX_KEY_IBASE:
4052                         case BC_LEX_KEY_LAST:
4053                         case BC_LEX_KEY_OBASE:
4054                         {
4055                                 bc_parse_push(p, type - BC_LEX_KEY_IBASE + BC_INST_IBASE);
4056                                 s = bc_lex_next(&p->l);
4057                                 break;
4058                         }
4059
4060                         case BC_LEX_KEY_SCALE:
4061                         {
4062                                 s = bc_lex_next(&p->l);
4063                                 if (s) return s;
4064                                 if (p->l.t.t == BC_LEX_LPAREN)
4065                                         s = BC_STATUS_PARSE_BAD_TOKEN;
4066                                 else
4067                                         bc_parse_push(p, BC_INST_SCALE);
4068                                 break;
4069                         }
4070
4071                         default:
4072                         {
4073                                 s = BC_STATUS_PARSE_BAD_TOKEN;
4074                                 break;
4075                         }
4076                 }
4077
4078                 if (!s) bc_parse_push(p, inst);
4079         }
4080
4081         return s;
4082 }
4083
4084 static BcStatus bc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn,
4085                                bool rparen, size_t *nexprs)
4086 {
4087         BcStatus s;
4088         BcLexType type;
4089         BcInst etype = *prev;
4090
4091         s = bc_lex_next(&p->l);
4092         if (s) return s;
4093
4094         type = rparen || etype == BC_INST_INC_POST || etype == BC_INST_DEC_POST ||
4095                        (etype >= BC_INST_NUM && etype <= BC_INST_SQRT) ?
4096                    BC_LEX_OP_MINUS :
4097                    BC_LEX_NEG;
4098         *prev = BC_PARSE_TOKEN_INST(type);
4099
4100         // We can just push onto the op stack because this is the largest
4101         // precedence operator that gets pushed. Inc/dec does not.
4102         if (type != BC_LEX_OP_MINUS)
4103                 bc_vec_push(&p->ops, &type);
4104         else
4105                 s = bc_parse_operator(p, type, ops_bgn, nexprs, false);
4106
4107         return s;
4108 }
4109
4110 static BcStatus bc_parse_string(BcParse *p, char inst)
4111 {
4112         char *str = xstrdup(p->l.t.v.v);
4113
4114         bc_parse_push(p, BC_INST_STR);
4115         bc_parse_pushIndex(p, p->prog->strs.len);
4116         bc_vec_push(&p->prog->strs, &str);
4117         bc_parse_push(p, inst);
4118
4119         return bc_lex_next(&p->l);
4120 }
4121
4122 static BcStatus bc_parse_print(BcParse *p)
4123 {
4124         BcStatus s;
4125         BcLexType type;
4126         bool comma = false;
4127
4128         s = bc_lex_next(&p->l);
4129         if (s) return s;
4130
4131         type = p->l.t.t;
4132
4133         if (type == BC_LEX_SCOLON || type == BC_LEX_NLINE)
4134                 return BC_STATUS_PARSE_BAD_PRINT;
4135
4136         while (!s && type != BC_LEX_SCOLON && type != BC_LEX_NLINE) {
4137
4138                 if (type == BC_LEX_STR)
4139                         s = bc_parse_string(p, BC_INST_PRINT_POP);
4140                 else {
4141                         s = bc_parse_expr(p, 0, bc_parse_next_print);
4142                         if (s) return s;
4143                         bc_parse_push(p, BC_INST_PRINT_POP);
4144                 }
4145
4146                 if (s) return s;
4147
4148                 comma = p->l.t.t == BC_LEX_COMMA;
4149                 if (comma) s = bc_lex_next(&p->l);
4150                 type = p->l.t.t;
4151         }
4152
4153         if (s) return s;
4154         if (comma) return BC_STATUS_PARSE_BAD_TOKEN;
4155
4156         return bc_lex_next(&p->l);
4157 }
4158
4159 static BcStatus bc_parse_return(BcParse *p)
4160 {
4161         BcStatus s;
4162         BcLexType t;
4163         bool paren;
4164
4165         if (!BC_PARSE_FUNC(p)) return BC_STATUS_PARSE_BAD_TOKEN;
4166
4167         s = bc_lex_next(&p->l);
4168         if (s) return s;
4169
4170         t = p->l.t.t;
4171         paren = t == BC_LEX_LPAREN;
4172
4173         if (t == BC_LEX_NLINE || t == BC_LEX_SCOLON)
4174                 bc_parse_push(p, BC_INST_RET0);
4175         else {
4176
4177                 s = bc_parse_expr(p, 0, bc_parse_next_expr);
4178                 if (s && s != BC_STATUS_PARSE_EMPTY_EXP)
4179                         return s;
4180                 else if (s == BC_STATUS_PARSE_EMPTY_EXP) {
4181                         bc_parse_push(p, BC_INST_RET0);
4182                         s = bc_lex_next(&p->l);
4183                         if (s) return s;
4184                 }
4185
4186                 if (!paren || p->l.t.last != BC_LEX_RPAREN) {
4187                         s = bc_vm_posixError(BC_STATUS_POSIX_RET, p->l.f, p->l.line, NULL);
4188                         if (s) return s;
4189                 }
4190
4191                 bc_parse_push(p, BC_INST_RET);
4192         }
4193
4194         return s;
4195 }
4196
4197 static BcStatus bc_parse_endBody(BcParse *p, bool brace)
4198 {
4199         BcStatus s = BC_STATUS_SUCCESS;
4200
4201         if (p->flags.len <= 1 || (brace && p->nbraces == 0))
4202                 return BC_STATUS_PARSE_BAD_TOKEN;
4203
4204         if (brace) {
4205
4206                 if (p->l.t.t == BC_LEX_RBRACE) {
4207                         if (!p->nbraces) return BC_STATUS_PARSE_BAD_TOKEN;
4208                         --p->nbraces;
4209                         s = bc_lex_next(&p->l);
4210                         if (s) return s;
4211                 }
4212                 else
4213                         return BC_STATUS_PARSE_BAD_TOKEN;
4214         }
4215
4216         if (BC_PARSE_IF(p)) {
4217
4218                 uint8_t *flag_ptr;
4219
4220                 while (p->l.t.t == BC_LEX_NLINE) {
4221                         s = bc_lex_next(&p->l);
4222                         if (s) return s;
4223                 }
4224
4225                 bc_vec_pop(&p->flags);
4226
4227                 flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
4228                 *flag_ptr = (*flag_ptr | BC_PARSE_FLAG_IF_END);
4229
4230                 if (p->l.t.t == BC_LEX_KEY_ELSE) s = bc_parse_else(p);
4231         }
4232         else if (BC_PARSE_ELSE(p)) {
4233
4234                 BcInstPtr *ip;
4235                 size_t *label;
4236
4237                 bc_vec_pop(&p->flags);
4238
4239                 ip = bc_vec_top(&p->exits);
4240                 label = bc_vec_item(&p->func->labels, ip->idx);
4241                 *label = p->func->code.len;
4242
4243                 bc_vec_pop(&p->exits);
4244         }
4245         else if (BC_PARSE_FUNC_INNER(p)) {
4246                 bc_parse_push(p, BC_INST_RET0);
4247                 bc_parse_updateFunc(p, BC_PROG_MAIN);
4248                 bc_vec_pop(&p->flags);
4249         }
4250         else {
4251
4252                 BcInstPtr *ip = bc_vec_top(&p->exits);
4253                 size_t *label = bc_vec_top(&p->conds);
4254
4255                 bc_parse_push(p, BC_INST_JUMP);
4256                 bc_parse_pushIndex(p, *label);
4257
4258                 label = bc_vec_item(&p->func->labels, ip->idx);
4259                 *label = p->func->code.len;
4260
4261                 bc_vec_pop(&p->flags);
4262                 bc_vec_pop(&p->exits);
4263                 bc_vec_pop(&p->conds);
4264         }
4265
4266         return s;
4267 }
4268
4269 static void bc_parse_startBody(BcParse *p, uint8_t flags)
4270 {
4271         uint8_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
4272         flags |= (*flag_ptr & (BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_LOOP));
4273         flags |= BC_PARSE_FLAG_BODY;
4274         bc_vec_push(&p->flags, &flags);
4275 }
4276
4277 static void bc_parse_noElse(BcParse *p)
4278 {
4279         BcInstPtr *ip;
4280         size_t *label;
4281         uint8_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
4282
4283         *flag_ptr = (*flag_ptr & ~(BC_PARSE_FLAG_IF_END));
4284
4285         ip = bc_vec_top(&p->exits);
4286         label = bc_vec_item(&p->func->labels, ip->idx);
4287         *label = p->func->code.len;
4288
4289         bc_vec_pop(&p->exits);
4290 }
4291
4292 static BcStatus bc_parse_if(BcParse *p)
4293 {
4294         BcStatus s;
4295         BcInstPtr ip;
4296
4297         s = bc_lex_next(&p->l);
4298         if (s) return s;
4299         if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN;
4300
4301         s = bc_lex_next(&p->l);
4302         if (s) return s;
4303         s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel);
4304         if (s) return s;
4305         if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN;
4306
4307         s = bc_lex_next(&p->l);
4308         if (s) return s;
4309         bc_parse_push(p, BC_INST_JUMP_ZERO);
4310
4311         ip.idx = p->func->labels.len;
4312         ip.func = ip.len = 0;
4313
4314         bc_parse_pushIndex(p, ip.idx);
4315         bc_vec_push(&p->exits, &ip);
4316         bc_vec_push(&p->func->labels, &ip.idx);
4317         bc_parse_startBody(p, BC_PARSE_FLAG_IF);
4318
4319         return BC_STATUS_SUCCESS;
4320 }
4321
4322 static BcStatus bc_parse_else(BcParse *p)
4323 {
4324         BcInstPtr ip;
4325
4326         if (!BC_PARSE_IF_END(p)) return BC_STATUS_PARSE_BAD_TOKEN;
4327
4328         ip.idx = p->func->labels.len;
4329         ip.func = ip.len = 0;
4330
4331         bc_parse_push(p, BC_INST_JUMP);
4332         bc_parse_pushIndex(p, ip.idx);
4333
4334         bc_parse_noElse(p);
4335
4336         bc_vec_push(&p->exits, &ip);
4337         bc_vec_push(&p->func->labels, &ip.idx);
4338         bc_parse_startBody(p, BC_PARSE_FLAG_ELSE);
4339
4340         return bc_lex_next(&p->l);
4341 }
4342
4343 static BcStatus bc_parse_while(BcParse *p)
4344 {
4345         BcStatus s;
4346         BcInstPtr ip;
4347
4348         s = bc_lex_next(&p->l);
4349         if (s) return s;
4350         if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN;
4351         s = bc_lex_next(&p->l);
4352         if (s) return s;
4353
4354         ip.idx = p->func->labels.len;
4355
4356         bc_vec_push(&p->func->labels, &p->func->code.len);
4357         bc_vec_push(&p->conds, &ip.idx);
4358
4359         ip.idx = p->func->labels.len;
4360         ip.func = 1;
4361         ip.len = 0;
4362
4363         bc_vec_push(&p->exits, &ip);
4364         bc_vec_push(&p->func->labels, &ip.idx);
4365
4366         s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel);
4367         if (s) return s;
4368         if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN;
4369         s = bc_lex_next(&p->l);
4370         if (s) return s;
4371
4372         bc_parse_push(p, BC_INST_JUMP_ZERO);
4373         bc_parse_pushIndex(p, ip.idx);
4374         bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER);
4375
4376         return BC_STATUS_SUCCESS;
4377 }
4378
4379 static BcStatus bc_parse_for(BcParse *p)
4380 {
4381         BcStatus s;
4382         BcInstPtr ip;
4383         size_t cond_idx, exit_idx, body_idx, update_idx;
4384
4385         s = bc_lex_next(&p->l);
4386         if (s) return s;
4387         if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN;
4388         s = bc_lex_next(&p->l);
4389         if (s) return s;
4390
4391         if (p->l.t.t != BC_LEX_SCOLON)
4392                 s = bc_parse_expr(p, 0, bc_parse_next_for);
4393         else
4394                 s = bc_vm_posixError(BC_STATUS_POSIX_FOR1, p->l.f, p->l.line, NULL);
4395
4396         if (s) return s;
4397         if (p->l.t.t != BC_LEX_SCOLON) return BC_STATUS_PARSE_BAD_TOKEN;
4398         s = bc_lex_next(&p->l);
4399         if (s) return s;
4400
4401         cond_idx = p->func->labels.len;
4402         update_idx = cond_idx + 1;
4403         body_idx = update_idx + 1;
4404         exit_idx = body_idx + 1;
4405
4406         bc_vec_push(&p->func->labels, &p->func->code.len);
4407
4408         if (p->l.t.t != BC_LEX_SCOLON)
4409                 s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_for);
4410         else
4411                 s = bc_vm_posixError(BC_STATUS_POSIX_FOR2, p->l.f, p->l.line, NULL);
4412
4413         if (s) return s;
4414         if (p->l.t.t != BC_LEX_SCOLON) return BC_STATUS_PARSE_BAD_TOKEN;
4415
4416         s = bc_lex_next(&p->l);
4417         if (s) return s;
4418
4419         bc_parse_push(p, BC_INST_JUMP_ZERO);
4420         bc_parse_pushIndex(p, exit_idx);
4421         bc_parse_push(p, BC_INST_JUMP);
4422         bc_parse_pushIndex(p, body_idx);
4423
4424         ip.idx = p->func->labels.len;
4425
4426         bc_vec_push(&p->conds, &update_idx);
4427         bc_vec_push(&p->func->labels, &p->func->code.len);
4428
4429         if (p->l.t.t != BC_LEX_RPAREN)
4430                 s = bc_parse_expr(p, 0, bc_parse_next_rel);
4431         else
4432                 s = bc_vm_posixError(BC_STATUS_POSIX_FOR3, p->l.f, p->l.line, NULL);
4433
4434         if (s) return s;
4435
4436         if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN;
4437         bc_parse_push(p, BC_INST_JUMP);
4438         bc_parse_pushIndex(p, cond_idx);
4439         bc_vec_push(&p->func->labels, &p->func->code.len);
4440
4441         ip.idx = exit_idx;
4442         ip.func = 1;
4443         ip.len = 0;
4444
4445         bc_vec_push(&p->exits, &ip);
4446         bc_vec_push(&p->func->labels, &ip.idx);
4447         bc_lex_next(&p->l);
4448         bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER);
4449
4450         return BC_STATUS_SUCCESS;
4451 }
4452
4453 static BcStatus bc_parse_loopExit(BcParse *p, BcLexType type)
4454 {
4455         BcStatus s;
4456         size_t i;
4457         BcInstPtr *ip;
4458
4459         if (!BC_PARSE_LOOP(p)) return BC_STATUS_PARSE_BAD_TOKEN;
4460
4461         if (type == BC_LEX_KEY_BREAK) {
4462
4463                 if (p->exits.len == 0) return BC_STATUS_PARSE_BAD_TOKEN;
4464
4465                 i = p->exits.len - 1;
4466                 ip = bc_vec_item(&p->exits, i);
4467
4468                 while (!ip->func && i < p->exits.len) ip = bc_vec_item(&p->exits, i--);
4469                 if (i >= p->exits.len && !ip->func) return BC_STATUS_PARSE_BAD_TOKEN;
4470
4471                 i = ip->idx;
4472         }
4473         else
4474                 i = *((size_t *) bc_vec_top(&p->conds));
4475
4476         bc_parse_push(p, BC_INST_JUMP);
4477         bc_parse_pushIndex(p, i);
4478
4479         s = bc_lex_next(&p->l);
4480         if (s) return s;
4481
4482         if (p->l.t.t != BC_LEX_SCOLON && p->l.t.t != BC_LEX_NLINE)
4483                 return BC_STATUS_PARSE_BAD_TOKEN;
4484
4485         return bc_lex_next(&p->l);
4486 }
4487
4488 static BcStatus bc_parse_func(BcParse *p)
4489 {
4490         BcStatus s;
4491         bool var, comma = false;
4492         uint8_t flags;
4493         char *name;
4494
4495         s = bc_lex_next(&p->l);
4496         if (s) return s;
4497         if (p->l.t.t != BC_LEX_NAME) return BC_STATUS_PARSE_BAD_FUNC;
4498
4499         name = xstrdup(p->l.t.v.v);
4500         bc_parse_addFunc(p, name, &p->fidx);
4501
4502         s = bc_lex_next(&p->l);
4503         if (s) return s;
4504         if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_FUNC;
4505         s = bc_lex_next(&p->l);
4506         if (s) return s;
4507
4508         while (p->l.t.t != BC_LEX_RPAREN) {
4509
4510                 if (p->l.t.t != BC_LEX_NAME) return BC_STATUS_PARSE_BAD_FUNC;
4511
4512                 ++p->func->nparams;
4513
4514                 name = xstrdup(p->l.t.v.v);
4515                 s = bc_lex_next(&p->l);
4516                 if (s) goto err;
4517
4518                 var = p->l.t.t != BC_LEX_LBRACKET;
4519
4520                 if (!var) {
4521
4522                         s = bc_lex_next(&p->l);
4523                         if (s) goto err;
4524
4525                         if (p->l.t.t != BC_LEX_RBRACKET) {
4526                                 s = BC_STATUS_PARSE_BAD_FUNC;
4527                                 goto err;
4528                         }
4529
4530                         s = bc_lex_next(&p->l);
4531                         if (s) goto err;
4532                 }
4533
4534                 comma = p->l.t.t == BC_LEX_COMMA;
4535                 if (comma) {
4536                         s = bc_lex_next(&p->l);
4537                         if (s) goto err;
4538                 }
4539
4540                 s = bc_func_insert(p->func, name, var);
4541                 if (s) goto err;
4542         }
4543
4544         if (comma) return BC_STATUS_PARSE_BAD_FUNC;
4545
4546         flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_BODY;
4547         bc_parse_startBody(p, flags);
4548
4549         s = bc_lex_next(&p->l);
4550         if (s) return s;
4551
4552         if (p->l.t.t != BC_LEX_LBRACE)
4553                 s = bc_vm_posixError(BC_STATUS_POSIX_BRACE, p->l.f, p->l.line, NULL);
4554
4555         return s;
4556
4557 err:
4558         free(name);
4559         return s;
4560 }
4561
4562 static BcStatus bc_parse_auto(BcParse *p)
4563 {
4564         BcStatus s;
4565         bool comma, var, one;
4566         char *name;
4567
4568         if (!p->auto_part) return BC_STATUS_PARSE_BAD_TOKEN;
4569         s = bc_lex_next(&p->l);
4570         if (s) return s;
4571
4572         p->auto_part = comma = false;
4573         one = p->l.t.t == BC_LEX_NAME;
4574
4575         while (p->l.t.t == BC_LEX_NAME) {
4576
4577                 name = xstrdup(p->l.t.v.v);
4578                 s = bc_lex_next(&p->l);
4579                 if (s) goto err;
4580
4581                 var = p->l.t.t != BC_LEX_LBRACKET;
4582                 if (!var) {
4583
4584                         s = bc_lex_next(&p->l);
4585                         if (s) goto err;
4586
4587                         if (p->l.t.t != BC_LEX_RBRACKET) {
4588                                 s = BC_STATUS_PARSE_BAD_FUNC;
4589                                 goto err;
4590                         }
4591
4592                         s = bc_lex_next(&p->l);
4593                         if (s) goto err;
4594                 }
4595
4596                 comma = p->l.t.t == BC_LEX_COMMA;
4597                 if (comma) {
4598                         s = bc_lex_next(&p->l);
4599                         if (s) goto err;
4600                 }
4601
4602                 s = bc_func_insert(p->func, name, var);
4603                 if (s) goto err;
4604         }
4605
4606         if (comma) return BC_STATUS_PARSE_BAD_FUNC;
4607         if (!one) return BC_STATUS_PARSE_NO_AUTO;
4608
4609         if (p->l.t.t != BC_LEX_NLINE && p->l.t.t != BC_LEX_SCOLON)
4610                 return BC_STATUS_PARSE_BAD_TOKEN;
4611
4612         return bc_lex_next(&p->l);
4613
4614 err:
4615         free(name);
4616         return s;
4617 }
4618
4619 static BcStatus bc_parse_body(BcParse *p, bool brace)
4620 {
4621         BcStatus s = BC_STATUS_SUCCESS;
4622         uint8_t *flag_ptr = bc_vec_top(&p->flags);
4623
4624         *flag_ptr &= ~(BC_PARSE_FLAG_BODY);
4625
4626         if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) {
4627
4628                 if (!brace) return BC_STATUS_PARSE_BAD_TOKEN;
4629                 p->auto_part = p->l.t.t != BC_LEX_KEY_AUTO;
4630
4631                 if (!p->auto_part) {
4632                         s = bc_parse_auto(p);
4633                         if (s) return s;
4634                 }
4635
4636                 if (p->l.t.t == BC_LEX_NLINE) s = bc_lex_next(&p->l);
4637         }
4638         else {
4639                 s = bc_parse_stmt(p);
4640                 if (!s && !brace) s = bc_parse_endBody(p, false);
4641         }
4642
4643         return s;
4644 }
4645
4646 static BcStatus bc_parse_stmt(BcParse *p)
4647 {
4648         BcStatus s = BC_STATUS_SUCCESS;
4649
4650         switch (p->l.t.t) {
4651
4652                 case BC_LEX_NLINE:
4653                 {
4654                         return bc_lex_next(&p->l);
4655                 }
4656
4657                 case BC_LEX_KEY_ELSE:
4658                 {
4659                         p->auto_part = false;
4660                         break;
4661                 }
4662
4663                 case BC_LEX_LBRACE:
4664                 {
4665                         if (!BC_PARSE_BODY(p)) return BC_STATUS_PARSE_BAD_TOKEN;
4666
4667                         ++p->nbraces;
4668                         s = bc_lex_next(&p->l);
4669                         if (s) return s;
4670
4671                         return bc_parse_body(p, true);
4672                 }
4673
4674                 case BC_LEX_KEY_AUTO:
4675                 {
4676                         return bc_parse_auto(p);
4677                 }
4678
4679                 default:
4680                 {
4681                         p->auto_part = false;
4682
4683                         if (BC_PARSE_IF_END(p)) {
4684                                 bc_parse_noElse(p);
4685                                 return BC_STATUS_SUCCESS;
4686                         }
4687                         else if (BC_PARSE_BODY(p))
4688                                 return bc_parse_body(p, false);
4689
4690                         break;
4691                 }
4692         }
4693
4694         switch (p->l.t.t) {
4695
4696                 case BC_LEX_OP_INC:
4697                 case BC_LEX_OP_DEC:
4698                 case BC_LEX_OP_MINUS:
4699                 case BC_LEX_OP_BOOL_NOT:
4700                 case BC_LEX_LPAREN:
4701                 case BC_LEX_NAME:
4702                 case BC_LEX_NUMBER:
4703                 case BC_LEX_KEY_IBASE:
4704                 case BC_LEX_KEY_LAST:
4705                 case BC_LEX_KEY_LENGTH:
4706                 case BC_LEX_KEY_OBASE:
4707                 case BC_LEX_KEY_READ:
4708                 case BC_LEX_KEY_SCALE:
4709                 case BC_LEX_KEY_SQRT:
4710                 {
4711                         s = bc_parse_expr(p, BC_PARSE_PRINT, bc_parse_next_expr);
4712                         break;
4713                 }
4714
4715                 case BC_LEX_KEY_ELSE:
4716                 {
4717                         s = bc_parse_else(p);
4718                         break;
4719                 }
4720
4721                 case BC_LEX_SCOLON:
4722                 {
4723                         while (!s && p->l.t.t == BC_LEX_SCOLON) s = bc_lex_next(&p->l);
4724                         break;
4725                 }
4726
4727                 case BC_LEX_RBRACE:
4728                 {
4729                         s = bc_parse_endBody(p, true);
4730                         break;
4731                 }
4732
4733                 case BC_LEX_STR:
4734                 {
4735                         s = bc_parse_string(p, BC_INST_PRINT_STR);
4736                         break;
4737                 }
4738
4739                 case BC_LEX_KEY_BREAK:
4740                 case BC_LEX_KEY_CONTINUE:
4741                 {
4742                         s = bc_parse_loopExit(p, p->l.t.t);
4743                         break;
4744                 }
4745
4746                 case BC_LEX_KEY_FOR:
4747                 {
4748                         s = bc_parse_for(p);
4749                         break;
4750                 }
4751
4752                 case BC_LEX_KEY_HALT:
4753                 {
4754                         bc_parse_push(p, BC_INST_HALT);
4755                         s = bc_lex_next(&p->l);
4756                         break;
4757                 }
4758
4759                 case BC_LEX_KEY_IF:
4760                 {
4761                         s = bc_parse_if(p);
4762                         break;
4763                 }
4764
4765                 case BC_LEX_KEY_LIMITS:
4766                 {
4767                         s = bc_lex_next(&p->l);
4768                         if (s) return s;
4769                         s = BC_STATUS_LIMITS;
4770                         break;
4771                 }
4772
4773                 case BC_LEX_KEY_PRINT:
4774                 {
4775                         s = bc_parse_print(p);
4776                         break;
4777                 }
4778
4779                 case BC_LEX_KEY_QUIT:
4780                 {
4781                         // Quit is a compile-time command. We don't exit directly,
4782                         // so the vm can clean up. Limits do the same thing.
4783                         s = BC_STATUS_QUIT;
4784                         break;
4785                 }
4786
4787                 case BC_LEX_KEY_RETURN:
4788                 {
4789                         s = bc_parse_return(p);
4790                         break;
4791                 }
4792
4793                 case BC_LEX_KEY_WHILE:
4794                 {
4795                         s = bc_parse_while(p);
4796                         break;
4797                 }
4798
4799                 default:
4800                 {
4801                         s = BC_STATUS_PARSE_BAD_TOKEN;
4802                         break;
4803                 }
4804         }
4805
4806         return s;
4807 }
4808
4809 static BcStatus bc_parse_parse(BcParse *p)
4810 {
4811         BcStatus s;
4812
4813         if (p->l.t.t == BC_LEX_EOF)
4814                 s = p->flags.len > 0 ? BC_STATUS_PARSE_NO_BLOCK_END : BC_STATUS_LEX_EOF;
4815         else if (p->l.t.t == BC_LEX_KEY_DEFINE) {
4816                 if (!BC_PARSE_CAN_EXEC(p)) return BC_STATUS_PARSE_BAD_TOKEN;
4817                 s = bc_parse_func(p);
4818         }
4819         else
4820                 s = bc_parse_stmt(p);
4821
4822         if ((s && s != BC_STATUS_QUIT && s != BC_STATUS_LIMITS) || bcg.signe)
4823                 s = bc_parse_reset(p, s);
4824
4825         return s;
4826 }
4827
4828 static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
4829 {
4830         BcStatus s = BC_STATUS_SUCCESS;
4831         BcInst prev = BC_INST_PRINT;
4832         BcLexType top, t = p->l.t.t;
4833         size_t nexprs = 0, ops_bgn = p->ops.len;
4834         uint32_t i, nparens, nrelops;
4835         bool paren_first, paren_expr, rprn, done, get_token, assign, bin_last;
4836
4837         paren_first = p->l.t.t == BC_LEX_LPAREN;
4838         nparens = nrelops = 0;
4839         paren_expr = rprn = done = get_token = assign = false;
4840         bin_last = true;
4841
4842         for (; !bcg.signe && !s && !done && bc_parse_exprs[t]; t = p->l.t.t) {
4843                 switch (t) {
4844
4845                         case BC_LEX_OP_INC:
4846                         case BC_LEX_OP_DEC:
4847                         {
4848                                 s = bc_parse_incdec(p, &prev, &paren_expr, &nexprs, flags);
4849                                 rprn = get_token = bin_last = false;
4850                                 break;
4851                         }
4852
4853                         case BC_LEX_OP_MINUS:
4854                         {
4855                                 s = bc_parse_minus(p, &prev, ops_bgn, rprn, &nexprs);
4856                                 rprn = get_token = false;
4857                                 bin_last = prev == BC_INST_MINUS;
4858                                 break;
4859                         }
4860
4861                         case BC_LEX_OP_ASSIGN_POWER:
4862                         case BC_LEX_OP_ASSIGN_MULTIPLY:
4863                         case BC_LEX_OP_ASSIGN_DIVIDE:
4864                         case BC_LEX_OP_ASSIGN_MODULUS:
4865                         case BC_LEX_OP_ASSIGN_PLUS:
4866                         case BC_LEX_OP_ASSIGN_MINUS:
4867                         case BC_LEX_OP_ASSIGN:
4868                         {
4869                                 if (prev != BC_INST_VAR && prev != BC_INST_ARRAY_ELEM &&
4870                                     prev != BC_INST_SCALE && prev != BC_INST_IBASE &&
4871                                     prev != BC_INST_OBASE && prev != BC_INST_LAST)
4872                                 {
4873                                         s = BC_STATUS_PARSE_BAD_ASSIGN;
4874                                         break;
4875                                 }
4876                         }
4877                         // Fallthrough.
4878                         case BC_LEX_OP_POWER:
4879                         case BC_LEX_OP_MULTIPLY:
4880                         case BC_LEX_OP_DIVIDE:
4881                         case BC_LEX_OP_MODULUS:
4882                         case BC_LEX_OP_PLUS:
4883                         case BC_LEX_OP_REL_EQ:
4884                         case BC_LEX_OP_REL_LE:
4885                         case BC_LEX_OP_REL_GE:
4886                         case BC_LEX_OP_REL_NE:
4887                         case BC_LEX_OP_REL_LT:
4888                         case BC_LEX_OP_REL_GT:
4889                         case BC_LEX_OP_BOOL_NOT:
4890                         case BC_LEX_OP_BOOL_OR:
4891                         case BC_LEX_OP_BOOL_AND:
4892                         {
4893                                 if (((t == BC_LEX_OP_BOOL_NOT) != bin_last) ||
4894                                     (t != BC_LEX_OP_BOOL_NOT && prev == BC_INST_BOOL_NOT))
4895                                 {
4896                                         return BC_STATUS_PARSE_BAD_EXP;
4897                                 }
4898
4899                                 nrelops += t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT;
4900                                 prev = BC_PARSE_TOKEN_INST(t);
4901                                 s = bc_parse_operator(p, t, ops_bgn, &nexprs, true);
4902                                 rprn = get_token = false;
4903                                 bin_last = t != BC_LEX_OP_BOOL_NOT;
4904
4905                                 break;
4906                         }
4907
4908                         case BC_LEX_LPAREN:
4909                         {
4910                                 if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP;
4911
4912                                 ++nparens;
4913                                 paren_expr = rprn = bin_last = false;
4914                                 get_token = true;
4915                                 bc_vec_push(&p->ops, &t);
4916
4917                                 break;
4918                         }
4919
4920                         case BC_LEX_RPAREN:
4921                         {
4922                                 if (bin_last || prev == BC_INST_BOOL_NOT)
4923                                         return BC_STATUS_PARSE_BAD_EXP;
4924
4925                                 if (nparens == 0) {
4926                                         s = BC_STATUS_SUCCESS;
4927                                         done = true;
4928                                         get_token = false;
4929                                         break;
4930                                 }
4931                                 else if (!paren_expr)
4932                                         return BC_STATUS_PARSE_EMPTY_EXP;
4933
4934                                 --nparens;
4935                                 paren_expr = rprn = true;
4936                                 get_token = bin_last = false;
4937
4938                                 s = bc_parse_rightParen(p, ops_bgn, &nexprs);
4939
4940                                 break;
4941                         }
4942
4943                         case BC_LEX_NAME:
4944                         {
4945                                 if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP;
4946
4947                                 paren_expr = true;
4948                                 rprn = get_token = bin_last = false;
4949                                 s = bc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL);
4950                                 ++nexprs;
4951
4952                                 break;
4953                         }
4954
4955                         case BC_LEX_NUMBER:
4956                         {
4957                                 if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP;
4958
4959                                 bc_parse_number(p, &prev, &nexprs);
4960                                 paren_expr = get_token = true;
4961                                 rprn = bin_last = false;
4962
4963                                 break;
4964                         }
4965
4966                         case BC_LEX_KEY_IBASE:
4967                         case BC_LEX_KEY_LAST:
4968                         case BC_LEX_KEY_OBASE:
4969                         {
4970                                 if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP;
4971
4972                                 prev = (char) (t - BC_LEX_KEY_IBASE + BC_INST_IBASE);
4973                                 bc_parse_push(p, (char) prev);
4974
4975                                 paren_expr = get_token = true;
4976                                 rprn = bin_last = false;
4977                                 ++nexprs;
4978
4979                                 break;
4980                         }
4981
4982                         case BC_LEX_KEY_LENGTH:
4983                         case BC_LEX_KEY_SQRT:
4984                         {
4985                                 if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP;
4986
4987                                 s = bc_parse_builtin(p, t, flags, &prev);
4988                                 paren_expr = true;
4989                                 rprn = get_token = bin_last = false;
4990                                 ++nexprs;
4991
4992                                 break;
4993                         }
4994
4995                         case BC_LEX_KEY_READ:
4996                         {
4997                                 if (BC_PARSE_LEAF(prev, rprn))
4998                                         return BC_STATUS_PARSE_BAD_EXP;
4999                                 else if (flags & BC_PARSE_NOREAD)
5000                                         s = BC_STATUS_EXEC_REC_READ;
5001                                 else
5002                                         s = bc_parse_read(p);
5003
5004                                 paren_expr = true;
5005                                 rprn = get_token = bin_last = false;
5006                                 ++nexprs;
5007                                 prev = BC_INST_READ;
5008
5009                                 break;
5010                         }
5011
5012                         case BC_LEX_KEY_SCALE:
5013                         {
5014                                 if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP;
5015
5016                                 s = bc_parse_scale(p, &prev, flags);
5017                                 paren_expr = true;
5018                                 rprn = get_token = bin_last = false;
5019                                 ++nexprs;
5020                                 prev = BC_INST_SCALE;
5021
5022                                 break;
5023                         }
5024
5025                         default:
5026                         {
5027                                 s = BC_STATUS_PARSE_BAD_TOKEN;
5028                                 break;
5029                         }
5030                 }
5031
5032                 if (!s && get_token) s = bc_lex_next(&p->l);
5033         }
5034
5035         if (s) return s;
5036         if (bcg.signe) return BC_STATUS_EXEC_SIGNAL;
5037
5038         while (p->ops.len > ops_bgn) {
5039
5040                 top = BC_PARSE_TOP_OP(p);
5041                 assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN;
5042
5043                 if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN)
5044                         return BC_STATUS_PARSE_BAD_EXP;
5045
5046                 bc_parse_push(p, BC_PARSE_TOKEN_INST(top));
5047
5048                 nexprs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG;
5049                 bc_vec_pop(&p->ops);
5050         }
5051
5052         s = BC_STATUS_PARSE_BAD_EXP;
5053         if (prev == BC_INST_BOOL_NOT || nexprs != 1) return s;
5054
5055         for (i = 0; s && i < next.len; ++i) s *= t != next.tokens[i];
5056         if (s) return s;
5057
5058         if (!(flags & BC_PARSE_REL) && nrelops) {
5059                 s = bc_vm_posixError(BC_STATUS_POSIX_REL_POS, p->l.f, p->l.line, NULL);
5060                 if (s) return s;
5061         }
5062         else if ((flags & BC_PARSE_REL) && nrelops > 1) {
5063                 s = bc_vm_posixError(BC_STATUS_POSIX_MULTIREL, p->l.f, p->l.line, NULL);
5064                 if (s) return s;
5065         }
5066
5067         if (flags & BC_PARSE_PRINT) {
5068                 if (paren_first || !assign) bc_parse_push(p, BC_INST_PRINT);
5069                 bc_parse_push(p, BC_INST_POP);
5070         }
5071
5072         return s;
5073 }
5074
5075 static void bc_parse_init(BcParse *p, BcProgram *prog, size_t func)
5076 {
5077         bc_parse_create(p, prog, func, bc_parse_parse, bc_lex_token);
5078 }
5079
5080 static BcStatus bc_parse_expression(BcParse *p, uint8_t flags)
5081 {
5082         return bc_parse_expr(p, flags, bc_parse_next_read);
5083 }
5084 #endif // ENABLE_BC
5085
5086 #ifdef ENABLE_DC
5087 static BcStatus dc_parse_register(BcParse *p)
5088 {
5089         BcStatus s;
5090         char *name;
5091
5092         s = bc_lex_next(&p->l);
5093         if (s) return s;
5094         if (p->l.t.t != BC_LEX_NAME) return BC_STATUS_PARSE_BAD_TOKEN;
5095
5096         name = xstrdup(p->l.t.v.v);
5097         bc_parse_pushName(p, name);
5098
5099         return s;
5100 }
5101
5102 static BcStatus dc_parse_string(BcParse *p)
5103 {
5104         char *str, *name, b[DC_PARSE_BUF_LEN + 1];
5105         size_t idx, len = p->prog->strs.len;
5106
5107         sprintf(b, "%0*zu", DC_PARSE_BUF_LEN, len);
5108         name = xstrdup(b);
5109
5110         str = xstrdup(p->l.t.v.v);
5111         bc_parse_push(p, BC_INST_STR);
5112         bc_parse_pushIndex(p, len);
5113         bc_vec_push(&p->prog->strs, &str);
5114         bc_parse_addFunc(p, name, &idx);
5115
5116         return bc_lex_next(&p->l);
5117 }
5118
5119 static BcStatus dc_parse_mem(BcParse *p, uint8_t inst, bool name, bool store)
5120 {
5121         BcStatus s;
5122
5123         bc_parse_push(p, inst);
5124         if (name) {
5125                 s = dc_parse_register(p);
5126                 if (s) return s;
5127         }
5128
5129         if (store) {
5130                 bc_parse_push(p, BC_INST_SWAP);
5131                 bc_parse_push(p, BC_INST_ASSIGN);
5132                 bc_parse_push(p, BC_INST_POP);
5133         }
5134
5135         return bc_lex_next(&p->l);
5136 }
5137
5138 static BcStatus dc_parse_cond(BcParse *p, uint8_t inst)
5139 {
5140         BcStatus s;
5141
5142         bc_parse_push(p, inst);
5143         bc_parse_push(p, BC_INST_EXEC_COND);
5144
5145         s = dc_parse_register(p);
5146         if (s) return s;
5147
5148         s = bc_lex_next(&p->l);
5149         if (s) return s;
5150
5151         if (p->l.t.t == BC_LEX_ELSE) {
5152                 s = dc_parse_register(p);
5153                 if (s) return s;
5154                 s = bc_lex_next(&p->l);
5155         }
5156         else
5157                 bc_parse_push(p, BC_PARSE_STREND);
5158
5159         return s;
5160 }
5161
5162 static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags)
5163 {
5164         BcStatus s = BC_STATUS_SUCCESS;
5165         BcInst prev;
5166         uint8_t inst;
5167         bool assign, get_token = false;
5168
5169         switch (t) {
5170
5171                 case BC_LEX_OP_REL_EQ:
5172                 case BC_LEX_OP_REL_LE:
5173                 case BC_LEX_OP_REL_GE:
5174                 case BC_LEX_OP_REL_NE:
5175                 case BC_LEX_OP_REL_LT:
5176                 case BC_LEX_OP_REL_GT:
5177                 {
5178                         s = dc_parse_cond(p, t - BC_LEX_OP_REL_EQ + BC_INST_REL_EQ);
5179                         break;
5180                 }
5181
5182                 case BC_LEX_SCOLON:
5183                 case BC_LEX_COLON:
5184                 {
5185                         s = dc_parse_mem(p, BC_INST_ARRAY_ELEM, true, t == BC_LEX_COLON);
5186                         break;
5187                 }
5188
5189                 case BC_LEX_STR:
5190                 {
5191                         s = dc_parse_string(p);
5192                         break;
5193                 }
5194
5195                 case BC_LEX_NEG:
5196                 case BC_LEX_NUMBER:
5197                 {
5198                         if (t == BC_LEX_NEG) {
5199                                 s = bc_lex_next(&p->l);
5200                                 if (s) return s;
5201                                 if (p->l.t.t != BC_LEX_NUMBER) return BC_STATUS_PARSE_BAD_TOKEN;
5202                         }
5203
5204                         bc_parse_number(p, &prev, &p->nbraces);
5205
5206                         if (t == BC_LEX_NEG) bc_parse_push(p, BC_INST_NEG);
5207                         get_token = true;
5208
5209                         break;
5210                 }
5211
5212                 case BC_LEX_KEY_READ:
5213                 {
5214                         if (flags & BC_PARSE_NOREAD)
5215                                 s = BC_STATUS_EXEC_REC_READ;
5216                         else
5217                                 bc_parse_push(p, BC_INST_READ);
5218                         get_token = true;
5219                         break;
5220                 }
5221
5222                 case BC_LEX_OP_ASSIGN:
5223                 case BC_LEX_STORE_PUSH:
5224                 {
5225                         assign = t == BC_LEX_OP_ASSIGN;
5226                         inst = assign ? BC_INST_VAR : BC_INST_PUSH_TO_VAR;
5227                         s = dc_parse_mem(p, inst, true, assign);
5228                         break;
5229                 }
5230
5231                 case BC_LEX_LOAD:
5232                 case BC_LEX_LOAD_POP:
5233                 {
5234                         inst = t == BC_LEX_LOAD_POP ? BC_INST_PUSH_VAR : BC_INST_LOAD;
5235                         s = dc_parse_mem(p, inst, true, false);
5236                         break;
5237                 }
5238
5239                 case BC_LEX_STORE_IBASE:
5240                 case BC_LEX_STORE_SCALE:
5241                 case BC_LEX_STORE_OBASE:
5242                 {
5243                         inst = t - BC_LEX_STORE_IBASE + BC_INST_IBASE;
5244                         s = dc_parse_mem(p, inst, false, true);
5245                         break;
5246                 }
5247
5248                 default:
5249                 {
5250                         s = BC_STATUS_PARSE_BAD_TOKEN;
5251                         get_token = true;
5252                         break;
5253                 }
5254         }
5255
5256         if (!s && get_token) s = bc_lex_next(&p->l);
5257
5258         return s;
5259 }
5260
5261 static BcStatus dc_parse_expr(BcParse *p, uint8_t flags)
5262 {
5263         BcStatus s = BC_STATUS_SUCCESS;
5264         BcInst inst;
5265         BcLexType t;
5266
5267         if (flags & BC_PARSE_NOCALL) p->nbraces = p->prog->results.len;
5268
5269         for (t = p->l.t.t; !s && t != BC_LEX_EOF; t = p->l.t.t) {
5270
5271                 inst = dc_parse_insts[t];
5272
5273                 if (inst != BC_INST_INVALID) {
5274                         bc_parse_push(p, inst);
5275                         s = bc_lex_next(&p->l);
5276                 }
5277                 else
5278                         s = dc_parse_token(p, t, flags);
5279         }
5280
5281         if (!s && p->l.t.t == BC_LEX_EOF && (flags & BC_PARSE_NOCALL))
5282                 bc_parse_push(p, BC_INST_POP_EXEC);
5283
5284         return s;
5285 }
5286
5287 static BcStatus dc_parse_parse(BcParse *p)
5288 {
5289         BcStatus s;
5290
5291         if (p->l.t.t == BC_LEX_EOF)
5292                 s = BC_STATUS_LEX_EOF;
5293         else
5294                 s = dc_parse_expr(p, 0);
5295
5296         if (s || bcg.signe) s = bc_parse_reset(p, s);
5297
5298         return s;
5299 }
5300
5301 static void dc_parse_init(BcParse *p, BcProgram *prog, size_t func)
5302 {
5303         bc_parse_create(p, prog, func, dc_parse_parse, dc_lex_token);
5304 }
5305 #endif // ENABLE_DC
5306
5307 static void bc_program_search(BcProgram *p, char *id, BcVec **ret, bool var)
5308 {
5309         BcStatus s;
5310         BcId e, *ptr;
5311         BcVec *v, *map;
5312         size_t i;
5313         BcResultData data;
5314         bool new;
5315
5316         v = var ? &p->vars : &p->arrs;
5317         map = var ? &p->var_map : &p->arr_map;
5318
5319         e.name = id;
5320         e.idx = v->len;
5321         s = bc_map_insert(map, &e, &i);
5322         new = s != BC_STATUS_VEC_ITEM_EXISTS;
5323
5324         if (new) {
5325                 bc_array_init(&data.v, var);
5326                 bc_vec_push(v, &data.v);
5327         }
5328
5329         ptr = bc_vec_item(map, i);
5330         if (new) ptr->name = xstrdup(e.name);
5331         *ret = bc_vec_item(v, ptr->idx);
5332 }
5333
5334 static BcStatus bc_program_num(BcProgram *p, BcResult *r, BcNum **num, bool hex)
5335 {
5336         BcStatus s = BC_STATUS_SUCCESS;
5337
5338         switch (r->t) {
5339
5340                 case BC_RESULT_STR:
5341                 case BC_RESULT_TEMP:
5342                 case BC_RESULT_IBASE:
5343                 case BC_RESULT_SCALE:
5344                 case BC_RESULT_OBASE:
5345                 {
5346                         *num = &r->d.n;
5347                         break;
5348                 }
5349
5350                 case BC_RESULT_CONSTANT:
5351                 {
5352                         char **str = bc_vec_item(&p->consts, r->d.id.idx);
5353                         size_t base_t, len = strlen(*str);
5354                         BcNum *base;
5355
5356                         bc_num_init(&r->d.n, len);
5357
5358                         hex = hex && len == 1;
5359                         base = hex ? &p->hexb : &p->ib;
5360                         base_t = hex ? BC_NUM_MAX_IBASE : p->ib_t;
5361                         s = bc_num_parse(&r->d.n, *str, base, base_t);
5362
5363                         if (s) {
5364                                 bc_num_free(&r->d.n);
5365                                 return s;
5366                         }
5367
5368                         *num = &r->d.n;
5369                         r->t = BC_RESULT_TEMP;
5370
5371                         break;
5372                 }
5373
5374                 case BC_RESULT_VAR:
5375                 case BC_RESULT_ARRAY:
5376                 case BC_RESULT_ARRAY_ELEM:
5377                 {
5378                         BcVec *v;
5379
5380                         bc_program_search(p, r->d.id.name, &v, r->t == BC_RESULT_VAR);
5381
5382                         if (r->t == BC_RESULT_ARRAY_ELEM) {
5383                                 v = bc_vec_top(v);
5384                                 if (v->len <= r->d.id.idx) bc_array_expand(v, r->d.id.idx + 1);
5385                                 *num = bc_vec_item(v, r->d.id.idx);
5386                         }
5387                         else
5388                                 *num = bc_vec_top(v);
5389
5390                         break;
5391                 }
5392
5393                 case BC_RESULT_LAST:
5394                 {
5395                         *num = &p->last;
5396                         break;
5397                 }
5398
5399                 case BC_RESULT_ONE:
5400                 {
5401                         *num = &p->one;
5402                         break;
5403                 }
5404         }
5405
5406         return s;
5407 }
5408
5409 static BcStatus bc_program_binOpPrep(BcProgram *p, BcResult **l, BcNum **ln,
5410                                      BcResult **r, BcNum **rn, bool assign)
5411 {
5412         BcStatus s;
5413         bool hex;
5414         BcResultType lt, rt;
5415
5416         if (!BC_PROG_STACK(&p->results, 2)) return BC_STATUS_EXEC_STACK;
5417
5418         *r = bc_vec_item_rev(&p->results, 0);
5419         *l = bc_vec_item_rev(&p->results, 1);
5420
5421         lt = (*l)->t;
5422         rt = (*r)->t;
5423         hex = assign && (lt == BC_RESULT_IBASE || lt == BC_RESULT_OBASE);
5424
5425         s = bc_program_num(p, *l, ln, false);
5426         if (s) return s;
5427         s = bc_program_num(p, *r, rn, hex);
5428         if (s) return s;
5429
5430         // We run this again under these conditions in case any vector has been
5431         // reallocated out from under the BcNums or arrays we had.
5432         if (lt == rt && (lt == BC_RESULT_VAR || lt == BC_RESULT_ARRAY_ELEM)) {
5433                 s = bc_program_num(p, *l, ln, false);
5434                 if (s) return s;
5435         }
5436
5437         if (!BC_PROG_NUM((*l), (*ln)) && (!assign || (*l)->t != BC_RESULT_VAR))
5438                 return BC_STATUS_EXEC_BAD_TYPE;
5439         if (!assign && !BC_PROG_NUM((*r), (*ln))) return BC_STATUS_EXEC_BAD_TYPE;
5440
5441 #ifdef ENABLE_DC
5442 #else // ENABLE_DC
5443 #endif // ENABLE_DC
5444
5445         return s;
5446 }
5447
5448 static void bc_program_binOpRetire(BcProgram *p, BcResult *r)
5449 {
5450         r->t = BC_RESULT_TEMP;
5451         bc_vec_pop(&p->results);
5452         bc_vec_pop(&p->results);
5453         bc_vec_push(&p->results, r);
5454 }
5455
5456 static BcStatus bc_program_prep(BcProgram *p, BcResult **r, BcNum **n)
5457 {
5458         BcStatus s;
5459
5460         if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK;
5461         *r = bc_vec_top(&p->results);
5462
5463         s = bc_program_num(p, *r, n, false);
5464         if (s) return s;
5465
5466 #ifdef ENABLE_DC
5467 #endif // ENABLE_DC
5468
5469         if (!BC_PROG_NUM((*r), (*n))) return BC_STATUS_EXEC_BAD_TYPE;
5470
5471         return s;
5472 }
5473
5474 static void bc_program_retire(BcProgram *p, BcResult *r, BcResultType t)
5475 {
5476         r->t = t;
5477         bc_vec_pop(&p->results);
5478         bc_vec_push(&p->results, r);
5479 }
5480
5481 static BcStatus bc_program_op(BcProgram *p, char inst)
5482 {
5483         BcStatus s;
5484         BcResult *opd1, *opd2, res;
5485         BcNum *n1, *n2 = NULL;
5486
5487         s = bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, false);
5488         if (s) return s;
5489         bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
5490
5491         s = bc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, p->scale);
5492         if (s) goto err;
5493         bc_program_binOpRetire(p, &res);
5494
5495         return s;
5496
5497 err:
5498         bc_num_free(&res.d.n);
5499         return s;
5500 }
5501
5502 static BcStatus bc_program_read(BcProgram *p)
5503 {
5504         BcStatus s;
5505         BcParse parse;
5506         BcVec buf;
5507         BcInstPtr ip;
5508         size_t i;
5509         BcFunc *f = bc_vec_item(&p->fns, BC_PROG_READ);
5510
5511         for (i = 0; i < p->stack.len; ++i) {
5512                 BcInstPtr *ip_ptr = bc_vec_item(&p->stack, i);
5513                 if (ip_ptr->func == BC_PROG_READ) return BC_STATUS_EXEC_REC_READ;
5514         }
5515
5516         bc_vec_npop(&f->code, f->code.len);
5517         bc_vec_init(&buf, sizeof(char), NULL);
5518
5519         s = bc_read_line(&buf, "read> ");
5520         if (s) goto io_err;
5521
5522         p->parse_init(&parse, p, BC_PROG_READ);
5523         bc_lex_file(&parse.l, bc_program_stdin_name);
5524
5525         s = bc_parse_text(&parse, buf.v);
5526         if (s) goto exec_err;
5527         s = p->parse_expr(&parse, BC_PARSE_NOREAD);
5528         if (s) goto exec_err;
5529
5530         if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != BC_LEX_EOF) {
5531                 s = BC_STATUS_EXEC_BAD_READ_EXPR;
5532                 goto exec_err;
5533         }
5534
5535         ip.func = BC_PROG_READ;
5536         ip.idx = 0;
5537         ip.len = p->results.len;
5538
5539         // Update this pointer, just in case.
5540         f = bc_vec_item(&p->fns, BC_PROG_READ);
5541
5542         bc_vec_pushByte(&f->code, BC_INST_POP_EXEC);
5543         bc_vec_push(&p->stack, &ip);
5544
5545 exec_err:
5546         bc_parse_free(&parse);
5547 io_err:
5548         bc_vec_free(&buf);
5549         return s;
5550 }
5551
5552 static size_t bc_program_index(char *code, size_t *bgn)
5553 {
5554         char amt = code[(*bgn)++], i = 0;
5555         size_t res = 0;
5556
5557         for (; i < amt; ++i, ++(*bgn))
5558                 res |= (((size_t)((int) code[*bgn]) & UCHAR_MAX) << (i * CHAR_BIT));
5559
5560         return res;
5561 }
5562
5563 static char *bc_program_name(char *code, size_t *bgn)
5564 {
5565         size_t i;
5566         char c, *s, *str = code + *bgn, *ptr = strchr(str, BC_PARSE_STREND);
5567
5568         s = xmalloc(ptr - str + 1);
5569         c = code[(*bgn)++];
5570
5571         for (i = 0; c != 0 && c != BC_PARSE_STREND; c = code[(*bgn)++], ++i)
5572                 s[i] = c;
5573
5574         s[i] = '\0';
5575
5576         return s;
5577 }
5578
5579 static void bc_program_printString(const char *str, size_t *nchars)
5580 {
5581         size_t i, len = strlen(str);
5582
5583 #ifdef ENABLE_DC
5584         if (len == 0) {
5585                 bc_vm_putchar('\0');
5586                 return;
5587         }
5588 #endif // ENABLE_DC
5589
5590         for (i = 0; i < len; ++i, ++(*nchars)) {
5591
5592                 int c = str[i];
5593
5594                 if (c != '\\' || i == len - 1)
5595                         bc_vm_putchar(c);
5596                 else {
5597
5598                         c = str[++i];
5599
5600                         switch (c) {
5601
5602                                 case 'a':
5603                                 {
5604                                         bc_vm_putchar('\a');
5605                                         break;
5606                                 }
5607
5608                                 case 'b':
5609                                 {
5610                                         bc_vm_putchar('\b');
5611                                         break;
5612                                 }
5613
5614                                 case '\\':
5615                                 case 'e':
5616                                 {
5617                                         bc_vm_putchar('\\');
5618                                         break;
5619                                 }
5620
5621                                 case 'f':
5622                                 {
5623                                         bc_vm_putchar('\f');
5624                                         break;
5625                                 }
5626
5627                                 case 'n':
5628                                 {
5629                                         bc_vm_putchar('\n');
5630                                         *nchars = SIZE_MAX;
5631                                         break;
5632                                 }
5633
5634                                 case 'r':
5635                                 {
5636                                         bc_vm_putchar('\r');
5637                                         break;
5638                                 }
5639
5640                                 case 'q':
5641                                 {
5642                                         bc_vm_putchar('"');
5643                                         break;
5644                                 }
5645
5646                                 case 't':
5647                                 {
5648                                         bc_vm_putchar('\t');
5649                                         break;
5650                                 }
5651
5652                                 default:
5653                                 {
5654                                         // Just print the backslash and following character.
5655                                         bc_vm_putchar('\\');
5656                                         ++(*nchars);
5657                                         bc_vm_putchar(c);
5658                                         break;
5659                                 }
5660                         }
5661                 }
5662         }
5663 }
5664
5665 static BcStatus bc_program_print(BcProgram *p, char inst, size_t idx)
5666 {
5667         BcStatus s = BC_STATUS_SUCCESS;
5668         BcResult *r;
5669         size_t len, i;
5670         char *str;
5671         BcNum *num = NULL;
5672         bool pop = inst != BC_INST_PRINT;
5673
5674         if (!BC_PROG_STACK(&p->results, idx + 1)) return BC_STATUS_EXEC_STACK;
5675
5676         r = bc_vec_item_rev(&p->results, idx);
5677         s = bc_program_num(p, r, &num, false);
5678         if (s) return s;
5679
5680         if (BC_PROG_NUM(r, num)) {
5681                 s = bc_num_print(num, &p->ob, p->ob_t, !pop, &p->nchars, p->len);
5682                 if (!s) bc_num_copy(&p->last, num);
5683         }
5684         else {
5685
5686                 idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx;
5687                 str = *((char **) bc_vec_item(&p->strs, idx));
5688
5689                 if (inst == BC_INST_PRINT_STR) {
5690                         for (i = 0, len = strlen(str); i < len; ++i) {
5691                                 char c = str[i];
5692                                 bc_vm_putchar(c);
5693                                 if (c == '\n') p->nchars = SIZE_MAX;
5694                                 ++p->nchars;
5695                         }
5696                 }
5697                 else {
5698                         bc_program_printString(str, &p->nchars);
5699                         if (inst == BC_INST_PRINT) bc_vm_putchar('\n');
5700                 }
5701         }
5702
5703         if (!s && pop) bc_vec_pop(&p->results);
5704
5705         return s;
5706 }
5707
5708 static BcStatus bc_program_negate(BcProgram *p)
5709 {
5710         BcStatus s;
5711         BcResult res, *ptr;
5712         BcNum *num = NULL;
5713
5714         s = bc_program_prep(p, &ptr, &num);
5715         if (s) return s;
5716
5717         bc_num_init(&res.d.n, num->len);
5718         bc_num_copy(&res.d.n, num);
5719         if (res.d.n.len) res.d.n.neg = !res.d.n.neg;
5720
5721         bc_program_retire(p, &res, BC_RESULT_TEMP);
5722
5723         return s;
5724 }
5725
5726 static BcStatus bc_program_logical(BcProgram *p, char inst)
5727 {
5728         BcStatus s;
5729         BcResult *opd1, *opd2, res;
5730         BcNum *n1, *n2;
5731         bool cond = 0;
5732         ssize_t cmp;
5733
5734         s = bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, false);
5735         if (s) return s;
5736         bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
5737
5738         if (inst == BC_INST_BOOL_AND)
5739                 cond = bc_num_cmp(n1, &p->zero) && bc_num_cmp(n2, &p->zero);
5740         else if (inst == BC_INST_BOOL_OR)
5741                 cond = bc_num_cmp(n1, &p->zero) || bc_num_cmp(n2, &p->zero);
5742         else {
5743
5744                 cmp = bc_num_cmp(n1, n2);
5745
5746                 switch (inst) {
5747
5748                         case BC_INST_REL_EQ:
5749                         {
5750                                 cond = cmp == 0;
5751                                 break;
5752                         }
5753
5754                         case BC_INST_REL_LE:
5755                         {
5756                                 cond = cmp <= 0;
5757                                 break;
5758                         }
5759
5760                         case BC_INST_REL_GE:
5761                         {
5762                                 cond = cmp >= 0;
5763                                 break;
5764                         }
5765
5766                         case BC_INST_REL_NE:
5767                         {
5768                                 cond = cmp != 0;
5769                                 break;
5770                         }
5771
5772                         case BC_INST_REL_LT:
5773                         {
5774                                 cond = cmp < 0;
5775                                 break;
5776                         }
5777
5778                         case BC_INST_REL_GT:
5779                         {
5780                                 cond = cmp > 0;
5781                                 break;
5782                         }
5783                 }
5784         }
5785
5786         (cond ? bc_num_one : bc_num_zero)(&res.d.n);
5787
5788         bc_program_binOpRetire(p, &res);
5789
5790         return s;
5791 }
5792
5793 #ifdef ENABLE_DC
5794 static BcStatus bc_program_assignStr(BcProgram *p, BcResult *r, BcVec *v,
5795                                      bool push)
5796 {
5797         BcNum n2;
5798         BcResult res;
5799
5800         memset(&n2, 0, sizeof(BcNum));
5801         n2.rdx = res.d.id.idx = r->d.id.idx;
5802         res.t = BC_RESULT_STR;
5803
5804         if (!push) {
5805                 if (!BC_PROG_STACK(&p->results, 2)) return BC_STATUS_EXEC_STACK;
5806                 bc_vec_pop(v);
5807                 bc_vec_pop(&p->results);
5808         }
5809
5810         bc_vec_pop(&p->results);
5811
5812         bc_vec_push(&p->results, &res);
5813         bc_vec_push(v, &n2);
5814
5815         return BC_STATUS_SUCCESS;
5816 }
5817 #endif // ENABLE_DC
5818
5819 static BcStatus bc_program_copyToVar(BcProgram *p, char *name, bool var)
5820 {
5821         BcStatus s;
5822         BcResult *ptr, r;
5823         BcVec *v;
5824         BcNum *n;
5825
5826         if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK;
5827
5828         ptr = bc_vec_top(&p->results);
5829         if ((ptr->t == BC_RESULT_ARRAY) != !var) return BC_STATUS_EXEC_BAD_TYPE;
5830         bc_program_search(p, name, &v, var);
5831
5832 #ifdef ENABLE_DC
5833         if (ptr->t == BC_RESULT_STR && !var) return BC_STATUS_EXEC_BAD_TYPE;
5834         if (ptr->t == BC_RESULT_STR) return bc_program_assignStr(p, ptr, v, true);
5835 #endif // ENABLE_DC
5836
5837         s = bc_program_num(p, ptr, &n, false);
5838         if (s) return s;
5839
5840         // Do this once more to make sure that pointers were not invalidated.
5841         bc_program_search(p, name, &v, var);
5842
5843         if (var) {
5844                 bc_num_init(&r.d.n, BC_NUM_DEF_SIZE);
5845                 bc_num_copy(&r.d.n, n);
5846         }
5847         else {
5848                 bc_array_init(&r.d.v, true);
5849                 bc_array_copy(&r.d.v, (BcVec *) n);
5850         }
5851
5852         bc_vec_push(v, &r.d);
5853         bc_vec_pop(&p->results);
5854
5855         return s;
5856 }
5857
5858 static BcStatus bc_program_assign(BcProgram *p, char inst)
5859 {
5860         BcStatus s;
5861         BcResult *left, *right, res;
5862         BcNum *l = NULL, *r = NULL;
5863         unsigned long val, max;
5864         bool assign = inst == BC_INST_ASSIGN, ib, sc;
5865
5866         s = bc_program_binOpPrep(p, &left, &l, &right, &r, assign);
5867         if (s) return s;
5868
5869         ib = left->t == BC_RESULT_IBASE;
5870         sc = left->t == BC_RESULT_SCALE;
5871
5872 #ifdef ENABLE_DC
5873
5874         if (right->t == BC_RESULT_STR) {
5875
5876                 BcVec *v;
5877
5878                 if (left->t != BC_RESULT_VAR) return BC_STATUS_EXEC_BAD_TYPE;
5879                 bc_program_search(p, left->d.id.name, &v, true);
5880
5881                 return bc_program_assignStr(p, right, v, false);
5882         }
5883 #endif // ENABLE_DC
5884
5885         if (left->t == BC_RESULT_CONSTANT || left->t == BC_RESULT_TEMP)
5886                 return BC_STATUS_PARSE_BAD_ASSIGN;
5887
5888 #ifdef ENABLE_BC
5889         if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &p->zero))
5890                 return BC_STATUS_MATH_DIVIDE_BY_ZERO;
5891
5892         if (assign)
5893                 bc_num_copy(l, r);
5894         else
5895                 s = bc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, p->scale);
5896
5897         if (s) return s;
5898 #else // ENABLE_BC
5899         bc_num_copy(l, r);
5900 #endif // ENABLE_BC
5901
5902         if (ib || sc || left->t == BC_RESULT_OBASE) {
5903
5904                 size_t *ptr;
5905
5906                 s = bc_num_ulong(l, &val);
5907                 if (s) return s;
5908                 s = left->t - BC_RESULT_IBASE + BC_STATUS_EXEC_BAD_IBASE;
5909
5910                 if (sc) {
5911                         max = BC_MAX_SCALE;
5912                         ptr = &p->scale;
5913                 }
5914                 else {
5915                         if (val < BC_NUM_MIN_BASE) return s;
5916                         max = ib ? BC_NUM_MAX_IBASE : BC_MAX_OBASE;
5917                         ptr = ib ? &p->ib_t : &p->ob_t;
5918                 }
5919
5920                 if (val > max) return s;
5921                 if (!sc) bc_num_copy(ib ? &p->ib : &p->ob, l);
5922
5923                 *ptr = (size_t) val;
5924                 s = BC_STATUS_SUCCESS;
5925         }
5926
5927         bc_num_init(&res.d.n, l->len);
5928         bc_num_copy(&res.d.n, l);
5929         bc_program_binOpRetire(p, &res);
5930
5931         return s;
5932 }
5933
5934 static BcStatus bc_program_pushVar(BcProgram *p, char *code, size_t *bgn,
5935                                    bool pop, bool copy)
5936 {
5937         BcStatus s = BC_STATUS_SUCCESS;
5938         BcResult r;
5939         char *name = bc_program_name(code, bgn);
5940 #ifdef ENABLE_DC // Exclude
5941         BcNum *num;
5942         BcVec *v;
5943 #else // ENABLE_DC
5944         (void) pop, (void) copy;
5945 #endif // ENABLE_DC Exclude
5946
5947         r.t = BC_RESULT_VAR;
5948         r.d.id.name = name;
5949
5950 #ifdef ENABLE_DC
5951         bc_program_search(p, name, &v, true);
5952         num = bc_vec_top(v);
5953
5954         if (pop || copy) {
5955
5956                 if (!BC_PROG_STACK(v, 2 - copy)) {
5957                         free(name);
5958                         return BC_STATUS_EXEC_STACK;
5959                 }
5960
5961                 free(name);
5962                 name = NULL;
5963
5964                 if (!BC_PROG_STR(num)) {
5965
5966                         r.t = BC_RESULT_TEMP;
5967
5968                         bc_num_init(&r.d.n, BC_NUM_DEF_SIZE);
5969                         bc_num_copy(&r.d.n, num);
5970                 }
5971                 else {
5972                         r.t = BC_RESULT_STR;
5973                         r.d.id.idx = num->rdx;
5974                 }
5975
5976                 if (!copy) bc_vec_pop(v);
5977         }
5978 #endif // ENABLE_DC
5979
5980         bc_vec_push(&p->results, &r);
5981
5982         return s;
5983 }
5984
5985 static BcStatus bc_program_pushArray(BcProgram *p, char *code, size_t *bgn,
5986                                      char inst)
5987 {
5988         BcStatus s = BC_STATUS_SUCCESS;
5989         BcResult r;
5990         BcNum *num;
5991
5992         r.d.id.name = bc_program_name(code, bgn);
5993
5994         if (inst == BC_INST_ARRAY) {
5995                 r.t = BC_RESULT_ARRAY;
5996                 bc_vec_push(&p->results, &r);
5997         }
5998         else {
5999
6000                 BcResult *operand;
6001                 unsigned long temp;
6002
6003                 s = bc_program_prep(p, &operand, &num);
6004                 if (s) goto err;
6005                 s = bc_num_ulong(num, &temp);
6006                 if (s) goto err;
6007
6008                 if (temp > BC_MAX_DIM) {
6009                         s = BC_STATUS_EXEC_ARRAY_LEN;
6010                         goto err;
6011                 }
6012
6013                 r.d.id.idx = (size_t) temp;
6014                 bc_program_retire(p, &r, BC_RESULT_ARRAY_ELEM);
6015         }
6016
6017 err:
6018         if (s) free(r.d.id.name);
6019         return s;
6020 }
6021
6022 #ifdef ENABLE_BC
6023 static BcStatus bc_program_incdec(BcProgram *p, char inst)
6024 {
6025         BcStatus s;
6026         BcResult *ptr, res, copy;
6027         BcNum *num = NULL;
6028         char inst2 = inst;
6029
6030         s = bc_program_prep(p, &ptr, &num);
6031         if (s) return s;
6032
6033         if (inst == BC_INST_INC_POST || inst == BC_INST_DEC_POST) {
6034                 copy.t = BC_RESULT_TEMP;
6035                 bc_num_init(&copy.d.n, num->len);
6036                 bc_num_copy(&copy.d.n, num);
6037         }
6038
6039         res.t = BC_RESULT_ONE;
6040         inst = inst == BC_INST_INC_PRE || inst == BC_INST_INC_POST ?
6041                    BC_INST_ASSIGN_PLUS :
6042                    BC_INST_ASSIGN_MINUS;
6043
6044         bc_vec_push(&p->results, &res);
6045         bc_program_assign(p, inst);
6046
6047         if (inst2 == BC_INST_INC_POST || inst2 == BC_INST_DEC_POST) {
6048                 bc_vec_pop(&p->results);
6049                 bc_vec_push(&p->results, &copy);
6050         }
6051
6052         return s;
6053 }
6054
6055 static BcStatus bc_program_call(BcProgram *p, char *code, size_t *idx)
6056 {
6057         BcStatus s = BC_STATUS_SUCCESS;
6058         BcInstPtr ip;
6059         size_t i, nparams = bc_program_index(code, idx);
6060         BcFunc *func;
6061         BcVec *v;
6062         BcId *a;
6063         BcResultData param;
6064         BcResult *arg;
6065
6066         ip.idx = 0;
6067         ip.func = bc_program_index(code, idx);
6068         func = bc_vec_item(&p->fns, ip.func);
6069
6070         if (func->code.len == 0) return BC_STATUS_EXEC_UNDEFINED_FUNC;
6071         if (nparams != func->nparams) return BC_STATUS_EXEC_MISMATCHED_PARAMS;
6072         ip.len = p->results.len - nparams;
6073
6074         for (i = 0; i < nparams; ++i) {
6075
6076                 a = bc_vec_item(&func->autos, nparams - 1 - i);
6077                 arg = bc_vec_top(&p->results);
6078
6079                 if ((!a->idx) != (arg->t == BC_RESULT_ARRAY) || arg->t == BC_RESULT_STR)
6080                         return BC_STATUS_EXEC_BAD_TYPE;
6081
6082                 s = bc_program_copyToVar(p, a->name, a->idx);
6083                 if (s) return s;
6084         }
6085
6086         for (; i < func->autos.len; ++i) {
6087
6088                 a = bc_vec_item(&func->autos, i);
6089                 bc_program_search(p, a->name, &v, a->idx);
6090
6091                 if (a->idx) {
6092                         bc_num_init(&param.n, BC_NUM_DEF_SIZE);
6093                         bc_vec_push(v, &param.n);
6094                 }
6095                 else {
6096                         bc_array_init(&param.v, true);
6097                         bc_vec_push(v, &param.v);
6098                 }
6099         }
6100
6101         bc_vec_push(&p->stack, &ip);
6102
6103         return BC_STATUS_SUCCESS;
6104 }
6105
6106 static BcStatus bc_program_return(BcProgram *p, char inst)
6107 {
6108         BcStatus s;
6109         BcResult res;
6110         BcFunc *f;
6111         size_t i;
6112         BcInstPtr *ip = bc_vec_top(&p->stack);
6113
6114         if (!BC_PROG_STACK(&p->results, ip->len + inst == BC_INST_RET))
6115                 return BC_STATUS_EXEC_STACK;
6116
6117         f = bc_vec_item(&p->fns, ip->func);
6118         res.t = BC_RESULT_TEMP;
6119
6120         if (inst == BC_INST_RET) {
6121
6122                 BcNum *num;
6123                 BcResult *operand = bc_vec_top(&p->results);
6124
6125                 s = bc_program_num(p, operand, &num, false);
6126                 if (s) return s;
6127                 bc_num_init(&res.d.n, num->len);
6128                 bc_num_copy(&res.d.n, num);
6129         }
6130         else {
6131                 bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
6132                 bc_num_zero(&res.d.n);
6133         }
6134
6135         // We need to pop arguments as well, so this takes that into account.
6136         for (i = 0; i < f->autos.len; ++i) {
6137
6138                 BcVec *v;
6139                 BcId *a = bc_vec_item(&f->autos, i);
6140
6141                 bc_program_search(p, a->name, &v, a->idx);
6142                 bc_vec_pop(v);
6143         }
6144
6145         bc_vec_npop(&p->results, p->results.len - ip->len);
6146         bc_vec_push(&p->results, &res);
6147         bc_vec_pop(&p->stack);
6148
6149         return BC_STATUS_SUCCESS;
6150 }
6151 #endif // ENABLE_BC
6152
6153 static unsigned long bc_program_scale(BcNum *n)
6154 {
6155         return (unsigned long) n->rdx;
6156 }
6157
6158 static unsigned long bc_program_len(BcNum *n)
6159 {
6160         unsigned long len = n->len;
6161         size_t i;
6162
6163         if (n->rdx != n->len) return len;
6164         for (i = n->len - 1; i < n->len && n->num[i] == 0; --len, --i);
6165
6166         return len;
6167 }
6168
6169 static BcStatus bc_program_builtin(BcProgram *p, char inst)
6170 {
6171         BcStatus s;
6172         BcResult *opnd;
6173         BcNum *num = NULL;
6174         BcResult res;
6175         bool len = inst == BC_INST_LENGTH;
6176
6177         if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK;
6178         opnd = bc_vec_top(&p->results);
6179
6180         s = bc_program_num(p, opnd, &num, false);
6181         if (s) return s;
6182
6183 #ifdef ENABLE_DC
6184         if (!BC_PROG_NUM(opnd, num) && !len) return BC_STATUS_EXEC_BAD_TYPE;
6185 #endif // ENABLE_DC
6186
6187         bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
6188
6189         if (inst == BC_INST_SQRT) s = bc_num_sqrt(num, &res.d.n, p->scale);
6190 #ifdef ENABLE_BC
6191         else if (len != 0 && opnd->t == BC_RESULT_ARRAY) {
6192                 s = bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len);
6193         }
6194 #endif // ENABLE_BC
6195 #ifdef ENABLE_DC
6196         else if (len != 0 && !BC_PROG_NUM(opnd, num)) {
6197
6198                 char **str;
6199                 size_t idx = opnd->t == BC_RESULT_STR ? opnd->d.id.idx : num->rdx;
6200
6201                 str = bc_vec_item(&p->strs, idx);
6202                 s = bc_num_ulong2num(&res.d.n, strlen(*str));
6203                 if (s) goto err;
6204         }
6205 #endif // ENABLE_DC
6206         else {
6207                 BcProgramBuiltIn f = len ? bc_program_len : bc_program_scale;
6208                 s = bc_num_ulong2num(&res.d.n, f(num));
6209                 if (s) goto err;
6210         }
6211
6212         bc_program_retire(p, &res, BC_RESULT_TEMP);
6213
6214         return s;
6215
6216 err:
6217         bc_num_free(&res.d.n);
6218         return s;
6219 }
6220
6221 #ifdef ENABLE_DC
6222 static BcStatus bc_program_divmod(BcProgram *p)
6223 {
6224         BcStatus s;
6225         BcResult *opd1, *opd2, res, res2;
6226         BcNum *n1, *n2 = NULL;
6227
6228         s = bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, false);
6229         if (s) return s;
6230
6231         bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
6232         bc_num_init(&res2.d.n, n2->len);
6233
6234         s = bc_num_divmod(n1, n2, &res2.d.n, &res.d.n, p->scale);
6235         if (s) goto err;
6236
6237         bc_program_binOpRetire(p, &res2);
6238         res.t = BC_RESULT_TEMP;
6239         bc_vec_push(&p->results, &res);
6240
6241         return s;
6242
6243 err:
6244         bc_num_free(&res2.d.n);
6245         bc_num_free(&res.d.n);
6246         return s;
6247 }
6248
6249 static BcStatus bc_program_modexp(BcProgram *p)
6250 {
6251         BcStatus s;
6252         BcResult *r1, *r2, *r3, res;
6253         BcNum *n1, *n2, *n3;
6254
6255         if (!BC_PROG_STACK(&p->results, 3)) return BC_STATUS_EXEC_STACK;
6256         s = bc_program_binOpPrep(p, &r2, &n2, &r3, &n3, false);
6257         if (s) return s;
6258
6259         r1 = bc_vec_item_rev(&p->results, 2);
6260         s = bc_program_num(p, r1, &n1, false);
6261         if (s) return s;
6262         if (!BC_PROG_NUM(r1, n1)) return BC_STATUS_EXEC_BAD_TYPE;
6263
6264         // Make sure that the values have their pointers updated, if necessary.
6265         if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) {
6266
6267                 if (r1->t == r2->t) {
6268                         s = bc_program_num(p, r2, &n2, false);
6269                         if (s) return s;
6270                 }
6271
6272                 if (r1->t == r3->t) {
6273                         s = bc_program_num(p, r3, &n3, false);
6274                         if (s) return s;
6275                 }
6276         }
6277
6278         bc_num_init(&res.d.n, n3->len);
6279         s = bc_num_modexp(n1, n2, n3, &res.d.n);
6280         if (s) goto err;
6281
6282         bc_vec_pop(&p->results);
6283         bc_program_binOpRetire(p, &res);
6284
6285         return s;
6286
6287 err:
6288         bc_num_free(&res.d.n);
6289         return s;
6290 }
6291
6292 static BcStatus bc_program_stackLen(BcProgram *p)
6293 {
6294         BcStatus s;
6295         BcResult res;
6296         size_t len = p->results.len;
6297
6298         res.t = BC_RESULT_TEMP;
6299
6300         bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
6301         s = bc_num_ulong2num(&res.d.n, len);
6302         if (s) goto err;
6303         bc_vec_push(&p->results, &res);
6304
6305         return s;
6306
6307 err:
6308         bc_num_free(&res.d.n);
6309         return s;
6310 }
6311
6312 static BcStatus bc_program_asciify(BcProgram *p)
6313 {
6314         BcStatus s;
6315         BcResult *r, res;
6316         BcNum *num = NULL, n;
6317         char *str, *str2, c;
6318         size_t len = p->strs.len, idx;
6319         unsigned long val;
6320
6321         if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK;
6322         r = bc_vec_top(&p->results);
6323
6324         s = bc_program_num(p, r, &num, false);
6325         if (s) return s;
6326
6327         if (BC_PROG_NUM(r, num)) {
6328
6329                 bc_num_init(&n, BC_NUM_DEF_SIZE);
6330                 bc_num_copy(&n, num);
6331                 bc_num_truncate(&n, n.rdx);
6332
6333                 s = bc_num_mod(&n, &p->strmb, &n, 0);
6334                 if (s) goto num_err;
6335                 s = bc_num_ulong(&n, &val);
6336                 if (s) goto num_err;
6337
6338                 c = (char) val;
6339
6340                 bc_num_free(&n);
6341         }
6342         else {
6343                 idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx;
6344                 str2 = *((char **) bc_vec_item(&p->strs, idx));
6345                 c = str2[0];
6346         }
6347
6348         str = xmalloc(2);
6349         str[0] = c;
6350         str[1] = '\0';
6351
6352         str2 = xstrdup(str);
6353         bc_program_addFunc(p, str2, &idx);
6354
6355         if (idx != len + BC_PROG_REQ_FUNCS) {
6356
6357                 for (idx = 0; idx < p->strs.len; ++idx) {
6358                         if (!strcmp(*((char **) bc_vec_item(&p->strs, idx)), str)) {
6359                                 len = idx;
6360                                 break;
6361                         }
6362                 }
6363
6364                 free(str);
6365         }
6366         else
6367                 bc_vec_push(&p->strs, &str);
6368
6369         res.t = BC_RESULT_STR;
6370         res.d.id.idx = len;
6371         bc_vec_pop(&p->results);
6372         bc_vec_push(&p->results, &res);
6373
6374         return BC_STATUS_SUCCESS;
6375
6376 num_err:
6377         bc_num_free(&n);
6378         return s;
6379 }
6380
6381 static BcStatus bc_program_printStream(BcProgram *p)
6382 {
6383         BcStatus s;
6384         BcResult *r;
6385         BcNum *n = NULL;
6386         size_t idx;
6387         char *str;
6388
6389         if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK;
6390         r = bc_vec_top(&p->results);
6391
6392         s = bc_program_num(p, r, &n, false);
6393         if (s) return s;
6394
6395         if (BC_PROG_NUM(r, n))
6396                 s = bc_num_stream(n, &p->strmb, &p->nchars, p->len);
6397         else {
6398                 idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : n->rdx;
6399                 str = *((char **) bc_vec_item(&p->strs, idx));
6400                 bc_vm_printf(stdout, "%s", str);
6401         }
6402
6403         return s;
6404 }
6405
6406 static BcStatus bc_program_nquit(BcProgram *p)
6407 {
6408         BcStatus s;
6409         BcResult *opnd;
6410         BcNum *num = NULL;
6411         unsigned long val;
6412
6413         s = bc_program_prep(p, &opnd, &num);
6414         if (s) return s;
6415         s = bc_num_ulong(num, &val);
6416         if (s) return s;
6417
6418         bc_vec_pop(&p->results);
6419
6420         if (p->stack.len < val)
6421                 return BC_STATUS_EXEC_STACK;
6422         else if (p->stack.len == val)
6423                 return BC_STATUS_QUIT;
6424
6425         bc_vec_npop(&p->stack, val);
6426
6427         return s;
6428 }
6429
6430 static BcStatus bc_program_execStr(BcProgram *p, char *code, size_t *bgn,
6431                                    bool cond)
6432 {
6433         BcStatus s = BC_STATUS_SUCCESS;
6434         BcResult *r;
6435         char **str;
6436         BcFunc *f;
6437         BcParse prs;
6438         BcInstPtr ip;
6439         size_t fidx, sidx;
6440         BcNum *n;
6441         bool exec;
6442
6443         if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK;
6444
6445         r = bc_vec_top(&p->results);
6446
6447         if (cond) {
6448
6449                 BcVec *v;
6450                 char *name, *then_name = bc_program_name(code, bgn), *else_name = NULL;
6451
6452                 if (code[*bgn] == BC_PARSE_STREND)
6453                         (*bgn) += 1;
6454                 else
6455                         else_name = bc_program_name(code, bgn);
6456
6457                 exec = r->d.n.len != 0;
6458
6459                 if (exec)
6460                         name = then_name;
6461                 else if (else_name != NULL) {
6462                         exec = true;
6463                         name = else_name;
6464                 }
6465
6466                 if (exec) {
6467                         bc_program_search(p, name, &v, true);
6468                         n = bc_vec_top(v);
6469                 }
6470
6471                 free(then_name);
6472                 free(else_name);
6473
6474                 if (!exec) goto exit;
6475                 if (!BC_PROG_STR(n)) {
6476                         s = BC_STATUS_EXEC_BAD_TYPE;
6477                         goto exit;
6478                 }
6479
6480                 sidx = n->rdx;
6481         }
6482         else {
6483
6484                 if (r->t == BC_RESULT_STR)
6485                         sidx = r->d.id.idx;
6486                 else if (r->t == BC_RESULT_VAR) {
6487                         s = bc_program_num(p, r, &n, false);
6488                         if (s || !BC_PROG_STR(n)) goto exit;
6489                         sidx = n->rdx;
6490                 }
6491                 else
6492                         goto exit;
6493         }
6494
6495         fidx = sidx + BC_PROG_REQ_FUNCS;
6496
6497         str = bc_vec_item(&p->strs, sidx);
6498         f = bc_vec_item(&p->fns, fidx);
6499
6500         if (f->code.len == 0) {
6501
6502                 p->parse_init(&prs, p, fidx);
6503                 s = bc_parse_text(&prs, *str);
6504                 if (s) goto err;
6505                 s = p->parse_expr(&prs, BC_PARSE_NOCALL);
6506                 if (s) goto err;
6507
6508                 if (prs.l.t.t != BC_LEX_EOF) {
6509                         s = BC_STATUS_PARSE_BAD_EXP;
6510                         goto err;
6511                 }
6512
6513                 bc_parse_free(&prs);
6514         }
6515
6516         ip.idx = 0;
6517         ip.len = p->results.len;
6518         ip.func = fidx;
6519
6520         bc_vec_pop(&p->results);
6521         bc_vec_push(&p->stack, &ip);
6522
6523         return BC_STATUS_SUCCESS;
6524
6525 err:
6526         bc_parse_free(&prs);
6527         f = bc_vec_item(&p->fns, fidx);
6528         bc_vec_npop(&f->code, f->code.len);
6529 exit:
6530         bc_vec_pop(&p->results);
6531         return s;
6532 }
6533 #endif // ENABLE_DC
6534
6535 static BcStatus bc_program_pushGlobal(BcProgram *p, char inst)
6536 {
6537         BcStatus s;
6538         BcResult res;
6539         unsigned long val;
6540
6541         res.t = inst - BC_INST_IBASE + BC_RESULT_IBASE;
6542         if (inst == BC_INST_IBASE)
6543                 val = (unsigned long) p->ib_t;
6544         else if (inst == BC_INST_SCALE)
6545                 val = (unsigned long) p->scale;
6546         else
6547                 val = (unsigned long) p->ob_t;
6548
6549         bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
6550         s = bc_num_ulong2num(&res.d.n, val);
6551         if (s) goto err;
6552         bc_vec_push(&p->results, &res);
6553
6554         return s;
6555
6556 err:
6557         bc_num_free(&res.d.n);
6558         return s;
6559 }
6560
6561 static void bc_program_free(BcProgram *p)
6562 {
6563         bc_num_free(&p->ib);
6564         bc_num_free(&p->ob);
6565         bc_num_free(&p->hexb);
6566 #ifdef ENABLE_DC
6567         bc_num_free(&p->strmb);
6568 #endif // ENABLE_DC
6569         bc_vec_free(&p->fns);
6570         bc_vec_free(&p->fn_map);
6571         bc_vec_free(&p->vars);
6572         bc_vec_free(&p->var_map);
6573         bc_vec_free(&p->arrs);
6574         bc_vec_free(&p->arr_map);
6575         bc_vec_free(&p->strs);
6576         bc_vec_free(&p->consts);
6577         bc_vec_free(&p->results);
6578         bc_vec_free(&p->stack);
6579         bc_num_free(&p->last);
6580         bc_num_free(&p->zero);
6581         bc_num_free(&p->one);
6582 }
6583
6584 static void bc_program_init(BcProgram *p, size_t line_len, BcParseInit init,
6585                             BcParseExpr expr)
6586 {
6587         size_t idx;
6588         BcInstPtr ip;
6589
6590         memset(p, 0, sizeof(BcProgram));
6591         memset(&ip, 0, sizeof(BcInstPtr));
6592
6593         p->nchars = p->scale = 0;
6594         p->len = line_len;
6595         p->parse_init = init;
6596         p->parse_expr = expr;
6597
6598         bc_num_init(&p->ib, BC_NUM_DEF_SIZE);
6599         bc_num_ten(&p->ib);
6600         p->ib_t = 10;
6601
6602         bc_num_init(&p->ob, BC_NUM_DEF_SIZE);
6603         bc_num_ten(&p->ob);
6604         p->ob_t = 10;
6605
6606         bc_num_init(&p->hexb, BC_NUM_DEF_SIZE);
6607         bc_num_ten(&p->hexb);
6608         p->hexb.num[0] = 6;
6609
6610 #ifdef ENABLE_DC
6611         bc_num_init(&p->strmb, BC_NUM_DEF_SIZE);
6612         bc_num_ulong2num(&p->strmb, UCHAR_MAX + 1);
6613 #endif // ENABLE_DC
6614
6615         bc_num_init(&p->last, BC_NUM_DEF_SIZE);
6616         bc_num_zero(&p->last);
6617
6618         bc_num_init(&p->zero, BC_NUM_DEF_SIZE);
6619         bc_num_zero(&p->zero);
6620
6621         bc_num_init(&p->one, BC_NUM_DEF_SIZE);
6622         bc_num_one(&p->one);
6623
6624         bc_vec_init(&p->fns, sizeof(BcFunc), bc_func_free);
6625         bc_map_init(&p->fn_map);
6626
6627         bc_program_addFunc(p, xstrdup(bc_func_main), &idx);
6628         bc_program_addFunc(p, xstrdup(bc_func_read), &idx);
6629
6630         bc_vec_init(&p->vars, sizeof(BcVec), bc_vec_free);
6631         bc_map_init(&p->var_map);
6632
6633         bc_vec_init(&p->arrs, sizeof(BcVec), bc_vec_free);
6634         bc_map_init(&p->arr_map);
6635
6636         bc_vec_init(&p->strs, sizeof(char *), bc_string_free);
6637         bc_vec_init(&p->consts, sizeof(char *), bc_string_free);
6638         bc_vec_init(&p->results, sizeof(BcResult), bc_result_free);
6639         bc_vec_init(&p->stack, sizeof(BcInstPtr), NULL);
6640         bc_vec_push(&p->stack, &ip);
6641 }
6642
6643 static void bc_program_addFunc(BcProgram *p, char *name, size_t *idx)
6644 {
6645         BcStatus s;
6646         BcId entry, *entry_ptr;
6647         BcFunc f;
6648
6649         entry.name = name;
6650         entry.idx = p->fns.len;
6651
6652         s = bc_map_insert(&p->fn_map, &entry, idx);
6653         if (s) free(name);
6654
6655         entry_ptr = bc_vec_item(&p->fn_map, *idx);
6656         *idx = entry_ptr->idx;
6657
6658         if (s == BC_STATUS_VEC_ITEM_EXISTS) {
6659
6660                 BcFunc *func = bc_vec_item(&p->fns, entry_ptr->idx);
6661
6662                 // We need to reset these, so the function can be repopulated.
6663                 func->nparams = 0;
6664                 bc_vec_npop(&func->autos, func->autos.len);
6665                 bc_vec_npop(&func->code, func->code.len);
6666                 bc_vec_npop(&func->labels, func->labels.len);
6667         }
6668         else {
6669                 bc_func_init(&f);
6670                 bc_vec_push(&p->fns, &f);
6671         }
6672 }
6673
6674 static BcStatus bc_program_reset(BcProgram *p, BcStatus s)
6675 {
6676         BcFunc *f;
6677         BcInstPtr *ip;
6678
6679         bc_vec_npop(&p->stack, p->stack.len - 1);
6680         bc_vec_npop(&p->results, p->results.len);
6681
6682         f = bc_vec_item(&p->fns, 0);
6683         ip = bc_vec_top(&p->stack);
6684         ip->idx = f->code.len;
6685
6686         if (!s && bcg.signe && !bcg.tty) return BC_STATUS_QUIT;
6687
6688         bcg.sigc += bcg.signe;
6689         bcg.signe = bcg.sig != bcg.sigc;
6690
6691         if (!s || s == BC_STATUS_EXEC_SIGNAL) {
6692                 if (bcg.ttyin) {
6693                         bc_vm_puts(bc_program_ready_msg, stderr);
6694                         bc_vm_fflush(stderr);
6695                         s = BC_STATUS_SUCCESS;
6696                 }
6697                 else
6698                         s = BC_STATUS_QUIT;
6699         }
6700
6701         return s;
6702 }
6703
6704 static BcStatus bc_program_exec(BcProgram *p)
6705 {
6706         BcStatus s = BC_STATUS_SUCCESS;
6707         size_t idx;
6708         BcResult r, *ptr;
6709         BcNum *num;
6710         BcInstPtr *ip = bc_vec_top(&p->stack);
6711         BcFunc *func = bc_vec_item(&p->fns, ip->func);
6712         char *code = func->code.v;
6713         bool cond = false;
6714
6715         while (!s && ip->idx < func->code.len) {
6716
6717                 char inst = code[(ip->idx)++];
6718
6719                 switch (inst) {
6720
6721 #ifdef ENABLE_BC
6722                         case BC_INST_JUMP_ZERO:
6723                         {
6724                                 s = bc_program_prep(p, &ptr, &num);
6725                                 if (s) return s;
6726                                 cond = !bc_num_cmp(num, &p->zero);
6727                                 bc_vec_pop(&p->results);
6728                         }
6729                         // Fallthrough.
6730                         case BC_INST_JUMP:
6731                         {
6732                                 size_t *addr;
6733                                 idx = bc_program_index(code, &ip->idx);
6734                                 addr = bc_vec_item(&func->labels, idx);
6735                                 if (inst == BC_INST_JUMP || cond) ip->idx = *addr;
6736                                 break;
6737                         }
6738
6739                         case BC_INST_CALL:
6740                         {
6741                                 s = bc_program_call(p, code, &ip->idx);
6742                                 break;
6743                         }
6744
6745                         case BC_INST_INC_PRE:
6746                         case BC_INST_DEC_PRE:
6747                         case BC_INST_INC_POST:
6748                         case BC_INST_DEC_POST:
6749                         {
6750                                 s = bc_program_incdec(p, inst);
6751                                 break;
6752                         }
6753
6754                         case BC_INST_HALT:
6755                         {
6756                                 s = BC_STATUS_QUIT;
6757                                 break;
6758                         }
6759
6760                         case BC_INST_RET:
6761                         case BC_INST_RET0:
6762                         {
6763                                 s = bc_program_return(p, inst);
6764                                 break;
6765                         }
6766
6767                         case BC_INST_BOOL_OR:
6768                         case BC_INST_BOOL_AND:
6769 #endif // ENABLE_BC
6770                         case BC_INST_REL_EQ:
6771                         case BC_INST_REL_LE:
6772                         case BC_INST_REL_GE:
6773                         case BC_INST_REL_NE:
6774                         case BC_INST_REL_LT:
6775                         case BC_INST_REL_GT:
6776                         {
6777                                 s = bc_program_logical(p, inst);
6778                                 break;
6779                         }
6780
6781                         case BC_INST_READ:
6782                         {
6783                                 s = bc_program_read(p);
6784                                 break;
6785                         }
6786
6787                         case BC_INST_VAR:
6788                         {
6789                                 s = bc_program_pushVar(p, code, &ip->idx, false, false);
6790                                 break;
6791                         }
6792
6793                         case BC_INST_ARRAY_ELEM:
6794                         case BC_INST_ARRAY:
6795                         {
6796                                 s = bc_program_pushArray(p, code, &ip->idx, inst);
6797                                 break;
6798                         }
6799
6800                         case BC_INST_LAST:
6801                         {
6802                                 r.t = BC_RESULT_LAST;
6803                                 bc_vec_push(&p->results, &r);
6804                                 break;
6805                         }
6806
6807                         case BC_INST_IBASE:
6808                         case BC_INST_SCALE:
6809                         case BC_INST_OBASE:
6810                         {
6811                                 s = bc_program_pushGlobal(p, inst);
6812                                 break;
6813                         }
6814
6815                         case BC_INST_SCALE_FUNC:
6816                         case BC_INST_LENGTH:
6817                         case BC_INST_SQRT:
6818                         {
6819                                 s = bc_program_builtin(p, inst);
6820                                 break;
6821                         }
6822
6823                         case BC_INST_NUM:
6824                         {
6825                                 r.t = BC_RESULT_CONSTANT;
6826                                 r.d.id.idx = bc_program_index(code, &ip->idx);
6827                                 bc_vec_push(&p->results, &r);
6828                                 break;
6829                         }
6830
6831                         case BC_INST_POP:
6832                         {
6833                                 if (!BC_PROG_STACK(&p->results, 1))
6834                                         s = BC_STATUS_EXEC_STACK;
6835                                 else
6836                                         bc_vec_pop(&p->results);
6837                                 break;
6838                         }
6839
6840                         case BC_INST_POP_EXEC:
6841                         {
6842                                 bc_vec_pop(&p->stack);
6843                                 break;
6844                         }
6845
6846                         case BC_INST_PRINT:
6847                         case BC_INST_PRINT_POP:
6848                         case BC_INST_PRINT_STR:
6849                         {
6850                                 s = bc_program_print(p, inst, 0);
6851                                 break;
6852                         }
6853
6854                         case BC_INST_STR:
6855                         {
6856                                 r.t = BC_RESULT_STR;
6857                                 r.d.id.idx = bc_program_index(code, &ip->idx);
6858                                 bc_vec_push(&p->results, &r);
6859                                 break;
6860                         }
6861
6862                         case BC_INST_POWER:
6863                         case BC_INST_MULTIPLY:
6864                         case BC_INST_DIVIDE:
6865                         case BC_INST_MODULUS:
6866                         case BC_INST_PLUS:
6867                         case BC_INST_MINUS:
6868                         {
6869                                 s = bc_program_op(p, inst);
6870                                 break;
6871                         }
6872
6873                         case BC_INST_BOOL_NOT:
6874                         {
6875                                 s = bc_program_prep(p, &ptr, &num);
6876                                 if (s) return s;
6877
6878                                 bc_num_init(&r.d.n, BC_NUM_DEF_SIZE);
6879                                 (!bc_num_cmp(num, &p->zero) ? bc_num_one : bc_num_zero)(&r.d.n);
6880                                 bc_program_retire(p, &r, BC_RESULT_TEMP);
6881
6882                                 break;
6883                         }
6884
6885                         case BC_INST_NEG:
6886                         {
6887                                 s = bc_program_negate(p);
6888                                 break;
6889                         }
6890
6891 #ifdef ENABLE_BC
6892                         case BC_INST_ASSIGN_POWER:
6893                         case BC_INST_ASSIGN_MULTIPLY:
6894                         case BC_INST_ASSIGN_DIVIDE:
6895                         case BC_INST_ASSIGN_MODULUS:
6896                         case BC_INST_ASSIGN_PLUS:
6897                         case BC_INST_ASSIGN_MINUS:
6898 #endif // ENABLE_BC
6899                         case BC_INST_ASSIGN:
6900                         {
6901                                 s = bc_program_assign(p, inst);
6902                                 break;
6903                         }
6904 #ifdef ENABLE_DC
6905                         case BC_INST_MODEXP:
6906                         {
6907                                 s = bc_program_modexp(p);
6908                                 break;
6909                         }
6910
6911                         case BC_INST_DIVMOD:
6912                         {
6913                                 s = bc_program_divmod(p);
6914                                 break;
6915                         }
6916
6917                         case BC_INST_EXECUTE:
6918                         case BC_INST_EXEC_COND:
6919                         {
6920                                 cond = inst == BC_INST_EXEC_COND;
6921                                 s = bc_program_execStr(p, code, &ip->idx, cond);
6922                                 break;
6923                         }
6924
6925                         case BC_INST_PRINT_STACK:
6926                         {
6927                                 for (idx = 0; !s && idx < p->results.len; ++idx)
6928                                         s = bc_program_print(p, BC_INST_PRINT, idx);
6929                                 break;
6930                         }
6931
6932                         case BC_INST_CLEAR_STACK:
6933                         {
6934                                 bc_vec_npop(&p->results, p->results.len);
6935                                 break;
6936                         }
6937
6938                         case BC_INST_STACK_LEN:
6939                         {
6940                                 s = bc_program_stackLen(p);
6941                                 break;
6942                         }
6943
6944                         case BC_INST_DUPLICATE:
6945                         {
6946                                 if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK;
6947                                 ptr = bc_vec_top(&p->results);
6948                                 bc_result_copy(&r, ptr);
6949                                 bc_vec_push(&p->results, &r);
6950                                 break;
6951                         }
6952
6953                         case BC_INST_SWAP:
6954                         {
6955                                 BcResult *ptr2;
6956
6957                                 if (!BC_PROG_STACK(&p->results, 2)) return BC_STATUS_EXEC_STACK;
6958
6959                                 ptr = bc_vec_item_rev(&p->results, 0);
6960                                 ptr2 = bc_vec_item_rev(&p->results, 1);
6961                                 memcpy(&r, ptr, sizeof(BcResult));
6962                                 memcpy(ptr, ptr2, sizeof(BcResult));
6963                                 memcpy(ptr2, &r, sizeof(BcResult));
6964
6965                                 break;
6966                         }
6967
6968                         case BC_INST_ASCIIFY:
6969                         {
6970                                 s = bc_program_asciify(p);
6971                                 break;
6972                         }
6973
6974                         case BC_INST_PRINT_STREAM:
6975                         {
6976                                 s = bc_program_printStream(p);
6977                                 break;
6978                         }
6979
6980                         case BC_INST_LOAD:
6981                         case BC_INST_PUSH_VAR:
6982                         {
6983                                 bool copy = inst == BC_INST_LOAD;
6984                                 s = bc_program_pushVar(p, code, &ip->idx, true, copy);
6985                                 break;
6986                         }
6987
6988                         case BC_INST_PUSH_TO_VAR:
6989                         {
6990                                 char *name = bc_program_name(code, &ip->idx);
6991                                 s = bc_program_copyToVar(p, name, true);
6992                                 free(name);
6993                                 break;
6994                         }
6995
6996                         case BC_INST_QUIT:
6997                         {
6998                                 if (p->stack.len <= 2)
6999                                         s = BC_STATUS_QUIT;
7000                                 else
7001                                         bc_vec_npop(&p->stack, 2);
7002                                 break;
7003                         }
7004
7005                         case BC_INST_NQUIT:
7006                         {
7007                                 s = bc_program_nquit(p);
7008                                 break;
7009                         }
7010 #endif // ENABLE_DC
7011                 }
7012
7013                 if ((s && s != BC_STATUS_QUIT) || bcg.signe) s = bc_program_reset(p, s);
7014
7015                 // If the stack has changed, pointers may be invalid.
7016                 ip = bc_vec_top(&p->stack);
7017                 func = bc_vec_item(&p->fns, ip->func);
7018                 code = func->code.v;
7019         }
7020
7021         return s;
7022 }
7023
7024 #if ENABLE_FEATURE_BC_SIGNALS
7025 static void bc_vm_sig(int sig)
7026 {
7027         int err = errno;
7028         size_t len = strlen(bcg.sig_msg);
7029         if (sig == SIGINT && write(2, bcg.sig_msg, len) == (ssize_t) len) {
7030                 bcg.signe = bcg.sig == bcg.sigc;
7031                 bcg.sig += bcg.signe;
7032         }
7033         errno = err;
7034 }
7035 #endif // ENABLE_FEATURE_BC_SIGNALS
7036
7037 static void bc_vm_info(const char *const help)
7038 {
7039         bc_vm_printf(stdout, "%s %s\n", bcg.name, "1.1");
7040         bc_vm_puts(bc_copyright, stdout);
7041         if (help) bc_vm_printf(stdout, help, bcg.name);
7042 }
7043
7044 static BcStatus bc_vm_error(BcStatus s, const char *file, size_t line)
7045 {
7046         if (!s || s > BC_STATUS_VEC_ITEM_EXISTS) return s;
7047
7048         bc_vm_printf(stderr, bc_err_fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]);
7049         bc_vm_printf(stderr, "    %s", file);
7050         bc_vm_printf(stderr, bc_err_line + 4 * !line, line);
7051
7052         return s * (!bcg.ttyin || !!strcmp(file, bc_program_stdin_name));
7053 }
7054
7055 #ifdef ENABLE_BC
7056 static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line,
7057                                  const char *msg)
7058 {
7059         int p = (int) bcg.posix, w = (int) bcg.warn;
7060         const char *const fmt = p ? bc_err_fmt : bc_warn_fmt;
7061
7062         if (!(p || w) || s < BC_STATUS_POSIX_NAME_LEN) return BC_STATUS_SUCCESS;
7063
7064         bc_vm_printf(stderr, fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]);
7065         if (msg) bc_vm_printf(stderr, "    %s\n", msg);
7066         bc_vm_printf(stderr, "    %s", file);
7067         bc_vm_printf(stderr, bc_err_line + 4 * !line, line);
7068
7069         return s * (!bcg.ttyin && !!p);
7070 }
7071
7072 static BcStatus bc_vm_envArgs(BcVm *vm)
7073 {
7074         BcStatus s = BC_STATUS_SUCCESS;
7075         BcVec v;
7076         char *env_args = getenv(bc_args_env_name), *buf;
7077
7078         if (!env_args) return s;
7079
7080         vm->env_args = xstrdup(env_args);
7081         buf = vm->env_args;
7082
7083         bc_vec_init(&v, sizeof(char *), NULL);
7084         bc_vec_push(&v, &bc_args_env_name);
7085
7086         while (*buf != 0) {
7087                 if (!isspace(*buf)) {
7088                         bc_vec_push(&v, &buf);
7089                         while (*buf != 0 && !isspace(*buf)) ++buf;
7090                         if (*buf != 0) (*(buf++)) = '\0';
7091                 }
7092                 else
7093                         ++buf;
7094         }
7095
7096         s = bc_args((int) v.len, (char **) v.v, &vm->flags, &vm->files);
7097
7098         bc_vec_free(&v);
7099
7100         return s;
7101 }
7102 #endif // ENABLE_BC
7103
7104 static size_t bc_vm_envLen(const char *var)
7105 {
7106         char *lenv = getenv(var);
7107         size_t i, len = BC_NUM_PRINT_WIDTH;
7108         int num;
7109
7110         if (!lenv) return len;
7111
7112         len = strlen(lenv);
7113
7114         for (num = 1, i = 0; num && i < len; ++i) num = isdigit(lenv[i]);
7115         if (num) {
7116                 len = (size_t) atoi(lenv) - 1;
7117                 if (len < 2 || len >= INT32_MAX) len = BC_NUM_PRINT_WIDTH;
7118         }
7119         else
7120                 len = BC_NUM_PRINT_WIDTH;
7121
7122         return len;
7123 }
7124
7125 static void bc_vm_exit(BcStatus s)
7126 {
7127         bc_vm_printf(stderr, bc_err_fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]);
7128         exit((int) s);
7129 }
7130
7131 static void bc_vm_printf(FILE *restrict f, const char *fmt, ...)
7132 {
7133         va_list args;
7134         bool bad;
7135
7136         va_start(args, fmt);
7137         bad = vfprintf(f, fmt, args) < 0;
7138         va_end(args);
7139
7140         if (bad) bc_vm_exit(BC_STATUS_IO_ERR);
7141 }
7142
7143 static void bc_vm_puts(const char *str, FILE *restrict f)
7144 {
7145         if (fputs(str, f) == EOF) bc_vm_exit(BC_STATUS_IO_ERR);
7146 }
7147
7148 static void bc_vm_putchar(int c)
7149 {
7150         if (putchar(c) == EOF) bc_vm_exit(BC_STATUS_IO_ERR);
7151 }
7152
7153 static void bc_vm_fflush(FILE *restrict f)
7154 {
7155         if (fflush(f) == EOF) bc_vm_exit(BC_STATUS_IO_ERR);
7156 }
7157
7158 static BcStatus bc_vm_process(BcVm *vm, const char *text)
7159 {
7160         BcStatus s = bc_parse_text(&vm->prs, text);
7161
7162         s = bc_vm_error(s, vm->prs.l.f, vm->prs.l.line);
7163         if (s) return s;
7164
7165         while (vm->prs.l.t.t != BC_LEX_EOF) {
7166
7167                 s = vm->prs.parse(&vm->prs);
7168
7169                 if (s == BC_STATUS_LIMITS) {
7170
7171                         bc_vm_putchar('\n');
7172                         bc_vm_printf(stdout, "BC_BASE_MAX     = %lu\n", BC_MAX_OBASE);
7173                         bc_vm_printf(stdout, "BC_DIM_MAX      = %lu\n", BC_MAX_DIM);
7174                         bc_vm_printf(stdout, "BC_SCALE_MAX    = %lu\n", BC_MAX_SCALE);
7175                         bc_vm_printf(stdout, "BC_STRING_MAX   = %lu\n", BC_MAX_STRING);
7176                         bc_vm_printf(stdout, "BC_NAME_MAX     = %lu\n", BC_MAX_NAME);
7177                         bc_vm_printf(stdout, "BC_NUM_MAX      = %lu\n", BC_MAX_NUM);
7178                         bc_vm_printf(stdout, "Max Exponent    = %lu\n", BC_MAX_EXP);
7179                         bc_vm_printf(stdout, "Number of Vars  = %lu\n", BC_MAX_VARS);
7180                         bc_vm_putchar('\n');
7181
7182                         s = BC_STATUS_SUCCESS;
7183                 }
7184                 else {
7185                         if (s == BC_STATUS_QUIT) return s;
7186                         s = bc_vm_error(s, vm->prs.l.f, vm->prs.l.line);
7187                         if (s) return s;
7188                 }
7189         }
7190
7191         if (BC_PARSE_CAN_EXEC(&vm->prs)) {
7192                 s = bc_program_exec(&vm->prog);
7193                 if (!s && bcg.tty) bc_vm_fflush(stdout);
7194                 if (s && s != BC_STATUS_QUIT)
7195                         s = bc_vm_error(bc_program_reset(&vm->prog, s), vm->prs.l.f, 0);
7196         }
7197
7198         return s;
7199 }
7200
7201 static BcStatus bc_vm_file(BcVm *vm, const char *file)
7202 {
7203         BcStatus s;
7204         char *data;
7205         BcFunc *main_func;
7206         BcInstPtr *ip;
7207
7208         vm->prog.file = file;
7209         s = bc_read_file(file, &data);
7210         if (s) return bc_vm_error(s, file, 0);
7211
7212         bc_lex_file(&vm->prs.l, file);
7213         s = bc_vm_process(vm, data);
7214         if (s) goto err;
7215
7216         main_func = bc_vec_item(&vm->prog.fns, BC_PROG_MAIN);
7217         ip = bc_vec_item(&vm->prog.stack, 0);
7218
7219         if (main_func->code.len < ip->idx) s = BC_STATUS_EXEC_FILE_NOT_EXECUTABLE;
7220
7221 err:
7222         free(data);
7223         return s;
7224 }
7225
7226 static BcStatus bc_vm_stdin(BcVm *vm)
7227 {
7228         BcStatus s = BC_STATUS_SUCCESS;
7229         BcVec buf, buffer;
7230         char c;
7231         size_t len, i, str = 0;
7232         bool comment = false, notend;
7233
7234         vm->prog.file = bc_program_stdin_name;
7235         bc_lex_file(&vm->prs.l, bc_program_stdin_name);
7236
7237         bc_vec_init(&buffer, sizeof(char), NULL);
7238         bc_vec_init(&buf, sizeof(char), NULL);
7239         bc_vec_pushByte(&buffer, '\0');
7240
7241         // This loop is complex because the vm tries not to send any lines that end
7242         // with a backslash to the parser. The reason for that is because the parser
7243         // treats a backslash+newline combo as whitespace, per the bc spec. In that
7244         // case, and for strings and comments, the parser will expect more stuff.
7245         for (s = bc_read_line(&buf, ">>> "); !s; s = bc_read_line(&buf, ">>> ")) {
7246
7247                 char *string = buf.v;
7248
7249                 len = buf.len - 1;
7250
7251                 if (len == 1) {
7252                         if (str && buf.v[0] == vm->exe.send)
7253                                 str -= 1;
7254                         else if (buf.v[0] == vm->exe.sbgn)
7255                                 str += 1;
7256                 }
7257                 else if (len > 1 || comment) {
7258
7259                         for (i = 0; i < len; ++i) {
7260
7261                                 notend = len > i + 1;
7262                                 c = string[i];
7263
7264                                 if (i - 1 > len || string[i - 1] != '\\') {
7265                                         if (vm->exe.sbgn == vm->exe.send)
7266                                                 str ^= c == vm->exe.sbgn;
7267                                         else if (c == vm->exe.send)
7268                                                 str -= 1;
7269                                         else if (c == vm->exe.sbgn)
7270                                                 str += 1;
7271                                 }
7272
7273                                 if (c == '/' && notend && !comment && string[i + 1] == '*') {
7274                                         comment = true;
7275                                         break;
7276                                 }
7277                                 else if (c == '*' && notend && comment && string[i + 1] == '/')
7278                                         comment = false;
7279                         }
7280
7281                         if (str || comment || string[len - 2] == '\\') {
7282                                 bc_vec_concat(&buffer, buf.v);
7283                                 continue;
7284                         }
7285                 }
7286
7287                 bc_vec_concat(&buffer, buf.v);
7288                 s = bc_vm_process(vm, buffer.v);
7289                 if (s) goto err;
7290
7291                 bc_vec_npop(&buffer, buffer.len);
7292         }
7293
7294         if (s == BC_STATUS_BIN_FILE) s = bc_vm_error(s, vm->prs.l.f, 0);
7295
7296         // I/O error will always happen when stdin is
7297         // closed. It's not a problem in that case.
7298         s = s == BC_STATUS_IO_ERR || s == BC_STATUS_QUIT ? BC_STATUS_SUCCESS : s;
7299
7300         if (str)
7301                 s = bc_vm_error(BC_STATUS_LEX_NO_STRING_END, vm->prs.l.f,
7302                                 vm->prs.l.line);
7303         else if (comment)
7304                 s = bc_vm_error(BC_STATUS_LEX_NO_COMMENT_END, vm->prs.l.f,
7305                                 vm->prs.l.line);
7306
7307 err:
7308         bc_vec_free(&buf);
7309         bc_vec_free(&buffer);
7310         return s;
7311 }
7312
7313 static BcStatus bc_vm_exec(BcVm *vm)
7314 {
7315         BcStatus s = BC_STATUS_SUCCESS;
7316         size_t i;
7317
7318 #ifdef ENABLE_BC
7319         if (vm->flags & BC_FLAG_L) {
7320
7321                 bc_lex_file(&vm->prs.l, bc_lib_name);
7322                 s = bc_parse_text(&vm->prs, bc_lib);
7323
7324                 while (!s && vm->prs.l.t.t != BC_LEX_EOF) s = vm->prs.parse(&vm->prs);
7325
7326                 if (s) return s;
7327                 s = bc_program_exec(&vm->prog);
7328                 if (s) return s;
7329         }
7330 #endif // ENABLE_BC
7331
7332         for (i = 0; !s && i < vm->files.len; ++i)
7333                 s = bc_vm_file(vm, *((char **) bc_vec_item(&vm->files, i)));
7334         if (s && s != BC_STATUS_QUIT) return s;
7335
7336         if (bcg.bc || !vm->files.len) s = bc_vm_stdin(vm);
7337         if (!s && !BC_PARSE_CAN_EXEC(&vm->prs)) s = bc_vm_process(vm, "");
7338
7339         return s == BC_STATUS_QUIT ? BC_STATUS_SUCCESS : s;
7340 }
7341
7342 static void bc_vm_free(BcVm *vm)
7343 {
7344         bc_vec_free(&vm->files);
7345         bc_program_free(&vm->prog);
7346         bc_parse_free(&vm->prs);
7347         free(vm->env_args);
7348 }
7349
7350 static BcStatus bc_vm_init(BcVm *vm, BcVmExe exe, const char *env_len)
7351 {
7352         BcStatus s = BC_STATUS_SUCCESS;
7353         size_t len = bc_vm_envLen(env_len);
7354 #if ENABLE_FEATURE_BC_SIGNALS
7355         struct sigaction sa;
7356
7357         sigemptyset(&sa.sa_mask);
7358         sa.sa_handler = bc_vm_sig;
7359         sa.sa_flags = 0;
7360         sigaction(SIGINT, &sa, NULL);
7361 #endif // ENABLE_FEATURE_BC_SIGNALS
7362
7363         memset(vm, 0, sizeof(BcVm));
7364
7365         vm->exe = exe;
7366         vm->flags = 0;
7367         vm->env_args = NULL;
7368
7369         bc_vec_init(&vm->files, sizeof(char *), NULL);
7370
7371 #ifdef ENABLE_BC
7372         vm->flags |= BC_FLAG_S * bcg.bc * (getenv("POSIXLY_CORRECT") != NULL);
7373         if (bcg.bc) s = bc_vm_envArgs(vm);
7374 #endif // ENABLE_BC
7375
7376         bc_program_init(&vm->prog, len, exe.init, exe.exp);
7377         exe.init(&vm->prs, &vm->prog, BC_PROG_MAIN);
7378
7379         return s;
7380 }
7381
7382 static BcStatus bc_vm_run(int argc, char *argv[], BcVmExe exe,
7383                           const char *env_len)
7384 {
7385         BcStatus st;
7386         BcVm vm;
7387
7388         st = bc_vm_init(&vm, exe, env_len);
7389         if (st) goto exit;
7390         st = bc_args(argc, argv, &vm.flags, &vm.files);
7391         if (st) goto exit;
7392
7393         bcg.ttyin = isatty(0);
7394         bcg.tty = bcg.ttyin || (vm.flags & BC_FLAG_I) || isatty(1);
7395
7396 #ifdef ENABLE_BC
7397         bcg.posix = vm.flags & BC_FLAG_S;
7398         bcg.warn = vm.flags & BC_FLAG_W;
7399 #endif // ENABLE_BC
7400 #ifdef ENABLE_DC
7401         bcg.exreg = vm.flags & BC_FLAG_X;
7402 #endif // ENABLE_DC
7403
7404         if (bcg.ttyin && !(vm.flags & BC_FLAG_Q)) bc_vm_info(NULL);
7405         st = bc_vm_exec(&vm);
7406
7407 exit:
7408         bc_vm_free(&vm);
7409         return st;
7410 }
7411
7412 #ifdef ENABLE_BC
7413 BcStatus bc_main(int argc, char *argv[])
7414 {
7415         BcVmExe exec;
7416
7417         bcg.bc = true;
7418         bcg.name = bc_name;
7419 #if ENABLE_FEATURE_BC_SIGNALS
7420         bcg.sig_msg = bc_sig_msg;
7421 #endif // ENABLE_FEATURE_BC_SIGNALS
7422
7423         exec.init = bc_parse_init;
7424         exec.exp = bc_parse_expression;
7425         exec.sbgn = exec.send = '"';
7426
7427         return bc_vm_run(argc, argv, exec, "BC_LINE_LENGTH");
7428 }
7429 #endif // ENABLE_BC
7430
7431 #ifdef ENABLE_DC
7432 BcStatus dc_main(int argc, char *argv[])
7433 {
7434         BcVmExe exec;
7435
7436         bcg.bc = false;
7437         bcg.name = dc_name;
7438 #if ENABLE_FEATURE_BC_SIGNALS
7439         bcg.sig_msg = dc_sig_msg;
7440 #endif // ENABLE_FEATURE_BC_SIGNALS
7441
7442         exec.init = dc_parse_init;
7443         exec.exp = dc_parse_expr;
7444         exec.sbgn = '[';
7445         exec.send = ']';
7446
7447         return bc_vm_run(argc, argv, exec, "DC_LINE_LENGTH");
7448 }
7449 #endif // ENABLE_DC