aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-12-04 20:05:28 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2018-12-05 15:43:35 +0100
commit60cf747b6c234958387298068da658cfee9c42cb (patch)
tree1cd11d916fc420266dc11e98a9af867dcc7330d9
parentd38af48e0ae96fc4dc4a794ae8129372ed7c593f (diff)
downloadbusybox-w32-60cf747b6c234958387298068da658cfee9c42cb.tar.gz
busybox-w32-60cf747b6c234958387298068da658cfee9c42cb.tar.bz2
busybox-w32-60cf747b6c234958387298068da658cfee9c42cb.zip
bc: convert all non-POSIX BC_STATUS_foo codes
function old new delta bc_program_asciify - 469 +469 bc_parse_parse 432 495 +63 dc_parse_expr 727 775 +48 bc_vm_run 1955 1995 +40 bc_program_num 1115 1147 +32 bc_program_binOpPrep 296 324 +28 static.msg - 24 +24 bc_parse_name 570 593 +23 bc_lex_token 1344 1367 +23 dc_lex_token 695 714 +19 bc_num_ulong 85 103 +18 bc_program_read 336 353 +17 dc_parse_parse 47 60 +13 bc_parse_stmt 2301 2313 +12 bc_parse_auto 291 302 +11 bc_program_prep 89 99 +10 bc_lex_next 71 81 +10 dc_parse_register 52 61 +9 bc_program_print 775 784 +9 bc_func_insert 89 98 +9 bc_program_assignStr 159 167 +8 bc_program_assign 476 484 +8 bc_parse_body 116 124 +8 bc_lex_name 83 91 +8 bc_program_pushVar 215 221 +6 bc_parse_text 141 147 +6 bc_num_shift 68 74 +6 bc_num_p 472 478 +6 bc_program_execStr 559 564 +5 bc_parse_else 139 143 +4 bc_lex_number 301 305 +4 bc_num_d 558 561 +3 bc_parse_endBody 422 424 +2 bc_num_r 231 230 -1 bc_program_copyToVar 343 340 -3 bc_program_call 372 367 -5 bc_parse_expr 2215 2210 -5 bc_program_modexp 763 756 -7 bc_err_msgs 164 60 -104 bc_program_pushArray 136 - -136 bc_program_exec 4453 4153 -300 ------------------------------------------------------------------------------ (add/remove: 2/1 grow/shrink: 31/7 up/down: 961/-561) Total: 400 bytes text data bss dec hex filename 987766 485 7296 995547 f30db busybox_old 988258 485 7296 996039 f32c7 busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--miscutils/bc.c475
1 files changed, 271 insertions, 204 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c
index bd70670d5..7b20a94cc 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -168,8 +168,9 @@
168#include "libbb.h" 168#include "libbb.h"
169 169
170typedef enum BcStatus { 170typedef enum BcStatus {
171 BC_STATUS_SUCCESS, 171 BC_STATUS_SUCCESS = 0,
172 BC_STATUS_FAILURE, 172 BC_STATUS_FAILURE = 1,
173 BC_STATUS_PARSE_EMPTY_EXP = 2, // bc_parse_expr() uses this
173 174
174// BC_STATUS_ALLOC_ERR, 175// BC_STATUS_ALLOC_ERR,
175// BC_STATUS_INPUT_EOF, 176// BC_STATUS_INPUT_EOF,
@@ -177,48 +178,47 @@ typedef enum BcStatus {
177// BC_STATUS_PATH_IS_DIR, 178// BC_STATUS_PATH_IS_DIR,
178 179
179// BC_STATUS_LEX_BAD_CHAR, 180// BC_STATUS_LEX_BAD_CHAR,
180 BC_STATUS_LEX_NO_STRING_END, 181// BC_STATUS_LEX_NO_STRING_END,
181 BC_STATUS_LEX_NO_COMMENT_END, 182// BC_STATUS_LEX_NO_COMMENT_END,
182 BC_STATUS_LEX_EOF, 183// BC_STATUS_LEX_EOF,
183#if ENABLE_DC 184#if ENABLE_DC
184 BC_STATUS_LEX_EXTENDED_REG, 185// BC_STATUS_LEX_EXTENDED_REG,
185#endif 186#endif
186 BC_STATUS_PARSE_BAD_TOKEN, 187// BC_STATUS_PARSE_BAD_TOKEN,
187 BC_STATUS_PARSE_BAD_EXP, 188// BC_STATUS_PARSE_BAD_EXP,
188 BC_STATUS_PARSE_EMPTY_EXP, 189// BC_STATUS_PARSE_BAD_PRINT,
189 BC_STATUS_PARSE_BAD_PRINT, 190// BC_STATUS_PARSE_BAD_FUNC,
190 BC_STATUS_PARSE_BAD_FUNC, 191// BC_STATUS_PARSE_BAD_ASSIGN,
191 BC_STATUS_PARSE_BAD_ASSIGN,
192// BC_STATUS_PARSE_NO_AUTO, 192// BC_STATUS_PARSE_NO_AUTO,
193 BC_STATUS_PARSE_DUPLICATE_LOCAL, 193// BC_STATUS_PARSE_DUPLICATE_LOCAL,
194 BC_STATUS_PARSE_NO_BLOCK_END, 194// BC_STATUS_PARSE_NO_BLOCK_END,
195 195
196 BC_STATUS_MATH_NEGATIVE, 196// BC_STATUS_MATH_NEGATIVE,
197 BC_STATUS_MATH_NON_INTEGER, 197// BC_STATUS_MATH_NON_INTEGER,
198 BC_STATUS_MATH_OVERFLOW, 198// BC_STATUS_MATH_OVERFLOW,
199 BC_STATUS_MATH_DIVIDE_BY_ZERO, 199// BC_STATUS_MATH_DIVIDE_BY_ZERO,
200 BC_STATUS_MATH_BAD_STRING, 200// BC_STATUS_MATH_BAD_STRING,
201 201
202// BC_STATUS_EXEC_FILE_ERR, 202// BC_STATUS_EXEC_FILE_ERR,
203// BC_STATUS_EXEC_MISMATCHED_PARAMS, 203// BC_STATUS_EXEC_MISMATCHED_PARAMS,
204// BC_STATUS_EXEC_UNDEFINED_FUNC, 204// BC_STATUS_EXEC_UNDEFINED_FUNC,
205 BC_STATUS_EXEC_FILE_NOT_EXECUTABLE, 205// BC_STATUS_EXEC_FILE_NOT_EXECUTABLE,
206 BC_STATUS_EXEC_NUM_LEN, 206// BC_STATUS_EXEC_NUM_LEN,
207 BC_STATUS_EXEC_NAME_LEN, 207// BC_STATUS_EXEC_NAME_LEN,
208 BC_STATUS_EXEC_STRING_LEN, 208// BC_STATUS_EXEC_STRING_LEN,
209 BC_STATUS_EXEC_ARRAY_LEN, 209// BC_STATUS_EXEC_ARRAY_LEN,
210 BC_STATUS_EXEC_BAD_IBASE, 210// BC_STATUS_EXEC_BAD_IBASE,
211// BC_STATUS_EXEC_BAD_SCALE, 211// BC_STATUS_EXEC_BAD_SCALE,
212 BC_STATUS_EXEC_BAD_READ_EXPR, 212// BC_STATUS_EXEC_BAD_READ_EXPR,
213 BC_STATUS_EXEC_REC_READ, 213// BC_STATUS_EXEC_REC_READ,
214 BC_STATUS_EXEC_BAD_TYPE, 214// BC_STATUS_EXEC_BAD_TYPE,
215// BC_STATUS_EXEC_BAD_OBASE, 215// BC_STATUS_EXEC_BAD_OBASE,
216// BC_STATUS_EXEC_SIGNAL, 216// BC_STATUS_EXEC_SIGNAL,
217 BC_STATUS_EXEC_STACK, 217// BC_STATUS_EXEC_STACK,
218 218
219// BC_STATUS_VEC_OUT_OF_BOUNDS, 219// BC_STATUS_VEC_OUT_OF_BOUNDS,
220// BC_STATUS_VEC_ITEM_EXISTS, 220// BC_STATUS_VEC_ITEM_EXISTS,
221 BC_STATUS_BEFORE_POSIX = BC_STATUS_EXEC_STACK, 221 BC_STATUS_BEFORE_POSIX = BC_STATUS_PARSE_EMPTY_EXP,
222#if ENABLE_BC 222#if ENABLE_BC
223 BC_STATUS_POSIX_NAME_LEN, 223 BC_STATUS_POSIX_NAME_LEN,
224 BC_STATUS_POSIX_COMMENT, 224 BC_STATUS_POSIX_COMMENT,
@@ -242,51 +242,52 @@ typedef enum BcStatus {
242static const char *const bc_err_msgs[] = { 242static const char *const bc_err_msgs[] = {
243 NULL, 243 NULL,
244 NULL, 244 NULL,
245 NULL,
246
245// "memory allocation error", 247// "memory allocation error",
246// "I/O error", 248// "I/O error",
247// "file is not text:", 249// "file is not text:",
248// "path is a directory:", 250// "path is a directory:",
249 251
250// "bad character", 252// "bad character",
251 "string end could not be found", 253// "string end could not be found",
252 "comment end could not be found", 254// "comment end could not be found",
253 "end of file", 255// "end of file",
254#if ENABLE_DC 256#if ENABLE_DC
255 "extended register", 257// "extended register",
256#endif 258#endif
257 "bad token", 259// "bad token",
258 "bad expression", 260// "bad expression",
259 "empty expression", 261// "bad print statement",
260 "bad print statement", 262// "bad function definition",
261 "bad function definition", 263// "bad assignment: left side must be scale, ibase, "
262 "bad assignment: left side must be scale, ibase, " 264// "obase, last, var, or array element",
263 "obase, last, var, or array element",
264// "no auto variable found", 265// "no auto variable found",
265 "function parameter or auto var has the same name as another", 266// "function parameter or auto var has the same name as another",
266 "block end could not be found", 267// "block end could not be found",
267 268
268 "negative number", 269// "negative number",
269 "non integer number", 270// "non integer number",
270 "overflow", 271// "overflow",
271 "divide by zero", 272// "divide by zero",
272 "bad number string", 273// "bad number string",
273 274
274// "could not open file:", 275// "could not open file:",
275// "mismatched parameters", // wrong number of them, to be exact 276// "mismatched parameters", // wrong number of them, to be exact
276// "undefined function", 277// "undefined function",
277 "file is not executable:", 278// "file is not executable:",
278 "number too long: must be [1, BC_NUM_MAX]", 279// "number too long: must be [1, BC_NUM_MAX]",
279 "name too long: must be [1, BC_NAME_MAX]", 280// "name too long: must be [1, BC_NAME_MAX]",
280 "string too long: must be [1, BC_STRING_MAX]", 281// "string too long: must be [1, BC_STRING_MAX]",
281 "array too long; must be [1, BC_DIM_MAX]", 282// "array too long; must be [1, BC_DIM_MAX]",
282 "bad ibase; must be [2, 16]", 283// "bad ibase; must be [2, 16]",
283// "bad scale; must be [0, BC_SCALE_MAX]", 284// "bad scale; must be [0, BC_SCALE_MAX]",
284 "bad read() expression", 285// "bad read() expression",
285 "read() call inside of a read() call", 286// "read() call inside of a read() call",
286 "variable is wrong type", 287// "variable is wrong type",
287// "bad obase; must be [2, BC_BASE_MAX]", 288// "bad obase; must be [2, BC_BASE_MAX]",
288// "signal caught and not handled", 289// "signal caught and not handled",
289 "stack has too few elements", 290// "stack has too few elements",
290 291
291// "index is out of bounds", 292// "index is out of bounds",
292// "item already exists", 293// "item already exists",
@@ -1577,7 +1578,8 @@ static void bc_num_split(BcNum *restrict n, size_t idx, BcNum *restrict a,
1577static BcStatus bc_num_shift(BcNum *n, size_t places) 1578static BcStatus bc_num_shift(BcNum *n, size_t places)
1578{ 1579{
1579 if (places == 0 || n->len == 0) return BC_STATUS_SUCCESS; 1580 if (places == 0 || n->len == 0) return BC_STATUS_SUCCESS;
1580 if (places + n->len > BC_MAX_NUM) return BC_STATUS_EXEC_NUM_LEN; 1581 if (places + n->len > BC_MAX_NUM)
1582 return bc_error("number too long: must be [1, BC_NUM_MAX]");
1581 1583
1582 if (n->rdx >= places) 1584 if (n->rdx >= places)
1583 n->rdx -= places; 1585 n->rdx -= places;
@@ -1885,7 +1887,7 @@ static BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
1885 bool zero = true; 1887 bool zero = true;
1886 1888
1887 if (b->len == 0) 1889 if (b->len == 0)
1888 return BC_STATUS_MATH_DIVIDE_BY_ZERO; 1890 return bc_error("divide by zero");
1889 else if (a->len == 0) { 1891 else if (a->len == 0) {
1890 bc_num_setToZero(c, scale); 1892 bc_num_setToZero(c, scale);
1891 return BC_STATUS_SUCCESS; 1893 return BC_STATUS_SUCCESS;
@@ -1948,7 +1950,8 @@ static BcStatus bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c,
1948 BcNum temp; 1950 BcNum temp;
1949 bool neg; 1951 bool neg;
1950 1952
1951 if (b->len == 0) return BC_STATUS_MATH_DIVIDE_BY_ZERO; 1953 if (b->len == 0)
1954 return bc_error("divide by zero");
1952 1955
1953 if (a->len == 0) { 1956 if (a->len == 0) {
1954 bc_num_setToZero(d, ts); 1957 bc_num_setToZero(d, ts);
@@ -1997,7 +2000,7 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
1997 size_t i, powrdx, resrdx; 2000 size_t i, powrdx, resrdx;
1998 bool neg, zero; 2001 bool neg, zero;
1999 2002
2000 if (b->rdx) return BC_STATUS_MATH_NON_INTEGER; 2003 if (b->rdx) return bc_error("non integer number");
2001 2004
2002 if (b->len == 0) { 2005 if (b->len == 0) {
2003 bc_num_one(c); 2006 bc_num_one(c);
@@ -2435,7 +2438,8 @@ static void bc_num_copy(BcNum *d, BcNum *s)
2435static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, 2438static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base,
2436 size_t base_t) 2439 size_t base_t)
2437{ 2440{
2438 if (!bc_num_strValid(val, base_t)) return BC_STATUS_MATH_BAD_STRING; 2441 if (!bc_num_strValid(val, base_t))
2442 return bc_error("bad number string");
2439 2443
2440 if (base_t == 10) 2444 if (base_t == 10)
2441 bc_num_parseDecimal(n, val); 2445 bc_num_parseDecimal(n, val);
@@ -2474,7 +2478,7 @@ static BcStatus bc_num_ulong(BcNum *n, unsigned long *result)
2474 size_t i; 2478 size_t i;
2475 unsigned long pow; 2479 unsigned long pow;
2476 2480
2477 if (n->neg) return BC_STATUS_MATH_NEGATIVE; 2481 if (n->neg) return bc_error("negative number");
2478 2482
2479 for (*result = 0, pow = 1, i = n->rdx; i < n->len; ++i) { 2483 for (*result = 0, pow = 1, i = n->rdx; i < n->len; ++i) {
2480 2484
@@ -2483,7 +2487,8 @@ static BcStatus bc_num_ulong(BcNum *n, unsigned long *result)
2483 *result += ((unsigned long) n->num[i]) * pow; 2487 *result += ((unsigned long) n->num[i]) * pow;
2484 pow *= 10; 2488 pow *= 10;
2485 2489
2486 if (*result < prev || pow < powprev) return BC_STATUS_MATH_OVERFLOW; 2490 if (*result < prev || pow < powprev)
2491 return bc_error("overflow");
2487 } 2492 }
2488 2493
2489 return BC_STATUS_SUCCESS; 2494 return BC_STATUS_SUCCESS;
@@ -2555,7 +2560,7 @@ static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale)
2555 return BC_STATUS_SUCCESS; 2560 return BC_STATUS_SUCCESS;
2556 } 2561 }
2557 else if (a->neg) 2562 else if (a->neg)
2558 return BC_STATUS_MATH_NEGATIVE; 2563 return bc_error("negative number");
2559 else if (BC_NUM_ONE(a)) { 2564 else if (BC_NUM_ONE(a)) {
2560 bc_num_one(b); 2565 bc_num_one(b);
2561 bc_num_extend(b, scale); 2566 bc_num_extend(b, scale);
@@ -2674,9 +2679,12 @@ static BcStatus bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d)
2674 BcStatus s; 2679 BcStatus s;
2675 BcNum base, exp, two, temp; 2680 BcNum base, exp, two, temp;
2676 2681
2677 if (c->len == 0) return BC_STATUS_MATH_DIVIDE_BY_ZERO; 2682 if (c->len == 0)
2678 if (a->rdx || b->rdx || c->rdx) return BC_STATUS_MATH_NON_INTEGER; 2683 return bc_error("divide by zero");
2679 if (b->neg) return BC_STATUS_MATH_NEGATIVE; 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");
2680 2688
2681 bc_num_expand(d, c->len); 2689 bc_num_expand(d, c->len);
2682 bc_num_init(&base, c->len); 2690 bc_num_init(&base, c->len);
@@ -2735,8 +2743,8 @@ static BcStatus bc_func_insert(BcFunc *f, char *name, bool var)
2735 size_t i; 2743 size_t i;
2736 2744
2737 for (i = 0; i < f->autos.len; ++i) { 2745 for (i = 0; i < f->autos.len; ++i) {
2738 if (!strcmp(name, ((BcId *) bc_vec_item(&f->autos, i))->name)) 2746 if (strcmp(name, ((BcId *) bc_vec_item(&f->autos, i))->name) == 0)
2739 return BC_STATUS_PARSE_DUPLICATE_LOCAL; 2747 return bc_error("function parameter or auto var has the same name as another");
2740 } 2748 }
2741 2749
2742 a.idx = var; 2750 a.idx = var;
@@ -2918,7 +2926,8 @@ static BcStatus bc_lex_number(BcLex *l, char start)
2918 } 2926 }
2919 2927
2920 len = i + 1 * !last_pt - bslashes * 2; 2928 len = i + 1 * !last_pt - bslashes * 2;
2921 if (len > BC_MAX_NUM) return BC_STATUS_EXEC_NUM_LEN; 2929 if (len > BC_MAX_NUM)
2930 return bc_error("number too long: must be [1, BC_NUM_MAX]");
2922 2931
2923 bc_vec_npop(&l->t.v, l->t.v.len); 2932 bc_vec_npop(&l->t.v, l->t.v.len);
2924 bc_vec_expand(&l->t.v, len + 1); 2933 bc_vec_expand(&l->t.v, len + 1);
@@ -2955,7 +2964,8 @@ static BcStatus bc_lex_name(BcLex *l)
2955 2964
2956 while ((c >= 'a' && c <= 'z') || isdigit(c) || c == '_') c = buf[++i]; 2965 while ((c >= 'a' && c <= 'z') || isdigit(c) || c == '_') c = buf[++i];
2957 2966
2958 if (i > BC_MAX_STRING) return BC_STATUS_EXEC_NAME_LEN; 2967 if (i > BC_MAX_STRING)
2968 return bc_error("name too long: must be [1, BC_NAME_MAX]");
2959 bc_vec_string(&l->t.v, i, buf); 2969 bc_vec_string(&l->t.v, i, buf);
2960 2970
2961 // Increment the index. We minus 1 because it has already been incremented. 2971 // Increment the index. We minus 1 because it has already been incremented.
@@ -2987,7 +2997,7 @@ static BcStatus bc_lex_next(BcLex *l)
2987 BcStatus s; 2997 BcStatus s;
2988 2998
2989 l->t.last = l->t.t; 2999 l->t.last = l->t.t;
2990 if (l->t.last == BC_LEX_EOF) return BC_STATUS_LEX_EOF; 3000 if (l->t.last == BC_LEX_EOF) return bc_error("end of file");
2991 3001
2992 l->line += l->newline; 3002 l->line += l->newline;
2993 l->t.t = BC_LEX_EOF; 3003 l->t.t = BC_LEX_EOF;
@@ -3060,11 +3070,12 @@ static BcStatus bc_lex_string(BcLex *l)
3060 3070
3061 if (c == '\0') { 3071 if (c == '\0') {
3062 l->i = i; 3072 l->i = i;
3063 return BC_STATUS_LEX_NO_STRING_END; 3073 return bc_error("string end could not be found");
3064 } 3074 }
3065 3075
3066 len = i - l->i; 3076 len = i - l->i;
3067 if (len > BC_MAX_STRING) return BC_STATUS_EXEC_STRING_LEN; 3077 if (len > BC_MAX_STRING)
3078 return bc_error("string too long: must be [1, BC_STRING_MAX]");
3068 bc_vec_string(&l->t.v, len, l->buf + l->i); 3079 bc_vec_string(&l->t.v, len, l->buf + l->i);
3069 3080
3070 l->i = i + 1; 3081 l->i = i + 1;
@@ -3101,7 +3112,7 @@ static BcStatus bc_lex_comment(BcLex *l)
3101 } 3112 }
3102 if (c == '\0') { 3113 if (c == '\0') {
3103 l->i = i; 3114 l->i = i;
3104 return BC_STATUS_LEX_NO_COMMENT_END; 3115 return bc_error("comment end could not be found");
3105 } 3116 }
3106 nls += (c == '\n'); 3117 nls += (c == '\n');
3107 i++; 3118 i++;
@@ -3404,7 +3415,7 @@ static BcStatus dc_lex_register(BcLex *l)
3404 bc_lex_whitespace(l); 3415 bc_lex_whitespace(l);
3405 ++l->i; 3416 ++l->i;
3406 if (!G_exreg) 3417 if (!G_exreg)
3407 s = BC_STATUS_LEX_EXTENDED_REG; 3418 s = bc_error("extended register");
3408 else 3419 else
3409 s = bc_lex_name(l); 3420 s = bc_lex_name(l);
3410 } 3421 }
@@ -3437,11 +3448,12 @@ static BcStatus dc_lex_string(BcLex *l)
3437 3448
3438 if (c == '\0') { 3449 if (c == '\0') {
3439 l->i = i; 3450 l->i = i;
3440 return BC_STATUS_LEX_NO_STRING_END; 3451 return bc_error("string end could not be found");
3441 } 3452 }
3442 3453
3443 bc_vec_pushByte(&l->t.v, '\0'); 3454 bc_vec_pushByte(&l->t.v, '\0');
3444 if (i - l->i > BC_MAX_STRING) return BC_STATUS_EXEC_STRING_LEN; 3455 if (i - l->i > BC_MAX_STRING)
3456 return bc_error("string too long: must be [1, BC_STRING_MAX]");
3445 3457
3446 l->i = i; 3458 l->i = i;
3447 l->line += nls; 3459 l->line += nls;
@@ -3606,11 +3618,12 @@ static BcStatus bc_parse_text(BcParse *p, const char *text)
3606 3618
3607 p->func = bc_vec_item(&G.prog.fns, p->fidx); 3619 p->func = bc_vec_item(&G.prog.fns, p->fidx);
3608 3620
3609 if (!strcmp(text, "") && !BC_PARSE_CAN_EXEC(p)) { 3621 if (!text[0] && !BC_PARSE_CAN_EXEC(p)) {
3610 p->l.t.t = BC_LEX_INVALID; 3622 p->l.t.t = BC_LEX_INVALID;
3611 s = p->parse(p); 3623 s = p->parse(p);
3612 if (s) return s; 3624 if (s) return s;
3613 if (!BC_PARSE_CAN_EXEC(p)) return BC_STATUS_EXEC_FILE_NOT_EXECUTABLE; 3625 if (!BC_PARSE_CAN_EXEC(p))
3626 return bc_error("file is not executable");
3614 } 3627 }
3615 3628
3616 return bc_lex_text(&p->l, text); 3629 return bc_lex_text(&p->l, text);
@@ -3703,7 +3716,8 @@ static BcStatus bc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs)
3703{ 3716{
3704 BcLexType top; 3717 BcLexType top;
3705 3718
3706 if (p->ops.len <= ops_bgn) return BC_STATUS_PARSE_BAD_EXP; 3719 if (p->ops.len <= ops_bgn)
3720 return bc_error("bad expression");
3707 top = BC_PARSE_TOP_OP(p); 3721 top = BC_PARSE_TOP_OP(p);
3708 3722
3709 while (top != BC_LEX_LPAREN) { 3723 while (top != BC_LEX_LPAREN) {
@@ -3713,7 +3727,8 @@ static BcStatus bc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs)
3713 bc_vec_pop(&p->ops); 3727 bc_vec_pop(&p->ops);
3714 *nexs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG; 3728 *nexs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG;
3715 3729
3716 if (p->ops.len <= ops_bgn) return BC_STATUS_PARSE_BAD_EXP; 3730 if (p->ops.len <= ops_bgn)
3731 return bc_error("bad expression");
3717 top = BC_PARSE_TOP_OP(p); 3732 top = BC_PARSE_TOP_OP(p);
3718 } 3733 }
3719 3734
@@ -3744,7 +3759,7 @@ static BcStatus bc_parse_params(BcParse *p, uint8_t flags)
3744 } 3759 }
3745 } 3760 }
3746 3761
3747 if (comma) return BC_STATUS_PARSE_BAD_TOKEN; 3762 if (comma) return bc_error("bad token");
3748 bc_parse_push(p, BC_INST_CALL); 3763 bc_parse_push(p, BC_INST_CALL);
3749 bc_parse_pushIndex(p, nparams); 3764 bc_parse_pushIndex(p, nparams);
3750 3765
@@ -3763,7 +3778,7 @@ static BcStatus bc_parse_call(BcParse *p, char *name, uint8_t flags)
3763 if (s) goto err; 3778 if (s) goto err;
3764 3779
3765 if (p->l.t.t != BC_LEX_RPAREN) { 3780 if (p->l.t.t != BC_LEX_RPAREN) {
3766 s = BC_STATUS_PARSE_BAD_TOKEN; 3781 s = bc_error("bad token");
3767 goto err; 3782 goto err;
3768 } 3783 }
3769 3784
@@ -3805,7 +3820,7 @@ static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags)
3805 if (p->l.t.t == BC_LEX_RBRACKET) { 3820 if (p->l.t.t == BC_LEX_RBRACKET) {
3806 3821
3807 if (!(flags & BC_PARSE_ARRAY)) { 3822 if (!(flags & BC_PARSE_ARRAY)) {
3808 s = BC_STATUS_PARSE_BAD_EXP; 3823 s = bc_error("bad expression");
3809 goto err; 3824 goto err;
3810 } 3825 }
3811 3826
@@ -3828,7 +3843,7 @@ static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags)
3828 else if (p->l.t.t == BC_LEX_LPAREN) { 3843 else if (p->l.t.t == BC_LEX_LPAREN) {
3829 3844
3830 if (flags & BC_PARSE_NOCALL) { 3845 if (flags & BC_PARSE_NOCALL) {
3831 s = BC_STATUS_PARSE_BAD_TOKEN; 3846 s = bc_error("bad token");
3832 goto err; 3847 goto err;
3833 } 3848 }
3834 3849
@@ -3854,11 +3869,11 @@ static BcStatus bc_parse_read(BcParse *p)
3854 3869
3855 s = bc_lex_next(&p->l); 3870 s = bc_lex_next(&p->l);
3856 if (s) return s; 3871 if (s) return s;
3857 if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; 3872 if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token");
3858 3873
3859 s = bc_lex_next(&p->l); 3874 s = bc_lex_next(&p->l);
3860 if (s) return s; 3875 if (s) return s;
3861 if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; 3876 if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token");
3862 3877
3863 bc_parse_push(p, BC_INST_READ); 3878 bc_parse_push(p, BC_INST_READ);
3864 3879
@@ -3872,7 +3887,7 @@ static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags,
3872 3887
3873 s = bc_lex_next(&p->l); 3888 s = bc_lex_next(&p->l);
3874 if (s) return s; 3889 if (s) return s;
3875 if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; 3890 if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token");
3876 3891
3877 flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; 3892 flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY;
3878 3893
@@ -3882,7 +3897,7 @@ static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags,
3882 s = bc_parse_expr(p, flags, bc_parse_next_rel); 3897 s = bc_parse_expr(p, flags, bc_parse_next_rel);
3883 if (s) return s; 3898 if (s) return s;
3884 3899
3885 if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; 3900 if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token");
3886 3901
3887 *prev = (type == BC_LEX_KEY_LENGTH) ? BC_INST_LENGTH : BC_INST_SQRT; 3902 *prev = (type == BC_LEX_KEY_LENGTH) ? BC_INST_LENGTH : BC_INST_SQRT;
3888 bc_parse_push(p, *prev); 3903 bc_parse_push(p, *prev);
@@ -3911,7 +3926,7 @@ static BcStatus bc_parse_scale(BcParse *p, BcInst *type, uint8_t flags)
3911 3926
3912 s = bc_parse_expr(p, flags, bc_parse_next_rel); 3927 s = bc_parse_expr(p, flags, bc_parse_next_rel);
3913 if (s) return s; 3928 if (s) return s;
3914 if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; 3929 if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token");
3915 bc_parse_push(p, BC_INST_SCALE_FUNC); 3930 bc_parse_push(p, BC_INST_SCALE_FUNC);
3916 3931
3917 return bc_lex_next(&p->l); 3932 return bc_lex_next(&p->l);
@@ -3968,7 +3983,7 @@ static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr,
3968 s = bc_lex_next(&p->l); 3983 s = bc_lex_next(&p->l);
3969 if (s) return s; 3984 if (s) return s;
3970 if (p->l.t.t == BC_LEX_LPAREN) 3985 if (p->l.t.t == BC_LEX_LPAREN)
3971 s = BC_STATUS_PARSE_BAD_TOKEN; 3986 s = bc_error("bad token");
3972 else 3987 else
3973 bc_parse_push(p, BC_INST_SCALE); 3988 bc_parse_push(p, BC_INST_SCALE);
3974 break; 3989 break;
@@ -3976,7 +3991,7 @@ static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr,
3976 3991
3977 default: 3992 default:
3978 { 3993 {
3979 s = BC_STATUS_PARSE_BAD_TOKEN; 3994 s = bc_error("bad token");
3980 break; 3995 break;
3981 } 3996 }
3982 } 3997 }
@@ -4037,7 +4052,7 @@ static BcStatus bc_parse_print(BcParse *p)
4037 type = p->l.t.t; 4052 type = p->l.t.t;
4038 4053
4039 if (type == BC_LEX_SCOLON || type == BC_LEX_NLINE) 4054 if (type == BC_LEX_SCOLON || type == BC_LEX_NLINE)
4040 return BC_STATUS_PARSE_BAD_PRINT; 4055 return bc_error("bad print statement");
4041 4056
4042 while (!s && type != BC_LEX_SCOLON && type != BC_LEX_NLINE) { 4057 while (!s && type != BC_LEX_SCOLON && type != BC_LEX_NLINE) {
4043 4058
@@ -4057,7 +4072,7 @@ static BcStatus bc_parse_print(BcParse *p)
4057 } 4072 }
4058 4073
4059 if (s) return s; 4074 if (s) return s;
4060 if (comma) return BC_STATUS_PARSE_BAD_TOKEN; 4075 if (comma) return bc_error("bad token");
4061 4076
4062 return bc_lex_next(&p->l); 4077 return bc_lex_next(&p->l);
4063} 4078}
@@ -4068,7 +4083,7 @@ static BcStatus bc_parse_return(BcParse *p)
4068 BcLexType t; 4083 BcLexType t;
4069 bool paren; 4084 bool paren;
4070 4085
4071 if (!BC_PARSE_FUNC(p)) return BC_STATUS_PARSE_BAD_TOKEN; 4086 if (!BC_PARSE_FUNC(p)) return bc_error("bad token");
4072 4087
4073 s = bc_lex_next(&p->l); 4088 s = bc_lex_next(&p->l);
4074 if (s) return s; 4089 if (s) return s;
@@ -4083,7 +4098,8 @@ static BcStatus bc_parse_return(BcParse *p)
4083 s = bc_parse_expr(p, 0, bc_parse_next_expr); 4098 s = bc_parse_expr(p, 0, bc_parse_next_expr);
4084 if (s && s != BC_STATUS_PARSE_EMPTY_EXP) 4099 if (s && s != BC_STATUS_PARSE_EMPTY_EXP)
4085 return s; 4100 return s;
4086 else if (s == BC_STATUS_PARSE_EMPTY_EXP) { 4101
4102 if (s == BC_STATUS_PARSE_EMPTY_EXP) {
4087 bc_parse_push(p, BC_INST_RET0); 4103 bc_parse_push(p, BC_INST_RET0);
4088 s = bc_lex_next(&p->l); 4104 s = bc_lex_next(&p->l);
4089 if (s) return s; 4105 if (s) return s;
@@ -4105,18 +4121,18 @@ static BcStatus bc_parse_endBody(BcParse *p, bool brace)
4105 BcStatus s = BC_STATUS_SUCCESS; 4121 BcStatus s = BC_STATUS_SUCCESS;
4106 4122
4107 if (p->flags.len <= 1 || (brace && p->nbraces == 0)) 4123 if (p->flags.len <= 1 || (brace && p->nbraces == 0))
4108 return BC_STATUS_PARSE_BAD_TOKEN; 4124 return bc_error("bad token");
4109 4125
4110 if (brace) { 4126 if (brace) {
4111 4127
4112 if (p->l.t.t == BC_LEX_RBRACE) { 4128 if (p->l.t.t == BC_LEX_RBRACE) {
4113 if (!p->nbraces) return BC_STATUS_PARSE_BAD_TOKEN; 4129 if (!p->nbraces) return bc_error("bad token");
4114 --p->nbraces; 4130 --p->nbraces;
4115 s = bc_lex_next(&p->l); 4131 s = bc_lex_next(&p->l);
4116 if (s) return s; 4132 if (s) return s;
4117 } 4133 }
4118 else 4134 else
4119 return BC_STATUS_PARSE_BAD_TOKEN; 4135 return bc_error("bad token");
4120 } 4136 }
4121 4137
4122 if (BC_PARSE_IF(p)) { 4138 if (BC_PARSE_IF(p)) {
@@ -4202,13 +4218,13 @@ static BcStatus bc_parse_if(BcParse *p)
4202 4218
4203 s = bc_lex_next(&p->l); 4219 s = bc_lex_next(&p->l);
4204 if (s) return s; 4220 if (s) return s;
4205 if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; 4221 if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token");
4206 4222
4207 s = bc_lex_next(&p->l); 4223 s = bc_lex_next(&p->l);
4208 if (s) return s; 4224 if (s) return s;
4209 s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); 4225 s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel);
4210 if (s) return s; 4226 if (s) return s;
4211 if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; 4227 if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token");
4212 4228
4213 s = bc_lex_next(&p->l); 4229 s = bc_lex_next(&p->l);
4214 if (s) return s; 4230 if (s) return s;
@@ -4229,7 +4245,7 @@ static BcStatus bc_parse_else(BcParse *p)
4229{ 4245{
4230 BcInstPtr ip; 4246 BcInstPtr ip;
4231 4247
4232 if (!BC_PARSE_IF_END(p)) return BC_STATUS_PARSE_BAD_TOKEN; 4248 if (!BC_PARSE_IF_END(p)) return bc_error("bad token");
4233 4249
4234 ip.idx = p->func->labels.len; 4250 ip.idx = p->func->labels.len;
4235 ip.func = ip.len = 0; 4251 ip.func = ip.len = 0;
@@ -4253,7 +4269,7 @@ static BcStatus bc_parse_while(BcParse *p)
4253 4269
4254 s = bc_lex_next(&p->l); 4270 s = bc_lex_next(&p->l);
4255 if (s) return s; 4271 if (s) return s;
4256 if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; 4272 if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token");
4257 s = bc_lex_next(&p->l); 4273 s = bc_lex_next(&p->l);
4258 if (s) return s; 4274 if (s) return s;
4259 4275
@@ -4271,7 +4287,7 @@ static BcStatus bc_parse_while(BcParse *p)
4271 4287
4272 s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); 4288 s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel);
4273 if (s) return s; 4289 if (s) return s;
4274 if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; 4290 if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token");
4275 s = bc_lex_next(&p->l); 4291 s = bc_lex_next(&p->l);
4276 if (s) return s; 4292 if (s) return s;
4277 4293
@@ -4290,7 +4306,7 @@ static BcStatus bc_parse_for(BcParse *p)
4290 4306
4291 s = bc_lex_next(&p->l); 4307 s = bc_lex_next(&p->l);
4292 if (s) return s; 4308 if (s) return s;
4293 if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; 4309 if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token");
4294 s = bc_lex_next(&p->l); 4310 s = bc_lex_next(&p->l);
4295 if (s) return s; 4311 if (s) return s;
4296 4312
@@ -4300,7 +4316,7 @@ static BcStatus bc_parse_for(BcParse *p)
4300 s = bc_vm_posixError(BC_STATUS_POSIX_FOR1, p->l.f, p->l.line, NULL); 4316 s = bc_vm_posixError(BC_STATUS_POSIX_FOR1, p->l.f, p->l.line, NULL);
4301 4317
4302 if (s) return s; 4318 if (s) return s;
4303 if (p->l.t.t != BC_LEX_SCOLON) return BC_STATUS_PARSE_BAD_TOKEN; 4319 if (p->l.t.t != BC_LEX_SCOLON) return bc_error("bad token");
4304 s = bc_lex_next(&p->l); 4320 s = bc_lex_next(&p->l);
4305 if (s) return s; 4321 if (s) return s;
4306 4322
@@ -4317,7 +4333,7 @@ static BcStatus bc_parse_for(BcParse *p)
4317 s = bc_vm_posixError(BC_STATUS_POSIX_FOR2, p->l.f, p->l.line, NULL); 4333 s = bc_vm_posixError(BC_STATUS_POSIX_FOR2, p->l.f, p->l.line, NULL);
4318 4334
4319 if (s) return s; 4335 if (s) return s;
4320 if (p->l.t.t != BC_LEX_SCOLON) return BC_STATUS_PARSE_BAD_TOKEN; 4336 if (p->l.t.t != BC_LEX_SCOLON) return bc_error("bad token");
4321 4337
4322 s = bc_lex_next(&p->l); 4338 s = bc_lex_next(&p->l);
4323 if (s) return s; 4339 if (s) return s;
@@ -4339,7 +4355,7 @@ static BcStatus bc_parse_for(BcParse *p)
4339 4355
4340 if (s) return s; 4356 if (s) return s;
4341 4357
4342 if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; 4358 if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token");
4343 bc_parse_push(p, BC_INST_JUMP); 4359 bc_parse_push(p, BC_INST_JUMP);
4344 bc_parse_pushIndex(p, cond_idx); 4360 bc_parse_pushIndex(p, cond_idx);
4345 bc_vec_push(&p->func->labels, &p->func->code.len); 4361 bc_vec_push(&p->func->labels, &p->func->code.len);
@@ -4362,17 +4378,17 @@ static BcStatus bc_parse_loopExit(BcParse *p, BcLexType type)
4362 size_t i; 4378 size_t i;
4363 BcInstPtr *ip; 4379 BcInstPtr *ip;
4364 4380
4365 if (!BC_PARSE_LOOP(p)) return BC_STATUS_PARSE_BAD_TOKEN; 4381 if (!BC_PARSE_LOOP(p)) return bc_error("bad token");
4366 4382
4367 if (type == BC_LEX_KEY_BREAK) { 4383 if (type == BC_LEX_KEY_BREAK) {
4368 4384
4369 if (p->exits.len == 0) return BC_STATUS_PARSE_BAD_TOKEN; 4385 if (p->exits.len == 0) return bc_error("bad token");
4370 4386
4371 i = p->exits.len - 1; 4387 i = p->exits.len - 1;
4372 ip = bc_vec_item(&p->exits, i); 4388 ip = bc_vec_item(&p->exits, i);
4373 4389
4374 while (!ip->func && i < p->exits.len) ip = bc_vec_item(&p->exits, i--); 4390 while (!ip->func && i < p->exits.len) ip = bc_vec_item(&p->exits, i--);
4375 if (i >= p->exits.len && !ip->func) return BC_STATUS_PARSE_BAD_TOKEN; 4391 if (i >= p->exits.len && !ip->func) return bc_error("bad token");
4376 4392
4377 i = ip->idx; 4393 i = ip->idx;
4378 } 4394 }
@@ -4386,7 +4402,7 @@ static BcStatus bc_parse_loopExit(BcParse *p, BcLexType type)
4386 if (s) return s; 4402 if (s) return s;
4387 4403
4388 if (p->l.t.t != BC_LEX_SCOLON && p->l.t.t != BC_LEX_NLINE) 4404 if (p->l.t.t != BC_LEX_SCOLON && p->l.t.t != BC_LEX_NLINE)
4389 return BC_STATUS_PARSE_BAD_TOKEN; 4405 return bc_error("bad token");
4390 4406
4391 return bc_lex_next(&p->l); 4407 return bc_lex_next(&p->l);
4392} 4408}
@@ -4400,20 +4416,23 @@ static BcStatus bc_parse_func(BcParse *p)
4400 4416
4401 s = bc_lex_next(&p->l); 4417 s = bc_lex_next(&p->l);
4402 if (s) return s; 4418 if (s) return s;
4403 if (p->l.t.t != BC_LEX_NAME) return BC_STATUS_PARSE_BAD_FUNC; 4419 if (p->l.t.t != BC_LEX_NAME)
4420 return bc_error("bad function definition");
4404 4421
4405 name = xstrdup(p->l.t.v.v); 4422 name = xstrdup(p->l.t.v.v);
4406 bc_parse_addFunc(p, name, &p->fidx); 4423 bc_parse_addFunc(p, name, &p->fidx);
4407 4424
4408 s = bc_lex_next(&p->l); 4425 s = bc_lex_next(&p->l);
4409 if (s) return s; 4426 if (s) return s;
4410 if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_FUNC; 4427 if (p->l.t.t != BC_LEX_LPAREN)
4428 return bc_error("bad function definition");
4411 s = bc_lex_next(&p->l); 4429 s = bc_lex_next(&p->l);
4412 if (s) return s; 4430 if (s) return s;
4413 4431
4414 while (p->l.t.t != BC_LEX_RPAREN) { 4432 while (p->l.t.t != BC_LEX_RPAREN) {
4415 4433
4416 if (p->l.t.t != BC_LEX_NAME) return BC_STATUS_PARSE_BAD_FUNC; 4434 if (p->l.t.t != BC_LEX_NAME)
4435 return bc_error("bad function definition");
4417 4436
4418 ++p->func->nparams; 4437 ++p->func->nparams;
4419 4438
@@ -4429,7 +4448,7 @@ static BcStatus bc_parse_func(BcParse *p)
4429 if (s) goto err; 4448 if (s) goto err;
4430 4449
4431 if (p->l.t.t != BC_LEX_RBRACKET) { 4450 if (p->l.t.t != BC_LEX_RBRACKET) {
4432 s = BC_STATUS_PARSE_BAD_FUNC; 4451 s = bc_error("bad function definition");
4433 goto err; 4452 goto err;
4434 } 4453 }
4435 4454
@@ -4447,7 +4466,7 @@ static BcStatus bc_parse_func(BcParse *p)
4447 if (s) goto err; 4466 if (s) goto err;
4448 } 4467 }
4449 4468
4450 if (comma) return BC_STATUS_PARSE_BAD_FUNC; 4469 if (comma) return bc_error("bad function definition");
4451 4470
4452 flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_BODY; 4471 flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_BODY;
4453 bc_parse_startBody(p, flags); 4472 bc_parse_startBody(p, flags);
@@ -4471,7 +4490,7 @@ static BcStatus bc_parse_auto(BcParse *p)
4471 bool comma, var, one; 4490 bool comma, var, one;
4472 char *name; 4491 char *name;
4473 4492
4474 if (!p->auto_part) return BC_STATUS_PARSE_BAD_TOKEN; 4493 if (!p->auto_part) return bc_error("bad token");
4475 s = bc_lex_next(&p->l); 4494 s = bc_lex_next(&p->l);
4476 if (s) return s; 4495 if (s) return s;
4477 4496
@@ -4491,7 +4510,7 @@ static BcStatus bc_parse_auto(BcParse *p)
4491 if (s) goto err; 4510 if (s) goto err;
4492 4511
4493 if (p->l.t.t != BC_LEX_RBRACKET) { 4512 if (p->l.t.t != BC_LEX_RBRACKET) {
4494 s = BC_STATUS_PARSE_BAD_FUNC; 4513 s = bc_error("bad function definition");
4495 goto err; 4514 goto err;
4496 } 4515 }
4497 4516
@@ -4509,11 +4528,11 @@ static BcStatus bc_parse_auto(BcParse *p)
4509 if (s) goto err; 4528 if (s) goto err;
4510 } 4529 }
4511 4530
4512 if (comma) return BC_STATUS_PARSE_BAD_FUNC; 4531 if (comma) return bc_error("bad function definition");
4513 if (!one) return bc_error("no auto variable found"); 4532 if (!one) return bc_error("no auto variable found");
4514 4533
4515 if (p->l.t.t != BC_LEX_NLINE && p->l.t.t != BC_LEX_SCOLON) 4534 if (p->l.t.t != BC_LEX_NLINE && p->l.t.t != BC_LEX_SCOLON)
4516 return BC_STATUS_PARSE_BAD_TOKEN; 4535 return bc_error("bad token");
4517 4536
4518 return bc_lex_next(&p->l); 4537 return bc_lex_next(&p->l);
4519 4538
@@ -4531,7 +4550,7 @@ static BcStatus bc_parse_body(BcParse *p, bool brace)
4531 4550
4532 if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) { 4551 if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) {
4533 4552
4534 if (!brace) return BC_STATUS_PARSE_BAD_TOKEN; 4553 if (!brace) return bc_error("bad token");
4535 p->auto_part = p->l.t.t != BC_LEX_KEY_AUTO; 4554 p->auto_part = p->l.t.t != BC_LEX_KEY_AUTO;
4536 4555
4537 if (!p->auto_part) { 4556 if (!p->auto_part) {
@@ -4568,7 +4587,7 @@ static BcStatus bc_parse_stmt(BcParse *p)
4568 4587
4569 case BC_LEX_LBRACE: 4588 case BC_LEX_LBRACE:
4570 { 4589 {
4571 if (!BC_PARSE_BODY(p)) return BC_STATUS_PARSE_BAD_TOKEN; 4590 if (!BC_PARSE_BODY(p)) return bc_error("bad token");
4572 4591
4573 ++p->nbraces; 4592 ++p->nbraces;
4574 s = bc_lex_next(&p->l); 4593 s = bc_lex_next(&p->l);
@@ -4713,7 +4732,7 @@ static BcStatus bc_parse_stmt(BcParse *p)
4713 4732
4714 default: 4733 default:
4715 { 4734 {
4716 s = BC_STATUS_PARSE_BAD_TOKEN; 4735 s = bc_error("bad token");
4717 break; 4736 break;
4718 } 4737 }
4719 } 4738 }
@@ -4726,9 +4745,9 @@ static BcStatus bc_parse_parse(BcParse *p)
4726 BcStatus s; 4745 BcStatus s;
4727 4746
4728 if (p->l.t.t == BC_LEX_EOF) 4747 if (p->l.t.t == BC_LEX_EOF)
4729 s = p->flags.len > 0 ? BC_STATUS_PARSE_NO_BLOCK_END : BC_STATUS_LEX_EOF; 4748 s = p->flags.len > 0 ? bc_error("block end could not be found") : bc_error("end of file");
4730 else if (p->l.t.t == BC_LEX_KEY_DEFINE) { 4749 else if (p->l.t.t == BC_LEX_KEY_DEFINE) {
4731 if (!BC_PARSE_CAN_EXEC(p)) return BC_STATUS_PARSE_BAD_TOKEN; 4750 if (!BC_PARSE_CAN_EXEC(p)) return bc_error("bad token");
4732 s = bc_parse_func(p); 4751 s = bc_parse_func(p);
4733 } 4752 }
4734 else 4753 else
@@ -4787,7 +4806,11 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
4787 prev != BC_INST_SCALE && prev != BC_INST_IBASE && 4806 prev != BC_INST_SCALE && prev != BC_INST_IBASE &&
4788 prev != BC_INST_OBASE && prev != BC_INST_LAST) 4807 prev != BC_INST_OBASE && prev != BC_INST_LAST)
4789 { 4808 {
4790 s = BC_STATUS_PARSE_BAD_ASSIGN; 4809 s = bc_error("bad assignment:"
4810 " left side must be scale,"
4811 " ibase, obase, last, var,"
4812 " or array element"
4813 );
4791 break; 4814 break;
4792 } 4815 }
4793 } 4816 }
@@ -4807,10 +4830,10 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
4807 case BC_LEX_OP_BOOL_OR: 4830 case BC_LEX_OP_BOOL_OR:
4808 case BC_LEX_OP_BOOL_AND: 4831 case BC_LEX_OP_BOOL_AND:
4809 { 4832 {
4810 if (((t == BC_LEX_OP_BOOL_NOT) != bin_last) || 4833 if (((t == BC_LEX_OP_BOOL_NOT) != bin_last)
4811 (t != BC_LEX_OP_BOOL_NOT && prev == BC_INST_BOOL_NOT)) 4834 || (t != BC_LEX_OP_BOOL_NOT && prev == BC_INST_BOOL_NOT)
4812 { 4835 ) {
4813 return BC_STATUS_PARSE_BAD_EXP; 4836 return bc_error("bad expression");
4814 } 4837 }
4815 4838
4816 nrelops += t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT; 4839 nrelops += t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT;
@@ -4824,8 +4847,8 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
4824 4847
4825 case BC_LEX_LPAREN: 4848 case BC_LEX_LPAREN:
4826 { 4849 {
4827 if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; 4850 if (BC_PARSE_LEAF(prev, rprn))
4828 4851 return bc_error("bad expression");
4829 ++nparens; 4852 ++nparens;
4830 paren_expr = rprn = bin_last = false; 4853 paren_expr = rprn = bin_last = false;
4831 get_token = true; 4854 get_token = true;
@@ -4837,7 +4860,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
4837 case BC_LEX_RPAREN: 4860 case BC_LEX_RPAREN:
4838 { 4861 {
4839 if (bin_last || prev == BC_INST_BOOL_NOT) 4862 if (bin_last || prev == BC_INST_BOOL_NOT)
4840 return BC_STATUS_PARSE_BAD_EXP; 4863 return bc_error("bad expression");
4841 4864
4842 if (nparens == 0) { 4865 if (nparens == 0) {
4843 s = BC_STATUS_SUCCESS; 4866 s = BC_STATUS_SUCCESS;
@@ -4859,8 +4882,8 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
4859 4882
4860 case BC_LEX_NAME: 4883 case BC_LEX_NAME:
4861 { 4884 {
4862 if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; 4885 if (BC_PARSE_LEAF(prev, rprn))
4863 4886 return bc_error("bad expression");
4864 paren_expr = true; 4887 paren_expr = true;
4865 rprn = get_token = bin_last = false; 4888 rprn = get_token = bin_last = false;
4866 s = bc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL); 4889 s = bc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL);
@@ -4871,8 +4894,8 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
4871 4894
4872 case BC_LEX_NUMBER: 4895 case BC_LEX_NUMBER:
4873 { 4896 {
4874 if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; 4897 if (BC_PARSE_LEAF(prev, rprn))
4875 4898 return bc_error("bad expression");
4876 bc_parse_number(p, &prev, &nexprs); 4899 bc_parse_number(p, &prev, &nexprs);
4877 paren_expr = get_token = true; 4900 paren_expr = get_token = true;
4878 rprn = bin_last = false; 4901 rprn = bin_last = false;
@@ -4884,8 +4907,8 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
4884 case BC_LEX_KEY_LAST: 4907 case BC_LEX_KEY_LAST:
4885 case BC_LEX_KEY_OBASE: 4908 case BC_LEX_KEY_OBASE:
4886 { 4909 {
4887 if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; 4910 if (BC_PARSE_LEAF(prev, rprn))
4888 4911 return bc_error("bad expression");
4889 prev = (char) (t - BC_LEX_KEY_IBASE + BC_INST_IBASE); 4912 prev = (char) (t - BC_LEX_KEY_IBASE + BC_INST_IBASE);
4890 bc_parse_push(p, (char) prev); 4913 bc_parse_push(p, (char) prev);
4891 4914
@@ -4899,8 +4922,8 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
4899 case BC_LEX_KEY_LENGTH: 4922 case BC_LEX_KEY_LENGTH:
4900 case BC_LEX_KEY_SQRT: 4923 case BC_LEX_KEY_SQRT:
4901 { 4924 {
4902 if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; 4925 if (BC_PARSE_LEAF(prev, rprn))
4903 4926 return bc_error("bad expression");
4904 s = bc_parse_builtin(p, t, flags, &prev); 4927 s = bc_parse_builtin(p, t, flags, &prev);
4905 paren_expr = true; 4928 paren_expr = true;
4906 rprn = get_token = bin_last = false; 4929 rprn = get_token = bin_last = false;
@@ -4912,9 +4935,9 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
4912 case BC_LEX_KEY_READ: 4935 case BC_LEX_KEY_READ:
4913 { 4936 {
4914 if (BC_PARSE_LEAF(prev, rprn)) 4937 if (BC_PARSE_LEAF(prev, rprn))
4915 return BC_STATUS_PARSE_BAD_EXP; 4938 return bc_error("bad expression");
4916 else if (flags & BC_PARSE_NOREAD) 4939 else if (flags & BC_PARSE_NOREAD)
4917 s = BC_STATUS_EXEC_REC_READ; 4940 s = bc_error("read() call inside of a read() call");
4918 else 4941 else
4919 s = bc_parse_read(p); 4942 s = bc_parse_read(p);
4920 4943
@@ -4928,8 +4951,8 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
4928 4951
4929 case BC_LEX_KEY_SCALE: 4952 case BC_LEX_KEY_SCALE:
4930 { 4953 {
4931 if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; 4954 if (BC_PARSE_LEAF(prev, rprn))
4932 4955 return bc_error("bad expression");
4933 s = bc_parse_scale(p, &prev, flags); 4956 s = bc_parse_scale(p, &prev, flags);
4934 paren_expr = true; 4957 paren_expr = true;
4935 rprn = get_token = bin_last = false; 4958 rprn = get_token = bin_last = false;
@@ -4941,7 +4964,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
4941 4964
4942 default: 4965 default:
4943 { 4966 {
4944 s = BC_STATUS_PARSE_BAD_TOKEN; 4967 s = bc_error("bad token");
4945 break; 4968 break;
4946 } 4969 }
4947 } 4970 }
@@ -4958,7 +4981,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
4958 assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN; 4981 assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN;
4959 4982
4960 if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN) 4983 if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN)
4961 return BC_STATUS_PARSE_BAD_EXP; 4984 return bc_error("bad expression");
4962 4985
4963 bc_parse_push(p, BC_PARSE_TOKEN_INST(top)); 4986 bc_parse_push(p, BC_PARSE_TOKEN_INST(top));
4964 4987
@@ -4966,11 +4989,14 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
4966 bc_vec_pop(&p->ops); 4989 bc_vec_pop(&p->ops);
4967 } 4990 }
4968 4991
4969 s = BC_STATUS_PARSE_BAD_EXP; 4992 if (prev == BC_INST_BOOL_NOT || nexprs != 1)
4970 if (prev == BC_INST_BOOL_NOT || nexprs != 1) return s; 4993 return bc_error("bad expression");
4971 4994
4972 for (i = 0; s && i < next.len; ++i) s *= t != next.tokens[i]; 4995 for (i = 0; i < next.len; ++i)
4973 if (s) return s; 4996 if (t == next.tokens[i])
4997 goto ok;
4998 return bc_error("bad expression");
4999 ok:
4974 5000
4975 if (!(flags & BC_PARSE_REL) && nrelops) { 5001 if (!(flags & BC_PARSE_REL) && nrelops) {
4976 s = bc_vm_posixError(BC_STATUS_POSIX_REL_POS, p->l.f, p->l.line, NULL); 5002 s = bc_vm_posixError(BC_STATUS_POSIX_REL_POS, p->l.f, p->l.line, NULL);
@@ -5008,7 +5034,7 @@ static BcStatus dc_parse_register(BcParse *p)
5008 5034
5009 s = bc_lex_next(&p->l); 5035 s = bc_lex_next(&p->l);
5010 if (s) return s; 5036 if (s) return s;
5011 if (p->l.t.t != BC_LEX_NAME) return BC_STATUS_PARSE_BAD_TOKEN; 5037 if (p->l.t.t != BC_LEX_NAME) return bc_error("bad token");
5012 5038
5013 name = xstrdup(p->l.t.v.v); 5039 name = xstrdup(p->l.t.v.v);
5014 bc_parse_pushName(p, name); 5040 bc_parse_pushName(p, name);
@@ -5115,7 +5141,8 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags)
5115 if (t == BC_LEX_NEG) { 5141 if (t == BC_LEX_NEG) {
5116 s = bc_lex_next(&p->l); 5142 s = bc_lex_next(&p->l);
5117 if (s) return s; 5143 if (s) return s;
5118 if (p->l.t.t != BC_LEX_NUMBER) return BC_STATUS_PARSE_BAD_TOKEN; 5144 if (p->l.t.t != BC_LEX_NUMBER)
5145 return bc_error("bad token");
5119 } 5146 }
5120 5147
5121 bc_parse_number(p, &prev, &p->nbraces); 5148 bc_parse_number(p, &prev, &p->nbraces);
@@ -5129,7 +5156,7 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags)
5129 case BC_LEX_KEY_READ: 5156 case BC_LEX_KEY_READ:
5130 { 5157 {
5131 if (flags & BC_PARSE_NOREAD) 5158 if (flags & BC_PARSE_NOREAD)
5132 s = BC_STATUS_EXEC_REC_READ; 5159 s = bc_error("read() call inside of a read() call");
5133 else 5160 else
5134 bc_parse_push(p, BC_INST_READ); 5161 bc_parse_push(p, BC_INST_READ);
5135 get_token = true; 5162 get_token = true;
@@ -5164,7 +5191,7 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags)
5164 5191
5165 default: 5192 default:
5166 { 5193 {
5167 s = BC_STATUS_PARSE_BAD_TOKEN; 5194 s = bc_error("bad token");
5168 get_token = true; 5195 get_token = true;
5169 break; 5196 break;
5170 } 5197 }
@@ -5206,7 +5233,7 @@ static BcStatus dc_parse_parse(BcParse *p)
5206 BcStatus s; 5233 BcStatus s;
5207 5234
5208 if (p->l.t.t == BC_LEX_EOF) 5235 if (p->l.t.t == BC_LEX_EOF)
5209 s = BC_STATUS_LEX_EOF; 5236 s = bc_error("end of file");
5210 else 5237 else
5211 s = dc_parse_expr(p, 0); 5238 s = dc_parse_expr(p, 0);
5212 5239
@@ -5349,7 +5376,8 @@ static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln,
5349 bool hex; 5376 bool hex;
5350 BcResultType lt, rt; 5377 BcResultType lt, rt;
5351 5378
5352 if (!BC_PROG_STACK(&G.prog.results, 2)) return BC_STATUS_EXEC_STACK; 5379 if (!BC_PROG_STACK(&G.prog.results, 2))
5380 return bc_error("stack has too few elements");
5353 5381
5354 *r = bc_vec_item_rev(&G.prog.results, 0); 5382 *r = bc_vec_item_rev(&G.prog.results, 0);
5355 *l = bc_vec_item_rev(&G.prog.results, 1); 5383 *l = bc_vec_item_rev(&G.prog.results, 1);
@@ -5371,8 +5399,9 @@ static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln,
5371 } 5399 }
5372 5400
5373 if (!BC_PROG_NUM((*l), (*ln)) && (!assign || (*l)->t != BC_RESULT_VAR)) 5401 if (!BC_PROG_NUM((*l), (*ln)) && (!assign || (*l)->t != BC_RESULT_VAR))
5374 return BC_STATUS_EXEC_BAD_TYPE; 5402 return bc_error("variable is wrong type");
5375 if (!assign && !BC_PROG_NUM((*r), (*ln))) return BC_STATUS_EXEC_BAD_TYPE; 5403 if (!assign && !BC_PROG_NUM((*r), (*ln)))
5404 return bc_error("variable is wrong type");
5376 5405
5377 return s; 5406 return s;
5378} 5407}
@@ -5389,13 +5418,15 @@ static BcStatus bc_program_prep(BcResult **r, BcNum **n)
5389{ 5418{
5390 BcStatus s; 5419 BcStatus s;
5391 5420
5392 if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; 5421 if (!BC_PROG_STACK(&G.prog.results, 1))
5422 return bc_error("stack has too few elements");
5393 *r = bc_vec_top(&G.prog.results); 5423 *r = bc_vec_top(&G.prog.results);
5394 5424
5395 s = bc_program_num(*r, n, false); 5425 s = bc_program_num(*r, n, false);
5396 if (s) return s; 5426 if (s) return s;
5397 5427
5398 if (!BC_PROG_NUM((*r), (*n))) return BC_STATUS_EXEC_BAD_TYPE; 5428 if (!BC_PROG_NUM((*r), (*n)))
5429 return bc_error("variable is wrong type");
5399 5430
5400 return s; 5431 return s;
5401} 5432}
@@ -5439,7 +5470,8 @@ static BcStatus bc_program_read(void)
5439 5470
5440 for (i = 0; i < G.prog.stack.len; ++i) { 5471 for (i = 0; i < G.prog.stack.len; ++i) {
5441 BcInstPtr *ip_ptr = bc_vec_item(&G.prog.stack, i); 5472 BcInstPtr *ip_ptr = bc_vec_item(&G.prog.stack, i);
5442 if (ip_ptr->func == BC_PROG_READ) return BC_STATUS_EXEC_REC_READ; 5473 if (ip_ptr->func == BC_PROG_READ)
5474 return bc_error("read() call inside of a read() call");
5443 } 5475 }
5444 5476
5445 bc_vec_npop(&f->code, f->code.len); 5477 bc_vec_npop(&f->code, f->code.len);
@@ -5457,7 +5489,7 @@ static BcStatus bc_program_read(void)
5457 if (s) goto exec_err; 5489 if (s) goto exec_err;
5458 5490
5459 if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != BC_LEX_EOF) { 5491 if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != BC_LEX_EOF) {
5460 s = BC_STATUS_EXEC_BAD_READ_EXPR; 5492 s = bc_error("bad read() expression");
5461 goto exec_err; 5493 goto exec_err;
5462 } 5494 }
5463 5495
@@ -5600,7 +5632,8 @@ static BcStatus bc_program_print(char inst, size_t idx)
5600 BcNum *num = NULL; 5632 BcNum *num = NULL;
5601 bool pop = inst != BC_INST_PRINT; 5633 bool pop = inst != BC_INST_PRINT;
5602 5634
5603 if (!BC_PROG_STACK(&G.prog.results, idx + 1)) return BC_STATUS_EXEC_STACK; 5635 if (!BC_PROG_STACK(&G.prog.results, idx + 1))
5636 return bc_error("stack has too few elements");
5604 5637
5605 r = bc_vec_item_rev(&G.prog.results, idx); 5638 r = bc_vec_item_rev(&G.prog.results, idx);
5606 s = bc_program_num(r, &num, false); 5639 s = bc_program_num(r, &num, false);
@@ -5731,7 +5764,8 @@ static BcStatus bc_program_assignStr(BcResult *r, BcVec *v,
5731 res.t = BC_RESULT_STR; 5764 res.t = BC_RESULT_STR;
5732 5765
5733 if (!push) { 5766 if (!push) {
5734 if (!BC_PROG_STACK(&G.prog.results, 2)) return BC_STATUS_EXEC_STACK; 5767 if (!BC_PROG_STACK(&G.prog.results, 2))
5768 return bc_error("stack has too few elements");
5735 bc_vec_pop(v); 5769 bc_vec_pop(v);
5736 bc_vec_pop(&G.prog.results); 5770 bc_vec_pop(&G.prog.results);
5737 } 5771 }
@@ -5752,14 +5786,17 @@ static BcStatus bc_program_copyToVar(char *name, bool var)
5752 BcVec *v; 5786 BcVec *v;
5753 BcNum *n; 5787 BcNum *n;
5754 5788
5755 if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; 5789 if (!BC_PROG_STACK(&G.prog.results, 1))
5790 return bc_error("stack has too few elements");
5756 5791
5757 ptr = bc_vec_top(&G.prog.results); 5792 ptr = bc_vec_top(&G.prog.results);
5758 if ((ptr->t == BC_RESULT_ARRAY) != !var) return BC_STATUS_EXEC_BAD_TYPE; 5793 if ((ptr->t == BC_RESULT_ARRAY) != !var)
5794 return bc_error("variable is wrong type");
5759 v = bc_program_search(name, var); 5795 v = bc_program_search(name, var);
5760 5796
5761#if ENABLE_DC 5797#if ENABLE_DC
5762 if (ptr->t == BC_RESULT_STR && !var) return BC_STATUS_EXEC_BAD_TYPE; 5798 if (ptr->t == BC_RESULT_STR && !var)
5799 return bc_error("variable is wrong type");
5763 if (ptr->t == BC_RESULT_STR) return bc_program_assignStr(ptr, v, true); 5800 if (ptr->t == BC_RESULT_STR) return bc_program_assignStr(ptr, v, true);
5764#endif 5801#endif
5765 5802
@@ -5804,7 +5841,8 @@ static BcStatus bc_program_assign(char inst)
5804 5841
5805 BcVec *v; 5842 BcVec *v;
5806 5843
5807 if (left->t != BC_RESULT_VAR) return BC_STATUS_EXEC_BAD_TYPE; 5844 if (left->t != BC_RESULT_VAR)
5845 return bc_error("variable is wrong type");
5808 v = bc_program_search(left->d.id.name, true); 5846 v = bc_program_search(left->d.id.name, true);
5809 5847
5810 return bc_program_assignStr(right, v, false); 5848 return bc_program_assignStr(right, v, false);
@@ -5812,11 +5850,15 @@ static BcStatus bc_program_assign(char inst)
5812#endif 5850#endif
5813 5851
5814 if (left->t == BC_RESULT_CONSTANT || left->t == BC_RESULT_TEMP) 5852 if (left->t == BC_RESULT_CONSTANT || left->t == BC_RESULT_TEMP)
5815 return BC_STATUS_PARSE_BAD_ASSIGN; 5853 return bc_error("bad assignment:"
5854 " left side must be scale,"
5855 " ibase, obase, last, var,"
5856 " or array element"
5857 );
5816 5858
5817#if ENABLE_BC 5859#if ENABLE_BC
5818 if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &G.prog.zero)) 5860 if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &G.prog.zero))
5819 return BC_STATUS_MATH_DIVIDE_BY_ZERO; 5861 return bc_error("divide by zero");
5820 5862
5821 if (assign) 5863 if (assign)
5822 bc_num_copy(l, r); 5864 bc_num_copy(l, r);
@@ -5829,25 +5871,35 @@ static BcStatus bc_program_assign(char inst)
5829#endif 5871#endif
5830 5872
5831 if (ib || sc || left->t == BC_RESULT_OBASE) { 5873 if (ib || sc || left->t == BC_RESULT_OBASE) {
5832 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 };
5833 size_t *ptr; 5882 size_t *ptr;
5834 5883
5835 s = bc_num_ulong(l, &val); 5884 s = bc_num_ulong(l, &val);
5836 if (s) return s; 5885 if (s)
5837 s = left->t - BC_RESULT_IBASE + BC_STATUS_EXEC_BAD_IBASE; 5886 return s;
5838 5887 s = left->t - BC_RESULT_IBASE;
5839 if (sc) { 5888 if (sc) {
5840 max = BC_MAX_SCALE; 5889 max = BC_MAX_SCALE;
5841 ptr = &G.prog.scale; 5890 ptr = &G.prog.scale;
5842 } 5891 }
5843 else { 5892 else {
5844 if (val < BC_NUM_MIN_BASE) return s; 5893 if (val < BC_NUM_MIN_BASE)
5894 return bc_error(msg[s]);
5845 max = ib ? BC_NUM_MAX_IBASE : BC_MAX_OBASE; 5895 max = ib ? BC_NUM_MAX_IBASE : BC_MAX_OBASE;
5846 ptr = ib ? &G.prog.ib_t : &G.prog.ob_t; 5896 ptr = ib ? &G.prog.ib_t : &G.prog.ob_t;
5847 } 5897 }
5848 5898
5849 if (val > max) return s; 5899 if (val > max)
5850 if (!sc) bc_num_copy(ib ? &G.prog.ib : &G.prog.ob, l); 5900 return bc_error(msg[s]);
5901 if (!sc)
5902 bc_num_copy(ib ? &G.prog.ib : &G.prog.ob, l);
5851 5903
5852 *ptr = (size_t) val; 5904 *ptr = (size_t) val;
5853 s = BC_STATUS_SUCCESS; 5905 s = BC_STATUS_SUCCESS;
@@ -5884,7 +5936,7 @@ static BcStatus bc_program_pushVar(char *code, size_t *bgn,
5884 5936
5885 if (!BC_PROG_STACK(v, 2 - copy)) { 5937 if (!BC_PROG_STACK(v, 2 - copy)) {
5886 free(name); 5938 free(name);
5887 return BC_STATUS_EXEC_STACK; 5939 return bc_error("stack has too few elements");
5888 } 5940 }
5889 5941
5890 free(name); 5942 free(name);
@@ -5936,7 +5988,7 @@ static BcStatus bc_program_pushArray(char *code, size_t *bgn,
5936 if (s) goto err; 5988 if (s) goto err;
5937 5989
5938 if (temp > BC_MAX_DIM) { 5990 if (temp > BC_MAX_DIM) {
5939 s = BC_STATUS_EXEC_ARRAY_LEN; 5991 s = bc_error("array too long; must be [1, BC_DIM_MAX]");
5940 goto err; 5992 goto err;
5941 } 5993 }
5942 5994
@@ -6010,7 +6062,7 @@ static BcStatus bc_program_call(char *code, size_t *idx)
6010 arg = bc_vec_top(&G.prog.results); 6062 arg = bc_vec_top(&G.prog.results);
6011 6063
6012 if ((!a->idx) != (arg->t == BC_RESULT_ARRAY) || arg->t == BC_RESULT_STR) 6064 if ((!a->idx) != (arg->t == BC_RESULT_ARRAY) || arg->t == BC_RESULT_STR)
6013 return BC_STATUS_EXEC_BAD_TYPE; 6065 return bc_error("variable is wrong type");
6014 6066
6015 s = bc_program_copyToVar(a->name, a->idx); 6067 s = bc_program_copyToVar(a->name, a->idx);
6016 if (s) return s; 6068 if (s) return s;
@@ -6046,7 +6098,7 @@ static BcStatus bc_program_return(char inst)
6046 BcInstPtr *ip = bc_vec_top(&G.prog.stack); 6098 BcInstPtr *ip = bc_vec_top(&G.prog.stack);
6047 6099
6048 if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET)) 6100 if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET))
6049 return BC_STATUS_EXEC_STACK; 6101 return bc_error("stack has too few elements");
6050 6102
6051 f = bc_vec_item(&G.prog.fns, ip->func); 6103 f = bc_vec_item(&G.prog.fns, ip->func);
6052 res.t = BC_RESULT_TEMP; 6104 res.t = BC_RESULT_TEMP;
@@ -6108,14 +6160,16 @@ static BcStatus bc_program_builtin(char inst)
6108 BcResult res; 6160 BcResult res;
6109 bool len = inst == BC_INST_LENGTH; 6161 bool len = inst == BC_INST_LENGTH;
6110 6162
6111 if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; 6163 if (!BC_PROG_STACK(&G.prog.results, 1))
6164 return bc_error("stack has too few elements");
6112 opnd = bc_vec_top(&G.prog.results); 6165 opnd = bc_vec_top(&G.prog.results);
6113 6166
6114 s = bc_program_num(opnd, &num, false); 6167 s = bc_program_num(opnd, &num, false);
6115 if (s) return s; 6168 if (s) return s;
6116 6169
6117#if ENABLE_DC 6170#if ENABLE_DC
6118 if (!BC_PROG_NUM(opnd, num) && !len) return BC_STATUS_EXEC_BAD_TYPE; 6171 if (!BC_PROG_NUM(opnd, num) && !len)
6172 return bc_error("variable is wrong type");
6119#endif 6173#endif
6120 6174
6121 bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); 6175 bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
@@ -6180,14 +6234,16 @@ static BcStatus bc_program_modexp(void)
6180 BcResult *r1, *r2, *r3, res; 6234 BcResult *r1, *r2, *r3, res;
6181 BcNum *n1, *n2, *n3; 6235 BcNum *n1, *n2, *n3;
6182 6236
6183 if (!BC_PROG_STACK(&G.prog.results, 3)) return BC_STATUS_EXEC_STACK; 6237 if (!BC_PROG_STACK(&G.prog.results, 3))
6238 return bc_error("stack has too few elements");
6184 s = bc_program_binOpPrep(&r2, &n2, &r3, &n3, false); 6239 s = bc_program_binOpPrep(&r2, &n2, &r3, &n3, false);
6185 if (s) return s; 6240 if (s) return s;
6186 6241
6187 r1 = bc_vec_item_rev(&G.prog.results, 2); 6242 r1 = bc_vec_item_rev(&G.prog.results, 2);
6188 s = bc_program_num(r1, &n1, false); 6243 s = bc_program_num(r1, &n1, false);
6189 if (s) return s; 6244 if (s) return s;
6190 if (!BC_PROG_NUM(r1, n1)) return BC_STATUS_EXEC_BAD_TYPE; 6245 if (!BC_PROG_NUM(r1, n1))
6246 return bc_error("variable is wrong type");
6191 6247
6192 // Make sure that the values have their pointers updated, if necessary. 6248 // Make sure that the values have their pointers updated, if necessary.
6193 if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) { 6249 if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) {
@@ -6238,7 +6294,8 @@ static BcStatus bc_program_asciify(void)
6238 size_t len = G.prog.strs.len, idx; 6294 size_t len = G.prog.strs.len, idx;
6239 unsigned long val; 6295 unsigned long val;
6240 6296
6241 if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; 6297 if (!BC_PROG_STACK(&G.prog.results, 1))
6298 return bc_error("stack has too few elements");
6242 r = bc_vec_top(&G.prog.results); 6299 r = bc_vec_top(&G.prog.results);
6243 6300
6244 s = bc_program_num(r, &num, false); 6301 s = bc_program_num(r, &num, false);
@@ -6306,7 +6363,8 @@ static BcStatus bc_program_printStream(void)
6306 size_t idx; 6363 size_t idx;
6307 char *str; 6364 char *str;
6308 6365
6309 if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; 6366 if (!BC_PROG_STACK(&G.prog.results, 1))
6367 return bc_error("stack has too few elements");
6310 r = bc_vec_top(&G.prog.results); 6368 r = bc_vec_top(&G.prog.results);
6311 6369
6312 s = bc_program_num(r, &n, false); 6370 s = bc_program_num(r, &n, false);
@@ -6338,7 +6396,7 @@ static BcStatus bc_program_nquit(void)
6338 bc_vec_pop(&G.prog.results); 6396 bc_vec_pop(&G.prog.results);
6339 6397
6340 if (G.prog.stack.len < val) 6398 if (G.prog.stack.len < val)
6341 return BC_STATUS_EXEC_STACK; 6399 return bc_error("stack has too few elements");
6342 if (G.prog.stack.len == val) 6400 if (G.prog.stack.len == val)
6343 quit(); 6401 quit();
6344 6402
@@ -6360,7 +6418,8 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn,
6360 BcNum *n; 6418 BcNum *n;
6361 bool exec; 6419 bool exec;
6362 6420
6363 if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; 6421 if (!BC_PROG_STACK(&G.prog.results, 1))
6422 return bc_error("stack has too few elements");
6364 6423
6365 r = bc_vec_top(&G.prog.results); 6424 r = bc_vec_top(&G.prog.results);
6366 6425
@@ -6393,7 +6452,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn,
6393 6452
6394 if (!exec) goto exit; 6453 if (!exec) goto exit;
6395 if (!BC_PROG_STR(n)) { 6454 if (!BC_PROG_STR(n)) {
6396 s = BC_STATUS_EXEC_BAD_TYPE; 6455 s = bc_error("variable is wrong type");
6397 goto exit; 6456 goto exit;
6398 } 6457 }
6399 6458
@@ -6425,7 +6484,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn,
6425 if (s) goto err; 6484 if (s) goto err;
6426 6485
6427 if (prs.l.t.t != BC_LEX_EOF) { 6486 if (prs.l.t.t != BC_LEX_EOF) {
6428 s = BC_STATUS_PARSE_BAD_EXP; 6487 s = bc_error("bad expression");
6429 goto err; 6488 goto err;
6430 } 6489 }
6431 6490
@@ -6652,7 +6711,7 @@ static BcStatus bc_program_exec(void)
6652 case BC_INST_POP: 6711 case BC_INST_POP:
6653 { 6712 {
6654 if (!BC_PROG_STACK(&G.prog.results, 1)) 6713 if (!BC_PROG_STACK(&G.prog.results, 1))
6655 s = BC_STATUS_EXEC_STACK; 6714 s = bc_error("stack has too few elements");
6656 else 6715 else
6657 bc_vec_pop(&G.prog.results); 6716 bc_vec_pop(&G.prog.results);
6658 break; 6717 break;
@@ -6764,7 +6823,8 @@ static BcStatus bc_program_exec(void)
6764 6823
6765 case BC_INST_DUPLICATE: 6824 case BC_INST_DUPLICATE:
6766 { 6825 {
6767 if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; 6826 if (!BC_PROG_STACK(&G.prog.results, 1))
6827 return bc_error("stack has too few elements");
6768 ptr = bc_vec_top(&G.prog.results); 6828 ptr = bc_vec_top(&G.prog.results);
6769 bc_result_copy(&r, ptr); 6829 bc_result_copy(&r, ptr);
6770 bc_vec_push(&G.prog.results, &r); 6830 bc_vec_push(&G.prog.results, &r);
@@ -6775,7 +6835,8 @@ static BcStatus bc_program_exec(void)
6775 { 6835 {
6776 BcResult *ptr2; 6836 BcResult *ptr2;
6777 6837
6778 if (!BC_PROG_STACK(&G.prog.results, 2)) return BC_STATUS_EXEC_STACK; 6838 if (!BC_PROG_STACK(&G.prog.results, 2))
6839 return bc_error("stack has too few elements");
6779 6840
6780 ptr = bc_vec_item_rev(&G.prog.results, 0); 6841 ptr = bc_vec_item_rev(&G.prog.results, 0);
6781 ptr2 = bc_vec_item_rev(&G.prog.results, 1); 6842 ptr2 = bc_vec_item_rev(&G.prog.results, 1);
@@ -6863,6 +6924,7 @@ static BcStatus bc_vm_error(BcStatus s, const char *file, size_t line)
6863 fprintf(stderr, bc_err_line + 4 * !line, line); 6924 fprintf(stderr, bc_err_line + 4 * !line, line);
6864 } 6925 }
6865 6926
6927///
6866 return s * (!G.ttyin || !!strcmp(file, bc_program_stdin_name)); 6928 return s * (!G.ttyin || !!strcmp(file, bc_program_stdin_name));
6867} 6929}
6868 6930
@@ -6983,7 +7045,8 @@ static BcStatus bc_vm_file(const char *file)
6983 main_func = bc_vec_item(&G.prog.fns, BC_PROG_MAIN); 7045 main_func = bc_vec_item(&G.prog.fns, BC_PROG_MAIN);
6984 ip = bc_vec_item(&G.prog.stack, 0); 7046 ip = bc_vec_item(&G.prog.stack, 0);
6985 7047
6986 if (main_func->code.len < ip->idx) s = BC_STATUS_EXEC_FILE_NOT_EXECUTABLE; 7048 if (main_func->code.len < ip->idx)
7049 s = bc_error("file '%s' is not executable", file);
6987 7050
6988err: 7051err:
6989 free(data); 7052 free(data);
@@ -7057,12 +7120,16 @@ static BcStatus bc_vm_stdin(void)
7057 bc_vec_npop(&buffer, buffer.len); 7120 bc_vec_npop(&buffer, buffer.len);
7058 } 7121 }
7059 7122
7060 if (str) 7123 if (str) {
7061 s = bc_vm_error(BC_STATUS_LEX_NO_STRING_END, G.prs.l.f, 7124 bc_error("string end could not be found");
7125 s = bc_vm_error(BC_STATUS_FAILURE, G.prs.l.f,
7062 G.prs.l.line); 7126 G.prs.l.line);
7063 else if (comment) 7127 }
7064 s = bc_vm_error(BC_STATUS_LEX_NO_COMMENT_END, G.prs.l.f, 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,
7065 G.prs.l.line); 7131 G.prs.l.line);
7132 }
7066 7133
7067err: 7134err:
7068 bc_vec_free(&buf); 7135 bc_vec_free(&buf);