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