ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/vendor/ircservices-5.1.24/modes.c
Revision: 3389
Committed: Fri Apr 25 14:12:15 2014 UTC (9 years, 10 months ago) by michael
Content type: text/x-csrc
File size: 8487 byte(s)
Log Message:
- Imported ircservices-5.1.24

File Contents

# Content
1 /* Routines for handling mode flags and strings.
2 *
3 * IRC Services is copyright (c) 1996-2009 Andrew Church.
4 * E-mail: <achurch@achurch.org>
5 * Parts written by Andrew Kempe and others.
6 * This program is free but copyrighted software; see the file GPL.txt for
7 * details.
8 */
9
10 #include "services.h"
11
12 /*************************************************************************/
13
14 /* List of user/channel modes and associated mode letters. */
15
16 ModeData usermodes[] = {
17 ['o'] = {0x00000001},
18 ['i'] = {0x00000002},
19 ['w'] = {0x00000004},
20 };
21
22 ModeData chanmodes[] = {
23 ['i'] = {0x00000001, 0, 0},
24 ['m'] = {0x00000002, 0, 0},
25 ['n'] = {0x00000004, 0, 0},
26 ['p'] = {0x00000008, 0, 0},
27 ['s'] = {0x00000010, 0, 0},
28 ['t'] = {0x00000020, 0, 0},
29 ['k'] = {0x00000040, 1, 1},
30 ['l'] = {0x00000080, 1, 0},
31 ['b'] = {0x80000000, 1, 1, 0, MI_MULTIPLE},
32 };
33
34 ModeData chanusermodes[] = {
35 ['o'] = {0x00000001, 1, 1, '@'},
36 ['v'] = {0x00000002, 1, 1, '+'},
37 };
38
39 /* The following are initialized by mode_setup(): */
40 int32 usermode_reg; /* Usermodes applied to registered nicks */
41 int32 chanmode_reg; /* Chanmodes applied to registered chans */
42 int32 chanmode_regonly; /* Chanmodes indicating regnick-only channels*/
43 int32 chanmode_opersonly; /* Chanmodes indicating oper-only channels */
44 char chanmode_multiple[257]; /* Chanmodes that can be set multiple times */
45
46 /* Flag tables, used internally to speed up flag lookups. 0 indicates a
47 * flag with no associated mode. */
48 static char userflags[31], chanflags[31], chanuserflags[31];
49
50 /* Table of channel user mode prefixes, used like flag tables above. */
51 static int32 prefixtable[256];
52
53 /* Tables used for fast lookups. */
54 static ModeData *modetable[] = {usermodes, chanmodes, chanusermodes};
55 static char *flagtable[] = {userflags, chanflags, chanuserflags};
56
57 /*************************************************************************/
58 /*************************************************************************/
59
60 /* Initialize flag tables and flag sets from mode tables. Must be called
61 * before any other mode_* function, and should be called again if the mode
62 * tables are modified.
63 */
64
65 void mode_setup(void)
66 {
67 int i;
68 ModeData *modelist;
69 char *flaglist;
70 int multi_index = 0; /* index into chanmode_multiple[] */
71
72 modelist = usermodes;
73 flaglist = userflags;
74 for (i = 0; i < 256; i++) {
75 if (modelist[i].flag) {
76 int n = 0;
77 uint32 tmp = (uint32) modelist[i].flag;
78 if (modelist[i].info & MI_REGISTERED)
79 usermode_reg |= tmp;
80 while (tmp >>= 1)
81 n++;
82 if (n < 31)
83 flaglist[n] = (char)i;
84 }
85 }
86
87 modelist = chanmodes;
88 flaglist = chanflags;
89 for (i = 0; i < 256; i++) {
90 if (modelist[i].flag) {
91 int n = 0;
92 uint32 tmp = (uint32) modelist[i].flag;
93 if (modelist[i].info & MI_REGISTERED)
94 chanmode_reg |= tmp;
95 if (modelist[i].info & MI_REGNICKS_ONLY)
96 chanmode_regonly |= tmp;
97 if (modelist[i].info & MI_OPERS_ONLY)
98 chanmode_opersonly |= tmp;
99 if (modelist[i].info & MI_MULTIPLE)
100 chanmode_multiple[multi_index++] = i;
101 while (tmp >>= 1)
102 n++;
103 if (n < 31)
104 flaglist[n] = (char)i;
105 }
106 }
107 chanmode_multiple[multi_index] = 0;
108
109 modelist = chanusermodes;
110 flaglist = chanuserflags;
111 for (i = 0; i < 256; i++) {
112 if (modelist[i].flag) {
113 int n = 0;
114 uint32 tmp = (uint32) modelist[i].flag;
115 prefixtable[ (uint8)modelist[i].prefix ] = tmp;
116 while (tmp >>= 1)
117 n++;
118 if (n < 31)
119 flaglist[n] = (char)i;
120 if (modelist[i].plus_params!=1 || modelist[i].minus_params!=1) {
121 log("modes: Warning: channel user mode `%c' takes %d/%d"
122 " parameters (should be 1/1)",
123 i, modelist[i].plus_params, modelist[i].minus_params);
124 }
125 }
126 }
127 }
128
129 /*************************************************************************/
130
131 /* Return the flag corresponding to the given mode character, or 0 if no
132 * such mode exists. Return MODE_INVALID if the mode exists but has no
133 * assigned flag. `which' indicates the mode set to be used: MODE_USER,
134 * MODE_CHANNEL, or MODE_CHANUSER.
135 */
136
137 int32 mode_char_to_flag(char c, int which)
138 {
139 if (which != MODE_USER && which != MODE_CHANNEL && which != MODE_CHANUSER){
140 log("mode_char_to_flag(): bad `which' value %d", which);
141 return MODE_INVALID;
142 }
143 return modetable[which][(uint8)c].flag;
144 }
145
146 /*************************************************************************/
147
148 /* Return the number of parameters the given mode takes, as
149 * (plus_params<<8) | (minus_params). Return -1 if there is no such mode.
150 */
151
152 int mode_char_to_params(char c, int which)
153 {
154 ModeData *ptr;
155
156 if (which != MODE_USER && which != MODE_CHANNEL && which != MODE_CHANUSER){
157 log("mode_char_to_params(): bad `which' value %d", which);
158 return -1;
159 }
160 ptr = &modetable[which][(uint8)c];
161 return ptr->plus_params<<8 | ptr->minus_params;
162 }
163
164 /*************************************************************************/
165
166 /* Return the mode character corresponding to the given flag, or 0 if no
167 * such mode exists. If more than one bit is set in `f', then the mode
168 * character corresponding to the highest bit is used.
169 */
170
171 char mode_flag_to_char(int32 f, int which)
172 {
173 char *flaglist;
174 int n = 0, tmp = f;
175
176 if (which != MODE_USER && which != MODE_CHANNEL && which != MODE_CHANUSER){
177 log("mode_flag_to_char(): bad `which' value %d", which);
178 return 0;
179 }
180 flaglist = flagtable[which];
181
182 while (tmp >>= 1)
183 n++;
184 if (n >= 31)
185 return 0;
186 return flaglist[n];
187 }
188
189 /*************************************************************************/
190
191 /* Return the flag set corresponding to the given string of mode characters
192 * in the given mode set. If MODE_NOERROR is set in `which', invalid mode
193 * characters are ignored; if not set, (CMODE_INVALID | modechar) is
194 * returned for the first invalid mode character found.
195 */
196
197 int32 mode_string_to_flags(const char *s, int which)
198 {
199 int noerror = (which & MODE_NOERROR);
200 int32 flags = 0;
201 const ModeData *modelist;
202
203 which &= ~MODE_NOERROR;
204 if (which != MODE_USER && which != MODE_CHANNEL && which != MODE_CHANUSER){
205 log("mode_string_to_flags(): bad `which' value %d", which|noerror);
206 return 0;
207 }
208 modelist = modetable[which];
209
210 while (*s) {
211 int f = modelist[(uint8)*s].flag;
212 if (!f) {
213 if (noerror) {
214 s++;
215 continue;
216 }
217 return MODE_INVALID | *s;
218 }
219 if (f != MODE_INVALID)
220 flags |= f;
221 s++;
222 }
223 return flags;
224 }
225
226 /*************************************************************************/
227
228 /* Return the string of mode characters corresponding to the given flag
229 * set. If the flag set has invalid flags in it, they are ignored.
230 * The returned string is stored in a static buffer which will be
231 * overwritten on the next call.
232 */
233
234 char *mode_flags_to_string(int32 flags, int which)
235 {
236 static char buf[32];
237 char *s = buf;
238 int n = 0;
239 const char *flaglist;
240
241 if (which != MODE_USER && which != MODE_CHANNEL && which != MODE_CHANUSER){
242 log("mode_flags_to_string(): bad `which' value %d", which);
243 *buf = 0;
244 return buf;
245 }
246 flaglist = flagtable[which];
247
248 flags &= ~MODE_INVALID;
249 while (flags) {
250 if ((flags & 1) && flaglist[n])
251 *s++ = flaglist[n];
252 n++;
253 flags >>= 1;
254 }
255 *s = 0;
256 return buf;
257 }
258
259 /*************************************************************************/
260
261 /* Return the flag corresponding to the given channel user mode prefix, or
262 * 0 if no such mode exists.
263 */
264
265 int32 cumode_prefix_to_flag(char c)
266 {
267 return prefixtable[(uint8)c];
268 }
269
270 /*************************************************************************/
271
272 /*
273 * Local variables:
274 * c-file-style: "stroustrup"
275 * c-file-offsets: ((case-label . *) (statement-case-intro . *))
276 * indent-tabs-mode: nil
277 * End:
278 *
279 * vim: expandtab shiftwidth=4:
280 */