~mdw
/
anag
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
*.c: General spring-clean of the coding style.
[anag]
/
wildcard.c
diff --git
a/wildcard.c
b/wildcard.c
index
78b3168
..
82f33f0
100644
(file)
--- a/
wildcard.c
+++ b/
wildcard.c
@@
-51,81
+51,96
@@
typedef struct node_wild {
static int match(const char *p, const char *s)
{
static int match(const char *p, const char *s)
{
- for (;;) {
- char pch = *p++, pche, sch;
- int sense;
+ char pch, pche, sch;
+ int sense;
+ for (;;) {
+ pch = *p++;
switch (pch) {
switch (pch) {
+
case '?':
case '?':
- if (!*s)
- return (0);
- s++;
+ /* If there's no character left, then we fail; otherwise consume
+ * anything and move on.
+ */
+
+ if (!*s++) return (0);
break;
break;
+
case '*':
case '*':
- if (!*p)
- return (1);
- while (*s) {
- if (match(p, s))
- return (1);
+ /* If there's no more pattern then we win. */
+ if (!*p) return (1);
+
+ /* Try skipping any number of characters from the pattern looking for
+ * a match.
+ */
+ do {
+ if (match(p, s)) return (1);
s++;
s++;
- }
+ }
while (*s);
return (0);
return (0);
+
case '[':
case '[':
- if (!*s)
- return (0);
+ /* Character sets. This is the hard part. */
+
+ /* If there is no character left, then we fail. */
+ if (!*s) return (0);
+
+ /* Fetch the string character, and start munching through the
+ * pattern.
+ */
sch = *s++;
sch = *s++;
- pch = *p++;
- sense = 1;
- if (pch == '^' || pch == '!') {
- sense = !sense;
- pch = *p++;
- }
+ pch = *p++;
sense = 1;
+
+ /* Maybe we need to negate. */
+ if (pch == '^' || pch == '!') { sense = !sense; pch = *p++; }
+
+ /* A close bracket here is literal. Watch for ranges. */
if (pch == ']') {
if (*p == '-' && p[1] && p[1] != ']') {
if (pch == ']') {
if (*p == '-' && p[1] && p[1] != ']') {
- pche = p[1];
- p += 2;
- if (pch <= sch && sch <= pche)
- goto class_match;
- } else if (pch == sch)
- goto class_match;
+ pche = p[1]; p += 2;
+ if (pch <= sch && sch <= pche) goto class_match;
+ } else if (pch == sch) goto class_match;
pch = *p++;
}
pch = *p++;
}
+
+ /* Work through the other characters and ranges in the set. */
for (;; pch = *p++) {
for (;; pch = *p++) {
- if (!pch || pch == ']')
- goto class_nomatch;
+ if (!pch || pch == ']') goto class_nomatch;
if (*p == '-' && p[1] && p[1] != ']') {
if (*p == '-' && p[1] && p[1] != ']') {
- pche = p[1];
- p += 2;
- if (pch <= sch && sch <= pche)
- goto class_match;
- } else if (pch == sch)
- goto class_match;
+ pche = p[1]; p += 2;
+ if (pch <= sch && sch <= pche) goto class_match;
+ } else if (pch == sch) goto class_match;
}
}
+
class_match:
class_match:
- if (!sense)
-
return (0);
+ /* Found a match. Chew through the rest of the pattern. */
+
if (!sense)
return (0);
for (;;) {
for (;;) {
- pch = *p++;
- if (!pch)
- return (0);
- if (pch == ']')
- break;
- if (*p == '-' && p[1] && p[1] != ']')
- p += 2;
+ pch = *p++; if (!pch) return (0);
+ if (pch == ']') break;
+ if (*p == '-' && p[1] && p[1] != ']') p += 2;
}
break;
}
break;
+
class_nomatch:
class_nomatch:
- if (sense)
-
return (0);
+ /* Found the end of the set, so it's a mismatch. */
+
if (sense)
return (0);
break;
break;
+
case '\\':
case '\\':
+ /* Treat the next thing literally. */
pch = *p++;
pch = *p++;
+ /* fall through... */
+
default:
default:
- if (pch != *s)
- return (0);
- if (!pch)
- return (1);
- s++;
+ /* A plain character match.
+ *
+ * Trick: If this is the end of the pattern, we expect the end of
+ * the string.
+ */
+
+ if (pch != *s++) return (0);
+ if (!pch) return (1);
break;
}
}
break;
}
}