aboutsummaryrefslogtreecommitdiff
path: root/miscutils/bc.c
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 /miscutils/bc.c
parent2638454464b944f9c407326257851bab13c045ec (diff)
downloadbusybox-53e569c06b12ef2cb9ef2ceeff92f04cfbf113e3.tar.gz
bc: fix interactive read()
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils/bc.c')
-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)
s = zbc_parse_text_init(&G.prs, text); // does the first zbc_lex_next()
if (s) RETURN_STATUS(s);
+ IF_BC(check_eof:)
while (G.prs.l.lex != XC_LEX_EOF) {
BcInstPtr *ip;
BcFunc *f;
@@ -6760,34 +6761,34 @@ static BC_STATUS zbc_vm_process(const char *text)
dbg_lex("%s:%d G.prs.l.lex:%d, parsing...", __func__, __LINE__, G.prs.l.lex);
if (IS_BC) {
#if ENABLE_BC
+ if (G.prs.l.lex == BC_LEX_SCOLON
+ || G.prs.l.lex == XC_LEX_NLINE
+ ) {
+ s = zbc_lex_next(&G.prs.l);
+ if (s) goto err;
+ goto check_eof;
+ }
+
s = zbc_parse_stmt_or_funcdef(&G.prs);
if (s) goto err;
- // Check that next token is not bogus, and skip over
- // stmt delimiter(s) - newlines and semicolons
- s = 1; // s == 1 on first iteration only
- for (;;) {
- if (G.prs.l.lex == XC_LEX_EOF)
- goto execute; // this goto avoids resetting 's' to zero
- if (G.prs.l.lex != BC_LEX_SCOLON
- && G.prs.l.lex != XC_LEX_NLINE
- ) {
- const char *err_at;
- // Not newline and not semicolon
- if (s == 0) // saw at least one NL/semicolon before it?
- break; // yes, good
-//TODO: commolalize for other parse errors:
- err_at = G.prs.l.lex_next_at ? G.prs.l.lex_next_at : "UNKNOWN";
- bc_error_fmt("bad statement terminator at '%.*s'",
- (int)(strchrnul(err_at, '\n') - err_at),
- err_at
- );
- goto err;
- }
- // NL or semicolon: skip it, set s = 0, repeat
- s = zbc_lex_next(&G.prs.l);
- if (s) goto err;
+ // Check that next token is a correct stmt delimiter -
+ // disallows "print 1 print 2" and such.
+ if (G.prs.l.lex != BC_LEX_SCOLON
+ && G.prs.l.lex != XC_LEX_NLINE
+ && G.prs.l.lex != XC_LEX_EOF
+ ) {
+ const char *err_at;
+//TODO: commonalize for other parse errors:
+ err_at = G.prs.l.lex_next_at ? G.prs.l.lex_next_at : "UNKNOWN";
+ bc_error_fmt("bad statement terminator at '%.*s'",
+ (int)(strchrnul(err_at, '\n') - err_at),
+ err_at
+ );
+ goto err;
}
+ // The above logic is fragile. Check these examples:
+ // - interative read() still works
#endif
} else {
#if ENABLE_DC
@@ -6807,7 +6808,7 @@ static BC_STATUS zbc_vm_process(const char *text)
bc_parse_reset(&G.prs); // includes bc_program_reset()
RETURN_STATUS(BC_STATUS_FAILURE);
}
- IF_BC(execute:)
+
dbg_lex("%s:%d executing...", __func__, __LINE__);
s = zbc_program_exec();
if (s) {