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 /miscutils | |
| 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>
Diffstat (limited to 'miscutils')
| -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 | ||
