chiark / gitweb /
infra: Clean up project setup
[anag] / wildcard.c
1 /* -*-c-*-
2  *
3  * $Id: wildcard.c,v 1.2 2004/04/08 01:36:19 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 /*----- Header files ------------------------------------------------------*/
30
31 #include "anag.h"
32
33 /*----- Data structures ---------------------------------------------------*/
34
35 typedef struct node_wild {
36   node n;
37   const char *p;
38 } node_wild;
39
40 /*----- Main code ---------------------------------------------------------*/
41
42 /* --- @match@ --- *
43  *
44  * Arguments:   @const char *p@ = pointer to pattern string
45  *              @const char *s@ = string to compare with
46  *
47  * Returns:     Nonzero if the pattern matches the string.
48  *
49  * Use:         Does simple wildcard matching.  This is quite nasty and more
50  *              than a little slow.  Supports metacharacters `*', `?' and
51  *              '['.
52  */
53
54 static int match(const char *p, const char *s)
55 {
56   for (;;) {
57     char pch = *p++, pche, sch;
58     int sense;
59
60     switch (pch) {
61       case '?':
62         if (!*s)
63           return (0);
64         s++;
65         break;
66       case '*':
67         if (!*p)
68           return (1);
69         while (*s) {
70           if (match(p, s))
71             return (1);
72           s++;
73         }
74         return (0);
75       case '[':
76         if (!*s)
77           return (0);
78         sch = *s++;
79         pch = *p++;
80         sense = 1;
81         if (pch == '^' || pch == '!') {
82           sense = !sense;
83           pch = *p++;
84         }
85         if (pch == ']') {
86           if (*p == '-' && p[1] && p[1] != ']') {
87             pche = p[1];
88             p += 2;
89             if (pch <= sch && sch <= pche)
90               goto class_match;
91           } else if (pch == sch)
92             goto class_match;
93           pch = *p++;
94         }
95         for (;; pch = *p++) {
96           if (!pch || pch == ']')
97             goto class_nomatch;
98           if (*p == '-' && p[1] && p[1] != ']') {
99             pche = p[1];
100             p += 2;
101             if (pch <= sch && sch <= pche)
102               goto class_match;
103           } else if (pch == sch)
104             goto class_match;
105         }
106       class_match:
107         if (!sense)
108           return (0);
109         for (;;) {
110           pch = *p++;
111           if (!pch)
112             return (0);
113           if (pch == ']')
114             break;
115           if (*p == '-' && p[1] && p[1] != ']')
116             p += 2;
117         }
118         break;
119       class_nomatch:
120         if (sense)
121           return (0);
122         break;
123       case '\\':
124         pch = *p++;
125       default:
126         if (pch != *s)
127           return (0);
128         if (!pch)
129           return (1);
130         s++;
131         break;
132     }
133   }
134 }
135
136 /* --- Node matcher --- */
137
138 static int n_wild(node *nn, const char *p, size_t sz)
139 {
140   node_wild *n = (node_wild *)nn;
141   return (match(n->p, p));
142 }
143
144 /* --- Node creation --- */
145
146 node *wildcard(const char *const *av)
147 {
148   node_wild *n = xmalloc(sizeof(*n));
149   n->n.func = n_wild;
150   n->p = av[0];
151   return (&n->n);
152 }
153
154 /*----- That's all, folks -------------------------------------------------*/