Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: Case statement with ";|" [not implemented]
- X-seq: zsh-workers 23115
- From: Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxx
- Subject: Re: Case statement with ";|" [not implemented]
- Date: Fri, 19 Jan 2007 21:31:46 +0000
- Cc: "Gerald Lai" <laigera@xxxxxxxxx>
- In-reply-to: <200701191201.l0JC1KkO003663@xxxxxxxxxxxxxx>
- Mailing-list: contact zsh-workers-help@xxxxxxxxxx; run by ezmlm
- References: <e5d50bd20701181153j4ac7faeajd0ec871ea02af518@xxxxxxxxxxxxxx> <070118205243.ZM30783@xxxxxxxxxxxxxxxxxxxxxx> <200701191201.l0JC1KkO003663@xxxxxxxxxxxxxx>
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