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