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