mirror of
https://github.com/sheumann/hush.git
synced 2024-12-21 23:29:34 +00:00
hush: fix a bit different instance of "No EOL" bug,
add testsuite for that. Expand another testsuite.
This commit is contained in:
parent
94dace3016
commit
1a7358612f
84
shell/hush.c
84
shell/hush.c
@ -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] */
|
||||
|
1
shell/hush_test/hush-parsing/noeol2.right
Normal file
1
shell/hush_test/hush-parsing/noeol2.right
Normal file
@ -0,0 +1 @@
|
||||
1
|
7
shell/hush_test/hush-parsing/noeol2.tests
Executable file
7
shell/hush_test/hush-parsing/noeol2.tests
Executable file
@ -0,0 +1,7 @@
|
||||
# last line has no EOL!
|
||||
if true
|
||||
then
|
||||
echo 1
|
||||
else
|
||||
echo 2
|
||||
fi
|
@ -3,3 +3,4 @@
|
||||
.d.
|
||||
.e.
|
||||
.f.
|
||||
.1 abc d e f.
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user