chiark / gitweb /
Monoalphabetic match filter.
[anag] / wildcard.c
CommitLineData
6e403221 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
43typedef 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
62static 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
146static 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
154node *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 -------------------------------------------------*/