aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-12-16 17:30:35 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2018-12-16 17:30:35 +0100
commit202dd1943c90dea3c5c3365dd75d4e7ac9499c5f (patch)
treeb8673fed2a601867b3ecb46cf313e6d60f548fed
parente9519e44a65fa80fa473cfd2041af4e7f428b81a (diff)
downloadbusybox-w32-202dd1943c90dea3c5c3365dd75d4e7ac9499c5f.tar.gz
busybox-w32-202dd1943c90dea3c5c3365dd75d4e7ac9499c5f.tar.bz2
busybox-w32-202dd1943c90dea3c5c3365dd75d4e7ac9499c5f.zip
bc: fixes for multi-line if/while/for
function old new delta zbc_vm_process 561 589 +28 zbc_lex_next_and_skip_NLINE - 22 +22 zbc_parse_stmt_possibly_auto 2232 2253 +21 zbc_lex_skip_if_at_NLINE - 14 +14 zbc_lex_number 192 200 +8 zbc_num_divmod 150 156 +6 bc_vm_run 134 139 +5 bc_vm_init 757 760 +3 bc_num_printNewline 51 54 +3 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 7/0 up/down: 110/0) Total: 110 bytes text data bss dec hex filename 982138 485 7296 989919 f1adf busybox_old 982275 485 7296 990056 f1b68 busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--miscutils/bc.c43
-rwxr-xr-xtestsuite/bc.tests10
2 files changed, 45 insertions, 8 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c
index 4dc382476..a5d7a01c0 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -3018,6 +3018,29 @@ static BC_STATUS zbc_lex_next(BcLex *l)
3018# define zbc_lex_next(...) (zbc_lex_next(__VA_ARGS__), BC_STATUS_SUCCESS) 3018# define zbc_lex_next(...) (zbc_lex_next(__VA_ARGS__), BC_STATUS_SUCCESS)
3019#endif 3019#endif
3020 3020
3021static BC_STATUS zbc_lex_skip_if_at_NLINE(BcLex *l)
3022{
3023 if (l->t.t == BC_LEX_NLINE)
3024 RETURN_STATUS(zbc_lex_next(l));
3025 RETURN_STATUS(BC_STATUS_SUCCESS);
3026}
3027#if ERRORS_ARE_FATAL
3028# define zbc_lex_skip_if_at_NLINE(...) (zbc_lex_skip_if_at_NLINE(__VA_ARGS__), BC_STATUS_SUCCESS)
3029#endif
3030
3031static BC_STATUS zbc_lex_next_and_skip_NLINE(BcLex *l)
3032{
3033 BcStatus s;
3034 s = zbc_lex_next(l);
3035 if (s) RETURN_STATUS(s);
3036 // if(cond)<newline>stmt is accepted too (but not 2+ newlines)
3037 s = zbc_lex_skip_if_at_NLINE(l);
3038 RETURN_STATUS(s);
3039}
3040#if ERRORS_ARE_FATAL
3041# define zbc_lex_next_and_skip_NLINE(...) (zbc_lex_next_and_skip_NLINE(__VA_ARGS__), BC_STATUS_SUCCESS)
3042#endif
3043
3021static BC_STATUS zbc_lex_text_init(BcLex *l, const char *text) 3044static BC_STATUS zbc_lex_text_init(BcLex *l, const char *text)
3022{ 3045{
3023 l->buf = text; 3046 l->buf = text;
@@ -4152,7 +4175,8 @@ static BC_STATUS zbc_parse_if(BcParse *p)
4152 if (s) RETURN_STATUS(s); 4175 if (s) RETURN_STATUS(s);
4153 4176
4154 if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); 4177 if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token());
4155 s = zbc_lex_next(&p->l); 4178 // if(cond)<newline>stmt is accepted too (but not 2+ newlines)
4179 s = zbc_lex_next_and_skip_NLINE(&p->l);
4156 if (s) RETURN_STATUS(s); 4180 if (s) RETURN_STATUS(s);
4157 4181
4158 bc_parse_push(p, BC_INST_JUMP_ZERO); 4182 bc_parse_push(p, BC_INST_JUMP_ZERO);
@@ -4216,12 +4240,15 @@ static BC_STATUS zbc_parse_while(BcParse *p)
4216 s = zbc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); 4240 s = zbc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel);
4217 if (s) RETURN_STATUS(s); 4241 if (s) RETURN_STATUS(s);
4218 if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); 4242 if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token());
4219 s = zbc_lex_next(&p->l); 4243
4244 // while(cond)<newline>stmt is accepted too
4245 s = zbc_lex_next_and_skip_NLINE(&p->l);
4220 if (s) RETURN_STATUS(s); 4246 if (s) RETURN_STATUS(s);
4221 4247
4222 bc_parse_push(p, BC_INST_JUMP_ZERO); 4248 bc_parse_push(p, BC_INST_JUMP_ZERO);
4223 bc_parse_pushIndex(p, ip.idx); 4249 bc_parse_pushIndex(p, ip.idx);
4224 4250
4251//TODO: diagnose "while(cond)<newline><newline>"? Now it is seen as "while() with empty body"
4225 s = zbc_parse_stmt(p); 4252 s = zbc_parse_stmt(p);
4226 if (s) RETURN_STATUS(s); 4253 if (s) RETURN_STATUS(s);
4227 4254
@@ -4321,7 +4348,9 @@ static BC_STATUS zbc_parse_for(BcParse *p)
4321 4348
4322 bc_vec_push(&p->exits, &ip); 4349 bc_vec_push(&p->exits, &ip);
4323 bc_vec_push(&p->func->labels, &ip.idx); 4350 bc_vec_push(&p->func->labels, &ip.idx);
4324 s = zbc_lex_next(&p->l); 4351
4352 // for(...)<newline>stmt is accepted as well
4353 s = zbc_lex_next_and_skip_NLINE(&p->l);
4325 if (s) RETURN_STATUS(s); 4354 if (s) RETURN_STATUS(s);
4326 4355
4327 s = zbc_parse_stmt(p); 4356 s = zbc_parse_stmt(p);
@@ -4453,11 +4482,9 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p)
4453 if (p->l.t.t != BC_LEX_LBRACE) 4482 if (p->l.t.t != BC_LEX_LBRACE)
4454 s = bc_POSIX_requires("the left brace be on the same line as the function header"); 4483 s = bc_POSIX_requires("the left brace be on the same line as the function header");
4455 4484
4456 // Prevent "define z()<newline>" to be interpreted as function with empty stmt as body 4485 // Prevent "define z()<newline>" from being interpreted as function with empty stmt as body
4457 while (p->l.t.t == BC_LEX_NLINE) { 4486 s = zbc_lex_skip_if_at_NLINE(&p->l);
4458 s = zbc_lex_next(&p->l); 4487 if (s) RETURN_STATUS(s);
4459 if (s) RETURN_STATUS(s);
4460 }
4461//TODO: GNU bc requires a {} block even if function body has single stmt, enforce this? 4488//TODO: GNU bc requires a {} block even if function body has single stmt, enforce this?
4462 4489
4463 p->in_funcdef++; // to determine whether "return" stmt is allowed, and such 4490 p->in_funcdef++; // to determine whether "return" stmt is allowed, and such
diff --git a/testsuite/bc.tests b/testsuite/bc.tests
index 093b3950e..95cc28dad 100755
--- a/testsuite/bc.tests
+++ b/testsuite/bc.tests
@@ -56,6 +56,16 @@ testing "bc define with body on next line" \
56 "8\n9\n" \ 56 "8\n9\n" \
57 "" "define w()\n{ auto z; return 8; }\nw()\n9" 57 "" "define w()\n{ auto z; return 8; }\nw()\n9"
58 58
59testing "bc if(cond)<NL>" \
60 "bc" \
61 "9\n" \
62 "" "if(0)\n3\n9"
63
64testing "bc while(cond)<NL>" \
65 "bc" \
66 "8\n7\n6\n5\n4\n3\n2\n1\n9\n" \
67 "" "i=9;while(--i)\ni\n9"
68
59tar xJf bc_large.tar.xz 69tar xJf bc_large.tar.xz
60 70
61for f in bc*.bc; do 71for f in bc*.bc; do