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