/[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.1 - (show annotations) (download) (as text)
Wed Jun 23 19:51:29 1999 UTC (20 years, 3 months ago) by segfault
Branch: MAIN
Branch point for: eggdev
File MIME type: text/x-chdr
Initial revision

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23