1 /*
2 * stack.c - does the handling of stack functions
3 *
4 * written by matthew green
5 *
6 * Copyright (c) 1993-2000 Matthew R. Green.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include "irc.h"
34 #include "dma.h"
35 IRCII_RCSID("@(#)$Id: stack.c,v 1.29 2000/04/09 07:14:16 mrg Exp $");
36
37 #include "stack.h"
38 #include "window.h"
39 #include "hook.h"
40 #include "ircaux.h"
41 #include "output.h"
42 #include "list.h"
43
44 static OnStack *on_stack = NULL;
45 static AliasStack *alias_stack = NULL;
46 static AliasStack *assign_stack = NULL;
47 static SetStack *set_stack = NULL;
48
49 static AliasStack *alias_get _((u_char *, int));
50 static AliasStack *alias_stack_find _((u_char *, int));
51 static void alias_stack_add _((AliasStack *, int));
52 static void do_stack_on _((int, u_char *));
53 static void do_stack_alias _((int, u_char *, int));
54 static void do_stack_set _((int, u_char *));
55
56 static void
do_stack_on(type,args)57 do_stack_on(type, args)
58 int type;
59 u_char *args;
60 {
61 u_char foo[7];
62 int cnt, i, which = 0;
63 size_t len;
64 Hook *list;
65 NumericList *nhook,
66 *nptr,
67 *ntmp = NULL;
68
69 if (!on_stack && (type == STACK_POP || type == STACK_LIST))
70 {
71 say("ON stack is empty!");
72 return;
73 }
74 if (!args || !*args)
75 {
76 say("Missing event type for STACK ON");
77 return;
78 }
79 len = my_strlen(args);
80 for (cnt = 0, i = 0; i < NUMBER_OF_LISTS; i++)
81 {
82 if (!my_strnicmp(args, UP(hook_functions[i].name), len))
83 {
84 if (my_strlen(hook_functions[i].name) == len)
85 {
86 cnt = 1;
87 which = i;
88 break;
89 }
90 else
91 {
92 cnt++;
93 which = i;
94 }
95 }
96 else if (cnt)
97 break;
98 }
99 if (!cnt)
100 {
101 if (is_number(args))
102 {
103 which = my_atoi(args);
104 if (which < 1 || which > 999)
105 {
106 say("Numerics must be between 001 and 999");
107 return;
108 }
109 which = -which;
110 }
111 else
112 {
113 say("No such ON function: %s", args);
114 return;
115 }
116 }
117 if (which < 0)
118 {
119 /* XXX: check cnt != 1 */
120 sprintf(CP(foo), "%3.3u", -which);
121 if ((nhook = (NumericList *) find_in_list((List **) &numeric_list, foo, 0)) != NULL)
122 list = nhook->list;
123 else
124 list = NULL;
125 }
126 else
127 list = hook_functions[which].list;
128 if (type == STACK_PUSH)
129 {
130 OnStack *new;
131
132 if (list == NULL)
133 {
134 say("The ON %s list is empty", args);
135 return;
136 }
137 new = (OnStack *) new_malloc(sizeof(OnStack));
138 new->next = on_stack;
139 on_stack = new;
140 new->which = which;
141 new->list = list;
142 if (which < 0)
143 {
144 if (nhook == numeric_list)
145 {
146 numeric_list = nhook->next;
147 new_free(&nhook->name);
148 new_free(&nhook);
149 return;
150 }
151 for (nptr = numeric_list; nptr;
152 ntmp = nptr, nptr = nptr->next)
153 {
154 if (nptr == nhook)
155 {
156 ntmp->next = nptr->next;
157 new_free(&nptr->name);
158 new_free(&nptr);
159 return;
160 }
161 }
162 }
163 else
164 hook_functions[which].list = NULL;
165 return;
166 }
167 else if (type == STACK_POP)
168 {
169 OnStack *p,
170 *tmp = NULL;
171
172 for (p = on_stack; p; tmp = p, p = p->next)
173 {
174 if (p->which == which)
175 {
176 if (p == on_stack)
177 on_stack = p->next;
178 else
179 tmp->next = p->next;
180 break;
181 }
182 }
183 if (!p)
184 {
185 say("No %s on the stack", args);
186 return;
187 }
188 if ((which < 0 && nhook) || hook_functions[which].list)
189 remove_hook(which, NULL, 0, 0, 1); /* free hooks */
190 if (which < 0)
191 {
192 if ((nptr = (NumericList *) find_in_list((List **) &numeric_list, foo, 0)) == NULL)
193 {
194 nptr = (NumericList *) new_malloc(sizeof(NumericList));
195 nptr->name = NULL;
196 nptr->list = p->list;
197 malloc_strcpy((u_char **) &nptr->name, foo);
198 add_to_list((List **) &numeric_list, (List *) nptr);
199 }
200 else
201 add_to_list((List **) &numeric_list->list, (List *) p->list);
202 }
203 else
204 hook_functions[which].list = p->list;
205 return;
206 }
207 else if (type == STACK_LIST)
208 {
209 int slevel = 0;
210 OnStack *osptr;
211
212 for (osptr = on_stack; osptr; osptr = osptr->next)
213 if (osptr->which == which)
214 {
215 Hook *hptr;
216
217 slevel++;
218 say("Level %d stack", slevel);
219 for (hptr = osptr->list; hptr; hptr = hptr->next)
220 show_hook(hptr, CP(args));
221 }
222
223 if (!slevel)
224 say("The STACK ON %s list is empty", args);
225 return;
226 }
227 say("Unknown STACK ON type ??");
228 }
229
230 static void
do_stack_alias(type,args,which)231 do_stack_alias(type, args, which)
232 int type;
233 u_char *args;
234 int which;
235 {
236 char *name;
237 AliasStack *aptr,
238 **aptrptr;
239
240 if (which == STACK_DO_ALIAS)
241 {
242 name = "ALIAS";
243 aptrptr = &alias_stack;
244 }
245 else
246 {
247 name = "ASSIGN";
248 aptrptr = &assign_stack;
249 }
250 if (!*aptrptr && (type == STACK_POP || type == STACK_LIST))
251 {
252 say("%s stack is empty!", name);
253 return;
254 }
255
256 if (STACK_PUSH == type)
257 {
258 aptr = alias_get(args, which);
259 if ((AliasStack *) 0 == aptr)
260 {
261 say("No such %s %s", name, args);
262 return;
263 }
264 if (aptrptr)
265 aptr->next = *aptrptr;
266 *aptrptr = aptr;
267 return;
268 }
269 if (STACK_POP == type)
270 {
271 aptr = alias_stack_find(args, which);
272 if ((AliasStack *) 0 == aptr)
273 {
274 say("%s is not on the %s stack!", args, name);
275 return;
276 }
277 alias_stack_add(aptr, which);
278 return;
279 }
280 if (STACK_LIST == type)
281 {
282 say("stack list is not implimented yet");
283 return;
284 }
285 say("Unknown STACK type ??");
286 }
287
288 static void
do_stack_set(type,args)289 do_stack_set(type, args)
290 int type;
291 u_char *args;
292 {
293 SetStack *tmp = set_stack;
294
295 tmp++;
296 }
297
298 /*
299 * alias_get: this returns a point to an `AliasStack' structure that
300 * has be extracted from the current aliases, and removed from that
301 * list.
302 */
alias_get(args,which)303 static AliasStack* alias_get(args, which)
304 u_char *args;
305 int which;
306 {
307 return (AliasStack *) 0;
308 }
309
310 /*
311 * alias_stack_find: this returns the pointer to the struct with the
312 * most recent alias for `args' in the stack.
313 */
314 static AliasStack*
alias_stack_find(args,which)315 alias_stack_find(args, which)
316 u_char *args;
317 int which;
318 {
319 return (AliasStack *) 0;
320 }
321
322 /*
323 * alias_stack_add: this adds `aptr' to the alias/assign stack.
324 */
325 static void
alias_stack_add(aptr,which)326 alias_stack_add(aptr, which)
327 AliasStack *aptr;
328 int which;
329 {
330 return;
331 }
332
333 void
stackcmd(command,args,subargs)334 stackcmd(command, args, subargs)
335 u_char *command,
336 *args,
337 *subargs;
338 {
339 u_char *arg,
340 *cmd = NULL;
341 int type;
342 size_t len;
343
344 if ((arg = next_arg(args, &args)) != NULL)
345 {
346 len = my_strlen(arg);
347 malloc_strcpy(&cmd, arg);
348 upper(cmd);
349 if (!my_strncmp(cmd, "PUSH", len))
350 type = STACK_PUSH;
351 else if (!my_strncmp(cmd, "POP", len))
352 type = STACK_POP;
353 else if (!my_strncmp(cmd, "LIST", len))
354 type = STACK_LIST;
355 else
356 {
357 say("%s is unknown stack type", arg);
358 new_free(&cmd);
359 return;
360 }
361 new_free(&cmd);
362 }
363 else
364 {
365 say("Need operation for STACK");
366 return;
367 }
368 if ((arg = next_arg(args, &args)) != NULL)
369 {
370 len = my_strlen(arg);
371 malloc_strcpy(&cmd, arg);
372 upper(cmd);
373 if (!my_strncmp(cmd, "ON", len))
374 do_stack_on(type, args);
375 else if (!my_strncmp(cmd, "ALIAS", len))
376 do_stack_alias(type, args, STACK_DO_ALIAS);
377 else if (!my_strncmp(cmd, "ASSIGN", len))
378 do_stack_alias(type, args, STACK_DO_ASSIGN);
379 else if (!my_strncmp(cmd, "SET", len))
380 do_stack_set(type, args);
381 else
382 {
383 say("%s is not a valid STACK type");
384 new_free(&cmd);
385 return;
386 }
387 new_free(&cmd);
388 }
389 else
390 {
391 say("Need stack type for STACK");
392 return;
393 }
394 }
395