hush: fix a bug where we were requiring semicolon here: (cmd;)

also fix a bug where after error prompt is not shown.

function                                             old     new   delta
parse_stream                                        1612    1638     +26
parse_and_run_stream                                 361     375     +14
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 40/0)               Total: 40 bytes
This commit is contained in:
Denis Vlasenko 2008-06-14 17:13:20 +00:00
parent dd316dd283
commit f8d01d3f66
4 changed files with 34 additions and 22 deletions

View File

@ -3437,11 +3437,11 @@ static int parse_group(o_string *dest, struct p_context *ctx,
child->subshell = 1; child->subshell = 1;
} }
rcode = parse_stream(dest, &sub, input, endch); rcode = parse_stream(dest, &sub, input, endch);
//vda: err chk? if (rcode == 0) {
done_word(dest, &sub); /* finish off the final word in the subcontext */ done_word(dest, &sub); /* finish off the final word in the subcontext */
done_pipe(&sub, PIPE_SEQ); /* and the final command there, too */ done_pipe(&sub, PIPE_SEQ); /* and the final command there, too */
child->group = sub.list_head; child->group = sub.list_head;
}
debug_printf_parse("parse_group return %d\n", rcode); debug_printf_parse("parse_group return %d\n", rcode);
return rcode; return rcode;
/* child remains "open", available for possible redirects */ /* child remains "open", available for possible redirects */
@ -3700,11 +3700,19 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
done_pipe(ctx, PIPE_SEQ); done_pipe(ctx, PIPE_SEQ);
} }
} }
if ((end_trigger && strchr(end_trigger, ch)) if (end_trigger) {
&& !dest->o_quote && ctx->res_w == RES_NONE if (!dest->o_quote && strchr(end_trigger, ch)) {
) { /* Special case: (...word) makes last word terminate,
debug_printf_parse("parse_stream return 0: end_trigger char found\n"); * as if ';' is seen */
return 0; if (ch == ')') {
done_word(dest, ctx);
done_pipe(ctx, PIPE_SEQ);
}
if (ctx->res_w == RES_NONE) {
debug_printf_parse("parse_stream return 0: end_trigger char found\n");
return 0;
}
}
} }
if (m == CHAR_IFS) if (m == CHAR_IFS)
continue; continue;
@ -3757,15 +3765,15 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
dest->nonnull = 1; dest->nonnull = 1;
while (1) { while (1) {
ch = i_getch(input); ch = i_getch(input);
if (ch == EOF || ch == '\'') if (ch == EOF) {
syntax("unterminated '");
debug_printf_parse("parse_stream return 1: unterminated '\n");
return 1;
}
if (ch == '\'')
break; break;
o_addqchr(dest, ch); o_addqchr(dest, ch);
} }
if (ch == EOF) {
syntax("unterminated '");
debug_printf_parse("parse_stream return 1: unterminated '\n");
return 1;
}
break; break;
case '"': case '"':
dest->nonnull = 1; dest->nonnull = 1;
@ -3861,7 +3869,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
if (ENABLE_HUSH_DEBUG) if (ENABLE_HUSH_DEBUG)
bb_error_msg_and_die("BUG: unexpected %c\n", ch); bb_error_msg_and_die("BUG: unexpected %c\n", ch);
} }
} } /* while (1) */
/* Complain if quote? No, maybe we just finished a command substitution /* Complain if quote? No, maybe we just finished a command substitution
* that was quoted. Example: * that was quoted. Example:
* $ echo "`cat foo` plus more" * $ echo "`cat foo` plus more"
@ -3913,8 +3921,9 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag)
struct p_context ctx; struct p_context ctx;
o_string temp = NULL_O_STRING; o_string temp = NULL_O_STRING;
int rcode; int rcode;
do { do {
// It always has PARSEFLAG_SEMICOLON, can we remove all checks for this bit? // parse_type always has PARSEFLAG_SEMICOLON, can we remove all checks for this bit?
// After that, the whole parse_type fiels is not needed. // After that, the whole parse_type fiels is not needed.
ctx.parse_type = parse_flag; ctx.parse_type = parse_flag;
initialize_context(&ctx); initialize_context(&ctx);
@ -3938,17 +3947,21 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag)
debug_printf_exec("parse_stream_outer: run_and_free_list\n"); debug_printf_exec("parse_stream_outer: run_and_free_list\n");
run_and_free_list(ctx.list_head); run_and_free_list(ctx.list_head);
} else { } else {
/* We arrive here also if rcode == 1 (error in parse_stream) */
if (ctx.old_flag != 0) { if (ctx.old_flag != 0) {
free(ctx.stack); free(ctx.stack);
o_reset(&temp); o_reset(&temp);
} }
temp.nonnull = 0; temp.nonnull = 0;
temp.o_quote = 0; temp.o_quote = 0;
inp->p = NULL;
free_pipe_list(ctx.list_head, /* indent: */ 0); free_pipe_list(ctx.list_head, /* indent: */ 0);
/* Discard all unprocessed line input, force prompt on */
inp->p = NULL;
inp->promptme = 1;
} }
o_free(&temp); o_free(&temp);
} while (rcode != -1 && !(parse_flag & PARSEFLAG_EXIT_FROM_LOOP)); /* loop on syntax errors, return on EOF */ /* loop on syntax errors, return on EOF: */
} while (rcode != -1 && !(parse_flag & PARSEFLAG_EXIT_FROM_LOOP));
return 0; return 0;
} }

View File

@ -1,6 +1,5 @@
false false
: :
echo $? echo $?
# Extra ; after done is due to a bug (while :; do exit; done)
(while :; do exit; done;)
echo OK: $? echo OK: $?