diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-14 08:26:47 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-14 08:26:47 +0000 |
commit | 757361f9f58e120ddb9855fa0f50e12b921c37f0 (patch) | |
tree | f3f7bbe64e3e0dcf394205b7c5c8fa6046c38d1e | |
parent | 395ae452165a607c6b5bc4623225516044619616 (diff) | |
download | busybox-w32-757361f9f58e120ddb9855fa0f50e12b921c37f0.tar.gz busybox-w32-757361f9f58e120ddb9855fa0f50e12b921c37f0.tar.bz2 busybox-w32-757361f9f58e120ddb9855fa0f50e12b921c37f0.zip |
hush: fix "... pattern) cmd;; esac" case
-rw-r--r-- | shell/hush.c | 6 | ||||
-rw-r--r-- | shell/hush_doc.txt | 24 |
2 files changed, 27 insertions, 3 deletions
diff --git a/shell/hush.c b/shell/hush.c index db608018c..47cdf6f02 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -2986,7 +2986,9 @@ static int done_word(o_string *word, struct p_context *ctx) | |||
2986 | } | 2986 | } |
2987 | #if HAS_KEYWORDS | 2987 | #if HAS_KEYWORDS |
2988 | #if ENABLE_HUSH_CASE | 2988 | #if ENABLE_HUSH_CASE |
2989 | if (ctx->ctx_dsemicolon) { | 2989 | if (ctx->ctx_dsemicolon |
2990 | && strcmp(word->data, "esac") != 0 /* not "... pattern) cmd;; esac" */ | ||
2991 | ) { | ||
2990 | /* already done when ctx_dsemicolon was set to 1: */ | 2992 | /* already done when ctx_dsemicolon was set to 1: */ |
2991 | /* ctx->ctx_res_w = RES_MATCH; */ | 2993 | /* ctx->ctx_res_w = RES_MATCH; */ |
2992 | ctx->ctx_dsemicolon = 0; | 2994 | ctx->ctx_dsemicolon = 0; |
@@ -3112,7 +3114,7 @@ static void done_pipe(struct p_context *ctx, pipe_style type) | |||
3112 | if (not_null IF_HAS_KEYWORDS(|| ctx->ctx_res_w != RES_NONE)) { | 3114 | if (not_null IF_HAS_KEYWORDS(|| ctx->ctx_res_w != RES_NONE)) { |
3113 | struct pipe *new_p; | 3115 | struct pipe *new_p; |
3114 | debug_printf_parse("done_pipe: adding new pipe: " | 3116 | debug_printf_parse("done_pipe: adding new pipe: " |
3115 | " not_null:%d ctx->ctx_res_w:%d\n", | 3117 | "not_null:%d ctx->ctx_res_w:%d\n", |
3116 | not_null, ctx->ctx_res_w); | 3118 | not_null, ctx->ctx_res_w); |
3117 | new_p = new_pipe(); | 3119 | new_p = new_pipe(); |
3118 | ctx->pipe->next = new_p; | 3120 | ctx->pipe->next = new_p; |
diff --git a/shell/hush_doc.txt b/shell/hush_doc.txt index ec5dd00f2..b2fd24426 100644 --- a/shell/hush_doc.txt +++ b/shell/hush_doc.txt | |||
@@ -72,10 +72,32 @@ Dummy trailing pipes with no commands are artifacts of imperfect | |||
72 | parsing algorithm - done_pipe() appends new pipe struct beforehand | 72 | parsing algorithm - done_pipe() appends new pipe struct beforehand |
73 | and last one ends up empty and unused. | 73 | and last one ends up empty and unused. |
74 | 74 | ||
75 | "for" and "case" statements (ab)use progs[] to keep their data | ||
76 | instead of argv vector progs[] usually do. "for" keyword is forcing | ||
77 | pipe termination after first word, which makes hush see | ||
78 | "for v in..." as "for v; in...". "case" keyword does the same. | ||
79 | Other judiciuosly placed hacks make hush see | ||
80 | "case word in a) cmd1;; b) cmd2;; esac" as if it was | ||
81 | "case word; match a; cmd; match b; cmd2; esac" | ||
82 | ("match" is a fictitious keyword here): | ||
83 | |||
84 | "case word in a) cmd1;; b) cmd2; esac" - | ||
85 | pipe 0 res_word=NONE followup=1 SEQ | ||
86 | prog 0 group {}: | ||
87 | pipe 0 res_word=CASE followup=SEQ prog[0] 'word' | ||
88 | pipe 1 res_word=MATCH followup=SEQ prog[0] 'a' | ||
89 | pipe 2 res_word=CASEI followup=SEQ prog[0] 'cmd1' | ||
90 | pipe 3 res_word=MATCH followup=SEQ prog[0] 'b' | ||
91 | pipe 4 res_word=CASEI followup=SEQ prog[0] 'cmd2' | ||
92 | pipe 5 res_word=CASEI followup=SEQ prog[0] 'cmd3' | ||
93 | pipe 6 res_word=ESAC followup=SEQ | ||
94 | pipe 7 res_word=NONE followup=(null) | ||
95 | pipe 1 res_word=NONE followup=1 SEQ | ||
96 | |||
75 | 97 | ||
76 | 2008-01 | 98 | 2008-01 |
77 | 99 | ||
78 | This is how hush runs commands: | 100 | Command execution |
79 | 101 | ||
80 | /* callsite: process_command_subs */ | 102 | /* callsite: process_command_subs */ |
81 | generate_stream_from_list(struct pipe *head) - handles `cmds` | 103 | generate_stream_from_list(struct pipe *head) - handles `cmds` |