diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-03 14:02:35 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-05 15:43:35 +0100 |
commit | cfdc1334c3e0cfbbe41f850e426c51c37a653dfb (patch) | |
tree | 36e563d437ede8e7022aec6cd23fbe140fb83d1d | |
parent | 01cabafd05410548bd7f539fb09dc3a8a9f48e08 (diff) | |
download | busybox-w32-cfdc1334c3e0cfbbe41f850e426c51c37a653dfb.tar.gz busybox-w32-cfdc1334c3e0cfbbe41f850e426c51c37a653dfb.tar.bz2 busybox-w32-cfdc1334c3e0cfbbe41f850e426c51c37a653dfb.zip |
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>
-rw-r--r-- | miscutils/bc.c | 107 |
1 files 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 { | |||
231 | BC_STATUS_POSIX_FOR3, | 231 | BC_STATUS_POSIX_FOR3, |
232 | BC_STATUS_POSIX_BRACE, | 232 | BC_STATUS_POSIX_BRACE, |
233 | #endif | 233 | #endif |
234 | BC_STATUS_QUIT, | 234 | // BC_STATUS_QUIT, |
235 | BC_STATUS_LIMITS, | 235 | // BC_STATUS_LIMITS, |
236 | 236 | ||
237 | // BC_STATUS_INVALID_OPTION, | 237 | // BC_STATUS_INVALID_OPTION, |
238 | } BcStatus; | 238 | } BcStatus; |
@@ -1121,6 +1121,13 @@ static const char bc_lib[] = { | |||
1121 | }; | 1121 | }; |
1122 | #endif // ENABLE_BC | 1122 | #endif // ENABLE_BC |
1123 | 1123 | ||
1124 | static void quit(void) NORETURN; | ||
1125 | static void quit(void) | ||
1126 | { | ||
1127 | fflush_all(); | ||
1128 | exit(ferror(stdout) || ferror(stderr)); | ||
1129 | } | ||
1130 | |||
1124 | static void bc_vec_grow(BcVec *v, size_t n) | 1131 | static void bc_vec_grow(BcVec *v, size_t n) |
1125 | { | 1132 | { |
1126 | size_t cap = v->cap * 2; | 1133 | size_t cap = v->cap * 2; |
@@ -1279,9 +1286,9 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) | |||
1279 | 1286 | ||
1280 | fflush(stdout); | 1287 | fflush(stdout); |
1281 | #if ENABLE_FEATURE_BC_SIGNALS | 1288 | #if ENABLE_FEATURE_BC_SIGNALS |
1282 | if (bb_got_signal) { /* ^C was pressed */ | 1289 | if (bb_got_signal) { // ^C was pressed |
1283 | intr: | 1290 | intr: |
1284 | bb_got_signal = 0; /* resets G_interrupt to zero */ | 1291 | bb_got_signal = 0; // resets G_interrupt to zero |
1285 | fputs(IS_BC | 1292 | fputs(IS_BC |
1286 | ? "\ninterrupt (type \"quit\" to exit)\n" | 1293 | ? "\ninterrupt (type \"quit\" to exit)\n" |
1287 | : "\ninterrupt (type \"q\" to exit)\n" | 1294 | : "\ninterrupt (type \"q\" to exit)\n" |
@@ -1293,7 +1300,6 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) | |||
1293 | fflush(stderr); | 1300 | fflush(stderr); |
1294 | 1301 | ||
1295 | #if ENABLE_FEATURE_BC_SIGNALS | 1302 | #if ENABLE_FEATURE_BC_SIGNALS |
1296 | again: | ||
1297 | errno = 0; | 1303 | errno = 0; |
1298 | #endif | 1304 | #endif |
1299 | do { | 1305 | do { |
@@ -1302,16 +1308,13 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) | |||
1302 | 1308 | ||
1303 | i = fgetc(stdin); | 1309 | i = fgetc(stdin); |
1304 | 1310 | ||
1305 | #if ENABLE_FEATURE_BC_SIGNALS | ||
1306 | if (bb_got_signal) /* ^C was pressed */ | ||
1307 | goto intr; | ||
1308 | #endif | ||
1309 | |||
1310 | if (i == EOF) { | 1311 | if (i == EOF) { |
1311 | #if ENABLE_FEATURE_BC_SIGNALS | 1312 | #if ENABLE_FEATURE_BC_SIGNALS |
1312 | if (errno == EINTR) { | 1313 | // Both conditions appear simultaneously, check both just in case |
1314 | if (errno == EINTR || bb_got_signal) { | ||
1315 | // ^C was pressed | ||
1313 | clearerr(stdin); | 1316 | clearerr(stdin); |
1314 | goto again; | 1317 | goto intr; |
1315 | } | 1318 | } |
1316 | #endif | 1319 | #endif |
1317 | if (ferror(stdin)) | 1320 | if (ferror(stdin)) |
@@ -4630,9 +4633,18 @@ static BcStatus bc_parse_stmt(BcParse *p) | |||
4630 | 4633 | ||
4631 | case BC_LEX_KEY_LIMITS: | 4634 | case BC_LEX_KEY_LIMITS: |
4632 | { | 4635 | { |
4636 | // "limits" is a compile-time command, | ||
4637 | // the output is produced at _parse time_. | ||
4633 | s = bc_lex_next(&p->l); | 4638 | s = bc_lex_next(&p->l); |
4634 | if (s) return s; | 4639 | if (s) return s; |
4635 | s = BC_STATUS_LIMITS; | 4640 | printf("BC_BASE_MAX = %u\n", BC_MAX_OBASE); |
4641 | printf("BC_DIM_MAX = %u\n", BC_MAX_DIM); | ||
4642 | printf("BC_SCALE_MAX = %u\n", BC_MAX_SCALE); | ||
4643 | printf("BC_STRING_MAX = %u\n", BC_MAX_STRING); | ||
4644 | printf("BC_NAME_MAX = %u\n", BC_MAX_NAME); | ||
4645 | printf("BC_NUM_MAX = %u\n", BC_MAX_NUM); | ||
4646 | printf("MAX Exponent = %lu\n", BC_MAX_EXP); | ||
4647 | printf("Number of vars = %lu\n", BC_MAX_VARS); | ||
4636 | break; | 4648 | break; |
4637 | } | 4649 | } |
4638 | 4650 | ||
@@ -4644,10 +4656,10 @@ static BcStatus bc_parse_stmt(BcParse *p) | |||
4644 | 4656 | ||
4645 | case BC_LEX_KEY_QUIT: | 4657 | case BC_LEX_KEY_QUIT: |
4646 | { | 4658 | { |
4647 | // Quit is a compile-time command. We don't exit directly, | 4659 | // "quit" is a compile-time command. For example, |
4648 | // so the vm can clean up. Limits do the same thing. | 4660 | // "if (0 == 1) quit" terminates when parsing the statement, |
4649 | s = BC_STATUS_QUIT; | 4661 | // not when it is executed |
4650 | break; | 4662 | quit(); |
4651 | } | 4663 | } |
4652 | 4664 | ||
4653 | case BC_LEX_KEY_RETURN: | 4665 | case BC_LEX_KEY_RETURN: |
@@ -4685,7 +4697,7 @@ static BcStatus bc_parse_parse(BcParse *p) | |||
4685 | else | 4697 | else |
4686 | s = bc_parse_stmt(p); | 4698 | s = bc_parse_stmt(p); |
4687 | 4699 | ||
4688 | if ((s && s != BC_STATUS_QUIT && s != BC_STATUS_LIMITS) || G_interrupt) | 4700 | if (s || G_interrupt) |
4689 | s = bc_parse_reset(p, s); | 4701 | s = bc_parse_reset(p, s); |
4690 | 4702 | ||
4691 | return s; | 4703 | return s; |
@@ -6283,8 +6295,8 @@ static BcStatus bc_program_nquit(void) | |||
6283 | 6295 | ||
6284 | if (G.prog.stack.len < val) | 6296 | if (G.prog.stack.len < val) |
6285 | return BC_STATUS_EXEC_STACK; | 6297 | return BC_STATUS_EXEC_STACK; |
6286 | else if (G.prog.stack.len == val) | 6298 | if (G.prog.stack.len == val) |
6287 | return BC_STATUS_QUIT; | 6299 | quit(); |
6288 | 6300 | ||
6289 | bc_vec_npop(&G.prog.stack, val); | 6301 | bc_vec_npop(&G.prog.stack, val); |
6290 | 6302 | ||
@@ -6456,17 +6468,15 @@ static BcStatus bc_program_reset(BcStatus s) | |||
6456 | ip = bc_vec_top(&G.prog.stack); | 6468 | ip = bc_vec_top(&G.prog.stack); |
6457 | ip->idx = f->code.len; | 6469 | ip->idx = f->code.len; |
6458 | 6470 | ||
6459 | if (!s && G_interrupt && !G.tty) return BC_STATUS_QUIT; | 6471 | if (!s && G_interrupt && !G.tty) quit(); |
6460 | 6472 | ||
6461 | if (!s || s == BC_STATUS_EXEC_SIGNAL) { | 6473 | if (!s || s == BC_STATUS_EXEC_SIGNAL) { |
6462 | if (G.ttyin) { | 6474 | if (!G.ttyin) |
6463 | fflush(stdout); | 6475 | quit(); |
6464 | fputs(bc_program_ready_msg, stderr); | 6476 | fflush(stdout); |
6465 | fflush(stderr); | 6477 | fputs(bc_program_ready_msg, stderr); |
6466 | s = BC_STATUS_SUCCESS; | 6478 | fflush(stderr); |
6467 | } | 6479 | s = BC_STATUS_SUCCESS; |
6468 | else | ||
6469 | s = BC_STATUS_QUIT; | ||
6470 | } | 6480 | } |
6471 | 6481 | ||
6472 | return s; | 6482 | return s; |
@@ -6524,7 +6534,7 @@ static BcStatus bc_program_exec(void) | |||
6524 | 6534 | ||
6525 | case BC_INST_HALT: | 6535 | case BC_INST_HALT: |
6526 | { | 6536 | { |
6527 | s = BC_STATUS_QUIT; | 6537 | quit(); |
6528 | break; | 6538 | break; |
6529 | } | 6539 | } |
6530 | 6540 | ||
@@ -6767,9 +6777,8 @@ static BcStatus bc_program_exec(void) | |||
6767 | case BC_INST_QUIT: | 6777 | case BC_INST_QUIT: |
6768 | { | 6778 | { |
6769 | if (G.prog.stack.len <= 2) | 6779 | if (G.prog.stack.len <= 2) |
6770 | s = BC_STATUS_QUIT; | 6780 | quit(); |
6771 | else | 6781 | bc_vec_npop(&G.prog.stack, 2); |
6772 | bc_vec_npop(&G.prog.stack, 2); | ||
6773 | break; | 6782 | break; |
6774 | } | 6783 | } |
6775 | 6784 | ||
@@ -6781,7 +6790,7 @@ static BcStatus bc_program_exec(void) | |||
6781 | #endif // ENABLE_DC | 6790 | #endif // ENABLE_DC |
6782 | } | 6791 | } |
6783 | 6792 | ||
6784 | if ((s && s != BC_STATUS_QUIT) || G_interrupt) s = bc_program_reset(s); | 6793 | if (s || G_interrupt) s = bc_program_reset(s); |
6785 | 6794 | ||
6786 | // If the stack has changed, pointers may be invalid. | 6795 | // If the stack has changed, pointers may be invalid. |
6787 | ip = bc_vec_top(&G.prog.stack); | 6796 | ip = bc_vec_top(&G.prog.stack); |
@@ -6895,30 +6904,14 @@ static BcStatus bc_vm_process(const char *text) | |||
6895 | 6904 | ||
6896 | s = G.prs.parse(&G.prs); | 6905 | s = G.prs.parse(&G.prs); |
6897 | 6906 | ||
6898 | if (s == BC_STATUS_LIMITS) { | 6907 | s = bc_vm_error(s, G.prs.l.f, G.prs.l.line); |
6899 | 6908 | if (s) return s; | |
6900 | printf("BC_BASE_MAX = %u\n", BC_MAX_OBASE); | ||
6901 | printf("BC_DIM_MAX = %u\n", BC_MAX_DIM); | ||
6902 | printf("BC_SCALE_MAX = %u\n", BC_MAX_SCALE); | ||
6903 | printf("BC_STRING_MAX = %u\n", BC_MAX_STRING); | ||
6904 | printf("BC_NAME_MAX = %u\n", BC_MAX_NAME); | ||
6905 | printf("BC_NUM_MAX = %u\n", BC_MAX_NUM); | ||
6906 | printf("MAX Exponent = %lu\n", BC_MAX_EXP); | ||
6907 | printf("Number of vars = %lu\n", BC_MAX_VARS); | ||
6908 | |||
6909 | s = BC_STATUS_SUCCESS; | ||
6910 | } | ||
6911 | else { | ||
6912 | if (s == BC_STATUS_QUIT) return s; | ||
6913 | s = bc_vm_error(s, G.prs.l.f, G.prs.l.line); | ||
6914 | if (s) return s; | ||
6915 | } | ||
6916 | } | 6909 | } |
6917 | 6910 | ||
6918 | if (BC_PARSE_CAN_EXEC(&G.prs)) { | 6911 | if (BC_PARSE_CAN_EXEC(&G.prs)) { |
6919 | s = bc_program_exec(); | 6912 | s = bc_program_exec(); |
6920 | if (!s && G.tty) fflush(stdout); | 6913 | fflush(stdout); |
6921 | if (s && s != BC_STATUS_QUIT) | 6914 | if (s) |
6922 | s = bc_vm_error(bc_program_reset(s), G.prs.l.f, 0); | 6915 | s = bc_vm_error(bc_program_reset(s), G.prs.l.f, 0); |
6923 | } | 6916 | } |
6924 | 6917 | ||
@@ -7021,7 +7014,7 @@ static BcStatus bc_vm_stdin(void) | |||
7021 | 7014 | ||
7022 | // INPUT_EOF will always happen when stdin is | 7015 | // INPUT_EOF will always happen when stdin is |
7023 | // closed. It's not a problem in that case. | 7016 | // closed. It's not a problem in that case. |
7024 | if (s == BC_STATUS_INPUT_EOF || s == BC_STATUS_QUIT) | 7017 | if (s == BC_STATUS_INPUT_EOF) |
7025 | s = BC_STATUS_SUCCESS; | 7018 | s = BC_STATUS_SUCCESS; |
7026 | 7019 | ||
7027 | if (str) | 7020 | if (str) |
@@ -7058,13 +7051,11 @@ static BcStatus bc_vm_exec(void) | |||
7058 | 7051 | ||
7059 | for (i = 0; !s && i < G.files.len; ++i) | 7052 | for (i = 0; !s && i < G.files.len; ++i) |
7060 | s = bc_vm_file(*((char **) bc_vec_item(&G.files, i))); | 7053 | s = bc_vm_file(*((char **) bc_vec_item(&G.files, i))); |
7061 | if (s && s != BC_STATUS_QUIT) return s; | 7054 | if (s) return s; |
7062 | 7055 | ||
7063 | if (IS_BC || !G.files.len) s = bc_vm_stdin(); | 7056 | if (IS_BC || !G.files.len) s = bc_vm_stdin(); |
7064 | if (!s && !BC_PARSE_CAN_EXEC(&G.prs)) s = bc_vm_process(""); | 7057 | if (!s && !BC_PARSE_CAN_EXEC(&G.prs)) s = bc_vm_process(""); |
7065 | 7058 | ||
7066 | if (s == BC_STATUS_QUIT) | ||
7067 | s = BC_STATUS_SUCCESS; | ||
7068 | return s; | 7059 | return s; |
7069 | } | 7060 | } |
7070 | 7061 | ||