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