summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bin/sh/eval.c8
-rw-r--r--bin/sh/mktokens1
-rw-r--r--bin/sh/nodetypes3
-rw-r--r--bin/sh/parser.c14
-rw-r--r--bin/sh/sh.19
-rw-r--r--tools/regression/bin/sh/builtins/case9.039
6 files changed, 67 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
diff --git a/tools/regression/bin/sh/builtins/case9.0 b/tools/regression/bin/sh/builtins/case9.0
new file mode 100644
index 0000000..476caec
--- /dev/null
+++ b/tools/regression/bin/sh/builtins/case9.0
@@ -0,0 +1,39 @@
+# $FreeBSD$
+
+errors=0
+
+f() {
+ result=
+ case $1 in
+ a) result=${result}a ;;
+ b) result=${result}b ;&
+ c) result=${result}c ;&
+ d) result=${result}d ;;
+ e) result=${result}e ;&
+ esac
+}
+
+check() {
+ f "$1"
+ if [ "$result" != "$2" ]; then
+ printf "For %s, expected %s got %s\n" "$1" "$2" "$result"
+ errors=$((errors + 1))
+ fi
+}
+
+check '' ''
+check a a
+check b bcd
+check c cd
+check d d
+check e e
+
+if ! (case 1 in
+ 1) false ;&
+ 2) true ;;
+esac) then
+ echo "Subshell bad"
+ errors=$((errors + 1))
+fi
+
+exit $((errors != 0))
OpenPOWER on IntegriCloud