swh:1:snp:687ac8cdbfab3b78b7f301abee5f451127f135fc
Tip revision: dbe4ddb10315479fc00086f08e25d968b4b43c49 authored by Travis Bradshaw on 31 January 2012, 19:41:34 UTC
The Quake III Arena sources as originally released under the GPL license on August 20, 2005.
The Quake III Arena sources as originally released under the GPL license on August 20, 2005.
Tip revision: dbe4ddb
scriplib.c
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// scriplib.c
#include "cmdlib.h"
#include "scriplib.h"
/*
=============================================================================
PARSING STUFF
=============================================================================
*/
typedef struct
{
char filename[1024];
char *buffer,*script_p,*end_p;
int line;
} script_t;
#define MAX_INCLUDES 8
script_t scriptstack[MAX_INCLUDES];
script_t *script;
int scriptline;
char token[MAXTOKEN];
qboolean endofscript;
qboolean tokenready; // only qtrue if UnGetToken was just called
/*
==============
AddScriptToStack
==============
*/
void AddScriptToStack( const char *filename ) {
int size;
script++;
if (script == &scriptstack[MAX_INCLUDES])
Error ("script file exceeded MAX_INCLUDES");
strcpy (script->filename, ExpandPath (filename) );
size = LoadFile (script->filename, (void **)&script->buffer);
printf ("entering %s\n", script->filename);
script->line = 1;
script->script_p = script->buffer;
script->end_p = script->buffer + size;
}
/*
==============
LoadScriptFile
==============
*/
void LoadScriptFile( const char *filename ) {
script = scriptstack;
AddScriptToStack (filename);
endofscript = qfalse;
tokenready = qfalse;
}
/*
==============
ParseFromMemory
==============
*/
void ParseFromMemory (char *buffer, int size)
{
script = scriptstack;
script++;
if (script == &scriptstack[MAX_INCLUDES])
Error ("script file exceeded MAX_INCLUDES");
strcpy (script->filename, "memory buffer" );
script->buffer = buffer;
script->line = 1;
script->script_p = script->buffer;
script->end_p = script->buffer + size;
endofscript = qfalse;
tokenready = qfalse;
}
/*
==============
UnGetToken
Signals that the current token was not used, and should be reported
for the next GetToken. Note that
GetToken (qtrue);
UnGetToken ();
GetToken (qfalse);
could cross a line boundary.
==============
*/
void UnGetToken (void)
{
tokenready = qtrue;
}
qboolean EndOfScript (qboolean crossline)
{
if (!crossline)
Error ("Line %i is incomplete\n",scriptline);
if (!strcmp (script->filename, "memory buffer"))
{
endofscript = qtrue;
return qfalse;
}
free (script->buffer);
if (script == scriptstack+1)
{
endofscript = qtrue;
return qfalse;
}
script--;
scriptline = script->line;
printf ("returning to %s\n", script->filename);
return GetToken (crossline);
}
/*
==============
GetToken
==============
*/
qboolean GetToken (qboolean crossline)
{
char *token_p;
if (tokenready) // is a token allready waiting?
{
tokenready = qfalse;
return qtrue;
}
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
//
// skip space
//
skipspace:
while (*script->script_p <= 32)
{
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
if (*script->script_p++ == '\n')
{
if (!crossline)
Error ("Line %i is incomplete\n",scriptline);
scriptline = script->line++;
}
}
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
// ; # // comments
if (*script->script_p == ';' || *script->script_p == '#'
|| ( script->script_p[0] == '/' && script->script_p[1] == '/') )
{
if (!crossline)
Error ("Line %i is incomplete\n",scriptline);
while (*script->script_p++ != '\n')
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
scriptline = script->line++;
goto skipspace;
}
// /* */ comments
if (script->script_p[0] == '/' && script->script_p[1] == '*')
{
if (!crossline)
Error ("Line %i is incomplete\n",scriptline);
script->script_p+=2;
while (script->script_p[0] != '*' && script->script_p[1] != '/')
{
if ( *script->script_p == '\n' ) {
scriptline = script->line++;
}
script->script_p++;
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
}
script->script_p += 2;
goto skipspace;
}
//
// copy token
//
token_p = token;
if (*script->script_p == '"')
{
// quoted token
script->script_p++;
while (*script->script_p != '"')
{
*token_p++ = *script->script_p++;
if (script->script_p == script->end_p)
break;
if (token_p == &token[MAXTOKEN])
Error ("Token too large on line %i\n",scriptline);
}
script->script_p++;
}
else // regular token
while ( *script->script_p > 32 && *script->script_p != ';')
{
*token_p++ = *script->script_p++;
if (script->script_p == script->end_p)
break;
if (token_p == &token[MAXTOKEN])
Error ("Token too large on line %i\n",scriptline);
}
*token_p = 0;
if (!strcmp (token, "$include"))
{
GetToken (qfalse);
AddScriptToStack (token);
return GetToken (crossline);
}
return qtrue;
}
/*
==============
TokenAvailable
Returns qtrue if there is another token on the line
==============
*/
qboolean TokenAvailable (void) {
int oldLine;
qboolean r;
oldLine = script->line;
r = GetToken( qtrue );
if ( !r ) {
return qfalse;
}
UnGetToken();
if ( oldLine == script->line ) {
return qtrue;
}
return qfalse;
}
//=====================================================================
void MatchToken( char *match ) {
GetToken( qtrue );
if ( strcmp( token, match ) ) {
Error( "MatchToken( \"%s\" ) failed at line %i", match, scriptline );
}
}
void Parse1DMatrix (int x, vec_t *m) {
int i;
MatchToken( "(" );
for (i = 0 ; i < x ; i++) {
GetToken( qfalse );
m[i] = atof(token);
}
MatchToken( ")" );
}
void Parse2DMatrix (int y, int x, vec_t *m) {
int i;
MatchToken( "(" );
for (i = 0 ; i < y ; i++) {
Parse1DMatrix (x, m + i * x);
}
MatchToken( ")" );
}
void Parse3DMatrix (int z, int y, int x, vec_t *m) {
int i;
MatchToken( "(" );
for (i = 0 ; i < z ; i++) {
Parse2DMatrix (y, x, m + i * x*y);
}
MatchToken( ")" );
}
void Write1DMatrix (FILE *f, int x, vec_t *m) {
int i;
fprintf (f, "( ");
for (i = 0 ; i < x ; i++) {
if (m[i] == (int)m[i] ) {
fprintf (f, "%i ", (int)m[i]);
} else {
fprintf (f, "%f ", m[i]);
}
}
fprintf (f, ")");
}
void Write2DMatrix (FILE *f, int y, int x, vec_t *m) {
int i;
fprintf (f, "( ");
for (i = 0 ; i < y ; i++) {
Write1DMatrix (f, x, m + i*x);
fprintf (f, " ");
}
fprintf (f, ")\n");
}
void Write3DMatrix (FILE *f, int z, int y, int x, vec_t *m) {
int i;
fprintf (f, "(\n");
for (i = 0 ; i < z ; i++) {
Write2DMatrix (f, y, x, m + i*(x*y) );
}
fprintf (f, ")\n");
}