Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

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