]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - libs/splines/q_parse.cpp
more eol-style
[xonotic/netradiant.git] / libs / splines / q_parse.cpp
index 7709d2ba1cda1460adfa36fb2b289eb15781e812..17fd12ed39825b438ca7cbe26f3f065fa1e7889c 100644 (file)
-/*\r
-Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
-For a list of contributors, see the accompanying CONTRIBUTORS file.\r
-\r
-This file is part of GtkRadiant.\r
-\r
-GtkRadiant is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU General Public License as published by\r
-the Free Software Foundation; either version 2 of the License, or\r
-(at your option) any later version.\r
-\r
-GtkRadiant is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License\r
-along with GtkRadiant; if not, write to the Free Software\r
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
-*/\r
-\r
-// q_parse.c -- support for parsing text files\r
-\r
-#include "q_shared.h"\r
-\r
-/*\r
-============================================================================\r
-\r
-PARSING\r
-\r
-============================================================================\r
-*/\r
-\r
-// multiple character punctuation tokens\r
-static const char *punctuation[] = {\r
-       "+=", "-=",  "*=",  "/=", "&=", "|=", "++", "--",\r
-               "&&", "||",  "<=",  ">=", "==", "!=",\r
-       NULL\r
-};\r
-\r
-typedef struct {\r
-       char    token[MAX_TOKEN_CHARS];\r
-       int             lines;\r
-       qboolean        ungetToken;\r
-       char    parseFile[MAX_QPATH];\r
-} parseInfo_t;\r
-\r
-#define        MAX_PARSE_INFO  16\r
-static parseInfo_t     parseInfo[MAX_PARSE_INFO];\r
-static int                     parseInfoNum;\r
-static parseInfo_t     *pi = &parseInfo[0];\r
-\r
-/*\r
-===================\r
-Com_BeginParseSession\r
-===================\r
-*/\r
-void Com_BeginParseSession( const char *filename ) {\r
-       if ( parseInfoNum == MAX_PARSE_INFO - 1 ) {\r
-               Com_Error( ERR_FATAL, "Com_BeginParseSession: session overflow" );\r
-       }\r
-       parseInfoNum++;\r
-       pi = &parseInfo[parseInfoNum];\r
-\r
-       pi->lines = 1;\r
-       Q_strncpyz( pi->parseFile, filename, sizeof( pi->parseFile ) );\r
-}\r
-\r
-/*\r
-===================\r
-Com_EndParseSession\r
-===================\r
-*/\r
-void Com_EndParseSession( void ) {\r
-       if ( parseInfoNum == 0 ) {\r
-               Com_Error( ERR_FATAL, "Com_EndParseSession: session underflow" );\r
-       }\r
-       parseInfoNum--;\r
-       pi = &parseInfo[parseInfoNum];\r
-}\r
-\r
-/*\r
-===================\r
-Com_GetCurrentParseLine\r
-===================\r
-*/\r
-int Com_GetCurrentParseLine( void ) {\r
-       return pi->lines;\r
-}\r
-\r
-/*\r
-===================\r
-Com_ScriptError\r
-\r
-Prints the script name and line number in the message\r
-===================\r
-*/\r
-void Com_ScriptError( const char *msg, ... ) {\r
-       va_list         argptr;\r
-       char            string[32000];\r
-\r
-       va_start( argptr, msg );\r
-       vsprintf( string, msg,argptr );\r
-       va_end( argptr );\r
-\r
-       Com_Error( ERR_DROP, "File %s, line %i: %s", pi->parseFile, pi->lines, string );\r
-}\r
-\r
-void Com_ScriptWarning( const char *msg, ... ) {\r
-       va_list         argptr;\r
-       char            string[32000];\r
-\r
-       va_start( argptr, msg );\r
-       vsprintf( string, msg,argptr );\r
-       va_end( argptr );\r
-\r
-       Com_Printf( "File %s, line %i: %s", pi->parseFile, pi->lines, string );\r
-}\r
-\r
-\r
-/*\r
-===================\r
-Com_UngetToken\r
-\r
-Calling this will make the next Com_Parse return\r
-the current token instead of advancing the pointer\r
-===================\r
-*/\r
-void Com_UngetToken( void ) {\r
-       if ( pi->ungetToken ) {\r
-               Com_ScriptError( "UngetToken called twice" );\r
-       }\r
-       pi->ungetToken = qtrue;\r
-}\r
-\r
-\r
-static const char *SkipWhitespace( const char (*data), qboolean *hasNewLines ) {\r
-       int c;\r
-\r
-       while( (c = *data) <= ' ') {\r
-               if( !c ) {\r
-                       return NULL;\r
-               }\r
-               if( c == '\n' ) {\r
-                       pi->lines++;\r
-                       *hasNewLines = qtrue;\r
-               }\r
-               data++;\r
-       }\r
-\r
-       return data;\r
-}\r
-\r
-/*\r
-==============\r
-Com_ParseExt\r
-\r
-Parse a token out of a string\r
-Will never return NULL, just empty strings.\r
-An empty string will only be returned at end of file.\r
-\r
-If "allowLineBreaks" is qtrue then an empty\r
-string will be returned if the next token is\r
-a newline.\r
-==============\r
-*/\r
-static char *Com_ParseExt( const char *(*data_p), qboolean allowLineBreaks ) {\r
-       int c = 0, len;\r
-       qboolean hasNewLines = qfalse;\r
-       const char *data;\r
-       const char **punc;\r
-\r
-       if ( !data_p ) {\r
-               Com_Error( ERR_FATAL, "Com_ParseExt: NULL data_p" );\r
-       }\r
-\r
-       data = *data_p;\r
-       len = 0;\r
-       pi->token[0] = 0;\r
-\r
-       // make sure incoming data is valid\r
-       if ( !data ) {\r
-               *data_p = NULL;\r
-               return pi->token;\r
-       }\r
-\r
-       // skip any leading whitespace\r
-       while ( 1 ) {\r
-               // skip whitespace\r
-               data = SkipWhitespace( data, &hasNewLines );\r
-               if ( !data ) {\r
-                       *data_p = NULL;\r
-                       return pi->token;\r
-               }\r
-               if ( hasNewLines && !allowLineBreaks ) {\r
-                       *data_p = data;\r
-                       return pi->token;\r
-               }\r
-\r
-               c = *data;\r
-\r
-               // skip double slash comments\r
-               if ( c == '/' && data[1] == '/' ) {\r
-                       while (*data && *data != '\n') {\r
-                               data++;\r
-                       }\r
-                       continue;\r
-               }\r
-\r
-               // skip /* */ comments\r
-               if ( c=='/' && data[1] == '*' ) {\r
-                       while ( *data && ( *data != '*' || data[1] != '/' ) ) {\r
-                               if( *data == '\n' ) {\r
-                                       pi->lines++;\r
-                               }\r
-                               data++;\r
-                       }\r
-                       if ( *data ) {\r
-                               data += 2;\r
-                       }\r
-                       continue;\r
-               }\r
-\r
-               // a real token to parse\r
-               break;\r
-       }\r
-\r
-       // handle quoted strings\r
-       if ( c == '\"' ) {\r
-               data++;\r
-               while( 1 ) {\r
-                       c = *data++;\r
-                       if ( ( c=='\\' ) && ( *data == '\"' ) ) {\r
-                               // allow quoted strings to use \" to indicate the " character\r
-                               data++;\r
-                       } else if ( c=='\"' || !c ) {\r
-                               pi->token[len] = 0;\r
-                               *data_p = ( char * ) data;\r
-                               return pi->token;\r
-                       } else if( *data == '\n' ) {\r
-                               pi->lines++;\r
-                       }\r
-                       if ( len < MAX_TOKEN_CHARS - 1 ) {\r
-                               pi->token[len] = c;\r
-                               len++;\r
-                       }\r
-               }\r
-       }\r
-\r
-       // check for a number\r
-       // is this parsing of negative numbers going to cause expression problems\r
-       if ( ( c >= '0' && c <= '9' ) || ( c == '-' && data[ 1 ] >= '0' && data[ 1 ] <= '9' ) || \r
-               ( c == '.' && data[ 1 ] >= '0' && data[ 1 ] <= '9' ) ) {\r
-               do  {\r
-\r
-                       if (len < MAX_TOKEN_CHARS - 1) {\r
-                               pi->token[len] = c;\r
-                               len++;\r
-                       }\r
-                       data++;\r
-\r
-                       c = *data;\r
-               } while ( ( c >= '0' && c <= '9' ) || c == '.' );\r
-\r
-               // parse the exponent\r
-               if ( c == 'e' || c == 'E' ) {\r
-                       if (len < MAX_TOKEN_CHARS - 1) {\r
-                               pi->token[len] = c;\r
-                               len++;\r
-                       }\r
-                       data++;\r
-                       c = *data;\r
-\r
-                       if ( c == '-' || c == '+' ) {\r
-                               if (len < MAX_TOKEN_CHARS - 1) {\r
-                                       pi->token[len] = c;\r
-                                       len++;\r
-                               }\r
-                               data++;\r
-                               c = *data;\r
-                       }\r
-\r
-                       do  {\r
-                               if (len < MAX_TOKEN_CHARS - 1) {\r
-                                       pi->token[len] = c;\r
-                                       len++;\r
-                               }\r
-                               data++;\r
-\r
-                               c = *data;\r
-                       } while ( c >= '0' && c <= '9' );\r
-               }\r
-\r
-               if (len == MAX_TOKEN_CHARS) {\r
-                       len = 0;\r
-               }\r
-               pi->token[len] = 0;\r
-\r
-               *data_p = ( char * ) data;\r
-               return pi->token;\r
-       }\r
-\r
-       // check for a regular word\r
-       // we still allow forward and back slashes in name tokens for pathnames\r
-       // and also colons for drive letters\r
-       if ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || c == '_' || c == '/' || c == '\\' ) {\r
-               do  {\r
-                       if (len < MAX_TOKEN_CHARS - 1) {\r
-                               pi->token[len] = c;\r
-                               len++;\r
-                       }\r
-                       data++;\r
-\r
-                       c = *data;\r
-               } while ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || c == '_' \r
-                       || ( c >= '0' && c <= '9' ) || c == '/' || c == '\\' || c == ':' || c == '.' );\r
-\r
-               if (len == MAX_TOKEN_CHARS) {\r
-                       len = 0;\r
-               }\r
-               pi->token[len] = 0;\r
-\r
-               *data_p = ( char * ) data;\r
-               return pi->token;\r
-       }\r
-\r
-       // check for multi-character punctuation token\r
-       for ( punc = punctuation ; *punc ; punc++ ) {\r
-               int             l;\r
-               int             j;\r
-\r
-               l = strlen( *punc );\r
-               for ( j = 0 ; j < l ; j++ ) {\r
-                       if ( data[j] != (*punc)[j] ) {\r
-                               break;\r
-                       }\r
-               }\r
-               if ( j == l ) {\r
-                       // a valid multi-character punctuation\r
-                       memcpy( pi->token, *punc, l );\r
-                       pi->token[l] = 0;\r
-                       data += l;\r
-                       *data_p = (char *)data;\r
-                       return pi->token;\r
-               }\r
-       }\r
-\r
-       // single character punctuation\r
-       pi->token[0] = *data;\r
-       pi->token[1] = 0;\r
-       data++;\r
-       *data_p = (char *)data;\r
-\r
-       return pi->token;\r
-}\r
-\r
-/*\r
-===================\r
-Com_Parse\r
-===================\r
-*/\r
-const char *Com_Parse( const char *(*data_p) ) {\r
-       if ( pi->ungetToken ) {\r
-               pi->ungetToken = qfalse;\r
-               return pi->token;\r
-       }\r
-       return Com_ParseExt( data_p, qtrue );\r
-}\r
-\r
-/*\r
-===================\r
-Com_ParseOnLine\r
-===================\r
-*/\r
-const char *Com_ParseOnLine( const char *(*data_p) ) {\r
-       if ( pi->ungetToken ) {\r
-               pi->ungetToken = qfalse;\r
-               return pi->token;\r
-       }\r
-       return Com_ParseExt( data_p, qfalse );\r
-}\r
-\r
-\r
-\r
-/*\r
-==================\r
-Com_MatchToken\r
-==================\r
-*/\r
-void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning ) {\r
-       const char      *token;\r
-\r
-       token = Com_Parse( buf_p );\r
-       if ( strcmp( token, match ) ) {\r
-               if (warning) {\r
-                       Com_ScriptWarning( "MatchToken: %s != %s", token, match );\r
-               } else {\r
-                       Com_ScriptError( "MatchToken: %s != %s", token, match );\r
-               }\r
-       }\r
-}\r
-\r
-\r
-/*\r
-=================\r
-Com_SkipBracedSection\r
-\r
-The next token should be an open brace.\r
-Skips until a matching close brace is found.\r
-Internal brace depths are properly skipped.\r
-=================\r
-*/\r
-void Com_SkipBracedSection( const char *(*program) ) {\r
-       const char                      *token;\r
-       int                             depth;\r
-\r
-       depth = 0;\r
-       do {\r
-               token = Com_Parse( program );\r
-               if( token[1] == 0 ) {\r
-                       if( token[0] == '{' ) {\r
-                               depth++;\r
-                       }\r
-                       else if( token[0] == '}' ) {\r
-                               depth--;\r
-                       }\r
-               }\r
-       } while( depth && *program );\r
-}\r
-\r
-/*\r
-=================\r
-Com_SkipRestOfLine\r
-=================\r
-*/\r
-void Com_SkipRestOfLine ( const char *(*data) ) {\r
-       const char      *p;\r
-       int             c;\r
-\r
-       p = *data;\r
-       while ( (c = *p++) != 0 ) {\r
-               if ( c == '\n' ) {\r
-                       pi->lines++;\r
-                       break;\r
-               }\r
-       }\r
-\r
-       *data = p;\r
-}\r
-\r
-/*\r
-====================\r
-Com_ParseRestOfLine\r
-====================\r
-*/\r
-const char *Com_ParseRestOfLine( const char *(*data_p) ) {\r
-       static char     line[MAX_TOKEN_CHARS];\r
-       const char *token;\r
-\r
-       line[0] = 0;\r
-       while( 1 ) {\r
-               token = Com_ParseOnLine( data_p );\r
-               if ( !token[0] ) {\r
-                       break;\r
-               }\r
-               if ( line[0] ) {\r
-                       Q_strcat( line, sizeof(line), " " );\r
-               }\r
-               Q_strcat( line, sizeof(line), token );\r
-       }\r
-\r
-       return line;\r
-}\r
-\r
-\r
-float Com_ParseFloat( const char *(*buf_p) ) {\r
-       const char              *token;\r
-\r
-       token = Com_Parse( buf_p );\r
-       if ( !token[0] ) {\r
-               return 0;\r
-       }\r
-       return atof( token );\r
-}\r
-\r
-int Com_ParseInt( const char *(*buf_p) ) {\r
-       const char              *token;\r
-\r
-       token = Com_Parse( buf_p );\r
-       if ( !token[0] ) {\r
-               return 0;\r
-       }\r
-       return (int)atof( token );\r
-}\r
-\r
-\r
-\r
-void Com_Parse1DMatrix( const char *(*buf_p), int x, float *m ) {\r
-       const char      *token;\r
-       int             i;\r
-\r
-       Com_MatchToken( buf_p, "(" );\r
-\r
-       for (i = 0 ; i < x ; i++) {\r
-               token = Com_Parse(buf_p);\r
-               m[i] = atof(token);\r
-       }\r
-\r
-       Com_MatchToken( buf_p, ")" );\r
-}\r
-\r
-void Com_Parse2DMatrix( const char *(*buf_p), int y, int x, float *m ) {\r
-       int             i;\r
-\r
-       Com_MatchToken( buf_p, "(" );\r
-\r
-       for (i = 0 ; i < y ; i++) {\r
-               Com_Parse1DMatrix (buf_p, x, m + i * x);\r
-       }\r
-\r
-       Com_MatchToken( buf_p, ")" );\r
-}\r
-\r
-void Com_Parse3DMatrix( const char *(*buf_p), int z, int y, int x, float *m ) {\r
-       int             i;\r
-\r
-       Com_MatchToken( buf_p, "(" );\r
-\r
-       for (i = 0 ; i < z ; i++) {\r
-               Com_Parse2DMatrix (buf_p, y, x, m + i * x*y);\r
-       }\r
-\r
-       Com_MatchToken( buf_p, ")" );\r
-}\r
-\r
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; 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.h"
+
+/*
+============================================================================
+
+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 (int)atof( 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, ")" );
+}
+