Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Case statement with ";|" [not implemented]



On Fri, 19 Jan 2007 12:01:20 +0000
Peter Stephenson <pws@xxxxxxx> wrote:
> I think we simply have to apply the restriction that the word in the
> case statement is expanded only once at the start of the case statement.
> I don't see that's either unnatural or confusing.  With this it looks
> like it ought to be quite straightforward, possible even trivial, to
> implement.

So it turns out.  Hope the documentation is unambiguous.

I've kept the feature when decoding code that ";;" appears with a space
before it but the others, now ";&" and ";|", don't.  I don't understand
why it's that way, however, and it might be a typo.

Index: Doc/Zsh/grammar.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/grammar.yo,v
retrieving revision 1.11
diff -u -r1.11 grammar.yo
--- Doc/Zsh/grammar.yo	19 Sep 2005 15:19:21 -0000	1.11
+++ Doc/Zsh/grammar.yo	19 Jan 2007 21:24:06 -0000
@@ -199,14 +199,23 @@
 findex(case)
 cindex(case selection)
 cindex(selection, case)
-item(tt(case) var(word) tt(in) [ [tt(LPAR())] var(pattern) [ tt(|) var(pattern) ] ... tt(RPAR()) var(list) (tt(;;)|tt(;&)) ] ... tt(esac))(
+item(tt(case) var(word) tt(in) [ [tt(LPAR())] var(pattern) [ tt(|) var(pattern) ] ... tt(RPAR()) var(list) (tt(;;)|tt(;&)|tt(;|)) ] ... tt(esac))(
 Execute the var(list) associated with the first var(pattern)
 that matches var(word), if any.  The form of the patterns
 is the same as that used for filename generation.  See
 noderef(Filename Generation).
+
 If the var(list) that is executed is terminated with tt(;&) rather than
-tt(;;), the following list is also executed.  This continues until either
-a list is terminated with tt(;;) or the tt(esac) is reached.
+tt(;;), the following list is also executed.  The rule for
+the terminator of the following list tt(;;), tt(;&) or tt(;|) is
+applied unless the tt(esac) is reached.
+
+If the var(list) that is executed is terminated with tt(;|) the
+shell continues to scan the var(pattern)s looking for the next match,
+executing the corresponding var(list), and applying the rule for
+the corresponding terminator tt(;;), tt(;&) or tt(;|).
+Note that var(word) is not re-expanded; all applicable var(pattern)s
+are tested with the same var(word).
 )
 findex(select)
 cindex(user selection)
@@ -390,7 +399,7 @@
 item(tt(repeat) var(word) var(sublist))(
 This is a short form of tt(repeat).
 )
-item(tt(case) var(word) tt({) [ [tt(LPAR())] var(pattern) [ tt(|) var(pattern) ] ... tt(RPAR()) var(list) (tt(;;)|tt(;&)) ] ... tt(}))(
+item(tt(case) var(word) tt({) [ [tt(LPAR())] var(pattern) [ tt(|) var(pattern) ] ... tt(RPAR()) var(list) (tt(;;)|tt(;&)|tt(;|)) ] ... tt(}))(
 An alternative form of tt(case).
 )
 item(tt(select) var(name) [ tt(in) var(word) var(term) ] var(sublist))(
Index: Src/lex.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/lex.c,v
retrieving revision 1.36
diff -u -r1.36 lex.c
--- Src/lex.c	8 Jan 2007 22:05:55 -0000	1.36
+++ Src/lex.c	19 Jan 2007 21:24:08 -0000
@@ -155,6 +155,7 @@
     "))",	/* DOUTPAR	     */
     "&|",	/* AMPERBANG	  30 */
     ";&",	/* SEMIAMP	     */
+    ";|",	/* SEMIBAR	     */
 };
 
 /* lexical state */
@@ -381,6 +382,7 @@
     case SEMI:
     case DSEMI:
     case SEMIAMP:
+    case SEMIBAR:
     case AMPER:
     case AMPERBANG:
     case INPAR:
@@ -713,6 +715,8 @@
 	    return DSEMI;
 	else if(d == '&')
 	    return SEMIAMP;
+	else if (d == '|')
+	    return SEMIBAR;
 	hungetc(d);
 	lexstop = 0;
 	return SEMI;
Index: Src/loop.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/loop.c,v
retrieving revision 1.19
diff -u -r1.19 loop.c
--- Src/loop.c	30 May 2006 22:35:03 -0000	1.19
+++ Src/loop.c	19 Jan 2007 21:24:09 -0000
@@ -606,9 +606,10 @@
 		execlist(state, 1, ((WC_CASE_TYPE(code) == WC_CASE_OR) &&
 				    do_exec));
 	    }
-	    break;
-	} else
-	    state->pc = next;
+	    if (WC_CASE_TYPE(code) != WC_CASE_TESTAND)
+		break;
+	}
+	state->pc = next;
     }
     cmdpop();
 
