/[cvs]/eggdrop1.4/src/match.c
ViewVC logotype

Contents of /eggdrop1.4/src/match.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.5 - (show annotations) (download) (as text)
Wed Dec 22 20:30:03 1999 UTC (19 years, 8 months ago) by guppy
Branch: MAIN
CVS Tags: eggdrop104030RC2, eggdrop10403RC1, eggdrop10402RC1, eggdrop10404, eggdrop10403, eggdrop10402, HEAD
Changes since 1.4: +12 -10 lines
File MIME type: text/x-chdr
patches .. and more patches

1 /*
2 * match.c
3 * wildcard matching functions
4 * (rename to reg.c for ircII)
5 *
6 * $Id: match.c,v 1.4 1999/12/15 02:32:58 guppy Exp $
7 */
8 /*
9 * Once this code was working, I added support for % so that I could
10 * use the same code both in Eggdrop and in my IrcII client.
11 * Pleased with this, I added the option of a fourth wildcard, ~,
12 * which matches varying amounts of whitespace (at LEAST one space,
13 * though, for sanity reasons).
14 *
15 * This code would not have been possible without the prior work and
16 * suggestions of various sourced. Special thanks to Robey for
17 * all his time/help tracking down bugs and his ever-helpful advice.
18 *
19 * 04/09: Fixed the "*\*" against "*a" bug (caused an endless loop)
20 *
21 * Chris Fuller (aka Fred1@IRC & Fwitz@IRC)
22 * crf@cfox.bchs.uh.edu
23 *
24 * I hereby release this code into the public domain
25 *
26 */
27
28 /*
29 * This will get us around most of the mess and replace the chunk that
30 * was removed from the middle of this file. --+ Dagmar
31 */
32 /*
33 * You'll also want to grab the rfc1459.c file or change all rfc_*()
34 * calls to the standard library call to make this work with ircII
35 * derivatives now.
36 */
37
38 #ifdef HAVE_CONFIG_H
39 # include <config.h>
40 #endif
41
42 /* Remove the next line to use this in IrcII */
43 #define EGGDROP
44
45 /*
46 * Best to leave stuff after this point alone, but go on and change
47 * it if you're adventurous...
48 */
49
50 /* The quoting character -- what overrides wildcards (do not undef) */
51 #define QUOTE '\\'
52
53 /* The "matches ANYTHING" wildcard (do not undef) */
54 #define WILDS '*'
55
56 /* The "matches ANY NUMBER OF NON-SPACE CHARS" wildcard (do not undef) */
57 #define WILDP '%'
58
59 /* The "matches EXACTLY ONE CHARACTER" wildcard (do not undef) */
60 #define WILDQ '?'
61
62 /* The "matches AT LEAST ONE SPACE" wildcard (undef me to disable!) */
63 #define WILDT '~'
64
65 /*
66 * This makes sure WILDT doesn't get used in in the IrcII version of
67 * this code. If ya wanna live dangerously, you can remove these 3
68 * lines, but WARNING: IT WOULD MAKE THIS CODE INCOMPATIBLE WITH THE
69 * CURRENT reg.c OF IrcII!!! Support for ~ is NOT in the reg.c of
70 * IrcII, and adding it may cause compatibility problems, especially
71 * in scripts. If you don't think you have to worry about that, go
72 * for it!
73 */
74 #ifndef EGGDROP
75 #undef WILDT
76 #endif
77
78 /*
79 * If you edit below this line and it stops working, don't even THINK
80 * about whining to *ME* about it!
81 */
82
83 /*
84 * No problem, you got it wrong anyway, Chris. You should have gone to
85 * uppercase instead of lowercase. (A really minor mistake)
86 */
87
88 /* Changing these is probably counter-productive :) */
89 #define MATCH (match+saved+sofar)
90 #define NOMATCH 0
91
92 /*
93 * EGGDROP: wild_match_per(char *m, char *n)
94 * IrcII: wild_match(char *m, char *n)
95 *
96 * Features: Forward, case-insensitive, ?, *, %, ~(optional)
97 * Best use: Generic string matching, such as in IrcII-esque bindings
98 */
99 #ifdef EGGDROP
100 static int wild_match_per(register unsigned char *m, register unsigned char *n)
101 #else
102 int wild_match(register unsigned char *m, register unsigned char *n)
103 #endif
104 {
105 unsigned char *ma = m, *lsm = 0, *lsn = 0, *lpm = 0, *lpn = 0;
106 int match = 1, saved = 0;
107 register unsigned int sofar = 0;
108
109 #ifdef WILDT
110 int space;
111 #endif
112
113 /* take care of null strings (should never match) */
114 if ((m == 0) || (n == 0) || (!*n))
115 return NOMATCH;
116 /* (!*m) test used to be here, too, but I got rid of it. After all,
117 * If (!*n) was false, there must be a character in the name (the
118 * second string), so if the mask is empty it is a non-match. Since
119 * the algorithm handles this correctly without testing for it here
120 * and this shouldn't be called with null masks anyway, it should be
121 * a bit faster this way */
122
123 while (*n) {
124 /* Used to test for (!*m) here, but this scheme seems to work better */
125 #ifdef WILDT
126 if (*m == WILDT) { /* Match >=1 space */
127 space = 0; /* Don't need any spaces */
128 do {
129 m++;
130 space++;
131 } /* Tally 1 more space ... */
132 while ((*m == WILDT) || (*m == ' ')); /* for each space or ~ */
133 sofar += space; /* Each counts as exact */
134 while (*n == ' ') {
135 n++;
136 space--;
137 } /* Do we have enough? */
138 if (space <= 0)
139 continue; /* Had enough spaces! */
140 }
141 /* Do the fallback */
142 else {
143 #endif
144 switch (*m) {
145 case 0:
146 do
147 m--; /* Search backwards */
148 while ((m > ma) && (*m == '?')); /* For first non-? char */
149 if ((m > ma) ? ((*m == '*') && (m[-1] != QUOTE)) : (*m == '*'))
150 return MATCH; /* nonquoted * = match */
151 break;
152 case WILDP:
153 while (*(++m) == WILDP); /* Zap redundant %s */
154 if (*m != WILDS) { /* Don't both if next=* */
155 if (*n != ' ') { /* WILDS can't match ' ' */
156 lpm = m;
157 lpn = n; /* Save '%' fallback spot */
158 saved += sofar;
159 sofar = 0; /* And save tally count */
160 }
161 continue; /* Done with '%' */
162 }
163 /* FALL THROUGH */
164 case WILDS:
165 do
166 m++; /* Zap redundant wilds */
167 while ((*m == WILDS) || (*m == WILDP));
168 lsm = m;
169 lsn = n;
170 lpm = 0; /* Save '*' fallback spot */
171 match += (saved + sofar); /* Save tally count */
172 saved = sofar = 0;
173 continue; /* Done with '*' */
174 case WILDQ:
175 m++;
176 n++;
177 continue; /* Match one char */
178 case QUOTE:
179 m++; /* Handle quoting */
180 }
181 if (rfc_toupper(*m) == rfc_toupper(*n)) { /* If matching */
182 m++;
183 n++;
184 sofar++;
185 continue; /* Tally the match */
186 }
187 #ifdef WILDT
188 }
189 #endif
190 if (lpm) { /* Try to fallback on '%' */
191 n = ++lpn;
192 m = lpm;
193 sofar = 0; /* Restore position */
194 if ((*n | 32) == 32)
195 lpm = 0; /* Can't match 0 or ' ' */
196 continue; /* Next char, please */
197 }
198 if (lsm) { /* Try to fallback on '*' */
199 n = ++lsn;
200 m = lsm; /* Restore position */
201 /* Used to test for (!*n) here but it wasn't necessary so it's gone */
202 saved = sofar = 0;
203 continue; /* Next char, please */
204 }
205 return NOMATCH; /* No fallbacks=No match */
206 }
207 while ((*m == WILDS) || (*m == WILDP))
208 m++; /* Zap leftover %s & *s */
209 return (*m) ? NOMATCH : MATCH; /* End of both = match */
210 }
211
212 #ifndef EGGDROP
213
214 /* For IrcII compatibility */
215
216 int _wild_match(ma, na)
217 register unsigned char *ma, *na;
218 {
219 return wild_match(ma, na) - 1; /* Don't think IrcII's code
220 * actually uses this directly,
221 * but just in case */
222 }
223
224 int match(ma, na)
225 register unsigned char *ma, *na;
226 {
227 return wild_match(ma, na) ? 1 : 0; /* Returns 1 for match,
228 * 0 for non-match */
229 }
230
231 #else
232
233 /*
234 * Remaining code is not used by IrcII
235 */
236
237 /*
238 * For this matcher, sofar's high bit is used as a flag of whether or
239 * not we are quoting. The other matchers don't need this because
240 * when you're going forward, you just skip over the quote char.
241 */
242 #define UNQUOTED (0x7FFF)
243 #define QUOTED (0x8000)
244
245 #undef MATCH
246 #define MATCH ((match+sofar)&UNQUOTED)
247
248 /*
249 * EGGDROP: wild_match(char *ma, char *na)
250 * IrcII: NOT USED
251 *
252 * Features: Backwards, case-insensitive, ?, *
253 * Best use: Matching of hostmasks (since they are likely to begin
254 * with a * rather than end with one).
255 */
256 int _wild_match(register unsigned char *m, register unsigned char *n)
257 {
258 unsigned char *ma = m, *na = n, *lsm = 0, *lsn = 0;
259 int match = 1;
260 register int sofar = 0;
261
262 /* take care of null strings (should never match) */
263 if ((ma == 0) || (na == 0) || (!*ma) || (!*na))
264 return NOMATCH;
265 /* find the end of each string */
266 while (*(++m));
267 m--;
268 while (*(++n));
269 n--;
270
271 while (n >= na) {
272 if ((m <= ma) || (m[-1] != QUOTE)) { /* Only look if no quote */
273 switch (*m) {
274 case WILDS: /* Matches anything */
275 do
276 m--; /* Zap redundant wilds */
277 while ((m >= ma) && ((*m == WILDS) || (*m == WILDP)));
278 if ((m >= ma) && (*m == '\\'))
279 m++; /* Keep quoted wildcard! */
280 lsm = m;
281 lsn = n;
282 match += sofar;
283 sofar = 0; /* Update fallback pos */
284 continue; /* Next char, please */
285 case WILDQ:
286 m--;
287 n--;
288 continue; /* '?' always matches */
289 }
290 sofar &= UNQUOTED; /* Remember not quoted */
291 } else
292 sofar |= QUOTED; /* Remember quoted */
293 if (rfc_toupper(*m) == rfc_toupper(*n)) { /* If matching char */
294 m--;
295 n--;
296 sofar++; /* Tally the match */
297 if (sofar & QUOTED)
298 m--; /* Skip the quote char */
299 continue; /* Next char, please */
300 }
301 if (lsm) { /* To to fallback on '*' */
302 n = --lsn;
303 m = lsm;
304 if (n < na)
305 lsm = 0; /* Rewind to saved pos */
306 sofar = 0;
307 continue; /* Next char, please */
308 }
309 return NOMATCH; /* No fallback=No match */
310 }
311 while ((m >= ma) && ((*m == WILDS) || (*m == WILDP)))
312 m--; /* Zap leftover %s & *s */
313 return (m >= ma) ? NOMATCH : MATCH; /* Start of both = match */
314 }
315
316 /*
317 * For this matcher, no "saved" is used to track "%" and no special quoting
318 * ability is needed, so we just have (match+sofar) as the result.
319 */
320
321 #endif

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23