d208a0cc6aee29eb7e1abe40eb86e8aebc125088
[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 #define bc_map_init(v) (bc_vec_init((v), sizeof(BcId), bc_id_free))
193
194 typedef signed char BcDig;
195
196 typedef struct BcNum {
197         BcDig *restrict num;
198         size_t rdx;
199         size_t len;
200         size_t cap;
201         bool neg;
202 } BcNum;
203
204 #define BC_NUM_MIN_BASE ((unsigned long) 2)
205 #define BC_NUM_MAX_IBASE ((unsigned long) 16)
206 #define BC_NUM_DEF_SIZE (16)
207 #define BC_NUM_PRINT_WIDTH (69)
208
209 #define BC_NUM_KARATSUBA_LEN (32)
210
211 #define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg))
212 #define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1)
213 #define BC_NUM_INT(n) ((n)->len - (n)->rdx)
214 #define BC_NUM_AREQ(a, b) \
215         (BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1)
216 #define BC_NUM_MREQ(a, b, scale) \
217         (BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX((scale), (a)->rdx + (b)->rdx) + 1)
218
219 typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t);
220 typedef void (*BcNumDigitOp)(size_t, size_t, bool, size_t *, size_t);
221
222 static void bc_num_init(BcNum *n, size_t req);
223 static void bc_num_expand(BcNum *n, size_t req);
224 static void bc_num_copy(BcNum *d, BcNum *s);
225 static void bc_num_free(void *num);
226
227 static BcStatus bc_num_ulong(BcNum *n, unsigned long *result);
228 static void bc_num_ulong2num(BcNum *n, unsigned long val);
229
230 static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale);
231 static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale);
232 static BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale);
233 static BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale);
234 static BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale);
235 static BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale);
236 static BcStatus bc_num_sqrt(BcNum *a, BcNum *b, size_t scale);
237 static BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d,
238                               size_t scale);
239
240 typedef enum BcInst {
241
242 #if ENABLE_BC
243         BC_INST_INC_PRE,
244         BC_INST_DEC_PRE,
245         BC_INST_INC_POST,
246         BC_INST_DEC_POST,
247 #endif
248
249         BC_INST_NEG,
250
251         BC_INST_POWER,
252         BC_INST_MULTIPLY,
253         BC_INST_DIVIDE,
254         BC_INST_MODULUS,
255         BC_INST_PLUS,
256         BC_INST_MINUS,
257
258         BC_INST_REL_EQ,
259         BC_INST_REL_LE,
260         BC_INST_REL_GE,
261         BC_INST_REL_NE,
262         BC_INST_REL_LT,
263         BC_INST_REL_GT,
264
265         BC_INST_BOOL_NOT,
266         BC_INST_BOOL_OR,
267         BC_INST_BOOL_AND,
268
269 #if ENABLE_BC
270         BC_INST_ASSIGN_POWER,
271         BC_INST_ASSIGN_MULTIPLY,
272         BC_INST_ASSIGN_DIVIDE,
273         BC_INST_ASSIGN_MODULUS,
274         BC_INST_ASSIGN_PLUS,
275         BC_INST_ASSIGN_MINUS,
276 #endif
277         BC_INST_ASSIGN,
278
279         BC_INST_NUM,
280         BC_INST_VAR,
281         BC_INST_ARRAY_ELEM,
282         BC_INST_ARRAY,
283
284         BC_INST_SCALE_FUNC,
285         BC_INST_IBASE,
286         BC_INST_SCALE,
287         BC_INST_LAST,
288         BC_INST_LENGTH,
289         BC_INST_READ,
290         BC_INST_OBASE,
291         BC_INST_SQRT,
292
293         BC_INST_PRINT,
294         BC_INST_PRINT_POP,
295         BC_INST_STR,
296         BC_INST_PRINT_STR,
297
298 #if ENABLE_BC
299         BC_INST_JUMP,
300         BC_INST_JUMP_ZERO,
301
302         BC_INST_CALL,
303
304         BC_INST_RET,
305         BC_INST_RET0,
306
307         BC_INST_HALT,
308 #endif
309
310         BC_INST_POP,
311         BC_INST_POP_EXEC,
312
313 #if ENABLE_DC
314         BC_INST_MODEXP,
315         BC_INST_DIVMOD,
316
317         BC_INST_EXECUTE,
318         BC_INST_EXEC_COND,
319
320         BC_INST_ASCIIFY,
321         BC_INST_PRINT_STREAM,
322
323         BC_INST_PRINT_STACK,
324         BC_INST_CLEAR_STACK,
325         BC_INST_STACK_LEN,
326         BC_INST_DUPLICATE,
327         BC_INST_SWAP,
328
329         BC_INST_LOAD,
330         BC_INST_PUSH_VAR,
331         BC_INST_PUSH_TO_VAR,
332
333         BC_INST_QUIT,
334         BC_INST_NQUIT,
335
336         BC_INST_INVALID = -1,
337 #endif
338
339 } BcInst;
340
341 typedef struct BcId {
342         char *name;
343         size_t idx;
344 } BcId;
345
346 typedef struct BcFunc {
347         BcVec code;
348         BcVec labels;
349         size_t nparams;
350         BcVec autos;
351 } BcFunc;
352
353 typedef enum BcResultType {
354
355         BC_RESULT_TEMP,
356
357         BC_RESULT_VAR,
358         BC_RESULT_ARRAY_ELEM,
359         BC_RESULT_ARRAY,
360
361         BC_RESULT_STR,
362
363         BC_RESULT_IBASE,
364         BC_RESULT_SCALE,
365         BC_RESULT_LAST,
366
367         // These are between to calculate ibase, obase, and last from instructions.
368         BC_RESULT_CONSTANT,
369         BC_RESULT_ONE,
370
371         BC_RESULT_OBASE,
372
373 } BcResultType;
374
375 typedef union BcResultData {
376         BcNum n;
377         BcVec v;
378         BcId id;
379 } BcResultData;
380
381 typedef struct BcResult {
382         BcResultType t;
383         BcResultData d;
384 } BcResult;
385
386 typedef struct BcInstPtr {
387         size_t func;
388         size_t idx;
389         size_t len;
390 } BcInstPtr;
391
392 static void bc_array_expand(BcVec *a, size_t len);
393 static int bc_id_cmp(const void *e1, const void *e2);
394
395 // BC_LEX_NEG is not used in lexing; it is only for parsing.
396 typedef enum BcLexType {
397
398         BC_LEX_EOF,
399         BC_LEX_INVALID,
400
401         BC_LEX_OP_INC,
402         BC_LEX_OP_DEC,
403
404         BC_LEX_NEG,
405
406         BC_LEX_OP_POWER,
407         BC_LEX_OP_MULTIPLY,
408         BC_LEX_OP_DIVIDE,
409         BC_LEX_OP_MODULUS,
410         BC_LEX_OP_PLUS,
411         BC_LEX_OP_MINUS,
412
413         BC_LEX_OP_REL_EQ,
414         BC_LEX_OP_REL_LE,
415         BC_LEX_OP_REL_GE,
416         BC_LEX_OP_REL_NE,
417         BC_LEX_OP_REL_LT,
418         BC_LEX_OP_REL_GT,
419
420         BC_LEX_OP_BOOL_NOT,
421         BC_LEX_OP_BOOL_OR,
422         BC_LEX_OP_BOOL_AND,
423
424         BC_LEX_OP_ASSIGN_POWER,
425         BC_LEX_OP_ASSIGN_MULTIPLY,
426         BC_LEX_OP_ASSIGN_DIVIDE,
427         BC_LEX_OP_ASSIGN_MODULUS,
428         BC_LEX_OP_ASSIGN_PLUS,
429         BC_LEX_OP_ASSIGN_MINUS,
430         BC_LEX_OP_ASSIGN,
431
432         BC_LEX_NLINE,
433         BC_LEX_WHITESPACE,
434
435         BC_LEX_LPAREN,
436         BC_LEX_RPAREN,
437
438         BC_LEX_LBRACKET,
439         BC_LEX_COMMA,
440         BC_LEX_RBRACKET,
441
442         BC_LEX_LBRACE,
443         BC_LEX_SCOLON,
444         BC_LEX_RBRACE,
445
446         BC_LEX_STR,
447         BC_LEX_NAME,
448         BC_LEX_NUMBER,
449
450         BC_LEX_KEY_AUTO,
451         BC_LEX_KEY_BREAK,
452         BC_LEX_KEY_CONTINUE,
453         BC_LEX_KEY_DEFINE,
454         BC_LEX_KEY_ELSE,
455         BC_LEX_KEY_FOR,
456         BC_LEX_KEY_HALT,
457         BC_LEX_KEY_IBASE,
458         BC_LEX_KEY_IF,
459         BC_LEX_KEY_LAST,
460         BC_LEX_KEY_LENGTH,
461         BC_LEX_KEY_LIMITS,
462         BC_LEX_KEY_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
500 } BcLexType;
501
502 struct BcLex;
503 typedef BcStatus (*BcLexNext)(struct BcLex *);
504
505 typedef struct BcLex {
506
507         const char *buf;
508         size_t i;
509         size_t line;
510         const char *f;
511         size_t len;
512         bool newline;
513
514         struct {
515                 BcLexType t;
516                 BcLexType last;
517                 BcVec v;
518         } t;
519
520         BcLexNext next;
521
522 } BcLex;
523
524 #define BC_PARSE_STREND ((char) UCHAR_MAX)
525
526 #define bc_parse_push(p, i) (bc_vec_pushByte(&(p)->func->code, (char) (i)))
527 #define bc_parse_updateFunc(p, f) \
528         ((p)->func = bc_vec_item(&G.prog.fns, ((p)->fidx = (f))))
529
530 #define BC_PARSE_REL (1 << 0)
531 #define BC_PARSE_PRINT (1 << 1)
532 #define BC_PARSE_NOCALL (1 << 2)
533 #define BC_PARSE_NOREAD (1 << 3)
534 #define BC_PARSE_ARRAY (1 << 4)
535
536 #define BC_PARSE_TOP_FLAG_PTR(parse) ((uint8_t *) bc_vec_top(&(parse)->flags))
537 #define BC_PARSE_TOP_FLAG(parse) (*(BC_PARSE_TOP_FLAG_PTR(parse)))
538
539 #define BC_PARSE_FLAG_FUNC_INNER (1 << 0)
540 #define BC_PARSE_FUNC_INNER(parse) \
541         (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_FUNC_INNER)
542
543 #define BC_PARSE_FLAG_FUNC (1 << 1)
544 #define BC_PARSE_FUNC(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_FUNC)
545
546 #define BC_PARSE_FLAG_BODY (1 << 2)
547 #define BC_PARSE_BODY(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_BODY)
548
549 #define BC_PARSE_FLAG_LOOP (1 << 3)
550 #define BC_PARSE_LOOP(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_LOOP)
551
552 #define BC_PARSE_FLAG_LOOP_INNER (1 << 4)
553 #define BC_PARSE_LOOP_INNER(parse) \
554         (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_LOOP_INNER)
555
556 #define BC_PARSE_FLAG_IF (1 << 5)
557 #define BC_PARSE_IF(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_IF)
558
559 #define BC_PARSE_FLAG_ELSE (1 << 6)
560 #define BC_PARSE_ELSE(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_ELSE)
561
562 #define BC_PARSE_FLAG_IF_END (1 << 7)
563 #define BC_PARSE_IF_END(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_IF_END)
564
565 #define BC_PARSE_CAN_EXEC(parse)                                             \
566         (!(BC_PARSE_TOP_FLAG(parse) &                                            \
567            (BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_BODY | \
568             BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER | BC_PARSE_FLAG_IF |   \
569             BC_PARSE_FLAG_ELSE | BC_PARSE_FLAG_IF_END)))
570
571 typedef struct BcOp {
572         char prec;
573         bool left;
574 } BcOp;
575
576 typedef struct BcParseNext {
577         uint32_t len;
578         BcLexType tokens[4];
579 } BcParseNext;
580
581 #define BC_PARSE_NEXT_TOKENS(...) .tokens = { __VA_ARGS__ }
582 #define BC_PARSE_NEXT(a, ...)                         \
583         {                                                 \
584                 .len = (a), BC_PARSE_NEXT_TOKENS(__VA_ARGS__) \
585         }
586
587 struct BcParse;
588
589 struct BcProgram;
590
591 typedef BcStatus (*BcParseParse)(struct BcParse *);
592
593 typedef struct BcParse {
594
595         BcParseParse parse;
596
597         BcLex l;
598
599         BcVec flags;
600
601         BcVec exits;
602         BcVec conds;
603
604         BcVec ops;
605
606         BcFunc *func;
607         size_t fidx;
608
609         size_t nbraces;
610         bool auto_part;
611
612 } BcParse;
613
614 #if ENABLE_BC
615
616 typedef struct BcLexKeyword {
617         const char name[9];
618         const char len;
619         const bool posix;
620 } BcLexKeyword;
621
622 #define BC_LEX_KW_ENTRY(a, b, c)            \
623         {                                       \
624                 .name = a, .len = (b), .posix = (c) \
625         }
626
627 static BcStatus bc_lex_token(BcLex *l);
628
629 #define BC_PARSE_TOP_OP(p) (*((BcLexType *) bc_vec_top(&(p)->ops)))
630 #define BC_PARSE_LEAF(p, rparen)                                \
631         (((p) >= BC_INST_NUM && (p) <= BC_INST_SQRT) || (rparen) || \
632          (p) == BC_INST_INC_POST || (p) == BC_INST_DEC_POST)
633
634 // We can calculate the conversion between tokens and exprs by subtracting the
635 // position of the first operator in the lex enum and adding the position of the
636 // first in the expr enum. Note: This only works for binary operators.
637 #define BC_PARSE_TOKEN_INST(t) ((char) ((t) -BC_LEX_NEG + BC_INST_NEG))
638
639 static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next);
640
641 #endif // ENABLE_BC
642
643 #if ENABLE_DC
644
645 #define DC_PARSE_BUF_LEN ((int) (sizeof(uint32_t) * CHAR_BIT))
646
647 static BcStatus dc_lex_token(BcLex *l);
648
649 static BcStatus dc_parse_expr(BcParse *p, uint8_t flags);
650
651 #endif // ENABLE_DC
652
653 typedef struct BcProgram {
654
655         size_t len;
656         size_t scale;
657
658         BcNum ib;
659         size_t ib_t;
660         BcNum ob;
661         size_t ob_t;
662
663         BcNum hexb;
664
665 #if ENABLE_DC
666         BcNum strmb;
667 #endif
668
669         BcVec results;
670         BcVec stack;
671
672         BcVec fns;
673         BcVec fn_map;
674
675         BcVec vars;
676         BcVec var_map;
677
678         BcVec arrs;
679         BcVec arr_map;
680
681         BcVec strs;
682         BcVec consts;
683
684         const char *file;
685
686         BcNum last;
687         BcNum zero;
688         BcNum one;
689
690         size_t nchars;
691
692 } BcProgram;
693
694 #define BC_PROG_STACK(s, n) ((s)->len >= ((size_t) n))
695
696 #define BC_PROG_MAIN (0)
697 #define BC_PROG_READ (1)
698
699 #if ENABLE_DC
700 #define BC_PROG_REQ_FUNCS (2)
701 #endif
702
703 #define BC_PROG_STR(n) (!(n)->num && !(n)->cap)
704 #define BC_PROG_NUM(r, n) \
705         ((r)->t != BC_RESULT_ARRAY && (r)->t != BC_RESULT_STR && !BC_PROG_STR(n))
706
707 typedef unsigned long (*BcProgramBuiltIn)(BcNum *);
708
709 static void bc_program_addFunc(char *name, size_t *idx);
710 static void bc_program_reset(void);
711
712 #define BC_FLAG_X (1 << 0)
713 #define BC_FLAG_W (1 << 1)
714 #define BC_FLAG_V (1 << 2)
715 #define BC_FLAG_S (1 << 3)
716 #define BC_FLAG_Q (1 << 4)
717 #define BC_FLAG_L (1 << 5)
718 #define BC_FLAG_I (1 << 6)
719
720 #define BC_MAX(a, b) ((a) > (b) ? (a) : (b))
721 #define BC_MIN(a, b) ((a) < (b) ? (a) : (b))
722
723 #define BC_MAX_OBASE  ((unsigned) 999)
724 #define BC_MAX_DIM    ((unsigned) INT_MAX)
725 #define BC_MAX_SCALE  ((unsigned) UINT_MAX)
726 #define BC_MAX_STRING ((unsigned) UINT_MAX - 1)
727 #define BC_MAX_NAME   BC_MAX_STRING
728 #define BC_MAX_NUM    BC_MAX_STRING
729 #define BC_MAX_EXP    ((unsigned long) LONG_MAX)
730 #define BC_MAX_VARS   ((unsigned long) SIZE_MAX - 1)
731
732 struct globals {
733         smallint ttyin;
734         smallint eof;
735         char sbgn;
736         char send;
737
738         BcParse prs;
739         BcProgram prog;
740
741         BcVec files;
742
743         char *env_args;
744 } FIX_ALIASING;
745 #define G (*ptr_to_globals)
746 #define INIT_G() do { \
747         SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
748 } while (0)
749 #define G_posix (ENABLE_BC && (option_mask32 & BC_FLAG_S))
750 #define G_warn  (ENABLE_BC && (option_mask32 & BC_FLAG_W))
751 #define G_exreg (ENABLE_DC && (option_mask32 & BC_FLAG_X))
752 #define G_interrupt (ENABLE_FEATURE_BC_SIGNALS ? bb_got_signal : 0)
753
754
755 #define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b'))
756
757 static void bc_vm_info(void);
758
759 #if ENABLE_BC
760 static const BcLexKeyword bc_lex_kws[20] = {
761         BC_LEX_KW_ENTRY("auto", 4, true),
762         BC_LEX_KW_ENTRY("break", 5, true),
763         BC_LEX_KW_ENTRY("continue", 8, false),
764         BC_LEX_KW_ENTRY("define", 6, true),
765         BC_LEX_KW_ENTRY("else", 4, false),
766         BC_LEX_KW_ENTRY("for", 3, true),
767         BC_LEX_KW_ENTRY("halt", 4, false),
768         BC_LEX_KW_ENTRY("ibase", 5, true),
769         BC_LEX_KW_ENTRY("if", 2, true),
770         BC_LEX_KW_ENTRY("last", 4, false),
771         BC_LEX_KW_ENTRY("length", 6, true),
772         BC_LEX_KW_ENTRY("limits", 6, false),
773         BC_LEX_KW_ENTRY("obase", 5, true),
774         BC_LEX_KW_ENTRY("print", 5, false),
775         BC_LEX_KW_ENTRY("quit", 4, true),
776         BC_LEX_KW_ENTRY("read", 4, false),
777         BC_LEX_KW_ENTRY("return", 6, true),
778         BC_LEX_KW_ENTRY("scale", 5, true),
779         BC_LEX_KW_ENTRY("sqrt", 4, true),
780         BC_LEX_KW_ENTRY("while", 5, true),
781 };
782
783 // This is an array that corresponds to token types. An entry is
784 // true if the token is valid in an expression, false otherwise.
785 static const bool bc_parse_exprs[] = {
786         false, false, true, true, true, true, true, true, true, true, true, true,
787         true, true, true, true, true, true, true, true, true, true, true, true,
788         true, true, true, false, false, true, true, false, false, false, false,
789         false, false, false, true, true, false, false, false, false, false, false,
790         false, true, false, true, true, true, true, false, false, true, false, true,
791         true, false,
792 };
793
794 // This is an array of data for operators that correspond to token types.
795 static const BcOp bc_parse_ops[] = {
796         { 0, false }, { 0, false },
797         { 1, false },
798         { 2, false },
799         { 3, true }, { 3, true }, { 3, true },
800         { 4, true }, { 4, true },
801         { 6, true }, { 6, true }, { 6, true }, { 6, true }, { 6, true }, { 6, true },
802         { 1, false },
803         { 7, true }, { 7, true },
804         { 5, false }, { 5, false }, { 5, false }, { 5, false }, { 5, false },
805         { 5, false }, { 5, false },
806 };
807
808 // These identify what tokens can come after expressions in certain cases.
809 static const BcParseNext bc_parse_next_expr =
810         BC_PARSE_NEXT(4, BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_RBRACE, BC_LEX_EOF);
811 static const BcParseNext bc_parse_next_param =
812         BC_PARSE_NEXT(2, BC_LEX_RPAREN, BC_LEX_COMMA);
813 static const BcParseNext bc_parse_next_print =
814         BC_PARSE_NEXT(4, BC_LEX_COMMA, BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_EOF);
815 static const BcParseNext bc_parse_next_rel = BC_PARSE_NEXT(1, BC_LEX_RPAREN);
816 static const BcParseNext bc_parse_next_elem = BC_PARSE_NEXT(1, BC_LEX_RBRACKET);
817 static const BcParseNext bc_parse_next_for = BC_PARSE_NEXT(1, BC_LEX_SCOLON);
818 static const BcParseNext bc_parse_next_read =
819         BC_PARSE_NEXT(2, BC_LEX_NLINE, BC_LEX_EOF);
820 #endif // ENABLE_BC
821
822 #if ENABLE_DC
823 static const BcLexType dc_lex_regs[] = {
824         BC_LEX_OP_REL_EQ, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_NE,
825         BC_LEX_OP_REL_LT, BC_LEX_OP_REL_GT, BC_LEX_SCOLON, BC_LEX_COLON,
826         BC_LEX_ELSE, BC_LEX_LOAD, BC_LEX_LOAD_POP, BC_LEX_OP_ASSIGN,
827         BC_LEX_STORE_PUSH,
828 };
829
830 static const size_t dc_lex_regs_len = sizeof(dc_lex_regs) / sizeof(BcLexType);
831
832 static const BcLexType dc_lex_tokens[] = {
833         BC_LEX_OP_MODULUS, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_LPAREN,
834         BC_LEX_INVALID, BC_LEX_OP_MULTIPLY, BC_LEX_OP_PLUS, BC_LEX_INVALID,
835         BC_LEX_OP_MINUS, BC_LEX_INVALID, BC_LEX_OP_DIVIDE,
836         BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID,
837         BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID,
838         BC_LEX_INVALID, BC_LEX_INVALID,
839         BC_LEX_COLON, BC_LEX_SCOLON, BC_LEX_OP_REL_GT, BC_LEX_OP_REL_EQ,
840         BC_LEX_OP_REL_LT, BC_LEX_KEY_READ, BC_LEX_INVALID,
841         BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID,
842         BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_EQ_NO_REG, BC_LEX_INVALID,
843         BC_LEX_KEY_IBASE, BC_LEX_INVALID, BC_LEX_KEY_SCALE, BC_LEX_LOAD_POP,
844         BC_LEX_INVALID, BC_LEX_OP_BOOL_NOT, BC_LEX_KEY_OBASE, BC_LEX_PRINT_STREAM,
845         BC_LEX_NQUIT, BC_LEX_POP, BC_LEX_STORE_PUSH, BC_LEX_INVALID, BC_LEX_INVALID,
846         BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_SCALE_FACTOR, BC_LEX_INVALID,
847         BC_LEX_KEY_LENGTH, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID,
848         BC_LEX_OP_POWER, BC_LEX_NEG, BC_LEX_INVALID,
849         BC_LEX_ASCIIFY, BC_LEX_INVALID, BC_LEX_CLEAR_STACK, BC_LEX_DUPLICATE,
850         BC_LEX_ELSE, BC_LEX_PRINT_STACK, BC_LEX_INVALID, BC_LEX_INVALID,
851         BC_LEX_STORE_IBASE, BC_LEX_INVALID, BC_LEX_STORE_SCALE, BC_LEX_LOAD,
852         BC_LEX_INVALID, BC_LEX_PRINT_POP, BC_LEX_STORE_OBASE, BC_LEX_KEY_PRINT,
853         BC_LEX_KEY_QUIT, BC_LEX_SWAP, BC_LEX_OP_ASSIGN, BC_LEX_INVALID,
854         BC_LEX_INVALID, BC_LEX_KEY_SQRT, BC_LEX_INVALID, BC_LEX_EXECUTE,
855         BC_LEX_INVALID, BC_LEX_STACK_LEVEL,
856         BC_LEX_LBRACE, BC_LEX_OP_MODEXP, BC_LEX_INVALID, BC_LEX_OP_DIVMOD,
857         BC_LEX_INVALID
858 };
859
860 static const BcInst dc_parse_insts[] = {
861         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE,
862         BC_INST_INVALID, BC_INST_POWER, BC_INST_MULTIPLY, BC_INST_DIVIDE,
863         BC_INST_MODULUS, BC_INST_PLUS, BC_INST_MINUS,
864         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
865         BC_INST_INVALID, BC_INST_INVALID,
866         BC_INST_BOOL_NOT, BC_INST_INVALID, BC_INST_INVALID,
867         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
868         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
869         BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GT, BC_INST_INVALID,
870         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE,
871         BC_INST_INVALID, BC_INST_INVALID,
872         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
873         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
874         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_IBASE,
875         BC_INST_INVALID, BC_INST_INVALID, BC_INST_LENGTH, BC_INST_INVALID,
876         BC_INST_OBASE, BC_INST_PRINT, BC_INST_QUIT, BC_INST_INVALID,
877         BC_INST_INVALID, BC_INST_SCALE, BC_INST_SQRT, BC_INST_INVALID,
878         BC_INST_REL_EQ, BC_INST_MODEXP, BC_INST_DIVMOD, BC_INST_INVALID,
879         BC_INST_INVALID, BC_INST_EXECUTE, BC_INST_PRINT_STACK, BC_INST_CLEAR_STACK,
880         BC_INST_STACK_LEN, BC_INST_DUPLICATE, BC_INST_SWAP, BC_INST_POP,
881         BC_INST_ASCIIFY, BC_INST_PRINT_STREAM, BC_INST_INVALID, BC_INST_INVALID,
882         BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
883         BC_INST_PRINT, BC_INST_NQUIT, BC_INST_SCALE_FUNC,
884 };
885 #endif // ENABLE_DC
886
887 static const BcNumBinaryOp bc_program_ops[] = {
888         bc_num_pow, bc_num_mul, bc_num_div, bc_num_mod, bc_num_add, bc_num_sub,
889 };
890
891 static const char bc_program_stdin_name[] = "<stdin>";
892
893 #if ENABLE_BC
894 static const char *bc_lib_name = "gen/lib.bc";
895
896 static const char bc_lib[] = {
897   115,99,97,108,101,61,50,48,10,100,101,102,105,110,101,32,101,40,120,41,123,
898   10,9,97,117,116,111,32,98,44,115,44,110,44,114,44,100,44,105,44,112,44,102,
899   44,118,10,9,98,61,105,98,97,115,101,10,9,105,98,97,115,101,61,65,10,9,105,102,
900   40,120,60,48,41,123,10,9,9,110,61,49,10,9,9,120,61,45,120,10,9,125,10,9,115,
901   61,115,99,97,108,101,10,9,114,61,54,43,115,43,48,46,52,52,42,120,10,9,115,99,
902   97,108,101,61,115,99,97,108,101,40,120,41,43,49,10,9,119,104,105,108,101,40,
903   120,62,49,41,123,10,9,9,100,43,61,49,10,9,9,120,47,61,50,10,9,9,115,99,97,108,
904   101,43,61,49,10,9,125,10,9,115,99,97,108,101,61,114,10,9,114,61,120,43,49,10,
905   9,112,61,120,10,9,102,61,118,61,49,10,9,102,111,114,40,105,61,50,59,118,33,
906   61,48,59,43,43,105,41,123,10,9,9,112,42,61,120,10,9,9,102,42,61,105,10,9,9,
907   118,61,112,47,102,10,9,9,114,43,61,118,10,9,125,10,9,119,104,105,108,101,40,
908   40,100,45,45,41,33,61,48,41,114,42,61,114,10,9,115,99,97,108,101,61,115,10,
909   9,105,98,97,115,101,61,98,10,9,105,102,40,110,33,61,48,41,114,101,116,117,114,
910   110,40,49,47,114,41,10,9,114,101,116,117,114,110,40,114,47,49,41,10,125,10,
911   100,101,102,105,110,101,32,108,40,120,41,123,10,9,97,117,116,111,32,98,44,115,
912   44,114,44,112,44,97,44,113,44,105,44,118,10,9,98,61,105,98,97,115,101,10,9,
913   105,98,97,115,101,61,65,10,9,105,102,40,120,60,61,48,41,123,10,9,9,114,61,40,
914   49,45,49,48,94,115,99,97,108,101,41,47,49,10,9,9,105,98,97,115,101,61,98,10,
915   9,9,114,101,116,117,114,110,40,114,41,10,9,125,10,9,115,61,115,99,97,108,101,
916   10,9,115,99,97,108,101,43,61,54,10,9,112,61,50,10,9,119,104,105,108,101,40,
917   120,62,61,50,41,123,10,9,9,112,42,61,50,10,9,9,120,61,115,113,114,116,40,120,
918   41,10,9,125,10,9,119,104,105,108,101,40,120,60,61,48,46,53,41,123,10,9,9,112,
919   42,61,50,10,9,9,120,61,115,113,114,116,40,120,41,10,9,125,10,9,114,61,97,61,
920   40,120,45,49,41,47,40,120,43,49,41,10,9,113,61,97,42,97,10,9,118,61,49,10,9,
921   102,111,114,40,105,61,51,59,118,33,61,48,59,105,43,61,50,41,123,10,9,9,97,42,
922   61,113,10,9,9,118,61,97,47,105,10,9,9,114,43,61,118,10,9,125,10,9,114,42,61,
923   112,10,9,115,99,97,108,101,61,115,10,9,105,98,97,115,101,61,98,10,9,114,101,
924   116,117,114,110,40,114,47,49,41,10,125,10,100,101,102,105,110,101,32,115,40,
925   120,41,123,10,9,97,117,116,111,32,98,44,115,44,114,44,110,44,97,44,113,44,105,
926   10,9,98,61,105,98,97,115,101,10,9,105,98,97,115,101,61,65,10,9,115,61,115,99,
927   97,108,101,10,9,115,99,97,108,101,61,49,46,49,42,115,43,50,10,9,97,61,97,40,
928   49,41,10,9,105,102,40,120,60,48,41,123,10,9,9,110,61,49,10,9,9,120,61,45,120,
929   10,9,125,10,9,115,99,97,108,101,61,48,10,9,113,61,40,120,47,97,43,50,41,47,
930   52,10,9,120,61,120,45,52,42,113,42,97,10,9,105,102,40,113,37,50,33,61,48,41,
931   120,61,45,120,10,9,115,99,97,108,101,61,115,43,50,10,9,114,61,97,61,120,10,
932   9,113,61,45,120,42,120,10,9,102,111,114,40,105,61,51,59,97,33,61,48,59,105,
933   43,61,50,41,123,10,9,9,97,42,61,113,47,40,105,42,40,105,45,49,41,41,10,9,9,
934   114,43,61,97,10,9,125,10,9,115,99,97,108,101,61,115,10,9,105,98,97,115,101,
935   61,98,10,9,105,102,40,110,33,61,48,41,114,101,116,117,114,110,40,45,114,47,
936   49,41,10,9,114,101,116,117,114,110,40,114,47,49,41,10,125,10,100,101,102,105,
937   110,101,32,99,40,120,41,123,10,9,97,117,116,111,32,98,44,115,10,9,98,61,105,
938   98,97,115,101,10,9,105,98,97,115,101,61,65,10,9,115,61,115,99,97,108,101,10,
939   9,115,99,97,108,101,42,61,49,46,50,10,9,120,61,115,40,50,42,97,40,49,41,43,
940   120,41,10,9,115,99,97,108,101,61,115,10,9,105,98,97,115,101,61,98,10,9,114,
941   101,116,117,114,110,40,120,47,49,41,10,125,10,100,101,102,105,110,101,32,97,
942   40,120,41,123,10,9,97,117,116,111,32,98,44,115,44,114,44,110,44,97,44,109,44,
943   116,44,102,44,105,44,117,10,9,98,61,105,98,97,115,101,10,9,105,98,97,115,101,
944   61,65,10,9,110,61,49,10,9,105,102,40,120,60,48,41,123,10,9,9,110,61,45,49,10,
945   9,9,120,61,45,120,10,9,125,10,9,105,102,40,120,61,61,49,41,123,10,9,9,105,102,
946   40,115,99,97,108,101,60,54,53,41,123,10,9,9,9,114,101,116,117,114,110,40,46,
947   55,56,53,51,57,56,49,54,51,51,57,55,52,52,56,51,48,57,54,49,53,54,54,48,56,
948   52,53,56,49,57,56,55,53,55,50,49,48,52,57,50,57,50,51,52,57,56,52,51,55,55,
949   54,52,53,53,50,52,51,55,51,54,49,52,56,48,47,110,41,10,9,9,125,10,9,125,10,
950   9,105,102,40,120,61,61,46,50,41,123,10,9,9,105,102,40,115,99,97,108,101,60,
951   54,53,41,123,10,9,9,9,114,101,116,117,114,110,40,46,49,57,55,51,57,53,53,53,
952   57,56,52,57,56,56,48,55,53,56,51,55,48,48,52,57,55,54,53,49,57,52,55,57,48,
953   50,57,51,52,52,55,53,56,53,49,48,51,55,56,55,56,53,50,49,48,49,53,49,55,54,
954   56,56,57,52,48,50,47,110,41,10,9,9,125,10,9,125,10,9,115,61,115,99,97,108,101,
955   10,9,105,102,40,120,62,46,50,41,123,10,9,9,115,99,97,108,101,43,61,53,10,9,
956   9,97,61,97,40,46,50,41,10,9,125,10,9,115,99,97,108,101,61,115,43,51,10,9,119,
957   104,105,108,101,40,120,62,46,50,41,123,10,9,9,109,43,61,49,10,9,9,120,61,40,
958   120,45,46,50,41,47,40,49,43,46,50,42,120,41,10,9,125,10,9,114,61,117,61,120,
959   10,9,102,61,45,120,42,120,10,9,116,61,49,10,9,102,111,114,40,105,61,51,59,116,
960   33,61,48,59,105,43,61,50,41,123,10,9,9,117,42,61,102,10,9,9,116,61,117,47,105,
961   10,9,9,114,43,61,116,10,9,125,10,9,115,99,97,108,101,61,115,10,9,105,98,97,
962   115,101,61,98,10,9,114,101,116,117,114,110,40,40,109,42,97,43,114,41,47,110,
963   41,10,125,10,100,101,102,105,110,101,32,106,40,110,44,120,41,123,10,9,97,117,
964   116,111,32,98,44,115,44,111,44,97,44,105,44,118,44,102,10,9,98,61,105,98,97,
965   115,101,10,9,105,98,97,115,101,61,65,10,9,115,61,115,99,97,108,101,10,9,115,
966   99,97,108,101,61,48,10,9,110,47,61,49,10,9,105,102,40,110,60,48,41,123,10,9,
967   9,110,61,45,110,10,9,9,105,102,40,110,37,50,61,61,49,41,111,61,49,10,9,125,
968   10,9,97,61,49,10,9,102,111,114,40,105,61,50,59,105,60,61,110,59,43,43,105,41,
969   97,42,61,105,10,9,115,99,97,108,101,61,49,46,53,42,115,10,9,97,61,40,120,94,
970   110,41,47,50,94,110,47,97,10,9,114,61,118,61,49,10,9,102,61,45,120,42,120,47,
971   52,10,9,115,99,97,108,101,61,115,99,97,108,101,43,108,101,110,103,116,104,40,
972   97,41,45,115,99,97,108,101,40,97,41,10,9,102,111,114,40,105,61,49,59,118,33,
973   61,48,59,43,43,105,41,123,10,9,9,118,61,118,42,102,47,105,47,40,110,43,105,
974   41,10,9,9,114,43,61,118,10,9,125,10,9,115,99,97,108,101,61,115,10,9,105,98,
975   97,115,101,61,98,10,9,105,102,40,111,33,61,48,41,97,61,45,97,10,9,114,101,116,
976   117,114,110,40,97,42,114,47,49,41,10,125,10,0
977 };
978 #endif // ENABLE_BC
979
980 static void fflush_and_check(void)
981 {
982         fflush_all();
983         if (ferror(stdout) || ferror(stderr))
984                 bb_perror_msg_and_die("output error");
985 }
986
987 static void quit(void) NORETURN;
988 static void quit(void)
989 {
990         if (ferror(stdin))
991                 bb_perror_msg_and_die("input error");
992         fflush_and_check();
993         exit(0);
994 }
995
996 static int bc_error(const char *fmt, ...)
997 {
998         va_list p;
999
1000         va_start(p, fmt);
1001         bb_verror_msg(fmt, p, NULL);
1002         va_end(p);
1003         if (!G.ttyin)
1004                 exit(1);
1005         return BC_STATUS_FAILURE;
1006 }
1007
1008 static int bc_posix_error(const char *fmt, ...)
1009 {
1010         va_list p;
1011
1012         if (!(option_mask32 & (BC_FLAG_S|BC_FLAG_W)))
1013                 return BC_STATUS_SUCCESS;
1014
1015         va_start(p, fmt);
1016         bb_verror_msg(fmt, p, NULL);
1017         va_end(p);
1018
1019         // Do we treat non-POSIX constructs as errors?
1020         if (!(option_mask32 & BC_FLAG_S))
1021                 return BC_STATUS_SUCCESS; // no, it's a warning
1022         if (!G.ttyin)
1023                 exit(1);
1024         return BC_STATUS_FAILURE;
1025 }
1026
1027 static void bc_vec_grow(BcVec *v, size_t n)
1028 {
1029         size_t cap = v->cap * 2;
1030         while (cap < v->len + n) cap *= 2;
1031         v->v = xrealloc(v->v, v->size * cap);
1032         v->cap = cap;
1033 }
1034
1035 static void bc_vec_init(BcVec *v, size_t esize, BcVecFree dtor)
1036 {
1037         v->size = esize;
1038         v->cap = BC_VEC_START_CAP;
1039         v->len = 0;
1040         v->dtor = dtor;
1041         v->v = xmalloc(esize * BC_VEC_START_CAP);
1042 }
1043
1044 static void bc_vec_expand(BcVec *v, size_t req)
1045 {
1046         if (v->cap < req) {
1047                 v->v = xrealloc(v->v, v->size * req);
1048                 v->cap = req;
1049         }
1050 }
1051
1052 static void bc_vec_npop(BcVec *v, size_t n)
1053 {
1054         if (!v->dtor)
1055                 v->len -= n;
1056         else {
1057                 size_t len = v->len - n;
1058                 while (v->len > len) v->dtor(v->v + (v->size * --v->len));
1059         }
1060 }
1061
1062 static void bc_vec_push(BcVec *v, const void *data)
1063 {
1064         if (v->len + 1 > v->cap) bc_vec_grow(v, 1);
1065         memmove(v->v + (v->size * v->len), data, v->size);
1066         v->len += 1;
1067 }
1068
1069 static void bc_vec_pushByte(BcVec *v, char data)
1070 {
1071         bc_vec_push(v, &data);
1072 }
1073
1074 static void bc_vec_pushAt(BcVec *v, const void *data, size_t idx)
1075 {
1076         if (idx == v->len)
1077                 bc_vec_push(v, data);
1078         else {
1079
1080                 char *ptr;
1081
1082                 if (v->len == v->cap) bc_vec_grow(v, 1);
1083
1084                 ptr = v->v + v->size * idx;
1085
1086                 memmove(ptr + v->size, ptr, v->size * (v->len++ - idx));
1087                 memmove(ptr, data, v->size);
1088         }
1089 }
1090
1091 static void bc_vec_string(BcVec *v, size_t len, const char *str)
1092 {
1093         bc_vec_npop(v, v->len);
1094         bc_vec_expand(v, len + 1);
1095         memcpy(v->v, str, len);
1096         v->len = len;
1097
1098         bc_vec_pushByte(v, '\0');
1099 }
1100
1101 static void bc_vec_concat(BcVec *v, const char *str)
1102 {
1103         size_t len;
1104
1105         if (v->len == 0) bc_vec_pushByte(v, '\0');
1106
1107         len = v->len + strlen(str);
1108
1109         if (v->cap < len) bc_vec_grow(v, len - v->len);
1110         strcat(v->v, str);
1111
1112         v->len = len;
1113 }
1114
1115 static void *bc_vec_item(const BcVec *v, size_t idx)
1116 {
1117         return v->v + v->size * idx;
1118 }
1119
1120 static void *bc_vec_item_rev(const BcVec *v, size_t idx)
1121 {
1122         return v->v + v->size * (v->len - idx - 1);
1123 }
1124
1125 static void bc_vec_free(void *vec)
1126 {
1127         BcVec *v = (BcVec *) vec;
1128         bc_vec_npop(v, v->len);
1129         free(v->v);
1130 }
1131
1132 static size_t bc_map_find(const BcVec *v, const void *ptr)
1133 {
1134         size_t low = 0, high = v->len;
1135
1136         while (low < high) {
1137
1138                 size_t mid = (low + high) / 2;
1139                 BcId *id = bc_vec_item(v, mid);
1140                 int result = bc_id_cmp(ptr, id);
1141
1142                 if (result == 0)
1143                         return mid;
1144                 else if (result < 0)
1145                         high = mid;
1146                 else
1147                         low = mid + 1;
1148         }
1149
1150         return low;
1151 }
1152
1153 static int bc_map_insert(BcVec *v, const void *ptr, size_t *i)
1154 {
1155         size_t n = *i = bc_map_find(v, ptr);
1156
1157         if (n == v->len)
1158                 bc_vec_push(v, ptr);
1159         else if (!bc_id_cmp(ptr, bc_vec_item(v, n)))
1160                 return 0; // "was not inserted"
1161         else
1162                 bc_vec_pushAt(v, ptr, n);
1163         return 1; // "was inserted"
1164 }
1165
1166 static size_t bc_map_index(const BcVec *v, const void *ptr)
1167 {
1168         size_t i = bc_map_find(v, ptr);
1169         if (i >= v->len) return BC_VEC_INVALID_IDX;
1170         return bc_id_cmp(ptr, bc_vec_item(v, i)) ? BC_VEC_INVALID_IDX : i;
1171 }
1172
1173 static BcStatus bc_read_line(BcVec *vec, const char *prompt)
1174 {
1175         bool bad_chars;
1176
1177         do {
1178                 int i;
1179                 char c;
1180
1181                 bad_chars = 0;
1182                 bc_vec_npop(vec, vec->len);
1183
1184                 fflush_and_check();
1185 #if ENABLE_FEATURE_BC_SIGNALS
1186                 if (bb_got_signal) { // ^C was pressed
1187  intr:
1188                         bb_got_signal = 0; // resets G_interrupt to zero
1189                         fputs(IS_BC
1190                                 ? "\ninterrupt (type \"quit\" to exit)\n"
1191                                 : "\ninterrupt (type \"q\" to exit)\n"
1192                                 , stderr);
1193                 }
1194 #endif
1195                 if (G.ttyin && !G_posix)
1196                         fputs(prompt, stderr);
1197
1198 #if ENABLE_FEATURE_BC_SIGNALS
1199                 errno = 0;
1200 #endif
1201                 do {
1202                         i = fgetc(stdin);
1203                         if (i == EOF) {
1204 #if ENABLE_FEATURE_BC_SIGNALS
1205                                 // Both conditions appear simultaneously, check both just in case
1206                                 if (errno == EINTR || bb_got_signal) {
1207                                         // ^C was pressed
1208                                         clearerr(stdin);
1209                                         goto intr;
1210                                 }
1211 #endif
1212                                 if (ferror(stdin))
1213                                         quit(); // this emits error message
1214                                 G.eof = 1;
1215                                 // Note: EOF does not append '\n', therefore:
1216                                 // printf 'print 123\n' | bc - works
1217                                 // printf 'print 123' | bc   - fails (syntax error)
1218                                 break;
1219                         }
1220
1221                         if ((i < ' ' && i != '\t' && i != '\r' && i != '\n') // also allow '\v' '\f'?
1222                          || i > 0x7e
1223                         ) {
1224                                 // Bad chars on this line, ignore entire line
1225                                 bc_error("illegal character 0x%02x", i);
1226                                 bad_chars = 1;
1227                         }
1228                         c = (char) i;
1229                         bc_vec_push(vec, &c);
1230                 } while (i != '\n');
1231         } while (bad_chars);
1232
1233         bc_vec_pushByte(vec, '\0');
1234
1235         return BC_STATUS_SUCCESS;
1236 }
1237
1238 static char* bc_read_file(const char *path)
1239 {
1240         char *buf;
1241         size_t size = ((size_t) -1);
1242         size_t i;
1243
1244         buf = xmalloc_open_read_close(path, &size);
1245
1246         for (i = 0; i < size; ++i) {
1247                 char c = buf[i];
1248                 if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'?
1249                  || c > 0x7e
1250                 ) {
1251                         free(buf);
1252                         buf = NULL;
1253                         break;
1254                 }
1255         }
1256
1257         return buf;
1258 }
1259
1260 static void bc_args(int argc, char **argv)
1261 {
1262         unsigned opts;
1263         int i;
1264
1265         GETOPT_RESET();
1266 #if ENABLE_FEATURE_BC_LONG_OPTIONS
1267         opts = getopt32long(argv, "xwvsqli",
1268                 "extended-register\0" No_argument "x"
1269                 "warn\0"              No_argument "w"
1270                 "version\0"           No_argument "v"
1271                 "standard\0"          No_argument "s"
1272                 "quiet\0"             No_argument "q"
1273                 "mathlib\0"           No_argument "l"
1274                 "interactive\0"       No_argument "i"
1275         );
1276 #else
1277         opts = getopt32(argv, "xwvsqli");
1278 #endif
1279         if (getenv("POSIXLY_CORRECT"))
1280                 option_mask32 |= BC_FLAG_S;
1281
1282         if (opts & BC_FLAG_V) bc_vm_info();
1283         // should not be necessary, getopt32() handles this??
1284         //if (argv[optind] && !strcmp(argv[optind], "--")) ++optind;
1285
1286         for (i = optind; i < argc; ++i)
1287                 bc_vec_push(&G.files, argv + i);
1288 }
1289
1290 static void bc_num_setToZero(BcNum *n, size_t scale)
1291 {
1292         n->len = 0;
1293         n->neg = false;
1294         n->rdx = scale;
1295 }
1296
1297 static void bc_num_zero(BcNum *n)
1298 {
1299         bc_num_setToZero(n, 0);
1300 }
1301
1302 static void bc_num_one(BcNum *n)
1303 {
1304         bc_num_setToZero(n, 0);
1305         n->len = 1;
1306         n->num[0] = 1;
1307 }
1308
1309 static void bc_num_ten(BcNum *n)
1310 {
1311         bc_num_setToZero(n, 0);
1312         n->len = 2;
1313         n->num[0] = 0;
1314         n->num[1] = 1;
1315 }
1316
1317 static void bc_num_subArrays(BcDig *restrict a, BcDig *restrict b,
1318                                  size_t len)
1319 {
1320         size_t i, j;
1321         for (i = 0; i < len; ++i) {
1322                 for (a[i] -= b[i], j = 0; a[i + j] < 0;) {
1323                         a[i + j++] += 10;
1324                         a[i + j] -= 1;
1325                 }
1326         }
1327 }
1328
1329 static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len)
1330 {
1331         size_t i;
1332         int c = 0;
1333         for (i = len - 1; i < len && !(c = a[i] - b[i]); --i);
1334         return BC_NUM_NEG(i + 1, c < 0);
1335 }
1336
1337 static ssize_t bc_num_cmp(BcNum *a, BcNum *b)
1338 {
1339         size_t i, min, a_int, b_int, diff;
1340         BcDig *max_num, *min_num;
1341         bool a_max, neg = false;
1342         ssize_t cmp;
1343
1344         if (a == b) return 0;
1345         if (a->len == 0) return BC_NUM_NEG(!!b->len, !b->neg);
1346         if (b->len == 0) return BC_NUM_NEG(1, a->neg);
1347         if (a->neg) {
1348                 if (b->neg)
1349                         neg = true;
1350                 else
1351                         return -1;
1352         }
1353         else if (b->neg)
1354                 return 1;
1355
1356         a_int = BC_NUM_INT(a);
1357         b_int = BC_NUM_INT(b);
1358         a_int -= b_int;
1359         a_max = (a->rdx > b->rdx);
1360
1361         if (a_int != 0) return (ssize_t) a_int;
1362
1363         if (a_max) {
1364                 min = b->rdx;
1365                 diff = a->rdx - b->rdx;
1366                 max_num = a->num + diff;
1367                 min_num = b->num;
1368         }
1369         else {
1370                 min = a->rdx;
1371                 diff = b->rdx - a->rdx;
1372                 max_num = b->num + diff;
1373                 min_num = a->num;
1374         }
1375
1376         cmp = bc_num_compare(max_num, min_num, b_int + min);
1377         if (cmp != 0) return BC_NUM_NEG(cmp, (!a_max) != neg);
1378
1379         for (max_num -= diff, i = diff - 1; i < diff; --i) {
1380                 if (max_num[i]) return BC_NUM_NEG(1, (!a_max) != neg);
1381         }
1382
1383         return 0;
1384 }
1385
1386 static void bc_num_truncate(BcNum *n, size_t places)
1387 {
1388         if (places == 0) return;
1389
1390         n->rdx -= places;
1391
1392         if (n->len != 0) {
1393                 n->len -= places;
1394                 memmove(n->num, n->num + places, n->len * sizeof(BcDig));
1395         }
1396 }
1397
1398 static void bc_num_extend(BcNum *n, size_t places)
1399 {
1400         size_t len = n->len + places;
1401
1402         if (places != 0) {
1403
1404                 if (n->cap < len) bc_num_expand(n, len);
1405
1406                 memmove(n->num + places, n->num, sizeof(BcDig) * n->len);
1407                 memset(n->num, 0, sizeof(BcDig) * places);
1408
1409                 n->len += places;
1410                 n->rdx += places;
1411         }
1412 }
1413
1414 static void bc_num_clean(BcNum *n)
1415 {
1416         while (n->len > 0 && n->num[n->len - 1] == 0) --n->len;
1417         if (n->len == 0)
1418                 n->neg = false;
1419         else if (n->len < n->rdx)
1420                 n->len = n->rdx;
1421 }
1422
1423 static void bc_num_retireMul(BcNum *n, size_t scale, bool neg1, bool neg2)
1424 {
1425         if (n->rdx < scale)
1426                 bc_num_extend(n, scale - n->rdx);
1427         else
1428                 bc_num_truncate(n, n->rdx - scale);
1429
1430         bc_num_clean(n);
1431         if (n->len != 0) n->neg = !neg1 != !neg2;
1432 }
1433
1434 static void bc_num_split(BcNum *restrict n, size_t idx, BcNum *restrict a,
1435                          BcNum *restrict b)
1436 {
1437         if (idx < n->len) {
1438
1439                 b->len = n->len - idx;
1440                 a->len = idx;
1441                 a->rdx = b->rdx = 0;
1442
1443                 memcpy(b->num, n->num + idx, b->len * sizeof(BcDig));
1444                 memcpy(a->num, n->num, idx * sizeof(BcDig));
1445         }
1446         else {
1447                 bc_num_zero(b);
1448                 bc_num_copy(a, n);
1449         }
1450
1451         bc_num_clean(a);
1452         bc_num_clean(b);
1453 }
1454
1455 static BcStatus bc_num_shift(BcNum *n, size_t places)
1456 {
1457         if (places == 0 || n->len == 0) return BC_STATUS_SUCCESS;
1458         if (places + n->len > BC_MAX_NUM)
1459                 return bc_error("number too long: must be [1, BC_NUM_MAX]");
1460
1461         if (n->rdx >= places)
1462                 n->rdx -= places;
1463         else {
1464                 bc_num_extend(n, places - n->rdx);
1465                 n->rdx = 0;
1466         }
1467
1468         bc_num_clean(n);
1469
1470         return BC_STATUS_SUCCESS;
1471 }
1472
1473 static BcStatus bc_num_inv(BcNum *a, BcNum *b, size_t scale)
1474 {
1475         BcNum one;
1476         BcDig num[2];
1477
1478         one.cap = 2;
1479         one.num = num;
1480         bc_num_one(&one);
1481
1482         return bc_num_div(&one, a, b, scale);
1483 }
1484
1485 static BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub)
1486 {
1487         BcDig *ptr, *ptr_a, *ptr_b, *ptr_c;
1488         size_t i, max, min_rdx, min_int, diff, a_int, b_int;
1489         int carry, in;
1490
1491         // Because this function doesn't need to use scale (per the bc spec),
1492         // I am hijacking it to say whether it's doing an add or a subtract.
1493
1494         if (a->len == 0) {
1495                 bc_num_copy(c, b);
1496                 if (sub && c->len) c->neg = !c->neg;
1497                 return BC_STATUS_SUCCESS;
1498         }
1499         else if (b->len == 0) {
1500                 bc_num_copy(c, a);
1501                 return BC_STATUS_SUCCESS;
1502         }
1503
1504         c->neg = a->neg;
1505         c->rdx = BC_MAX(a->rdx, b->rdx);
1506         min_rdx = BC_MIN(a->rdx, b->rdx);
1507         c->len = 0;
1508
1509         if (a->rdx > b->rdx) {
1510                 diff = a->rdx - b->rdx;
1511                 ptr = a->num;
1512                 ptr_a = a->num + diff;
1513                 ptr_b = b->num;
1514         }
1515         else {
1516                 diff = b->rdx - a->rdx;
1517                 ptr = b->num;
1518                 ptr_a = a->num;
1519                 ptr_b = b->num + diff;
1520         }
1521
1522         for (ptr_c = c->num, i = 0; i < diff; ++i, ++c->len) ptr_c[i] = ptr[i];
1523
1524         ptr_c += diff;
1525         a_int = BC_NUM_INT(a);
1526         b_int = BC_NUM_INT(b);
1527
1528         if (a_int > b_int) {
1529                 min_int = b_int;
1530                 max = a_int;
1531                 ptr = ptr_a;
1532         }
1533         else {
1534                 min_int = a_int;
1535                 max = b_int;
1536                 ptr = ptr_b;
1537         }
1538
1539         for (carry = 0, i = 0; i < min_rdx + min_int; ++i, ++c->len) {
1540                 in = ((int) ptr_a[i]) + ((int) ptr_b[i]) + carry;
1541                 carry = in / 10;
1542                 ptr_c[i] = (BcDig)(in % 10);
1543         }
1544
1545         for (; i < max + min_rdx; ++i, ++c->len) {
1546                 in = ((int) ptr[i]) + carry;
1547                 carry = in / 10;
1548                 ptr_c[i] = (BcDig)(in % 10);
1549         }
1550
1551         if (carry != 0) c->num[c->len++] = (BcDig) carry;
1552
1553         return BC_STATUS_SUCCESS; // can't make void, see bc_num_binary()
1554 }
1555
1556 static BcStatus bc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub)
1557 {
1558         ssize_t cmp;
1559         BcNum *minuend, *subtrahend;
1560         size_t start;
1561         bool aneg, bneg, neg;
1562
1563         // Because this function doesn't need to use scale (per the bc spec),
1564         // I am hijacking it to say whether it's doing an add or a subtract.
1565
1566         if (a->len == 0) {
1567                 bc_num_copy(c, b);
1568                 if (sub && c->len) c->neg = !c->neg;
1569                 return BC_STATUS_SUCCESS;
1570         }
1571         else if (b->len == 0) {
1572                 bc_num_copy(c, a);
1573                 return BC_STATUS_SUCCESS;
1574         }
1575
1576         aneg = a->neg;
1577         bneg = b->neg;
1578         a->neg = b->neg = false;
1579
1580         cmp = bc_num_cmp(a, b);
1581
1582         a->neg = aneg;
1583         b->neg = bneg;
1584
1585         if (cmp == 0) {
1586                 bc_num_setToZero(c, BC_MAX(a->rdx, b->rdx));
1587                 return BC_STATUS_SUCCESS;
1588         }
1589         else if (cmp > 0) {
1590                 neg = a->neg;
1591                 minuend = a;
1592                 subtrahend = b;
1593         }
1594         else {
1595                 neg = b->neg;
1596                 if (sub) neg = !neg;
1597                 minuend = b;
1598                 subtrahend = a;
1599         }
1600
1601         bc_num_copy(c, minuend);
1602         c->neg = neg;
1603
1604         if (c->rdx < subtrahend->rdx) {
1605                 bc_num_extend(c, subtrahend->rdx - c->rdx);
1606                 start = 0;
1607         }
1608         else
1609                 start = c->rdx - subtrahend->rdx;
1610
1611         bc_num_subArrays(c->num + start, subtrahend->num, subtrahend->len);
1612
1613         bc_num_clean(c);
1614
1615         return BC_STATUS_SUCCESS; // can't make void, see bc_num_binary()
1616 }
1617
1618 static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b,
1619                          BcNum *restrict c)
1620 {
1621         BcStatus s;
1622         int carry;
1623         size_t i, j, len, max = BC_MAX(a->len, b->len), max2 = (max + 1) / 2;
1624         BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp;
1625         bool aone = BC_NUM_ONE(a);
1626
1627         if (a->len == 0 || b->len == 0) {
1628                 bc_num_zero(c);
1629                 return BC_STATUS_SUCCESS;
1630         }
1631         else if (aone || BC_NUM_ONE(b)) {
1632                 bc_num_copy(c, aone ? b : a);
1633                 return BC_STATUS_SUCCESS;
1634         }
1635
1636         if (a->len + b->len < BC_NUM_KARATSUBA_LEN ||
1637             a->len < BC_NUM_KARATSUBA_LEN || b->len < BC_NUM_KARATSUBA_LEN)
1638         {
1639                 bc_num_expand(c, a->len + b->len + 1);
1640
1641                 memset(c->num, 0, sizeof(BcDig) * c->cap);
1642                 c->len = carry = len = 0;
1643
1644                 for (i = 0; i < b->len; ++i) {
1645
1646                         for (j = 0; j < a->len; ++j) {
1647                                 int in = (int) c->num[i + j];
1648                                 in += ((int) a->num[j]) * ((int) b->num[i]) + carry;
1649                                 carry = in / 10;
1650                                 c->num[i + j] = (BcDig)(in % 10);
1651                         }
1652
1653                         c->num[i + j] += (BcDig) carry;
1654                         len = BC_MAX(len, i + j + !!carry);
1655                         carry = 0;
1656                 }
1657
1658                 c->len = len;
1659
1660                 return BC_STATUS_SUCCESS;
1661         }
1662
1663         bc_num_init(&l1, max);
1664         bc_num_init(&h1, max);
1665         bc_num_init(&l2, max);
1666         bc_num_init(&h2, max);
1667         bc_num_init(&m1, max);
1668         bc_num_init(&m2, max);
1669         bc_num_init(&z0, max);
1670         bc_num_init(&z1, max);
1671         bc_num_init(&z2, max);
1672         bc_num_init(&temp, max + max);
1673
1674         bc_num_split(a, max2, &l1, &h1);
1675         bc_num_split(b, max2, &l2, &h2);
1676
1677         s = bc_num_add(&h1, &l1, &m1, 0);
1678         if (s) goto err;
1679         s = bc_num_add(&h2, &l2, &m2, 0);
1680         if (s) goto err;
1681
1682         s = bc_num_k(&h1, &h2, &z0);
1683         if (s) goto err;
1684         s = bc_num_k(&m1, &m2, &z1);
1685         if (s) goto err;
1686         s = bc_num_k(&l1, &l2, &z2);
1687         if (s) goto err;
1688
1689         s = bc_num_sub(&z1, &z0, &temp, 0);
1690         if (s) goto err;
1691         s = bc_num_sub(&temp, &z2, &z1, 0);
1692         if (s) goto err;
1693
1694         s = bc_num_shift(&z0, max2 * 2);
1695         if (s) goto err;
1696         s = bc_num_shift(&z1, max2);
1697         if (s) goto err;
1698         s = bc_num_add(&z0, &z1, &temp, 0);
1699         if (s) goto err;
1700         s = bc_num_add(&temp, &z2, c, 0);
1701
1702 err:
1703         bc_num_free(&temp);
1704         bc_num_free(&z2);
1705         bc_num_free(&z1);
1706         bc_num_free(&z0);
1707         bc_num_free(&m2);
1708         bc_num_free(&m1);
1709         bc_num_free(&h2);
1710         bc_num_free(&l2);
1711         bc_num_free(&h1);
1712         bc_num_free(&l1);
1713         return s;
1714 }
1715
1716 static BcStatus bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
1717 {
1718         BcStatus s;
1719         BcNum cpa, cpb;
1720         size_t maxrdx = BC_MAX(a->rdx, b->rdx);
1721
1722         scale = BC_MAX(scale, a->rdx);
1723         scale = BC_MAX(scale, b->rdx);
1724         scale = BC_MIN(a->rdx + b->rdx, scale);
1725         maxrdx = BC_MAX(maxrdx, scale);
1726
1727         bc_num_init(&cpa, a->len);
1728         bc_num_init(&cpb, b->len);
1729
1730         bc_num_copy(&cpa, a);
1731         bc_num_copy(&cpb, b);
1732         cpa.neg = cpb.neg = false;
1733
1734         s = bc_num_shift(&cpa, maxrdx);
1735         if (s) goto err;
1736         s = bc_num_shift(&cpb, maxrdx);
1737         if (s) goto err;
1738         s = bc_num_k(&cpa, &cpb, c);
1739         if (s) goto err;
1740
1741         maxrdx += scale;
1742         bc_num_expand(c, c->len + maxrdx);
1743
1744         if (c->len < maxrdx) {
1745                 memset(c->num + c->len, 0, (c->cap - c->len) * sizeof(BcDig));
1746                 c->len += maxrdx;
1747         }
1748
1749         c->rdx = maxrdx;
1750         bc_num_retireMul(c, scale, a->neg, b->neg);
1751
1752 err:
1753         bc_num_free(&cpb);
1754         bc_num_free(&cpa);
1755         return s;
1756 }
1757
1758 static BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
1759 {
1760         BcStatus s = BC_STATUS_SUCCESS;
1761         BcDig *n, *p, q;
1762         size_t len, end, i;
1763         BcNum cp;
1764         bool zero = true;
1765
1766         if (b->len == 0)
1767                 return bc_error("divide by zero");
1768         else if (a->len == 0) {
1769                 bc_num_setToZero(c, scale);
1770                 return BC_STATUS_SUCCESS;
1771         }
1772         else if (BC_NUM_ONE(b)) {
1773                 bc_num_copy(c, a);
1774                 bc_num_retireMul(c, scale, a->neg, b->neg);
1775                 return BC_STATUS_SUCCESS;
1776         }
1777
1778         bc_num_init(&cp, BC_NUM_MREQ(a, b, scale));
1779         bc_num_copy(&cp, a);
1780         len = b->len;
1781
1782         if (len > cp.len) {
1783                 bc_num_expand(&cp, len + 2);
1784                 bc_num_extend(&cp, len - cp.len);
1785         }
1786
1787         if (b->rdx > cp.rdx) bc_num_extend(&cp, b->rdx - cp.rdx);
1788         cp.rdx -= b->rdx;
1789         if (scale > cp.rdx) bc_num_extend(&cp, scale - cp.rdx);
1790
1791         if (b->rdx == b->len) {
1792                 for (i = 0; zero && i < len; ++i) zero = !b->num[len - i - 1];
1793                 len -= i - 1;
1794         }
1795
1796         if (cp.cap == cp.len) bc_num_expand(&cp, cp.len + 1);
1797
1798         // We want an extra zero in front to make things simpler.
1799         cp.num[cp.len++] = 0;
1800         end = cp.len - len;
1801
1802         bc_num_expand(c, cp.len);
1803
1804         bc_num_zero(c);
1805         memset(c->num + end, 0, (c->cap - end) * sizeof(BcDig));
1806         c->rdx = cp.rdx;
1807         c->len = cp.len;
1808         p = b->num;
1809
1810         for (i = end - 1; !s && i < end; --i) {
1811                 n = cp.num + i;
1812                 for (q = 0; (!s && n[len] != 0) || bc_num_compare(n, p, len) >= 0; ++q)
1813                         bc_num_subArrays(n, p, len);
1814                 c->num[i] = q;
1815         }
1816
1817         bc_num_retireMul(c, scale, a->neg, b->neg);
1818         bc_num_free(&cp);
1819
1820         return BC_STATUS_SUCCESS; // can't make void, see bc_num_binary()
1821 }
1822
1823 static BcStatus bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c,
1824                          BcNum *restrict d, size_t scale, size_t ts)
1825 {
1826         BcStatus s;
1827         BcNum temp;
1828         bool neg;
1829
1830         if (b->len == 0)
1831                 return bc_error("divide by zero");
1832
1833         if (a->len == 0) {
1834                 bc_num_setToZero(d, ts);
1835                 return BC_STATUS_SUCCESS;
1836         }
1837
1838         bc_num_init(&temp, d->cap);
1839         bc_num_d(a, b, c, scale);
1840
1841         if (scale != 0) scale = ts;
1842
1843         s = bc_num_m(c, b, &temp, scale);
1844         if (s) goto err;
1845         s = bc_num_sub(a, &temp, d, scale);
1846         if (s) goto err;
1847
1848         if (ts > d->rdx && d->len) bc_num_extend(d, ts - d->rdx);
1849
1850         neg = d->neg;
1851         bc_num_retireMul(d, ts, a->neg, b->neg);
1852         d->neg = neg;
1853
1854 err:
1855         bc_num_free(&temp);
1856         return s;
1857 }
1858
1859 static BcStatus bc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
1860 {
1861         BcStatus s;
1862         BcNum c1;
1863         size_t ts = BC_MAX(scale + b->rdx, a->rdx), len = BC_NUM_MREQ(a, b, ts);
1864
1865         bc_num_init(&c1, len);
1866         s = bc_num_r(a, b, &c1, c, scale, ts);
1867         bc_num_free(&c1);
1868
1869         return s;
1870 }
1871
1872 static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
1873 {
1874         BcStatus s = BC_STATUS_SUCCESS;
1875         BcNum copy;
1876         unsigned long pow;
1877         size_t i, powrdx, resrdx;
1878         bool neg, zero;
1879
1880         if (b->rdx) return bc_error("non integer number");
1881
1882         if (b->len == 0) {
1883                 bc_num_one(c);
1884                 return BC_STATUS_SUCCESS;
1885         }
1886         else if (a->len == 0) {
1887                 bc_num_setToZero(c, scale);
1888                 return BC_STATUS_SUCCESS;
1889         }
1890         else if (BC_NUM_ONE(b)) {
1891                 if (!b->neg)
1892                         bc_num_copy(c, a);
1893                 else
1894                         s = bc_num_inv(a, c, scale);
1895                 return s;
1896         }
1897
1898         neg = b->neg;
1899         b->neg = false;
1900
1901         s = bc_num_ulong(b, &pow);
1902         if (s) return s;
1903
1904         bc_num_init(&copy, a->len);
1905         bc_num_copy(&copy, a);
1906
1907         if (!neg) scale = BC_MIN(a->rdx * pow, BC_MAX(scale, a->rdx));
1908
1909         b->neg = neg;
1910
1911         for (powrdx = a->rdx; !(pow & 1); pow >>= 1) {
1912                 powrdx <<= 1;
1913                 s = bc_num_mul(&copy, &copy, &copy, powrdx);
1914                 if (s) goto err;
1915         }
1916
1917         bc_num_copy(c, &copy);
1918
1919         for (resrdx = powrdx, pow >>= 1; pow != 0; pow >>= 1) {
1920
1921                 powrdx <<= 1;
1922                 s = bc_num_mul(&copy, &copy, &copy, powrdx);
1923                 if (s) goto err;
1924
1925                 if (pow & 1) {
1926                         resrdx += powrdx;
1927                         s = bc_num_mul(c, &copy, c, resrdx);
1928                         if (s) goto err;
1929                 }
1930         }
1931
1932         if (neg) {
1933                 s = bc_num_inv(c, c, scale);
1934                 if (s) goto err;
1935         }
1936
1937         if (c->rdx > scale) bc_num_truncate(c, c->rdx - scale);
1938
1939         // We can't use bc_num_clean() here.
1940         for (zero = true, i = 0; zero && i < c->len; ++i) zero = !c->num[i];
1941         if (zero) bc_num_setToZero(c, scale);
1942
1943 err:
1944         bc_num_free(&copy);
1945         return s;
1946 }
1947
1948 static BcStatus bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
1949                               BcNumBinaryOp op, size_t req)
1950 {
1951         BcStatus s;
1952         BcNum num2, *ptr_a, *ptr_b;
1953         bool init = false;
1954
1955         if (c == a) {
1956                 ptr_a = &num2;
1957                 memcpy(ptr_a, c, sizeof(BcNum));
1958                 init = true;
1959         }
1960         else
1961                 ptr_a = a;
1962
1963         if (c == b) {
1964                 ptr_b = &num2;
1965                 if (c != a) {
1966                         memcpy(ptr_b, c, sizeof(BcNum));
1967                         init = true;
1968                 }
1969         }
1970         else
1971                 ptr_b = b;
1972
1973         if (init)
1974                 bc_num_init(c, req);
1975         else
1976                 bc_num_expand(c, req);
1977
1978         s = op(ptr_a, ptr_b, c, scale);
1979
1980         if (init) bc_num_free(&num2);
1981
1982         return s;
1983 }
1984
1985 static bool bc_num_strValid(const char *val, size_t base)
1986 {
1987         BcDig b;
1988         bool small, radix = false;
1989         size_t i, len = strlen(val);
1990
1991         if (!len) return true;
1992
1993         small = base <= 10;
1994         b = (BcDig)(small ? base + '0' : base - 10 + 'A');
1995
1996         for (i = 0; i < len; ++i) {
1997
1998                 BcDig c = val[i];
1999
2000                 if (c == '.') {
2001
2002                         if (radix) return false;
2003
2004                         radix = true;
2005                         continue;
2006                 }
2007
2008                 if (c < '0' || (small && c >= b) || (c > '9' && (c < 'A' || c >= b)))
2009                         return false;
2010         }
2011
2012         return true;
2013 }
2014
2015 static void bc_num_parseDecimal(BcNum *n, const char *val)
2016 {
2017         size_t len, i;
2018         const char *ptr;
2019         bool zero = true;
2020
2021         for (i = 0; val[i] == '0'; ++i);
2022
2023         val += i;
2024         len = strlen(val);
2025         bc_num_zero(n);
2026
2027         if (len != 0) {
2028                 for (i = 0; zero && i < len; ++i) zero = val[i] == '0' || val[i] == '.';
2029                 bc_num_expand(n, len);
2030         }
2031
2032         ptr = strchr(val, '.');
2033
2034         n->rdx = 0;
2035         if (ptr != NULL)
2036                 n->rdx = (size_t)((val + len) - (ptr + 1));
2037
2038         if (!zero) {
2039                 for (i = len - 1; i < len; ++n->len, i -= 1 + (i && val[i - 1] == '.'))
2040                         n->num[n->len] = val[i] - '0';
2041         }
2042 }
2043
2044 static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base)
2045 {
2046         BcStatus s;
2047         BcNum temp, mult, result;
2048         BcDig c = '\0';
2049         bool zero = true;
2050         unsigned long v;
2051         size_t i, digits, len = strlen(val);
2052
2053         bc_num_zero(n);
2054
2055         for (i = 0; zero && i < len; ++i) zero = (val[i] == '.' || val[i] == '0');
2056         if (zero) return;
2057
2058         bc_num_init(&temp, BC_NUM_DEF_SIZE);
2059         bc_num_init(&mult, BC_NUM_DEF_SIZE);
2060
2061         for (i = 0; i < len; ++i) {
2062
2063                 c = val[i];
2064                 if (c == '.') break;
2065
2066                 v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10);
2067
2068                 s = bc_num_mul(n, base, &mult, 0);
2069                 if (s) goto int_err;
2070                 bc_num_ulong2num(&temp, v);
2071                 s = bc_num_add(&mult, &temp, n, 0);
2072                 if (s) goto int_err;
2073         }
2074
2075         if (i == len) {
2076                 c = val[i];
2077                 if (c == 0) goto int_err;
2078         }
2079
2080         bc_num_init(&result, base->len);
2081         bc_num_zero(&result);
2082         bc_num_one(&mult);
2083
2084         for (i += 1, digits = 0; i < len; ++i, ++digits) {
2085
2086                 c = val[i];
2087                 if (c == 0) break;
2088
2089                 v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10);
2090
2091                 s = bc_num_mul(&result, base, &result, 0);
2092                 if (s) goto err;
2093                 bc_num_ulong2num(&temp, v);
2094                 s = bc_num_add(&result, &temp, &result, 0);
2095                 if (s) goto err;
2096                 s = bc_num_mul(&mult, base, &mult, 0);
2097                 if (s) goto err;
2098         }
2099
2100         s = bc_num_div(&result, &mult, &result, digits);
2101         if (s) goto err;
2102         s = bc_num_add(n, &result, n, digits);
2103         if (s) goto err;
2104
2105         if (n->len != 0) {
2106                 if (n->rdx < digits) bc_num_extend(n, digits - n->rdx);
2107         }
2108         else
2109                 bc_num_zero(n);
2110
2111 err:
2112         bc_num_free(&result);
2113 int_err:
2114         bc_num_free(&mult);
2115         bc_num_free(&temp);
2116 }
2117
2118 static void bc_num_printNewline(size_t *nchars, size_t line_len)
2119 {
2120         if (*nchars == line_len - 1) {
2121                 bb_putchar('\\');
2122                 bb_putchar('\n');
2123                 *nchars = 0;
2124         }
2125 }
2126
2127 #if ENABLE_DC
2128 static void bc_num_printChar(size_t num, size_t width, bool radix,
2129                              size_t *nchars, size_t line_len)
2130 {
2131         (void) radix, (void) line_len;
2132         bb_putchar((char) num);
2133         *nchars = *nchars + width;
2134 }
2135 #endif
2136
2137 static void bc_num_printDigits(size_t num, size_t width, bool radix,
2138                                size_t *nchars, size_t line_len)
2139 {
2140         size_t exp, pow;
2141
2142         bc_num_printNewline(nchars, line_len);
2143         bb_putchar(radix ? '.' : ' ');
2144         ++(*nchars);
2145
2146         bc_num_printNewline(nchars, line_len);
2147         for (exp = 0, pow = 1; exp < width - 1; ++exp, pow *= 10)
2148                 continue;
2149
2150         for (exp = 0; exp < width; pow /= 10, ++(*nchars), ++exp) {
2151                 size_t dig;
2152                 bc_num_printNewline(nchars, line_len);
2153                 dig = num / pow;
2154                 num -= dig * pow;
2155                 bb_putchar(((char) dig) + '0');
2156         }
2157 }
2158
2159 static void bc_num_printHex(size_t num, size_t width, bool radix,
2160                             size_t *nchars, size_t line_len)
2161 {
2162         if (radix) {
2163                 bc_num_printNewline(nchars, line_len);
2164                 bb_putchar('.');
2165                 *nchars += 1;
2166         }
2167
2168         bc_num_printNewline(nchars, line_len);
2169         bb_putchar(bb_hexdigits_upcase[num]);
2170         *nchars = *nchars + width;
2171 }
2172
2173 static void bc_num_printDecimal(BcNum *n, size_t *nchars, size_t len)
2174 {
2175         size_t i, rdx = n->rdx - 1;
2176
2177         if (n->neg) bb_putchar('-');
2178         (*nchars) += n->neg;
2179
2180         for (i = n->len - 1; i < n->len; --i)
2181                 bc_num_printHex((size_t) n->num[i], 1, i == rdx, nchars, len);
2182 }
2183
2184 static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width,
2185                                 size_t *nchars, size_t len, BcNumDigitOp print)
2186 {
2187         BcStatus s;
2188         BcVec stack;
2189         BcNum intp, fracp, digit, frac_len;
2190         unsigned long dig, *ptr;
2191         size_t i;
2192         bool radix;
2193
2194         if (n->len == 0) {
2195                 print(0, width, false, nchars, len);
2196                 return BC_STATUS_SUCCESS;
2197         }
2198
2199         bc_vec_init(&stack, sizeof(long), NULL);
2200         bc_num_init(&intp, n->len);
2201         bc_num_init(&fracp, n->rdx);
2202         bc_num_init(&digit, width);
2203         bc_num_init(&frac_len, BC_NUM_INT(n));
2204         bc_num_copy(&intp, n);
2205         bc_num_one(&frac_len);
2206
2207         bc_num_truncate(&intp, intp.rdx);
2208         s = bc_num_sub(n, &intp, &fracp, 0);
2209         if (s) goto err;
2210
2211         while (intp.len != 0) {
2212                 s = bc_num_divmod(&intp, base, &intp, &digit, 0);
2213                 if (s) goto err;
2214                 s = bc_num_ulong(&digit, &dig);
2215                 if (s) goto err;
2216                 bc_vec_push(&stack, &dig);
2217         }
2218
2219         for (i = 0; i < stack.len; ++i) {
2220                 ptr = bc_vec_item_rev(&stack, i);
2221                 print(*ptr, width, false, nchars, len);
2222         }
2223
2224         if (!n->rdx) goto err;
2225
2226         for (radix = true; frac_len.len <= n->rdx; radix = false) {
2227                 s = bc_num_mul(&fracp, base, &fracp, n->rdx);
2228                 if (s) goto err;
2229                 s = bc_num_ulong(&fracp, &dig);
2230                 if (s) goto err;
2231                 bc_num_ulong2num(&intp, dig);
2232                 s = bc_num_sub(&fracp, &intp, &fracp, 0);
2233                 if (s) goto err;
2234                 print(dig, width, radix, nchars, len);
2235                 s = bc_num_mul(&frac_len, base, &frac_len, 0);
2236                 if (s) goto err;
2237         }
2238
2239 err:
2240         bc_num_free(&frac_len);
2241         bc_num_free(&digit);
2242         bc_num_free(&fracp);
2243         bc_num_free(&intp);
2244         bc_vec_free(&stack);
2245         return s;
2246 }
2247
2248 static BcStatus bc_num_printBase(BcNum *n, BcNum *base, size_t base_t,
2249                                  size_t *nchars, size_t line_len)
2250 {
2251         BcStatus s;
2252         size_t width, i;
2253         BcNumDigitOp print;
2254         bool neg = n->neg;
2255
2256         if (neg) bb_putchar('-');
2257         (*nchars) += neg;
2258
2259         n->neg = false;
2260
2261         if (base_t <= BC_NUM_MAX_IBASE) {
2262                 width = 1;
2263                 print = bc_num_printHex;
2264         }
2265         else {
2266                 for (i = base_t - 1, width = 0; i != 0; i /= 10, ++width);
2267                 print = bc_num_printDigits;
2268         }
2269
2270         s = bc_num_printNum(n, base, width, nchars, line_len, print);
2271         n->neg = neg;
2272
2273         return s;
2274 }
2275
2276 #if ENABLE_DC
2277 static BcStatus bc_num_stream(BcNum *n, BcNum *base, size_t *nchars, size_t len)
2278 {
2279         return bc_num_printNum(n, base, 1, nchars, len, bc_num_printChar);
2280 }
2281 #endif
2282
2283 static void bc_num_init(BcNum *n, size_t req)
2284 {
2285         req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
2286         memset(n, 0, sizeof(BcNum));
2287         n->num = xmalloc(req);
2288         n->cap = req;
2289 }
2290
2291 static void bc_num_expand(BcNum *n, size_t req)
2292 {
2293         req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
2294         if (req > n->cap) {
2295                 n->num = xrealloc(n->num, req);
2296                 n->cap = req;
2297         }
2298 }
2299
2300 static void bc_num_free(void *num)
2301 {
2302         free(((BcNum *) num)->num);
2303 }
2304
2305 static void bc_num_copy(BcNum *d, BcNum *s)
2306 {
2307         if (d != s) {
2308                 bc_num_expand(d, s->cap);
2309                 d->len = s->len;
2310                 d->neg = s->neg;
2311                 d->rdx = s->rdx;
2312                 memcpy(d->num, s->num, sizeof(BcDig) * d->len);
2313         }
2314 }
2315
2316 static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base,
2317                              size_t base_t)
2318 {
2319         if (!bc_num_strValid(val, base_t))
2320                 return bc_error("bad number string");
2321
2322         if (base_t == 10)
2323                 bc_num_parseDecimal(n, val);
2324         else
2325                 bc_num_parseBase(n, val, base);
2326
2327         return BC_STATUS_SUCCESS;
2328 }
2329
2330 static BcStatus bc_num_print(BcNum *n, BcNum *base, size_t base_t, bool newline,
2331                              size_t *nchars, size_t line_len)
2332 {
2333         BcStatus s = BC_STATUS_SUCCESS;
2334
2335         bc_num_printNewline(nchars, line_len);
2336
2337         if (n->len == 0) {
2338                 bb_putchar('0');
2339                 ++(*nchars);
2340         }
2341         else if (base_t == 10)
2342                 bc_num_printDecimal(n, nchars, line_len);
2343         else
2344                 s = bc_num_printBase(n, base, base_t, nchars, line_len);
2345
2346         if (newline) {
2347                 bb_putchar('\n');
2348                 *nchars = 0;
2349         }
2350
2351         return s;
2352 }
2353
2354 static BcStatus bc_num_ulong(BcNum *n, unsigned long *result)
2355 {
2356         size_t i;
2357         unsigned long pow;
2358
2359         if (n->neg) return bc_error("negative number");
2360
2361         for (*result = 0, pow = 1, i = n->rdx; i < n->len; ++i) {
2362
2363                 unsigned long prev = *result, powprev = pow;
2364
2365                 *result += ((unsigned long) n->num[i]) * pow;
2366                 pow *= 10;
2367
2368                 if (*result < prev || pow < powprev)
2369                         return bc_error("overflow");
2370         }
2371
2372         return BC_STATUS_SUCCESS;
2373 }
2374
2375 static void bc_num_ulong2num(BcNum *n, unsigned long val)
2376 {
2377         size_t len;
2378         BcDig *ptr;
2379         unsigned long i;
2380
2381         bc_num_zero(n);
2382
2383         if (val == 0) return;
2384
2385         for (len = 1, i = ULONG_MAX; i != 0; i /= 10, ++len) bc_num_expand(n, len);
2386         for (ptr = n->num, i = 0; val; ++i, ++n->len, val /= 10) ptr[i] = val % 10;
2387 }
2388
2389 static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2390 {
2391         BcNumBinaryOp op = (!a->neg == !b->neg) ? bc_num_a : bc_num_s;
2392         (void) scale;
2393         return bc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b));
2394 }
2395
2396 static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2397 {
2398         BcNumBinaryOp op = (!a->neg == !b->neg) ? bc_num_s : bc_num_a;
2399         (void) scale;
2400         return bc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b));
2401 }
2402
2403 static BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2404 {
2405         size_t req = BC_NUM_MREQ(a, b, scale);
2406         return bc_num_binary(a, b, c, scale, bc_num_m, req);
2407 }
2408
2409 static BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2410 {
2411         size_t req = BC_NUM_MREQ(a, b, scale);
2412         return bc_num_binary(a, b, c, scale, bc_num_d, req);
2413 }
2414
2415 static BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2416 {
2417         size_t req = BC_NUM_MREQ(a, b, scale);
2418         return bc_num_binary(a, b, c, scale, bc_num_rem, req);
2419 }
2420
2421 static BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2422 {
2423         return bc_num_binary(a, b, c, scale, bc_num_p, a->len * b->len + 1);
2424 }
2425
2426 static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale)
2427 {
2428         BcStatus s;
2429         BcNum num1, num2, half, f, fprime, *x0, *x1, *temp;
2430         size_t pow, len, digs, digs1, resrdx, req, times = 0;
2431         ssize_t cmp = 1, cmp1 = SSIZE_MAX, cmp2 = SSIZE_MAX;
2432
2433         req = BC_MAX(scale, a->rdx) + ((BC_NUM_INT(a) + 1) >> 1) + 1;
2434         bc_num_expand(b, req);
2435
2436         if (a->len == 0) {
2437                 bc_num_setToZero(b, scale);
2438                 return BC_STATUS_SUCCESS;
2439         }
2440         else if (a->neg)
2441                 return bc_error("negative number");
2442         else if (BC_NUM_ONE(a)) {
2443                 bc_num_one(b);
2444                 bc_num_extend(b, scale);
2445                 return BC_STATUS_SUCCESS;
2446         }
2447
2448         scale = BC_MAX(scale, a->rdx) + 1;
2449         len = a->len + scale;
2450
2451         bc_num_init(&num1, len);
2452         bc_num_init(&num2, len);
2453         bc_num_init(&half, BC_NUM_DEF_SIZE);
2454
2455         bc_num_one(&half);
2456         half.num[0] = 5;
2457         half.rdx = 1;
2458
2459         bc_num_init(&f, len);
2460         bc_num_init(&fprime, len);
2461
2462         x0 = &num1;
2463         x1 = &num2;
2464
2465         bc_num_one(x0);
2466         pow = BC_NUM_INT(a);
2467
2468         if (pow) {
2469
2470                 if (pow & 1)
2471                         x0->num[0] = 2;
2472                 else
2473                         x0->num[0] = 6;
2474
2475                 pow -= 2 - (pow & 1);
2476
2477                 bc_num_extend(x0, pow);
2478
2479                 // Make sure to move the radix back.
2480                 x0->rdx -= pow;
2481         }
2482
2483         x0->rdx = digs = digs1 = 0;
2484         resrdx = scale + 2;
2485         len = BC_NUM_INT(x0) + resrdx - 1;
2486
2487         while (cmp != 0 || digs < len) {
2488
2489                 s = bc_num_div(a, x0, &f, resrdx);
2490                 if (s) goto err;
2491                 s = bc_num_add(x0, &f, &fprime, resrdx);
2492                 if (s) goto err;
2493                 s = bc_num_mul(&fprime, &half, x1, resrdx);
2494                 if (s) goto err;
2495
2496                 cmp = bc_num_cmp(x1, x0);
2497                 digs = x1->len - (unsigned long long) llabs(cmp);
2498
2499                 if (cmp == cmp2 && digs == digs1)
2500                         times += 1;
2501                 else
2502                         times = 0;
2503
2504                 resrdx += times > 4;
2505
2506                 cmp2 = cmp1;
2507                 cmp1 = cmp;
2508                 digs1 = digs;
2509
2510                 temp = x0;
2511                 x0 = x1;
2512                 x1 = temp;
2513         }
2514
2515         bc_num_copy(b, x0);
2516         scale -= 1;
2517         if (b->rdx > scale) bc_num_truncate(b, b->rdx - scale);
2518
2519 err:
2520         bc_num_free(&fprime);
2521         bc_num_free(&f);
2522         bc_num_free(&half);
2523         bc_num_free(&num2);
2524         bc_num_free(&num1);
2525         return s;
2526 }
2527
2528 static BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d,
2529                               size_t scale)
2530 {
2531         BcStatus s;
2532         BcNum num2, *ptr_a;
2533         bool init = false;
2534         size_t ts = BC_MAX(scale + b->rdx, a->rdx), len = BC_NUM_MREQ(a, b, ts);
2535
2536         if (c == a) {
2537                 memcpy(&num2, c, sizeof(BcNum));
2538                 ptr_a = &num2;
2539                 bc_num_init(c, len);
2540                 init = true;
2541         }
2542         else {
2543                 ptr_a = a;
2544                 bc_num_expand(c, len);
2545         }
2546
2547         s = bc_num_r(ptr_a, b, c, d, scale, ts);
2548
2549         if (init) bc_num_free(&num2);
2550
2551         return s;
2552 }
2553
2554 #if ENABLE_DC
2555 static BcStatus bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d)
2556 {
2557         BcStatus s;
2558         BcNum base, exp, two, temp;
2559
2560         if (c->len == 0)
2561                 return bc_error("divide by zero");
2562         if (a->rdx || b->rdx || c->rdx)
2563                 return bc_error("non integer number");
2564         if (b->neg)
2565                 return bc_error("negative number");
2566
2567         bc_num_expand(d, c->len);
2568         bc_num_init(&base, c->len);
2569         bc_num_init(&exp, b->len);
2570         bc_num_init(&two, BC_NUM_DEF_SIZE);
2571         bc_num_init(&temp, b->len);
2572
2573         bc_num_one(&two);
2574         two.num[0] = 2;
2575         bc_num_one(d);
2576
2577         s = bc_num_rem(a, c, &base, 0);
2578         if (s) goto err;
2579         bc_num_copy(&exp, b);
2580
2581         while (exp.len != 0) {
2582
2583                 s = bc_num_divmod(&exp, &two, &exp, &temp, 0);
2584                 if (s) goto err;
2585
2586                 if (BC_NUM_ONE(&temp)) {
2587                         s = bc_num_mul(d, &base, &temp, 0);
2588                         if (s) goto err;
2589                         s = bc_num_rem(&temp, c, d, 0);
2590                         if (s) goto err;
2591                 }
2592
2593                 s = bc_num_mul(&base, &base, &temp, 0);
2594                 if (s) goto err;
2595                 s = bc_num_rem(&temp, c, &base, 0);
2596                 if (s) goto err;
2597         }
2598
2599 err:
2600         bc_num_free(&temp);
2601         bc_num_free(&two);
2602         bc_num_free(&exp);
2603         bc_num_free(&base);
2604         return s;
2605 }
2606 #endif // ENABLE_DC
2607
2608 static int bc_id_cmp(const void *e1, const void *e2)
2609 {
2610         return strcmp(((const BcId *) e1)->name, ((const BcId *) e2)->name);
2611 }
2612
2613 static void bc_id_free(void *id)
2614 {
2615         free(((BcId *) id)->name);
2616 }
2617
2618 static BcStatus bc_func_insert(BcFunc *f, char *name, bool var)
2619 {
2620         BcId a;
2621         size_t i;
2622
2623         for (i = 0; i < f->autos.len; ++i) {
2624                 if (strcmp(name, ((BcId *) bc_vec_item(&f->autos, i))->name) == 0)
2625                         return bc_error("function parameter or auto var has the same name as another");
2626         }
2627
2628         a.idx = var;
2629         a.name = name;
2630
2631         bc_vec_push(&f->autos, &a);
2632
2633         return BC_STATUS_SUCCESS;
2634 }
2635
2636 static void bc_func_init(BcFunc *f)
2637 {
2638         bc_vec_init(&f->code, sizeof(char), NULL);
2639         bc_vec_init(&f->autos, sizeof(BcId), bc_id_free);
2640         bc_vec_init(&f->labels, sizeof(size_t), NULL);
2641         f->nparams = 0;
2642 }
2643
2644 static void bc_func_free(void *func)
2645 {
2646         BcFunc *f = (BcFunc *) func;
2647         bc_vec_free(&f->code);
2648         bc_vec_free(&f->autos);
2649         bc_vec_free(&f->labels);
2650 }
2651
2652 static void bc_array_init(BcVec *a, bool nums)
2653 {
2654         if (nums)
2655                 bc_vec_init(a, sizeof(BcNum), bc_num_free);
2656         else
2657                 bc_vec_init(a, sizeof(BcVec), bc_vec_free);
2658         bc_array_expand(a, 1);
2659 }
2660
2661 static void bc_array_copy(BcVec *d, const BcVec *s)
2662 {
2663         size_t i;
2664
2665         bc_vec_npop(d, d->len);
2666         bc_vec_expand(d, s->cap);
2667         d->len = s->len;
2668
2669         for (i = 0; i < s->len; ++i) {
2670                 BcNum *dnum = bc_vec_item(d, i), *snum = bc_vec_item(s, i);
2671                 bc_num_init(dnum, snum->len);
2672                 bc_num_copy(dnum, snum);
2673         }
2674 }
2675
2676 static void bc_array_expand(BcVec *a, size_t len)
2677 {
2678         BcResultData data;
2679
2680         if (a->size == sizeof(BcNum) && a->dtor == bc_num_free) {
2681                 while (len > a->len) {
2682                         bc_num_init(&data.n, BC_NUM_DEF_SIZE);
2683                         bc_vec_push(a, &data.n);
2684                 }
2685         }
2686         else {
2687                 while (len > a->len) {
2688                         bc_array_init(&data.v, true);
2689                         bc_vec_push(a, &data.v);
2690                 }
2691         }
2692 }
2693
2694 static void bc_string_free(void *string)
2695 {
2696         free(*((char **) string));
2697 }
2698
2699 #if ENABLE_DC
2700 static void bc_result_copy(BcResult *d, BcResult *src)
2701 {
2702         d->t = src->t;
2703
2704         switch (d->t) {
2705
2706                 case BC_RESULT_TEMP:
2707                 case BC_RESULT_IBASE:
2708                 case BC_RESULT_SCALE:
2709                 case BC_RESULT_OBASE:
2710                 {
2711                         bc_num_init(&d->d.n, src->d.n.len);
2712                         bc_num_copy(&d->d.n, &src->d.n);
2713                         break;
2714                 }
2715
2716                 case BC_RESULT_VAR:
2717                 case BC_RESULT_ARRAY:
2718                 case BC_RESULT_ARRAY_ELEM:
2719                 {
2720                         d->d.id.name = xstrdup(src->d.id.name);
2721                         break;
2722                 }
2723
2724                 case BC_RESULT_CONSTANT:
2725                 case BC_RESULT_LAST:
2726                 case BC_RESULT_ONE:
2727                 case BC_RESULT_STR:
2728                 {
2729                         memcpy(&d->d.n, &src->d.n, sizeof(BcNum));
2730                         break;
2731                 }
2732         }
2733 }
2734 #endif // ENABLE_DC
2735
2736 static void bc_result_free(void *result)
2737 {
2738         BcResult *r = (BcResult *) result;
2739
2740         switch (r->t) {
2741
2742                 case BC_RESULT_TEMP:
2743                 case BC_RESULT_IBASE:
2744                 case BC_RESULT_SCALE:
2745                 case BC_RESULT_OBASE:
2746                 {
2747                         bc_num_free(&r->d.n);
2748                         break;
2749                 }
2750
2751                 case BC_RESULT_VAR:
2752                 case BC_RESULT_ARRAY:
2753                 case BC_RESULT_ARRAY_ELEM:
2754                 {
2755                         free(r->d.id.name);
2756                         break;
2757                 }
2758
2759                 default:
2760                 {
2761                         // Do nothing.
2762                         break;
2763                 }
2764         }
2765 }
2766
2767 static void bc_lex_lineComment(BcLex *l)
2768 {
2769         l->t.t = BC_LEX_WHITESPACE;
2770         while (l->i < l->len && l->buf[l->i++] != '\n');
2771         --l->i;
2772 }
2773
2774 static void bc_lex_whitespace(BcLex *l)
2775 {
2776         char c;
2777         l->t.t = BC_LEX_WHITESPACE;
2778         for (c = l->buf[l->i]; c != '\n' && isspace(c); c = l->buf[++l->i]);
2779 }
2780
2781 static BcStatus bc_lex_number(BcLex *l, char start)
2782 {
2783         const char *buf = l->buf + l->i;
2784         size_t len, hits = 0, bslashes = 0, i = 0, j;
2785         char c = buf[i];
2786         bool last_pt, pt = start == '.';
2787
2788         last_pt = pt;
2789         l->t.t = BC_LEX_NUMBER;
2790
2791         while (c != 0 && (isdigit(c) || (c >= 'A' && c <= 'F') ||
2792                           (c == '.' && !pt) || (c == '\\' && buf[i + 1] == '\n')))
2793         {
2794                 if (c != '\\') {
2795                         last_pt = c == '.';
2796                         pt = pt || last_pt;
2797                 }
2798                 else {
2799                         ++i;
2800                         bslashes += 1;
2801                 }
2802
2803                 c = buf[++i];
2804         }
2805
2806         len = i + !last_pt - bslashes * 2;
2807         if (len > BC_MAX_NUM)
2808                 return bc_error("number too long: must be [1, BC_NUM_MAX]");
2809
2810         bc_vec_npop(&l->t.v, l->t.v.len);
2811         bc_vec_expand(&l->t.v, len + 1);
2812         bc_vec_push(&l->t.v, &start);
2813
2814         for (buf -= 1, j = 1; j < len + hits * 2; ++j) {
2815
2816                 c = buf[j];
2817
2818                 // If we have hit a backslash, skip it. We don't have
2819                 // to check for a newline because it's guaranteed.
2820                 if (hits < bslashes && c == '\\') {
2821                         ++hits;
2822                         ++j;
2823                         continue;
2824                 }
2825
2826                 bc_vec_push(&l->t.v, &c);
2827         }
2828
2829         bc_vec_pushByte(&l->t.v, '\0');
2830         l->i += i;
2831
2832         return BC_STATUS_SUCCESS;
2833 }
2834
2835 static BcStatus bc_lex_name(BcLex *l)
2836 {
2837         size_t i = 0;
2838         const char *buf = l->buf + l->i - 1;
2839         char c = buf[i];
2840
2841         l->t.t = BC_LEX_NAME;
2842
2843         while ((c >= 'a' && c <= 'z') || isdigit(c) || c == '_') c = buf[++i];
2844
2845         if (i > BC_MAX_STRING)
2846                 return bc_error("name too long: must be [1, BC_NAME_MAX]");
2847         bc_vec_string(&l->t.v, i, buf);
2848
2849         // Increment the index. We minus 1 because it has already been incremented.
2850         l->i += i - 1;
2851
2852         return BC_STATUS_SUCCESS;
2853 }
2854
2855 static void bc_lex_init(BcLex *l, BcLexNext next)
2856 {
2857         l->next = next;
2858         bc_vec_init(&l->t.v, sizeof(char), NULL);
2859 }
2860
2861 static void bc_lex_free(BcLex *l)
2862 {
2863         bc_vec_free(&l->t.v);
2864 }
2865
2866 static void bc_lex_file(BcLex *l, const char *file)
2867 {
2868         l->line = 1;
2869         l->newline = false;
2870         l->f = file;
2871 }
2872
2873 static BcStatus bc_lex_next(BcLex *l)
2874 {
2875         BcStatus s;
2876
2877         l->t.last = l->t.t;
2878         if (l->t.last == BC_LEX_EOF) return bc_error("end of file");
2879
2880         l->line += l->newline;
2881         l->t.t = BC_LEX_EOF;
2882
2883         l->newline = (l->i == l->len);
2884         if (l->newline) return BC_STATUS_SUCCESS;
2885
2886         // Loop until failure or we don't have whitespace. This
2887         // is so the parser doesn't get inundated with whitespace.
2888         do {
2889                 s = l->next(l);
2890         } while (!s && l->t.t == BC_LEX_WHITESPACE);
2891
2892         return s;
2893 }
2894
2895 static BcStatus bc_lex_text(BcLex *l, const char *text)
2896 {
2897         l->buf = text;
2898         l->i = 0;
2899         l->len = strlen(text);
2900         l->t.t = l->t.last = BC_LEX_INVALID;
2901         return bc_lex_next(l);
2902 }
2903
2904 #if ENABLE_BC
2905 static BcStatus bc_lex_identifier(BcLex *l)
2906 {
2907         BcStatus s;
2908         size_t i;
2909         const char *buf = l->buf + l->i - 1;
2910
2911         for (i = 0; i < sizeof(bc_lex_kws) / sizeof(bc_lex_kws[0]); ++i) {
2912
2913                 unsigned long len = (unsigned long) bc_lex_kws[i].len;
2914
2915                 if (strncmp(buf, bc_lex_kws[i].name, len) == 0) {
2916
2917                         l->t.t = BC_LEX_KEY_AUTO + (BcLexType) i;
2918
2919                         if (!bc_lex_kws[i].posix) {
2920                                 s = bc_posix_error("POSIX does not allow the following keyword:"); // bc_lex_kws[i].name
2921                                 if (s) return s;
2922                         }
2923
2924                         // We minus 1 because the index has already been incremented.
2925                         l->i += len - 1;
2926                         return BC_STATUS_SUCCESS;
2927                 }
2928         }
2929
2930         s = bc_lex_name(l);
2931         if (s) return s;
2932
2933         if (l->t.v.len - 1 > 1)
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 '%c'", '&');
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'", 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'", c);
3268                         }
3269
3270                         break;
3271                 }
3272
3273                 default:
3274                 {
3275                         l->t.t = BC_LEX_INVALID;
3276                         s = bc_error("bad character '%c'", 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_npop(&l->t.v, l->t.v.len);
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_npop(&l->t.v, l->t.v.len);
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 < dc_lex_regs_len; ++i) {
3347                 if (l->t.last == dc_lex_regs[i]) return dc_lex_register(l);
3348         }
3349
3350         if (c >= '%' && c <= '~' &&
3351             (l->t.t = dc_lex_tokens[(c - '%')]) != BC_LEX_INVALID)
3352         {
3353                 return s;
3354         }
3355
3356         // This is the workhorse of the lexer.
3357         switch (c) {
3358
3359                 case '\0':
3360                 {
3361                         l->t.t = BC_LEX_EOF;
3362                         break;
3363                 }
3364
3365                 case '\n':
3366                 case '\t':
3367                 case '\v':
3368                 case '\f':
3369                 case '\r':
3370                 case ' ':
3371                 {
3372                         l->newline = (c == '\n');
3373                         bc_lex_whitespace(l);
3374                         break;
3375                 }
3376
3377                 case '!':
3378                 {
3379                         c2 = l->buf[l->i];
3380
3381                         if (c2 == '=')
3382                                 l->t.t = BC_LEX_OP_REL_NE;
3383                         else if (c2 == '<')
3384                                 l->t.t = BC_LEX_OP_REL_LE;
3385                         else if (c2 == '>')
3386                                 l->t.t = BC_LEX_OP_REL_GE;
3387                         else
3388                                 return bc_error("bad character '%c'", c);
3389
3390                         ++l->i;
3391                         break;
3392                 }
3393
3394                 case '#':
3395                 {
3396                         bc_lex_lineComment(l);
3397                         break;
3398                 }
3399
3400                 case '.':
3401                 {
3402                         if (isdigit(l->buf[l->i]))
3403                                 s = bc_lex_number(l, c);
3404                         else
3405                                 s = bc_error("bad character '%c'", c);
3406                         break;
3407                 }
3408
3409                 case '0':
3410                 case '1':
3411                 case '2':
3412                 case '3':
3413                 case '4':
3414                 case '5':
3415                 case '6':
3416                 case '7':
3417                 case '8':
3418                 case '9':
3419                 case 'A':
3420                 case 'B':
3421                 case 'C':
3422                 case 'D':
3423                 case 'E':
3424                 case 'F':
3425                 {
3426                         s = bc_lex_number(l, c);
3427                         break;
3428                 }
3429
3430                 case '[':
3431                 {
3432                         s = dc_lex_string(l);
3433                         break;
3434                 }
3435
3436                 default:
3437                 {
3438                         l->t.t = BC_LEX_INVALID;
3439                         s = bc_error("bad character '%c'", c);
3440                         break;
3441                 }
3442         }
3443
3444         return s;
3445 }
3446 #endif // ENABLE_DC
3447
3448 static void bc_parse_addFunc(BcParse *p, char *name, size_t *idx)
3449 {
3450         bc_program_addFunc(name, idx);
3451         p->func = bc_vec_item(&G.prog.fns, p->fidx);
3452 }
3453
3454 static void bc_parse_pushName(BcParse *p, char *name)
3455 {
3456         size_t i = 0, len = strlen(name);
3457
3458         for (; i < len; ++i) bc_parse_push(p, name[i]);
3459         bc_parse_push(p, BC_PARSE_STREND);
3460
3461         free(name);
3462 }
3463
3464 static void bc_parse_pushIndex(BcParse *p, size_t idx)
3465 {
3466         unsigned char amt, i, nums[sizeof(size_t)];
3467
3468         for (amt = 0; idx; ++amt) {
3469                 nums[amt] = (char) idx;
3470                 idx = (idx & ((unsigned long) ~(UCHAR_MAX))) >> sizeof(char) * CHAR_BIT;
3471         }
3472
3473         bc_parse_push(p, amt);
3474         for (i = 0; i < amt; ++i) bc_parse_push(p, nums[i]);
3475 }
3476
3477 static void bc_parse_number(BcParse *p, BcInst *prev, size_t *nexs)
3478 {
3479         char *num = xstrdup(p->l.t.v.v);
3480         size_t idx = G.prog.consts.len;
3481
3482         bc_vec_push(&G.prog.consts, &num);
3483
3484         bc_parse_push(p, BC_INST_NUM);
3485         bc_parse_pushIndex(p, idx);
3486
3487         ++(*nexs);
3488         (*prev) = BC_INST_NUM;
3489 }
3490
3491 static BcStatus bc_parse_text(BcParse *p, const char *text)
3492 {
3493         BcStatus s;
3494
3495         p->func = bc_vec_item(&G.prog.fns, p->fidx);
3496
3497         if (!text[0] && !BC_PARSE_CAN_EXEC(p)) {
3498                 p->l.t.t = BC_LEX_INVALID;
3499                 s = p->parse(p);
3500                 if (s) return s;
3501                 if (!BC_PARSE_CAN_EXEC(p))
3502                         return bc_error("file is not executable");
3503         }
3504
3505         return bc_lex_text(&p->l, text);
3506 }
3507
3508 // Called when bc/dc_parse_parse() detects a failure,
3509 // resets parsing structures.
3510 static void bc_parse_reset(BcParse *p)
3511 {
3512         if (p->fidx != BC_PROG_MAIN) {
3513
3514                 p->func->nparams = 0;
3515                 bc_vec_npop(&p->func->code, p->func->code.len);
3516                 bc_vec_npop(&p->func->autos, p->func->autos.len);
3517                 bc_vec_npop(&p->func->labels, p->func->labels.len);
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_npop(&p->exits, p->exits.len);
3528         bc_vec_npop(&p->conds, p->conds.len);
3529         bc_vec_npop(&p->ops, p->ops.len);
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("read() call inside of a 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("read() call inside of a 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("read() call inside of a read() call");
5351         }
5352
5353         bc_vec_npop(&f->code, f->code.len);
5354         bc_vec_init(&buf, sizeof(char), NULL);
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("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_npop(&f->code, f->code.len);
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_npop(&func->autos, func->autos.len);
6429                 bc_vec_npop(&func->code, func->code.len);
6430                 bc_vec_npop(&func->labels, func->labels.len);
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_npop(&G.prog.results, G.prog.results.len);
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_npop(&G.prog.results, G.prog.results.len);
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("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("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_vec_init(&buffer, sizeof(char), NULL);
6900         bc_vec_init(&buf, sizeof(char), NULL);
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_npop(&buffer, buffer.len);
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 static BcStatus bc_vm_exec(void)
6972 {
6973         BcStatus s = BC_STATUS_SUCCESS;
6974         size_t i;
6975
6976 #if ENABLE_BC
6977         if (option_mask32 & BC_FLAG_L) {
6978
6979                 bc_lex_file(&G.prs.l, bc_lib_name);
6980                 s = bc_parse_text(&G.prs, bc_lib);
6981
6982                 while (!s && G.prs.l.t.t != BC_LEX_EOF)
6983                         s = G.prs.parse(&G.prs);
6984
6985                 if (s) return s;
6986                 s = bc_program_exec();
6987                 if (s) return s;
6988         }
6989 #endif
6990
6991         for (i = 0; !s && i < G.files.len; ++i)
6992                 s = bc_vm_file(*((char **) bc_vec_item(&G.files, i)));
6993         if (s) {
6994                 fflush_and_check();
6995                 fputs("ready for more input\n", stderr);
6996         }
6997
6998         if (IS_BC || !G.files.len)
6999                 s = bc_vm_stdin();
7000         if (!s && !BC_PARSE_CAN_EXEC(&G.prs))
7001                 s = bc_vm_process("");
7002
7003         return s;
7004 }
7005
7006 #if ENABLE_FEATURE_CLEAN_UP
7007 static void bc_program_free()
7008 {
7009         bc_num_free(&G.prog.ib);
7010         bc_num_free(&G.prog.ob);
7011         bc_num_free(&G.prog.hexb);
7012 # if ENABLE_DC
7013         bc_num_free(&G.prog.strmb);
7014 # endif
7015         bc_vec_free(&G.prog.fns);
7016         bc_vec_free(&G.prog.fn_map);
7017         bc_vec_free(&G.prog.vars);
7018         bc_vec_free(&G.prog.var_map);
7019         bc_vec_free(&G.prog.arrs);
7020         bc_vec_free(&G.prog.arr_map);
7021         bc_vec_free(&G.prog.strs);
7022         bc_vec_free(&G.prog.consts);
7023         bc_vec_free(&G.prog.results);
7024         bc_vec_free(&G.prog.stack);
7025         bc_num_free(&G.prog.last);
7026         bc_num_free(&G.prog.zero);
7027         bc_num_free(&G.prog.one);
7028 }
7029
7030 static void bc_vm_free(void)
7031 {
7032         bc_vec_free(&G.files);
7033         bc_program_free();
7034         bc_parse_free(&G.prs);
7035         free(G.env_args);
7036 }
7037 #endif
7038
7039 static void bc_program_init(size_t line_len)
7040 {
7041         size_t idx;
7042         BcInstPtr ip;
7043
7044         /* memset(&G.prog, 0, sizeof(G.prog)); - already is */
7045         memset(&ip, 0, sizeof(BcInstPtr));
7046
7047         /* G.prog.nchars = G.prog.scale = 0; - already is */
7048         G.prog.len = line_len;
7049
7050         bc_num_init(&G.prog.ib, BC_NUM_DEF_SIZE);
7051         bc_num_ten(&G.prog.ib);
7052         G.prog.ib_t = 10;
7053
7054         bc_num_init(&G.prog.ob, BC_NUM_DEF_SIZE);
7055         bc_num_ten(&G.prog.ob);
7056         G.prog.ob_t = 10;
7057
7058         bc_num_init(&G.prog.hexb, BC_NUM_DEF_SIZE);
7059         bc_num_ten(&G.prog.hexb);
7060         G.prog.hexb.num[0] = 6;
7061
7062 #if ENABLE_DC
7063         bc_num_init(&G.prog.strmb, BC_NUM_DEF_SIZE);
7064         bc_num_ulong2num(&G.prog.strmb, UCHAR_MAX + 1);
7065 #endif
7066
7067         bc_num_init(&G.prog.last, BC_NUM_DEF_SIZE);
7068         bc_num_zero(&G.prog.last);
7069
7070         bc_num_init(&G.prog.zero, BC_NUM_DEF_SIZE);
7071         bc_num_zero(&G.prog.zero);
7072
7073         bc_num_init(&G.prog.one, BC_NUM_DEF_SIZE);
7074         bc_num_one(&G.prog.one);
7075
7076         bc_vec_init(&G.prog.fns, sizeof(BcFunc), bc_func_free);
7077         bc_map_init(&G.prog.fn_map);
7078
7079         bc_program_addFunc(xstrdup("(main)"), &idx);
7080         bc_program_addFunc(xstrdup("(read)"), &idx);
7081
7082         bc_vec_init(&G.prog.vars, sizeof(BcVec), bc_vec_free);
7083         bc_map_init(&G.prog.var_map);
7084
7085         bc_vec_init(&G.prog.arrs, sizeof(BcVec), bc_vec_free);
7086         bc_map_init(&G.prog.arr_map);
7087
7088         bc_vec_init(&G.prog.strs, sizeof(char *), bc_string_free);
7089         bc_vec_init(&G.prog.consts, sizeof(char *), bc_string_free);
7090         bc_vec_init(&G.prog.results, sizeof(BcResult), bc_result_free);
7091         bc_vec_init(&G.prog.stack, sizeof(BcInstPtr), NULL);
7092         bc_vec_push(&G.prog.stack, &ip);
7093 }
7094
7095 static void bc_vm_init(const char *env_len)
7096 {
7097         size_t len = bc_vm_envLen(env_len);
7098
7099         bc_vec_init(&G.files, sizeof(char *), NULL);
7100
7101         if (IS_BC) {
7102                 bc_vm_envArgs();
7103         }
7104
7105         bc_program_init(len);
7106         if (IS_BC) {
7107                 bc_parse_init(&G.prs, BC_PROG_MAIN);
7108         } else {
7109                 dc_parse_init(&G.prs, BC_PROG_MAIN);
7110         }
7111 }
7112
7113 static BcStatus bc_vm_run(int argc, char *argv[],
7114                           const char *env_len)
7115 {
7116         BcStatus st;
7117
7118         bc_vm_init(env_len);
7119         bc_args(argc, argv);
7120
7121         G.ttyin = isatty(0);
7122
7123         if (G.ttyin) {
7124 #if ENABLE_FEATURE_BC_SIGNALS
7125                 // With SA_RESTART, most system calls will restart
7126                 // (IOW: they won't fail with EINTR).
7127                 // In particular, this means ^C won't cause
7128                 // stdout to get into "error state" if SIGINT hits
7129                 // within write() syscall.
7130                 // The downside is that ^C while line input is taken
7131                 // will only be handled after [Enter] since read()
7132                 // from stdin is not interrupted by ^C either,
7133                 // it restarts, thus fgetc() does not return on ^C.
7134                 signal_SA_RESTART_empty_mask(SIGINT, record_signo);
7135
7136                 // Without SA_RESTART, this exhibits a bug:
7137                 // "while (1) print 1" and try ^C-ing it.
7138                 // Intermittently, instead of returning to input line,
7139                 // you'll get "output error: Interrupted system call"
7140                 // and exit.
7141                 //signal_no_SA_RESTART_empty_mask(SIGINT, record_signo);
7142 #endif
7143                 if (!(option_mask32 & BC_FLAG_Q))
7144                         bc_vm_info();
7145         }
7146         st = bc_vm_exec();
7147
7148 #if ENABLE_FEATURE_CLEAN_UP
7149         bc_vm_free();
7150 #endif
7151         return st;
7152 }
7153
7154 #if ENABLE_BC
7155 int bc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
7156 int bc_main(int argc, char **argv)
7157 {
7158         INIT_G();
7159         G.sbgn = G.send = '"';
7160
7161         return bc_vm_run(argc, argv, "BC_LINE_LENGTH");
7162 }
7163 #endif
7164
7165 #if ENABLE_DC
7166 int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
7167 int dc_main(int argc, char **argv)
7168 {
7169         INIT_G();
7170         G.sbgn = '[';
7171         G.send = ']';
7172
7173         return bc_vm_run(argc, argv, "DC_LINE_LENGTH");
7174 }
7175 #endif