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

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

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


Revision 1.1 - (hide 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 segfault 1.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