[git commit] bc: convert all non-POSIX BC_STATUS_foo codes

Denys Vlasenko vda.linux at googlemail.com
Wed Dec 5 14:43:35 UTC 2018


commit: https://git.busybox.net/busybox/commit/?id=60cf747b6c234958387298068da658cfee9c42cb
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

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 at googlemail.com>
---
 miscutils/bc.c | 475 ++++++++++++++++++++++++++++++++-------------------------
 1 file 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);


More information about the busybox-cvs mailing list