From 952c5c128f9efaea89d41d882c4ea3ade7df4591 Mon Sep 17 00:00:00 2001 From: zakk Date: Fri, 26 Aug 2005 04:48:05 +0000 Subject: Itsa me, quake3io! git-svn-id: svn://svn.icculus.org/quake3/trunk@2 edf5b092-35ff-0310-97b2-ce42778d08ea --- code/splines/q_parse.cpp | 535 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 535 insertions(+) create mode 100755 code/splines/q_parse.cpp (limited to 'code/splines/q_parse.cpp') diff --git a/code/splines/q_parse.cpp b/code/splines/q_parse.cpp new file mode 100755 index 0000000..4b29ea7 --- /dev/null +++ b/code/splines/q_parse.cpp @@ -0,0 +1,535 @@ +/* +=========================================================================== +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 +=========================================================================== +*/ +// q_parse.c -- support for parsing text files + +#include "q_shared.hpp" + +/* +============================================================================ + +PARSING + +============================================================================ +*/ + +// multiple character punctuation tokens +static const char *punctuation[] = { + "+=", "-=", "*=", "/=", "&=", "|=", "++", "--", + "&&", "||", "<=", ">=", "==", "!=", + NULL +}; + +typedef struct { + char token[MAX_TOKEN_CHARS]; + int lines; + qboolean ungetToken; + char parseFile[MAX_QPATH]; +} parseInfo_t; + +#define MAX_PARSE_INFO 16 +static parseInfo_t parseInfo[MAX_PARSE_INFO]; +static int parseInfoNum; +static parseInfo_t *pi = &parseInfo[0]; + +/* +=================== +Com_BeginParseSession +=================== +*/ +void Com_BeginParseSession( const char *filename ) { + if ( parseInfoNum == MAX_PARSE_INFO - 1 ) { + Com_Error( ERR_FATAL, "Com_BeginParseSession: session overflow" ); + } + parseInfoNum++; + pi = &parseInfo[parseInfoNum]; + + pi->lines = 1; + Q_strncpyz( pi->parseFile, filename, sizeof( pi->parseFile ) ); +} + +/* +=================== +Com_EndParseSession +=================== +*/ +void Com_EndParseSession( void ) { + if ( parseInfoNum == 0 ) { + Com_Error( ERR_FATAL, "Com_EndParseSession: session underflow" ); + } + parseInfoNum--; + pi = &parseInfo[parseInfoNum]; +} + +/* +=================== +Com_GetCurrentParseLine +=================== +*/ +int Com_GetCurrentParseLine( void ) { + return pi->lines; +} + +/* +=================== +Com_ScriptError + +Prints the script name and line number in the message +=================== +*/ +void Com_ScriptError( const char *msg, ... ) { + va_list argptr; + char string[32000]; + + va_start( argptr, msg ); + vsprintf( string, msg,argptr ); + va_end( argptr ); + + Com_Error( ERR_DROP, "File %s, line %i: %s", pi->parseFile, pi->lines, string ); +} + +void Com_ScriptWarning( const char *msg, ... ) { + va_list argptr; + char string[32000]; + + va_start( argptr, msg ); + vsprintf( string, msg,argptr ); + va_end( argptr ); + + Com_Printf( "File %s, line %i: %s", pi->parseFile, pi->lines, string ); +} + + +/* +=================== +Com_UngetToken + +Calling this will make the next Com_Parse return +the current token instead of advancing the pointer +=================== +*/ +void Com_UngetToken( void ) { + if ( pi->ungetToken ) { + Com_ScriptError( "UngetToken called twice" ); + } + pi->ungetToken = qtrue; +} + + +static const char *SkipWhitespace( const char (*data), qboolean *hasNewLines ) { + int c; + + while( (c = *data) <= ' ') { + if( !c ) { + return NULL; + } + if( c == '\n' ) { + pi->lines++; + *hasNewLines = qtrue; + } + data++; + } + + return data; +} + +/* +============== +Com_ParseExt + +Parse a token out of a string +Will never return NULL, just empty strings. +An empty string will only be returned at end of file. + +If "allowLineBreaks" is qtrue then an empty +string will be returned if the next token is +a newline. +============== +*/ +static char *Com_ParseExt( const char *(*data_p), qboolean allowLineBreaks ) { + int c = 0, len; + qboolean hasNewLines = qfalse; + const char *data; + const char **punc; + + if ( !data_p ) { + Com_Error( ERR_FATAL, "Com_ParseExt: NULL data_p" ); + } + + data = *data_p; + len = 0; + pi->token[0] = 0; + + // make sure incoming data is valid + if ( !data ) { + *data_p = NULL; + return pi->token; + } + + // skip any leading whitespace + while ( 1 ) { + // skip whitespace + data = SkipWhitespace( data, &hasNewLines ); + if ( !data ) { + *data_p = NULL; + return pi->token; + } + if ( hasNewLines && !allowLineBreaks ) { + *data_p = data; + return pi->token; + } + + c = *data; + + // skip double slash comments + if ( c == '/' && data[1] == '/' ) { + while (*data && *data != '\n') { + data++; + } + continue; + } + + // skip /* */ comments + if ( c=='/' && data[1] == '*' ) { + while ( *data && ( *data != '*' || data[1] != '/' ) ) { + if( *data == '\n' ) { + pi->lines++; + } + data++; + } + if ( *data ) { + data += 2; + } + continue; + } + + // a real token to parse + break; + } + + // handle quoted strings + if ( c == '\"' ) { + data++; + while( 1 ) { + c = *data++; + if ( ( c=='\\' ) && ( *data == '\"' ) ) { + // allow quoted strings to use \" to indicate the " character + data++; + } else if ( c=='\"' || !c ) { + pi->token[len] = 0; + *data_p = ( char * ) data; + return pi->token; + } else if( *data == '\n' ) { + pi->lines++; + } + if ( len < MAX_TOKEN_CHARS - 1 ) { + pi->token[len] = c; + len++; + } + } + } + + // check for a number + // is this parsing of negative numbers going to cause expression problems + if ( ( c >= '0' && c <= '9' ) || ( c == '-' && data[ 1 ] >= '0' && data[ 1 ] <= '9' ) || + ( c == '.' && data[ 1 ] >= '0' && data[ 1 ] <= '9' ) ) { + do { + + if (len < MAX_TOKEN_CHARS - 1) { + pi->token[len] = c; + len++; + } + data++; + + c = *data; + } while ( ( c >= '0' && c <= '9' ) || c == '.' ); + + // parse the exponent + if ( c == 'e' || c == 'E' ) { + if (len < MAX_TOKEN_CHARS - 1) { + pi->token[len] = c; + len++; + } + data++; + c = *data; + + if ( c == '-' || c == '+' ) { + if (len < MAX_TOKEN_CHARS - 1) { + pi->token[len] = c; + len++; + } + data++; + c = *data; + } + + do { + if (len < MAX_TOKEN_CHARS - 1) { + pi->token[len] = c; + len++; + } + data++; + + c = *data; + } while ( c >= '0' && c <= '9' ); + } + + if (len == MAX_TOKEN_CHARS) { + len = 0; + } + pi->token[len] = 0; + + *data_p = ( char * ) data; + return pi->token; + } + + // check for a regular word + // we still allow forward and back slashes in name tokens for pathnames + // and also colons for drive letters + if ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || c == '_' || c == '/' || c == '\\' ) { + do { + if (len < MAX_TOKEN_CHARS - 1) { + pi->token[len] = c; + len++; + } + data++; + + c = *data; + } while ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || c == '_' + || ( c >= '0' && c <= '9' ) || c == '/' || c == '\\' || c == ':' || c == '.' ); + + if (len == MAX_TOKEN_CHARS) { + len = 0; + } + pi->token[len] = 0; + + *data_p = ( char * ) data; + return pi->token; + } + + // check for multi-character punctuation token + for ( punc = punctuation ; *punc ; punc++ ) { + int l; + int j; + + l = strlen( *punc ); + for ( j = 0 ; j < l ; j++ ) { + if ( data[j] != (*punc)[j] ) { + break; + } + } + if ( j == l ) { + // a valid multi-character punctuation + memcpy( pi->token, *punc, l ); + pi->token[l] = 0; + data += l; + *data_p = (char *)data; + return pi->token; + } + } + + // single character punctuation + pi->token[0] = *data; + pi->token[1] = 0; + data++; + *data_p = (char *)data; + + return pi->token; +} + +/* +=================== +Com_Parse +=================== +*/ +const char *Com_Parse( const char *(*data_p) ) { + if ( pi->ungetToken ) { + pi->ungetToken = qfalse; + return pi->token; + } + return Com_ParseExt( data_p, qtrue ); +} + +/* +=================== +Com_ParseOnLine +=================== +*/ +const char *Com_ParseOnLine( const char *(*data_p) ) { + if ( pi->ungetToken ) { + pi->ungetToken = qfalse; + return pi->token; + } + return Com_ParseExt( data_p, qfalse ); +} + + + +/* +================== +Com_MatchToken +================== +*/ +void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning ) { + const char *token; + + token = Com_Parse( buf_p ); + if ( strcmp( token, match ) ) { + if (warning) { + Com_ScriptWarning( "MatchToken: %s != %s", token, match ); + } else { + Com_ScriptError( "MatchToken: %s != %s", token, match ); + } + } +} + + +/* +================= +Com_SkipBracedSection + +The next token should be an open brace. +Skips until a matching close brace is found. +Internal brace depths are properly skipped. +================= +*/ +void Com_SkipBracedSection( const char *(*program) ) { + const char *token; + int depth; + + depth = 0; + do { + token = Com_Parse( program ); + if( token[1] == 0 ) { + if( token[0] == '{' ) { + depth++; + } + else if( token[0] == '}' ) { + depth--; + } + } + } while( depth && *program ); +} + +/* +================= +Com_SkipRestOfLine +================= +*/ +void Com_SkipRestOfLine ( const char *(*data) ) { + const char *p; + int c; + + p = *data; + while ( (c = *p++) != 0 ) { + if ( c == '\n' ) { + pi->lines++; + break; + } + } + + *data = p; +} + +/* +==================== +Com_ParseRestOfLine +==================== +*/ +const char *Com_ParseRestOfLine( const char *(*data_p) ) { + static char line[MAX_TOKEN_CHARS]; + const char *token; + + line[0] = 0; + while( 1 ) { + token = Com_ParseOnLine( data_p ); + if ( !token[0] ) { + break; + } + if ( line[0] ) { + Q_strcat( line, sizeof(line), " " ); + } + Q_strcat( line, sizeof(line), token ); + } + + return line; +} + + +float Com_ParseFloat( const char *(*buf_p) ) { + const char *token; + + token = Com_Parse( buf_p ); + if ( !token[0] ) { + return 0; + } + return atof( token ); +} + +int Com_ParseInt( const char *(*buf_p) ) { + const char *token; + + token = Com_Parse( buf_p ); + if ( !token[0] ) { + return 0; + } + return atoi( token ); +} + + + +void Com_Parse1DMatrix( const char *(*buf_p), int x, float *m ) { + const char *token; + int i; + + Com_MatchToken( buf_p, "(" ); + + for (i = 0 ; i < x ; i++) { + token = Com_Parse(buf_p); + m[i] = atof(token); + } + + Com_MatchToken( buf_p, ")" ); +} + +void Com_Parse2DMatrix( const char *(*buf_p), int y, int x, float *m ) { + int i; + + Com_MatchToken( buf_p, "(" ); + + for (i = 0 ; i < y ; i++) { + Com_Parse1DMatrix (buf_p, x, m + i * x); + } + + Com_MatchToken( buf_p, ")" ); +} + +void Com_Parse3DMatrix( const char *(*buf_p), int z, int y, int x, float *m ) { + int i; + + Com_MatchToken( buf_p, "(" ); + + for (i = 0 ; i < z ; i++) { + Com_Parse2DMatrix (buf_p, y, x, m + i * x*y); + } + + Com_MatchToken( buf_p, ")" ); +} + -- cgit v1.2.3