From 1a7358612ff2dfdfc9fa461faa946c577666787f Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Wed, 23 May 2007 00:32:25 +0000 Subject: [PATCH] hush: fix a bit different instance of "No EOL" bug, add testsuite for that. Expand another testsuite. --- shell/hush.c | 84 +++++++++++++---------- shell/hush_test/hush-parsing/noeol2.right | 1 + shell/hush_test/hush-parsing/noeol2.tests | 7 ++ shell/hush_test/hush-vars/star.right | 1 + shell/hush_test/hush-vars/star.tests | 4 +- 5 files changed, 57 insertions(+), 40 deletions(-) create mode 100644 shell/hush_test/hush-parsing/noeol2.right create mode 100755 shell/hush_test/hush-parsing/noeol2.tests diff --git a/shell/hush.c b/shell/hush.c index 61c03f703..aab6ff3a3 100644 --- a/shell/hush.c +++ b/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] */ diff --git a/shell/hush_test/hush-parsing/noeol2.right b/shell/hush_test/hush-parsing/noeol2.right new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/shell/hush_test/hush-parsing/noeol2.right @@ -0,0 +1 @@ +1 diff --git a/shell/hush_test/hush-parsing/noeol2.tests b/shell/hush_test/hush-parsing/noeol2.tests new file mode 100755 index 000000000..1220f056f --- /dev/null +++ b/shell/hush_test/hush-parsing/noeol2.tests @@ -0,0 +1,7 @@ +# last line has no EOL! +if true +then + echo 1 +else + echo 2 +fi \ No newline at end of file diff --git a/shell/hush_test/hush-vars/star.right b/shell/hush_test/hush-vars/star.right index b33b176b2..0ecc55bc2 100644 --- a/shell/hush_test/hush-vars/star.right +++ b/shell/hush_test/hush-vars/star.right @@ -3,3 +3,4 @@ .d. .e. .f. +.1 abc d e f. diff --git a/shell/hush_test/hush-vars/star.tests b/shell/hush_test/hush-vars/star.tests index 1914dde44..5554c4090 100755 --- a/shell/hush_test/hush-vars/star.tests +++ b/shell/hush_test/hush-vars/star.tests @@ -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