chiark / gitweb /
anag.h: Mark `die' as non-returning and accepting a `printf' format.
[anag] / wildcard.c
1 /* -*-c-*-
2  *
3  * Matches wildcard patterns
4  *
5  * (c) 2001 Mark Wooding
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of Anag: a simple wordgame helper.
11  *
12  * Anag is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * Anag is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with Anag; if not, write to the Free Software Foundation,
24  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  */
26
27 /*----- Header files ------------------------------------------------------*/
28
29 #include "anag.h"
30
31 /*----- Data structures ---------------------------------------------------*/
32
33 typedef struct node_wild {
34   node n;
35   const char *p;
36 } node_wild;
37
38 /*----- Main code ---------------------------------------------------------*/
39
40 /* --- @match@ --- *
41  *
42  * Arguments:   @const char *p@ = pointer to pattern string
43  *              @const char *s@ = string to compare with
44  *
45  * Returns:     Nonzero if the pattern matches the string.
46  *
47  * Use:         Does simple wildcard matching.  This is quite nasty and more
48  *              than a little slow.  Supports metacharacters `*', `?' and
49  *              '['.
50  */
51
52 static int match(const char *p, const char *s)
53 {
54   for (;;) {
55     char pch = *p++, pche, sch;
56     int sense;
57
58     switch (pch) {
59       case '?':
60         if (!*s)
61           return (0);
62         s++;
63         break;
64       case '*':
65         if (!*p)
66           return (1);
67         while (*s) {
68           if (match(p, s))
69             return (1);
70           s++;
71         }
72         return (0);
73       case '[':
74         if (!*s)
75           return (0);
76         sch = *s++;
77         pch = *p++;
78         sense = 1;
79         if (pch == '^' || pch == '!') {
80           sense = !sense;
81           pch = *p++;
82         }
83         if (pch == ']') {
84           if (*p == '-' && p[1] && p[1] != ']') {
85             pche = p[1];
86             p += 2;
87             if (pch <= sch && sch <= pche)
88               goto class_match;
89           } else if (pch == sch)
90             goto class_match;
91           pch = *p++;
92         }
93         for (;; pch = *p++) {
94           if (!pch || pch == ']')
95             goto class_nomatch;
96           if (*p == '-' && p[1] && p[1] != ']') {
97             pche = p[1];
98             p += 2;
99             if (pch <= sch && sch <= pche)
100               goto class_match;
101           } else if (pch == sch)
102             goto class_match;
103         }
104       class_match:
105         if (!sense)
106           return (0);
107         for (;;) {
108           pch = *p++;
109           if (!pch)
110             return (0);
111           if (pch == ']')
112             break;
113           if (*p == '-' && p[1] && p[1] != ']')
114             p += 2;
115         }
116         break;
117       class_nomatch:
118         if (sense)
119           return (0);
120         break;
121       case '\\':
122         pch = *p++;
123       default:
124         if (pch != *s)
125           return (0);
126         if (!pch)
127           return (1);
128         s++;
129         break;
130     }
131   }
132 }
133
134 /* --- Node matcher --- */
135
136 static int n_wild(node *nn, const char *p, size_t sz)
137 {
138   node_wild *n = (node_wild *)nn;
139   return (match(n->p, p));
140 }
141
142 /* --- Node creation --- */
143
144 node *wildcard(const char *const *av)
145 {
146   node_wild *n = xmalloc(sizeof(*n));
147   n->n.func = n_wild;
148   n->p = av[0];
149   return (&n->n);
150 }
151
152 /*----- That's all, folks -------------------------------------------------*/