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