scriplib.c (7389B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, 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 Foobar; 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 "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 qtrue if UnGetToken was just called 50 51 /* 52 ============== 53 AddScriptToStack 54 ============== 55 */ 56 void AddScriptToStack( const char *filename ) { 57 int size; 58 59 script++; 60 if (script == &scriptstack[MAX_INCLUDES]) 61 Error ("script file exceeded MAX_INCLUDES"); 62 strcpy (script->filename, ExpandPath (filename) ); 63 64 size = LoadFile (script->filename, (void **)&script->buffer); 65 66 printf ("entering %s\n", script->filename); 67 68 script->line = 1; 69 70 script->script_p = script->buffer; 71 script->end_p = script->buffer + size; 72 } 73 74 75 /* 76 ============== 77 LoadScriptFile 78 ============== 79 */ 80 void LoadScriptFile( const char *filename ) { 81 script = scriptstack; 82 AddScriptToStack (filename); 83 84 endofscript = qfalse; 85 tokenready = qfalse; 86 } 87 88 89 /* 90 ============== 91 ParseFromMemory 92 ============== 93 */ 94 void ParseFromMemory (char *buffer, int size) 95 { 96 script = scriptstack; 97 script++; 98 if (script == &scriptstack[MAX_INCLUDES]) 99 Error ("script file exceeded MAX_INCLUDES"); 100 strcpy (script->filename, "memory buffer" ); 101 102 script->buffer = buffer; 103 script->line = 1; 104 script->script_p = script->buffer; 105 script->end_p = script->buffer + size; 106 107 endofscript = qfalse; 108 tokenready = qfalse; 109 } 110 111 112 /* 113 ============== 114 UnGetToken 115 116 Signals that the current token was not used, and should be reported 117 for the next GetToken. Note that 118 119 GetToken (qtrue); 120 UnGetToken (); 121 GetToken (qfalse); 122 123 could cross a line boundary. 124 ============== 125 */ 126 void UnGetToken (void) 127 { 128 tokenready = qtrue; 129 } 130 131 132 qboolean EndOfScript (qboolean crossline) 133 { 134 if (!crossline) 135 Error ("Line %i is incomplete\n",scriptline); 136 137 if (!strcmp (script->filename, "memory buffer")) 138 { 139 endofscript = qtrue; 140 return qfalse; 141 } 142 143 free (script->buffer); 144 if (script == scriptstack+1) 145 { 146 endofscript = qtrue; 147 return qfalse; 148 } 149 script--; 150 scriptline = script->line; 151 printf ("returning to %s\n", script->filename); 152 return GetToken (crossline); 153 } 154 155 /* 156 ============== 157 GetToken 158 ============== 159 */ 160 qboolean GetToken (qboolean crossline) 161 { 162 char *token_p; 163 164 if (tokenready) // is a token allready waiting? 165 { 166 tokenready = qfalse; 167 return qtrue; 168 } 169 170 if (script->script_p >= script->end_p) 171 return EndOfScript (crossline); 172 173 // 174 // skip space 175 // 176 skipspace: 177 while (*script->script_p <= 32) 178 { 179 if (script->script_p >= script->end_p) 180 return EndOfScript (crossline); 181 if (*script->script_p++ == '\n') 182 { 183 if (!crossline) 184 Error ("Line %i is incomplete\n",scriptline); 185 scriptline = script->line++; 186 } 187 } 188 189 if (script->script_p >= script->end_p) 190 return EndOfScript (crossline); 191 192 // ; # // comments 193 if (*script->script_p == ';' || *script->script_p == '#' 194 || ( script->script_p[0] == '/' && script->script_p[1] == '/') ) 195 { 196 if (!crossline) 197 Error ("Line %i is incomplete\n",scriptline); 198 while (*script->script_p++ != '\n') 199 if (script->script_p >= script->end_p) 200 return EndOfScript (crossline); 201 scriptline = script->line++; 202 goto skipspace; 203 } 204 205 // /* */ comments 206 if (script->script_p[0] == '/' && script->script_p[1] == '*') 207 { 208 if (!crossline) 209 Error ("Line %i is incomplete\n",scriptline); 210 script->script_p+=2; 211 while (script->script_p[0] != '*' && script->script_p[1] != '/') 212 { 213 if ( *script->script_p == '\n' ) { 214 scriptline = script->line++; 215 } 216 script->script_p++; 217 if (script->script_p >= script->end_p) 218 return EndOfScript (crossline); 219 } 220 script->script_p += 2; 221 goto skipspace; 222 } 223 224 // 225 // copy token 226 // 227 token_p = token; 228 229 if (*script->script_p == '"') 230 { 231 // quoted token 232 script->script_p++; 233 while (*script->script_p != '"') 234 { 235 *token_p++ = *script->script_p++; 236 if (script->script_p == script->end_p) 237 break; 238 if (token_p == &token[MAXTOKEN]) 239 Error ("Token too large on line %i\n",scriptline); 240 } 241 script->script_p++; 242 } 243 else // regular token 244 while ( *script->script_p > 32 && *script->script_p != ';') 245 { 246 *token_p++ = *script->script_p++; 247 if (script->script_p == script->end_p) 248 break; 249 if (token_p == &token[MAXTOKEN]) 250 Error ("Token too large on line %i\n",scriptline); 251 } 252 253 *token_p = 0; 254 255 if (!strcmp (token, "$include")) 256 { 257 GetToken (qfalse); 258 AddScriptToStack (token); 259 return GetToken (crossline); 260 } 261 262 return qtrue; 263 } 264 265 266 /* 267 ============== 268 TokenAvailable 269 270 Returns qtrue if there is another token on the line 271 ============== 272 */ 273 qboolean TokenAvailable (void) { 274 int oldLine; 275 qboolean r; 276 277 oldLine = script->line; 278 r = GetToken( qtrue ); 279 if ( !r ) { 280 return qfalse; 281 } 282 UnGetToken(); 283 if ( oldLine == script->line ) { 284 return qtrue; 285 } 286 return qfalse; 287 } 288 289 290 //===================================================================== 291 292 293 void MatchToken( char *match ) { 294 GetToken( qtrue ); 295 296 if ( strcmp( token, match ) ) { 297 Error( "MatchToken( \"%s\" ) failed at line %i", match, scriptline ); 298 } 299 } 300 301 302 void Parse1DMatrix (int x, vec_t *m) { 303 int i; 304 305 MatchToken( "(" ); 306 307 for (i = 0 ; i < x ; i++) { 308 GetToken( qfalse ); 309 m[i] = atof(token); 310 } 311 312 MatchToken( ")" ); 313 } 314 315 void Parse2DMatrix (int y, int x, vec_t *m) { 316 int i; 317 318 MatchToken( "(" ); 319 320 for (i = 0 ; i < y ; i++) { 321 Parse1DMatrix (x, m + i * x); 322 } 323 324 MatchToken( ")" ); 325 } 326 327 void Parse3DMatrix (int z, int y, int x, vec_t *m) { 328 int i; 329 330 MatchToken( "(" ); 331 332 for (i = 0 ; i < z ; i++) { 333 Parse2DMatrix (y, x, m + i * x*y); 334 } 335 336 MatchToken( ")" ); 337 } 338 339 340 void Write1DMatrix (FILE *f, int x, vec_t *m) { 341 int i; 342 343 fprintf (f, "( "); 344 for (i = 0 ; i < x ; i++) { 345 if (m[i] == (int)m[i] ) { 346 fprintf (f, "%i ", (int)m[i]); 347 } else { 348 fprintf (f, "%f ", m[i]); 349 } 350 } 351 fprintf (f, ")"); 352 } 353 354 void Write2DMatrix (FILE *f, int y, int x, vec_t *m) { 355 int i; 356 357 fprintf (f, "( "); 358 for (i = 0 ; i < y ; i++) { 359 Write1DMatrix (f, x, m + i*x); 360 fprintf (f, " "); 361 } 362 fprintf (f, ")\n"); 363 } 364 365 366 void Write3DMatrix (FILE *f, int z, int y, int x, vec_t *m) { 367 int i; 368 369 fprintf (f, "(\n"); 370 for (i = 0 ; i < z ; i++) { 371 Write2DMatrix (f, y, x, m + i*(x*y) ); 372 } 373 fprintf (f, ")\n"); 374 } 375