aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-12-03 14:02:35 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2018-12-05 15:43:35 +0100
commitcfdc1334c3e0cfbbe41f850e426c51c37a653dfb (patch)
tree36e563d437ede8e7022aec6cd23fbe140fb83d1d
parent01cabafd05410548bd7f539fb09dc3a8a9f48e08 (diff)
downloadbusybox-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.c107
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
1124static void quit(void) NORETURN;
1125static void quit(void)
1126{
1127 fflush_all();
1128 exit(ferror(stdout) || ferror(stderr));
1129}
1130
1124static void bc_vec_grow(BcVec *v, size_t n) 1131static 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