1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-09-03 10:21:46 +02:00

35248: treat fully parenthised zsh patterns as complete case patterns again

This commit is contained in:
Peter Stephenson 2015-05-21 10:25:07 +01:00
parent af957f2ed6
commit afb78f5d14
4 changed files with 124 additions and 15 deletions

View file

@ -1,3 +1,9 @@
2015-05-21 Peter Stephenson <p.stephenson@samsung.com>
* 35248: Src/lex.c, Src/parse.c, Test/A01grammar.ztst:
treat fully parenthesised zsh patterns as complete
case patterns again.
2015-05-20 Peter Stephenson <p.stephenson@samsung.com>
* Ismail: 35232: Completion/Unix/Type/_urls: matching

View file

@ -761,8 +761,6 @@ gettok(void)
lexstop = 0;
return BAR;
case LX1_INPAR:
if (incasepat == 2)
return INPAR;
d = hgetc();
if (d == '(') {
if (infor) {

View file

@ -1152,7 +1152,7 @@ par_case(int *cmplx)
YYERRORV(oecused);
}
brflag = (tok == INBRACE);
incasepat = 2;
incasepat = 1;
incmdpos = 0;
noaliases = ona;
nocorrect = onc;
@ -1165,10 +1165,8 @@ par_case(int *cmplx)
zshlex();
if (tok == OUTBRACE)
break;
if (tok == INPAR) {
incasepat = 1;
if (tok == INPAR)
zshlex();
}
if (tok != STRING)
YYERRORV(oecused);
if (!strcmp(tokstr, "esac"))
@ -1178,19 +1176,96 @@ par_case(int *cmplx)
pp = ecadd(0);
palts = ecadd(0);
nalts = 0;
/*
* Hack here.
*
* [Pause for astonished hubbub to subside.]
*
* The next token we get may be
* - ")" or "|" if we're looking at an honest-to-god
* "case" patten, either because there's no opening
* parenthesis, or because SH_GLOB is set and we
* managed to grab an initial "(" to mark the start
* of the case pattern.
* - Something else --- we don't care what --- because
* we're parsing a complete "(...)" as a complete
* zsh pattern. In that case, we treat this as a
* single instance of a case pattern but we pretend
* we're doing proper case parsing --- in which the
* parentheses and bar are in different words from
* the string, so may be separated by whitespace.
* So we quietly massage the whitespace and hope
* no one noticed. This is horrible, but it's
* unfortunately too difficult to comine traditional
* zsh patterns with a properly parsed case pattern
* without generating incompatibilities which aren't
* all that popular (I've discovered).
* - We can also end up with something other than ")" or "|"
* just because we're looking at garbage.
*
* Because of the second case, what happens next might
* be the start of the command after the pattern, so we
* need to treat it as in command position. Luckily
* this doesn't affect our ability to match a | or ) as
* these are valid on command lines.
*/
incasepat = 0;
incmdpos = 1;
for (;;) {
ecstr(str);
ecadd(ecnpats++);
nalts++;
zshlex();
if (tok == OUTPAR) {
ecstr(str);
ecadd(ecnpats++);
nalts++;
incasepat = 0;
incmdpos = 1;
zshlex();
break;
} else if (tok != BAR)
} else if (tok == BAR) {
ecstr(str);
ecadd(ecnpats++);
nalts++;
incasepat = 1;
incmdpos = 0;
} else {
if (!nalts && str[0] == Inpar) {
int pct = 0, sl;
char *s;
for (s = str; *s; s++) {
if (*s == Inpar)
pct++;
if (!pct)
break;
if (pct == 1) {
if (*s == Bar || *s == Inpar)
while (iblank(s[1]))
chuck(s+1);
if (*s == Bar || *s == Outpar)
while (iblank(s[-1]) &&
(s < str + 1 || s[-2] != Meta))
chuck(--s);
}
if (*s == Outpar)
pct--;
}
if (*s || pct || s == str)
YYERRORV(oecused);
/* Simplify pattern by removing surrounding (...) */
sl = strlen(str);
DPUTS(*str != Inpar || str[sl - 1] != Outpar,
"BUG: strange case pattern");
str[sl - 1] = '\0';
chuck(str);
ecstr(str);
ecadd(ecnpats++);
nalts++;
break;
}
YYERRORV(oecused);
}
zshlex();
if (tok != STRING)
@ -1208,7 +1283,7 @@ par_case(int *cmplx)
break;
if (tok != DSEMI && tok != SEMIAMP && tok != SEMIBAR)
YYERRORV(oecused);
incasepat = 2;
incasepat = 1;
incmdpos = 0;
zshlex();
}

View file

@ -614,7 +614,8 @@
>mytrue
>END
fn() {
(emulate sh -c '
fn() {
case $1 in
( one | two | three )
print Matched $1
@ -627,6 +628,7 @@
;;
esac
}
'
which fn
fn one
fn two
@ -635,8 +637,8 @@
fn five
fn six
fn abecedinarian
fn xylophone
0: case word handling
fn xylophone)
0: case word handling in sh emulation (SH_GLOB parentheses)
>fn () {
> case $1 in
> (one | two | three) print Matched $1 ;;
@ -665,3 +667,31 @@
0: case patterns within words
>1 OK
>2 OK
case horrible in
([a-m])(|[n-z])rr(|ib(um|le|ah)))
print It worked
;;
esac
case "a string with separate words" in
(*with separate*))
print That worked, too
;;
esac
0:Unbalanced parentheses and spaces with zsh pattern
>It worked
>That worked, too
case horrible in
(([a-m])(|[n-z])rr(|ib(um|le|ah)))
print It worked
;;
esac
case "a string with separate words" in
(*with separate*)
print That worked, too
;;
esac
0:Balanced parentheses and spaces with zsh pattern
>It worked
>That worked, too