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