summaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-05-23 16:50:07 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-05-23 16:50:07 +0200
commite9bda90e549d1470c7630e1f015b7c1e1560b56b (patch)
tree171240523541449a1d97562564c2f0037057782d /shell
parent342a63d659ed41b0fe9f412eb75d495e64cc2096 (diff)
downloadbusybox-w32-e9bda90e549d1470c7630e1f015b7c1e1560b56b.tar.gz
busybox-w32-e9bda90e549d1470c7630e1f015b7c1e1560b56b.tar.bz2
busybox-w32-e9bda90e549d1470c7630e1f015b7c1e1560b56b.zip
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.c35
-rw-r--r--shell/hush_test/hush-misc/case1.right8
-rwxr-xr-xshell/hush_test/hush-misc/case1.tests15
-rw-r--r--shell/hush_test/hush-vars/unset.right2
4 files changed, 42 insertions, 18 deletions
diff --git a/shell/hush.c b/shell/hush.c
index d6286b61c..acc8ef944 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -192,9 +192,10 @@ typedef enum reserved_style {
192#endif 192#endif
193#if ENABLE_HUSH_CASE 193#if ENABLE_HUSH_CASE
194 RES_CASE , 194 RES_CASE ,
195 /* two pseudo-keywords support contrived "case" syntax: */ 195 /* three pseudo-keywords support contrived "case" syntax: */
196 RES_MATCH , /* "word)" */ 196 RES_CASE_IN, /* "case ... IN", turns into RES_MATCH when IN is observed */
197 RES_CASEI , /* "this command is inside CASE" */ 197 RES_MATCH , /* "word)" */
198 RES_CASE_BODY, /* "this command is inside CASE" */
198 RES_ESAC , 199 RES_ESAC ,
199#endif 200#endif
200 RES_XXXX , 201 RES_XXXX ,
@@ -3766,8 +3767,9 @@ static void debug_print_tree(struct pipe *pi, int lvl)
3766#endif 3767#endif
3767#if ENABLE_HUSH_CASE 3768#if ENABLE_HUSH_CASE
3768 [RES_CASE ] = "CASE" , 3769 [RES_CASE ] = "CASE" ,
3770 [RES_CASE_IN ] = "CASE_IN" ,
3769 [RES_MATCH] = "MATCH", 3771 [RES_MATCH] = "MATCH",
3770 [RES_CASEI] = "CASEI", 3772 [RES_CASE_BODY] = "CASE_BODY",
3771 [RES_ESAC ] = "ESAC" , 3773 [RES_ESAC ] = "ESAC" ,
3772#endif 3774#endif
3773 [RES_XXXX ] = "XXXX" , 3775 [RES_XXXX ] = "XXXX" ,
@@ -4011,7 +4013,7 @@ static int run_list(struct pipe *pi)
4011 } 4013 }
4012 continue; 4014 continue;
4013 } 4015 }
4014 if (rword == RES_CASEI) { /* inside of a case branch */ 4016 if (rword == RES_CASE_BODY) { /* inside of a case branch */
4015 if (cond_code != 0) 4017 if (cond_code != 0)
4016 continue; /* not matched yet, skip this pipe */ 4018 continue; /* not matched yet, skip this pipe */
4017 } 4019 }
@@ -4252,7 +4254,9 @@ static void done_pipe(struct parse_context *ctx, pipe_style type)
4252#endif 4254#endif
4253#if ENABLE_HUSH_CASE 4255#if ENABLE_HUSH_CASE
4254 if (ctx->ctx_res_w == RES_MATCH) 4256 if (ctx->ctx_res_w == RES_MATCH)
4255 ctx->ctx_res_w = RES_CASEI; 4257 ctx->ctx_res_w = RES_CASE_BODY;
4258 if (ctx->ctx_res_w == RES_CASE)
4259 ctx->ctx_res_w = RES_CASE_IN;
4256#endif 4260#endif
4257 ctx->command = NULL; /* trick done_command below */ 4261 ctx->command = NULL; /* trick done_command below */
4258 /* Create the memory for command, roughly: 4262 /* Create the memory for command, roughly:
@@ -4366,10 +4370,10 @@ static int reserved_word(o_string *word, struct parse_context *ctx)
4366 4370
4367 debug_printf("found reserved word %s, res %d\n", r->literal, r->res); 4371 debug_printf("found reserved word %s, res %d\n", r->literal, r->res);
4368#if ENABLE_HUSH_CASE 4372#if ENABLE_HUSH_CASE
4369 if (r->res == RES_IN && ctx->ctx_res_w == RES_CASE) 4373 if (r->res == RES_IN && ctx->ctx_res_w == RES_CASE_IN) {
4370 /* "case word IN ..." - IN part starts first match part */ 4374 /* "case word IN ..." - IN part starts first MATCH part */
4371 r = &reserved_match; 4375 r = &reserved_match;
4372 else 4376 } else
4373#endif 4377#endif
4374 if (r->flag == 0) { /* '!' */ 4378 if (r->flag == 0) { /* '!' */
4375 if (ctx->ctx_inverted) { /* bash doesn't accept '! ! true' */ 4379 if (ctx->ctx_inverted) { /* bash doesn't accept '! ! true' */
@@ -4495,6 +4499,9 @@ static int done_word(o_string *word, struct parse_context *ctx)
4495 && ctx->ctx_res_w != RES_FOR /* ...not after FOR or IN */ 4499 && ctx->ctx_res_w != RES_FOR /* ...not after FOR or IN */
4496 && ctx->ctx_res_w != RES_IN 4500 && ctx->ctx_res_w != RES_IN
4497# endif 4501# endif
4502# if ENABLE_HUSH_CASE
4503 && ctx->ctx_res_w != RES_CASE
4504# endif
4498 ) { 4505 ) {
4499 debug_printf_parse("checking '%s' for reserved-ness\n", word->data); 4506 debug_printf_parse("checking '%s' for reserved-ness\n", word->data);
4500 if (reserved_word(word, ctx)) { 4507 if (reserved_word(word, ctx)) {
@@ -5578,7 +5585,13 @@ static struct pipe *parse_stream(char **pstring,
5578 } 5585 }
5579 5586
5580 if (end_trigger && end_trigger == ch 5587 if (end_trigger && end_trigger == ch
5581 && (heredoc_cnt == 0 || end_trigger != ';') 5588 && (ch != ';' || heredoc_cnt == 0)
5589#if ENABLE_HUSH_CASE
5590 && (ch != ')'
5591 || ctx.ctx_res_w != RES_MATCH
5592 || (!dest.o_quoted && strcmp(dest.data, "esac") == 0)
5593 )
5594#endif
5582 ) { 5595 ) {
5583 if (heredoc_cnt) { 5596 if (heredoc_cnt) {
5584 /* This is technically valid: 5597 /* This is technically valid:
@@ -5784,7 +5797,7 @@ static struct pipe *parse_stream(char **pstring,
5784 break; 5797 break;
5785 ch = i_getch(input); 5798 ch = i_getch(input);
5786 nommu_addchr(&ctx.as_string, ch); 5799 nommu_addchr(&ctx.as_string, ch);
5787 if (ctx.ctx_res_w == RES_CASEI) { 5800 if (ctx.ctx_res_w == RES_CASE_BODY) {
5788 ctx.ctx_dsemicolon = 1; 5801 ctx.ctx_dsemicolon = 1;
5789 ctx.ctx_res_w = RES_MATCH; 5802 ctx.ctx_res_w = RES_MATCH;
5790 break; 5803 break;
diff --git a/shell/hush_test/hush-misc/case1.right b/shell/hush_test/hush-misc/case1.right
index e9e371ac0..4afb2f51c 100644
--- a/shell/hush_test/hush-misc/case1.right
+++ b/shell/hush_test/hush-misc/case1.right
@@ -12,3 +12,11 @@ OK_44
12OK_51 12OK_51
13OK_52 13OK_52
14OK_53 14OK_53
15OK_sub1
16OK_sub2
17OK_sub3
18OK_sub4
19OK_sub5
20OK_sub6
21OK_esac1
22Done
diff --git a/shell/hush_test/hush-misc/case1.tests b/shell/hush_test/hush-misc/case1.tests
index b2c96ccf8..d72b57f53 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;
25case w in `echo OK_52 >&2`) echo SKIP;; `echo`w) echo OK_53;; esac; 25case w in `echo OK_52 >&2`) echo SKIP;; `echo`w) echo OK_53;; esac;
26 26
27# parsing cases in subshells can easily get messy 27# parsing cases in subshells can easily get messy
28 case m in m) echo ok-sub1;; esac 28 case m in m) echo OK_sub1;; esac
29 case m in (m) echo ok-sub2;; esac 29 case m in (m) echo OK_sub2;; esac
30(case m in m) echo ok-sub3;; esac) 30(case m in m) echo OK_sub3;; esac)
31(case m in (m) echo ok-sub4;; esac) 31(case m in (m) echo OK_sub4;; esac)
32( 32(
33 case m in m) echo ok-sub5;; esac 33 case m in m) echo OK_sub5;; esac
34) 34)
35( 35(
36 case m in (m) echo ok-sub6;; esac 36 case m in (m) echo OK_sub6;; esac
37) 37)
38(case esac in "esac") echo OK_esac1;; esac)
39
40echo Done
diff --git a/shell/hush_test/hush-vars/unset.right b/shell/hush_test/hush-vars/unset.right
index 0da0e5736..1fbe76a73 100644
--- a/shell/hush_test/hush-vars/unset.right
+++ b/shell/hush_test/hush-vars/unset.right
@@ -1,5 +1,5 @@
10 10
2unset: invalid option -- 'm' 2unset: invalid option -- m
31 31
40 40
5___ 5___