From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22147 invoked from network); 1 Apr 1997 00:25:25 -0000 Received: from euclid.skiles.gatech.edu (list@130.207.146.50) by coral.primenet.com.au with SMTP; 1 Apr 1997 00:25:25 -0000 Received: (from list@localhost) by euclid.skiles.gatech.edu (8.7.3/8.7.3) id TAA11255; Mon, 31 Mar 1997 19:09:55 -0500 (EST) Resent-Date: Mon, 31 Mar 1997 19:09:55 -0500 (EST) Date: Tue, 1 Apr 1997 01:12:48 +0100 (BST) From: Zefram Message-Id: <17975.199704010012@stone.dcs.warwick.ac.uk> Subject: case fall-through X-Patch: 248 Resent-Message-ID: <"KK9Zu.0.ll2.J95Gp"@euclid> To: zsh-workers@math.gatech.edu Resent-From: zsh-workers@math.gatech.edu X-Mailing-List: archive/latest/3062 X-Loop: zsh-workers@math.gatech.edu Precedence: list Resent-Sender: zsh-workers-request@math.gatech.edu -----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-----