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