bc: convert all status codes, remove bc_err_msgs[], bc_vm_error(), bc_vm_posixError()
function old new delta bc_posix_error - 65 +65 bc_vm_run 1995 2039 +44 bc_err_line 7 - -7 bc_num_ulong 103 93 -10 bc_parse_parse 495 483 -12 bc_err_fmt 12 - -12 bc_warn_fmt 14 - -14 bc_parse_expr 2210 2194 -16 bc_program_reset 105 78 -27 bc_vm_process 130 94 -36 bc_parse_stmt 2313 2277 -36 bc_err_msgs 60 - -60 bc_lex_token 1367 1282 -85 bc_vm_error 143 - -143 bc_vm_posixError 189 - -189 ------------------------------------------------------------------------------ (add/remove: 1/6 grow/shrink: 1/7 up/down: 109/-647) Total: -538 bytes text data bss dec hex filename 988258 485 7296 996039 f32c7 busybox_old 987717 485 7296 995498 f30aa busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
60cf747b6c
commit
9b70f197b4
267
miscutils/bc.c
267
miscutils/bc.c
@ -171,141 +171,7 @@ typedef enum BcStatus {
|
||||
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,
|
||||
// BC_STATUS_BIN_FILE,
|
||||
// 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,
|
||||
#if ENABLE_DC
|
||||
// BC_STATUS_LEX_EXTENDED_REG,
|
||||
#endif
|
||||
// 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_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_BAD_SCALE,
|
||||
// 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_VEC_OUT_OF_BOUNDS,
|
||||
// BC_STATUS_VEC_ITEM_EXISTS,
|
||||
BC_STATUS_BEFORE_POSIX = BC_STATUS_PARSE_EMPTY_EXP,
|
||||
#if ENABLE_BC
|
||||
BC_STATUS_POSIX_NAME_LEN,
|
||||
BC_STATUS_POSIX_COMMENT,
|
||||
BC_STATUS_POSIX_BAD_KW,
|
||||
BC_STATUS_POSIX_DOT,
|
||||
BC_STATUS_POSIX_RET,
|
||||
BC_STATUS_POSIX_BOOL,
|
||||
BC_STATUS_POSIX_REL_POS,
|
||||
BC_STATUS_POSIX_MULTIREL,
|
||||
BC_STATUS_POSIX_FOR1,
|
||||
BC_STATUS_POSIX_FOR2,
|
||||
BC_STATUS_POSIX_FOR3,
|
||||
BC_STATUS_POSIX_BRACE,
|
||||
#endif
|
||||
// BC_STATUS_QUIT,
|
||||
// BC_STATUS_LIMITS,
|
||||
|
||||
// BC_STATUS_INVALID_OPTION,
|
||||
} BcStatus;
|
||||
// Keep enum above and messages below in sync!
|
||||
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",
|
||||
#if ENABLE_DC
|
||||
// "extended register",
|
||||
#endif
|
||||
// "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",
|
||||
|
||||
// "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]",
|
||||
// "bad scale; must be [0, BC_SCALE_MAX]",
|
||||
// "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",
|
||||
|
||||
// "index is out of bounds",
|
||||
// "item already exists",
|
||||
#if ENABLE_BC
|
||||
"POSIX only allows one character names; the following is bad:",
|
||||
"POSIX does not allow '#' script comments",
|
||||
"POSIX does not allow the following keyword:",
|
||||
"POSIX does not allow a period ('.') as a shortcut for the last result",
|
||||
"POSIX requires parentheses around return expressions",
|
||||
"POSIX does not allow boolean operators; the following is bad:",
|
||||
"POSIX does not allow comparison operators outside if or loops",
|
||||
"POSIX requires exactly one comparison operator per condition",
|
||||
"POSIX does not allow an empty init expression in a for loop",
|
||||
"POSIX does not allow an empty condition expression in a for loop",
|
||||
"POSIX does not allow an empty update expression in a for loop",
|
||||
"POSIX requires the left brace be on the same line as the function header",
|
||||
#endif
|
||||
};
|
||||
|
||||
#define BC_VEC_INVALID_IDX ((size_t) -1)
|
||||
#define BC_VEC_START_CAP (1 << 5)
|
||||
@ -891,17 +757,8 @@ struct globals {
|
||||
|
||||
#define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b'))
|
||||
|
||||
#if ENABLE_BC
|
||||
static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line,
|
||||
const char *msg);
|
||||
#endif
|
||||
|
||||
static void bc_vm_info(void);
|
||||
|
||||
static const char bc_err_fmt[] = "\nerror: %s\n";
|
||||
static const char bc_warn_fmt[] = "\nwarning: %s\n";
|
||||
static const char bc_err_line[] = ":%zu\n\n";
|
||||
|
||||
#if ENABLE_BC
|
||||
static const BcLexKeyword bc_lex_kws[20] = {
|
||||
BC_LEX_KW_ENTRY("auto", 4, true),
|
||||
@ -1151,6 +1008,25 @@ static int bc_error(const char *fmt, ...)
|
||||
return BC_STATUS_FAILURE;
|
||||
}
|
||||
|
||||
static int bc_posix_error(const char *fmt, ...)
|
||||
{
|
||||
va_list p;
|
||||
|
||||
if (!(G.flags & (BC_FLAG_S|BC_FLAG_W)))
|
||||
return BC_STATUS_SUCCESS;
|
||||
|
||||
va_start(p, fmt);
|
||||
bb_verror_msg(fmt, p, NULL);
|
||||
va_end(p);
|
||||
|
||||
// Do we treat non-POSIX constructs as errors?
|
||||
if (!(G.flags & BC_FLAG_S))
|
||||
return BC_STATUS_SUCCESS; // no, it's a warning
|
||||
if (!G.ttyin)
|
||||
exit(1);
|
||||
return BC_STATUS_FAILURE;
|
||||
}
|
||||
|
||||
static void bc_vec_grow(BcVec *v, size_t n)
|
||||
{
|
||||
size_t cap = v->cap * 2;
|
||||
@ -3039,8 +2915,7 @@ static BcStatus bc_lex_identifier(BcLex *l)
|
||||
l->t.t = BC_LEX_KEY_AUTO + (BcLexType) i;
|
||||
|
||||
if (!bc_lex_kws[i].posix) {
|
||||
s = bc_vm_posixError(BC_STATUS_POSIX_BAD_KW, l->f, l->line,
|
||||
bc_lex_kws[i].name);
|
||||
s = bc_posix_error("POSIX does not allow the following keyword:"); // bc_lex_kws[i].name
|
||||
if (s) return s;
|
||||
}
|
||||
|
||||
@ -3054,7 +2929,7 @@ static BcStatus bc_lex_identifier(BcLex *l)
|
||||
if (s) return s;
|
||||
|
||||
if (l->t.v.len - 1 > 1)
|
||||
s = bc_vm_posixError(BC_STATUS_POSIX_NAME_LEN, l->f, l->line, buf);
|
||||
s = bc_posix_error("POSIX only allows one character names; the following is bad:"); // buf
|
||||
|
||||
return s;
|
||||
}
|
||||
@ -3155,7 +3030,7 @@ static BcStatus bc_lex_token(BcLex *l)
|
||||
bc_lex_assign(l, BC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT);
|
||||
|
||||
if (l->t.t == BC_LEX_OP_BOOL_NOT) {
|
||||
s = bc_vm_posixError(BC_STATUS_POSIX_BOOL, l->f, l->line, "!");
|
||||
s = bc_posix_error("POSIX does not allow boolean operators; the following is bad:"); // "!"
|
||||
if (s) return s;
|
||||
}
|
||||
|
||||
@ -3170,7 +3045,7 @@ static BcStatus bc_lex_token(BcLex *l)
|
||||
|
||||
case '#':
|
||||
{
|
||||
s = bc_vm_posixError(BC_STATUS_POSIX_COMMENT, l->f, l->line, NULL);
|
||||
s = bc_posix_error("POSIX does not allow '#' script comments");
|
||||
if (s) return s;
|
||||
|
||||
bc_lex_lineComment(l);
|
||||
@ -3189,7 +3064,7 @@ static BcStatus bc_lex_token(BcLex *l)
|
||||
c2 = l->buf[l->i];
|
||||
if (c2 == '&') {
|
||||
|
||||
s = bc_vm_posixError(BC_STATUS_POSIX_BOOL, l->f, l->line, "&&");
|
||||
s = bc_posix_error("POSIX does not allow boolean operators; the following is bad:"); // "&&"
|
||||
if (s) return s;
|
||||
|
||||
++l->i;
|
||||
@ -3252,7 +3127,7 @@ static BcStatus bc_lex_token(BcLex *l)
|
||||
s = bc_lex_number(l, c);
|
||||
else {
|
||||
l->t.t = BC_LEX_KEY_LAST;
|
||||
s = bc_vm_posixError(BC_STATUS_POSIX_DOT, l->f, l->line, NULL);
|
||||
s = bc_posix_error("POSIX does not allow a period ('.') as a shortcut for the last result");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -3379,8 +3254,7 @@ static BcStatus bc_lex_token(BcLex *l)
|
||||
c2 = l->buf[l->i];
|
||||
|
||||
if (c2 == '|') {
|
||||
|
||||
s = bc_vm_posixError(BC_STATUS_POSIX_BOOL, l->f, l->line, "||");
|
||||
s = bc_posix_error("POSIX does not allow boolean operators; the following is bad:"); // "||"
|
||||
if (s) return s;
|
||||
|
||||
++l->i;
|
||||
@ -4106,7 +3980,7 @@ static BcStatus bc_parse_return(BcParse *p)
|
||||
}
|
||||
|
||||
if (!paren || p->l.t.last != BC_LEX_RPAREN) {
|
||||
s = bc_vm_posixError(BC_STATUS_POSIX_RET, p->l.f, p->l.line, NULL);
|
||||
s = bc_posix_error("POSIX requires parentheses around return expressions");
|
||||
if (s) return s;
|
||||
}
|
||||
|
||||
@ -4313,7 +4187,7 @@ static BcStatus bc_parse_for(BcParse *p)
|
||||
if (p->l.t.t != BC_LEX_SCOLON)
|
||||
s = bc_parse_expr(p, 0, bc_parse_next_for);
|
||||
else
|
||||
s = bc_vm_posixError(BC_STATUS_POSIX_FOR1, p->l.f, p->l.line, NULL);
|
||||
s = bc_posix_error("POSIX does not allow an empty init expression in a for loop");
|
||||
|
||||
if (s) return s;
|
||||
if (p->l.t.t != BC_LEX_SCOLON) return bc_error("bad token");
|
||||
@ -4330,7 +4204,7 @@ static BcStatus bc_parse_for(BcParse *p)
|
||||
if (p->l.t.t != BC_LEX_SCOLON)
|
||||
s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_for);
|
||||
else
|
||||
s = bc_vm_posixError(BC_STATUS_POSIX_FOR2, p->l.f, p->l.line, NULL);
|
||||
s = bc_posix_error("POSIX does not allow an empty condition expression in a for loop");
|
||||
|
||||
if (s) return s;
|
||||
if (p->l.t.t != BC_LEX_SCOLON) return bc_error("bad token");
|
||||
@ -4351,7 +4225,7 @@ static BcStatus bc_parse_for(BcParse *p)
|
||||
if (p->l.t.t != BC_LEX_RPAREN)
|
||||
s = bc_parse_expr(p, 0, bc_parse_next_rel);
|
||||
else
|
||||
s = bc_vm_posixError(BC_STATUS_POSIX_FOR3, p->l.f, p->l.line, NULL);
|
||||
s = bc_posix_error("POSIX does not allow an empty update expression in a for loop");
|
||||
|
||||
if (s) return s;
|
||||
|
||||
@ -4475,7 +4349,7 @@ static BcStatus bc_parse_func(BcParse *p)
|
||||
if (s) return s;
|
||||
|
||||
if (p->l.t.t != BC_LEX_LBRACE)
|
||||
s = bc_vm_posixError(BC_STATUS_POSIX_BRACE, p->l.f, p->l.line, NULL);
|
||||
s = bc_posix_error("POSIX requires the left brace be on the same line as the function header");
|
||||
|
||||
return s;
|
||||
|
||||
@ -4999,11 +4873,11 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
|
||||
ok:
|
||||
|
||||
if (!(flags & BC_PARSE_REL) && nrelops) {
|
||||
s = bc_vm_posixError(BC_STATUS_POSIX_REL_POS, p->l.f, p->l.line, NULL);
|
||||
s = bc_posix_error("POSIX does not allow comparison operators outside if or loops");
|
||||
if (s) return s;
|
||||
}
|
||||
else if ((flags & BC_PARSE_REL) && nrelops > 1) {
|
||||
s = bc_vm_posixError(BC_STATUS_POSIX_MULTIREL, p->l.f, p->l.line, NULL);
|
||||
s = bc_posix_error("POSIX requires exactly one comparison operator per condition");
|
||||
if (s) return s;
|
||||
}
|
||||
|
||||
@ -6575,10 +6449,6 @@ static void bc_program_reset(void)
|
||||
|
||||
// If !tty, no need to check for ^C: we don't have ^C handler,
|
||||
// we would be killed by a signal and won't reach this place
|
||||
|
||||
fflush_and_check(); // make sure buffered stdout is printed
|
||||
fputs("ready for more input\n", stderr);
|
||||
fflush_and_check();
|
||||
}
|
||||
|
||||
static BcStatus bc_program_exec(void)
|
||||
@ -6914,40 +6784,7 @@ static void bc_vm_info(void)
|
||||
, applet_name);
|
||||
}
|
||||
|
||||
static BcStatus bc_vm_error(BcStatus s, const char *file, size_t line)
|
||||
{
|
||||
if (!s || s > BC_STATUS_BEFORE_POSIX) return s;
|
||||
|
||||
if (bc_err_msgs[s]) {
|
||||
fprintf(stderr, bc_err_fmt, bc_err_msgs[s]);
|
||||
fprintf(stderr, " %s", file);
|
||||
fprintf(stderr, bc_err_line + 4 * !line, line);
|
||||
}
|
||||
|
||||
///
|
||||
return s * (!G.ttyin || !!strcmp(file, bc_program_stdin_name));
|
||||
}
|
||||
|
||||
#if ENABLE_BC
|
||||
static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line,
|
||||
const char *msg)
|
||||
{
|
||||
const char *fmt;
|
||||
|
||||
if (!(G.flags & (BC_FLAG_S|BC_FLAG_W))) return BC_STATUS_SUCCESS;
|
||||
if (s < BC_STATUS_POSIX_NAME_LEN) return BC_STATUS_SUCCESS;
|
||||
|
||||
fmt = G_posix ? bc_err_fmt : bc_warn_fmt;
|
||||
fprintf(stderr, fmt, bc_err_msgs[s]);
|
||||
if (msg) fprintf(stderr, " %s\n", msg);
|
||||
fprintf(stderr, " %s", file);
|
||||
fprintf(stderr, bc_err_line + 4 * !line, line);
|
||||
|
||||
if (G.ttyin || !G_posix)
|
||||
s = BC_STATUS_SUCCESS;
|
||||
return s;
|
||||
}
|
||||
|
||||
static void bc_vm_envArgs(void)
|
||||
{
|
||||
static const char* const bc_args_env_name = "BC_ENV_ARGS";
|
||||
@ -7004,24 +6841,18 @@ static BcStatus bc_vm_process(const char *text)
|
||||
{
|
||||
BcStatus s = bc_parse_text(&G.prs, text);
|
||||
|
||||
s = bc_vm_error(s, G.prs.l.f, G.prs.l.line);
|
||||
if (s) return s;
|
||||
|
||||
while (G.prs.l.t.t != BC_LEX_EOF) {
|
||||
|
||||
s = G.prs.parse(&G.prs);
|
||||
|
||||
s = bc_vm_error(s, G.prs.l.f, G.prs.l.line);
|
||||
if (s) return s;
|
||||
}
|
||||
|
||||
if (BC_PARSE_CAN_EXEC(&G.prs)) {
|
||||
s = bc_program_exec();
|
||||
fflush_and_check();
|
||||
if (s) {
|
||||
if (s)
|
||||
bc_program_reset();
|
||||
s = bc_vm_error(s, G.prs.l.f, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
@ -7115,23 +6946,21 @@ static BcStatus bc_vm_stdin(void)
|
||||
|
||||
bc_vec_concat(&buffer, buf.v);
|
||||
s = bc_vm_process(buffer.v);
|
||||
if (s) goto err;
|
||||
if (s) {
|
||||
fflush_and_check();
|
||||
fputs("ready for more input\n", stderr);
|
||||
}
|
||||
|
||||
bc_vec_npop(&buffer, buffer.len);
|
||||
}
|
||||
|
||||
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);
|
||||
s = bc_error("string end could not be found");
|
||||
}
|
||||
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);
|
||||
s = bc_error("comment end could not be found");
|
||||
}
|
||||
|
||||
err:
|
||||
bc_vec_free(&buf);
|
||||
bc_vec_free(&buffer);
|
||||
return s;
|
||||
@ -7148,7 +6977,8 @@ static BcStatus bc_vm_exec(void)
|
||||
bc_lex_file(&G.prs.l, bc_lib_name);
|
||||
s = bc_parse_text(&G.prs, bc_lib);
|
||||
|
||||
while (!s && G.prs.l.t.t != BC_LEX_EOF) s = G.prs.parse(&G.prs);
|
||||
while (!s && G.prs.l.t.t != BC_LEX_EOF)
|
||||
s = G.prs.parse(&G.prs);
|
||||
|
||||
if (s) return s;
|
||||
s = bc_program_exec();
|
||||
@ -7158,10 +6988,17 @@ static BcStatus bc_vm_exec(void)
|
||||
|
||||
for (i = 0; !s && i < G.files.len; ++i)
|
||||
s = bc_vm_file(*((char **) bc_vec_item(&G.files, i)));
|
||||
if (s) return s;
|
||||
if (s) {
|
||||
if (!G.tty)
|
||||
return s;
|
||||
fflush_and_check();
|
||||
fputs("ready for more input\n", stderr);
|
||||
}
|
||||
|
||||
if (IS_BC || !G.files.len) s = bc_vm_stdin();
|
||||
if (!s && !BC_PARSE_CAN_EXEC(&G.prs)) s = bc_vm_process("");
|
||||
if (IS_BC || !G.files.len)
|
||||
s = bc_vm_stdin();
|
||||
if (!s && !BC_PARSE_CAN_EXEC(&G.prs))
|
||||
s = bc_vm_process("");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user