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:
parent
dd316dd283
commit
f8d01d3f66
53
shell/hush.c
53
shell/hush.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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: $?
|
||||||
|
Loading…
Reference in New Issue
Block a user