return 0;
}
+
+struct max_n {
+ const char *predot;
+ const char *postdot;
+};
+
/*
- the original, recursive function. Needs replacing, but with exactly
- the same output
+ the test function
*/
-static int fnmatch_test2(const char *p, size_t ofs, const char *n, char **max_n)
+static int fnmatch_core(const char *p, const char *n, struct max_n *max_n, const char *ldot)
{
char c;
int i;
- while ((c = p[ofs++])) {
+ while ((c = *p++)) {
switch (c) {
case '*':
- if (max_n[ofs] && max_n[ofs] <= n) {
- return null_match(p+ofs);
+ if (max_n->predot && max_n->predot <= n) {
+ return null_match(p);
}
for (i=0; n[i]; i++) {
- if (fnmatch_test2(p, ofs, n+i, max_n) == 0) {
+ if (fnmatch_core(p, n+i, max_n+1, ldot) == 0) {
return 0;
}
}
- if (!max_n[ofs] || max_n[ofs] > n) max_n[ofs] = n;
- return null_match(p+ofs);
+ if (!max_n->predot || max_n->predot > n) max_n->predot = n;
+ return null_match(p);
case '<':
- if (max_n[ofs] && max_n[ofs] <= n) {
- return null_match(p+ofs);
+ if (max_n->predot && max_n->predot <= n) {
+ return null_match(p);
+ }
+ if (max_n->postdot && max_n->postdot <= n && n < ldot) {
+ return -1;
}
for (i=0; n[i]; i++) {
- if (fnmatch_test2(p, ofs, n+i, max_n) == 0) return 0;
- if (n[i] == '.' && !strchr(n+i+1,'.')) {
- return fnmatch_test2(p, ofs, n+i+1, max_n);
+ if (fnmatch_core(p, n+i, max_n+1, ldot) == 0) return 0;
+ if (n+i == ldot) {
+ if (fnmatch_core(p, n+i+1, max_n+1, ldot) == 0) return 0;
+ if (!max_n->postdot || max_n->postdot > n) max_n->postdot = n;
+ return -1;
}
}
- if (!max_n[ofs] || max_n[ofs] > n) max_n[ofs] = n;
- return null_match(p+ofs);
+ if (!max_n->predot || max_n->predot > n) max_n->predot = n;
+ return null_match(p);
case '?':
if (! *n) {
case '>':
if (n[0] == '.') {
- if (! n[1] && null_match(p+ofs) == 0) {
+ if (! n[1] && null_match(p) == 0) {
return 0;
}
break;
}
- if (! *n) return null_match(p+ofs);
+ if (! *n) return null_match(p);
n++;
break;
case '"':
- if (*n == 0 &&
- null_match(p+ofs) == 0) {
+ if (*n == 0 && null_match(p) == 0) {
return 0;
}
if (*n != '.') return -1;
break;
default:
- if (c != *n &&
- toupper(c) !=
- toupper(*n)) {
+ if (c != *n && toupper(c) != toupper(*n)) {
return -1;
}
n++;
*/
static int fnmatch_test(const char *p, const char *n)
{
- int ret;
- char **max_n;
+ int ret, count, i;
+ struct max_n *max_n = NULL;
- max_n = calloc(sizeof(char *), strlen(p)+1);
+ for (count=i=0;p[i];i++) {
+ if (p[i] == '*' || p[i] == '<') count++;
+ }
- ret = fnmatch_test2(p, 0, n, max_n);
+ if (count) {
+ max_n = calloc(sizeof(struct max_n), count);
+ }
- free(max_n);
+ ret = fnmatch_core(p, n, max_n, strrchr(n, '.'));
+
+ if (max_n) {
+ free(max_n);
+ }
return ret;
}
static void sig_alrm(int sig)
{
- printf("Too slow!!\np='%s'\ns='%s'\n", p_used, n_used);
+ printf("\nToo slow!!\np='%s'\ns='%s'\n", p_used, n_used);
exit(0);
}
if (t2 > w2) w2 = t2;
if (ret1 != ret2) {
- printf("mismatch: ret1=%d ret2=%d pattern='%s' string='%s'\n",
+ printf("\nmismatch: ret1=%d ret2=%d pattern='%s' string='%s'\n",
ret1, ret2, p, n);
free(p);
free(n);