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