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