Backport from xs.

This commit is contained in:
default 2023-09-21 11:37:51 +02:00
parent 8698b3f59e
commit 8775424f13
2 changed files with 59 additions and 37 deletions

View file

@ -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 *b_str;
const char *b_spec = NULL;
const char *o_str = str; 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; return 1;
str++; else
} while (*str); break;
}
else
if (p == '?') {
/* match anything except the end */
if (c == '\0')
return 0; return 0;
} }
else
if (p == '*') {
/* end of spec? match */
if (*spec == '\0')
return 1;
if (*spec == '?' && *str) { /* store spec for later */
spec++; /* any character */ b_spec = spec;
str++;
goto again; /* 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 == '|') /* try to find an alternative mark */
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;

View file

@ -1 +1 @@
/* 06767a70773865042a70680aef50f7ecb077681a */ /* 263e97c8ac21ff8524e3c890fe4310c696d01056 */