1 /*
2 * stack.c - does the handling of stack functions
3 *
4 * written by matthew green
5 *
6 * Copyright (c) 1993-2003 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 * $Id: stack.c,v 1.7 2003-01-08 20:00:54 f Exp $
33 */
34
35 #include "irc.h"
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 #ifndef LITE
45
46 static OnStack *on_stack = NULL;
47 static AliasStack *alias_stack = NULL;
48 static AliasStack *assign_stack = NULL;
49 static SetStack *set_stack = NULL;
50
51 static AliasStack *alias_get _((char *, int));
52 static AliasStack *alias_stack_find _((char *, int));
53 static void alias_stack_add _((AliasStack *, int));
54 static void do_stack_on _((int, char *));
55 static void do_stack_alias _((int, char *, int));
56 static void do_stack_set _((int, char *));
57
58 static void
do_stack_on(type,args)59 do_stack_on(type, args)
60 int type;
61 char *args;
62 {
63 char foo[4];
64 int cnt, i, which = 0;
65 size_t len;
66 Hook *list;
67 NumericList *nhook,
68 *nptr,
69 *ntmp = NULL;
70
71 if (!on_stack && (type == STACK_POP || type == STACK_LIST))
72 {
73 say("ON stack is empty!");
74 return;
75 }
76 if (!args || !*args)
77 {
78 say("Missing event type for STACK ON");
79 return;
80 }
81 len = strlen(args);
82 for (cnt = 0, i = 0; i < NUMBER_OF_LISTS; i++)
83 {
84 if (!my_strnicmp(args, hook_functions[i].name, len))
85 {
86 if (strlen(hook_functions[i].name) == len)
87 {
88 cnt = 1;
89 which = i;
90 break;
91 }
92 else
93 {
94 cnt++;
95 which = i;
96 }
97 }
98 else if (cnt)
99 break;
100 }
101 if (!cnt)
102 {
103 if (is_number(args))
104 {
105 which = atoi(args);
106 if (which < 1 || which > 999)
107 {
108 say("Numerics must be between 001 and 999");
109 return;
110 }
111 which = -which;
112 }
113 else
114 {
115 say("No such ON function: %s", args);
116 return;
117 }
118 }
119 if (which < 0)
120 {
121 /* XXX: check cnt != 1 */
122 snprintf(foo, sizeof foo, "%3.3u", -which);
123 if ((nhook = (NumericList *) find_in_list((List **) &numeric_list, foo, 0)) != NULL)
124 list = nhook->list;
125 else
126 list = NULL;
127 }
128 else
129 list = hook_functions[which].list;
130 if (type == STACK_PUSH)
131 {
132 OnStack *new;
133
134 if (list == NULL)
135 {
136 say("The ON %s list is empty", args);
137 return;
138 }
139 new = (OnStack *) new_malloc(sizeof(OnStack));
140 new->next = on_stack;
141 on_stack = new;
142 new->which = which;
143 new->list = list;
144 if (which < 0)
145 {
146 if (nhook == numeric_list)
147 {
148 numeric_list = nhook->next;
149 new_free(&nhook->name);
150 new_free(&nhook);
151 return;
152 }
153 for (nptr = numeric_list; nptr;
154 ntmp = nptr, nptr = nptr->next)
155 {
156 if (nptr == nhook)
157 {
158 ntmp->next = nptr->next;
159 new_free(&nptr->name);
160 new_free(&nptr);
161 return;
162 }
163 }
164 }
165 else
166 hook_functions[which].list = NULL;
167 return;
168 }
169 else if (type == STACK_POP)
170 {
171 OnStack *p,
172 *tmp = NULL;
173
174 for (p = on_stack; p; tmp = p, p = p->next)
175 {
176 if (p->which == which)
177 {
178 if (p == on_stack)
179 on_stack = p->next;
180 else
181 tmp->next = p->next;
182 break;
183 }
184 }
185 if (!p)
186 {
187 say("No %s on the stack", args);
188 return;
189 }
190 if ((which < 0 && nhook) || hook_functions[which].list)
191 remove_hook(which, NULL, 0, 0, 1); /* free hooks */
192 if (which < 0)
193 {
194 if ((nptr = (NumericList *) find_in_list((List **) &numeric_list, foo, 0)) == NULL)
195 {
196 nptr = (NumericList *) new_malloc(sizeof(NumericList));
197 nptr->name = NULL;
198 nptr->list = p->list;
199 malloc_strcpy(&nptr->name, foo);
200 add_to_list((List **) &numeric_list, (List *) nptr);
201 }
202 else
203 add_to_list((List **) &numeric_list->list, (List *) p->list);
204 }
205 else
206 hook_functions[which].list = p->list;
207 return;
208 }
209 else if (type == STACK_LIST)
210 {
211 int slevel = 0;
212 OnStack *osptr;
213
214 for (osptr = on_stack; osptr; osptr = osptr->next)
215 if (osptr->which == which)
216 {
217 Hook *hptr;
218
219 slevel++;
220 say("Level %d stack", slevel);
221 for (hptr = osptr->list; hptr; hptr = hptr->next)
222 show_hook(hptr, args);
223 }
224
225 if (!slevel)
226 say("The STACK ON %s list is empty", args);
227 return;
228 }
229 say("Unknown STACK ON type ??");
230 }
231
232 static void
do_stack_alias(type,args,which)233 do_stack_alias(type, args, which)
234 int type;
235 char *args;
236 int which;
237 {
238 char *name;
239 AliasStack *aptr,
240 **aptrptr;
241
242 if (which == STACK_DO_ALIAS)
243 {
244 name = "ALIAS";
245 aptrptr = &alias_stack;
246 }
247 else
248 {
249 name = "ASSIGN";
250 aptrptr = &assign_stack;
251 }
252 if (!*aptrptr && (type == STACK_POP || type == STACK_LIST))
253 {
254 say("%s stack is empty!", name);
255 return;
256 }
257
258 if (STACK_PUSH == type)
259 {
260 aptr = alias_get(args, which);
261 if ((AliasStack *) 0 == aptr)
262 {
263 say("No such %s %s", name, args);
264 return;
265 }
266 if (aptrptr)
267 aptr->next = *aptrptr;
268 *aptrptr = aptr;
269 return;
270 }
271 if (STACK_POP == type)
272 {
273 aptr = alias_stack_find(args, which);
274 if ((AliasStack *) 0 == aptr)
275 {
276 say("%s is not on the %s stack!", args, name);
277 return;
278 }
279 alias_stack_add(aptr, which);
280 return;
281 }
282 if (STACK_LIST == type)
283 {
284 say("stack list is not implimented yet");
285 return;
286 }
287 say("Unknown STACK type ??");
288 }
289
290 static void
do_stack_set(type,args)291 do_stack_set(type, args)
292 int type;
293 char *args;
294 {
295 SetStack *tmp = set_stack;
296
297 tmp++;
298 }
299
300 /*
301 * alias_get: this returns a point to an `AliasStack' structure that
302 * has be extracted from the current aliases, and removed from that
303 * list.
304 */
alias_get(args,which)305 static AliasStack* alias_get(args, which)
306 char *args;
307 int which;
308 {
309 return (AliasStack *) 0;
310 }
311
312 /*
313 * alias_stack_find: this returns the pointer to the struct with the
314 * most recent alias for `args' in the stack.
315 */
316 static AliasStack*
alias_stack_find(args,which)317 alias_stack_find(args, which)
318 char *args;
319 int which;
320 {
321 return (AliasStack *) 0;
322 }
323
324 /*
325 * alias_stack_add: this adds `aptr' to the alias/assign stack.
326 */
327 static void
alias_stack_add(aptr,which)328 alias_stack_add(aptr, which)
329 AliasStack *aptr;
330 int which;
331 {
332 return;
333 }
334
335 void
stackcmd(command,args,subargs)336 stackcmd(command, args, subargs)
337 char *command,
338 *args,
339 *subargs;
340 {
341 char *arg,
342 *cmd = NULL;
343 int type;
344 size_t len;
345
346 if ((arg = next_arg(args, &args)) != NULL)
347 {
348 len = strlen(arg);
349 malloc_strcpy(&cmd, arg);
350 upper(cmd);
351 if (!strncmp(cmd, "PUSH", len))
352 type = STACK_PUSH;
353 else if (!strncmp(cmd, "POP", len))
354 type = STACK_POP;
355 else if (!strncmp(cmd, "LIST", len))
356 type = STACK_LIST;
357 else
358 {
359 say("%s is unknown stack type", arg);
360 new_free(&cmd);
361 return;
362 }
363 new_free(&cmd);
364 }
365 else
366 {
367 say("Need operation for STACK");
368 return;
369 }
370 if ((arg = next_arg(args, &args)) != NULL)
371 {
372 len = strlen(arg);
373 malloc_strcpy(&cmd, arg);
374 upper(cmd);
375 if (!strncmp(cmd, "ON", len))
376 do_stack_on(type, args);
377 else if (!strncmp(cmd, "ALIAS", len))
378 do_stack_alias(type, args, STACK_DO_ALIAS);
379 else if (!strncmp(cmd, "ASSIGN", len))
380 do_stack_alias(type, args, STACK_DO_ASSIGN);
381 else if (!strncmp(cmd, "SET", len))
382 do_stack_set(type, args);
383 else
384 {
385 say("%s is not a valid STACK type");
386 new_free(&cmd);
387 return;
388 }
389 new_free(&cmd);
390 }
391 else
392 {
393 say("Need stack type for STACK");
394 return;
395 }
396 }
397
398 #endif /* LITE */
399