]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/qdata_heretic2/common/scriplib.c
Merge branch 'fix-fast' into 'master'
[xonotic/netradiant.git] / tools / quake2 / qdata_heretic2 / common / scriplib.c
1 /*
2    Copyright (C) 1999-2007 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         int size;
59
60         script++;
61         if ( script == &scriptstack[MAX_INCLUDES] ) {
62                 Error( "script file exceeded MAX_INCLUDES" );
63         }
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         script = scriptstack;
84         AddScriptToStack( filename );
85
86         endofscript = false;
87         tokenready = false;
88 }
89
90
91 /*
92    ==============
93    ParseFromMemory
94    ==============
95  */
96 void ParseFromMemory( char *buffer, int size ){
97         script = scriptstack;
98         script++;
99         if ( script == &scriptstack[MAX_INCLUDES] ) {
100                 Error( "script file exceeded MAX_INCLUDES" );
101         }
102         strcpy( script->filename, "memory buffer" );
103
104         script->buffer = buffer;
105         script->line = 1;
106         script->script_p = script->buffer;
107         script->end_p = script->buffer + size;
108
109         endofscript = false;
110         tokenready = false;
111 }
112
113
114 /*
115    ==============
116    UnGetScriptToken
117
118    Signals that the current token was not used, and should be reported
119    for the next GetScriptToken.  Note that
120
121    GetScriptToken (true);
122    UnGetScriptToken ();
123    GetScriptToken (false);
124
125    could cross a line boundary.
126    ==============
127  */
128 void UnGetScriptToken( void ){
129         tokenready = true;
130 }
131
132
133 qboolean EndOfScript( qboolean crossline ){
134         if ( !crossline ) {
135                 Error( "Line %i is incomplete\n",scriptline );
136         }
137
138         if ( !strcmp( script->filename, "memory buffer" ) ) {
139                 endofscript = true;
140                 return false;
141         }
142
143         free( script->buffer );
144         if ( script == scriptstack + 1 ) {
145                 endofscript = true;
146                 return false;
147         }
148         script--;
149         scriptline = script->line;
150         printf( "returning to %s\n", script->filename );
151         return GetScriptToken( crossline );
152 }
153
154 /*
155    ==============
156    GetScriptToken
157    ==============
158  */
159 qboolean GetScriptToken( qboolean crossline ){
160         char    *token_p;
161
162         if ( tokenready ) {                       // is a token allready waiting?
163                 tokenready = false;
164                 return true;
165         }
166
167         if ( script->script_p >= script->end_p ) {
168                 return EndOfScript( crossline );
169         }
170
171 //
172 // skip space
173 //
174 skipspace:
175         while ( *script->script_p <= 32 )
176         {
177                 if ( script->script_p >= script->end_p ) {
178                         return EndOfScript( crossline );
179                 }
180                 if ( *script->script_p++ == '\n' ) {
181                         if ( !crossline ) {
182                                 Error( "Line %i is incomplete\n",scriptline );
183                         }
184                         scriptline = script->line++;
185                 }
186         }
187
188         if ( script->script_p >= script->end_p ) {
189                 return EndOfScript( crossline );
190         }
191
192         // ; # // comments
193         if ( *script->script_p == ';' || *script->script_p == '#'
194                  || ( script->script_p[0] == '/' && script->script_p[1] == '/' ) ) {
195                 if ( !crossline ) {
196                         Error( "Line %i is incomplete\n",scriptline );
197                 }
198                 while ( *script->script_p++ != '\n' )
199                         if ( script->script_p >= script->end_p ) {
200                                 return EndOfScript( crossline );
201                         }
202                 goto skipspace;
203         }
204
205         // /* */ comments
206         if ( script->script_p[0] == '/' && script->script_p[1] == '*' ) {
207                 if ( !crossline ) {
208                         Error( "Line %i is incomplete\n",scriptline );
209                 }
210                 script->script_p += 2;
211                 while ( script->script_p[0] != '*' && script->script_p[1] != '/' )
212                 {
213                         script->script_p++;
214                         if ( script->script_p >= script->end_p ) {
215                                 return EndOfScript( crossline );
216                         }
217                 }
218                 script->script_p += 2;
219                 goto skipspace;
220         }
221
222 //
223 // copy token
224 //
225         token_p = token;
226
227         if ( *script->script_p == '"' ) {
228                 // quoted token
229                 script->script_p++;
230                 while ( *script->script_p != '"' )
231                 {
232                         *token_p++ = *script->script_p++;
233                         if ( script->script_p == script->end_p ) {
234                                 break;
235                         }
236                         if ( token_p == &token[MAXTOKEN] ) {
237                                 Error( "Token too large on line %i\n",scriptline );
238                         }
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                         }
249                         if ( token_p == &token[MAXTOKEN] ) {
250                                 Error( "Token too large on line %i\n",scriptline );
251                         }
252                 }
253         }
254
255         *token_p = 0;
256
257         if ( !strcmp( token, "$include" ) ) {
258                 GetScriptToken( false );
259                 AddScriptToStack( token );
260                 return GetScriptToken( crossline );
261         }
262
263         return true;
264 }
265
266
267 /*
268    ==============
269    ScriptTokenAvailable
270
271    Returns true if there is another token on the line
272    ==============
273  */
274 qboolean ScriptTokenAvailable( void ){
275         char    *search_p;
276
277         search_p = script->script_p;
278
279         if ( search_p >= script->end_p ) {
280                 return false;
281         }
282
283         while ( *search_p <= 32 )
284         {
285                 if ( *search_p == '\n' ) {
286                         return false;
287                 }
288                 search_p++;
289                 if ( search_p == script->end_p ) {
290                         return false;
291                 }
292
293         }
294
295         if ( *search_p == ';' ) {
296                 return false;
297         }
298
299         return true;
300 }