From ab3c568fd869e84a7862f3450a4690d3d7b60704 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Dec 2018 16:32:36 +0100 Subject: bc: simplify ^C handling It's still buggy: if SIGINT would interrupt e.g. output write(), the result would not be as intended: >>> while ( 1 ) print 1 ... 11111111111111111111111111111111111111111111111111111111111111111111\ 11111111111111111111111111111111111111111111111111111111111111111111\ ^Cready for more input interrupt (type "quit" to exit) >>> bc: output error function old new delta dc_parse_parse 58 53 -5 bc_parse_parse 476 471 -5 bc_num_d 609 604 -5 bc_num_cmp 299 294 -5 bc_num_compare 90 84 -6 bc_parse_expr 2222 2215 -7 bc_num_subArrays 82 74 -8 dc_main 72 62 -10 bc_main 72 62 -10 bc_program_exec 4413 4401 -12 bc_num_a 491 474 -17 bc_read_line 364 344 -20 bc_num_p 540 518 -22 bc_program_reset 192 168 -24 bc_num_k 1031 1005 -26 bc_vm_run 2382 2317 -65 bc_vm_sig 97 - -97 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 0/16 up/down: 0/-344) Total: -344 bytes text data bss dec hex filename 989372 485 7296 997153 f3721 busybox_old 989028 485 7296 996809 f35c9 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 139 ++++++++++++++++++++++++--------------------------------- 1 file changed, 59 insertions(+), 80 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index e13b228..72afb68 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -826,16 +826,8 @@ struct globals { char *env_args; - unsigned sig; //counter? - unsigned sigc; //counter? - smallint signe; //flag - smallint tty; smallint ttyin; - -#if ENABLE_FEATURE_BC_SIGNALS - const char *sig_msg; -#endif } FIX_ALIASING; #define G (*ptr_to_globals) #define INIT_G() do { \ @@ -844,6 +836,7 @@ struct globals { #define G_posix (ENABLE_BC && (G.flags & BC_FLAG_S)) #define G_warn (ENABLE_BC && (G.flags & BC_FLAG_W)) #define G_exreg (ENABLE_DC && (G.flags & BC_FLAG_X)) +#define G_interrupt (ENABLE_FEATURE_BC_SIGNALS ? bb_got_signal : 0) #define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b')) @@ -1349,36 +1342,47 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) int i; signed char c; - if (G.ttyin && !G_posix) { - fputs(prompt, stderr); - fflush(stderr); - } - bc_vec_npop(vec, vec->len); + fflush(stdout); +#if ENABLE_FEATURE_BC_SIGNALS + if (bb_got_signal) { /* ^C was pressed */ + intr: + fputs(IS_BC + ? "\ninterrupt (type \"quit\" to exit)\n" + : "\ninterrupt (type \"q\" to exit)\n" + , stderr); + } + bb_got_signal = 0; /* resets G_interrupt to zero */ +#endif + if (G.ttyin && !G_posix) + fputs(prompt, stderr); + fflush(stderr); + +#if ENABLE_FEATURE_BC_SIGNALS + again: + errno = 0; +#endif do { if (ferror(stdout) || ferror(stderr)) bb_perror_msg_and_die("output error"); - errno = 0; 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) { - G.sigc = G.sig; - G.signe = 0; - if (G.ttyin) { - fputs(bc_program_ready_msg, stderr); - if (!G_posix) fputs(prompt, stderr); - fflush(stderr); - } clearerr(stdin); - continue; + goto again; } +#endif if (ferror(stdin)) bb_perror_msg_and_die("input error"); -#endif return BC_STATUS_INPUT_EOF; } @@ -1471,20 +1475,20 @@ static BcStatus bc_num_subArrays(BcDig *restrict a, BcDig *restrict b, size_t len) { size_t i, j; - for (i = 0; !G.signe && i < len; ++i) { - for (a[i] -= b[i], j = 0; !G.signe && a[i + j] < 0;) { + for (i = 0; !G_interrupt && i < len; ++i) { + for (a[i] -= b[i], j = 0; !G_interrupt && a[i + j] < 0;) { a[i + j++] += 10; a[i + j] -= 1; } } - return G.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; + return G_interrupt ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; } static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len) { size_t i; int c = 0; - for (i = len - 1; !G.signe && i < len && !(c = a[i] - b[i]); --i); + for (i = len - 1; !G_interrupt && i < len && !(c = a[i] - b[i]); --i); return BC_NUM_NEG(i + 1, c < 0); } @@ -1530,7 +1534,7 @@ static ssize_t bc_num_cmp(BcNum *a, BcNum *b) cmp = bc_num_compare(max_num, min_num, b_int + min); if (cmp != 0) return BC_NUM_NEG(cmp, (!a_max) != neg); - for (max_num -= diff, i = diff - 1; !G.signe && i < diff; --i) { + for (max_num -= diff, i = diff - 1; !G_interrupt && i < diff; --i) { if (max_num[i]) return BC_NUM_NEG(1, (!a_max) != neg); } @@ -1689,13 +1693,13 @@ static BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) ptr = ptr_b; } - for (carry = 0, i = 0; !G.signe && i < min_rdx + min_int; ++i, ++c->len) { + for (carry = 0, i = 0; !G_interrupt && i < min_rdx + min_int; ++i, ++c->len) { in = ((int) ptr_a[i]) + ((int) ptr_b[i]) + carry; carry = in / 10; ptr_c[i] = (BcDig)(in % 10); } - for (; !G.signe && i < max + min_rdx; ++i, ++c->len) { + for (; !G_interrupt && i < max + min_rdx; ++i, ++c->len) { in = ((int) ptr[i]) + carry; carry = in / 10; ptr_c[i] = (BcDig)(in % 10); @@ -1703,7 +1707,7 @@ static BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) if (carry != 0) c->num[c->len++] = (BcDig) carry; - return G.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; + return G_interrupt ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; } static BcStatus bc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) @@ -1778,7 +1782,7 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp; bool aone = BC_NUM_ONE(a); - if (G.signe) return BC_STATUS_EXEC_SIGNAL; + if (G_interrupt) return BC_STATUS_EXEC_SIGNAL; if (a->len == 0 || b->len == 0) { bc_num_zero(c); return BC_STATUS_SUCCESS; @@ -1796,9 +1800,9 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, memset(c->num, 0, sizeof(BcDig) * c->cap); c->len = carry = len = 0; - for (i = 0; !G.signe && i < b->len; ++i) { + for (i = 0; !G_interrupt && i < b->len; ++i) { - for (j = 0; !G.signe && j < a->len; ++j) { + for (j = 0; !G_interrupt && j < a->len; ++j) { int in = (int) c->num[i + j]; in += ((int) a->num[j]) * ((int) b->num[i]) + carry; carry = in / 10; @@ -1812,7 +1816,7 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, c->len = len; - return G.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; + return G_interrupt ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; } bc_num_init(&l1, max); @@ -1962,7 +1966,7 @@ static BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) c->len = cp.len; p = b->num; - for (i = end - 1; !G.signe && !s && i < end; --i) { + for (i = end - 1; !G_interrupt && !s && i < end; --i) { n = cp.num + i; for (q = 0; (!s && n[len] != 0) || bc_num_compare(n, p, len) >= 0; ++q) s = bc_num_subArrays(n, p, len); @@ -2062,20 +2066,20 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) b->neg = neg; - for (powrdx = a->rdx; !G.signe && !(pow & 1); pow >>= 1) { + for (powrdx = a->rdx; !G_interrupt && !(pow & 1); pow >>= 1) { powrdx <<= 1; s = bc_num_mul(©, ©, ©, powrdx); if (s) goto err; } - if (G.signe) { + if (G_interrupt) { s = BC_STATUS_EXEC_SIGNAL; goto err; } bc_num_copy(c, ©); - for (resrdx = powrdx, pow >>= 1; !G.signe && pow != 0; pow >>= 1) { + for (resrdx = powrdx, pow >>= 1; !G_interrupt && pow != 0; pow >>= 1) { powrdx <<= 1; s = bc_num_mul(©, ©, ©, powrdx); @@ -2093,7 +2097,7 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) if (s) goto err; } - if (G.signe) { + if (G_interrupt) { s = BC_STATUS_EXEC_SIGNAL; goto err; } @@ -2650,7 +2654,7 @@ static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) resrdx = scale + 2; len = BC_NUM_INT(x0) + resrdx - 1; - while (!G.signe && (cmp != 0 || digs < len)) { + while (!G_interrupt && (cmp != 0 || digs < len)) { s = bc_num_div(a, x0, &f, resrdx); if (s) goto err; @@ -2678,7 +2682,7 @@ static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) x1 = temp; } - if (G.signe) { + if (G_interrupt) { s = BC_STATUS_EXEC_SIGNAL; goto err; } @@ -4775,7 +4779,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.signe) + if ((s && s != BC_STATUS_QUIT && s != BC_STATUS_LIMITS) || G_interrupt) s = bc_parse_reset(p, s); return s; @@ -4795,7 +4799,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) paren_expr = rprn = done = get_token = assign = false; bin_last = true; - for (; !G.signe && !s && !done && bc_parse_exprs[t]; t = p->l.t.t) { + for (; !G_interrupt && !s && !done && bc_parse_exprs[t]; t = p->l.t.t) { switch (t) { case BC_LEX_OP_INC: @@ -4989,7 +4993,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) } if (s) return s; - if (G.signe) return BC_STATUS_EXEC_SIGNAL; + if (G_interrupt) return BC_STATUS_EXEC_SIGNAL; while (p->ops.len > ops_bgn) { @@ -5249,7 +5253,7 @@ static BcStatus dc_parse_parse(BcParse *p) else s = dc_parse_expr(p, 0); - if (s || G.signe) s = bc_parse_reset(p, s); + if (s || G_interrupt) s = bc_parse_reset(p, s); return s; } @@ -6632,13 +6636,11 @@ static BcStatus bc_program_reset(BcProgram *p, BcStatus s) ip = bc_vec_top(&p->stack); ip->idx = f->code.len; - if (!s && G.signe && !G.tty) return BC_STATUS_QUIT; - - G.sigc += G.signe; - G.signe = G.sig != G.sigc; + if (!s && G_interrupt && !G.tty) return BC_STATUS_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; @@ -6959,7 +6961,7 @@ static BcStatus bc_program_exec(BcProgram *p) #endif // ENABLE_DC } - if ((s && s != BC_STATUS_QUIT) || G.signe) s = bc_program_reset(p, s); + if ((s && s != BC_STATUS_QUIT) || G_interrupt) s = bc_program_reset(p, s); // If the stack has changed, pointers may be invalid. ip = bc_vec_top(&p->stack); @@ -6970,19 +6972,6 @@ static BcStatus bc_program_exec(BcProgram *p) return s; } -#if ENABLE_FEATURE_BC_SIGNALS -static void bc_vm_sig(int sig) -{ - int err = errno; - size_t len = strlen(G.sig_msg); - if (sig == SIGINT && write(2, G.sig_msg, len) == (ssize_t) len) { - G.signe = G.sig == G.sigc; - G.sig += G.signe; - } - errno = err; -} -#endif - static void bc_vm_info(void) { printf("%s "BB_VER"\n" @@ -7268,21 +7257,17 @@ static void bc_vm_free(void) static void bc_vm_init(const char *env_len) { size_t len = bc_vm_envLen(env_len); -#if ENABLE_FEATURE_BC_SIGNALS - struct sigaction sa; - sigemptyset(&sa.sa_mask); - sa.sa_handler = bc_vm_sig; - sa.sa_flags = 0; - sigaction(SIGINT, &sa, NULL); +#if ENABLE_FEATURE_BC_SIGNALS + signal_no_SA_RESTART_empty_mask(SIGINT, record_signo); #endif bc_vec_init(&G.files, sizeof(char *), NULL); -#if ENABLE_BC - G.flags |= BC_FLAG_S * IS_BC * (getenv("POSIXLY_CORRECT") != NULL); - if (IS_BC) bc_vm_envArgs(); -#endif + if (IS_BC) { + G.flags |= BC_FLAG_S * (getenv("POSIXLY_CORRECT") != NULL); + bc_vm_envArgs(); + } bc_program_init(&G.prog, len, G.init, G.exp); G.init(&G.prs, &G.prog, BC_PROG_MAIN); @@ -7311,9 +7296,6 @@ int bc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int bc_main(int argc, char **argv) { INIT_G(); -# if ENABLE_FEATURE_BC_SIGNALS - G.sig_msg = "\ninterrupt (type \"quit\" to exit)\n"; -# endif G.init = bc_parse_init; G.exp = bc_parse_expression; G.sbgn = G.send = '"'; @@ -7327,9 +7309,6 @@ int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int dc_main(int argc, char **argv) { INIT_G(); -# if ENABLE_FEATURE_BC_SIGNALS - G.sig_msg = "\ninterrupt (type \"q\" to exit)\n"; -# endif G.init = dc_parse_init; G.exp = dc_parse_expr; G.sbgn = '['; -- cgit v1.1