]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/qdata_heretic2/common/scriplib.c
ok
[xonotic/netradiant.git] / tools / quake2 / qdata_heretic2 / common / scriplib.c
1 /*
2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 // scriplib.c
23
24 #include "cmdlib.h"
25 #include "inout.h"
26 #include "scriplib.h"
27
28 /*
29 =============================================================================
30
31                                                 PARSING STUFF
32
33 =============================================================================
34 */
35
36 typedef struct
37 {
38         char    filename[1024];
39         char    *buffer,*script_p,*end_p;
40         int     line;
41 } script_t;
42
43 #define MAX_INCLUDES    8
44 script_t        scriptstack[MAX_INCLUDES];
45 script_t        *script;
46 int                     scriptline;
47
48 char    token[MAXTOKEN];
49 qboolean endofscript;
50 qboolean tokenready;                     // only true if UnGetScriptToken was just called
51
52 /*
53 ==============
54 AddScriptToStack
55 ==============
56 */
57 void AddScriptToStack (char *filename)
58 {
59         int            size;
60
61         script++;
62         if (script == &scriptstack[MAX_INCLUDES])
63                 Error ("script file exceeded MAX_INCLUDES");
64         strcpy (script->filename, ExpandPath (filename) );
65
66         size = LoadFile (script->filename, (void **)&script->buffer);
67
68         printf ("entering %s\n", script->filename);
69
70         script->line = 1;
71
72         script->script_p = script->buffer;
73         script->end_p = script->buffer + size;
74 }
75
76
77 /*
78 ==============
79 LoadScriptFile
80 ==============
81 */
82 void LoadScriptFile (char *filename)
83 {
84         script = scriptstack;
85         AddScriptToStack (filename);
86
87         endofscript = false;
88         tokenready = false;
89 }
90
91
92 /*
93 ==============
94 ParseFromMemory
95 ==============
96 */
97 void ParseFromMemory (char *buffer, int size)
98 {
99         script = scriptstack;
100         script++;
101         if (script == &scriptstack[MAX_INCLUDES])
102                 Error ("script file exceeded MAX_INCLUDES");
103         strcpy (script->filename, "memory buffer" );
104
105         script->buffer = buffer;
106         script->line = 1;
107         script->script_p = script->buffer;
108         script->end_p = script->buffer + size;
109
110         endofscript = false;
111         tokenready = false;
112 }
113
114
115 /*
116 ==============
117 UnGetScriptToken
118
119 Signals that the current token was not used, and should be reported
120 for the next GetScriptToken.  Note that
121
122 GetScriptToken (true);
123 UnGetScriptToken ();
124 GetScriptToken (false);
125
126 could cross a line boundary.
127 ==============
128 */
129 void UnGetScriptToken (void)
130 {
131         tokenready = true;
132 }
133
134
135 qboolean EndOfScript (qboolean crossline)
136 {
137         if (!crossline)
138                 Error ("Line %i is incomplete\n",scriptline);
139
140         if (!strcmp (script->filename, "memory buffer"))
141         {
142                 endofscript = true;
143                 return false;
144         }
145
146         free (script->buffer);
147         if (script == scriptstack+1)
148         {
149                 endofscript = true;
150                 return false;
151         }
152         script--;
153         scriptline = script->line;
154         printf ("returning to %s\n", script->filename);
155         return GetScriptToken (crossline);
156 }
157
158 /*
159 ==============
160 GetScriptToken
161 ==============
162 */
163 qboolean GetScriptToken (qboolean crossline)
164 {
165         char    *token_p;
166
167         if (tokenready)                         // is a token allready waiting?
168         {
169                 tokenready = false;
170                 return true;
171         }
172
173         if (script->script_p >= script->end_p)
174                 return EndOfScript (crossline);
175
176 //
177 // skip space
178 //
179 skipspace:
180         while (*script->script_p <= 32)
181         {
182                 if (script->script_p >= script->end_p)
183                         return EndOfScript (crossline);
184                 if (*script->script_p++ == '\n')
185                 {
186                         if (!crossline)
187                                 Error ("Line %i is incomplete\n",scriptline);
188                         scriptline = script->line++;
189                 }
190         }
191
192         if (script->script_p >= script->end_p)
193                 return EndOfScript (crossline);
194
195         // ; # // comments
196         if (*script->script_p == ';' || *script->script_p == '#'
197                 || ( script->script_p[0] == '/' && script->script_p[1] == '/') )
198         {
199                 if (!crossline)
200                         Error ("Line %i is incomplete\n",scriptline);
201                 while (*script->script_p++ != '\n')
202                         if (script->script_p >= script->end_p)
203                                 return EndOfScript (crossline);
204                 goto skipspace;
205         }
206
207         // /* */ comments
208         if (script->script_p[0] == '/' && script->script_p[1] == '*')
209         {
210                 if (!crossline)
211                         Error ("Line %i is incomplete\n",scriptline);
212                 script->script_p+=2;
213                 while (script->script_p[0] != '*' && script->script_p[1] != '/')
214                 {
215                         script->script_p++;
216                         if (script->script_p >= script->end_p)
217                                 return EndOfScript (crossline);
218                 }
219                 script->script_p += 2;
220                 goto skipspace;
221         }
222
223 //
224 // copy token
225 //
226         token_p = token;
227
228         if (*script->script_p == '"')
229         {
230                 // quoted token
231                 script->script_p++;
232                 while (*script->script_p != '"')
233                 {
234                         *token_p++ = *script->script_p++;
235                         if (script->script_p == script->end_p)
236                                 break;
237                         if (token_p == &token[MAXTOKEN])
238                                 Error ("Token too large on line %i\n",scriptline);
239                 }
240                 script->script_p++;
241         }
242         else    // regular token
243         while ( *script->script_p > 32 && *script->script_p != ';')
244         {
245                 *token_p++ = *script->script_p++;
246                 if (script->script_p == script->end_p)
247                         break;
248                 if (token_p == &token[MAXTOKEN])
249                         Error ("Token too large on line %i\n",scriptline);
250         }
251
252         *token_p = 0;
253
254         if (!strcmp (token, "$include"))
255         {
256                 GetScriptToken (false);
257                 AddScriptToStack (token);
258                 return GetScriptToken (crossline);
259         }
260
261         return true;
262 }
263
264
265 /*
266 ==============
267 ScriptTokenAvailable
268
269 Returns true if there is another token on the line
270 ==============
271 */
272 qboolean ScriptTokenAvailable (void)
273 {
274         char    *search_p;
275
276         search_p = script->script_p;
277
278         if (search_p >= script->end_p)
279                 return false;
280
281         while ( *search_p <= 32)
282         {
283                 if (*search_p == '\n')
284                         return false;
285                 search_p++;
286                 if (search_p == script->end_p)
287                         return false;
288
289         }
290
291         if (*search_p == ';')
292                 return false;
293
294         return true;
295 }
296
297