*.c: General spring-clean of the coding style.
[anag] / wildcard.c
index 78b3168..82f33f0 100644 (file)
@@ -51,81 +51,96 @@ typedef struct node_wild {
 
 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) {
+
       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;
+
       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++;
-       }
+       } while (*s);
        return (0);
+
       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++;
-       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] != ']') {
-           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++;
        }
+
+       /* Work through the other characters and ranges in the set. */
        for (;; pch = *p++) {
-         if (!pch || pch == ']')
-           goto class_nomatch;
+         if (!pch || pch == ']') goto class_nomatch;
          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:
-       if (!sense)
-         return (0);
+       /* Found a match.  Chew through the rest of the pattern. */
+       if (!sense) return (0);
        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;
+
       class_nomatch:
-       if (sense)
-         return (0);
+       /* Found the end of the set, so it's a mismatch. */
+       if (sense) return (0);
        break;
+
       case '\\':
+       /* Treat the next thing literally. */
        pch = *p++;
+       /* fall through... */
+
       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;
     }
   }