*.c: General spring-clean of the coding style.
[anag] / wildcard.c
index d28720a..82f33f0 100644 (file)
@@ -1,13 +1,11 @@
 /* -*-c-*-
  *
- * $Id: wildcard.c,v 1.1 2001/02/04 17:14:42 mdw Exp $
- *
  * Matches wildcard patterns
  *
  * (c) 2001 Mark Wooding
  */
 
-/*----- Licensing notice --------------------------------------------------* 
+/*----- Licensing notice --------------------------------------------------*
  *
  * This file is part of Anag: a simple wordgame helper.
  *
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * Anag is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with Anag; if not, write to the Free Software Foundation,
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-/*----- Revision history --------------------------------------------------* 
- *
- * $Log: wildcard.c,v $
- * Revision 1.1  2001/02/04 17:14:42  mdw
- * Initial checkin
- *
- */
-
 /*----- Header files ------------------------------------------------------*/
 
 #include "anag.h"
@@ -61,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;
     }
   }