diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-04 20:05:28 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-05 15:43:35 +0100 |
| commit | 60cf747b6c234958387298068da658cfee9c42cb (patch) | |
| tree | 1cd11d916fc420266dc11e98a9af867dcc7330d9 /miscutils | |
| parent | d38af48e0ae96fc4dc4a794ae8129372ed7c593f (diff) | |
| download | busybox-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>
Diffstat (limited to 'miscutils')
| -rw-r--r-- | miscutils/bc.c | 475 |
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 | ||
| 170 | typedef enum BcStatus { | 170 | typedef 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 { | |||
| 242 | static const char *const bc_err_msgs[] = { | 242 | static 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, | |||
| 1577 | static BcStatus bc_num_shift(BcNum *n, size_t places) | 1578 | static 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) | |||
| 2435 | static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, | 2438 | static 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 | ||
| 6988 | err: | 7051 | err: |
| 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 | ||
| 7067 | err: | 7134 | err: |
| 7068 | bc_vec_free(&buf); | 7135 | bc_vec_free(&buf); |
