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