1 /************************************************************************
2 * IRC - Internet Relay Chat, src/match.c
3 * Copyright (C) 1990 Jarkko Oikarinen
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)
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.
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.
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.
35 * Originally by Douglas A Lewis (dalewis@acsu.buffalo.edu)
36 * Rewritten by Timothy Vogelsang (netski), net@astrolink.org
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.
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.
48 int match(const char *mask
, const char *name
)
50 const char *m
= mask
, *n
= name
;
51 const char *m_tmp
= mask
, *n_tmp
= name
;
54 s_assert(mask
!= NULL
);
55 s_assert(name
!= NULL
);
72 for (star_p
= 0;; m
++)
91 for (n_tmp
= n
; *n
&& irctolower(*n
) != irctolower(*m
); n
++);
94 /* and fall through */
97 return (*m
!= '\0' ? 0 : 1);
98 if (irctolower(*m
) != irctolower(*n
))
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.
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.
118 int mask_match(const char *mask
, const char *name
)
120 const char *m
= mask
, *n
= name
;
121 const char *m_tmp
= mask
, *n_tmp
= name
;
124 s_assert(mask
!= NULL
);
125 s_assert(name
!= NULL
);
142 for (star_p
= 0;; m
++)
148 /* changed for mask_match() */
149 if (*n
== '*' || !*n
)
163 for (n_tmp
= n
; *n
&& irctolower(*n
) != irctolower(*m
); n
++);
166 /* and fall through */
169 return (*m
!= '\0' ? 0 : 1);
170 if (irctolower(*m
) != irctolower(*n
))
180 #define MATCH_MAX_CALLS 512 /* ACK! This dies when it's less that this
181 and we have long lines to parse */
182 /** Check a string against a mask.
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.
189 * This function supports escaping, so that a wildcard may be matched
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.
197 match_esc(const char *mask
, const char *name
)
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
;
208 s_assert(mask
!= NULL
);
209 s_assert(name
!= NULL
);
214 /* if the mask is "*", it matches everything */
215 if((*m
== '*') && (*(m
+ 1) == '\0'))
218 while(calls
++ < MATCH_MAX_CALLS
)
224 if(*m
== '\\' && !quote
)
230 if(!quote
&& *m
== '*')
233 * XXX - shouldn't need to spin here, the mask should have been
234 * collapsed before match is called
246 /* This means it is an invalid mask -A1kmm. */
260 for(m
--; (m
> (const unsigned char *)mask
) && (*m
== '?'); m
--)
263 if(*m
== '*' && (m
> (const unsigned char *)mask
))
273 * XXX - shouldn't need to spin here, the mask should have been
274 * collapsed before match is called
284 match1
= *m
== 's' ? *n
== ' ' : irctolower(*m
) == irctolower(*n
);
288 match1
= IsLetter(*n
);
290 match1
= IsDigit(*n
);
292 match1
= irctolower(*m
) == irctolower(*n
);
311 int comp_with_mask(void *addr
, void *dest
, unsigned int mask
)
313 if (memcmp(addr
, dest
, mask
/ 8) == 0)
316 unsigned char m
= (0xFF << (8 - (mask
% 8)));
317 if (mask
% 8 == 0 || (((unsigned char *) addr
)[n
] & m
) == (((unsigned char *) dest
)[n
] & m
))
325 int comp_with_mask_sock(struct sockaddr
*addr
, struct sockaddr
*dest
, unsigned int mask
)
330 if (addr
->sa_family
== AF_INET
)
332 iaddr
= &((struct sockaddr_in
*)(void *)addr
)->sin_addr
;
333 idest
= &((struct sockaddr_in
*)(void *)dest
)->sin_addr
;
337 iaddr
= &((struct sockaddr_in6
*)(void *)addr
)->sin6_addr
;
338 idest
= &((struct sockaddr_in6
*)(void *)dest
)->sin6_addr
;
342 return (comp_with_mask(iaddr
, idest
, mask
));
348 * Input - cidr ip mask, address
350 int match_ips(const char *s1
, const char *s2
)
352 struct rb_sockaddr_storage ipaddr
, maskaddr
;
354 char address
[HOSTLEN
+ 1];
356 void *ipptr
, *maskptr
;
359 rb_strlcpy(mask
, s1
, sizeof(mask
));
360 rb_strlcpy(address
, s2
, sizeof(address
));
362 len
= strrchr(mask
, '/');
372 if (strchr(mask
, ':') && strchr(address
, ':'))
378 ipptr
= &((struct sockaddr_in6
*)&ipaddr
)->sin6_addr
;
379 maskptr
= &((struct sockaddr_in6
*)&maskaddr
)->sin6_addr
;
381 else if (!strchr(mask
, ':') && !strchr(address
, ':'))
387 ipptr
= &((struct sockaddr_in
*)&ipaddr
)->sin_addr
;
388 maskptr
= &((struct sockaddr_in
*)&maskaddr
)->sin_addr
;
393 if (rb_inet_pton(aftype
, address
, ipptr
) <= 0)
395 if (rb_inet_pton(aftype
, mask
, maskptr
) <= 0)
397 if (comp_with_mask(ipptr
, maskptr
, cidrlen
))
405 * Input - mask, address
406 * Ouput - 1 = Matched 0 = Did not match
409 int match_cidr(const char *s1
, const char *s2
)
411 struct rb_sockaddr_storage ipaddr
, maskaddr
;
413 char address
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
417 void *ipptr
, *maskptr
;
420 rb_strlcpy(mask
, s1
, sizeof(mask
));
421 rb_strlcpy(address
, s2
, sizeof(address
));
423 ipmask
= strrchr(mask
, '@');
429 ip
= strrchr(address
, '@');
435 len
= strrchr(ipmask
, '/');
445 if (strchr(ip
, ':') && strchr(ipmask
, ':'))
451 ipptr
= &((struct sockaddr_in6
*)&ipaddr
)->sin6_addr
;
452 maskptr
= &((struct sockaddr_in6
*)&maskaddr
)->sin6_addr
;
454 else if (!strchr(ip
, ':') && !strchr(ipmask
, ':'))
460 ipptr
= &((struct sockaddr_in
*)&ipaddr
)->sin_addr
;
461 maskptr
= &((struct sockaddr_in
*)&maskaddr
)->sin_addr
;
466 if (rb_inet_pton(aftype
, ip
, ipptr
) <= 0)
468 if (rb_inet_pton(aftype
, ipmask
, maskptr
) <= 0)
470 if (comp_with_mask(ipptr
, maskptr
, cidrlen
) && match(mask
, address
))
478 * collapses a string containing multiple *'s.
480 char *collapse(char *pattern
)
482 char *p
= pattern
, *po
= pattern
;
510 * The collapse() function with support for escaping characters
512 char *collapse_esc(char *pattern
)
514 char *p
= pattern
, *po
= pattern
;
523 if (!(f
& 2) && c
== '*')
529 else if (!(f
& 2) && c
== '\\')
545 * irccmp - case insensitive comparison of two 0 terminated strings.
547 * returns 0, if s1 equal to s2
548 * <0, if s1 lexicographically less than s2
549 * >0, if s1 lexicographically greater than s2
551 int irccmp(const char *s1
, const char *s2
)
553 const unsigned char *str1
= (const unsigned char *)s1
;
554 const unsigned char *str2
= (const unsigned char *)s2
;
557 s_assert(s1
!= NULL
);
558 s_assert(s2
!= NULL
);
560 while ((res
= irctoupper(*str1
) - irctoupper(*str2
)) == 0)
570 int ircncmp(const char *s1
, const char *s2
, int n
)
572 const unsigned char *str1
= (const unsigned char *)s1
;
573 const unsigned char *str2
= (const unsigned char *)s2
;
575 s_assert(s1
!= NULL
);
576 s_assert(s2
!= NULL
);
578 while ((res
= irctoupper(*str1
) - irctoupper(*str2
)) == 0)
583 if (n
== 0 || (*str1
== '\0' && *str2
== '\0'))
589 void matchset_for_client(struct Client
*who
, struct matchset
*m
)
594 struct sockaddr_in ip4
;
596 sprintf(m
->host
[hostn
++], "%s!%s@%s", who
->name
, who
->username
, who
->host
);
600 sprintf(m
->ip
[ipn
++], "%s!%s@%s", who
->name
, who
->username
, who
->sockhost
);
603 if (who
->localClient
->mangledhost
!= NULL
)
605 /* if host mangling mode enabled, also check their real host */
606 if (!strcmp(who
->host
, who
->localClient
->mangledhost
))
608 sprintf(m
->host
[hostn
++], "%s!%s@%s", who
->name
, who
->username
, who
->orighost
);
610 /* if host mangling mode not enabled and no other spoof,
611 * also check the mangled form of their host */
612 else if (!IsDynSpoof(who
))
614 sprintf(m
->host
[hostn
++], "%s!%s@%s", who
->name
, who
->username
, who
->localClient
->mangledhost
);
617 if (!IsIPSpoof(who
) && GET_SS_FAMILY(&who
->localClient
->ip
) == AF_INET6
&&
618 rb_ipv4_from_ipv6((const struct sockaddr_in6
*)&who
->localClient
->ip
, &ip4
))
620 int n
= sprintf(m
->ip
[ipn
++], "%s!%s@", who
->name
, who
->username
);
621 rb_inet_ntop_sock((struct sockaddr
*)&ip4
,
622 m
->ip
[ipn
] + n
, sizeof m
->ip
[ipn
] - n
);
625 for (int i
= hostn
; i
< ARRAY_SIZE(m
->host
); i
++)
627 m
->host
[i
][0] = '\0';
629 for (int i
= ipn
; i
< ARRAY_SIZE(m
->ip
); i
++)
635 bool client_matches_mask(struct Client
*who
, const char *mask
)
637 static struct matchset ms
;
638 matchset_for_client(who
, &ms
);
639 return matches_mask(&ms
, mask
);
642 bool matches_mask(const struct matchset
*m
, const char *mask
)
644 for (int i
= 0; i
< ARRAY_SIZE(m
->host
); i
++)
646 if (m
->host
[i
][0] == '\0')
648 if (match(mask
, m
->host
[i
]))
651 for (int i
= 0; i
< ARRAY_SIZE(m
->ip
); i
++)
653 if (m
->ip
[i
][0] == '\0')
655 if (match(mask
, m
->ip
[i
]))
657 if (match_cidr(mask
, m
->ip
[i
]))
663 const unsigned char irctolower_tab
[] = {
664 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
665 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
666 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
668 ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
669 '*', '+', ',', '-', '.', '/',
670 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
671 ':', ';', '<', '=', '>', '?',
672 '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
673 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
674 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
676 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
677 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
678 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
680 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
681 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
682 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
683 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
684 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
685 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
686 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
687 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
688 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
689 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
690 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
691 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
692 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
693 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
694 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
695 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
698 const unsigned char irctoupper_tab
[] = {
699 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
700 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
701 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
703 ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
704 '*', '+', ',', '-', '.', '/',
705 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
706 ':', ';', '<', '=', '>', '?',
707 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
708 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
709 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
711 '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
712 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
713 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
715 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
716 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
717 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
718 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
719 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
720 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
721 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
722 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
723 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
724 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
725 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
726 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
727 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
728 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
729 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
730 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
736 * NOTE: RFC 1459 sez: anything but a ^G, comma, or space is allowed
739 unsigned int CharAttrs
[] = {
741 /* 1 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
742 /* 2 */ CNTRL_C
| CHAN_C
| FCHAN_C
| NONEOS_C
,
743 /* 3 */ CNTRL_C
| CHAN_C
| FCHAN_C
| NONEOS_C
,
744 /* 4 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
745 /* 5 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
746 /* 6 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
747 /* 7 BEL */ CNTRL_C
| NONEOS_C
,
748 /* 8 \b */ CNTRL_C
| CHAN_C
| NONEOS_C
,
749 /* 9 \t */ CNTRL_C
| SPACE_C
| CHAN_C
| NONEOS_C
,
750 /* 10 \n */ CNTRL_C
| SPACE_C
| CHAN_C
| NONEOS_C
| EOL_C
,
751 /* 11 \v */ CNTRL_C
| SPACE_C
| CHAN_C
| NONEOS_C
,
752 /* 12 \f */ CNTRL_C
| SPACE_C
| CHAN_C
| NONEOS_C
,
753 /* 13 \r */ CNTRL_C
| SPACE_C
| CHAN_C
| NONEOS_C
| EOL_C
,
754 /* 14 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
755 /* 15 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
756 /* 16 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
757 /* 17 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
758 /* 18 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
759 /* 19 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
760 /* 20 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
761 /* 21 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
762 /* 22 */ CNTRL_C
| CHAN_C
| FCHAN_C
| NONEOS_C
,
763 /* 23 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
764 /* 24 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
765 /* 25 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
766 /* 26 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
767 /* 27 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
768 /* 28 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
769 /* 29 */ CNTRL_C
| CHAN_C
| FCHAN_C
| NONEOS_C
,
770 /* 30 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
771 /* 31 */ CNTRL_C
| CHAN_C
| FCHAN_C
| NONEOS_C
,
772 /* SP */ PRINT_C
| SPACE_C
,
773 /* ! */ PRINT_C
| KWILD_C
| CHAN_C
| NONEOS_C
,
774 /* " */ PRINT_C
| CHAN_C
| NONEOS_C
,
775 /* # */ PRINT_C
| MWILD_C
| CHANPFX_C
| CHAN_C
| NONEOS_C
,
776 /* $ */ PRINT_C
| CHAN_C
| NONEOS_C
,
777 /* % */ PRINT_C
| CHAN_C
| NONEOS_C
,
778 /* & */ PRINT_C
| CHANPFX_C
| CHAN_C
| NONEOS_C
,
779 /* ' */ PRINT_C
| CHAN_C
| NONEOS_C
,
780 /* ( */ PRINT_C
| CHAN_C
| NONEOS_C
,
781 /* ) */ PRINT_C
| CHAN_C
| NONEOS_C
,
782 /* * */ PRINT_C
| KWILD_C
| MWILD_C
| CHAN_C
| NONEOS_C
,
783 /* + */ PRINT_C
| CHAN_C
| NONEOS_C
,
784 /* , */ PRINT_C
| NONEOS_C
,
785 /* - */ PRINT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
786 /* . */ PRINT_C
| KWILD_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
| SERV_C
,
787 /* / */ PRINT_C
| CHAN_C
| NONEOS_C
| HOST_C
,
788 /* 0 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
789 /* 1 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
790 /* 2 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
791 /* 3 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
792 /* 4 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
793 /* 5 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
794 /* 6 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
795 /* 7 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
796 /* 8 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
797 /* 9 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
798 /* : */ PRINT_C
| CHAN_C
| NONEOS_C
| HOST_C
,
799 /* ; */ PRINT_C
| CHAN_C
| NONEOS_C
,
800 /* < */ PRINT_C
| CHAN_C
| NONEOS_C
,
801 /* = */ PRINT_C
| CHAN_C
| NONEOS_C
,
802 /* > */ PRINT_C
| CHAN_C
| NONEOS_C
,
803 /* ? */ PRINT_C
| KWILD_C
| MWILD_C
| CHAN_C
| NONEOS_C
,
804 /* @ */ PRINT_C
| KWILD_C
| MWILD_C
| CHAN_C
| NONEOS_C
,
805 /* A */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
806 /* B */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
807 /* C */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
808 /* D */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
809 /* E */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
810 /* F */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
811 /* G */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
812 /* H */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
813 /* I */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
814 /* J */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
815 /* K */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
816 /* L */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
817 /* M */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
818 /* N */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
819 /* O */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
820 /* P */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
821 /* Q */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
822 /* R */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
823 /* S */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
824 /* T */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
825 /* U */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
826 /* V */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
827 /* W */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
828 /* X */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
829 /* Y */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
830 /* Z */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
831 /* [ */ PRINT_C
| ALPHA_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
832 /* \ */ PRINT_C
| ALPHA_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
833 /* ] */ PRINT_C
| ALPHA_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
834 /* ^ */ PRINT_C
| ALPHA_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
835 /* _ */ PRINT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
836 /* ` */ PRINT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
837 /* a */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
838 /* b */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
839 /* c */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
840 /* d */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
841 /* e */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
842 /* f */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
843 /* g */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
844 /* h */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
845 /* i */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
846 /* j */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
847 /* k */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
848 /* l */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
849 /* m */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
850 /* n */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
851 /* o */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
852 /* p */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
853 /* q */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
854 /* r */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
855 /* s */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
856 /* t */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
857 /* u */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
858 /* v */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
859 /* w */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
860 /* x */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
861 /* y */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
862 /* z */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
863 /* { */ PRINT_C
| ALPHA_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
864 /* | */ PRINT_C
| ALPHA_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
865 /* } */ PRINT_C
| ALPHA_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
866 /* ~ */ PRINT_C
| ALPHA_C
| CHAN_C
| NONEOS_C
| USER_C
,
867 /* del */ CHAN_C
| NONEOS_C
,
868 /* 0x80 */ CHAN_C
| NONEOS_C
,
869 /* 0x81 */ CHAN_C
| NONEOS_C
,
870 /* 0x82 */ CHAN_C
| NONEOS_C
,
871 /* 0x83 */ CHAN_C
| NONEOS_C
,
872 /* 0x84 */ CHAN_C
| NONEOS_C
,
873 /* 0x85 */ CHAN_C
| NONEOS_C
,
874 /* 0x86 */ CHAN_C
| NONEOS_C
,
875 /* 0x87 */ CHAN_C
| NONEOS_C
,
876 /* 0x88 */ CHAN_C
| NONEOS_C
,
877 /* 0x89 */ CHAN_C
| NONEOS_C
,
878 /* 0x8A */ CHAN_C
| NONEOS_C
,
879 /* 0x8B */ CHAN_C
| NONEOS_C
,
880 /* 0x8C */ CHAN_C
| NONEOS_C
,
881 /* 0x8D */ CHAN_C
| NONEOS_C
,
882 /* 0x8E */ CHAN_C
| NONEOS_C
,
883 /* 0x8F */ CHAN_C
| NONEOS_C
,
884 /* 0x90 */ CHAN_C
| NONEOS_C
,
885 /* 0x91 */ CHAN_C
| NONEOS_C
,
886 /* 0x92 */ CHAN_C
| NONEOS_C
,
887 /* 0x93 */ CHAN_C
| NONEOS_C
,
888 /* 0x94 */ CHAN_C
| NONEOS_C
,
889 /* 0x95 */ CHAN_C
| NONEOS_C
,
890 /* 0x96 */ CHAN_C
| NONEOS_C
,
891 /* 0x97 */ CHAN_C
| NONEOS_C
,
892 /* 0x98 */ CHAN_C
| NONEOS_C
,
893 /* 0x99 */ CHAN_C
| NONEOS_C
,
894 /* 0x9A */ CHAN_C
| NONEOS_C
,
895 /* 0x9B */ CHAN_C
| NONEOS_C
,
896 /* 0x9C */ CHAN_C
| NONEOS_C
,
897 /* 0x9D */ CHAN_C
| NONEOS_C
,
898 /* 0x9E */ CHAN_C
| NONEOS_C
,
899 /* 0x9F */ CHAN_C
| NONEOS_C
,
900 /* 0xA0 */ CHAN_C
| FCHAN_C
| NONEOS_C
,
901 /* 0xA1 */ CHAN_C
| NONEOS_C
,
902 /* 0xA2 */ CHAN_C
| NONEOS_C
,
903 /* 0xA3 */ CHAN_C
| NONEOS_C
,
904 /* 0xA4 */ CHAN_C
| NONEOS_C
,
905 /* 0xA5 */ CHAN_C
| NONEOS_C
,
906 /* 0xA6 */ CHAN_C
| NONEOS_C
,
907 /* 0xA7 */ CHAN_C
| NONEOS_C
,
908 /* 0xA8 */ CHAN_C
| NONEOS_C
,
909 /* 0xA9 */ CHAN_C
| NONEOS_C
,
910 /* 0xAA */ CHAN_C
| NONEOS_C
,
911 /* 0xAB */ CHAN_C
| NONEOS_C
,
912 /* 0xAC */ CHAN_C
| NONEOS_C
,
913 /* 0xAD */ CHAN_C
| NONEOS_C
,
914 /* 0xAE */ CHAN_C
| NONEOS_C
,
915 /* 0xAF */ CHAN_C
| NONEOS_C
,
916 /* 0xB0 */ CHAN_C
| NONEOS_C
,
917 /* 0xB1 */ CHAN_C
| NONEOS_C
,
918 /* 0xB2 */ CHAN_C
| NONEOS_C
,
919 /* 0xB3 */ CHAN_C
| NONEOS_C
,
920 /* 0xB4 */ CHAN_C
| NONEOS_C
,
921 /* 0xB5 */ CHAN_C
| NONEOS_C
,
922 /* 0xB6 */ CHAN_C
| NONEOS_C
,
923 /* 0xB7 */ CHAN_C
| NONEOS_C
,
924 /* 0xB8 */ CHAN_C
| NONEOS_C
,
925 /* 0xB9 */ CHAN_C
| NONEOS_C
,
926 /* 0xBA */ CHAN_C
| NONEOS_C
,
927 /* 0xBB */ CHAN_C
| NONEOS_C
,
928 /* 0xBC */ CHAN_C
| NONEOS_C
,
929 /* 0xBD */ CHAN_C
| NONEOS_C
,
930 /* 0xBE */ CHAN_C
| NONEOS_C
,
931 /* 0xBF */ CHAN_C
| NONEOS_C
,
932 /* 0xC0 */ CHAN_C
| NONEOS_C
,
933 /* 0xC1 */ CHAN_C
| NONEOS_C
,
934 /* 0xC2 */ CHAN_C
| NONEOS_C
,
935 /* 0xC3 */ CHAN_C
| NONEOS_C
,
936 /* 0xC4 */ CHAN_C
| NONEOS_C
,
937 /* 0xC5 */ CHAN_C
| NONEOS_C
,
938 /* 0xC6 */ CHAN_C
| NONEOS_C
,
939 /* 0xC7 */ CHAN_C
| NONEOS_C
,
940 /* 0xC8 */ CHAN_C
| NONEOS_C
,
941 /* 0xC9 */ CHAN_C
| NONEOS_C
,
942 /* 0xCA */ CHAN_C
| NONEOS_C
,
943 /* 0xCB */ CHAN_C
| NONEOS_C
,
944 /* 0xCC */ CHAN_C
| NONEOS_C
,
945 /* 0xCD */ CHAN_C
| NONEOS_C
,
946 /* 0xCE */ CHAN_C
| NONEOS_C
,
947 /* 0xCF */ CHAN_C
| NONEOS_C
,
948 /* 0xD0 */ CHAN_C
| NONEOS_C
,
949 /* 0xD1 */ CHAN_C
| NONEOS_C
,
950 /* 0xD2 */ CHAN_C
| NONEOS_C
,
951 /* 0xD3 */ CHAN_C
| NONEOS_C
,
952 /* 0xD4 */ CHAN_C
| NONEOS_C
,
953 /* 0xD5 */ CHAN_C
| NONEOS_C
,
954 /* 0xD6 */ CHAN_C
| NONEOS_C
,
955 /* 0xD7 */ CHAN_C
| NONEOS_C
,
956 /* 0xD8 */ CHAN_C
| NONEOS_C
,
957 /* 0xD9 */ CHAN_C
| NONEOS_C
,
958 /* 0xDA */ CHAN_C
| NONEOS_C
,
959 /* 0xDB */ CHAN_C
| NONEOS_C
,
960 /* 0xDC */ CHAN_C
| NONEOS_C
,
961 /* 0xDD */ CHAN_C
| NONEOS_C
,
962 /* 0xDE */ CHAN_C
| NONEOS_C
,
963 /* 0xDF */ CHAN_C
| NONEOS_C
,
964 /* 0xE0 */ CHAN_C
| NONEOS_C
,
965 /* 0xE1 */ CHAN_C
| NONEOS_C
,
966 /* 0xE2 */ CHAN_C
| NONEOS_C
,
967 /* 0xE3 */ CHAN_C
| NONEOS_C
,
968 /* 0xE4 */ CHAN_C
| NONEOS_C
,
969 /* 0xE5 */ CHAN_C
| NONEOS_C
,
970 /* 0xE6 */ CHAN_C
| NONEOS_C
,
971 /* 0xE7 */ CHAN_C
| NONEOS_C
,
972 /* 0xE8 */ CHAN_C
| NONEOS_C
,
973 /* 0xE9 */ CHAN_C
| NONEOS_C
,
974 /* 0xEA */ CHAN_C
| NONEOS_C
,
975 /* 0xEB */ CHAN_C
| NONEOS_C
,
976 /* 0xEC */ CHAN_C
| NONEOS_C
,
977 /* 0xED */ CHAN_C
| NONEOS_C
,
978 /* 0xEE */ CHAN_C
| NONEOS_C
,
979 /* 0xEF */ CHAN_C
| NONEOS_C
,
980 /* 0xF0 */ CHAN_C
| NONEOS_C
,
981 /* 0xF1 */ CHAN_C
| NONEOS_C
,
982 /* 0xF2 */ CHAN_C
| NONEOS_C
,
983 /* 0xF3 */ CHAN_C
| NONEOS_C
,
984 /* 0xF4 */ CHAN_C
| NONEOS_C
,
985 /* 0xF5 */ CHAN_C
| NONEOS_C
,
986 /* 0xF6 */ CHAN_C
| NONEOS_C
,
987 /* 0xF7 */ CHAN_C
| NONEOS_C
,
988 /* 0xF8 */ CHAN_C
| NONEOS_C
,
989 /* 0xF9 */ CHAN_C
| NONEOS_C
,
990 /* 0xFA */ CHAN_C
| NONEOS_C
,
991 /* 0xFB */ CHAN_C
| NONEOS_C
,
992 /* 0xFC */ CHAN_C
| NONEOS_C
,
993 /* 0xFD */ CHAN_C
| NONEOS_C
,
994 /* 0xFE */ CHAN_C
| NONEOS_C
,
995 /* 0xFF */ CHAN_C
| NONEOS_C