diff options
author | jilles <jilles@FreeBSD.org> | 2011-06-17 13:03:49 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2011-06-17 13:03:49 +0000 |
commit | c7a72567a8474dcecd93215073976b04171d1144 (patch) | |
tree | d74a77976194c0d5d68bbf18c002a166b97300a5 /bin | |
parent | f405f6d6f8e62f9714eb668d35001c794646022b (diff) | |
download | FreeBSD-src-c7a72567a8474dcecd93215073976b04171d1144.zip FreeBSD-src-c7a72567a8474dcecd93215073976b04171d1144.tar.gz |
sh: Add case statement fallthrough (with ';&' instead of ';;').
Replacing ;; with the new control operator ;& will cause the next list to be
executed as well without checking its pattern, continuing until a list ends
with ;; or until the end of the case statement. This is like omitting
"break" in a C "switch" statement.
The sequence ;& was formerly invalid.
This feature is proposed for the next POSIX issue in Austin Group issue
#449.
Diffstat (limited to 'bin')
-rw-r--r-- | bin/sh/eval.c | 8 | ||||
-rw-r--r-- | bin/sh/mktokens | 1 | ||||
-rw-r--r-- | bin/sh/nodetypes | 3 | ||||
-rw-r--r-- | bin/sh/parser.c | 14 | ||||
-rw-r--r-- | bin/sh/sh.1 | 9 |
5 files changed, 28 insertions, 7 deletions
diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 25793c1..a22d4b1 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -386,6 +386,14 @@ evalcase(union node *n, int flags) for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) { for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) { if (casematch(patp, arglist.list->text)) { + while (cp->nclist.next && + cp->type == NCLISTFALLTHRU) { + if (evalskip != 0) + break; + evaltree(cp->nclist.body, + flags & ~EV_EXIT); + cp = cp->nclist.next; + } if (evalskip == 0) { evaltree(cp->nclist.body, flags); } diff --git a/bin/sh/mktokens b/bin/sh/mktokens index b85c8cb9..82d7cd7 100644 --- a/bin/sh/mktokens +++ b/bin/sh/mktokens @@ -50,6 +50,7 @@ TPIPE 0 "|" TLP 0 "(" TRP 1 ")" TENDCASE 1 ";;" +TFALLTHRU 1 ";&" TREDIR 0 redirection TWORD 0 word TIF 0 "if" diff --git a/bin/sh/nodetypes b/bin/sh/nodetypes index e1e1b04..f705827 100644 --- a/bin/sh/nodetypes +++ b/bin/sh/nodetypes @@ -96,12 +96,13 @@ NCASE ncase # a case statement expr nodeptr # the word to switch on cases nodeptr # the list of cases (NCLIST nodes) -NCLIST nclist # a case +NCLIST nclist # a case ending with ;; type int next nodeptr # the next case in list pattern nodeptr # list of patterns for this case body nodeptr # code to execute for this case +NCLISTFALLTHRU nclist # a case ending with ;& NDEFUN narg # define a function. The "next" field contains # the body of the function. diff --git a/bin/sh/parser.c b/bin/sh/parser.c index 2fea1ec..61be512 100644 --- a/bin/sh/parser.c +++ b/bin/sh/parser.c @@ -542,10 +542,13 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); checkkwd = CHKNL | CHKKWD | CHKALIAS; if ((t = readtoken()) != TESAC) { - if (t != TENDCASE) - synexpect(TENDCASE); + if (t == TENDCASE) + ; + else if (t == TFALLTHRU) + cp->type = NCLISTFALLTHRU; else - checkkwd = CHKNL | CHKKWD, readtoken(); + synexpect(TENDCASE); + checkkwd = CHKNL | CHKKWD, readtoken(); } cpp = &cp->nclist.next; } @@ -931,8 +934,11 @@ xxreadtoken(void) pungetc(); RETURN(TPIPE); case ';': - if (pgetc() == ';') + c = pgetc(); + if (c == ';') RETURN(TENDCASE); + else if (c == '&') + RETURN(TFALLTHRU); pungetc(); RETURN(TSEMI); case '(': diff --git a/bin/sh/sh.1 b/bin/sh/sh.1 index 67ffcc6..82a71e9 100644 --- a/bin/sh/sh.1 +++ b/bin/sh/sh.1 @@ -32,7 +32,7 @@ .\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95 .\" $FreeBSD$ .\" -.Dd June 15, 2011 +.Dd June 17, 2011 .Dt SH 1 .Os .Sh NAME @@ -372,7 +372,7 @@ The following is a list of valid operators: .It Control operators: .Bl -column "XXX" "XXX" "XXX" "XXX" "XXX" -offset center -compact .It Li & Ta Li && Ta Li ( Ta Li ) Ta Li \en -.It Li ;; Ta Li ; Ta Li | Ta Li || +.It Li ;; Ta Li ;& Ta Li ; Ta Li | Ta Li || .El .It Redirection operators: .Bl -column "XXX" "XXX" "XXX" "XXX" "XXX" -offset center -compact @@ -990,6 +990,11 @@ described later), separated by .Ql \&| characters. +If the selected list is terminated by the control operator +.Ql ;& +instead of +.Ql ;; , +execution continues with the next list. The exit code of the .Ic case command is the exit code of the last command executed in the list or |