diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-25 19:37:23 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-25 19:37:23 +0100 |
| commit | 53e569c06b12ef2cb9ef2ceeff92f04cfbf113e3 (patch) | |
| tree | 4409d271eac5d1777a34da84a92de65f024daead | |
| parent | 2638454464b944f9c407326257851bab13c045ec (diff) | |
| download | busybox-w32-53e569c06b12ef2cb9ef2ceeff92f04cfbf113e3.tar.gz busybox-w32-53e569c06b12ef2cb9ef2ceeff92f04cfbf113e3.tar.bz2 busybox-w32-53e569c06b12ef2cb9ef2ceeff92f04cfbf113e3.zip | |
bc: fix interactive read()
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | miscutils/bc.c | 51 |
1 files changed, 26 insertions, 25 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index 8b44d4425..79f981eaf 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
| @@ -6753,6 +6753,7 @@ static BC_STATUS zbc_vm_process(const char *text) | |||
| 6753 | s = zbc_parse_text_init(&G.prs, text); // does the first zbc_lex_next() | 6753 | s = zbc_parse_text_init(&G.prs, text); // does the first zbc_lex_next() |
| 6754 | if (s) RETURN_STATUS(s); | 6754 | if (s) RETURN_STATUS(s); |
| 6755 | 6755 | ||
| 6756 | IF_BC(check_eof:) | ||
| 6756 | while (G.prs.l.lex != XC_LEX_EOF) { | 6757 | while (G.prs.l.lex != XC_LEX_EOF) { |
| 6757 | BcInstPtr *ip; | 6758 | BcInstPtr *ip; |
| 6758 | BcFunc *f; | 6759 | BcFunc *f; |
| @@ -6760,34 +6761,34 @@ static BC_STATUS zbc_vm_process(const char *text) | |||
| 6760 | dbg_lex("%s:%d G.prs.l.lex:%d, parsing...", __func__, __LINE__, G.prs.l.lex); | 6761 | dbg_lex("%s:%d G.prs.l.lex:%d, parsing...", __func__, __LINE__, G.prs.l.lex); |
| 6761 | if (IS_BC) { | 6762 | if (IS_BC) { |
| 6762 | #if ENABLE_BC | 6763 | #if ENABLE_BC |
| 6764 | if (G.prs.l.lex == BC_LEX_SCOLON | ||
| 6765 | || G.prs.l.lex == XC_LEX_NLINE | ||
| 6766 | ) { | ||
| 6767 | s = zbc_lex_next(&G.prs.l); | ||
| 6768 | if (s) goto err; | ||
| 6769 | goto check_eof; | ||
| 6770 | } | ||
| 6771 | |||
| 6763 | s = zbc_parse_stmt_or_funcdef(&G.prs); | 6772 | s = zbc_parse_stmt_or_funcdef(&G.prs); |
| 6764 | if (s) goto err; | 6773 | if (s) goto err; |
| 6765 | 6774 | ||
| 6766 | // Check that next token is not bogus, and skip over | 6775 | // Check that next token is a correct stmt delimiter - |
| 6767 | // stmt delimiter(s) - newlines and semicolons | 6776 | // disallows "print 1 print 2" and such. |
| 6768 | s = 1; // s == 1 on first iteration only | 6777 | if (G.prs.l.lex != BC_LEX_SCOLON |
| 6769 | for (;;) { | 6778 | && G.prs.l.lex != XC_LEX_NLINE |
| 6770 | if (G.prs.l.lex == XC_LEX_EOF) | 6779 | && G.prs.l.lex != XC_LEX_EOF |
| 6771 | goto execute; // this goto avoids resetting 's' to zero | 6780 | ) { |
| 6772 | if (G.prs.l.lex != BC_LEX_SCOLON | 6781 | const char *err_at; |
| 6773 | && G.prs.l.lex != XC_LEX_NLINE | 6782 | //TODO: commonalize for other parse errors: |
| 6774 | ) { | 6783 | err_at = G.prs.l.lex_next_at ? G.prs.l.lex_next_at : "UNKNOWN"; |
| 6775 | const char *err_at; | 6784 | bc_error_fmt("bad statement terminator at '%.*s'", |
| 6776 | // Not newline and not semicolon | 6785 | (int)(strchrnul(err_at, '\n') - err_at), |
| 6777 | if (s == 0) // saw at least one NL/semicolon before it? | 6786 | err_at |
| 6778 | break; // yes, good | 6787 | ); |
| 6779 | //TODO: commolalize for other parse errors: | 6788 | goto err; |
| 6780 | err_at = G.prs.l.lex_next_at ? G.prs.l.lex_next_at : "UNKNOWN"; | ||
| 6781 | bc_error_fmt("bad statement terminator at '%.*s'", | ||
| 6782 | (int)(strchrnul(err_at, '\n') - err_at), | ||
| 6783 | err_at | ||
| 6784 | ); | ||
| 6785 | goto err; | ||
| 6786 | } | ||
| 6787 | // NL or semicolon: skip it, set s = 0, repeat | ||
| 6788 | s = zbc_lex_next(&G.prs.l); | ||
| 6789 | if (s) goto err; | ||
| 6790 | } | 6789 | } |
| 6790 | // The above logic is fragile. Check these examples: | ||
| 6791 | // - interative read() still works | ||
| 6791 | #endif | 6792 | #endif |
| 6792 | } else { | 6793 | } else { |
| 6793 | #if ENABLE_DC | 6794 | #if ENABLE_DC |
| @@ -6807,7 +6808,7 @@ static BC_STATUS zbc_vm_process(const char *text) | |||
| 6807 | bc_parse_reset(&G.prs); // includes bc_program_reset() | 6808 | bc_parse_reset(&G.prs); // includes bc_program_reset() |
| 6808 | RETURN_STATUS(BC_STATUS_FAILURE); | 6809 | RETURN_STATUS(BC_STATUS_FAILURE); |
| 6809 | } | 6810 | } |
| 6810 | IF_BC(execute:) | 6811 | |
| 6811 | dbg_lex("%s:%d executing...", __func__, __LINE__); | 6812 | dbg_lex("%s:%d executing...", __func__, __LINE__); |
| 6812 | s = zbc_program_exec(); | 6813 | s = zbc_program_exec(); |
| 6813 | if (s) { | 6814 | if (s) { |