Index: Src/parse.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/parse.c,v
retrieving revision 1.59
diff -u -r1.59 parse.c
--- Src/parse.c	4 Aug 2006 13:38:27 -0000	1.59
+++ Src/parse.c	19 Jan 2007 21:24:10 -0000
@@ -169,9 +169,9 @@
  *
  *   WC_CASE
  *     - first CASE is always of type HEAD, data contains offset to esac
- *     - after that CASEs of type OR (;;) and AND (;&), data is offset to
- *       next case
- *     - each OR/AND case is followed by pattern, pattern-number, list
+ *     - after that CASEs of type OR (;;), AND (;&) and TESTAND (;|),
+ *       data is offset to next case
+ *     - each OR/AND/TESTAND case is followed by pattern, pattern-number, list
  *
  *   WC_IF
  *     - first IF is of type HEAD, data contains offset to fi
@@ -1014,7 +1014,7 @@
 /*
  * case	: CASE STRING { SEPER } ( "in" | INBRACE )
 				{ { SEPER } STRING { BAR STRING } OUTPAR
-					list [ DSEMI | SEMIAMP ] }
+					list [ DSEMI | SEMIAMP | SEMIBAR ] }
 				{ SEPER } ( "esac" | OUTBRACE )
  */
 
@@ -1141,10 +1141,12 @@
 	n++;
 	if (tok == SEMIAMP)
 	    type = WC_CASE_AND;
+	else if (tok == SEMIBAR)
+	    type = WC_CASE_TESTAND;
 	ecbuf[pp] = WCB_CASE(type, ecused - 1 - pp);
 	if ((tok == ESAC && !brflag) || (tok == OUTBRACE && brflag))
 	    break;
-	if (tok != DSEMI && tok != SEMIAMP)
+	if (tok != DSEMI && tok != SEMIAMP && tok != SEMIBAR)
 	    YYERRORV(oecused);
 	incasepat = 1;
 	incmdpos = 0;
Index: Src/text.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/text.c,v
retrieving revision 1.17
diff -u -r1.17 text.c
--- Src/text.c	5 Oct 2006 21:53:27 -0000	1.17
+++ Src/text.c	19 Jan 2007 21:24:11 -0000
@@ -537,7 +537,19 @@
 		}
 	    } else if (state->pc < s->u._case.end) {
 		tindent--;
-		taddstr(WC_CASE_TYPE(code) == WC_CASE_OR ? " ;;" : ";&");
+		switch (WC_CASE_TYPE(code)) {
+		case WC_CASE_OR:
+		    taddstr(" ;;");
+		    break;
+
+		case WC_CASE_AND:
+		    taddstr(";&");
+		    break;
+
+		default:
+		    taddstr(";|");
+		    break;
+		}
 		if (tnewlins)
 		    taddnl();
 		else
@@ -553,7 +565,19 @@
 			  s->u._case.end);
 	    } else {
 		tindent--;
-		taddstr(WC_CASE_TYPE(code) == WC_CASE_OR ? " ;;" : ";&");
+		switch (WC_CASE_TYPE(code)) {
+		case WC_CASE_OR:
+		    taddstr(" ;;");
+		    break;
+
+		case WC_CASE_AND:
+		    taddstr(";&");
+		    break;
+
+		default:
+		    taddstr(";|");
+		    break;
+		}
 		tindent--;
 		if (tnewlins)
 		    taddnl();
Index: Src/zsh.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v
retrieving revision 1.108
diff -u -r1.108 zsh.h
--- Src/zsh.h	14 Jan 2007 19:22:46 -0000	1.108
+++ Src/zsh.h	19 Jan 2007 21:24:12 -0000
@@ -246,37 +246,38 @@
     DOUTPAR,
     AMPERBANG,		/* 30 */
     SEMIAMP,
+    SEMIBAR,
     DOUTBRACK,
     STRING,
-    ENVSTRING,
-    ENVARRAY,		/* 35 */
+    ENVSTRING,		/* 35 */
+    ENVARRAY,
     ENDINPUT,
     LEXERR,
 
     /* Tokens for reserved words */
     BANG,	/* !         */
-    DINBRACK,	/* [[        */
-    INBRACE,    /* {         */	/* 40 */
+    DINBRACK,	/* [[        */	/* 40 */
+    INBRACE,    /* {         */
     OUTBRACE,   /* }         */
     CASE,	/* case      */
     COPROC,	/* coproc    */
-    DOLOOP,	/* do        */
-    DONE,	/* done      */ /* 45 */
+    DOLOOP,	/* do        */ /* 45 */
+    DONE,	/* done      */
     ELIF,	/* elif      */
     ELSE,	/* else      */
     ZEND,	/* end       */
-    ESAC,	/* esac      */
-    FI,		/* fi        */ /* 50 */
+    ESAC,	/* esac      */ /* 50 */
+    FI,		/* fi        */
     FOR,	/* for       */
     FOREACH,	/* foreach   */
     FUNC,	/* function  */
-    IF,		/* if        */
-    NOCORRECT,	/* nocorrect */ /* 55 */
+    IF,		/* if        */ /* 55 */
+    NOCORRECT,	/* nocorrect */
     REPEAT,	/* repeat    */
     SELECT,	/* select    */
     THEN,	/* then      */
-    TIME,	/* time      */
-    UNTIL,	/* until     */ /* 60 */
+    TIME,	/* time      */ /* 60 */
+    UNTIL,	/* until     */
     WHILE	/* while     */
 };
 
