hush: fix a bit different instance of "No EOL" bug,
authorDenis Vlasenko <vda.linux@googlemail.com>
Wed, 23 May 2007 00:32:25 +0000 (00:32 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Wed, 23 May 2007 00:32:25 +0000 (00:32 -0000)
add testsuite for that. Expand another testsuite.

shell/hush.c
shell/hush_test/hush-parsing/noeol2.right [new file with mode: 0644]
shell/hush_test/hush-parsing/noeol2.tests [new file with mode: 0755]
shell/hush_test/hush-vars/star.right
shell/hush_test/hush-vars/star.tests

index 61c03f7..aab6ff3 100644 (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] */
diff --git a/shell/hush_test/hush-parsing/noeol2.right b/shell/hush_test/hush-parsing/noeol2.right
new file mode 100644 (file)
index 0000000..d00491f
--- /dev/null
@@ -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 (executable)
index 0000000..1220f05
--- /dev/null
@@ -0,0 +1,7 @@
+# last line has no EOL!
+if true
+then
+  echo 1
+else
+  echo 2
+fi
\ No newline at end of file
index 1914dde..5554c40 100755 (executable)
@@ -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