diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-22 18:04:08 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-22 18:10:50 +0100 |
commit | badf683b0aa693de9b1a7c1634ad20665463c503 (patch) | |
tree | c0d98441715a00b73971743e49f4c82c90beaf9b /miscutils | |
parent | 5daa1a0adfe08bae588e5293686a84ab3649a2aa (diff) | |
download | busybox-w32-badf683b0aa693de9b1a7c1634ad20665463c503.tar.gz busybox-w32-badf683b0aa693de9b1a7c1634ad20665463c503.tar.bz2 busybox-w32-badf683b0aa693de9b1a7c1634ad20665463c503.zip |
dc: unbreak interactive mode - was trying to get next tokens instead of executing
function old new delta
zbc_program_read - 268 +268
zdc_program_printStream - 146 +146
zbc_program_exec 4046 4182 +136
zdc_program_execStr 472 512 +40
zdc_parse_exprs_until_eof - 26 +26
zbc_vm_process 740 765 +25
zbc_lex_next 2225 2240 +15
zdc_parse_expr 569 535 -34
zbc_program_pushArray 147 - -147
zdc_program_asciify 370 - -370
------------------------------------------------------------------------------
(add/remove: 3/2 grow/shrink: 4/1 up/down: 656/-551) Total: 105 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils')
-rw-r--r-- | miscutils/bc.c | 96 |
1 files changed, 66 insertions, 30 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index 5d5449efa..d8fbb6ed7 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
@@ -3431,6 +3431,17 @@ static BC_STATUS zdc_lex_token(BcLex *l) | |||
3431 | // l->t.t = BC_LEX_EOF; | 3431 | // l->t.t = BC_LEX_EOF; |
3432 | // break; | 3432 | // break; |
3433 | case '\n': | 3433 | case '\n': |
3434 | // '\n' is BC_LEX_NLINE, not BC_LEX_WHITESPACE | ||
3435 | // (and "case '\n'" is not just empty here) | ||
3436 | // only to allow interactive dc have a way to exit | ||
3437 | // "parse" stage of "parse,execute" loop | ||
3438 | // on '\n', not on _next_ token (which would mean | ||
3439 | // command are not executed on pressing <enter>). | ||
3440 | // IOW: typing "1p<enter>" should print "1" _at once_, | ||
3441 | // not after some more input. | ||
3442 | l->t.t = BC_LEX_NLINE; | ||
3443 | l->newline = true; | ||
3444 | break; | ||
3434 | case '\t': | 3445 | case '\t': |
3435 | case '\v': | 3446 | case '\v': |
3436 | case '\f': | 3447 | case '\f': |
@@ -4861,12 +4872,16 @@ static BC_STATUS zdc_parse_cond(BcParse *p, uint8_t inst) | |||
4861 | s = zbc_lex_next(&p->l); | 4872 | s = zbc_lex_next(&p->l); |
4862 | if (s) RETURN_STATUS(s); | 4873 | if (s) RETURN_STATUS(s); |
4863 | 4874 | ||
4875 | // Note that 'else' part can not be on the next line: | ||
4876 | // echo -e '[1p]sa [2p]sb 2 1>a eb' | dc - OK, prints "2" | ||
4877 | // echo -e '[1p]sa [2p]sb 2 1>a\neb' | dc - parse error | ||
4864 | if (p->l.t.t == BC_LEX_ELSE) { | 4878 | if (p->l.t.t == BC_LEX_ELSE) { |
4865 | s = zdc_parse_register(p); | 4879 | s = zdc_parse_register(p); |
4866 | if (s) RETURN_STATUS(s); | 4880 | if (s) RETURN_STATUS(s); |
4867 | s = zbc_lex_next(&p->l); | 4881 | s = zbc_lex_next(&p->l); |
4868 | } else | 4882 | } else { |
4869 | bc_parse_push(p, BC_PARSE_STREND); | 4883 | bc_parse_push(p, BC_PARSE_STREND); |
4884 | } | ||
4870 | 4885 | ||
4871 | RETURN_STATUS(s); | 4886 | RETURN_STATUS(s); |
4872 | } | 4887 | } |
@@ -4945,33 +4960,32 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) | |||
4945 | 4960 | ||
4946 | static BC_STATUS zdc_parse_expr(BcParse *p) | 4961 | static BC_STATUS zdc_parse_expr(BcParse *p) |
4947 | { | 4962 | { |
4948 | BcLexType t; | 4963 | BcInst inst; |
4949 | 4964 | BcStatus s; | |
4950 | dbg_lex_enter("%s:%d entered, p->l.t.t:%d", __func__, __LINE__, p->l.t.t); | ||
4951 | for (;;) { | ||
4952 | BcInst inst; | ||
4953 | BcStatus s; | ||
4954 | 4965 | ||
4955 | t = p->l.t.t; | 4966 | inst = dc_parse_insts[p->l.t.t]; |
4956 | dbg_lex("%s:%d p->l.t.t:%d", __func__, __LINE__, p->l.t.t); | 4967 | if (inst != BC_INST_INVALID) { |
4957 | if (t == BC_LEX_EOF) break; | 4968 | bc_parse_push(p, inst); |
4969 | s = zbc_lex_next(&p->l); | ||
4970 | } else { | ||
4971 | s = zdc_parse_token(p, p->l.t.t); | ||
4972 | } | ||
4973 | RETURN_STATUS(s); | ||
4974 | } | ||
4975 | #define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) | ||
4958 | 4976 | ||
4959 | inst = dc_parse_insts[t]; | 4977 | static BC_STATUS zdc_parse_exprs_until_eof(BcParse *p) |
4960 | if (inst != BC_INST_INVALID) { | 4978 | { |
4961 | dbg_lex("%s:%d", __func__, __LINE__); | 4979 | dbg_lex_enter("%s:%d entered, p->l.t.t:%d", __func__, __LINE__, p->l.t.t); |
4962 | bc_parse_push(p, inst); | 4980 | while (p->l.t.t != BC_LEX_EOF) { |
4963 | s = zbc_lex_next(&p->l); | 4981 | BcStatus s = zdc_parse_expr(p); |
4964 | } else { | ||
4965 | dbg_lex("%s:%d", __func__, __LINE__); | ||
4966 | s = zdc_parse_token(p, t); | ||
4967 | } | ||
4968 | if (s) RETURN_STATUS(s); | 4982 | if (s) RETURN_STATUS(s); |
4969 | } | 4983 | } |
4970 | 4984 | ||
4971 | dbg_lex_done("%s:%d done", __func__, __LINE__); | 4985 | dbg_lex_done("%s:%d done", __func__, __LINE__); |
4972 | RETURN_STATUS(BC_STATUS_SUCCESS); | 4986 | RETURN_STATUS(BC_STATUS_SUCCESS); |
4973 | } | 4987 | } |
4974 | #define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) | 4988 | #define zdc_parse_exprs_until_eof(...) (zdc_parse_exprs_until_eof(__VA_ARGS__) COMMA_SUCCESS) |
4975 | 4989 | ||
4976 | #endif // ENABLE_DC | 4990 | #endif // ENABLE_DC |
4977 | 4991 | ||
@@ -5182,7 +5196,7 @@ static BC_STATUS zbc_program_read(void) | |||
5182 | if (IS_BC) { | 5196 | if (IS_BC) { |
5183 | IF_BC(s = zbc_parse_expr(&parse, 0)); | 5197 | IF_BC(s = zbc_parse_expr(&parse, 0)); |
5184 | } else { | 5198 | } else { |
5185 | IF_DC(s = zdc_parse_expr(&parse)); | 5199 | IF_DC(s = zdc_parse_exprs_until_eof(&parse)); |
5186 | } | 5200 | } |
5187 | if (s) goto exec_err; | 5201 | if (s) goto exec_err; |
5188 | 5202 | ||
@@ -6304,6 +6318,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) | |||
6304 | f = bc_program_func(fidx); | 6318 | f = bc_program_func(fidx); |
6305 | 6319 | ||
6306 | if (f->code.len == 0) { | 6320 | if (f->code.len == 0) { |
6321 | FILE *sv_input_fp; | ||
6307 | BcParse prs; | 6322 | BcParse prs; |
6308 | char *str; | 6323 | char *str; |
6309 | 6324 | ||
@@ -6311,7 +6326,12 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) | |||
6311 | str = *bc_program_str(sidx); | 6326 | str = *bc_program_str(sidx); |
6312 | s = zbc_parse_text_init(&prs, str); | 6327 | s = zbc_parse_text_init(&prs, str); |
6313 | if (s) goto err; | 6328 | if (s) goto err; |
6314 | s = zdc_parse_expr(&prs); | 6329 | |
6330 | sv_input_fp = G.input_fp; | ||
6331 | G.input_fp = NULL; // "do not read from input file when <EOL> reached" | ||
6332 | s = zdc_parse_exprs_until_eof(&prs); | ||
6333 | G.input_fp = sv_input_fp; | ||
6334 | |||
6315 | if (s) goto err; | 6335 | if (s) goto err; |
6316 | if (prs.l.t.t != BC_LEX_EOF) { | 6336 | if (prs.l.t.t != BC_LEX_EOF) { |
6317 | s = bc_error_bad_expression(); | 6337 | s = bc_error_bad_expression(); |
@@ -6439,12 +6459,15 @@ static BC_STATUS zbc_program_exec(void) | |||
6439 | s = zbc_program_pushArray(code, &ip->inst_idx, inst); | 6459 | s = zbc_program_pushArray(code, &ip->inst_idx, inst); |
6440 | break; | 6460 | break; |
6441 | case BC_INST_LAST: | 6461 | case BC_INST_LAST: |
6462 | //TODO: this can't happen on dc, right? | ||
6463 | dbg_exec("BC_INST_LAST:"); | ||
6442 | r.t = BC_RESULT_LAST; | 6464 | r.t = BC_RESULT_LAST; |
6443 | bc_vec_push(&G.prog.results, &r); | 6465 | bc_vec_push(&G.prog.results, &r); |
6444 | break; | 6466 | break; |
6445 | case BC_INST_IBASE: | 6467 | case BC_INST_IBASE: |
6446 | case BC_INST_SCALE: | 6468 | case BC_INST_SCALE: |
6447 | case BC_INST_OBASE: | 6469 | case BC_INST_OBASE: |
6470 | dbg_exec("BC_INST_internalvar:"); | ||
6448 | bc_program_pushGlobal(inst); | 6471 | bc_program_pushGlobal(inst); |
6449 | break; | 6472 | break; |
6450 | case BC_INST_SCALE_FUNC: | 6473 | case BC_INST_SCALE_FUNC: |
@@ -6519,17 +6542,21 @@ static BC_STATUS zbc_program_exec(void) | |||
6519 | bc_vec_pop(&G.prog.exestack); | 6542 | bc_vec_pop(&G.prog.exestack); |
6520 | goto read_updated_ip; | 6543 | goto read_updated_ip; |
6521 | case BC_INST_MODEXP: | 6544 | case BC_INST_MODEXP: |
6545 | dbg_exec("BC_INST_MODEXP:"); | ||
6522 | s = zdc_program_modexp(); | 6546 | s = zdc_program_modexp(); |
6523 | break; | 6547 | break; |
6524 | case BC_INST_DIVMOD: | 6548 | case BC_INST_DIVMOD: |
6549 | dbg_exec("BC_INST_DIVMOD:"); | ||
6525 | s = zdc_program_divmod(); | 6550 | s = zdc_program_divmod(); |
6526 | break; | 6551 | break; |
6527 | case BC_INST_EXECUTE: | 6552 | case BC_INST_EXECUTE: |
6528 | case BC_INST_EXEC_COND: | 6553 | case BC_INST_EXEC_COND: |
6554 | dbg_exec("BC_INST_EXEC[_COND]:"); | ||
6529 | s = zdc_program_execStr(code, &ip->inst_idx, inst == BC_INST_EXEC_COND); | 6555 | s = zdc_program_execStr(code, &ip->inst_idx, inst == BC_INST_EXEC_COND); |
6530 | goto read_updated_ip; | 6556 | goto read_updated_ip; |
6531 | case BC_INST_PRINT_STACK: { | 6557 | case BC_INST_PRINT_STACK: { |
6532 | size_t idx; | 6558 | size_t idx; |
6559 | dbg_exec("BC_INST_PRINT_STACK:"); | ||
6533 | for (idx = 0; idx < G.prog.results.len; ++idx) { | 6560 | for (idx = 0; idx < G.prog.results.len; ++idx) { |
6534 | s = zbc_program_print(BC_INST_PRINT, idx); | 6561 | s = zbc_program_print(BC_INST_PRINT, idx); |
6535 | if (s) break; | 6562 | if (s) break; |
@@ -6537,12 +6564,15 @@ static BC_STATUS zbc_program_exec(void) | |||
6537 | break; | 6564 | break; |
6538 | } | 6565 | } |
6539 | case BC_INST_CLEAR_STACK: | 6566 | case BC_INST_CLEAR_STACK: |
6567 | dbg_exec("BC_INST_CLEAR_STACK:"); | ||
6540 | bc_vec_pop_all(&G.prog.results); | 6568 | bc_vec_pop_all(&G.prog.results); |
6541 | break; | 6569 | break; |
6542 | case BC_INST_STACK_LEN: | 6570 | case BC_INST_STACK_LEN: |
6571 | dbg_exec("BC_INST_STACK_LEN:"); | ||
6543 | dc_program_stackLen(); | 6572 | dc_program_stackLen(); |
6544 | break; | 6573 | break; |
6545 | case BC_INST_DUPLICATE: | 6574 | case BC_INST_DUPLICATE: |
6575 | dbg_exec("BC_INST_DUPLICATE:"); | ||
6546 | if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) | 6576 | if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) |
6547 | RETURN_STATUS(bc_error_stack_has_too_few_elements()); | 6577 | RETURN_STATUS(bc_error_stack_has_too_few_elements()); |
6548 | ptr = bc_vec_top(&G.prog.results); | 6578 | ptr = bc_vec_top(&G.prog.results); |
@@ -6551,6 +6581,7 @@ static BC_STATUS zbc_program_exec(void) | |||
6551 | break; | 6581 | break; |
6552 | case BC_INST_SWAP: { | 6582 | case BC_INST_SWAP: { |
6553 | BcResult *ptr2; | 6583 | BcResult *ptr2; |
6584 | dbg_exec("BC_INST_SWAP:"); | ||
6554 | if (!STACK_HAS_MORE_THAN(&G.prog.results, 1)) | 6585 | if (!STACK_HAS_MORE_THAN(&G.prog.results, 1)) |
6555 | RETURN_STATUS(bc_error_stack_has_too_few_elements()); | 6586 | RETURN_STATUS(bc_error_stack_has_too_few_elements()); |
6556 | ptr = bc_vec_item_rev(&G.prog.results, 0); | 6587 | ptr = bc_vec_item_rev(&G.prog.results, 0); |
@@ -6561,9 +6592,11 @@ static BC_STATUS zbc_program_exec(void) | |||
6561 | break; | 6592 | break; |
6562 | } | 6593 | } |
6563 | case BC_INST_ASCIIFY: | 6594 | case BC_INST_ASCIIFY: |
6595 | dbg_exec("BC_INST_ASCIIFY:"); | ||
6564 | s = zdc_program_asciify(); | 6596 | s = zdc_program_asciify(); |
6565 | break; | 6597 | break; |
6566 | case BC_INST_PRINT_STREAM: | 6598 | case BC_INST_PRINT_STREAM: |
6599 | dbg_exec("BC_INST_STREAM:"); | ||
6567 | s = zdc_program_printStream(); | 6600 | s = zdc_program_printStream(); |
6568 | break; | 6601 | break; |
6569 | case BC_INST_LOAD: | 6602 | case BC_INST_LOAD: |
@@ -6585,6 +6618,7 @@ static BC_STATUS zbc_program_exec(void) | |||
6585 | bc_vec_npop(&G.prog.exestack, 2); | 6618 | bc_vec_npop(&G.prog.exestack, 2); |
6586 | goto read_updated_ip; | 6619 | goto read_updated_ip; |
6587 | case BC_INST_NQUIT: | 6620 | case BC_INST_NQUIT: |
6621 | dbg_exec("BC_INST_NQUIT:"); | ||
6588 | s = zdc_program_nquit(); | 6622 | s = zdc_program_nquit(); |
6589 | //goto read_updated_ip; - just fall through to it | 6623 | //goto read_updated_ip; - just fall through to it |
6590 | #endif // ENABLE_DC | 6624 | #endif // ENABLE_DC |
@@ -6629,25 +6663,20 @@ static BC_STATUS zbc_vm_process(const char *text) | |||
6629 | BcStatus s; | 6663 | BcStatus s; |
6630 | 6664 | ||
6631 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); | 6665 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); |
6632 | s = zbc_parse_text_init(&G.prs, text); | 6666 | s = zbc_parse_text_init(&G.prs, text); // does the first zbc_lex_next() |
6633 | if (s) RETURN_STATUS(s); | 6667 | if (s) RETURN_STATUS(s); |
6634 | 6668 | ||
6635 | while (G.prs.l.t.t != BC_LEX_EOF) { | 6669 | while (G.prs.l.t.t != BC_LEX_EOF) { |
6636 | dbg_lex("%s:%d G.prs.l.t.t:%d, parsing...", __func__, __LINE__, G.prs.l.t.t); | 6670 | dbg_lex("%s:%d G.prs.l.t.t:%d, parsing...", __func__, __LINE__, G.prs.l.t.t); |
6637 | if (IS_BC) { | 6671 | if (IS_BC) { |
6638 | // FIXME: "eating" of stmt delemiters is coded inconsistently | 6672 | // FIXME: "eating" of stmt delimiters is coded inconsistently |
6639 | // (sometimes zbc_parse_stmt() eats the delimiter, sometimes don't), | 6673 | // (sometimes zbc_parse_stmt() eats the delimiter, sometimes don't), |
6640 | // which causes bugs such as "print 1 print 2" erroneously accepted, | 6674 | // which causes bugs such as "print 1 print 2" erroneously accepted, |
6641 | // or "print 1 else 2" detecting parse error only after executing | 6675 | // or "print 1 else 2" detecting parse error only after executing |
6642 | // "print 1" part. | 6676 | // "print 1" part. |
6643 | IF_BC(s = zbc_parse_stmt_or_funcdef(&G.prs)); | 6677 | IF_BC(s = zbc_parse_stmt_or_funcdef(&G.prs)); |
6644 | } else { | 6678 | } else { |
6645 | #if ENABLE_DC | 6679 | IF_DC(s = zdc_parse_expr(&G.prs)); |
6646 | if (G.prs.l.t.t == BC_LEX_EOF) | ||
6647 | s = bc_error("end of file"); | ||
6648 | else | ||
6649 | s = zdc_parse_expr(&G.prs); | ||
6650 | #endif | ||
6651 | } | 6680 | } |
6652 | if (s || G_interrupt) { | 6681 | if (s || G_interrupt) { |
6653 | bc_parse_reset(&G.prs); // includes bc_program_reset() | 6682 | bc_parse_reset(&G.prs); // includes bc_program_reset() |
@@ -6689,6 +6718,13 @@ static BC_STATUS zbc_vm_process(const char *text) | |||
6689 | ip->inst_idx = 0; | 6718 | ip->inst_idx = 0; |
6690 | IF_BC(bc_vec_pop_all(&f->strs);) | 6719 | IF_BC(bc_vec_pop_all(&f->strs);) |
6691 | IF_BC(bc_vec_pop_all(&f->consts);) | 6720 | IF_BC(bc_vec_pop_all(&f->consts);) |
6721 | } else { | ||
6722 | // Most of dc parsing assumes all whitespace, | ||
6723 | // including '\n', is eaten. | ||
6724 | if (G.prs.l.t.t == BC_LEX_NLINE) { | ||
6725 | s = zbc_lex_next(&G.prs.l); | ||
6726 | if (s) RETURN_STATUS(s); | ||
6727 | } | ||
6692 | } | 6728 | } |
6693 | } | 6729 | } |
6694 | 6730 | ||