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