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