From cfdc1334c3e0cfbbe41f850e426c51c37a653dfb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Dec 2018 14:02:35 +0100 Subject: 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 --- miscutils/bc.c | 107 ++++++++++++++++++++++++++------------------------------- 1 file changed, 49 insertions(+), 58 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ee6cc47ce..c3d118417 100644 --- a/miscutils/bc.c +++ b/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; } -- cgit v1.2.3