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