mirror of
https://codeberg.org/grunfink/snac2.git
synced 2024-11-12 21:10:22 +03:00
Backport from xs.
This commit is contained in:
parent
8698b3f59e
commit
8775424f13
94
xs_match.h
94
xs_match.h
@ -17,50 +17,72 @@ int xs_match(const char *str, const char *spec);
|
|||||||
|
|
||||||
int xs_match(const char *str, const char *spec)
|
int xs_match(const char *str, const char *spec)
|
||||||
{
|
{
|
||||||
const char *o_str = str;
|
const char *b_str;
|
||||||
|
const char *b_spec = NULL;
|
||||||
|
const char *o_str = str;
|
||||||
|
|
||||||
again:
|
retry:
|
||||||
if (*spec == '*') {
|
|
||||||
spec++; /* wildcard */
|
|
||||||
|
|
||||||
do {
|
for (;;) {
|
||||||
if (xs_match(str, spec))
|
char c = *str++;
|
||||||
|
char p = *spec++;
|
||||||
|
|
||||||
|
if (c == '\0') {
|
||||||
|
/* end of string; also end of spec? */
|
||||||
|
if (p == '\0' || p == '|')
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (p == '?') {
|
||||||
|
/* match anything except the end */
|
||||||
|
if (c == '\0')
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (p == '*') {
|
||||||
|
/* end of spec? match */
|
||||||
|
if (*spec == '\0')
|
||||||
return 1;
|
return 1;
|
||||||
str++;
|
|
||||||
} while (*str);
|
|
||||||
|
|
||||||
return 0;
|
/* store spec for later */
|
||||||
|
b_spec = spec;
|
||||||
|
|
||||||
|
/* back one char */
|
||||||
|
b_str = --str;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (p == '\\')
|
||||||
|
p = *spec++;
|
||||||
|
|
||||||
|
if (c != p) {
|
||||||
|
/* mismatch; do we have a backtrack? */
|
||||||
|
if (b_spec) {
|
||||||
|
/* continue where we left, one char forward */
|
||||||
|
spec = b_spec;
|
||||||
|
str = ++b_str;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*spec == '?' && *str) {
|
/* try to find an alternative mark */
|
||||||
spec++; /* any character */
|
|
||||||
str++;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*spec == '|')
|
|
||||||
return 1; /* alternative separator? positive match */
|
|
||||||
|
|
||||||
if (!*spec)
|
|
||||||
return 1; /* end of spec? positive match */
|
|
||||||
|
|
||||||
if (*spec == '\\')
|
|
||||||
spec++; /* escaped char */
|
|
||||||
|
|
||||||
if (*spec == *str) {
|
|
||||||
spec++; /* matched 1 char */
|
|
||||||
str++;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* not matched; are there any alternatives? */
|
|
||||||
while (*spec) {
|
while (*spec) {
|
||||||
if (*spec == '|')
|
char p = *spec++;
|
||||||
return xs_match(o_str, spec + 1); /* try next alternative */
|
|
||||||
|
|
||||||
if (*spec == '\\')
|
if (p == '\\')
|
||||||
spec++; /* escaped char */
|
p = *spec++;
|
||||||
spec++;
|
|
||||||
|
if (p == '|') {
|
||||||
|
/* no backtrack spec, restart str from the beginning */
|
||||||
|
b_spec = NULL;
|
||||||
|
str = o_str;
|
||||||
|
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1 +1 @@
|
|||||||
/* 06767a70773865042a70680aef50f7ecb077681a */
|
/* 263e97c8ac21ff8524e3c890fe4310c696d01056 */
|
||||||
|
Loading…
Reference in New Issue
Block a user