hush: fix "... pattern) cmd;; esac" case
authorDenis Vlasenko <vda.linux@googlemail.com>
Mon, 14 Jul 2008 08:26:47 +0000 (08:26 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Mon, 14 Jul 2008 08:26:47 +0000 (08:26 -0000)
shell/hush.c
shell/hush_doc.txt

index db60801..47cdf6f 100644 (file)
@@ -2986,7 +2986,9 @@ static int done_word(o_string *word, struct p_context *ctx)
                }
 #if HAS_KEYWORDS
 #if ENABLE_HUSH_CASE
-               if (ctx->ctx_dsemicolon) {
+               if (ctx->ctx_dsemicolon
+                && strcmp(word->data, "esac") != 0 /* not "... pattern) cmd;; esac" */
+               ) {
                        /* already done when ctx_dsemicolon was set to 1: */
                        /* ctx->ctx_res_w = RES_MATCH; */
                        ctx->ctx_dsemicolon = 0;
@@ -3112,7 +3114,7 @@ static void done_pipe(struct p_context *ctx, pipe_style type)
        if (not_null IF_HAS_KEYWORDS(|| ctx->ctx_res_w != RES_NONE)) {
                struct pipe *new_p;
                debug_printf_parse("done_pipe: adding new pipe: "
-                               " not_null:%d ctx->ctx_res_w:%d\n",
+                               "not_null:%d ctx->ctx_res_w:%d\n",
                                not_null, ctx->ctx_res_w);
                new_p = new_pipe();
                ctx->pipe->next = new_p;
index ec5dd00..b2fd244 100644 (file)
@@ -72,10 +72,32 @@ Dummy trailing pipes with no commands are artifacts of imperfect
 parsing algorithm - done_pipe() appends new pipe struct beforehand
 and last one ends up empty and unused.
 
+"for" and "case" statements (ab)use progs[] to keep their data
+instead of argv vector progs[] usually do. "for" keyword is forcing
+pipe termination after first word, which makes hush see
+"for v in..." as "for v; in...". "case" keyword does the same.
+Other judiciuosly placed hacks make hush see
+"case word in a) cmd1;; b) cmd2;; esac" as if it was
+"case word; match a; cmd; match b; cmd2; esac"
+("match" is a fictitious keyword here):
+
+"case word in a) cmd1;; b) cmd2; esac" -
+pipe 0 res_word=NONE followup=1 SEQ
+ prog 0 group {}:
+  pipe 0 res_word=CASE followup=SEQ prog[0] 'word'
+  pipe 1 res_word=MATCH followup=SEQ prog[0] 'a'
+  pipe 2 res_word=CASEI followup=SEQ prog[0] 'cmd1'
+  pipe 3 res_word=MATCH followup=SEQ prog[0] 'b'
+  pipe 4 res_word=CASEI followup=SEQ prog[0] 'cmd2'
+  pipe 5 res_word=CASEI followup=SEQ prog[0] 'cmd3'
+  pipe 6 res_word=ESAC followup=SEQ
+  pipe 7 res_word=NONE followup=(null)
+pipe 1 res_word=NONE followup=1 SEQ
+
 
 2008-01
 
-       This is how hush runs commands:
+       Command execution
 
 /* callsite: process_command_subs */
 generate_stream_from_list(struct pipe *head) - handles `cmds`