aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-12-22 01:34:10 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2018-12-22 01:34:10 +0100
commit8c1e72359626789b1b98aeac0225d73d1336bb59 (patch)
tree7c89877da4953bccddb88943e49def923c2d7a40
parent1dc4de9d9bbdf3f60b76cecf94d756ef9394e25f (diff)
downloadbusybox-w32-8c1e72359626789b1b98aeac0225d73d1336bb59.tar.gz
busybox-w32-8c1e72359626789b1b98aeac0225d73d1336bb59.tar.bz2
busybox-w32-8c1e72359626789b1b98aeac0225d73d1336bb59.zip
bc: unbreak read(), remove checks for nested read()
function old new delta zbc_parse_pushSTR - 65 +65 common_parse_expr - 32 +32 bc_error_nested_read_call 10 - -10 bc_parse_expr_empty_ok 1977 1963 -14 zdc_parse_expr 635 615 -20 zcommon_parse_expr 32 - -32 zbc_program_exec 4064 4023 -41 bc_parse_pushSTR 65 - -65 ------------------------------------------------------------------------------ (add/remove: 2/3 grow/shrink: 0/3 up/down: 97/-182) Total: -85 bytes text data bss dec hex filename 981661 485 7296 989442 f1902 busybox_old 981540 485 7296 989321 f1889 busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--miscutils/bc.c64
-rwxr-xr-xtestsuite/bc.tests15
2 files changed, 41 insertions, 38 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c
index cac3cb734..1ba8427da 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -314,9 +314,9 @@ typedef enum BcInst {
314#endif 314#endif
315 315
316 BC_INST_POP, 316 BC_INST_POP,
317#if ENABLE_DC
317 BC_INST_POP_EXEC, 318 BC_INST_POP_EXEC,
318 319
319#if ENABLE_DC
320 BC_INST_MODEXP, 320 BC_INST_MODEXP,
321 BC_INST_DIVMOD, 321 BC_INST_DIVMOD,
322 322
@@ -662,8 +662,7 @@ typedef struct BcLex {
662#define BC_PARSE_REL (1 << 0) 662#define BC_PARSE_REL (1 << 0)
663#define BC_PARSE_PRINT (1 << 1) 663#define BC_PARSE_PRINT (1 << 1)
664#define BC_PARSE_NOCALL (1 << 2) 664#define BC_PARSE_NOCALL (1 << 2)
665#define BC_PARSE_NOREAD (1 << 3) 665#define BC_PARSE_ARRAY (1 << 3)
666#define BC_PARSE_ARRAY (1 << 4)
667 666
668typedef struct BcParse { 667typedef struct BcParse {
669 BcLex l; 668 BcLex l;
@@ -766,7 +765,6 @@ typedef struct BcProgram {
766struct globals { 765struct globals {
767 IF_FEATURE_BC_SIGNALS(smallint ttyin;) 766 IF_FEATURE_BC_SIGNALS(smallint ttyin;)
768 IF_FEATURE_CLEAN_UP(smallint exiting;) 767 IF_FEATURE_CLEAN_UP(smallint exiting;)
769 smallint in_read;
770 768
771 BcParse prs; 769 BcParse prs;
772 BcProgram prog; 770 BcProgram prog;
@@ -1022,10 +1020,6 @@ static ERRORFUNC int bc_error_variable_is_wrong_type(void)
1022{ 1020{
1023 IF_ERROR_RETURN_POSSIBLE(return) bc_error("variable is wrong type"); 1021 IF_ERROR_RETURN_POSSIBLE(return) bc_error("variable is wrong type");
1024} 1022}
1025static ERRORFUNC int bc_error_nested_read_call(void)
1026{
1027 IF_ERROR_RETURN_POSSIBLE(return) bc_error("read() call inside of a read() call");
1028}
1029#if ENABLE_BC 1023#if ENABLE_BC
1030static int bc_POSIX_requires(const char *msg) 1024static int bc_POSIX_requires(const char *msg)
1031{ 1025{
@@ -3550,7 +3544,7 @@ static void bc_parse_pushJUMP_ZERO(BcParse *p, size_t idx)
3550 bc_parse_pushIndex(p, idx); 3544 bc_parse_pushIndex(p, idx);
3551} 3545}
3552 3546
3553static BC_STATUS bc_parse_pushSTR(BcParse *p) 3547static BC_STATUS zbc_parse_pushSTR(BcParse *p)
3554{ 3548{
3555 char *str = xstrdup(p->l.t.v.v); 3549 char *str = xstrdup(p->l.t.v.v);
3556 3550
@@ -3560,7 +3554,7 @@ static BC_STATUS bc_parse_pushSTR(BcParse *p)
3560 3554
3561 RETURN_STATUS(zbc_lex_next(&p->l)); 3555 RETURN_STATUS(zbc_lex_next(&p->l));
3562} 3556}
3563#define bc_parse_pushSTR(...) (bc_parse_pushSTR(__VA_ARGS__) COMMA_SUCCESS) 3557#define zbc_parse_pushSTR(...) (zbc_parse_pushSTR(__VA_ARGS__) COMMA_SUCCESS)
3564#endif 3558#endif
3565 3559
3566static void bc_parse_pushNUM(BcParse *p) 3560static void bc_parse_pushNUM(BcParse *p)
@@ -4083,7 +4077,7 @@ static BC_STATUS zbc_parse_print(BcParse *p)
4083 if (s) RETURN_STATUS(s); 4077 if (s) RETURN_STATUS(s);
4084 type = p->l.t.t; 4078 type = p->l.t.t;
4085 if (type == BC_LEX_STR) { 4079 if (type == BC_LEX_STR) {
4086 s = bc_parse_pushSTR(p); 4080 s = zbc_parse_pushSTR(p);
4087 } else { 4081 } else {
4088 s = zbc_parse_expr(p, 0); 4082 s = zbc_parse_expr(p, 0);
4089 } 4083 }
@@ -4545,7 +4539,7 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed)
4545 s = zbc_parse_expr(p, BC_PARSE_PRINT); 4539 s = zbc_parse_expr(p, BC_PARSE_PRINT);
4546 break; 4540 break;
4547 case BC_LEX_STR: 4541 case BC_LEX_STR:
4548 s = bc_parse_pushSTR(p); 4542 s = zbc_parse_pushSTR(p);
4549 bc_parse_push(p, BC_INST_PRINT_STR); 4543 bc_parse_push(p, BC_INST_PRINT_STR);
4550 break; 4544 break;
4551 case BC_LEX_KEY_BREAK: 4545 case BC_LEX_KEY_BREAK:
@@ -4645,6 +4639,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags)
4645 bin_last = true; 4639 bin_last = true;
4646 4640
4647 for (; !G_interrupt && !s && !done && bc_parse_exprs(t); t = p->l.t.t) { 4641 for (; !G_interrupt && !s && !done && bc_parse_exprs(t); t = p->l.t.t) {
4642 dbg_lex("%s:%d t:%d", __func__, __LINE__, t);
4648 switch (t) { 4643 switch (t) {
4649 case BC_LEX_OP_INC: 4644 case BC_LEX_OP_INC:
4650 case BC_LEX_OP_DEC: 4645 case BC_LEX_OP_DEC:
@@ -4766,8 +4761,6 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags)
4766 case BC_LEX_KEY_READ: 4761 case BC_LEX_KEY_READ:
4767 if (BC_PARSE_LEAF(prev, rprn)) 4762 if (BC_PARSE_LEAF(prev, rprn))
4768 return bc_error_bad_expression(); 4763 return bc_error_bad_expression();
4769 else if (flags & BC_PARSE_NOREAD)
4770 s = bc_error_nested_read_call();
4771 else 4764 else
4772 s = zbc_parse_read(p); 4765 s = zbc_parse_read(p);
4773 paren_expr = true; 4766 paren_expr = true;
@@ -4912,7 +4905,7 @@ static BC_STATUS zdc_parse_cond(BcParse *p, uint8_t inst)
4912} 4905}
4913#define zdc_parse_cond(...) (zdc_parse_cond(__VA_ARGS__) COMMA_SUCCESS) 4906#define zdc_parse_cond(...) (zdc_parse_cond(__VA_ARGS__) COMMA_SUCCESS)
4914 4907
4915static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t, uint8_t flags) 4908static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t)
4916{ 4909{
4917 BcStatus s = BC_STATUS_SUCCESS; 4910 BcStatus s = BC_STATUS_SUCCESS;
4918 uint8_t inst; 4911 uint8_t inst;
@@ -4950,10 +4943,7 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t, uint8_t flags)
4950 get_token = true; 4943 get_token = true;
4951 break; 4944 break;
4952 case BC_LEX_KEY_READ: 4945 case BC_LEX_KEY_READ:
4953 if (flags & BC_PARSE_NOREAD) 4946 bc_parse_push(p, BC_INST_READ);
4954 s = bc_error_nested_read_call();
4955 else
4956 bc_parse_push(p, BC_INST_READ);
4957 get_token = true; 4947 get_token = true;
4958 break; 4948 break;
4959 case BC_LEX_OP_ASSIGN: 4949 case BC_LEX_OP_ASSIGN:
@@ -5005,7 +4995,7 @@ static BC_STATUS zdc_parse_expr(BcParse *p, uint8_t flags)
5005 s = zbc_lex_next(&p->l); 4995 s = zbc_lex_next(&p->l);
5006 } else { 4996 } else {
5007 dbg_lex("%s:%d", __func__, __LINE__); 4997 dbg_lex("%s:%d", __func__, __LINE__);
5008 s = zdc_parse_token(p, t, flags); 4998 s = zdc_parse_token(p, t);
5009 } 4999 }
5010 if (s) RETURN_STATUS(s); 5000 if (s) RETURN_STATUS(s);
5011 } 5001 }
@@ -5038,7 +5028,12 @@ static BC_STATUS zdc_parse_parse(BcParse *p)
5038 5028
5039#endif // ENABLE_DC 5029#endif // ENABLE_DC
5040 5030
5041static BC_STATUS zcommon_parse_expr(BcParse *p, uint8_t flags) 5031#if !ENABLE_DC
5032#define common_parse_expr(p,flags) \
5033 common_parse_expr(p)
5034#define flags 0
5035#endif
5036static BC_STATUS common_parse_expr(BcParse *p, uint8_t flags)
5042{ 5037{
5043 if (IS_BC) { 5038 if (IS_BC) {
5044 IF_BC(RETURN_STATUS(zbc_parse_expr(p, flags))); 5039 IF_BC(RETURN_STATUS(zbc_parse_expr(p, flags)));
@@ -5046,7 +5041,7 @@ static BC_STATUS zcommon_parse_expr(BcParse *p, uint8_t flags)
5046 IF_DC(RETURN_STATUS(zdc_parse_expr(p, flags))); 5041 IF_DC(RETURN_STATUS(zdc_parse_expr(p, flags)));
5047 } 5042 }
5048} 5043}
5049#define zcommon_parse_expr(...) (zcommon_parse_expr(__VA_ARGS__) COMMA_SUCCESS) 5044#define zcommon_parse_expr(...) (common_parse_expr(__VA_ARGS__) COMMA_SUCCESS)
5050 5045
5051static BcVec* bc_program_search(char *id, bool var) 5046static BcVec* bc_program_search(char *id, bool var)
5052{ 5047{
@@ -5238,15 +5233,11 @@ static BC_STATUS zbc_program_read(void)
5238 BcInstPtr ip; 5233 BcInstPtr ip;
5239 BcFunc *f; 5234 BcFunc *f;
5240 5235
5241 if (G.in_read)
5242 RETURN_STATUS(bc_error_nested_read_call());
5243
5244 f = bc_program_func(BC_PROG_READ); 5236 f = bc_program_func(BC_PROG_READ);
5245 bc_vec_pop_all(&f->code); 5237 bc_vec_pop_all(&f->code);
5246 5238
5247 sv_file = G.prog.file; 5239 sv_file = G.prog.file;
5248 G.prog.file = NULL; 5240 G.prog.file = NULL;
5249 G.in_read = 1;
5250 5241
5251 bc_char_vec_init(&buf); 5242 bc_char_vec_init(&buf);
5252 bc_read_line(&buf, stdin); 5243 bc_read_line(&buf, stdin);
@@ -5256,7 +5247,7 @@ static BC_STATUS zbc_program_read(void)
5256 5247
5257 s = zbc_parse_text_init(&parse, buf.v); 5248 s = zbc_parse_text_init(&parse, buf.v);
5258 if (s) goto exec_err; 5249 if (s) goto exec_err;
5259 s = zcommon_parse_expr(&parse, BC_PARSE_NOREAD); 5250 s = zcommon_parse_expr(&parse, 0);
5260 if (s) goto exec_err; 5251 if (s) goto exec_err;
5261 5252
5262 if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != BC_LEX_EOF) { 5253 if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != BC_LEX_EOF) {
@@ -5268,14 +5259,10 @@ static BC_STATUS zbc_program_read(void)
5268 ip.inst_idx = 0; 5259 ip.inst_idx = 0;
5269 IF_BC(ip.results_len_before_call = G.prog.results.len;) 5260 IF_BC(ip.results_len_before_call = G.prog.results.len;)
5270 5261
5271 // Update this pointer, just in case. 5262 bc_parse_push(&parse, BC_INST_RET);
5272 f = bc_program_func(BC_PROG_READ);
5273
5274 bc_vec_pushByte(&f->code, BC_INST_POP_EXEC);
5275 bc_vec_push(&G.prog.exestack, &ip); 5263 bc_vec_push(&G.prog.exestack, &ip);
5276 exec_err: 5264 exec_err:
5277 bc_parse_free(&parse); 5265 bc_parse_free(&parse);
5278 G.in_read = 0;
5279 G.prog.file = sv_file; 5266 G.prog.file = sv_file;
5280 bc_vec_free(&buf); 5267 bc_vec_free(&buf);
5281 RETURN_STATUS(s); 5268 RETURN_STATUS(s);
@@ -6542,10 +6529,6 @@ static BC_STATUS zbc_program_exec(void)
6542 else 6529 else
6543 bc_vec_pop(&G.prog.results); 6530 bc_vec_pop(&G.prog.results);
6544 break; 6531 break;
6545 case BC_INST_POP_EXEC:
6546 dbg_exec("BC_INST_POP_EXEC:");
6547 bc_vec_pop(&G.prog.exestack);
6548 goto read_updated_ip;
6549 case BC_INST_PRINT: 6532 case BC_INST_PRINT:
6550 case BC_INST_PRINT_POP: 6533 case BC_INST_PRINT_POP:
6551 case BC_INST_PRINT_STR: 6534 case BC_INST_PRINT_STR:
@@ -6594,6 +6577,10 @@ static BC_STATUS zbc_program_exec(void)
6594 s = zbc_program_assign(inst); 6577 s = zbc_program_assign(inst);
6595 break; 6578 break;
6596#if ENABLE_DC 6579#if ENABLE_DC
6580 case BC_INST_POP_EXEC:
6581 dbg_exec("BC_INST_POP_EXEC:");
6582 bc_vec_pop(&G.prog.exestack);
6583 goto read_updated_ip;
6597 case BC_INST_MODEXP: 6584 case BC_INST_MODEXP:
6598 s = zdc_program_modexp(); 6585 s = zdc_program_modexp();
6599 break; 6586 break;
@@ -7122,11 +7109,12 @@ static void bc_program_init(void)
7122 IF_BC(bc_vec_init(&G.prog.fn_map, sizeof(BcId), bc_id_free);) 7109 IF_BC(bc_vec_init(&G.prog.fn_map, sizeof(BcId), bc_id_free);)
7123 7110
7124 if (IS_BC) { 7111 if (IS_BC) {
7125 // Names are chosen simply to never match 7112 // Names are chosen simply to be distinct and never match
7126 // a valid function name (and be short) 7113 // a valid function name (and be short)
7127 IF_BC(bc_program_addFunc(xstrdup(""))); // func #0: main 7114 IF_BC(bc_program_addFunc(xstrdup(""))); // func #0: main
7128 IF_BC(bc_program_addFunc(xstrdup(""))); // func #1: for read() 7115 IF_BC(bc_program_addFunc(xstrdup("1"))); // func #1: for read()
7129 } else { 7116 } else {
7117 // in dc, functions have no names
7130 bc_program_add_fn(); 7118 bc_program_add_fn();
7131 bc_program_add_fn(); 7119 bc_program_add_fn();
7132 } 7120 }
diff --git a/testsuite/bc.tests b/testsuite/bc.tests
index b3ce894ee..c84a2987c 100755
--- a/testsuite/bc.tests
+++ b/testsuite/bc.tests
@@ -31,6 +31,21 @@ testing "bc string 1" \
31 "STR\n" \ 31 "STR\n" \
32 "" "\"STR\n\"" 32 "" "\"STR\n\""
33 33
34testing "bc read() 4<EOF>" \
35 "bc input" \
36 "4\n" \
37 "read();halt" "4"
38
39testing "bc read()^2" \
40 "bc input" \
41 "16\n" \
42 "read()^2;halt" "4\n"
43
44testing "bc read()*read()" \
45 "bc input" \
46 "20\n" \
47 "read()*read();halt" "4\n5"
48
34testing "bc if 0 else" \ 49testing "bc if 0 else" \
35 "bc" \ 50 "bc" \
36 "2\n9\n" \ 51 "2\n9\n" \