diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-21 20:29:34 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-21 20:29:34 +0100 |
commit | 19eee8ed7cf32de37afa53ce56c62376c880a5a8 (patch) | |
tree | 7a7e952d4f28af8b9ab7361093d40ac3a935c3ba | |
parent | 5d57bc442dfebefdd7db37c04fe2c9f1343bd08d (diff) | |
download | busybox-w32-19eee8ed7cf32de37afa53ce56c62376c880a5a8.tar.gz busybox-w32-19eee8ed7cf32de37afa53ce56c62376c880a5a8.tar.bz2 busybox-w32-19eee8ed7cf32de37afa53ce56c62376c880a5a8.zip |
bc: fix for() to not leave data on stack
function old new delta
zbc_parse_stmt_possibly_auto 1665 1697 +32
zbc_vm_process 672 701 +29
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 61/0) Total: 61 bytes
text data bss dec hex filename
981656 485 7296 989437 f18fd busybox_old
981748 485 7296 989529 f1959 busybox_unstripped
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | miscutils/bc.c | 48 | ||||
-rwxr-xr-x | testsuite/bc.tests | 15 |
2 files changed, 38 insertions, 25 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index 50e5457b9..441cb0467 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
@@ -170,6 +170,8 @@ | |||
170 | #define DEBUG_LEXER 0 | 170 | #define DEBUG_LEXER 0 |
171 | #define DEBUG_COMPILE 0 | 171 | #define DEBUG_COMPILE 0 |
172 | #define DEBUG_EXEC 0 | 172 | #define DEBUG_EXEC 0 |
173 | // This can be left enabled for production as well: | ||
174 | #define SANITY_CHECKS 1 | ||
173 | 175 | ||
174 | #if DEBUG_LEXER | 176 | #if DEBUG_LEXER |
175 | static uint8_t lex_indent; | 177 | static uint8_t lex_indent; |
@@ -1218,8 +1220,6 @@ static char** bc_program_const(size_t idx) | |||
1218 | IF_DC(return bc_vec_item(&G.prog.consts, idx);) | 1220 | IF_DC(return bc_vec_item(&G.prog.consts, idx);) |
1219 | } | 1221 | } |
1220 | 1222 | ||
1221 | |||
1222 | |||
1223 | static int bc_id_cmp(const void *e1, const void *e2) | 1223 | static int bc_id_cmp(const void *e1, const void *e2) |
1224 | { | 1224 | { |
1225 | return strcmp(((const BcId *) e1)->name, ((const BcId *) e2)->name); | 1225 | return strcmp(((const BcId *) e1)->name, ((const BcId *) e2)->name); |
@@ -4227,12 +4227,15 @@ static BC_STATUS zbc_parse_for(BcParse *p) | |||
4227 | s = zbc_lex_next(&p->l); | 4227 | s = zbc_lex_next(&p->l); |
4228 | if (s) RETURN_STATUS(s); | 4228 | if (s) RETURN_STATUS(s); |
4229 | 4229 | ||
4230 | if (p->l.t.t != BC_LEX_SCOLON) | 4230 | if (p->l.t.t != BC_LEX_SCOLON) { |
4231 | s = zbc_parse_expr(p, 0); | 4231 | s = zbc_parse_expr(p, 0); |
4232 | else | 4232 | bc_parse_push(p, BC_INST_POP); |
4233 | if (s) RETURN_STATUS(s); | ||
4234 | } else { | ||
4233 | s = bc_POSIX_does_not_allow_empty_X_expression_in_for("init"); | 4235 | s = bc_POSIX_does_not_allow_empty_X_expression_in_for("init"); |
4236 | IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s);) | ||
4237 | } | ||
4234 | 4238 | ||
4235 | if (s) RETURN_STATUS(s); | ||
4236 | if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); | 4239 | if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); |
4237 | s = zbc_lex_next(&p->l); | 4240 | s = zbc_lex_next(&p->l); |
4238 | if (s) RETURN_STATUS(s); | 4241 | if (s) RETURN_STATUS(s); |
@@ -4254,8 +4257,8 @@ static BC_STATUS zbc_parse_for(BcParse *p) | |||
4254 | bc_parse_pushNUM(p); | 4257 | bc_parse_pushNUM(p); |
4255 | s = bc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); | 4258 | s = bc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); |
4256 | } | 4259 | } |
4257 | |||
4258 | if (s) RETURN_STATUS(s); | 4260 | if (s) RETURN_STATUS(s); |
4261 | |||
4259 | if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); | 4262 | if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); |
4260 | 4263 | ||
4261 | s = zbc_lex_next(&p->l); | 4264 | s = zbc_lex_next(&p->l); |
@@ -4267,12 +4270,14 @@ static BC_STATUS zbc_parse_for(BcParse *p) | |||
4267 | bc_vec_push(&p->conds, &update_idx); | 4270 | bc_vec_push(&p->conds, &update_idx); |
4268 | bc_vec_push(&p->func->labels, &p->func->code.len); | 4271 | bc_vec_push(&p->func->labels, &p->func->code.len); |
4269 | 4272 | ||
4270 | if (p->l.t.t != BC_LEX_RPAREN) | 4273 | if (p->l.t.t != BC_LEX_RPAREN) { |
4271 | s = zbc_parse_expr(p, 0); | 4274 | s = zbc_parse_expr(p, 0); |
4272 | else | 4275 | bc_parse_push(p, BC_INST_POP); |
4276 | if (s) RETURN_STATUS(s); | ||
4277 | } else { | ||
4273 | s = bc_POSIX_does_not_allow_empty_X_expression_in_for("update"); | 4278 | s = bc_POSIX_does_not_allow_empty_X_expression_in_for("update"); |
4274 | 4279 | IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s);) | |
4275 | if (s) RETURN_STATUS(s); | 4280 | } |
4276 | 4281 | ||
4277 | if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); | 4282 | if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); |
4278 | bc_parse_pushJUMP(p, cond_idx); | 4283 | bc_parse_pushJUMP(p, cond_idx); |
@@ -6434,12 +6439,13 @@ static BC_STATUS zbc_program_exec(void) | |||
6434 | BcFunc *func = bc_program_func(ip->func); | 6439 | BcFunc *func = bc_program_func(ip->func); |
6435 | char *code = func->code.v; | 6440 | char *code = func->code.v; |
6436 | 6441 | ||
6437 | dbg_exec("func:%zd bytes:%zd ip:%zd", ip->func, func->code.len, ip->idx); | 6442 | dbg_exec("func:%zd bytes:%zd ip:%zd results.len:%d", |
6443 | ip->func, func->code.len, ip->idx, G.prog.results.len); | ||
6438 | while (ip->idx < func->code.len) { | 6444 | while (ip->idx < func->code.len) { |
6439 | BcStatus s = BC_STATUS_SUCCESS; | 6445 | BcStatus s = BC_STATUS_SUCCESS; |
6440 | char inst = code[ip->idx++]; | 6446 | char inst = code[ip->idx++]; |
6441 | 6447 | ||
6442 | dbg_exec("inst at %zd:%d", ip->idx - 1, inst); | 6448 | dbg_exec("inst at %zd:%d results.len:%d", ip->idx - 1, inst, G.prog.results.len); |
6443 | switch (inst) { | 6449 | switch (inst) { |
6444 | #if ENABLE_BC | 6450 | #if ENABLE_BC |
6445 | case BC_INST_JUMP_ZERO: { | 6451 | case BC_INST_JUMP_ZERO: { |
@@ -6671,7 +6677,6 @@ static BC_STATUS zbc_program_exec(void) | |||
6671 | } | 6677 | } |
6672 | 6678 | ||
6673 | fflush_and_check(); | 6679 | fflush_and_check(); |
6674 | |||
6675 | } | 6680 | } |
6676 | 6681 | ||
6677 | RETURN_STATUS(BC_STATUS_SUCCESS); | 6682 | RETURN_STATUS(BC_STATUS_SUCCESS); |
@@ -6723,23 +6728,16 @@ static BC_STATUS zbc_vm_process(const char *text) | |||
6723 | // storage. | 6728 | // storage. |
6724 | if (IS_BC) { | 6729 | if (IS_BC) { |
6725 | BcFunc *f; | 6730 | BcFunc *f; |
6726 | BcInstPtr *ip; | 6731 | BcInstPtr *ip = (void*)G.prog.exestack.v; |
6727 | |||
6728 | //FIXME: this does not clear up the stack | ||
6729 | //for(i=1; i<3; i++) { | ||
6730 | // i | ||
6731 | // if(i==2) continue | ||
6732 | // 77 | ||
6733 | //} | ||
6734 | // if (G.prog.results.len != 0) | ||
6735 | // bb_error_msg_and_die("data stack not empty: %d slots", G.prog.results.len); | ||
6736 | 6732 | ||
6733 | #if SANITY_CHECKS | ||
6734 | if (G.prog.results.len != 0) | ||
6735 | bb_error_msg_and_die("data stack not empty: %d slots", G.prog.results.len); | ||
6737 | if (G.prog.exestack.len != 1) // should be empty | 6736 | if (G.prog.exestack.len != 1) // should be empty |
6738 | bb_error_msg_and_die("BUG:call stack"); | 6737 | bb_error_msg_and_die("BUG:call stack"); |
6739 | |||
6740 | ip = (void*)G.prog.exestack.v; | ||
6741 | if (ip->func != BC_PROG_MAIN) | 6738 | if (ip->func != BC_PROG_MAIN) |
6742 | bb_error_msg_and_die("BUG:not MAIN"); | 6739 | bb_error_msg_and_die("BUG:not MAIN"); |
6740 | #endif | ||
6743 | //bb_error_msg("ip->func:%d >idx:%d >len:%d", ip->func, ip->idx, ip->len); | 6741 | //bb_error_msg("ip->func:%d >idx:%d >len:%d", ip->func, ip->idx, ip->len); |
6744 | f = bc_program_func_BC_PROG_MAIN(); | 6742 | f = bc_program_func_BC_PROG_MAIN(); |
6745 | //bb_error_msg("MAIN->code.len:%d >strs.len:%d >consts.len:%d", f->code.len, f->strs.len, f->consts.len); // labels, autos, nparams | 6743 | //bb_error_msg("MAIN->code.len:%d >strs.len:%d >consts.len:%d", f->code.len, f->strs.len, f->consts.len); // labels, autos, nparams |
diff --git a/testsuite/bc.tests b/testsuite/bc.tests index edff209bb..b3ce894ee 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests | |||
@@ -56,6 +56,21 @@ testing "bc for(;;)" \ | |||
56 | "2\n3\n2\n9\n" \ | 56 | "2\n3\n2\n9\n" \ |
57 | "" "i=2; for (;;) { 2; if(--i==0) break; 3; }; 9" | 57 | "" "i=2; for (;;) { 2; if(--i==0) break; 3; }; 9" |
58 | 58 | ||
59 | testing "bc for (;cond;)" \ | ||
60 | "bc" \ | ||
61 | "1\n2\n3\n9\n" \ | ||
62 | "" "i=0; for(;i<3;)++i; 9" | ||
63 | |||
64 | testing "bc for (;cond;upd)" \ | ||
65 | "bc" \ | ||
66 | "1\n2\n3\n9\n" \ | ||
67 | "" "i=1; for(;i<4;i++)i; 9" | ||
68 | |||
69 | testing "bc for (init;cond;upd)" \ | ||
70 | "bc" \ | ||
71 | "1\n2\n3\n9\n" \ | ||
72 | "" "for(i=1;i<4;i++)i; 9" | ||
73 | |||
59 | testing "bc define auto" \ | 74 | testing "bc define auto" \ |
60 | "bc" \ | 75 | "bc" \ |
61 | "8\n9\n" \ | 76 | "8\n9\n" \ |