Module Name:    src
Committed By:   kre
Date:           Thu May  4 04:37:51 UTC 2017

Modified Files:
        src/bin/sh: eval.c jobs.c mktokens nodetypes parser.c sh.1

Log Message:
Implement the ';&' (used instead of ';;') case statement list terminator
which causes fall through the to command list of the following pattern
(wuthout evaluating that pattern).   This has been approved for inclusion
in the next major version of the POSIX standard (Issue 8), and is
implemented by most other shells.

Now all form a circle and together attempt to summon the great wizd
in the hopes that his magic spells can transform the poor attempt
at documenting this feature into something rational...


To generate a diff of this commit:
cvs rdiff -u -r1.133 -r1.134 src/bin/sh/eval.c
cvs rdiff -u -r1.81 -r1.82 src/bin/sh/jobs.c
cvs rdiff -u -r1.12 -r1.13 src/bin/sh/mktokens
cvs rdiff -u -r1.13 -r1.14 src/bin/sh/nodetypes
cvs rdiff -u -r1.122 -r1.123 src/bin/sh/parser.c
cvs rdiff -u -r1.134 -r1.135 src/bin/sh/sh.1

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/bin/sh/eval.c
diff -u src/bin/sh/eval.c:1.133 src/bin/sh/eval.c:1.134
--- src/bin/sh/eval.c:1.133	Wed May  3 05:49:54 2017
+++ src/bin/sh/eval.c	Thu May  4 04:37:51 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: eval.c,v 1.133 2017/05/03 05:49:54 kre Exp $	*/
+/*	$NetBSD: eval.c,v 1.134 2017/05/04 04:37:51 kre Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)eval.c	8.9 (Berkeley) 6/8/95";
 #else
-__RCSID("$NetBSD: eval.c,v 1.133 2017/05/03 05:49:54 kre Exp $");
+__RCSID("$NetBSD: eval.c,v 1.134 2017/05/04 04:37:51 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -456,7 +456,7 @@ out:
 STATIC void
 evalcase(union node *n, int flags)
 {
-	union node *cp;
+	union node *cp, *ncp;
 	union node *patp;
 	struct arglist arglist;
 	struct stackmark smark;
@@ -465,18 +465,26 @@ evalcase(union node *n, int flags)
 	setstackmark(&smark);
 	arglist.lastp = &arglist.list;
 	expandarg(n->ncase.expr, &arglist, EXP_TILDE);
-	for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
-		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
+	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)) {
-				if (evalskip == 0) {
-					evaltree(cp->nclist.body, flags);
+				while (cp != NULL && evalskip == 0 &&
+				    nflag == 0) {
+					if (cp->type == NCLISTCONT)
+						ncp = cp->nclist.next;
+					else
+						ncp = NULL;
+					evaltree(cp->nclist.body,
+					    ncp ? (flags & ~EV_EXIT) | EV_MORE
+						: flags );
 					status = exitstatus;
+					cp = ncp;
 				}
 				goto out;
 			}
 		}
 	}
-out:
+ out:
 	exitstatus = status;
 	popstackmark(&smark);
 }

Index: src/bin/sh/jobs.c
diff -u src/bin/sh/jobs.c:1.81 src/bin/sh/jobs.c:1.82
--- src/bin/sh/jobs.c:1.81	Wed May  3 21:31:03 2017
+++ src/bin/sh/jobs.c	Thu May  4 04:37:51 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: jobs.c,v 1.81 2017/05/03 21:31:03 kre Exp $	*/
+/*	$NetBSD: jobs.c,v 1.82 2017/05/04 04:37:51 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)jobs.c	8.5 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: jobs.c,v 1.81 2017/05/03 21:31:03 kre Exp $");
+__RCSID("$NetBSD: jobs.c,v 1.82 2017/05/04 04:37:51 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -1336,7 +1336,14 @@ cmdtxt(union node *n)
 			cmdtxt(np->nclist.pattern);
 			cmdputs(") ");
 			cmdtxt(np->nclist.body);
-			cmdputs(";; ");
+			switch (n->type) {	/* switch (not if) for later */
+			case NCLISTCONT:
+				cmdputs(";& ");
+				break;
+			default:
+				cmdputs(";; ");
+				break;
+			}
 		}
 		cmdputs("esac");
 		break;

Index: src/bin/sh/mktokens
diff -u src/bin/sh/mktokens:1.12 src/bin/sh/mktokens:1.13
--- src/bin/sh/mktokens:1.12	Sat Oct 25 22:18:15 2008
+++ src/bin/sh/mktokens	Thu May  4 04:37:51 2017
@@ -1,5 +1,5 @@
 #!/bin/sh -
-#	$NetBSD: mktokens,v 1.12 2008/10/25 22:18:15 apb Exp $
+#	$NetBSD: mktokens,v 1.13 2017/05/04 04:37:51 kre Exp $
 #
 # Copyright (c) 1991, 1993
 #	The Regents of the University of California.  All rights reserved.
@@ -51,6 +51,7 @@ TPIPE	0	"|"
 TLP	0	"("
 TRP	1	")"
 TENDCASE 1	";;"
