New front-end in Tcl/Tk. Easier to maintain than the Java interface.
[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 -------------------------------------------------*/