hush: fix a bit different instance of "No EOL" bug,

add testsuite for that. Expand another testsuite.
This commit is contained in:
Denis Vlasenko 2007-05-23 00:32:25 +00:00
parent 94dace3016
commit 1a7358612f
5 changed files with 57 additions and 40 deletions

View File

@ -2836,14 +2836,13 @@ static struct pipe *new_pipe(void)
static void initialize_context(struct p_context *ctx)
{
ctx->pipe = NULL;
ctx->pending_redirect = NULL;
ctx->child = NULL;
ctx->list_head = new_pipe();
ctx->pipe = ctx->list_head;
ctx->pipe = ctx->list_head = new_pipe();
ctx->pending_redirect = NULL;
ctx->res_w = RES_NONE;
ctx->stack = NULL;
//only ctx->parse_type is not touched... is this intentional?
ctx->old_flag = 0;
ctx->stack = NULL;
done_command(ctx); /* creates the memory for working child */
}
@ -2886,44 +2885,44 @@ static int reserved_word(o_string *dest, struct p_context *ctx)
const struct reserved_combo *r;
for (r = reserved_list; r < reserved_list + NRES; r++) {
if (strcmp(dest->data, r->literal) == 0) {
debug_printf("found reserved word %s, code %d\n", r->literal, r->code);
if (r->flag & FLAG_START) {
struct p_context *new = xmalloc(sizeof(struct p_context));
debug_printf("push stack\n");
if (strcmp(dest->data, r->literal) != 0)
continue;
debug_printf("found reserved word %s, code %d\n", r->literal, r->code);
if (r->flag & FLAG_START) {
struct p_context *new;
debug_printf("push stack\n");
#if ENABLE_HUSH_LOOPS
if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) {
syntax();
free(new);
ctx->res_w = RES_SNTX;
b_reset(dest);
return 1;
}
#endif
*new = *ctx; /* physical copy */
initialize_context(ctx);
ctx->stack = new;
} else if (ctx->res_w == RES_NONE || !(ctx->old_flag & (1 << r->code))) {
if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) {
syntax();
ctx->res_w = RES_SNTX;
b_reset(dest);
return 1;
}
ctx->res_w = r->code;
ctx->old_flag = r->flag;
if (ctx->old_flag & FLAG_END) {
struct p_context *old;
debug_printf("pop stack\n");
done_pipe(ctx, PIPE_SEQ);
old = ctx->stack;
old->child->group = ctx->list_head;
old->child->subshell = 0;
*ctx = *old; /* physical copy */
free(old);
}
#endif
new = xmalloc(sizeof(*new));
*new = *ctx; /* physical copy */
initialize_context(ctx);
ctx->stack = new;
} else if (ctx->res_w == RES_NONE || !(ctx->old_flag & (1 << r->code))) {
syntax();
ctx->res_w = RES_SNTX;
b_reset(dest);
return 1;
}
ctx->res_w = r->code;
ctx->old_flag = r->flag;
if (ctx->old_flag & FLAG_END) {
struct p_context *old;
debug_printf("pop stack\n");
done_pipe(ctx, PIPE_SEQ);
old = ctx->stack;
old->child->group = ctx->list_head;
old->child->subshell = 0;
*ctx = *old; /* physical copy */
free(old);
}
b_reset(dest);
return 1;
}
return 0;
}
@ -3155,7 +3154,8 @@ static int process_command_subs(o_string *dest, struct p_context *ctx,
/* recursion to generate command */
retcode = parse_stream(&result, &inner, input, subst_end);
if (retcode != 0) return retcode; /* syntax error or EOF */
if (retcode != 0)
return retcode; /* syntax error or EOF */
done_word(&result, &inner);
done_pipe(&inner, PIPE_SEQ);
b_free(&result);
@ -3357,9 +3357,15 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
debug_printf_parse("parse_stream entered, end_trigger='%s'\n", end_trigger);
while ((ch = b_getch(input)) != EOF) {
m = charmap[ch];
next = (ch == '\n') ? '\0' : b_peek(input);
while (1) {
ch = b_getch(input);
m = CHAR_IFS;
next = '\0';
if (ch != EOF) {
m = charmap[ch];
if (ch != '\n')
next = b_peek(input);
}
debug_printf_parse(": ch=%c (%d) m=%d quote=%d\n",
ch, ch, m, dest->quote);
if (m == CHAR_ORDINARY
@ -3373,6 +3379,8 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
debug_printf_parse("parse_stream return 1: done_word!=0\n");
return 1;
}
if (ch == EOF)
break;
/* If we aren't performing a substitution, treat
* a newline as a command separator.
* [why we don't handle it exactly like ';'? --vda] */

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,7 @@
# last line has no EOL!
if true
then
echo 1
else
echo 2
fi

View File

@ -3,3 +3,4 @@
.d.
.e.
.f.
.1 abc d e f.

View File

@ -4,5 +4,5 @@ fi
# 'd e f' should be split into 3 separate args:
for a in $*; do echo ".$a."; done
# must produce .1 abc d e f. Currently does not
#for a in "$*"; do echo ".$a."; done
# must produce .1 abc d e f.
for a in "$*"; do echo ".$a."; done