@@ -783,12 +784,14 @@
 #define WC_TRY_SKIP(C)	    wc_data(C)
 #define WCB_TRY(O)	    wc_bld(WC_TRY, (O))
 
-#define WC_CASE_TYPE(C)     (wc_data(C) & 3)
+#define WC_CASE_TYPE(C)     (wc_data(C) & 7)
 #define WC_CASE_HEAD        0
 #define WC_CASE_OR          1
 #define WC_CASE_AND         2
-#define WC_CASE_SKIP(C)     (wc_data(C) >> 2)
-#define WCB_CASE(T,O)       wc_bld(WC_CASE, ((T) | ((O) << 2)))
+#define WC_CASE_TESTAND     3
+#define WC_CASE_FREE	    (3) /* Next bit available in integer */
+#define WC_CASE_SKIP(C)     (wc_data(C) >> WC_CASE_FREE)
+#define WCB_CASE(T,O)       wc_bld(WC_CASE, ((T) | ((O) << WC_CASE_FREE)))
 
 #define WC_IF_TYPE(C)       (wc_data(C) & 3)
 #define WC_IF_HEAD          0
Index: Test/A01grammar.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/A01grammar.ztst,v
retrieving revision 1.12
diff -u -r1.12 A01grammar.ztst
--- Test/A01grammar.ztst	11 Apr 2005 10:23:57 -0000	1.12
+++ Test/A01grammar.ztst	19 Jan 2007 21:24:13 -0000
@@ -413,6 +413,29 @@
 0:`case' with braces
 >schmavo
 
+  for word in artichoke bladderwort chrysanthemum Zanzibar
+  case $word in
+    (*der*) print $word contains the forbidden incantation der
+         ;;
+    (a*) print $word begins with a
+         ;&
+    ([[:upper:]]*) print $word either begins with a or an upper case letter
+         ;|
+    ([[:lower:]]*) print $word begins with a lower case letter
+         ;|
+    (*e*) print $word contains an e
+         ;;
+  esac
+0:`case' with mixed ;& and ;|
+>artichoke begins with a
+>artichoke either begins with a or an upper case letter
+>artichoke begins with a lower case letter
+>artichoke contains an e
+>bladderwort contains the forbidden incantation der
+>chrysanthemum begins with a lower case letter
+>chrysanthemum contains an e
+>Zanzibar either begins with a or an upper case letter
+
   print 'This test hangs the shell when it fails...' >&8
   name=0
 # The number 4375 here is chosen to produce more than 16384 bytes of output

-- 
Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/



Messages sorted by: Reverse Date, Date, Thread, Author