diff options
-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 @@ #include "libbb.h" typedef enum BcStatus { - BC_STATUS_SUCCESS, - BC_STATUS_FAILURE, + BC_STATUS_SUCCESS = 0, + BC_STATUS_FAILURE = 1, + BC_STATUS_PARSE_EMPTY_EXP = 2, // bc_parse_expr() uses this // BC_STATUS_ALLOC_ERR, // BC_STATUS_INPUT_EOF, @@ -177,48 +178,47 @@ typedef enum BcStatus { // BC_STATUS_PATH_IS_DIR, // BC_STATUS_LEX_BAD_CHAR, - BC_STATUS_LEX_NO_STRING_END, - BC_STATUS_LEX_NO_COMMENT_END, - BC_STATUS_LEX_EOF, +// BC_STATUS_LEX_NO_STRING_END, +// BC_STATUS_LEX_NO_COMMENT_END, +// BC_STATUS_LEX_EOF, #if ENABLE_DC - BC_STATUS_LEX_EXTENDED_REG, +// BC_STATUS_LEX_EXTENDED_REG, #endif - BC_STATUS_PARSE_BAD_TOKEN, - BC_STATUS_PARSE_BAD_EXP, - BC_STATUS_PARSE_EMPTY_EXP, - BC_STATUS_PARSE_BAD_PRINT, - BC_STATUS_PARSE_BAD_FUNC, - BC_STATUS_PARSE_BAD_ASSIGN, +// BC_STATUS_PARSE_BAD_TOKEN, +// BC_STATUS_PARSE_BAD_EXP, +// BC_STATUS_PARSE_BAD_PRINT, +// BC_STATUS_PARSE_BAD_FUNC, +// BC_STATUS_PARSE_BAD_ASSIGN, // BC_STATUS_PARSE_NO_AUTO, - BC_STATUS_PARSE_DUPLICATE_LOCAL, - BC_STATUS_PARSE_NO_BLOCK_END, +// BC_STATUS_PARSE_DUPLICATE_LOCAL, +// BC_STATUS_PARSE_NO_BLOCK_END, - BC_STATUS_MATH_NEGATIVE, - BC_STATUS_MATH_NON_INTEGER, - BC_STATUS_MATH_OVERFLOW, - BC_STATUS_MATH_DIVIDE_BY_ZERO, - BC_STATUS_MATH_BAD_STRING, +// BC_STATUS_MATH_NEGATIVE, +// BC_STATUS_MATH_NON_INTEGER, +// BC_STATUS_MATH_OVERFLOW, +// BC_STATUS_MATH_DIVIDE_BY_ZERO, +// BC_STATUS_MATH_BAD_STRING, // BC_STATUS_EXEC_FILE_ERR, // BC_STATUS_EXEC_MISMATCHED_PARAMS, // BC_STATUS_EXEC_UNDEFINED_FUNC, - BC_STATUS_EXEC_FILE_NOT_EXECUTABLE, - BC_STATUS_EXEC_NUM_LEN, - BC_STATUS_EXEC_NAME_LEN, - BC_STATUS_EXEC_STRING_LEN, - BC_STATUS_EXEC_ARRAY_LEN, - BC_STATUS_EXEC_BAD_IBASE, +// BC_STATUS_EXEC_FILE_NOT_EXECUTABLE, +// BC_STATUS_EXEC_NUM_LEN, +// BC_STATUS_EXEC_NAME_LEN, +// BC_STATUS_EXEC_STRING_LEN, +// BC_STATUS_EXEC_ARRAY_LEN, +// BC_STATUS_EXEC_BAD_IBASE, // BC_STATUS_EXEC_BAD_SCALE, - BC_STATUS_EXEC_BAD_READ_EXPR, - BC_STATUS_EXEC_REC_READ, - BC_STATUS_EXEC_BAD_TYPE, +// BC_STATUS_EXEC_BAD_READ_EXPR, +// BC_STATUS_EXEC_REC_READ, +// BC_STATUS_EXEC_BAD_TYPE, // BC_STATUS_EXEC_BAD_OBASE, // BC_STATUS_EXEC_SIGNAL, - BC_STATUS_EXEC_STACK, +// BC_STATUS_EXEC_STACK, // BC_STATUS_VEC_OUT_OF_BOUNDS, // BC_STATUS_VEC_ITEM_EXISTS, - BC_STATUS_BEFORE_POSIX = BC_STATUS_EXEC_STACK, + BC_STATUS_BEFORE_POSIX = BC_STATUS_PARSE_EMPTY_EXP, #if ENABLE_BC BC_STATUS_POSIX_NAME_LEN, BC_STATUS_POSIX_COMMENT, @@ -242,51 +242,52 @@ typedef enum BcStatus { static const char *const bc_err_msgs[] = { NULL, NULL, + NULL, + // "memory allocation error", // "I/O error", // "file is not text:", // "path is a directory:", // "bad character", - "string end could not be found", - "comment end could not be found", - "end of file", +// "string end could not be found", +// "comment end could not be found", +// "end of file", #if ENABLE_DC - "extended register", +// "extended register", #endif - "bad token", - "bad expression", - "empty expression", - "bad print statement", - "bad function definition", - "bad assignment: left side must be scale, ibase, " - "obase, last, var, or array element", +// "bad token", +// "bad expression", +// "bad print statement", +// "bad function definition", +// "bad assignment: left side must be scale, ibase, " +// "obase, last, var, or array element", // "no auto variable found", - "function parameter or auto var has the same name as another", - "block end could not be found", +// "function parameter or auto var has the same name as another", +// "block end could not be found", - "negative number", - "non integer number", - "overflow", - "divide by zero", - "bad number string", +// "negative number", +// "non integer number", +// "overflow", +// "divide by zero", +// "bad number string", // "could not open file:", // "mismatched parameters", // wrong number of them, to be exact // "undefined function", - "file is not executable:", - "number too long: must be [1, BC_NUM_MAX]", - "name too long: must be [1, BC_NAME_MAX]", - "string too long: must be [1, BC_STRING_MAX]", - "array too long; must be [1, BC_DIM_MAX]", - "bad ibase; must be [2, 16]", +// "file is not executable:", +// "number too long: must be [1, BC_NUM_MAX]", +// "name too long: must be [1, BC_NAME_MAX]", +// "string too long: must be [1, BC_STRING_MAX]", +// "array too long; must be [1, BC_DIM_MAX]", +// "bad ibase; must be [2, 16]", // "bad scale; must be [0, BC_SCALE_MAX]", - "bad read() expression", - "read() call inside of a read() call", - "variable is wrong type", +// "bad read() expression", +// "read() call inside of a read() call", +// "variable is wrong type", // "bad obase; must be [2, BC_BASE_MAX]", // "signal caught and not handled", - "stack has too few elements", +// "stack has too few elements", // "index is out of bounds", // "item already exists", @@ -1577,7 +1578,8 @@ static void bc_num_split(BcNum *restrict n, size_t idx, BcNum *restrict a, static BcStatus bc_num_shift(BcNum *n, size_t places) { if (places == 0 || n->len == 0) return BC_STATUS_SUCCESS; - if (places + n->len > BC_MAX_NUM) return BC_STATUS_EXEC_NUM_LEN; + if (places + n->len > BC_MAX_NUM) + return bc_error("number too long: must be [1, BC_NUM_MAX]"); if (n->rdx >= places) n->rdx -= places; @@ -1885,7 +1887,7 @@ static BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) bool zero = true; if (b->len == 0) - return BC_STATUS_MATH_DIVIDE_BY_ZERO; + return bc_error("divide by zero"); else if (a->len == 0) { bc_num_setToZero(c, scale); return BC_STATUS_SUCCESS; @@ -1948,7 +1950,8 @@ static BcStatus bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, BcNum temp; bool neg; - if (b->len == 0) return BC_STATUS_MATH_DIVIDE_BY_ZERO; + if (b->len == 0) + return bc_error("divide by zero"); if (a->len == 0) { bc_num_setToZero(d, ts); @@ -1997,7 +2000,7 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) size_t i, powrdx, resrdx; bool neg, zero; - if (b->rdx) return BC_STATUS_MATH_NON_INTEGER; + if (b->rdx) return bc_error("non integer number"); if (b->len == 0) { bc_num_one(c); @@ -2435,7 +2438,8 @@ static void bc_num_copy(BcNum *d, BcNum *s) static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, size_t base_t) { - if (!bc_num_strValid(val, base_t)) return BC_STATUS_MATH_BAD_STRING; + if (!bc_num_strValid(val, base_t)) + return bc_error("bad number string"); if (base_t == 10) bc_num_parseDecimal(n, val); @@ -2474,7 +2478,7 @@ static BcStatus bc_num_ulong(BcNum *n, unsigned long *result) size_t i; unsigned long pow; - if (n->neg) return BC_STATUS_MATH_NEGATIVE; + if (n->neg) return bc_error("negative number"); for (*result = 0, pow = 1, i = n->rdx; i < n->len; ++i) { @@ -2483,7 +2487,8 @@ static BcStatus bc_num_ulong(BcNum *n, unsigned long *result) *result += ((unsigned long) n->num[i]) * pow; pow *= 10; - if (*result < prev || pow < powprev) return BC_STATUS_MATH_OVERFLOW; + if (*result < prev || pow < powprev) + return bc_error("overflow"); } return BC_STATUS_SUCCESS; @@ -2555,7 +2560,7 @@ static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) return BC_STATUS_SUCCESS; } else if (a->neg) - return BC_STATUS_MATH_NEGATIVE; + return bc_error("negative number"); else if (BC_NUM_ONE(a)) { bc_num_one(b); bc_num_extend(b, scale); @@ -2674,9 +2679,12 @@ static BcStatus bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) BcStatus s; BcNum base, exp, two, temp; - if (c->len == 0) return BC_STATUS_MATH_DIVIDE_BY_ZERO; - if (a->rdx || b->rdx || c->rdx) return BC_STATUS_MATH_NON_INTEGER; - if (b->neg) return BC_STATUS_MATH_NEGATIVE; + if (c->len == 0) + return bc_error("divide by zero"); + if (a->rdx || b->rdx || c->rdx) + return bc_error("non integer number"); + if (b->neg) + return bc_error("negative number"); bc_num_expand(d, c->len); bc_num_init(&base, c->len); @@ -2735,8 +2743,8 @@ static BcStatus bc_func_insert(BcFunc *f, char *name, bool var) size_t i; for (i = 0; i < f->autos.len; ++i) { - if (!strcmp(name, ((BcId *) bc_vec_item(&f->autos, i))->name)) - return BC_STATUS_PARSE_DUPLICATE_LOCAL; + if (strcmp(name, ((BcId *) bc_vec_item(&f->autos, i))->name) == 0) + return bc_error("function parameter or auto var has the same name as another"); } a.idx = var; @@ -2918,7 +2926,8 @@ static BcStatus bc_lex_number(BcLex *l, char start) } len = i + 1 * !last_pt - bslashes * 2; - if (len > BC_MAX_NUM) return BC_STATUS_EXEC_NUM_LEN; + if (len > BC_MAX_NUM) + return bc_error("number too long: must be [1, BC_NUM_MAX]"); bc_vec_npop(&l->t.v, l->t.v.len); bc_vec_expand(&l->t.v, len + 1); @@ -2955,7 +2964,8 @@ static BcStatus bc_lex_name(BcLex *l) while ((c >= 'a' && c <= 'z') || isdigit(c) || c == '_') c = buf[++i]; - if (i > BC_MAX_STRING) return BC_STATUS_EXEC_NAME_LEN; + if (i > BC_MAX_STRING) + return bc_error("name too long: must be [1, BC_NAME_MAX]"); bc_vec_string(&l->t.v, i, buf); // Increment the index. We minus 1 because it has already been incremented. @@ -2987,7 +2997,7 @@ static BcStatus bc_lex_next(BcLex *l) BcStatus s; l->t.last = l->t.t; - if (l->t.last == BC_LEX_EOF) return BC_STATUS_LEX_EOF; + if (l->t.last == BC_LEX_EOF) return bc_error("end of file"); l->line += l->newline; l->t.t = BC_LEX_EOF; @@ -3060,11 +3070,12 @@ static BcStatus bc_lex_string(BcLex *l) if (c == '\0') { l->i = i; - return BC_STATUS_LEX_NO_STRING_END; + return bc_error("string end could not be found"); } len = i - l->i; - if (len > BC_MAX_STRING) return BC_STATUS_EXEC_STRING_LEN; + if (len > BC_MAX_STRING) + return bc_error("string too long: must be [1, BC_STRING_MAX]"); bc_vec_string(&l->t.v, len, l->buf + l->i); l->i = i + 1; @@ -3101,7 +3112,7 @@ static BcStatus bc_lex_comment(BcLex *l) } if (c == '\0') { l->i = i; - return BC_STATUS_LEX_NO_COMMENT_END; + return bc_error("comment end could not be found"); } nls += (c == '\n'); i++; @@ -3404,7 +3415,7 @@ static BcStatus dc_lex_register(BcLex *l) bc_lex_whitespace(l); ++l->i; if (!G_exreg) - s = BC_STATUS_LEX_EXTENDED_REG; + s = bc_error("extended register"); else s = bc_lex_name(l); } @@ -3437,11 +3448,12 @@ static BcStatus dc_lex_string(BcLex *l) if (c == '\0') { l->i = i; - return BC_STATUS_LEX_NO_STRING_END; + return bc_error("string end could not be found"); } bc_vec_pushByte(&l->t.v, '\0'); - if (i - l->i > BC_MAX_STRING) return BC_STATUS_EXEC_STRING_LEN; + if (i - l->i > BC_MAX_STRING) + return bc_error("string too long: must be [1, BC_STRING_MAX]"); l->i = i; l->line += nls; @@ -3606,11 +3618,12 @@ static BcStatus bc_parse_text(BcParse *p, const char *text) p->func = bc_vec_item(&G.prog.fns, p->fidx); - if (!strcmp(text, "") && !BC_PARSE_CAN_EXEC(p)) { + if (!text[0] && !BC_PARSE_CAN_EXEC(p)) { p->l.t.t = BC_LEX_INVALID; s = p->parse(p); if (s) return s; - if (!BC_PARSE_CAN_EXEC(p)) return BC_STATUS_EXEC_FILE_NOT_EXECUTABLE; + if (!BC_PARSE_CAN_EXEC(p)) + return bc_error("file is not executable"); } 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) { BcLexType top; - if (p->ops.len <= ops_bgn) return BC_STATUS_PARSE_BAD_EXP; + if (p->ops.len <= ops_bgn) + return bc_error("bad expression"); top = BC_PARSE_TOP_OP(p); while (top != BC_LEX_LPAREN) { @@ -3713,7 +3727,8 @@ static BcStatus bc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) bc_vec_pop(&p->ops); *nexs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG; - if (p->ops.len <= ops_bgn) return BC_STATUS_PARSE_BAD_EXP; + if (p->ops.len <= ops_bgn) + return bc_error("bad expression"); top = BC_PARSE_TOP_OP(p); } @@ -3744,7 +3759,7 @@ static BcStatus bc_parse_params(BcParse *p, uint8_t flags) } } - if (comma) return BC_STATUS_PARSE_BAD_TOKEN; + if (comma) return bc_error("bad token"); bc_parse_push(p, BC_INST_CALL); bc_parse_pushIndex(p, nparams); @@ -3763,7 +3778,7 @@ static BcStatus bc_parse_call(BcParse *p, char *name, uint8_t flags) if (s) goto err; if (p->l.t.t != BC_LEX_RPAREN) { - s = BC_STATUS_PARSE_BAD_TOKEN; + s = bc_error("bad token"); goto err; } @@ -3805,7 +3820,7 @@ static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags) if (p->l.t.t == BC_LEX_RBRACKET) { if (!(flags & BC_PARSE_ARRAY)) { - s = BC_STATUS_PARSE_BAD_EXP; + s = bc_error("bad expression"); goto err; } @@ -3828,7 +3843,7 @@ static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags) else if (p->l.t.t == BC_LEX_LPAREN) { if (flags & BC_PARSE_NOCALL) { - s = BC_STATUS_PARSE_BAD_TOKEN; + s = bc_error("bad token"); goto err; } @@ -3854,11 +3869,11 @@ static BcStatus bc_parse_read(BcParse *p) s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); bc_parse_push(p, BC_INST_READ); @@ -3872,7 +3887,7 @@ static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; @@ -3882,7 +3897,7 @@ static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, s = bc_parse_expr(p, flags, bc_parse_next_rel); if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); *prev = (type == BC_LEX_KEY_LENGTH) ? BC_INST_LENGTH : BC_INST_SQRT; bc_parse_push(p, *prev); @@ -3911,7 +3926,7 @@ static BcStatus bc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) s = bc_parse_expr(p, flags, bc_parse_next_rel); if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); bc_parse_push(p, BC_INST_SCALE_FUNC); return bc_lex_next(&p->l); @@ -3968,7 +3983,7 @@ static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, s = bc_lex_next(&p->l); if (s) return s; if (p->l.t.t == BC_LEX_LPAREN) - s = BC_STATUS_PARSE_BAD_TOKEN; + s = bc_error("bad token"); else bc_parse_push(p, BC_INST_SCALE); break; @@ -3976,7 +3991,7 @@ static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, default: { - s = BC_STATUS_PARSE_BAD_TOKEN; + s = bc_error("bad token"); break; } } @@ -4037,7 +4052,7 @@ static BcStatus bc_parse_print(BcParse *p) type = p->l.t.t; if (type == BC_LEX_SCOLON || type == BC_LEX_NLINE) - return BC_STATUS_PARSE_BAD_PRINT; + return bc_error("bad print statement"); while (!s && type != BC_LEX_SCOLON && type != BC_LEX_NLINE) { @@ -4057,7 +4072,7 @@ static BcStatus bc_parse_print(BcParse *p) } if (s) return s; - if (comma) return BC_STATUS_PARSE_BAD_TOKEN; + if (comma) return bc_error("bad token"); return bc_lex_next(&p->l); } @@ -4068,7 +4083,7 @@ static BcStatus bc_parse_return(BcParse *p) BcLexType t; bool paren; - if (!BC_PARSE_FUNC(p)) return BC_STATUS_PARSE_BAD_TOKEN; + if (!BC_PARSE_FUNC(p)) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; @@ -4083,7 +4098,8 @@ static BcStatus bc_parse_return(BcParse *p) s = bc_parse_expr(p, 0, bc_parse_next_expr); if (s && s != BC_STATUS_PARSE_EMPTY_EXP) return s; - else if (s == BC_STATUS_PARSE_EMPTY_EXP) { + + if (s == BC_STATUS_PARSE_EMPTY_EXP) { bc_parse_push(p, BC_INST_RET0); s = bc_lex_next(&p->l); if (s) return s; @@ -4105,18 +4121,18 @@ static BcStatus bc_parse_endBody(BcParse *p, bool brace) BcStatus s = BC_STATUS_SUCCESS; if (p->flags.len <= 1 || (brace && p->nbraces == 0)) - return BC_STATUS_PARSE_BAD_TOKEN; + return bc_error("bad token"); if (brace) { if (p->l.t.t == BC_LEX_RBRACE) { - if (!p->nbraces) return BC_STATUS_PARSE_BAD_TOKEN; + if (!p->nbraces) return bc_error("bad token"); --p->nbraces; s = bc_lex_next(&p->l); if (s) return s; } else - return BC_STATUS_PARSE_BAD_TOKEN; + return bc_error("bad token"); } if (BC_PARSE_IF(p)) { @@ -4202,13 +4218,13 @@ static BcStatus bc_parse_if(BcParse *p) s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; @@ -4229,7 +4245,7 @@ static BcStatus bc_parse_else(BcParse *p) { BcInstPtr ip; - if (!BC_PARSE_IF_END(p)) return BC_STATUS_PARSE_BAD_TOKEN; + if (!BC_PARSE_IF_END(p)) return bc_error("bad token"); ip.idx = p->func->labels.len; ip.func = ip.len = 0; @@ -4253,7 +4269,7 @@ static BcStatus bc_parse_while(BcParse *p) s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; @@ -4271,7 +4287,7 @@ static BcStatus bc_parse_while(BcParse *p) s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; @@ -4290,7 +4306,7 @@ static BcStatus bc_parse_for(BcParse *p) s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; @@ -4300,7 +4316,7 @@ static BcStatus bc_parse_for(BcParse *p) s = bc_vm_posixError(BC_STATUS_POSIX_FOR1, p->l.f, p->l.line, NULL); if (s) return s; - if (p->l.t.t != BC_LEX_SCOLON) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_SCOLON) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; @@ -4317,7 +4333,7 @@ static BcStatus bc_parse_for(BcParse *p) s = bc_vm_posixError(BC_STATUS_POSIX_FOR2, p->l.f, p->l.line, NULL); if (s) return s; - if (p->l.t.t != BC_LEX_SCOLON) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_SCOLON) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; @@ -4339,7 +4355,7 @@ static BcStatus bc_parse_for(BcParse *p) if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, cond_idx); bc_vec_push(&p->func->labels, &p->func->code.len); @@ -4362,17 +4378,17 @@ static BcStatus bc_parse_loopExit(BcParse *p, BcLexType type) size_t i; BcInstPtr *ip; - if (!BC_PARSE_LOOP(p)) return BC_STATUS_PARSE_BAD_TOKEN; + if (!BC_PARSE_LOOP(p)) return bc_error("bad token"); if (type == BC_LEX_KEY_BREAK) { - if (p->exits.len == 0) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->exits.len == 0) return bc_error("bad token"); i = p->exits.len - 1; ip = bc_vec_item(&p->exits, i); while (!ip->func && i < p->exits.len) ip = bc_vec_item(&p->exits, i--); - if (i >= p->exits.len && !ip->func) return BC_STATUS_PARSE_BAD_TOKEN; + if (i >= p->exits.len && !ip->func) return bc_error("bad token"); i = ip->idx; } @@ -4386,7 +4402,7 @@ static BcStatus bc_parse_loopExit(BcParse *p, BcLexType type) if (s) return s; if (p->l.t.t != BC_LEX_SCOLON && p->l.t.t != BC_LEX_NLINE) - return BC_STATUS_PARSE_BAD_TOKEN; + return bc_error("bad token"); return bc_lex_next(&p->l); } @@ -4400,20 +4416,23 @@ static BcStatus bc_parse_func(BcParse *p) s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_NAME) return BC_STATUS_PARSE_BAD_FUNC; + if (p->l.t.t != BC_LEX_NAME) + return bc_error("bad function definition"); name = xstrdup(p->l.t.v.v); bc_parse_addFunc(p, name, &p->fidx); s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_FUNC; + if (p->l.t.t != BC_LEX_LPAREN) + return bc_error("bad function definition"); s = bc_lex_next(&p->l); if (s) return s; while (p->l.t.t != BC_LEX_RPAREN) { - if (p->l.t.t != BC_LEX_NAME) return BC_STATUS_PARSE_BAD_FUNC; + if (p->l.t.t != BC_LEX_NAME) + return bc_error("bad function definition"); ++p->func->nparams; @@ -4429,7 +4448,7 @@ static BcStatus bc_parse_func(BcParse *p) if (s) goto err; if (p->l.t.t != BC_LEX_RBRACKET) { - s = BC_STATUS_PARSE_BAD_FUNC; + s = bc_error("bad function definition"); goto err; } @@ -4447,7 +4466,7 @@ static BcStatus bc_parse_func(BcParse *p) if (s) goto err; } - if (comma) return BC_STATUS_PARSE_BAD_FUNC; + if (comma) return bc_error("bad function definition"); flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_BODY; bc_parse_startBody(p, flags); @@ -4471,7 +4490,7 @@ static BcStatus bc_parse_auto(BcParse *p) bool comma, var, one; char *name; - if (!p->auto_part) return BC_STATUS_PARSE_BAD_TOKEN; + if (!p->auto_part) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; @@ -4491,7 +4510,7 @@ static BcStatus bc_parse_auto(BcParse *p) if (s) goto err; if (p->l.t.t != BC_LEX_RBRACKET) { - s = BC_STATUS_PARSE_BAD_FUNC; + s = bc_error("bad function definition"); goto err; } @@ -4509,11 +4528,11 @@ static BcStatus bc_parse_auto(BcParse *p) if (s) goto err; } - if (comma) return BC_STATUS_PARSE_BAD_FUNC; + if (comma) return bc_error("bad function definition"); if (!one) return bc_error("no auto variable found"); if (p->l.t.t != BC_LEX_NLINE && p->l.t.t != BC_LEX_SCOLON) - return BC_STATUS_PARSE_BAD_TOKEN; + return bc_error("bad token"); return bc_lex_next(&p->l); @@ -4531,7 +4550,7 @@ static BcStatus bc_parse_body(BcParse *p, bool brace) if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) { - if (!brace) return BC_STATUS_PARSE_BAD_TOKEN; + if (!brace) return bc_error("bad token"); p->auto_part = p->l.t.t != BC_LEX_KEY_AUTO; if (!p->auto_part) { @@ -4568,7 +4587,7 @@ static BcStatus bc_parse_stmt(BcParse *p) case BC_LEX_LBRACE: { - if (!BC_PARSE_BODY(p)) return BC_STATUS_PARSE_BAD_TOKEN; + if (!BC_PARSE_BODY(p)) return bc_error("bad token"); ++p->nbraces; s = bc_lex_next(&p->l); @@ -4713,7 +4732,7 @@ static BcStatus bc_parse_stmt(BcParse *p) default: { - s = BC_STATUS_PARSE_BAD_TOKEN; + s = bc_error("bad token"); break; } } @@ -4726,9 +4745,9 @@ static BcStatus bc_parse_parse(BcParse *p) BcStatus s; if (p->l.t.t == BC_LEX_EOF) - s = p->flags.len > 0 ? BC_STATUS_PARSE_NO_BLOCK_END : BC_STATUS_LEX_EOF; + s = p->flags.len > 0 ? bc_error("block end could not be found") : bc_error("end of file"); else if (p->l.t.t == BC_LEX_KEY_DEFINE) { - if (!BC_PARSE_CAN_EXEC(p)) return BC_STATUS_PARSE_BAD_TOKEN; + if (!BC_PARSE_CAN_EXEC(p)) return bc_error("bad token"); s = bc_parse_func(p); } else @@ -4787,7 +4806,11 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) prev != BC_INST_SCALE && prev != BC_INST_IBASE && prev != BC_INST_OBASE && prev != BC_INST_LAST) { - s = BC_STATUS_PARSE_BAD_ASSIGN; + s = bc_error("bad assignment:" + " left side must be scale," + " ibase, obase, last, var," + " or array element" + ); break; } } @@ -4807,10 +4830,10 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_OP_BOOL_OR: case BC_LEX_OP_BOOL_AND: { - if (((t == BC_LEX_OP_BOOL_NOT) != bin_last) || - (t != BC_LEX_OP_BOOL_NOT && prev == BC_INST_BOOL_NOT)) - { - return BC_STATUS_PARSE_BAD_EXP; + if (((t == BC_LEX_OP_BOOL_NOT) != bin_last) + || (t != BC_LEX_OP_BOOL_NOT && prev == BC_INST_BOOL_NOT) + ) { + return bc_error("bad expression"); } 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) case BC_LEX_LPAREN: { - if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; - + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error("bad expression"); ++nparens; paren_expr = rprn = bin_last = false; get_token = true; @@ -4837,7 +4860,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_RPAREN: { if (bin_last || prev == BC_INST_BOOL_NOT) - return BC_STATUS_PARSE_BAD_EXP; + return bc_error("bad expression"); if (nparens == 0) { s = BC_STATUS_SUCCESS; @@ -4859,8 +4882,8 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_NAME: { - if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; - + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error("bad expression"); paren_expr = true; rprn = get_token = bin_last = false; 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) case BC_LEX_NUMBER: { - if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; - + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error("bad expression"); bc_parse_number(p, &prev, &nexprs); paren_expr = get_token = true; rprn = bin_last = false; @@ -4884,8 +4907,8 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_KEY_LAST: case BC_LEX_KEY_OBASE: { - if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; - + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error("bad expression"); prev = (char) (t - BC_LEX_KEY_IBASE + BC_INST_IBASE); bc_parse_push(p, (char) prev); @@ -4899,8 +4922,8 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_KEY_LENGTH: case BC_LEX_KEY_SQRT: { - if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; - + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error("bad expression"); s = bc_parse_builtin(p, t, flags, &prev); paren_expr = true; rprn = get_token = bin_last = false; @@ -4912,9 +4935,9 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_KEY_READ: { if (BC_PARSE_LEAF(prev, rprn)) - return BC_STATUS_PARSE_BAD_EXP; + return bc_error("bad expression"); else if (flags & BC_PARSE_NOREAD) - s = BC_STATUS_EXEC_REC_READ; + s = bc_error("read() call inside of a read() call"); else s = bc_parse_read(p); @@ -4928,8 +4951,8 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_KEY_SCALE: { - if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; - + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error("bad expression"); s = bc_parse_scale(p, &prev, flags); paren_expr = true; rprn = get_token = bin_last = false; @@ -4941,7 +4964,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) default: { - s = BC_STATUS_PARSE_BAD_TOKEN; + s = bc_error("bad token"); break; } } @@ -4958,7 +4981,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN; if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN) - return BC_STATUS_PARSE_BAD_EXP; + return bc_error("bad expression"); bc_parse_push(p, BC_PARSE_TOKEN_INST(top)); @@ -4966,11 +4989,14 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) bc_vec_pop(&p->ops); } - s = BC_STATUS_PARSE_BAD_EXP; - if (prev == BC_INST_BOOL_NOT || nexprs != 1) return s; + if (prev == BC_INST_BOOL_NOT || nexprs != 1) + return bc_error("bad expression"); - for (i = 0; s && i < next.len; ++i) s *= t != next.tokens[i]; - if (s) return s; + for (i = 0; i < next.len; ++i) + if (t == next.tokens[i]) + goto ok; + return bc_error("bad expression"); + ok: if (!(flags & BC_PARSE_REL) && nrelops) { 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) s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_NAME) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_NAME) return bc_error("bad token"); name = xstrdup(p->l.t.v.v); bc_parse_pushName(p, name); @@ -5115,7 +5141,8 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) if (t == BC_LEX_NEG) { s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_NUMBER) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_NUMBER) + return bc_error("bad token"); } bc_parse_number(p, &prev, &p->nbraces); @@ -5129,7 +5156,7 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) case BC_LEX_KEY_READ: { if (flags & BC_PARSE_NOREAD) - s = BC_STATUS_EXEC_REC_READ; + s = bc_error("read() call inside of a read() call"); else bc_parse_push(p, BC_INST_READ); get_token = true; @@ -5164,7 +5191,7 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) default: { - s = BC_STATUS_PARSE_BAD_TOKEN; + s = bc_error("bad token"); get_token = true; break; } @@ -5206,7 +5233,7 @@ static BcStatus dc_parse_parse(BcParse *p) BcStatus s; if (p->l.t.t == BC_LEX_EOF) - s = BC_STATUS_LEX_EOF; + s = bc_error("end of file"); else s = dc_parse_expr(p, 0); @@ -5349,7 +5376,8 @@ static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln, bool hex; BcResultType lt, rt; - if (!BC_PROG_STACK(&G.prog.results, 2)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 2)) + return bc_error("stack has too few elements"); *r = bc_vec_item_rev(&G.prog.results, 0); *l = bc_vec_item_rev(&G.prog.results, 1); @@ -5371,8 +5399,9 @@ static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln, } if (!BC_PROG_NUM((*l), (*ln)) && (!assign || (*l)->t != BC_RESULT_VAR)) - return BC_STATUS_EXEC_BAD_TYPE; - if (!assign && !BC_PROG_NUM((*r), (*ln))) return BC_STATUS_EXEC_BAD_TYPE; + return bc_error("variable is wrong type"); + if (!assign && !BC_PROG_NUM((*r), (*ln))) + return bc_error("variable is wrong type"); return s; } @@ -5389,13 +5418,15 @@ static BcStatus bc_program_prep(BcResult **r, BcNum **n) { BcStatus s; - if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 1)) + return bc_error("stack has too few elements"); *r = bc_vec_top(&G.prog.results); s = bc_program_num(*r, n, false); if (s) return s; - if (!BC_PROG_NUM((*r), (*n))) return BC_STATUS_EXEC_BAD_TYPE; + if (!BC_PROG_NUM((*r), (*n))) + return bc_error("variable is wrong type"); return s; } @@ -5439,7 +5470,8 @@ static BcStatus bc_program_read(void) for (i = 0; i < G.prog.stack.len; ++i) { BcInstPtr *ip_ptr = bc_vec_item(&G.prog.stack, i); - if (ip_ptr->func == BC_PROG_READ) return BC_STATUS_EXEC_REC_READ; + if (ip_ptr->func == BC_PROG_READ) + return bc_error("read() call inside of a read() call"); } bc_vec_npop(&f->code, f->code.len); @@ -5457,7 +5489,7 @@ static BcStatus bc_program_read(void) if (s) goto exec_err; if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != BC_LEX_EOF) { - s = BC_STATUS_EXEC_BAD_READ_EXPR; + s = bc_error("bad read() expression"); goto exec_err; } @@ -5600,7 +5632,8 @@ static BcStatus bc_program_print(char inst, size_t idx) BcNum *num = NULL; bool pop = inst != BC_INST_PRINT; - if (!BC_PROG_STACK(&G.prog.results, idx + 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, idx + 1)) + return bc_error("stack has too few elements"); r = bc_vec_item_rev(&G.prog.results, idx); s = bc_program_num(r, &num, false); @@ -5731,7 +5764,8 @@ static BcStatus bc_program_assignStr(BcResult *r, BcVec *v, res.t = BC_RESULT_STR; if (!push) { - if (!BC_PROG_STACK(&G.prog.results, 2)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 2)) + return bc_error("stack has too few elements"); bc_vec_pop(v); bc_vec_pop(&G.prog.results); } @@ -5752,14 +5786,17 @@ static BcStatus bc_program_copyToVar(char *name, bool var) BcVec *v; BcNum *n; - if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 1)) + return bc_error("stack has too few elements"); ptr = bc_vec_top(&G.prog.results); - if ((ptr->t == BC_RESULT_ARRAY) != !var) return BC_STATUS_EXEC_BAD_TYPE; + if ((ptr->t == BC_RESULT_ARRAY) != !var) + return bc_error("variable is wrong type"); v = bc_program_search(name, var); #if ENABLE_DC - if (ptr->t == BC_RESULT_STR && !var) return BC_STATUS_EXEC_BAD_TYPE; + if (ptr->t == BC_RESULT_STR && !var) + return bc_error("variable is wrong type"); if (ptr->t == BC_RESULT_STR) return bc_program_assignStr(ptr, v, true); #endif @@ -5804,7 +5841,8 @@ static BcStatus bc_program_assign(char inst) BcVec *v; - if (left->t != BC_RESULT_VAR) return BC_STATUS_EXEC_BAD_TYPE; + if (left->t != BC_RESULT_VAR) + return bc_error("variable is wrong type"); v = bc_program_search(left->d.id.name, true); return bc_program_assignStr(right, v, false); @@ -5812,11 +5850,15 @@ static BcStatus bc_program_assign(char inst) #endif if (left->t == BC_RESULT_CONSTANT || left->t == BC_RESULT_TEMP) - return BC_STATUS_PARSE_BAD_ASSIGN; + return bc_error("bad assignment:" + " left side must be scale," + " ibase, obase, last, var," + " or array element" + ); #if ENABLE_BC if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &G.prog.zero)) - return BC_STATUS_MATH_DIVIDE_BY_ZERO; + return bc_error("divide by zero"); if (assign) bc_num_copy(l, r); @@ -5829,25 +5871,35 @@ static BcStatus bc_program_assign(char inst) #endif if (ib || sc || left->t == BC_RESULT_OBASE) { - + static const char *const msg[] = { + "bad ibase; must be [2, 16]", //BC_RESULT_IBASE + "bad scale; must be [0, BC_SCALE_MAX]", //BC_RESULT_SCALE + "?1", //BC_RESULT_LAST + "?2", //BC_RESULT_CONSTANT + "?3", //BC_RESULT_ONE + "bad obase; must be [2, BC_BASE_MAX]", //BC_RESULT_OBASE + }; size_t *ptr; s = bc_num_ulong(l, &val); - if (s) return s; - s = left->t - BC_RESULT_IBASE + BC_STATUS_EXEC_BAD_IBASE; - + if (s) + return s; + s = left->t - BC_RESULT_IBASE; if (sc) { max = BC_MAX_SCALE; ptr = &G.prog.scale; } else { - if (val < BC_NUM_MIN_BASE) return s; + if (val < BC_NUM_MIN_BASE) + return bc_error(msg[s]); max = ib ? BC_NUM_MAX_IBASE : BC_MAX_OBASE; ptr = ib ? &G.prog.ib_t : &G.prog.ob_t; } - if (val > max) return s; - if (!sc) bc_num_copy(ib ? &G.prog.ib : &G.prog.ob, l); + if (val > max) + return bc_error(msg[s]); + if (!sc) + bc_num_copy(ib ? &G.prog.ib : &G.prog.ob, l); *ptr = (size_t) val; s = BC_STATUS_SUCCESS; @@ -5884,7 +5936,7 @@ static BcStatus bc_program_pushVar(char *code, size_t *bgn, if (!BC_PROG_STACK(v, 2 - copy)) { free(name); - return BC_STATUS_EXEC_STACK; + return bc_error("stack has too few elements"); } free(name); @@ -5936,7 +5988,7 @@ static BcStatus bc_program_pushArray(char *code, size_t *bgn, if (s) goto err; if (temp > BC_MAX_DIM) { - s = BC_STATUS_EXEC_ARRAY_LEN; + s = bc_error("array too long; must be [1, BC_DIM_MAX]"); goto err; } @@ -6010,7 +6062,7 @@ static BcStatus bc_program_call(char *code, size_t *idx) arg = bc_vec_top(&G.prog.results); if ((!a->idx) != (arg->t == BC_RESULT_ARRAY) || arg->t == BC_RESULT_STR) - return BC_STATUS_EXEC_BAD_TYPE; + return bc_error("variable is wrong type"); s = bc_program_copyToVar(a->name, a->idx); if (s) return s; @@ -6046,7 +6098,7 @@ static BcStatus bc_program_return(char inst) BcInstPtr *ip = bc_vec_top(&G.prog.stack); if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET)) - return BC_STATUS_EXEC_STACK; + return bc_error("stack has too few elements"); f = bc_vec_item(&G.prog.fns, ip->func); res.t = BC_RESULT_TEMP; @@ -6108,14 +6160,16 @@ static BcStatus bc_program_builtin(char inst) BcResult res; bool len = inst == BC_INST_LENGTH; - if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 1)) + return bc_error("stack has too few elements"); opnd = bc_vec_top(&G.prog.results); s = bc_program_num(opnd, &num, false); if (s) return s; #if ENABLE_DC - if (!BC_PROG_NUM(opnd, num) && !len) return BC_STATUS_EXEC_BAD_TYPE; + if (!BC_PROG_NUM(opnd, num) && !len) + return bc_error("variable is wrong type"); #endif bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); @@ -6180,14 +6234,16 @@ static BcStatus bc_program_modexp(void) BcResult *r1, *r2, *r3, res; BcNum *n1, *n2, *n3; - if (!BC_PROG_STACK(&G.prog.results, 3)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 3)) + return bc_error("stack has too few elements"); s = bc_program_binOpPrep(&r2, &n2, &r3, &n3, false); if (s) return s; r1 = bc_vec_item_rev(&G.prog.results, 2); s = bc_program_num(r1, &n1, false); if (s) return s; - if (!BC_PROG_NUM(r1, n1)) return BC_STATUS_EXEC_BAD_TYPE; + if (!BC_PROG_NUM(r1, n1)) + return bc_error("variable is wrong type"); // Make sure that the values have their pointers updated, if necessary. if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) { @@ -6238,7 +6294,8 @@ static BcStatus bc_program_asciify(void) size_t len = G.prog.strs.len, idx; unsigned long val; - if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 1)) + return bc_error("stack has too few elements"); r = bc_vec_top(&G.prog.results); s = bc_program_num(r, &num, false); @@ -6306,7 +6363,8 @@ static BcStatus bc_program_printStream(void) size_t idx; char *str; - if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 1)) + return bc_error("stack has too few elements"); r = bc_vec_top(&G.prog.results); s = bc_program_num(r, &n, false); @@ -6338,7 +6396,7 @@ static BcStatus bc_program_nquit(void) bc_vec_pop(&G.prog.results); if (G.prog.stack.len < val) - return BC_STATUS_EXEC_STACK; + return bc_error("stack has too few elements"); if (G.prog.stack.len == val) quit(); @@ -6360,7 +6418,8 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, BcNum *n; bool exec; - if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 1)) + return bc_error("stack has too few elements"); r = bc_vec_top(&G.prog.results); @@ -6393,7 +6452,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, if (!exec) goto exit; if (!BC_PROG_STR(n)) { - s = BC_STATUS_EXEC_BAD_TYPE; + s = bc_error("variable is wrong type"); goto exit; } @@ -6425,7 +6484,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, if (s) goto err; if (prs.l.t.t != BC_LEX_EOF) { - s = BC_STATUS_PARSE_BAD_EXP; + s = bc_error("bad expression"); goto err; } @@ -6652,7 +6711,7 @@ static BcStatus bc_program_exec(void) case BC_INST_POP: { if (!BC_PROG_STACK(&G.prog.results, 1)) - s = BC_STATUS_EXEC_STACK; + s = bc_error("stack has too few elements"); else bc_vec_pop(&G.prog.results); break; @@ -6764,7 +6823,8 @@ static BcStatus bc_program_exec(void) case BC_INST_DUPLICATE: { - if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 1)) + return bc_error("stack has too few elements"); ptr = bc_vec_top(&G.prog.results); bc_result_copy(&r, ptr); bc_vec_push(&G.prog.results, &r); @@ -6775,7 +6835,8 @@ static BcStatus bc_program_exec(void) { BcResult *ptr2; - if (!BC_PROG_STACK(&G.prog.results, 2)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 2)) + return bc_error("stack has too few elements"); ptr = bc_vec_item_rev(&G.prog.results, 0); 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) fprintf(stderr, bc_err_line + 4 * !line, line); } +/// return s * (!G.ttyin || !!strcmp(file, bc_program_stdin_name)); } @@ -6983,7 +7045,8 @@ static BcStatus bc_vm_file(const char *file) main_func = bc_vec_item(&G.prog.fns, BC_PROG_MAIN); ip = bc_vec_item(&G.prog.stack, 0); - if (main_func->code.len < ip->idx) s = BC_STATUS_EXEC_FILE_NOT_EXECUTABLE; + if (main_func->code.len < ip->idx) + s = bc_error("file '%s' is not executable", file); err: free(data); @@ -7057,12 +7120,16 @@ static BcStatus bc_vm_stdin(void) bc_vec_npop(&buffer, buffer.len); } - if (str) - s = bc_vm_error(BC_STATUS_LEX_NO_STRING_END, G.prs.l.f, + if (str) { + bc_error("string end could not be found"); + s = bc_vm_error(BC_STATUS_FAILURE, G.prs.l.f, G.prs.l.line); - else if (comment) - s = bc_vm_error(BC_STATUS_LEX_NO_COMMENT_END, G.prs.l.f, + } + else if (comment) { + bc_error("comment end could not be found"); + s = bc_vm_error(BC_STATUS_FAILURE, G.prs.l.f, G.prs.l.line); + } err: bc_vec_free(&buf); |