bc: handle "limits" and "quit" immediately at parse time
No need to propagate a special exit code. function old new delta bc_parse_stmt 2197 2301 +104 quit - 38 +38 bc_read_line 344 349 +5 bc_program_reset 174 172 -2 bc_num_s 252 246 -6 bc_num_a 454 445 -9 bc_parse_parse 471 461 -10 bc_num_ulong 95 85 -10 bc_program_exec 4500 4478 -22 bc_vm_run 2006 1978 -28 bc_vm_process 291 139 -152 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 2/8 up/down: 147/-239) Total: -92 bytes text data bss dec hex filename 987936 485 7296 995717 f3185 busybox_old 987844 485 7296 995625 f3129 busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
01cabafd05
commit
cfdc1334c3
107
miscutils/bc.c
107
miscutils/bc.c
@ -231,8 +231,8 @@ typedef enum BcStatus {
|
||||
BC_STATUS_POSIX_FOR3,
|
||||
BC_STATUS_POSIX_BRACE,
|
||||
#endif
|
||||
BC_STATUS_QUIT,
|
||||
BC_STATUS_LIMITS,
|
||||
// BC_STATUS_QUIT,
|
||||
// BC_STATUS_LIMITS,
|
||||
|
||||
// BC_STATUS_INVALID_OPTION,
|
||||
} BcStatus;
|
||||
@ -1121,6 +1121,13 @@ static const char bc_lib[] = {
|
||||
};
|
||||
#endif // ENABLE_BC
|
||||
|
||||
static void quit(void) NORETURN;
|
||||
static void quit(void)
|
||||
{
|
||||
fflush_all();
|
||||
exit(ferror(stdout) || ferror(stderr));
|
||||
}
|
||||
|
||||
static void bc_vec_grow(BcVec *v, size_t n)
|
||||
{
|
||||
size_t cap = v->cap * 2;
|
||||
@ -1279,9 +1286,9 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt)
|
||||
|
||||
fflush(stdout);
|
||||
#if ENABLE_FEATURE_BC_SIGNALS
|
||||
if (bb_got_signal) { /* ^C was pressed */
|
||||
if (bb_got_signal) { // ^C was pressed
|
||||
intr:
|
||||
bb_got_signal = 0; /* resets G_interrupt to zero */
|
||||
bb_got_signal = 0; // resets G_interrupt to zero
|
||||
fputs(IS_BC
|
||||
? "\ninterrupt (type \"quit\" to exit)\n"
|
||||
: "\ninterrupt (type \"q\" to exit)\n"
|
||||
@ -1293,7 +1300,6 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt)
|
||||
fflush(stderr);
|
||||
|
||||
#if ENABLE_FEATURE_BC_SIGNALS
|
||||
again:
|
||||
errno = 0;
|
||||
#endif
|
||||
do {
|
||||
@ -1302,16 +1308,13 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt)
|
||||
|
||||
i = fgetc(stdin);
|
||||
|
||||
#if ENABLE_FEATURE_BC_SIGNALS
|
||||
if (bb_got_signal) /* ^C was pressed */
|
||||
goto intr;
|
||||
#endif
|
||||
|
||||
if (i == EOF) {
|
||||
#if ENABLE_FEATURE_BC_SIGNALS
|
||||
if (errno == EINTR) {
|
||||
// Both conditions appear simultaneously, check both just in case
|
||||
if (errno == EINTR || bb_got_signal) {
|
||||
// ^C was pressed
|
||||
clearerr(stdin);
|
||||
goto again;
|
||||
goto intr;
|
||||
}
|
||||
#endif
|
||||
if (ferror(stdin))
|
||||
@ -4630,9 +4633,18 @@ static BcStatus bc_parse_stmt(BcParse *p)
|
||||
|
||||
case BC_LEX_KEY_LIMITS:
|
||||
{
|
||||
// "limits" is a compile-time command,
|
||||
// the output is produced at _parse time_.
|
||||
s = bc_lex_next(&p->l);
|
||||
if (s) return s;
|
||||
s = BC_STATUS_LIMITS;
|
||||
printf("BC_BASE_MAX = %u\n", BC_MAX_OBASE);
|
||||
printf("BC_DIM_MAX = %u\n", BC_MAX_DIM);
|
||||
printf("BC_SCALE_MAX = %u\n", BC_MAX_SCALE);
|
||||
printf("BC_STRING_MAX = %u\n", BC_MAX_STRING);
|
||||
printf("BC_NAME_MAX = %u\n", BC_MAX_NAME);
|
||||
printf("BC_NUM_MAX = %u\n", BC_MAX_NUM);
|
||||
printf("MAX Exponent = %lu\n", BC_MAX_EXP);
|
||||
printf("Number of vars = %lu\n", BC_MAX_VARS);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4644,10 +4656,10 @@ static BcStatus bc_parse_stmt(BcParse *p)
|
||||
|
||||
case BC_LEX_KEY_QUIT:
|
||||
{
|
||||
// Quit is a compile-time command. We don't exit directly,
|
||||
// so the vm can clean up. Limits do the same thing.
|
||||
s = BC_STATUS_QUIT;
|
||||
break;
|
||||
// "quit" is a compile-time command. For example,
|
||||
// "if (0 == 1) quit" terminates when parsing the statement,
|
||||
// not when it is executed
|
||||
quit();
|
||||
}
|
||||
|
||||
case BC_LEX_KEY_RETURN:
|
||||
@ -4685,7 +4697,7 @@ static BcStatus bc_parse_parse(BcParse *p)
|
||||
else
|
||||
s = bc_parse_stmt(p);
|
||||
|
||||
if ((s && s != BC_STATUS_QUIT && s != BC_STATUS_LIMITS) || G_interrupt)
|
||||
if (s || G_interrupt)
|
||||
s = bc_parse_reset(p, s);
|
||||
|
||||
return s;
|
||||
@ -6283,8 +6295,8 @@ static BcStatus bc_program_nquit(void)
|
||||
|
||||
if (G.prog.stack.len < val)
|
||||
return BC_STATUS_EXEC_STACK;
|
||||
else if (G.prog.stack.len == val)
|
||||
return BC_STATUS_QUIT;
|
||||
if (G.prog.stack.len == val)
|
||||
quit();
|
||||
|
||||
bc_vec_npop(&G.prog.stack, val);
|
||||
|
||||
@ -6456,17 +6468,15 @@ static BcStatus bc_program_reset(BcStatus s)
|
||||
ip = bc_vec_top(&G.prog.stack);
|
||||
ip->idx = f->code.len;
|
||||
|
||||
if (!s && G_interrupt && !G.tty) return BC_STATUS_QUIT;
|
||||
if (!s && G_interrupt && !G.tty) quit();
|
||||
|
||||
if (!s || s == BC_STATUS_EXEC_SIGNAL) {
|
||||
if (G.ttyin) {
|
||||
fflush(stdout);
|
||||
fputs(bc_program_ready_msg, stderr);
|
||||
fflush(stderr);
|
||||
s = BC_STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
s = BC_STATUS_QUIT;
|
||||
if (!G.ttyin)
|
||||
quit();
|
||||
fflush(stdout);
|
||||
fputs(bc_program_ready_msg, stderr);
|
||||
fflush(stderr);
|
||||
s = BC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return s;
|
||||
@ -6524,7 +6534,7 @@ static BcStatus bc_program_exec(void)
|
||||
|
||||
case BC_INST_HALT:
|
||||
{
|
||||
s = BC_STATUS_QUIT;
|
||||
quit();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -6767,9 +6777,8 @@ static BcStatus bc_program_exec(void)
|
||||
case BC_INST_QUIT:
|
||||
{
|
||||
if (G.prog.stack.len <= 2)
|
||||
s = BC_STATUS_QUIT;
|
||||
else
|
||||
bc_vec_npop(&G.prog.stack, 2);
|
||||
quit();
|
||||
bc_vec_npop(&G.prog.stack, 2);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -6781,7 +6790,7 @@ static BcStatus bc_program_exec(void)
|
||||
#endif // ENABLE_DC
|
||||
}
|
||||
|
||||
if ((s && s != BC_STATUS_QUIT) || G_interrupt) s = bc_program_reset(s);
|
||||
if (s || G_interrupt) s = bc_program_reset(s);
|
||||
|
||||
// If the stack has changed, pointers may be invalid.
|
||||
ip = bc_vec_top(&G.prog.stack);
|
||||
@ -6895,30 +6904,14 @@ static BcStatus bc_vm_process(const char *text)
|
||||
|
||||
s = G.prs.parse(&G.prs);
|
||||
|
||||
if (s == BC_STATUS_LIMITS) {
|
||||
|
||||
printf("BC_BASE_MAX = %u\n", BC_MAX_OBASE);
|
||||
printf("BC_DIM_MAX = %u\n", BC_MAX_DIM);
|
||||
printf("BC_SCALE_MAX = %u\n", BC_MAX_SCALE);
|
||||
printf("BC_STRING_MAX = %u\n", BC_MAX_STRING);
|
||||
printf("BC_NAME_MAX = %u\n", BC_MAX_NAME);
|
||||
printf("BC_NUM_MAX = %u\n", BC_MAX_NUM);
|
||||
printf("MAX Exponent = %lu\n", BC_MAX_EXP);
|
||||
printf("Number of vars = %lu\n", BC_MAX_VARS);
|
||||
|
||||
s = BC_STATUS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
if (s == BC_STATUS_QUIT) return s;
|
||||
s = bc_vm_error(s, G.prs.l.f, G.prs.l.line);
|
||||
if (s) return s;
|
||||
}
|
||||
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();
|
||||
if (!s && G.tty) fflush(stdout);
|
||||
if (s && s != BC_STATUS_QUIT)
|
||||
fflush(stdout);
|
||||
if (s)
|
||||
s = bc_vm_error(bc_program_reset(s), G.prs.l.f, 0);
|
||||
}
|
||||
|
||||
@ -7021,7 +7014,7 @@ static BcStatus bc_vm_stdin(void)
|
||||
|
||||
// INPUT_EOF will always happen when stdin is
|
||||
// closed. It's not a problem in that case.
|
||||
if (s == BC_STATUS_INPUT_EOF || s == BC_STATUS_QUIT)
|
||||
if (s == BC_STATUS_INPUT_EOF)
|
||||
s = BC_STATUS_SUCCESS;
|
||||
|
||||
if (str)
|
||||
@ -7058,13 +7051,11 @@ 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 && s != BC_STATUS_QUIT) return s;
|
||||
if (s) return s;
|
||||
|
||||
if (IS_BC || !G.files.len) s = bc_vm_stdin();
|
||||
if (!s && !BC_PARSE_CAN_EXEC(&G.prs)) s = bc_vm_process("");
|
||||
|
||||
if (s == BC_STATUS_QUIT)
|
||||
s = BC_STATUS_SUCCESS;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user