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.
This commit is contained in:
parent
ce97208218
commit
c9afaa6389
@ -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);
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ TPIPE 0 "|"
|
||||
TLP 0 "("
|
||||
TRP 1 ")"
|
||||
TENDCASE 1 ";;"
|
||||
TFALLTHRU 1 ";&"
|
||||
TREDIR 0 redirection
|
||||
TWORD 0 word
|
||||
TIF 0 "if"
|
||||
|
@ -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.
|
||||
|
@ -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 '(':
|
||||
|
@ -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
|
||||
|
39
tools/regression/bin/sh/builtins/case9.0
Normal file
39
tools/regression/bin/sh/builtins/case9.0
Normal file
@ -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))
|
Loading…
Reference in New Issue
Block a user