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