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