+TCASEFALL 1	";&"
 TENDBQUOTE 1	"`"
 TREDIR	0	redirection
 TWORD	0	word

Index: src/bin/sh/nodetypes
diff -u src/bin/sh/nodetypes:1.13 src/bin/sh/nodetypes:1.14
--- src/bin/sh/nodetypes:1.13	Tue May 26 07:30:51 2009
+++ src/bin/sh/nodetypes	Thu May  4 04:37:51 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: nodetypes,v 1.13 2009/05/26 07:30:51 joerg Exp $
+#	$NetBSD: nodetypes,v 1.14 2017/05/04 04:37:51 kre Exp $
 # Copyright (c) 1991, 1993
 #	The Regents of the University of California.  All rights reserved.
 #
@@ -95,6 +95,7 @@ NCASE ncase			# a case statement
 	expr	  nodeptr		# the word to switch on
 	cases	  nodeptr		# the list of cases (NCLIST nodes)
 
+NCLISTCONT nclist		# a case terminated by ';&' (fall through)
 NCLIST nclist			# a case
 	type	  int
 	next	  nodeptr		# the next case in list

Index: src/bin/sh/parser.c
diff -u src/bin/sh/parser.c:1.122 src/bin/sh/parser.c:1.123
--- src/bin/sh/parser.c:1.122	Wed May  3 21:36:16 2017
+++ src/bin/sh/parser.c	Thu May  4 04:37:51 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: parser.c,v 1.122 2017/05/03 21:36:16 kre Exp $	*/
+/*	$NetBSD: parser.c,v 1.123 2017/05/04 04:37:51 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)parser.c	8.7 (Berkeley) 5/16/95";
 #else
-__RCSID("$NetBSD: parser.c,v 1.122 2017/05/03 21:36:16 kre Exp $");
+__RCSID("$NetBSD: parser.c,v 1.123 2017/05/04 04:37:51 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -469,10 +469,12 @@ TRACE(("expecting DO got %s %s\n", tokna
 
 			checkkwd = 2;
 			if ((t = readtoken()) != TESAC) {
-				if (t != TENDCASE) {
+				if (t != TENDCASE && t != TCASEFALL) {
 					noalias = 0;
 					synexpect(TENDCASE, 0);
 				} else {
+					if (t == TCASEFALL)
+						cp->type = NCLISTCONT;
 					noalias = 1;
 					checkkwd = 2;
 					readtoken();
@@ -1021,10 +1023,15 @@ xxreadtoken(void)
 			pungetc();
 			RETURN(TPIPE);
 		case ';':
-			if (pgetc_linecont() == ';')
+			switch (pgetc_linecont()) {
+			case ';':
 				RETURN(TENDCASE);
-			pungetc();
-			RETURN(TSEMI);
+			case '&':
+				RETURN(TCASEFALL);
+			default:
+				pungetc();
+				RETURN(TSEMI);
+			}
 		case '(':
 			RETURN(TLP);
 		case ')':

Index: src/bin/sh/sh.1
diff -u src/bin/sh/sh.1:1.134 src/bin/sh/sh.1:1.135
--- src/bin/sh/sh.1:1.134	Wed May  3 00:43:22 2017
+++ src/bin/sh/sh.1	Thu May  4 04:37:51 2017
@@ -1,4 +1,4 @@
-.\"	$NetBSD: sh.1,v 1.134 2017/05/03 00:43:22 kre Exp $
+.\"	$NetBSD: sh.1,v 1.135 2017/05/04 04:37:51 kre Exp $
 .\" Copyright (c) 1991, 1993
 .\"	The Regents of the University of California.  All rights reserved.
 .\"
@@ -31,7 +31,7 @@
 .\"
 .\"	@(#)sh.1	8.6 (Berkeley) 5/4/95
 .\"
-.Dd April 29, 2017
+.Dd May 4, 2017
 .Dt SH 1
 .ds flags abCEeFfhnuvxIimpqV
 .Os
@@ -807,7 +807,8 @@ These are implemented as built-in comman
 The syntax of the case command is
 .Bd -literal -offset indent
 case word in
-pattern) list ;;
+[(] pattern ) list ;&
+[(] pattern ) list ;;
 \&...
 esac
 .Ed
@@ -817,6 +818,25 @@ The pattern can actually be one or more 
 described later), separated by
 .Dq \*(Ba
 characters.
+.Pp
+Word is expanded and matched against each pattern in turn,
+from first to last,
+with each pattern being expanded just before the match is attempted.
+When a match is found, pattern comparisons cease, and the associated
+.Dq list
+(which may be empty)
+is evaluated.
+If the list is terminated with
+.Dq \&;&
+execution then falls through to the following list, if any,
+without evaluating its pattern, or attempting a match.
+When a list terminated with
+.Dq \&;;
+has been executed, or when
+.Dv esac
+is reached execution of the case statement is complete.
+The exit status is that of the last command executed
+from the last list evaluated, if any, or zero otherwise.
 .Ss Grouping Commands Together
 Commands may be grouped by writing either
 .Pp

Reply via email to