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