diff options
author | Denys Vlasenko | 2009-05-23 16:50:07 +0200 |
---|---|---|
committer | Denys Vlasenko | 2009-05-23 16:50:07 +0200 |
commit | e9bda90e549d1470c7630e1f015b7c1e1560b56b (patch) | |
tree | 171240523541449a1d97562564c2f0037057782d /shell | |
parent | 342a63d659ed41b0fe9f412eb75d495e64cc2096 (diff) | |
download | busybox-e9bda90e549d1470c7630e1f015b7c1e1560b56b.zip busybox-e9bda90e549d1470c7630e1f015b7c1e1560b56b.tar.gz |
hush: fix problems with case in subshells and with "case esac"
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r-- | shell/hush.c | 35 | ||||
-rw-r--r-- | shell/hush_test/hush-misc/case1.right | 8 | ||||
-rwxr-xr-x | shell/hush_test/hush-misc/case1.tests | 15 | ||||
-rw-r--r-- | shell/hush_test/hush-vars/unset.right | 2 |
4 files changed, 42 insertions, 18 deletions
diff --git a/shell/hush.c b/shell/hush.c index d6286b6..acc8ef9 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -192,9 +192,10 @@ typedef enum reserved_style { #endif #if ENABLE_HUSH_CASE RES_CASE , - /* two pseudo-keywords support contrived "case" syntax: */ - RES_MATCH , /* "word)" */ - RES_CASEI , /* "this command is inside CASE" */ + /* three pseudo-keywords support contrived "case" syntax: */ + RES_CASE_IN, /* "case ... IN", turns into RES_MATCH when IN is observed */ + RES_MATCH , /* "word)" */ + RES_CASE_BODY, /* "this command is inside CASE" */ RES_ESAC , #endif RES_XXXX , @@ -3766,8 +3767,9 @@ static void debug_print_tree(struct pipe *pi, int lvl) #endif #if ENABLE_HUSH_CASE [RES_CASE ] = "CASE" , + [RES_CASE_IN ] = "CASE_IN" , [RES_MATCH] = "MATCH", - [RES_CASEI] = "CASEI", + [RES_CASE_BODY] = "CASE_BODY", [RES_ESAC ] = "ESAC" , #endif [RES_XXXX ] = "XXXX" , @@ -4011,7 +4013,7 @@ static int run_list(struct pipe *pi) } continue; } - if (rword == RES_CASEI) { /* inside of a case branch */ + if (rword == RES_CASE_BODY) { /* inside of a case branch */ if (cond_code != 0) continue; /* not matched yet, skip this pipe */ } @@ -4252,7 +4254,9 @@ static void done_pipe(struct parse_context *ctx, pipe_style type) #endif #if ENABLE_HUSH_CASE if (ctx->ctx_res_w == RES_MATCH) - ctx->ctx_res_w = RES_CASEI; + ctx->ctx_res_w = RES_CASE_BODY; + if (ctx->ctx_res_w == RES_CASE) + ctx->ctx_res_w = RES_CASE_IN; #endif ctx->command = NULL; /* trick done_command below */ /* Create the memory for command, roughly: @@ -4366,10 +4370,10 @@ static int reserved_word(o_string *word, struct parse_context *ctx) debug_printf("found reserved word %s, res %d\n", r->literal, r->res); #if ENABLE_HUSH_CASE - if (r->res == RES_IN && ctx->ctx_res_w == RES_CASE) - /* "case word IN ..." - IN part starts first match part */ + if (r->res == RES_IN && ctx->ctx_res_w == RES_CASE_IN) { + /* "case word IN ..." - IN part starts first MATCH part */ r = &reserved_match; - else + } else #endif if (r->flag == 0) { /* '!' */ if (ctx->ctx_inverted) { /* bash doesn't accept '! ! true' */ @@ -4495,6 +4499,9 @@ static int done_word(o_string *word, struct parse_context *ctx) && ctx->ctx_res_w != RES_FOR /* ...not after FOR or IN */ && ctx->ctx_res_w != RES_IN # endif +# if ENABLE_HUSH_CASE + && ctx->ctx_res_w != RES_CASE +# endif ) { debug_printf_parse("checking '%s' for reserved-ness\n", word->data); if (reserved_word(word, ctx)) { @@ -5578,7 +5585,13 @@ static struct pipe *parse_stream(char **pstring, } if (end_trigger && end_trigger == ch - && (heredoc_cnt == 0 || end_trigger != ';') + && (ch != ';' || heredoc_cnt == 0) +#if ENABLE_HUSH_CASE + && (ch != ')' + || ctx.ctx_res_w != RES_MATCH + || (!dest.o_quoted && strcmp(dest.data, "esac") == 0) + ) +#endif ) { if (heredoc_cnt) { /* This is technically valid: @@ -5784,7 +5797,7 @@ static struct pipe *parse_stream(char **pstring, break; ch = i_getch(input); nommu_addchr(&ctx.as_string, ch); - if (ctx.ctx_res_w == RES_CASEI) { + if (ctx.ctx_res_w == RES_CASE_BODY) { ctx.ctx_dsemicolon = 1; ctx.ctx_res_w = RES_MATCH; break; diff --git a/shell/hush_test/hush-misc/case1.right b/shell/hush_test/hush-misc/case1.right index e9e371a..4afb2f5 100644 --- a/shell/hush_test/hush-misc/case1.right +++ b/shell/hush_test/hush-misc/case1.right @@ -12,3 +12,11 @@ OK_44 OK_51 OK_52 OK_53 +OK_sub1 +OK_sub2 +OK_sub3 +OK_sub4 +OK_sub5 +OK_sub6 +OK_esac1 +Done diff --git a/shell/hush_test/hush-misc/case1.tests b/shell/hush_test/hush-misc/case1.tests index b2c96cc..d72b57f 100755 --- a/shell/hush_test/hush-misc/case1.tests +++ b/shell/hush_test/hush-misc/case1.tests @@ -25,13 +25,16 @@ case w in `echo w`) echo OK_51;; `echo WRONG >&2`w) echo WRONG;; esac; case w in `echo OK_52 >&2`) echo SKIP;; `echo`w) echo OK_53;; esac; # parsing cases in subshells can easily get messy - case m in m) echo ok-sub1;; esac - case m in (m) echo ok-sub2;; esac -(case m in m) echo ok-sub3;; esac) -(case m in (m) echo ok-sub4;; esac) + case m in m) echo OK_sub1;; esac + case m in (m) echo OK_sub2;; esac +(case m in m) echo OK_sub3;; esac) +(case m in (m) echo OK_sub4;; esac) ( - case m in m) echo ok-sub5;; esac + case m in m) echo OK_sub5;; esac ) ( - case m in (m) echo ok-sub6;; esac + case m in (m) echo OK_sub6;; esac ) +(case esac in "esac") echo OK_esac1;; esac) + +echo Done diff --git a/shell/hush_test/hush-vars/unset.right b/shell/hush_test/hush-vars/unset.right index 0da0e57..1fbe76a 100644 --- a/shell/hush_test/hush-vars/unset.right +++ b/shell/hush_test/hush-vars/unset.right @@ -1,5 +1,5 @@ 0 -unset: invalid option -- 'm' +unset: invalid option -- m 1 0 ___ |