/[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.4 - (show annotations) (download) (as text)
Wed Dec 15 02:32:58 1999 UTC (19 years, 8 months ago) by guppy
Branch: MAIN
Changes since 1.3: +49 -36 lines
File MIME type: text/x-chdr
id-header patch, finally, we have id tags for each file

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23