Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: Bug in case stmt with '('
- X-seq: zsh-users 311
- From: "Bart Schaefer" <schaefer@xxxxxxxxxxxxxxxxxxxxxxx>
- To: segal@xxxxxxxxxx (Morris M. Siegel), zsh-users@xxxxxxxxxxxxxxx
- Subject: Re: Bug in case stmt with '('
- Date: Thu, 18 Jul 1996 11:27:51 -0700
- In-reply-to: segal@xxxxxxxxxx (Morris M. Siegel) "Bug in case stmt with '('" (Jul 17, 5:01pm)
- References: <9607171701.ZM10684@xxxxxxxxxx>
- Reply-to: schaefer@xxxxxxx
On Jul 17, 5:01pm, Morris M. Siegel wrote:
> Subject: Bug in case stmt with '('
> It seems that when a pattern in a case statement is preceded by the optional
> '(', the parser is in the wrong state when parsing the statement following
> the pattern.
Yup. Here's the problem:
To parse the case pattern, zsh attempts to lex a STRING token. In old
case syntax, this stops before either the next "|" or the ")". With the
fully-parenthesized syntax, it lexes the entire (...) expression.
Zsh then reads another token, and looks to see whether it's a "|" (in
which case it loops) or a ")" (in which case the parse is finished).
With the new syntax, neither of these is true, which means zsh has
lexed the next word (in this case, "gigo=...") instead of the OUTPAR.
Problem is, it needs to lex that word with incmdpos=1 to get an
ENVSTRING token, but instead it's lexing with incmdpos=0,incasepat=1
and getting a STRING token.
In the old syntax, where the token was OUTPAR, zsh sets incmdpos=1 and
then lexes again, getting ENVSTRING as it should. When zsh notices that
the token is not OUTPAR, it attempts to fix the situation by skipping
that lex; but the damage has already been done. Zsh needs to look for
the matched parens sooner.
There's one additional complication: zsh glob syntax uses parens, so zsh
has previously accepted this sort of thing:
case $foo in
(v|w)|x) echo 'case (v|w)|x';;
(y|z)) echo 'case (y|z)';;
*) echo 'default';;
esac
That means it can't look only for matching parens, but also has to look
for matching parens followed by a closing paren or vertical bar.
I'm unsure of this patch, so the pre3 stuff is still there #ifdef OLD.
There may be a better way to deal with it.
*** Src/parse.c.orig Mon Jul 15 00:07:21 1996
--- Src/parse.c Thu Jul 18 11:12:14 1996
***************
*** 502,508 ****
--- 502,527 ----
break;
}
str = tokstr;
+ #ifdef OLD
yylex();
+ #else
+ /* POSIX allows (foo*) patterns */
+ if (skipparens(Inpar, Outpar, &str) || *str) {
+ /* Not fully parenthesized, look for a token */
+ str = tokstr;
+ yylex();
+ } else {
+ /* Fully parenthesized, but zsh glob syntax permits
+ * parens in (x|y) patterns, so check for that too. */
+ int c;
+ str = tokstr;
+ c = hgetc();
+ if (c == /*(*/ ')' || c == '|') {
+ hungetc(c);
+ yylex();
+ }
+ }
+ #endif
while (tok == BAR) {
char *str2;
int sl = strlen(str);
***************
*** 527,532 ****
--- 546,552 ----
}
incasepat = 0;
incmdpos = 1;
+ #ifdef OLD
if (tok != OUTPAR) {
/* POSIX allows (foo*) patterns */
char *s = str;
***************
*** 534,539 ****
--- 554,560 ----
if (skipparens(Inpar, Outpar, &s) || *s)
YYERRORV;
} else
+ #endif
yylex();
addlinknode(pats, str);
addlinknode(lists, par_list());
***************
Messages sorted by:
Reverse Date,
Date,
Thread,
Author