Author: jilles
Date: Fri Jun 17 13:03:49 2011
New Revision: 223186
URL: http://svn.freebsd.org/changeset/base/223186

Log:
  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.

Added:
  head/tools/regression/bin/sh/builtins/case9.0   (contents, props changed)
Modified:
  head/bin/sh/eval.c
  head/bin/sh/mktokens
  head/bin/sh/nodetypes
  head/bin/sh/parser.c
  head/bin/sh/sh.1

Modified: head/bin/sh/eval.c
==============================================================================
--- head/bin/sh/eval.c  Fri Jun 17 12:12:52 2011        (r223185)
+++ head/bin/sh/eval.c  Fri Jun 17 13:03:49 2011        (r223186)
@@ -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);
                                }

Modified: head/bin/sh/mktokens
==============================================================================
--- head/bin/sh/mktokens        Fri Jun 17 12:12:52 2011        (r223185)
+++ head/bin/sh/mktokens        Fri Jun 17 13:03:49 2011        (r223186)
@@ -50,6 +50,7 @@ TPIPE 0       "|"
 TLP    0       "("
 TRP    1       ")"
 TENDCASE 1     ";;"
+TFALLTHRU 1    ";&"
 TREDIR 0       redirection
 TWORD  0       word
 TIF    0       "if"

Modified: head/bin/sh/nodetypes
==============================================================================
--- head/bin/sh/nodetypes       Fri Jun 17 12:12:52 2011        (r223185)
+++ head/bin/sh/nodetypes       Fri Jun 17 13:03:49 2011        (r223186)
@@ -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.

Modified: head/bin/sh/parser.c
==============================================================================
--- head/bin/sh/parser.c        Fri Jun 17 12:12:52 2011        (r223185)
+++ head/bin/sh/parser.c        Fri Jun 17 13:03:49 2011        (r223186)
@@ -542,10 +542,13 @@ TRACE(("expecting DO got %s %s\n", tokna
 
                        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 '(':

Modified: head/bin/sh/sh.1
==============================================================================
--- head/bin/sh/sh.1    Fri Jun 17 12:12:52 2011        (r223185)
+++ head/bin/sh/sh.1    Fri Jun 17 13:03:49 2011        (r223186)
@@ -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 operato
 .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

Added: head/tools/regression/bin/sh/builtins/case9.0
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/tools/regression/bin/sh/builtins/case9.0       Fri Jun 17 13:03:49 
2011        (r223186)
@@ -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))
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to