]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/common/scriplib.c
Merge branch 'NateEag-master-patch-12920' into 'master'
[xonotic/netradiant.git] / tools / quake2 / 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 // scriplib.c
22
23 #include "cmdlib.h"
24 #include "inout.h"
25 #include "scriplib.h"
26
27 /*
28    =============================================================================
29
30                         PARSING STUFF
31
32    =============================================================================
33  */
34
35 typedef struct
36 {
37         char filename[1024];
38         char    *buffer,*script_p,*end_p;
39         int line;
40 } script_t;
41
42 #define MAX_INCLUDES    8
43 script_t scriptstack[MAX_INCLUDES];
44 script_t    *script;
45 int scriptline;
46
47 char token[MAXTOKEN];
48 qboolean endofscript;
49 qboolean tokenready;                     // only true if UnGetToken was just called
50
51 /*
52    ==============
53    AddScriptToStack
54    ==============
55  */
56 void AddScriptToStack( char *filename ){
57         int size;
58
59         script++;
60         if ( script == &scriptstack[MAX_INCLUDES] ) {
61                 Error( "script file exceeded MAX_INCLUDES" );
62         }
63         strcpy( script->filename, ExpandPath( filename ) );
64
65         size = LoadFile( script->filename, (void **)&script->buffer );
66
67         printf( "entering %s\n", script->filename );
68
69         script->line = 1;
70
71         script->script_p = script->buffer;
72         script->end_p = script->buffer + size;
73 }
74
75
76 /*
77    ==============
78    LoadScriptFile
79    ==============
80  */
81 void LoadScriptFile( char *filename ){
82         script = scriptstack;
83         AddScriptToStack( filename );
84
85         endofscript = false;
86         tokenready = false;
87 }
88
89
90 /*
91    ==============
92    ParseFromMemory
93    ==============
94  */
95 void ParseFromMemory( char *buffer, int size ){
96         script = scriptstack;
97         script++;
98         if ( script == &scriptstack[MAX_INCLUDES] ) {
99                 Error( "script file exceeded MAX_INCLUDES" );
100         }
101         strcpy( script->filename, "memory buffer" );
102
103         script->buffer = buffer;
104         script->line = 1;
105         script->script_p = script->buffer;
106         script->end_p = script->buffer + size;
107
108         endofscript = false;
109         tokenready = false;
110 }
111
112
113 /*
114    ==============
115    UnGetToken
116
117    Signals that the current token was not used, and should be reported
118    for the next GetToken.  Note that
119
120    GetToken (true);
121    UnGetToken ();
122    GetToken (false);
123
124    could cross a line boundary.
125    ==============
126  */
127 void UnGetToken( void ){
128         tokenready = true;
129 }
130
131
132 qboolean EndOfScript( qboolean crossline ){
133         if ( !crossline ) {
134                 Error( "Line %i is incomplete\n",scriptline );
135         }
136
137         if ( !strcmp( script->filename, "memory buffer" ) ) {
138                 endofscript = true;
139                 return false;
140         }
141
142         free( script->buffer );
143         if ( script == scriptstack + 1 ) {
144                 endofscript = true;
145                 return false;
146         }
147         script--;
148         scriptline = script->line;
149         printf( "returning to %s\n", script->filename );
150         return GetToken( crossline );
151 }
152
153 /*
154    ==============
155    GetToken
156    ==============
157  */
158 qboolean GetToken( qboolean crossline ){
159         char    *token_p;
160
161         if ( tokenready ) {                       // is a token allready waiting?
162                 tokenready = false;
163                 return true;
164         }
165
166         if ( script->script_p >= script->end_p ) {
167                 return EndOfScript( crossline );
168         }
169
170 //
171 // skip space
172 //
173 skipspace:
174         while ( *script->script_p <= 32 )
175         {
176                 if ( script->script_p >= script->end_p ) {
177                         return EndOfScript( crossline );
178                 }
179                 if ( *script->script_p++ == '\n' ) {
180                         if ( !crossline ) {
181                                 Error( "Line %i is incomplete\n",scriptline );
182                         }
183                         scriptline = script->line++;
184                 }
185         }
186
187         if ( script->script_p >= script->end_p ) {
188                 return EndOfScript( crossline );
189         }
190
191         // ; # // comments
192         if ( *script->script_p == ';' || *script->script_p == '#'
193                  || ( script->script_p[0] == '/' && script->script_p[1] == '/' ) ) {
194                 if ( !crossline ) {
195                         Error( "Line %i is incomplete\n",scriptline );
196                 }
197                 while ( *script->script_p++ != '\n' )
198                         if ( script->script_p >= script->end_p ) {
199                                 return EndOfScript( crossline );
200                         }
201                 goto skipspace;
202         }
203
204         // /* */ comments
205         if ( script->script_p[0] == '/' && script->script_p[1] == '*' ) {
206                 if ( !crossline ) {
207                         Error( "Line %i is incomplete\n",scriptline );
208                 }
209                 script->script_p += 2;
210                 while ( script->script_p[0] != '*' && script->script_p[1] != '/' )
211                 {
212                         script->script_p++;
213                         if ( script->script_p >= script->end_p ) {
214                                 return EndOfScript( crossline );
215                         }
216                 }
217                 script->script_p += 2;
218                 goto skipspace;
219         }
220
221 //
222 // copy token
223 //
224         token_p = token;
225
226         if ( *script->script_p == '"' ) {
227                 // quoted token
228                 script->script_p++;
229                 while ( *script->script_p != '"' )
230                 {
231                         *token_p++ = *script->script_p++;
232                         if ( script->script_p == script->end_p ) {
233                                 break;
234                         }
235                         if ( token_p == &token[MAXTOKEN] ) {
236                                 Error( "Token too large on line %i\n",scriptline );
237                         }
238                 }
239                 script->script_p++;
240         }
241         else{   // regular token
242                 while ( *script->script_p > 32 && *script->script_p != ';' )
243                 {
244                         *token_p++ = *script->script_p++;
245                         if ( script->script_p == script->end_p ) {
246                                 break;
247                         }
248                         if ( token_p == &token[MAXTOKEN] ) {
249                                 Error( "Token too large on line %i\n",scriptline );
250                         }
251                 }
252         }
253
254         *token_p = 0;
255
256         if ( !strcmp( token, "$include" ) ) {
257                 GetToken( false );
258                 AddScriptToStack( token );
259                 return GetToken( crossline );
260         }
261
262         return true;
263 }
264
265
266 /*
267    ==============
268    TokenAvailable
269
270    Returns true if there is another token on the line
271    ==============
272  */
273 qboolean TokenAvailable( void ){
274         char    *search_p;
275
276         search_p = script->script_p;
277
278         if ( search_p >= script->end_p ) {
279                 return false;
280         }
281
282         while ( *search_p <= 32 )
283         {
284                 if ( *search_p == '\n' ) {
285                         return false;
286                 }
287                 search_p++;
288                 if ( search_p == script->end_p ) {
289                         return false;
290                 }
291
292         }
293
294         if ( *search_p == ';' ) {
295                 return false;
296         }
297
298         return true;
299 }