sh: Make patmatch() non-recursive.
This commit is contained in:
parent
8f8d30274a
commit
820491f824
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=229201
@ -1445,57 +1445,63 @@ int
|
|||||||
patmatch(const char *pattern, const char *string, int squoted)
|
patmatch(const char *pattern, const char *string, int squoted)
|
||||||
{
|
{
|
||||||
const char *p, *q, *end;
|
const char *p, *q, *end;
|
||||||
|
const char *bt_p, *bt_q;
|
||||||
char c;
|
char c;
|
||||||
wchar_t wc, wc2;
|
wchar_t wc, wc2;
|
||||||
|
|
||||||
p = pattern;
|
p = pattern;
|
||||||
q = string;
|
q = string;
|
||||||
|
bt_p = NULL;
|
||||||
|
bt_q = NULL;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
switch (c = *p++) {
|
switch (c = *p++) {
|
||||||
case '\0':
|
case '\0':
|
||||||
goto breakloop;
|
if (*q != '\0')
|
||||||
|
goto backtrack;
|
||||||
|
return 1;
|
||||||
case CTLESC:
|
case CTLESC:
|
||||||
if (squoted && *q == CTLESC)
|
if (squoted && *q == CTLESC)
|
||||||
q++;
|
q++;
|
||||||
if (*q++ != *p++)
|
if (*q++ != *p++)
|
||||||
return 0;
|
goto backtrack;
|
||||||
break;
|
break;
|
||||||
case CTLQUOTEMARK:
|
case CTLQUOTEMARK:
|
||||||
continue;
|
continue;
|
||||||
case '?':
|
case '?':
|
||||||
if (squoted && *q == CTLESC)
|
if (squoted && *q == CTLESC)
|
||||||
q++;
|
q++;
|
||||||
if (localeisutf8)
|
if (*q == '\0')
|
||||||
wc = get_wc(&q);
|
|
||||||
else
|
|
||||||
wc = (unsigned char)*q++;
|
|
||||||
if (wc == '\0')
|
|
||||||
return 0;
|
return 0;
|
||||||
|
if (localeisutf8) {
|
||||||
|
wc = get_wc(&q);
|
||||||
|
/*
|
||||||
|
* A '?' does not match invalid UTF-8 but a
|
||||||
|
* '*' does, so backtrack.
|
||||||
|
*/
|
||||||
|
if (wc == 0)
|
||||||
|
goto backtrack;
|
||||||
|
} else
|
||||||
|
wc = (unsigned char)*q++;
|
||||||
break;
|
break;
|
||||||
case '*':
|
case '*':
|
||||||
c = *p;
|
c = *p;
|
||||||
while (c == CTLQUOTEMARK || c == '*')
|
while (c == CTLQUOTEMARK || c == '*')
|
||||||
c = *++p;
|
c = *++p;
|
||||||
if (c != CTLESC && c != CTLQUOTEMARK &&
|
/*
|
||||||
c != '?' && c != '*' && c != '[') {
|
* If the pattern ends here, we know the string
|
||||||
while (*q != c) {
|
* matches without needing to look at the rest of it.
|
||||||
if (squoted && *q == CTLESC &&
|
*/
|
||||||
q[1] == c)
|
if (c == '\0')
|
||||||
break;
|
return 1;
|
||||||
if (*q == '\0')
|
/*
|
||||||
return 0;
|
* First try the shortest match for the '*' that
|
||||||
if (squoted && *q == CTLESC)
|
* could work. We can forget any earlier '*' since
|
||||||
q++;
|
* there is no way having it match more characters
|
||||||
q++;
|
* can help us, given that we are already here.
|
||||||
}
|
*/
|
||||||
}
|
bt_p = p;
|
||||||
do {
|
bt_q = q;
|
||||||
if (patmatch(p, q, squoted))
|
break;
|
||||||
return 1;
|
|
||||||
if (squoted && *q == CTLESC)
|
|
||||||
q++;
|
|
||||||
} while (*q++ != '\0');
|
|
||||||
return 0;
|
|
||||||
case '[': {
|
case '[': {
|
||||||
const char *endp;
|
const char *endp;
|
||||||
int invert, found;
|
int invert, found;
|
||||||
@ -1507,7 +1513,7 @@ patmatch(const char *pattern, const char *string, int squoted)
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
while (*endp == CTLQUOTEMARK)
|
while (*endp == CTLQUOTEMARK)
|
||||||
endp++;
|
endp++;
|
||||||
if (*endp == '\0')
|
if (*endp == 0)
|
||||||
goto dft; /* no matching ] */
|
goto dft; /* no matching ] */
|
||||||
if (*endp == CTLESC)
|
if (*endp == CTLESC)
|
||||||
endp++;
|
endp++;
|
||||||
@ -1522,12 +1528,14 @@ patmatch(const char *pattern, const char *string, int squoted)
|
|||||||
found = 0;
|
found = 0;
|
||||||
if (squoted && *q == CTLESC)
|
if (squoted && *q == CTLESC)
|
||||||
q++;
|
q++;
|
||||||
if (localeisutf8)
|
if (*q == '\0')
|
||||||
chr = get_wc(&q);
|
|
||||||
else
|
|
||||||
chr = (unsigned char)*q++;
|
|
||||||
if (chr == '\0')
|
|
||||||
return 0;
|
return 0;
|
||||||
|
if (localeisutf8) {
|
||||||
|
chr = get_wc(&q);
|
||||||
|
if (chr == 0)
|
||||||
|
goto backtrack;
|
||||||
|
} else
|
||||||
|
chr = (unsigned char)*q++;
|
||||||
c = *p++;
|
c = *p++;
|
||||||
do {
|
do {
|
||||||
if (c == CTLQUOTEMARK)
|
if (c == CTLQUOTEMARK)
|
||||||
@ -1568,21 +1576,34 @@ patmatch(const char *pattern, const char *string, int squoted)
|
|||||||
}
|
}
|
||||||
} while ((c = *p++) != ']');
|
} while ((c = *p++) != ']');
|
||||||
if (found == invert)
|
if (found == invert)
|
||||||
return 0;
|
goto backtrack;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dft: default:
|
dft: default:
|
||||||
if (squoted && *q == CTLESC)
|
if (squoted && *q == CTLESC)
|
||||||
q++;
|
q++;
|
||||||
if (*q++ != c)
|
if (*q == '\0')
|
||||||
return 0;
|
return 0;
|
||||||
|
if (*q++ == c)
|
||||||
|
break;
|
||||||
|
backtrack:
|
||||||
|
/*
|
||||||
|
* If we have a mismatch (other than hitting the end
|
||||||
|
* of the string), go back to the last '*' seen and
|
||||||
|
* have it match one additional character.
|
||||||
|
*/
|
||||||
|
if (bt_p == NULL)
|
||||||
|
return 0;
|
||||||
|
if (squoted && *bt_q == CTLESC)
|
||||||
|
bt_q++;
|
||||||
|
if (*bt_q == '\0')
|
||||||
|
return 0;
|
||||||
|
bt_q++;
|
||||||
|
p = bt_p;
|
||||||
|
q = bt_q;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
breakloop:
|
|
||||||
if (*q != '\0')
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user