aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-12-25 19:37:23 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2018-12-25 19:37:23 +0100
commit53e569c06b12ef2cb9ef2ceeff92f04cfbf113e3 (patch)
tree4409d271eac5d1777a34da84a92de65f024daead
parent2638454464b944f9c407326257851bab13c045ec (diff)
downloadbusybox-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.c51
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) {