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

case fall-through



-----BEGIN PGP SIGNED MESSAGE-----

This patch adds a feature from (IIRC) ksh93.  There is a new token,
`;&', which behaves like `;;' except that it allows execution to fall
through to the next branch of the case.

The gettext code for case commands was actually completely broken
before this patch.  It stopped working between 3.0.2 and 3.0.3-test1
(and between 3.1.0-test3 and 3.1.0).  The 3.0 tree ought to have the
text.c hunks of this patch applied, minus the (fairly obvious) parts
relating to this new feature.

 -zefram

 *** Doc/Zsh/grammar.yo	1997/01/29 03:24:53	1.4
 --- Doc/Zsh/grammar.yo	1997/03/31 20:17:35
 ***************
 *** 146,156 ****
   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(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).
   )
   findex(select)
   cindex(user selection)
 --- 146,159 ----
   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))(
   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.
   )
   findex(select)
   cindex(user selection)
 ***************
 *** 243,249 ****
   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(}))(
   An alternative form of tt(case).
   )
   item(tt(select) var(name) [ tt(in) var(word) var(term) ] var(sublist))(
 --- 246,252 ----
   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(}))(
   An alternative form of tt(case).
   )
   item(tt(select) var(name) [ tt(in) var(word) var(term) ] var(sublist))(
 *** Src/globals.h	1997/03/31 00:52:39	1.43
 --- Src/globals.h	1997/03/31 18:59:05
 ***************
 *** 694,699 ****
 --- 694,700 ----
       "((",	/* DINPAR	     */
       "))",	/* DOUTPAR	     */
       "&|",	/* AMPERBANG	  30 */
 +     ";&",	/* SEMIAMP	     */
   };
   #else
   extern char *tokstrings[];
 *** Src/lex.c	1997/02/04 14:13:05	1.27
 --- Src/lex.c	1997/03/31 19:05:14
 ***************
 *** 215,220 ****
 --- 215,221 ----
       case NEWLIN:
       case SEMI:
       case DSEMI:
 +     case SEMIAMP:
       case AMPER:
       case AMPERBANG:
       case INPAR:
 ***************
 *** 436,447 ****
   	return NEWLIN;
       case LX1_SEMI:
   	d = hgetc();
 ! 	if (d != ';') {
 ! 	    hungetc(d);
 ! 	    lexstop = 0;
 ! 	    return SEMI;
 ! 	}
 ! 	return DSEMI;
       case LX1_AMPER:
   	d = hgetc();
   	if (d == '&')
 --- 437,449 ----
   	return NEWLIN;
       case LX1_SEMI:
   	d = hgetc();
 ! 	if(d == ';')
 ! 	    return DSEMI;
 ! 	else if(d == '&')
 ! 	    return SEMIAMP;
 ! 	hungetc(d);
 ! 	lexstop = 0;
 ! 	return SEMI;
       case LX1_AMPER:
   	d = hgetc();
   	if (d == '&')
 *** Src/loop.c	1997/03/26 09:09:23	1.12
 --- Src/loop.c	1997/03/31 19:55:55
 ***************
 *** 387,400 ****
   
       if (node) {
   	while (*p) {
 ! 	    singsub(p);
 ! 	    if (matchpat(word, *p))
   		break;
   	    p++;
   	    l++;
   	}
 - 	if (*l)
 - 	    execlist(*l, 1, cmd->flags & CFLAG_EXEC);
       }
       return lastval;
   }
 --- 387,403 ----
   
       if (node) {
   	while (*p) {
 ! 	    char *pat = *p + 1;
 ! 	    singsub(&pat);
 ! 	    if (matchpat(word, pat)) {
 ! 		do {
 ! 		    execlist(*l++, 1, **p == ';' && (cmd->flags & CFLAG_EXEC));
 ! 		} while(**p++ == '&' && *p);
   		break;
 + 	    }
   	    p++;
   	    l++;
   	}
       }
       return lastval;
   }
 *** Src/parse.c	1997/01/29 03:25:22	1.18
 --- Src/parse.c	1997/03/31 19:15:33
 ***************
 *** 472,478 ****
   
   /*
    * case	: CASE STRING { SEPER } ( "in" | INBRACE )
 ! 				{ { SEPER } STRING { BAR STRING } OUTPAR list [ DSEMI ] }
   				{ SEPER } ( "esac" | OUTBRACE )
    */
   
 --- 472,479 ----
   
   /*
    * case	: CASE STRING { SEPER } ( "in" | INBRACE )
 ! 				{ { SEPER } STRING { BAR STRING } OUTPAR
 ! 					list [ DSEMI | SEMIAMP ] }
   				{ SEPER } ( "esac" | OUTBRACE )
    */
   
 ***************
 *** 522,528 ****
   	    yylex();
   	    break;
   	}
 ! 	str = tokstr;
   	incasepat = 0;
   	incmdpos = 1;
   	for (;;) {
 --- 523,531 ----
   	    yylex();
   	    break;
   	}
 ! 	str = ncalloc(strlen(tokstr) + 2);
 ! 	*str = ';';
 ! 	strcpy(str + 1, tokstr);
   	incasepat = 0;
   	incmdpos = 1;
   	for (;;) {
 ***************
 *** 549,557 ****
   		if (str[sl - 1] != Bar) {
   		    /* POSIX allows (foo*) patterns */
   		    int pct;
 ! 		    char *s = str;
   
 ! 		    for (s = str, pct = 0; *s; s++) {
   			if (*s == Inpar)
   			    pct++;
   			if (!pct)
 --- 552,560 ----
   		if (str[sl - 1] != Bar) {
   		    /* POSIX allows (foo*) patterns */
   		    int pct;
 ! 		    char *s;
   
 ! 		    for (s = str + 1, pct = 0; *s; s++) {
   			if (*s == Inpar)
   			    pct++;
   			if (!pct)
 ***************
 *** 568,574 ****
   			if (*s == Outpar)
   			    pct--;
   		    }
 ! 		    if (*s || pct || s == str)
   			YYERRORV;
   		    break;
   		} else {
 --- 571,577 ----
   			if (*s == Outpar)
   			    pct--;
   		    }
 ! 		    if (*s || pct || s == str + 1)
   			YYERRORV;
   		    break;
   		} else {
 ***************
 *** 590,596 ****
   	    yylex();
   	    break;
   	}
 ! 	if (tok != DSEMI)
   	    YYERRORV;
   	incasepat = 1;
   	incmdpos = 0;
 --- 593,601 ----
   	    yylex();
   	    break;
   	}
 ! 	if(tok == SEMIAMP)
 ! 	    *str = '&';
 ! 	else if (tok != DSEMI)
   	    YYERRORV;
   	incasepat = 1;
   	incmdpos = 0;
 *** Src/text.c	1997/01/29 03:25:27	1.11
 --- Src/text.c	1997/03/31 20:01:13
 ***************
 *** 264,281 ****
   	    taddstr("fi");
   	    break;
   	case CCASE:
 - 	    taddstr("case ");
 - 	    taddlist(nn->args);
 - 	    taddstr(" in");
 - 	    tindent++;
 - 	    taddnl();
   	    gt2(nn->u.casecmd);
 - 	    tindent--;
 - 	    if (tnewlins)
 - 		taddnl();
 - 	    else
 - 		taddchr(' ');
 - 	    taddstr("esac");
   	    break;
   	case COND:
   	    taddstr("[[ ");
 --- 264,270 ----
 ***************
 *** 316,333 ****
   	    l = _casecmd(n)->lists;
   	    p = _casecmd(n)->pats;
   
   	    for (; *l; p++, l++) {
 - 		taddstr(*p);
 - 		taddstr(") ");
 - 		tindent++;
 - 		gt2(*l);
 - 		tindent--;
 - 		taddstr(";;");
   		if (tnewlins)
   		    taddnl();
   		else
   		    taddchr(' ');
   	    }
   	    break;
   	}
       case N_IF:
 --- 305,333 ----
   	    l = _casecmd(n)->lists;
   	    p = _casecmd(n)->pats;
   
 + 	    taddstr("case ");
 + 	    taddstr(*p++);
 + 	    taddstr(" in");
 + 	    tindent++;
   	    for (; *l; p++, l++) {
   		if (tnewlins)
   		    taddnl();
   		else
   		    taddchr(' ');
 + 		taddstr(*p + 1);
 + 		taddstr(") ");
 + 		tindent++;
 + 		gt2(*l);
 + 		tindent--;
 + 		taddstr(" ;");
 + 		taddchr(**p);
   	    }
 + 	    tindent--;
 + 	    if (tnewlins)
 + 		taddnl();
 + 	    else
 + 		taddchr(' ');
 + 	    taddstr("esac");
   	    break;
   	}
       case N_IF:
 *** Src/zsh.h	1997/03/31 07:51:13	1.56
 --- Src/zsh.h	1997/03/31 19:01:56
 ***************
 *** 116,122 ****
   
   #define SPECCHARS "#$^*()=|{}[]`<>?~;&\n\t \\\'\""
   
 ! enum shopt {
       NULLTOK,		/* 0  */
       SEPER,
       NEWLIN,
 --- 116,122 ----
   
   #define SPECCHARS "#$^*()=|{}[]`<>?~;&\n\t \\\'\""
   
 ! enum {
       NULLTOK,		/* 0  */
       SEPER,
       NEWLIN,
 ***************
 *** 148,185 ****
       DINPAR,
       DOUTPAR,
       AMPERBANG,		/* 30 */
       DOUTBRACK,
       STRING,
       ENVSTRING,
 !     ENVARRAY,
 !     ENDINPUT,		/* 35 */
       LEXERR,
   
       /* Tokens for reserved words */
       BANG,	/* !         */
       DINBRACK,	/* [[        */
 !     INBRACE,    /* {         */
 !     OUTBRACE,   /* }         */	/* 40 */
       CASE,	/* case      */
       COPROC,	/* coproc    */
       DO,		/* do        */
 !     DONE,	/* done      */
 !     ELIF,	/* elif      */ /* 45 */
       ELSE,	/* else      */
       ZEND,	/* end       */
       ESAC,	/* esac      */
 !     FI,		/* fi        */
 !     FOR,	/* for       */ /* 50 */
       FOREACH,	/* foreach   */
       FUNC,	/* function  */
       IF,		/* if        */
 !     NOCORRECT,	/* nocorrect */
 !     REPEAT,	/* repeat    */ /* 55 */
       SELECT,	/* select    */
       THEN,	/* then      */
       TIME,	/* time      */
 !     UNTIL,	/* until     */
 !     WHILE	/* while     */ /* 60 */
   };
   
   /* Redirection types.  If you modify this, you may also have to modify *
 --- 148,186 ----
       DINPAR,
       DOUTPAR,
       AMPERBANG,		/* 30 */
 +     SEMIAMP,
       DOUTBRACK,
       STRING,
       ENVSTRING,
 !     ENVARRAY,		/* 35 */
 !     ENDINPUT,
       LEXERR,
   
       /* Tokens for reserved words */
       BANG,	/* !         */
       DINBRACK,	/* [[        */
 !     INBRACE,    /* {         */	/* 40 */
 !     OUTBRACE,   /* }         */
       CASE,	/* case      */
       COPROC,	/* coproc    */
       DO,		/* do        */
 !     DONE,	/* done      */ /* 45 */
 !     ELIF,	/* elif      */
       ELSE,	/* else      */
       ZEND,	/* end       */
       ESAC,	/* esac      */
 !     FI,		/* fi        */ /* 50 */
 !     FOR,	/* for       */
       FOREACH,	/* foreach   */
       FUNC,	/* function  */
       IF,		/* if        */
 !     NOCORRECT,	/* nocorrect */ /* 55 */
 !     REPEAT,	/* repeat    */
       SELECT,	/* select    */
       THEN,	/* then      */
       TIME,	/* time      */
 !     UNTIL,	/* until     */ /* 60 */
 !     WHILE	/* while     */
   };
   
   /* Redirection types.  If you modify this, you may also have to modify *

-----BEGIN PGP SIGNATURE-----
Version: 2.6.3ia
Charset: ascii

iQCVAwUBM0AeeHD/+HJTpU/hAQFXhAQAivqrVvHuhTndExTzOAqiA6+ghvI6Owkl
kMKRYrQ4UoftuNmSJ1UlUfs6lFUKNMNbxXD9ejm3po0PUVZFRPx+pu83DeWUBD2b
pJcnV6Fd+h+ikhPAmqi2+USK6c1dXMtbMEKeJm0Gvh6PJimV6FLqXFK9iuczNA5H
zxtntojvDiM=
=LsIz
-----END PGP SIGNATURE-----



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