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