1 /*
2 	#FILENAME#
3 
4 	#DESCRIPTION#
5 
6 	Copyright (C) 2002 #AUTHOR#
7 
8 	Author: #AUTHOR#
9 	Date: #DATE#
10 
11 	This program is free software; you can redistribute it and/or
12 	modify it under the terms of the GNU General Public License
13 	as published by the Free Software Foundation; either version 2
14 	of the License, or (at your option) any later version.
15 
16 	This program is distributed in the hope that it will be useful,
17 	but WITHOUT ANY WARRANTY; without even the implied warranty of
18 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 
20 	See the GNU General Public License for more details.
21 
22 	You should have received a copy of the GNU General Public License
23 	along with this program; if not, write to:
24 
25 		Free Software Foundation, Inc.
26 		59 Temple Place - Suite 330
27 		Boston, MA  02111-1307, USA
28 
29 */
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33 
34 #ifdef HAVE_STRING_H
35 # include <string.h>
36 #endif
37 #ifdef HAVE_STRINGS_H
38 # include <strings.h>
39 #endif
40 
41 #include <stdlib.h>
42 
43 #include "QF/sys.h"
44 #include "QF/cbuf.h"
45 #include "QF/cmd.h"
46 #include "QF/dstring.h"
47 #include "QF/qtypes.h"
48 
49 #include "compat.h"
50 
51 VISIBLE cbuf_t *cbuf_active = NULL;
52 
53 VISIBLE cbuf_args_t *
Cbuf_ArgsNew(void)54 Cbuf_ArgsNew (void)
55 {
56 	return calloc (1, sizeof (cbuf_args_t));
57 }
58 
59 VISIBLE void
Cbuf_ArgsDelete(cbuf_args_t * args)60 Cbuf_ArgsDelete (cbuf_args_t *args)
61 {
62 	int		i;
63 
64 	for (i = 0; i < args->argv_size; i++)
65 		dstring_delete (args->argv[i]);
66 	free (args->argv);
67 	free ((void*)args->args);
68 	free (args->argm);
69 	free (args);
70 }
71 
72 VISIBLE void
Cbuf_ArgsAdd(cbuf_args_t * args,const char * arg)73 Cbuf_ArgsAdd (cbuf_args_t *args, const char *arg)
74 {
75 	int		i;
76 
77 	if (args->argc == args->argv_size) {
78 		args->argv_size += 4;
79 		args->argv = realloc (args->argv,
80 							  args->argv_size * sizeof (dstring_t *));
81 		args->args = realloc ((void*)args->args, args->argv_size * sizeof (char *));
82 		args->argm = realloc (args->argm, args->argv_size * sizeof (void *));
83 		for (i = args->argv_size - 4; i < args->argv_size; i++) {
84 			args->argv[i] = dstring_newstr ();
85 			args->args[i] = 0;
86 		}
87 	}
88 	dstring_copystr (args->argv[args->argc], arg);
89 	args->argc++;
90 }
91 
92 VISIBLE cbuf_t *
Cbuf_New(cbuf_interpreter_t * interp)93 Cbuf_New (cbuf_interpreter_t *interp)
94 {
95 	cbuf_t		*cbuf = calloc (1, sizeof (cbuf_t));
96 
97 	cbuf->args = Cbuf_ArgsNew ();
98 	cbuf->interpreter = interp;
99 	if (interp->construct)
100 			interp->construct (cbuf);
101 	return cbuf;
102 }
103 
104 VISIBLE void
Cbuf_Delete(cbuf_t * cbuf)105 Cbuf_Delete (cbuf_t *cbuf)
106 {
107 	if (!cbuf)
108 		return;
109 	Cbuf_ArgsDelete (cbuf->args);
110 	if (cbuf->interpreter->destruct)
111 		cbuf->interpreter->destruct (cbuf);
112 	free (cbuf);
113 }
114 
115 VISIBLE void
Cbuf_DeleteStack(cbuf_t * stack)116 Cbuf_DeleteStack (cbuf_t *stack)
117 {
118 	cbuf_t		*next;
119 
120 	for (; stack; stack = next) {
121 		next = stack->down;
122 		Cbuf_Delete (stack);
123 	}
124 }
125 
126 void
Cbuf_Reset(cbuf_t * cbuf)127 Cbuf_Reset (cbuf_t *cbuf)
128 {
129 	cbuf->resumetime = 0.0;
130 	cbuf->args->argc = 0;
131 	cbuf->state = CBUF_STATE_NORMAL;
132 	if (cbuf->interpreter->reset)
133 		cbuf->interpreter->reset (cbuf);
134 }
135 
136 VISIBLE cbuf_t *
Cbuf_PushStack(cbuf_interpreter_t * interp)137 Cbuf_PushStack (cbuf_interpreter_t *interp)
138 {
139 	cbuf_t *new;
140 	if (cbuf_active->down) {
141 		new = cbuf_active->down;
142 		if (new->interpreter != interp) {
143 			new->interpreter->destruct (new);
144 			new->interpreter = interp;
145 			new->interpreter->construct (new);
146 		}
147 		Cbuf_Reset (new);
148 	} else
149 		new = Cbuf_New (interp);
150 	cbuf_active->down = new;
151 	new->up = cbuf_active;
152 	cbuf_active->state = CBUF_STATE_STACK;
153 	return new;
154 }
155 
156 VISIBLE void
Cbuf_AddText(cbuf_t * cbuf,const char * text)157 Cbuf_AddText (cbuf_t *cbuf, const char *text)
158 {
159 	if (cbuf->state == CBUF_STATE_JUNK)
160 		cbuf->state = CBUF_STATE_NORMAL;
161 	cbuf->interpreter->add (cbuf, text);
162 }
163 
164 VISIBLE void
Cbuf_InsertText(cbuf_t * cbuf,const char * text)165 Cbuf_InsertText (cbuf_t *cbuf, const char *text)
166 {
167 	if (cbuf->state == CBUF_STATE_JUNK)
168 		cbuf->state = CBUF_STATE_NORMAL;
169 	cbuf->interpreter->insert (cbuf, text);
170 }
171 
172 VISIBLE void
Cbuf_Execute(cbuf_t * cbuf)173 Cbuf_Execute (cbuf_t *cbuf)
174 {
175 	cbuf_t *old = cbuf_active;
176 	cbuf_active = cbuf;
177 	cbuf->interpreter->execute (cbuf);
178 	cbuf_active = old;
179 }
180 
181 VISIBLE void
Cbuf_Execute_Stack(cbuf_t * cbuf)182 Cbuf_Execute_Stack (cbuf_t *cbuf)
183 {
184 	cbuf_t		*sp;
185 
186 	if (cbuf->resumetime) {
187 		if (cbuf->resumetime < Sys_DoubleTime())
188 				cbuf->resumetime = 0;
189 		else
190 				return;
191 	}
192 	for (sp = cbuf; sp->down && sp->down->state != CBUF_STATE_JUNK; sp = sp->down);
193 	if (sp->state == CBUF_STATE_BLOCKED)
194 		return;
195 	while (sp) {
196 		Cbuf_Execute (sp);
197 		if (sp->state) {
198 			if (sp->state == CBUF_STATE_STACK) {
199 				sp->state = CBUF_STATE_NORMAL;
200 				sp = sp->down;
201 				continue;
202 			} else if (sp->state == CBUF_STATE_ERROR)
203 				break;
204 			else if (sp->state == CBUF_STATE_BLOCKED)
205 				return;
206 			else {
207 				sp->state = CBUF_STATE_NORMAL;
208 				return;
209 			}
210 		}
211 		sp->state = CBUF_STATE_JUNK;
212 		sp = sp->up;
213 	}
214 	if (cbuf->down) {
215 		Cbuf_DeleteStack (cbuf->down);
216 		cbuf->down = 0;
217 	}
218 	if (sp)
219 		Cbuf_Reset (cbuf);
220 }
221 
222 VISIBLE void
Cbuf_Execute_Sets(cbuf_t * cbuf)223 Cbuf_Execute_Sets (cbuf_t *cbuf)
224 {
225 	cbuf->interpreter->execute_sets (cbuf);
226 }
227 
228