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