]> jfr.im git - solanum.git/blame - src/match.c
modlist: Fix address display on 64-bit systems.
[solanum.git] / src / match.c
CommitLineData
212380e3
AC
1/************************************************************************
2 * IRC - Internet Relay Chat, src/match.c
3 * Copyright (C) 1990 Jarkko Oikarinen
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 1, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
df251055 19 * $Id: match.c 3532 2007-07-14 13:32:18Z jilles $
212380e3
AC
20 *
21 */
22#include "stdinc.h"
23#include "config.h"
24#include "client.h"
25#include "ircd.h"
4562c604 26#include "match.h"
77d3d2db 27#include "s_assert.h"
212380e3
AC
28
29/*
30 * Compare if a given string (name) matches the given
31 * mask (which can contain wild cards: '*' - match any
32 * number of chars, '?' - match any single character.
33 *
34 * return 1, if match
35 * 0, if no match
36 *
37 * Originally by Douglas A Lewis (dalewis@acsu.buffalo.edu)
38 * Rewritten by Timothy Vogelsang (netski), net@astrolink.org
39 */
40
41/** Check a string against a mask.
42 * This test checks using traditional IRC wildcards only: '*' means
43 * match zero or more characters of any type; '?' means match exactly
44 * one character of any type.
45 *
46 * @param[in] mask Wildcard-containing mask.
47 * @param[in] name String to check against \a mask.
48 * @return Zero if \a mask matches \a name, non-zero if no match.
49 */
50int match(const char *mask, const char *name)
51{
52 const char *m = mask, *n = name;
53 const char *m_tmp = mask, *n_tmp = name;
54 int star_p;
55
56 s_assert(mask != NULL);
57 s_assert(name != NULL);
58
59 for (;;)
60 {
61 switch (*m)
62 {
63 case '\0':
64 if (!*n)
65 return 1;
66 backtrack:
67 if (m_tmp == mask)
68 return 0;
69 m = m_tmp;
70 n = ++n_tmp;
71 break;
72 case '*':
73 case '?':
74 for (star_p = 0;; m++)
75 {
76 if (*m == '*')
77 star_p = 1;
78 else if (*m == '?')
79 {
80 if (!*n++)
81 goto backtrack;
82 }
83 else
84 break;
85 }
86 if (star_p)
87 {
88 if (!*m)
89 return 1;
90 else
91 {
92 m_tmp = m;
93 for (n_tmp = n; *n && ToLower(*n) != ToLower(*m); n++);
94 }
95 }
96 /* and fall through */
97 default:
98 if (!*n)
99 return (*m != '\0' ? 0 : 1);
100 if (ToLower(*m) != ToLower(*n))
101 goto backtrack;
102 m++;
103 n++;
104 break;
105 }
106 }
107}
108
df251055
JT
109/** Check a mask against a mask.
110 * This test checks using traditional IRC wildcards only: '*' means
111 * match zero or more characters of any type; '?' means match exactly
112 * one character of any type.
113 * The difference between mask_match() and match() is that in mask_match()
114 * a '?' in mask does not match a '*' in name.
115 *
116 * @param[in] mask Existing wildcard-containing mask.
117 * @param[in] name New wildcard-containing mask.
118 * @return 1 if \a name is equal to or more specific than \a mask, 0 otherwise.
119 */
120int mask_match(const char *mask, const char *name)
121{
122 const char *m = mask, *n = name;
123 const char *m_tmp = mask, *n_tmp = name;
124 int star_p;
125
126 s_assert(mask != NULL);
127 s_assert(name != NULL);
128
129 for (;;)
130 {
131 switch (*m)
132 {
133 case '\0':
134 if (!*n)
135 return 1;
136 backtrack:
137 if (m_tmp == mask)
138 return 0;
139 m = m_tmp;
140 n = ++n_tmp;
141 break;
142 case '*':
143 case '?':
144 for (star_p = 0;; m++)
145 {
146 if (*m == '*')
147 star_p = 1;
148 else if (*m == '?')
149 {
150 /* changed for mask_match() */
151 if (*n == '*' || !*n)
152 goto backtrack;
153 n++;
154 }
155 else
156 break;
157 }
158 if (star_p)
159 {
160 if (!*m)
161 return 1;
162 else
163 {
164 m_tmp = m;
165 for (n_tmp = n; *n && ToLower(*n) != ToLower(*m); n++);
166 }
167 }
168 /* and fall through */
169 default:
170 if (!*n)
171 return (*m != '\0' ? 0 : 1);
172 if (ToLower(*m) != ToLower(*n))
173 goto backtrack;
174 m++;
175 n++;
176 break;
177 }
178 }
179}
180
181
7eecdd68
JT
182#define MATCH_MAX_CALLS 512 /* ACK! This dies when it's less that this
183 and we have long lines to parse */
212380e3 184/** Check a string against a mask.
7eecdd68
JT
185 * This test checks using extended wildcards: '*' means match zero
186 * or more characters of any type; '?' means match exactly one
187 * character of any type; '#' means match exactly one character that
188 * is a number; '@' means match exactly one character that is a
189 * letter; '\s' means match a space.
212380e3
AC
190 *
191 * This function supports escaping, so that a wildcard may be matched
192 * exactly.
193 *
194 * @param[in] mask Wildcard-containing mask.
195 * @param[in] name String to check against \a mask.
196 * @return Zero if \a mask matches \a name, non-zero if no match.
197 */
7eecdd68
JT
198int
199match_esc(const char *mask, const char *name)
212380e3 200{
7eecdd68
JT
201 const unsigned char *m = (const unsigned char *)mask;
202 const unsigned char *n = (const unsigned char *)name;
203 const unsigned char *ma = (const unsigned char *)mask;
204 const unsigned char *na = (const unsigned char *)name;
205 int wild = 0;
206 int calls = 0;
207 int quote = 0;
208 int match1 = 0;
212380e3
AC
209
210 s_assert(mask != NULL);
211 s_assert(name != NULL);
212
7eecdd68
JT
213 if(!mask || !name)
214 return 0;
215
216 /* if the mask is "*", it matches everything */
217 if((*m == '*') && (*(m + 1) == '\0'))
218 return 1;
219
220 while(calls++ < MATCH_MAX_CALLS)
212380e3 221 {
7eecdd68
JT
222 if(quote)
223 quote++;
224 if(quote == 3)
225 quote = 0;
226 if(*m == '\\' && !quote)
212380e3 227 {
7eecdd68
JT
228 m++;
229 quote = 1;
230 continue;
231 }
232 if(!quote && *m == '*')
233 {
234 /*
235 * XXX - shouldn't need to spin here, the mask should have been
236 * collapsed before match is called
237 */
238 while(*m == '*')
239 m++;
240
241 wild = 1;
242 ma = m;
243 na = n;
244
245 if(*m == '\\')
246 {
247 m++;
248 /* This means it is an invalid mask -A1kmm. */
249 if(!*m)
250 return 0;
251 quote++;
252 continue;
253 }
254 }
255
256 if(!*m)
257 {
258 if(!*n)
259 return 1;
260 if(quote)
261 return 0;
5ef68b13
JT
262 for(m--; (m > (const unsigned char *)mask) && (*m == '?'); m--)
263 ;
7eecdd68
JT
264
265 if(*m == '*' && (m > (const unsigned char *)mask))
266 return 1;
267 if(!wild)
268 return 0;
269 m = ma;
270 n = ++na;
271 }
272 else if(!*n)
273 {
274 /*
275 * XXX - shouldn't need to spin here, the mask should have been
276 * collapsed before match is called
277 */
278 if(quote)
279 return 0;
280 while(*m == '*')
281 m++;
282 return (*m == 0);
283 }
284
285 if(quote)
286 match1 = *m == 's' ? *n == ' ' : ToLower(*m) == ToLower(*n);
287 else if(*m == '?')
288 match1 = 1;
289 else if(*m == '@')
290 match1 = IsLetter(*n);
291 else if(*m == '#')
292 match1 = IsDigit(*n);
293 else
294 match1 = ToLower(*m) == ToLower(*n);
295 if(match1)
296 {
297 if(*m)
298 m++;
299 if(*n)
300 n++;
301 }
302 else
303 {
304 if(!wild)
305 return 0;
306 m = ma;
307 n = ++na;
212380e3
AC
308 }
309 }
7eecdd68 310 return 0;
212380e3
AC
311}
312
313int comp_with_mask(void *addr, void *dest, u_int mask)
314{
315 if (memcmp(addr, dest, mask / 8) == 0)
316 {
317 int n = mask / 8;
318 int m = ((-1) << (8 - (mask % 8)));
319 if (mask % 8 == 0 || (((u_char *) addr)[n] & m) == (((u_char *) dest)[n] & m))
320 {
321 return (1);
322 }
323 }
324 return (0);
325}
326
327int comp_with_mask_sock(struct sockaddr *addr, struct sockaddr *dest, u_int mask)
328{
329 void *iaddr = NULL;
330 void *idest = NULL;
331
332 if (addr->sa_family == AF_INET)
333 {
334 iaddr = &((struct sockaddr_in *)addr)->sin_addr;
335 idest = &((struct sockaddr_in *)dest)->sin_addr;
336 }
ccda6e3f 337#ifdef RB_IPV6
212380e3
AC
338 else
339 {
340 iaddr = &((struct sockaddr_in6 *)addr)->sin6_addr;
341 idest = &((struct sockaddr_in6 *)dest)->sin6_addr;
342
343 }
344#endif
345
346 return (comp_with_mask(iaddr, idest, mask));
347}
348
349/*
350 * match_ips()
351 *
352 * Input - cidr ip mask, address
353 */
354int match_ips(const char *s1, const char *s2)
355{
e7046ee5 356 struct rb_sockaddr_storage ipaddr, maskaddr;
212380e3
AC
357 char mask[BUFSIZE];
358 char address[HOSTLEN + 1];
359 char *len;
360 void *ipptr, *maskptr;
361 int cidrlen, aftype;
362
363 strcpy(mask, s1);
364 strcpy(address, s2);
365
366 len = strrchr(mask, '/');
367 if (len == NULL)
368 return 0;
369
370 *len++ = '\0';
371
372 cidrlen = atoi(len);
441da2f2 373 if (cidrlen <= 0)
212380e3
AC
374 return 0;
375
ccda6e3f 376#ifdef RB_IPV6
212380e3
AC
377 if (strchr(mask, ':') && strchr(address, ':'))
378 {
441da2f2
JT
379 if (cidrlen > 128)
380 return 0;
381
212380e3
AC
382 aftype = AF_INET6;
383 ipptr = &((struct sockaddr_in6 *)&ipaddr)->sin6_addr;
384 maskptr = &((struct sockaddr_in6 *)&maskaddr)->sin6_addr;
385 }
386 else
387#endif
388 if (!strchr(mask, ':') && !strchr(address, ':'))
389 {
441da2f2
JT
390 if (cidrlen > 32)
391 return 0;
392
212380e3
AC
393 aftype = AF_INET;
394 ipptr = &((struct sockaddr_in *)&ipaddr)->sin_addr;
395 maskptr = &((struct sockaddr_in *)&maskaddr)->sin_addr;
396 }
397 else
398 return 0;
399
caa4d9d2
VY
400 rb_inet_pton(aftype, address, ipptr);
401 rb_inet_pton(aftype, mask, maskptr);
212380e3
AC
402 if (comp_with_mask(ipptr, maskptr, cidrlen))
403 return 1;
404 else
405 return 0;
406}
407
408/* match_cidr()
409 *
410 * Input - mask, address
411 * Ouput - 1 = Matched 0 = Did not match
412 */
413
414int match_cidr(const char *s1, const char *s2)
415{
e7046ee5 416 struct rb_sockaddr_storage ipaddr, maskaddr;
212380e3
AC
417 char mask[BUFSIZE];
418 char address[NICKLEN + USERLEN + HOSTLEN + 6];
419 char *ipmask;
420 char *ip;
421 char *len;
422 void *ipptr, *maskptr;
423 int cidrlen, aftype;
424
425 strcpy(mask, s1);
426 strcpy(address, s2);
427
428 ipmask = strrchr(mask, '@');
429 if (ipmask == NULL)
430 return 0;
431
432 *ipmask++ = '\0';
433
434 ip = strrchr(address, '@');
435 if (ip == NULL)
436 return 0;
437 *ip++ = '\0';
438
439
440 len = strrchr(ipmask, '/');
441 if (len == NULL)
442 return 0;
443
444 *len++ = '\0';
445
446 cidrlen = atoi(len);
4dbd5e07 447 if (cidrlen <= 0)
212380e3
AC
448 return 0;
449
ccda6e3f 450#ifdef RB_IPV6
212380e3
AC
451 if (strchr(ip, ':') && strchr(ipmask, ':'))
452 {
4dbd5e07
JT
453 if (cidrlen > 128)
454 return 0;
455
212380e3
AC
456 aftype = AF_INET6;
457 ipptr = &((struct sockaddr_in6 *)&ipaddr)->sin6_addr;
458 maskptr = &((struct sockaddr_in6 *)&maskaddr)->sin6_addr;
459 }
460 else
461#endif
462 if (!strchr(ip, ':') && !strchr(ipmask, ':'))
463 {
4dbd5e07
JT
464 if (cidrlen > 32)
465 return 0;
466
212380e3
AC
467 aftype = AF_INET;
468 ipptr = &((struct sockaddr_in *)&ipaddr)->sin_addr;
469 maskptr = &((struct sockaddr_in *)&maskaddr)->sin_addr;
470 }
471 else
472 return 0;
473
caa4d9d2
VY
474 rb_inet_pton(aftype, ip, ipptr);
475 rb_inet_pton(aftype, ipmask, maskptr);
212380e3
AC
476 if (comp_with_mask(ipptr, maskptr, cidrlen) && match(mask, address))
477 return 1;
478 else
479 return 0;
480}
481
482/* collapse()
483 *
484 * collapses a string containing multiple *'s.
485 */
486char *collapse(char *pattern)
487{
488 char *p = pattern, *po = pattern;
489 char c;
490 int f = 0;
491
492 if (p == NULL)
493 return NULL;
494
495 while ((c = *p++))
496 {
497 if (c == '*')
498 {
499 if (!(f & 1))
500 *po++ = '*';
501 f |= 1;
502 }
503 else
504 {
505 *po++ = c;
506 f &= ~1;
507 }
508 }
509 *po++ = 0;
510
511 return pattern;
512}
513
514/* collapse_esc()
515 *
516 * The collapse() function with support for escaping characters
517 */
518char *collapse_esc(char *pattern)
519{
520 char *p = pattern, *po = pattern;
521 char c;
522 int f = 0;
523
524 if (p == NULL)
525 return NULL;
526
527 while ((c = *p++))
528 {
529 if (!(f & 2) && c == '*')
530 {
531 if (!(f & 1))
532 *po++ = '*';
533 f |= 1;
534 }
535 else if (!(f & 2) && c == '\\')
536 {
537 *po++ = '\\';
538 f |= 2;
539 }
540 else
541 {
542 *po++ = c;
543 f &= ~3;
544 }
545 }
546 *po++ = 0;
547 return pattern;
548}
549
550/*
551 * irccmp - case insensitive comparison of two 0 terminated strings.
552 *
553 * returns 0, if s1 equal to s2
554 * <0, if s1 lexicographically less than s2
555 * >0, if s1 lexicographically greater than s2
556 */
557int irccmp(const char *s1, const char *s2)
558{
559 const unsigned char *str1 = (const unsigned char *)s1;
560 const unsigned char *str2 = (const unsigned char *)s2;
561 int res;
562
563 s_assert(s1 != NULL);
564 s_assert(s2 != NULL);
565
566 while ((res = ToUpper(*str1) - ToUpper(*str2)) == 0)
567 {
568 if (*str1 == '\0')
569 return 0;
570 str1++;
571 str2++;
572 }
573 return (res);
574}
575
576int ircncmp(const char *s1, const char *s2, int n)
577{
578 const unsigned char *str1 = (const unsigned char *)s1;
579 const unsigned char *str2 = (const unsigned char *)s2;
580 int res;
581 s_assert(s1 != NULL);
582 s_assert(s2 != NULL);
583
584 while ((res = ToUpper(*str1) - ToUpper(*str2)) == 0)
585 {
586 str1++;
587 str2++;
588 n--;
589 if (n == 0 || (*str1 == '\0' && *str2 == '\0'))
590 return 0;
591 }
592 return (res);
593}
594
595const unsigned char ToLowerTab[] = {
596 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
597 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
598 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
599 0x1e, 0x1f,
600 ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
601 '*', '+', ',', '-', '.', '/',
602 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
603 ':', ';', '<', '=', '>', '?',
604 '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
605 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
606 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
607 '_',
608 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
609 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
610 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
611 0x7f,
612 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
613 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
614 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
615 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
616 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
617 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
618 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
619 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
620 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
621 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
622 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
623 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
624 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
625 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
626 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
627 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
628};
629
630const unsigned char ToUpperTab[] = {
631 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
632 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
633 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
634 0x1e, 0x1f,
635 ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
636 '*', '+', ',', '-', '.', '/',
637 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
638 ':', ';', '<', '=', '>', '?',
639 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
640 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
641 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
642 0x5f,
643 '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
644 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
645 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
646 0x7f,
647 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
648 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
649 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
650 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
651 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
652 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
653 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
654 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
655 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
656 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
657 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
658 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
659 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
660 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
661 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
662 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
663};
664
665/*
666 * CharAttrs table
667 *
668 * NOTE: RFC 1459 sez: anything but a ^G, comma, or space is allowed
669 * for channel names
670 */
671const unsigned int CharAttrs[] = {
672/* 0 */ CNTRL_C,
673/* 1 */ CNTRL_C | CHAN_C | NONEOS_C,
674/* 2 */ CNTRL_C | CHAN_C | FCHAN_C | NONEOS_C,
675/* 3 */ CNTRL_C | CHAN_C | FCHAN_C | NONEOS_C,
676/* 4 */ CNTRL_C | CHAN_C | NONEOS_C,
677/* 5 */ CNTRL_C | CHAN_C | NONEOS_C,
678/* 6 */ CNTRL_C | CHAN_C | NONEOS_C,
679/* 7 BEL */ CNTRL_C | NONEOS_C,
680/* 8 \b */ CNTRL_C | CHAN_C | NONEOS_C,
681/* 9 \t */ CNTRL_C | SPACE_C | CHAN_C | NONEOS_C,
682/* 10 \n */ CNTRL_C | SPACE_C | CHAN_C | NONEOS_C | EOL_C,
683/* 11 \v */ CNTRL_C | SPACE_C | CHAN_C | NONEOS_C,
684/* 12 \f */ CNTRL_C | SPACE_C | CHAN_C | NONEOS_C,
685/* 13 \r */ CNTRL_C | SPACE_C | CHAN_C | NONEOS_C | EOL_C,
686/* 14 */ CNTRL_C | CHAN_C | NONEOS_C,
687/* 15 */ CNTRL_C | CHAN_C | NONEOS_C,
688/* 16 */ CNTRL_C | CHAN_C | NONEOS_C,
689/* 17 */ CNTRL_C | CHAN_C | NONEOS_C,
690/* 18 */ CNTRL_C | CHAN_C | NONEOS_C,
691/* 19 */ CNTRL_C | CHAN_C | NONEOS_C,
692/* 20 */ CNTRL_C | CHAN_C | NONEOS_C,
693/* 21 */ CNTRL_C | CHAN_C | NONEOS_C,
694/* 22 */ CNTRL_C | CHAN_C | FCHAN_C | NONEOS_C,
695/* 23 */ CNTRL_C | CHAN_C | NONEOS_C,
696/* 24 */ CNTRL_C | CHAN_C | NONEOS_C,
697/* 25 */ CNTRL_C | CHAN_C | NONEOS_C,
698/* 26 */ CNTRL_C | CHAN_C | NONEOS_C,
699/* 27 */ CNTRL_C | CHAN_C | NONEOS_C,
700/* 28 */ CNTRL_C | CHAN_C | NONEOS_C,
b19d3c51 701/* 29 */ CNTRL_C | CHAN_C | FCHAN_C | NONEOS_C,
212380e3
AC
702/* 30 */ CNTRL_C | CHAN_C | NONEOS_C,
703/* 31 */ CNTRL_C | CHAN_C | FCHAN_C | NONEOS_C,
704/* SP */ PRINT_C | SPACE_C,
705/* ! */ PRINT_C | KWILD_C | CHAN_C | NONEOS_C,
706/* " */ PRINT_C | CHAN_C | NONEOS_C,
707/* # */ PRINT_C | MWILD_C | CHANPFX_C | CHAN_C | NONEOS_C,
f2edb2be 708/* $ */ PRINT_C | CHAN_C | NONEOS_C,
212380e3
AC
709/* % */ PRINT_C | CHAN_C | NONEOS_C,
710/* & */ PRINT_C | CHANPFX_C | CHAN_C | NONEOS_C,
711/* ' */ PRINT_C | CHAN_C | NONEOS_C,
712/* ( */ PRINT_C | CHAN_C | NONEOS_C,
713/* ) */ PRINT_C | CHAN_C | NONEOS_C,
e5d9ca18 714/* * */ PRINT_C | KWILD_C | MWILD_C | CHAN_C | NONEOS_C,
212380e3
AC
715/* + */ PRINT_C | CHAN_C | NONEOS_C,
716/* , */ PRINT_C | NONEOS_C,
717/* - */ PRINT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
718/* . */ PRINT_C | KWILD_C | CHAN_C | NONEOS_C | USER_C | HOST_C | SERV_C,
9a180ae3 719/* / */ PRINT_C | CHAN_C | NONEOS_C | HOST_C,
212380e3
AC
720/* 0 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
721/* 1 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
722/* 2 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
723/* 3 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
724/* 4 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
725/* 5 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
726/* 6 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
727/* 7 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
728/* 8 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
729/* 9 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
730/* : */ PRINT_C | CHAN_C | NONEOS_C | HOST_C,
731/* ; */ PRINT_C | CHAN_C | NONEOS_C,
732/* < */ PRINT_C | CHAN_C | NONEOS_C,
733/* = */ PRINT_C | CHAN_C | NONEOS_C,
734/* > */ PRINT_C | CHAN_C | NONEOS_C,
735/* ? */ PRINT_C | KWILD_C | MWILD_C | CHAN_C | NONEOS_C,
736/* @ */ PRINT_C | KWILD_C | MWILD_C | CHAN_C | NONEOS_C,
737/* A */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
738/* B */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
739/* C */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
740/* D */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
741/* E */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
742/* F */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
743/* G */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
744/* H */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
745/* I */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
746/* J */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
747/* K */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
748/* L */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
749/* M */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
750/* N */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
751/* O */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
752/* P */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
753/* Q */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
754/* R */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
755/* S */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
756/* T */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
757/* U */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
758/* V */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
759/* W */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
760/* X */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
761/* Y */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
762/* Z */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
763/* [ */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
764/* \ */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
765/* ] */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
766/* ^ */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
767/* _ */ PRINT_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
768/* ` */ PRINT_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
769/* a */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
770/* b */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
771/* c */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
772/* d */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
773/* e */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
774/* f */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
775/* g */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
776/* h */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
777/* i */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
778/* j */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
779/* k */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
780/* l */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
781/* m */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
782/* n */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
783/* o */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
784/* p */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
785/* q */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
786/* r */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
787/* s */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
788/* t */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
789/* u */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
790/* v */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
791/* w */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
792/* x */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
793/* y */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
794/* z */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
795/* { */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
796/* | */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
797/* } */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
798/* ~ */ PRINT_C | ALPHA_C | CHAN_C | NONEOS_C | USER_C,
799/* del */ CHAN_C | NONEOS_C,
800/* 0x80 */ CHAN_C | NONEOS_C,
801/* 0x81 */ CHAN_C | NONEOS_C,
802/* 0x82 */ CHAN_C | NONEOS_C,
803/* 0x83 */ CHAN_C | NONEOS_C,
804/* 0x84 */ CHAN_C | NONEOS_C,
805/* 0x85 */ CHAN_C | NONEOS_C,
806/* 0x86 */ CHAN_C | NONEOS_C,
807/* 0x87 */ CHAN_C | NONEOS_C,
808/* 0x88 */ CHAN_C | NONEOS_C,
809/* 0x89 */ CHAN_C | NONEOS_C,
810/* 0x8A */ CHAN_C | NONEOS_C,
811/* 0x8B */ CHAN_C | NONEOS_C,
812/* 0x8C */ CHAN_C | NONEOS_C,
813/* 0x8D */ CHAN_C | NONEOS_C,
814/* 0x8E */ CHAN_C | NONEOS_C,
815/* 0x8F */ CHAN_C | NONEOS_C,
816/* 0x90 */ CHAN_C | NONEOS_C,
817/* 0x91 */ CHAN_C | NONEOS_C,
818/* 0x92 */ CHAN_C | NONEOS_C,
819/* 0x93 */ CHAN_C | NONEOS_C,
820/* 0x94 */ CHAN_C | NONEOS_C,
821/* 0x95 */ CHAN_C | NONEOS_C,
822/* 0x96 */ CHAN_C | NONEOS_C,
823/* 0x97 */ CHAN_C | NONEOS_C,
824/* 0x98 */ CHAN_C | NONEOS_C,
825/* 0x99 */ CHAN_C | NONEOS_C,
826/* 0x9A */ CHAN_C | NONEOS_C,
827/* 0x9B */ CHAN_C | NONEOS_C,
828/* 0x9C */ CHAN_C | NONEOS_C,
829/* 0x9D */ CHAN_C | NONEOS_C,
830/* 0x9E */ CHAN_C | NONEOS_C,
831/* 0x9F */ CHAN_C | NONEOS_C,
832/* 0xA0 */ CHAN_C | FCHAN_C | NONEOS_C,
833/* 0xA1 */ CHAN_C | NONEOS_C,
834/* 0xA2 */ CHAN_C | NONEOS_C,
835/* 0xA3 */ CHAN_C | NONEOS_C,
836/* 0xA4 */ CHAN_C | NONEOS_C,
837/* 0xA5 */ CHAN_C | NONEOS_C,
838/* 0xA6 */ CHAN_C | NONEOS_C,
839/* 0xA7 */ CHAN_C | NONEOS_C,
840/* 0xA8 */ CHAN_C | NONEOS_C,
841/* 0xA9 */ CHAN_C | NONEOS_C,
842/* 0xAA */ CHAN_C | NONEOS_C,
843/* 0xAB */ CHAN_C | NONEOS_C,
844/* 0xAC */ CHAN_C | NONEOS_C,
845/* 0xAD */ CHAN_C | NONEOS_C,
846/* 0xAE */ CHAN_C | NONEOS_C,
847/* 0xAF */ CHAN_C | NONEOS_C,
848/* 0xB0 */ CHAN_C | NONEOS_C,
849/* 0xB1 */ CHAN_C | NONEOS_C,
850/* 0xB2 */ CHAN_C | NONEOS_C,
851/* 0xB3 */ CHAN_C | NONEOS_C,
852/* 0xB4 */ CHAN_C | NONEOS_C,
853/* 0xB5 */ CHAN_C | NONEOS_C,
854/* 0xB6 */ CHAN_C | NONEOS_C,
855/* 0xB7 */ CHAN_C | NONEOS_C,
856/* 0xB8 */ CHAN_C | NONEOS_C,
857/* 0xB9 */ CHAN_C | NONEOS_C,
858/* 0xBA */ CHAN_C | NONEOS_C,
859/* 0xBB */ CHAN_C | NONEOS_C,
860/* 0xBC */ CHAN_C | NONEOS_C,
861/* 0xBD */ CHAN_C | NONEOS_C,
862/* 0xBE */ CHAN_C | NONEOS_C,
863/* 0xBF */ CHAN_C | NONEOS_C,
864/* 0xC0 */ CHAN_C | NONEOS_C,
865/* 0xC1 */ CHAN_C | NONEOS_C,
866/* 0xC2 */ CHAN_C | NONEOS_C,
867/* 0xC3 */ CHAN_C | NONEOS_C,
868/* 0xC4 */ CHAN_C | NONEOS_C,
869/* 0xC5 */ CHAN_C | NONEOS_C,
870/* 0xC6 */ CHAN_C | NONEOS_C,
871/* 0xC7 */ CHAN_C | NONEOS_C,
872/* 0xC8 */ CHAN_C | NONEOS_C,
873/* 0xC9 */ CHAN_C | NONEOS_C,
874/* 0xCA */ CHAN_C | NONEOS_C,
875/* 0xCB */ CHAN_C | NONEOS_C,
876/* 0xCC */ CHAN_C | NONEOS_C,
877/* 0xCD */ CHAN_C | NONEOS_C,
878/* 0xCE */ CHAN_C | NONEOS_C,
879/* 0xCF */ CHAN_C | NONEOS_C,
880/* 0xD0 */ CHAN_C | NONEOS_C,
881/* 0xD1 */ CHAN_C | NONEOS_C,
882/* 0xD2 */ CHAN_C | NONEOS_C,
883/* 0xD3 */ CHAN_C | NONEOS_C,
884/* 0xD4 */ CHAN_C | NONEOS_C,
885/* 0xD5 */ CHAN_C | NONEOS_C,
886/* 0xD6 */ CHAN_C | NONEOS_C,
887/* 0xD7 */ CHAN_C | NONEOS_C,
888/* 0xD8 */ CHAN_C | NONEOS_C,
889/* 0xD9 */ CHAN_C | NONEOS_C,
890/* 0xDA */ CHAN_C | NONEOS_C,
891/* 0xDB */ CHAN_C | NONEOS_C,
892/* 0xDC */ CHAN_C | NONEOS_C,
893/* 0xDD */ CHAN_C | NONEOS_C,
894/* 0xDE */ CHAN_C | NONEOS_C,
895/* 0xDF */ CHAN_C | NONEOS_C,
896/* 0xE0 */ CHAN_C | NONEOS_C,
897/* 0xE1 */ CHAN_C | NONEOS_C,
898/* 0xE2 */ CHAN_C | NONEOS_C,
899/* 0xE3 */ CHAN_C | NONEOS_C,
900/* 0xE4 */ CHAN_C | NONEOS_C,
901/* 0xE5 */ CHAN_C | NONEOS_C,
902/* 0xE6 */ CHAN_C | NONEOS_C,
903/* 0xE7 */ CHAN_C | NONEOS_C,
904/* 0xE8 */ CHAN_C | NONEOS_C,
905/* 0xE9 */ CHAN_C | NONEOS_C,
906/* 0xEA */ CHAN_C | NONEOS_C,
907/* 0xEB */ CHAN_C | NONEOS_C,
908/* 0xEC */ CHAN_C | NONEOS_C,
909/* 0xED */ CHAN_C | NONEOS_C,
910/* 0xEE */ CHAN_C | NONEOS_C,
911/* 0xEF */ CHAN_C | NONEOS_C,
912/* 0xF0 */ CHAN_C | NONEOS_C,
913/* 0xF1 */ CHAN_C | NONEOS_C,
914/* 0xF2 */ CHAN_C | NONEOS_C,
915/* 0xF3 */ CHAN_C | NONEOS_C,
916/* 0xF4 */ CHAN_C | NONEOS_C,
917/* 0xF5 */ CHAN_C | NONEOS_C,
918/* 0xF6 */ CHAN_C | NONEOS_C,
919/* 0xF7 */ CHAN_C | NONEOS_C,
920/* 0xF8 */ CHAN_C | NONEOS_C,
921/* 0xF9 */ CHAN_C | NONEOS_C,
922/* 0xFA */ CHAN_C | NONEOS_C,
923/* 0xFB */ CHAN_C | NONEOS_C,
924/* 0xFC */ CHAN_C | NONEOS_C,
925/* 0xFD */ CHAN_C | NONEOS_C,
926/* 0xFE */ CHAN_C | NONEOS_C,
927/* 0xFF */ CHAN_C | NONEOS_C
928};