mirror of
https://codeberg.org/grunfink/snac2.git
synced 2024-11-14 17:45:04 +00:00
Backport from xs.
This commit is contained in:
parent
8698b3f59e
commit
8775424f13
2 changed files with 59 additions and 37 deletions
88
xs_match.h
88
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)
|
||||
{
|
||||
const char *b_str;
|
||||
const char *b_spec = NULL;
|
||||
const char *o_str = str;
|
||||
|
||||
again:
|
||||
if (*spec == '*') {
|
||||
spec++; /* wildcard */
|
||||
retry:
|
||||
|
||||
do {
|
||||
if (xs_match(str, spec))
|
||||
for (;;) {
|
||||
char c = *str++;
|
||||
char p = *spec++;
|
||||
|
||||
if (c == '\0') {
|
||||
/* end of string; also end of spec? */
|
||||
if (p == '\0' || p == '|')
|
||||
return 1;
|
||||
str++;
|
||||
} while (*str);
|
||||
|
||||
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;
|
||||
|
||||
if (*spec == '?' && *str) {
|
||||
spec++; /* any character */
|
||||
str++;
|
||||
goto again;
|
||||
/* 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 == '|')
|
||||
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? */
|
||||
/* try to find an alternative mark */
|
||||
while (*spec) {
|
||||
if (*spec == '|')
|
||||
return xs_match(o_str, spec + 1); /* try next alternative */
|
||||
char p = *spec++;
|
||||
|
||||
if (*spec == '\\')
|
||||
spec++; /* escaped char */
|
||||
spec++;
|
||||
if (p == '\\')
|
||||
p = *spec++;
|
||||
|
||||
if (p == '|') {
|
||||
/* no backtrack spec, restart str from the beginning */
|
||||
b_spec = NULL;
|
||||
str = o_str;
|
||||
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1 +1 @@
|
|||
/* 06767a70773865042a70680aef50f7ecb077681a */
|
||||
/* 263e97c8ac21ff8524e3c890fe4310c696d01056 */
|
||||
|
|
Loading…
Reference in a new issue