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:
parent
af957f2ed6
commit
afb78f5d14
4 changed files with 124 additions and 15 deletions
|
@ -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
|
||||
|
|
|
@ -761,8 +761,6 @@ gettok(void)
|
|||
lexstop = 0;
|
||||
return BAR;
|
||||
case LX1_INPAR:
|
||||
if (incasepat == 2)
|
||||
return INPAR;
|
||||
d = hgetc();
|
||||
if (d == '(') {
|
||||
if (infor) {
|
||||
|
|
95
Src/parse.c
95
Src/parse.c
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue