From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7896 invoked from network); 19 Jan 2007 21:32:15 -0000 X-Spam-Checker-Version: SpamAssassin 3.1.7 (2006-10-05) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=AWL,BAYES_00, FORGED_RCVD_HELO autolearn=ham version=3.1.7 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by ns1.primenet.com.au with SMTP; 19 Jan 2007 21:32:15 -0000 Received-SPF: none (ns1.primenet.com.au: domain at sunsite.dk does not designate permitted sender hosts) Received: (qmail 28695 invoked from network); 19 Jan 2007 21:32:09 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 19 Jan 2007 21:32:09 -0000 Received: (qmail 10192 invoked by alias); 19 Jan 2007 21:32:05 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 23115 Received: (qmail 10182 invoked from network); 19 Jan 2007 21:32:04 -0000 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by sunsite.dk with SMTP; 19 Jan 2007 21:32:04 -0000 Received: (qmail 28388 invoked from network); 19 Jan 2007 21:32:04 -0000 Received: from mtaout01-winn.ispmail.ntl.com (81.103.221.47) by a.mx.sunsite.dk with SMTP; 19 Jan 2007 21:31:57 -0000 Received: from aamtaout04-winn.ispmail.ntl.com ([81.103.221.35]) by mtaout01-winn.ispmail.ntl.com with ESMTP id <20070119213154.PWTI9447.mtaout01-winn.ispmail.ntl.com@aamtaout04-winn.ispmail.ntl.com>; Fri, 19 Jan 2007 21:31:54 +0000 Received: from pwslaptop.csr.com ([81.107.42.214]) by aamtaout04-winn.ispmail.ntl.com with SMTP id <20070119213154.JNVD29112.aamtaout04-winn.ispmail.ntl.com@pwslaptop.csr.com>; Fri, 19 Jan 2007 21:31:54 +0000 Date: Fri, 19 Jan 2007 21:31:46 +0000 From: Peter Stephenson To: zsh-workers@sunsite.dk Cc: "Gerald Lai" Subject: Re: Case statement with ";|" [not implemented] Message-Id: <20070119213146.0a1bc54e.p.w.stephenson@ntlworld.com> In-Reply-To: <200701191201.l0JC1KkO003663@news01.csr.com> References: <070118205243.ZM30783@torch.brasslantern.com> <200701191201.l0JC1KkO003663@news01.csr.com> X-Mailer: Sylpheed version 2.2.10 (GTK+ 2.10.4; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Fri, 19 Jan 2007 12:01:20 +0000 Peter Stephenson 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 Web page now at http://homepage.ntlworld.com/p.w.stephenson/