From f56bb35301836e56582a575a75864392a0177875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Mon, 2 Dec 2013 19:31:46 -0800 Subject: Fix line endings. WHAMMY. --- mp/src/utils/common/scriplib.cpp | 2698 +++++++++++++++++++------------------- 1 file changed, 1349 insertions(+), 1349 deletions(-) (limited to 'mp/src/utils/common/scriplib.cpp') diff --git a/mp/src/utils/common/scriplib.cpp b/mp/src/utils/common/scriplib.cpp index 469c7885..1c8b47f8 100644 --- a/mp/src/utils/common/scriplib.cpp +++ b/mp/src/utils/common/scriplib.cpp @@ -1,1349 +1,1349 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -// scriplib.c - -#include "tier1/strtools.h" -#include "tier2/tier2.h" -#include "cmdlib.h" -#include "scriplib.h" -#if defined( _X360 ) -#include "xbox\xbox_win32stubs.h" -#endif -#if defined(POSIX) -#include "../../filesystem/linux_support.h" -#include -#endif -/* -============================================================================= - - PARSING STUFF - -============================================================================= -*/ - -typedef struct -{ - char filename[1024]; - char *buffer,*script_p,*end_p; - int line; - - char macrobuffer[4096]; - char *macroparam[64]; - char *macrovalue[64]; - int nummacroparams; - -} script_t; - -#define MAX_INCLUDES 64 -script_t scriptstack[MAX_INCLUDES]; -script_t *script = NULL; -int scriptline; - -char token[MAXTOKEN]; -qboolean endofscript; -qboolean tokenready; // only true if UnGetToken was just called - -typedef struct -{ - char *param; - char *value; -} variable_t; - -CUtlVector g_definevariable; - -/* -Callback stuff -*/ - -void DefaultScriptLoadedCallback( char const *pFilenameLoaded, char const *pIncludedFromFileName, int nIncludeLineNumber ) -{ - NULL; -} - -SCRIPT_LOADED_CALLBACK g_pfnCallback = DefaultScriptLoadedCallback; - -SCRIPT_LOADED_CALLBACK SetScriptLoadedCallback( SCRIPT_LOADED_CALLBACK pfnNewScriptLoadedCallback ) -{ - SCRIPT_LOADED_CALLBACK pfnCallback = g_pfnCallback; - g_pfnCallback = pfnNewScriptLoadedCallback; - return pfnCallback; -} - -/* -============== -AddScriptToStack -============== -*/ -void AddScriptToStack (char *filename, ScriptPathMode_t pathMode = SCRIPT_USE_ABSOLUTE_PATH) -{ - int size; - - script++; - if (script == &scriptstack[MAX_INCLUDES]) - Error ("script file exceeded MAX_INCLUDES"); - - if ( pathMode == SCRIPT_USE_RELATIVE_PATH ) - Q_strncpy( script->filename, filename, sizeof( script->filename ) ); - else - Q_strncpy (script->filename, ExpandPath (filename), sizeof( script->filename ) ); - - size = LoadFile (script->filename, (void **)&script->buffer); - - // printf ("entering %s\n", script->filename); - if ( g_pfnCallback ) - { - if ( script == scriptstack + 1 ) - g_pfnCallback( script->filename, NULL, 0 ); - else - g_pfnCallback( script->filename, script[-1].filename, script[-1].line ); - } - - script->line = 1; - - script->script_p = script->buffer; - script->end_p = script->buffer + size; -} - - -/* -============== -LoadScriptFile -============== -*/ -void LoadScriptFile (char *filename, ScriptPathMode_t pathMode) -{ - script = scriptstack; - AddScriptToStack (filename, pathMode); - - endofscript = false; - tokenready = false; -} - - -/* -============== -============== -*/ - -script_t *macrolist[256]; -int nummacros; - -void DefineMacro( char *macroname ) -{ - script_t *pmacro = (script_t *)malloc( sizeof( script_t ) ); - - strcpy( pmacro->filename, macroname ); - pmacro->line = script->line; - pmacro->nummacroparams = 0; - - char *mp = pmacro->macrobuffer; - char *cp = script->script_p; - - while (TokenAvailable( )) - { - GetToken( false ); - - if (token[0] == '\\' && token[1] == '\\') - { - break; - } - cp = script->script_p; - - pmacro->macroparam[pmacro->nummacroparams++] = mp; - - strcpy( mp, token ); - mp += strlen( token ) + 1; - - if (mp >= pmacro->macrobuffer + sizeof( pmacro->macrobuffer )) - Error("Macro buffer overflow\n"); - } - // roll back script_p to previous valid location - script->script_p = cp; - - // find end of macro def - while (*cp && *cp != '\n') - { - //Msg("%d ", *cp ); - if (*cp == '\\' && *(cp+1) == '\\') - { - // skip till end of line - while (*cp && *cp != '\n') - { - *cp = ' '; // replace with spaces - cp++; - } - - if (*cp) - { - cp++; - } - } - else - { - cp++; - } - } - - int size = (cp - script->script_p); - - pmacro->buffer = (char *)malloc( size + 1); - memcpy( pmacro->buffer, script->script_p, size ); - pmacro->buffer[size] = '\0'; - pmacro->end_p = &pmacro->buffer[size]; - - macrolist[nummacros++] = pmacro; - - script->script_p = cp; -} - - -void DefineVariable( char *variablename ) -{ - variable_t v; - - v.param = strdup( variablename ); - - GetToken( false ); - - v.value = strdup( token ); - - g_definevariable.AddToTail( v ); -} - - - -/* -============== -============== -*/ -bool AddMacroToStack( char *macroname ) -{ - // lookup macro - if (macroname[0] != '$') - return false; - - int i; - for (i = 0; i < nummacros; i++) - { - if (strcmpi( macrolist[i]->filename, ¯oname[1] ) == 0) - { - break; - } - } - if (i == nummacros) - return false; - - script_t *pmacro = macrolist[i]; - - // get tokens - script_t *pnext = script + 1; - - pnext++; - if (pnext == &scriptstack[MAX_INCLUDES]) - Error ("script file exceeded MAX_INCLUDES"); - - // get tokens - char *cp = pnext->macrobuffer; - - pnext->nummacroparams = pmacro->nummacroparams; - - for (i = 0; i < pnext->nummacroparams; i++) - { - GetToken(false); - - strcpy( cp, token ); - pnext->macroparam[i] = pmacro->macroparam[i]; - pnext->macrovalue[i] = cp; - - cp += strlen( token ) + 1; - - if (cp >= pnext->macrobuffer + sizeof( pnext->macrobuffer )) - Error("Macro buffer overflow\n"); - } - - script = pnext; - strcpy( script->filename, pmacro->filename ); - - int size = pmacro->end_p - pmacro->buffer; - script->buffer = (char *)malloc( size + 1 ); - memcpy( script->buffer, pmacro->buffer, size ); - pmacro->buffer[size] = '\0'; - script->script_p = script->buffer; - script->end_p = script->buffer + size; - script->line = pmacro->line; - - return true; -} - - - -bool ExpandMacroToken( char *&token_p ) -{ - if ( script->nummacroparams && *script->script_p == '$' ) - { - char *cp = script->script_p + 1; - - while ( *cp > 32 && *cp != '$' ) - { - cp++; - } - - // found a word with $'s on either end? - if (*cp != '$') - return false; - - // get token pointer - char *tp = script->script_p + 1; - int len = (cp - tp); - *(tp + len) = '\0'; - - // lookup macro parameter - int index = 0; - for (index = 0; index < script->nummacroparams; index++) - { - if (stricmp( script->macroparam[index], tp ) == 0) - break; - } - if (index >= script->nummacroparams) - { - Error("unknown macro token \"%s\" in %s\n", tp, script->filename ); - } - - // paste token into - len = strlen( script->macrovalue[index] ); - strcpy( token_p, script->macrovalue[index] ); - token_p += len; - - script->script_p = cp + 1; - - if (script->script_p >= script->end_p) - Error ("Macro expand overflow\n"); - - if (token_p >= &token[MAXTOKEN]) - Error ("Token too large on line %i\n",scriptline); - - return true; - } - return false; -} - - - -/* -============== -============== -*/ -// FIXME: this should create a new script context so the individual tokens in the variable can be parsed -bool ExpandVariableToken( char *&token_p ) -{ - if ( *script->script_p == '$' ) - { - char *cp = script->script_p + 1; - - while ( *cp > 32 && *cp != '$' ) - { - cp++; - } - - // found a word with $'s on either end? - if (*cp != '$') - return false; - - // get token pointer - char *tp = script->script_p + 1; - int len = (cp - tp); - *(tp + len) = '\0'; - - // lookup macro parameter - - int index; - for (index = 0; index < g_definevariable.Count(); index++) - { - if (Q_strnicmp( g_definevariable[index].param, tp, len ) == 0) - break; - } - - if (index >= g_definevariable.Count() ) - { - Error("unknown variable token \"%s\" in %s\n", tp, script->filename ); - } - - // paste token into - len = strlen( g_definevariable[index].value ); - strcpy( token_p, g_definevariable[index].value ); - token_p += len; - - script->script_p = cp + 1; - - if (script->script_p >= script->end_p) - Error ("Macro expand overflow\n"); - - if (token_p >= &token[MAXTOKEN]) - Error ("Token too large on line %i\n",scriptline); - - return true; - } - return false; -} - - - -/* -============== -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 = false; - tokenready = false; -} - - -//----------------------------------------------------------------------------- -// Used instead of ParseFromMemory to temporarily add a memory buffer -// to the script stack. ParseFromMemory just blows away the stack. -//----------------------------------------------------------------------------- -void PushMemoryScript( char *pszBuffer, const int nSize ) -{ - if ( script == NULL ) - { - script = scriptstack; - } - script++; - if ( script == &scriptstack[MAX_INCLUDES] ) - { - Error ( "script file exceeded MAX_INCLUDES" ); - } - strcpy (script->filename, "memory buffer" ); - - script->buffer = pszBuffer; - script->line = 1; - script->script_p = script->buffer; - script->end_p = script->buffer + nSize; - - endofscript = false; - tokenready = false; -} - - -//----------------------------------------------------------------------------- -// Used after calling PushMemoryScript to clean up the memory buffer -// added to the script stack. The normal end of script terminates -// all parsing at the end of a memory buffer even if there are more scripts -// remaining on the script stack -//----------------------------------------------------------------------------- -bool PopMemoryScript() -{ - if ( V_stricmp( script->filename, "memory buffer" ) ) - return false; - - if ( script == scriptstack ) - { - endofscript = true; - return false; - } - script--; - scriptline = script->line; - - endofscript = false; - - return true; -} - - -/* -============== -UnGetToken - -Signals that the current token was not used, and should be reported -for the next GetToken. Note that - -GetToken (true); -UnGetToken (); -GetToken (false); - -could cross a line boundary. -============== -*/ -void UnGetToken (void) -{ - tokenready = true; -} - - -qboolean EndOfScript (qboolean crossline) -{ - if (!crossline) - Error ("Line %i is incomplete\n",scriptline); - - if (!strcmp (script->filename, "memory buffer")) - { - endofscript = true; - return false; - } - - free (script->buffer); - script->buffer = NULL; - if (script == scriptstack+1) - { - endofscript = true; - return false; - } - script--; - scriptline = script->line; - // printf ("returning to %s\n", script->filename); - return GetToken (crossline); -} - - -//----------------------------------------------------------------------------- -// Purpose: Given an absolute path, do a find first find next on it and build -// a list of files. Physical file system only -//----------------------------------------------------------------------------- -static void FindFileAbsoluteList( CUtlVector< CUtlString > &outAbsolutePathNames, const char *pszFindName ) -{ - char szPath[MAX_PATH]; - V_strncpy( szPath, pszFindName, sizeof( szPath ) ); - V_StripFilename( szPath ); - - char szResult[MAX_PATH]; - FileFindHandle_t hFile = FILESYSTEM_INVALID_FIND_HANDLE; - - for ( const char *pszFoundFile = g_pFullFileSystem->FindFirst( pszFindName, &hFile ); pszFoundFile && hFile != FILESYSTEM_INVALID_FIND_HANDLE; pszFoundFile = g_pFullFileSystem->FindNext( hFile ) ) - { - V_ComposeFileName( szPath, pszFoundFile, szResult, sizeof( szResult ) ); - outAbsolutePathNames.AddToTail( szResult ); - } - - g_pFullFileSystem->FindClose( hFile ); -} - - -//----------------------------------------------------------------------------- -// Data for checking for single character tokens while parsing -//----------------------------------------------------------------------------- -bool g_bCheckSingleCharTokens = false; -CUtlString g_sSingleCharTokens; - - -//----------------------------------------------------------------------------- -// Sets whether the scriplib parser will do a special check for single -// character tokens. Returns previous state of whether single character -// tokens will be checked. -//----------------------------------------------------------------------------- -bool SetCheckSingleCharTokens( bool bCheck ) -{ - const bool bRetVal = g_bCheckSingleCharTokens; - - g_bCheckSingleCharTokens = bCheck; - - return bRetVal; -} - - -//----------------------------------------------------------------------------- -// Sets the list of single character tokens to check if SetCheckSingleCharTokens -// is turned on. -//----------------------------------------------------------------------------- -CUtlString SetSingleCharTokenList( const char *pszSingleCharTokenList ) -{ - const CUtlString sRetVal = g_sSingleCharTokens; - - if ( pszSingleCharTokenList ) - { - g_sSingleCharTokens = pszSingleCharTokenList; - } - - return sRetVal; -} - - -/* -============== -GetToken -============== -*/ -qboolean GetToken (qboolean crossline) -{ - char *token_p; - - if (tokenready) // is a token allready waiting? - { - tokenready = false; - return true; - } - - // printf("script_p %x (%x)\n", script->script_p, script->end_p ); fflush( stdout ); - - if (script->script_p >= script->end_p) - { - return EndOfScript (crossline); - } - - tokenready = false; - - // skip space, ctrl chars -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); - } - - // strip single line comments - if (*script->script_p == ';' || *script->script_p == '#' || // semicolon and # is comment field - (*script->script_p == '/' && *((script->script_p)+1) == '/')) // also make // a comment field - { - 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; - } - - // strip out matching /* */ comments - if (*script->script_p == '/' && *((script->script_p)+1) == '*') - { - script->script_p += 2; - while (*script->script_p != '*' || *((script->script_p)+1) != '/') - { - if (*script->script_p++ != '\n') - { - if (script->script_p >= script->end_p) - { - return EndOfScript (crossline); - } - - scriptline = ++script->line; - } - } - script->script_p += 2; - goto skipspace; - } - - // copy token to buffer - 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 if ( g_bCheckSingleCharTokens && !g_sSingleCharTokens.IsEmpty() && strchr( g_sSingleCharTokens.String(), *script->script_p ) != NULL ) - { - *token_p++ = *script->script_p++; - } - else // regular token - while ( *script->script_p > 32 && *script->script_p != ';') - { - if ( !ExpandMacroToken( token_p ) ) - { - if ( !ExpandVariableToken( token_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); - - } - } - } - - // add null to end of token - *token_p = 0; - - // check for other commands - if ( !stricmp( token, "$include" ) ) - { - GetToken( false ); - - bool bFallbackToToken = true; - - CUtlVector< CUtlString > expandedPathList; - - if ( CmdLib_ExpandWithBasePaths( expandedPathList, token ) > 0 ) - { - for ( int i = 0; i < expandedPathList.Count(); ++i ) - { - CUtlVector< CUtlString > findFileList; - FindFileAbsoluteList( findFileList, expandedPathList[i].String() ); - - if ( findFileList.Count() > 0 ) - { - bFallbackToToken = false; - - // Only add the first set of glob matches from the first base path - for ( int j = 0; j < findFileList.Count(); ++j ) - { - AddScriptToStack( const_cast< char * >( findFileList[j].String() ) ); - } - - break; - } - } - } - - if ( bFallbackToToken ) - { - AddScriptToStack( token ); - } - - return GetToken( crossline ); - } - else if (!stricmp (token, "$definemacro")) - { - GetToken (false); - DefineMacro(token); - return GetToken (crossline); - } - else if (!stricmp (token, "$definevariable")) - { - GetToken (false); - DefineVariable(token); - return GetToken (crossline); - } - else if (AddMacroToStack( token )) - { - return GetToken (crossline); - } - - return true; -} - - -/* -============== -GetExprToken - use C mathematical operator parsing rules to split tokens instead of whitespace -============== -*/ -qboolean GetExprToken (qboolean crossline) -{ - char *token_p; - - if (tokenready) // is a token allready waiting? - { - tokenready = false; - return true; - } - - if (script->script_p >= script->end_p) - return EndOfScript (crossline); - - tokenready = false; - -// -// 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); - - if (*script->script_p == ';' || *script->script_p == '#' || // semicolon and # is comment field - (*script->script_p == '/' && *((script->script_p)+1) == '/')) // also make // a comment field - { - if (!crossline) - Error ("Line %i is incomplete\n",scriptline); - while (*script->script_p++ != '\n') - if (script->script_p >= script->end_p) - return EndOfScript (crossline); - 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 - { - if ( V_isalpha( *script->script_p ) || *script->script_p == '_' ) - { - // regular token - while ( V_isalnum( *script->script_p ) || *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); - } - } - else if ( V_isdigit( *script->script_p ) || *script->script_p == '.' ) - { - // regular token - while ( V_isdigit( *script->script_p ) || *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); - } - } - else - { - // single char - *token_p++ = *script->script_p++; - } - } - - *token_p = 0; - - if (!stricmp (token, "$include")) - { - GetToken (false); - AddScriptToStack (token); - return GetToken (crossline); - } - - return true; -} - - -/* -============== -TokenAvailable - -Returns true if there is another token on the line -============== -*/ -qboolean TokenAvailable (void) -{ - char *search_p; - - if (tokenready) // is a token allready waiting? - { - return true; - } - - search_p = script->script_p; - - if (search_p >= script->end_p) - return false; - - while ( *search_p <= 32) - { - if (*search_p == '\n') - return false; - search_p++; - if (search_p == script->end_p) - return false; - - } - - if (*search_p == ';' || *search_p == '#' || // semicolon and # is comment field - (*search_p == '/' && *((search_p)+1) == '/')) // also make // a comment field - return false; - - return true; -} - -qboolean GetTokenizerStatus( char **pFilename, int *pLine ) -{ - // is this the default state? - if (!script) - return false; - - if (script->script_p >= script->end_p) - return false; - - if (pFilename) - { - *pFilename = script->filename; - } - if (pLine) - { - *pLine = script->line; - } - return true; -} - - -#include -#include -#ifdef WIN32 -#include -#include -#include -#endif -#include -#include -#include -#include -#include "tier1/utlbuffer.h" - -class CScriptLib : public IScriptLib -{ -public: - virtual bool ReadFileToBuffer( const char *pSourceName, CUtlBuffer &buffer, bool bText = false, bool bNoOpenFailureWarning = false ); - virtual bool WriteBufferToFile( const char *pTargetName, CUtlBuffer &buffer, DiskWriteMode_t writeMode ); - virtual int FindFiles( char* pFileMask, bool bRecurse, CUtlVector &fileList ); - virtual char *MakeTemporaryFilename( char const *pchModPath, char *pPath, int pathSize ); - virtual void DeleteTemporaryFiles( const char *pFileMask ); - virtual int CompareFileTime( const char *pFilenameA, const char *pFilenameB ); - virtual bool DoesFileExist( const char *pFilename ); - -private: - - int GetFileList( const char* pDirPath, const char* pPattern, CUtlVector< fileList_t > &fileList ); - void RecurseFileTree_r( const char* pDirPath, int depth, CUtlVector< CUtlString > &dirList ); -}; - -static CScriptLib g_ScriptLib; -IScriptLib *scriptlib = &g_ScriptLib; -IScriptLib *g_pScriptLib = &g_ScriptLib; - -//----------------------------------------------------------------------------- -// Existence check -//----------------------------------------------------------------------------- -bool CScriptLib::DoesFileExist( const char *pFilename ) -{ - return g_pFullFileSystem->FileExists( pFilename ); -} - -//----------------------------------------------------------------------------- -// Purpose: Helper utility, read file into buffer -//----------------------------------------------------------------------------- -bool CScriptLib::ReadFileToBuffer( const char *pSourceName, CUtlBuffer &buffer, bool bText, bool bNoOpenFailureWarning ) -{ - bool bSuccess = true; - - if ( !g_pFullFileSystem->ReadFile( pSourceName, NULL, buffer ) ) - { - if ( !bNoOpenFailureWarning ) - { - Msg( "ReadFileToBuffer(): Error opening %s: %s\n", pSourceName, strerror( errno ) ); - } - return false; - } - - if ( bText ) - { - // force it into text mode - buffer.SetBufferType( true, true ); - } - else - { - buffer.SetBufferType( false, false ); - } - - return bSuccess; -} - -//----------------------------------------------------------------------------- -// Purpose: Helper utility, Write buffer to file -//----------------------------------------------------------------------------- -bool CScriptLib::WriteBufferToFile( const char *pTargetName, CUtlBuffer &buffer, DiskWriteMode_t writeMode ) -{ - char* ptr; - char dirPath[MAX_PATH]; - - bool bSuccess = true; - - // create path - // prime and skip to first seperator - strcpy( dirPath, pTargetName ); - ptr = strchr( dirPath, '\\' ); - while ( ptr ) - { - ptr = strchr( ptr+1, '\\' ); - if ( ptr ) - { - *ptr = '\0'; - _mkdir( dirPath ); - *ptr = '\\'; - } - } - - bool bDoWrite = false; - if ( writeMode == WRITE_TO_DISK_ALWAYS ) - { - bDoWrite = true; - } - else if ( writeMode == WRITE_TO_DISK_UPDATE ) - { - if ( DoesFileExist( pTargetName ) ) - { - bDoWrite = true; - } - } - - if ( bDoWrite ) - { - bSuccess = g_pFullFileSystem->WriteFile( pTargetName, NULL, buffer ); - } - - return bSuccess; -} - -//----------------------------------------------------------------------------- -// Returns -1, 0, or 1. -//----------------------------------------------------------------------------- -int CScriptLib::CompareFileTime( const char *pFilenameA, const char *pFilenameB ) -{ - int timeA = g_pFullFileSystem->GetFileTime( (char *)pFilenameA ); - int timeB = g_pFullFileSystem->GetFileTime( (char *)pFilenameB ); - - if ( timeA == -1) - { - // file a not exist - timeA = 0; - } - if ( timeB == -1 ) - { - // file b not exist - timeB = 0; - } - - if ( (unsigned int)timeA < (unsigned int)timeB ) - { - return -1; - } - else if ( (unsigned int)timeA > (unsigned int)timeB ) - { - return 1; - } - - return 0; -} - -//----------------------------------------------------------------------------- -// Make a temporary filename -//----------------------------------------------------------------------------- -char *CScriptLib::MakeTemporaryFilename( char const *pchModPath, char *pPath, int pathSize ) -{ - char *pBuffer = _tempnam( pchModPath, "mgd_" ); - if ( pBuffer[0] == '\\' ) - { - pBuffer++; - } - if ( pBuffer[strlen( pBuffer )-1] == '.' ) - { - pBuffer[strlen( pBuffer )-1] = '\0'; - } - V_snprintf( pPath, pathSize, "%s.tmp", pBuffer ); - - free( pBuffer ); - - return pPath; -} - -//----------------------------------------------------------------------------- -// Delete temporary files -//----------------------------------------------------------------------------- -void CScriptLib::DeleteTemporaryFiles( const char *pFileMask ) -{ -#if !defined( _X360 ) - const char *pEnv = getenv( "temp" ); - if ( !pEnv ) - { - pEnv = getenv( "tmp" ); - } - - if ( pEnv ) - { - char tempPath[MAX_PATH]; - strcpy( tempPath, pEnv ); - V_AppendSlash( tempPath, sizeof( tempPath ) ); - strcat( tempPath, pFileMask ); - - CUtlVector fileList; - FindFiles( tempPath, false, fileList ); - for ( int i=0; i &fileList ) -{ - char sourcePath[MAX_PATH]; - char fullPath[MAX_PATH]; - bool bFindDirs; - - fileList.Purge(); - - strcpy( sourcePath, pDirPath ); - int len = (int)strlen( sourcePath ); - if ( !len ) - { - strcpy( sourcePath, ".\\" ); - } - else if ( sourcePath[len-1] != '\\' ) - { - sourcePath[len] = '\\'; - sourcePath[len+1] = '\0'; - } - - strcpy( fullPath, sourcePath ); - if ( pPattern[0] == '\\' && pPattern[1] == '\0' ) - { - // find directories only - bFindDirs = true; - strcat( fullPath, "*" ); - } - else - { - // find files, use provided pattern - bFindDirs = false; - strcat( fullPath, pPattern ); - } - -#ifdef WIN32 - struct _finddata_t findData; - intptr_t h = _findfirst( fullPath, &findData ); - if ( h == -1 ) - { - return 0; - } - - do - { - // dos attribute complexities i.e. _A_NORMAL is 0 - if ( bFindDirs ) - { - // skip non dirs - if ( !( findData.attrib & _A_SUBDIR ) ) - continue; - } - else - { - // skip dirs - if ( findData.attrib & _A_SUBDIR ) - continue; - } - - if ( !stricmp( findData.name, "." ) ) - continue; - - if ( !stricmp( findData.name, ".." ) ) - continue; - - char fileName[MAX_PATH]; - strcpy( fileName, sourcePath ); - strcat( fileName, findData.name ); - - int j = fileList.AddToTail(); - fileList[j].fileName.Set( fileName ); - fileList[j].timeWrite = findData.time_write; - } - while ( !_findnext( h, &findData ) ); - - _findclose( h ); -#elif defined(POSIX) - FIND_DATA findData; - Q_FixSlashes( fullPath ); - void *h = FindFirstFile( fullPath, &findData ); - if ( (int)h == -1 ) - { - return 0; - } - - do - { - // dos attribute complexities i.e. _A_NORMAL is 0 - if ( bFindDirs ) - { - // skip non dirs - if ( !( findData.dwFileAttributes & S_IFDIR ) ) - continue; - } - else - { - // skip dirs - if ( findData.dwFileAttributes & S_IFDIR ) - continue; - } - - if ( !stricmp( findData.cFileName, "." ) ) - continue; - - if ( !stricmp( findData.cFileName, ".." ) ) - continue; - - char fileName[MAX_PATH]; - strcpy( fileName, sourcePath ); - strcat( fileName, findData.cFileName ); - - int j = fileList.AddToTail(); - fileList[j].fileName.Set( fileName ); - struct stat statbuf; - if ( stat( fileName, &statbuf ) ) -#ifdef OSX - fileList[j].timeWrite = statbuf.st_mtimespec.tv_sec; -#else - fileList[j].timeWrite = statbuf.st_mtime; -#endif - else - fileList[j].timeWrite = 0; - } - while ( !FindNextFile( h, &findData ) ); - - FindClose( h ); - -#else -#error -#endif - - - return fileList.Count(); -} - -//----------------------------------------------------------------------------- -// Purpose: Recursively determine directory tree -//----------------------------------------------------------------------------- -void CScriptLib::RecurseFileTree_r( const char* pDirPath, int depth, CUtlVector< CUtlString > &dirList ) -{ - // recurse from source directory, get directories only - CUtlVector< fileList_t > fileList; - int dirCount = GetFileList( pDirPath, "\\", fileList ); - if ( !dirCount ) - { - // add directory name to search tree - int j = dirList.AddToTail(); - dirList[j].Set( pDirPath ); - return; - } - - for ( int i=0; i &fileList ) -{ - char dirPath[MAX_PATH]; - char pattern[MAX_PATH]; - char extension[MAX_PATH]; - - // get path only - strcpy( dirPath, pFileMask ); - V_StripFilename( dirPath ); - - // get pattern only - V_FileBase( pFileMask, pattern, sizeof( pattern ) ); - V_ExtractFileExtension( pFileMask, extension, sizeof( extension ) ); - if ( extension[0] ) - { - strcat( pattern, "." ); - strcat( pattern, extension ); - } - - if ( !bRecurse ) - { - GetFileList( dirPath, pattern, fileList ); - } - else - { - // recurse and get the tree - CUtlVector< fileList_t > tempList; - CUtlVector< CUtlString > dirList; - RecurseFileTree_r( dirPath, 0, dirList ); - for ( int i=0; i +#endif +/* +============================================================================= + + PARSING STUFF + +============================================================================= +*/ + +typedef struct +{ + char filename[1024]; + char *buffer,*script_p,*end_p; + int line; + + char macrobuffer[4096]; + char *macroparam[64]; + char *macrovalue[64]; + int nummacroparams; + +} script_t; + +#define MAX_INCLUDES 64 +script_t scriptstack[MAX_INCLUDES]; +script_t *script = NULL; +int scriptline; + +char token[MAXTOKEN]; +qboolean endofscript; +qboolean tokenready; // only true if UnGetToken was just called + +typedef struct +{ + char *param; + char *value; +} variable_t; + +CUtlVector g_definevariable; + +/* +Callback stuff +*/ + +void DefaultScriptLoadedCallback( char const *pFilenameLoaded, char const *pIncludedFromFileName, int nIncludeLineNumber ) +{ + NULL; +} + +SCRIPT_LOADED_CALLBACK g_pfnCallback = DefaultScriptLoadedCallback; + +SCRIPT_LOADED_CALLBACK SetScriptLoadedCallback( SCRIPT_LOADED_CALLBACK pfnNewScriptLoadedCallback ) +{ + SCRIPT_LOADED_CALLBACK pfnCallback = g_pfnCallback; + g_pfnCallback = pfnNewScriptLoadedCallback; + return pfnCallback; +} + +/* +============== +AddScriptToStack +============== +*/ +void AddScriptToStack (char *filename, ScriptPathMode_t pathMode = SCRIPT_USE_ABSOLUTE_PATH) +{ + int size; + + script++; + if (script == &scriptstack[MAX_INCLUDES]) + Error ("script file exceeded MAX_INCLUDES"); + + if ( pathMode == SCRIPT_USE_RELATIVE_PATH ) + Q_strncpy( script->filename, filename, sizeof( script->filename ) ); + else + Q_strncpy (script->filename, ExpandPath (filename), sizeof( script->filename ) ); + + size = LoadFile (script->filename, (void **)&script->buffer); + + // printf ("entering %s\n", script->filename); + if ( g_pfnCallback ) + { + if ( script == scriptstack + 1 ) + g_pfnCallback( script->filename, NULL, 0 ); + else + g_pfnCallback( script->filename, script[-1].filename, script[-1].line ); + } + + script->line = 1; + + script->script_p = script->buffer; + script->end_p = script->buffer + size; +} + + +/* +============== +LoadScriptFile +============== +*/ +void LoadScriptFile (char *filename, ScriptPathMode_t pathMode) +{ + script = scriptstack; + AddScriptToStack (filename, pathMode); + + endofscript = false; + tokenready = false; +} + + +/* +============== +============== +*/ + +script_t *macrolist[256]; +int nummacros; + +void DefineMacro( char *macroname ) +{ + script_t *pmacro = (script_t *)malloc( sizeof( script_t ) ); + + strcpy( pmacro->filename, macroname ); + pmacro->line = script->line; + pmacro->nummacroparams = 0; + + char *mp = pmacro->macrobuffer; + char *cp = script->script_p; + + while (TokenAvailable( )) + { + GetToken( false ); + + if (token[0] == '\\' && token[1] == '\\') + { + break; + } + cp = script->script_p; + + pmacro->macroparam[pmacro->nummacroparams++] = mp; + + strcpy( mp, token ); + mp += strlen( token ) + 1; + + if (mp >= pmacro->macrobuffer + sizeof( pmacro->macrobuffer )) + Error("Macro buffer overflow\n"); + } + // roll back script_p to previous valid location + script->script_p = cp; + + // find end of macro def + while (*cp && *cp != '\n') + { + //Msg("%d ", *cp ); + if (*cp == '\\' && *(cp+1) == '\\') + { + // skip till end of line + while (*cp && *cp != '\n') + { + *cp = ' '; // replace with spaces + cp++; + } + + if (*cp) + { + cp++; + } + } + else + { + cp++; + } + } + + int size = (cp - script->script_p); + + pmacro->buffer = (char *)malloc( size + 1); + memcpy( pmacro->buffer, script->script_p, size ); + pmacro->buffer[size] = '\0'; + pmacro->end_p = &pmacro->buffer[size]; + + macrolist[nummacros++] = pmacro; + + script->script_p = cp; +} + + +void DefineVariable( char *variablename ) +{ + variable_t v; + + v.param = strdup( variablename ); + + GetToken( false ); + + v.value = strdup( token ); + + g_definevariable.AddToTail( v ); +} + + + +/* +============== +============== +*/ +bool AddMacroToStack( char *macroname ) +{ + // lookup macro + if (macroname[0] != '$') + return false; + + int i; + for (i = 0; i < nummacros; i++) + { + if (strcmpi( macrolist[i]->filename, ¯oname[1] ) == 0) + { + break; + } + } + if (i == nummacros) + return false; + + script_t *pmacro = macrolist[i]; + + // get tokens + script_t *pnext = script + 1; + + pnext++; + if (pnext == &scriptstack[MAX_INCLUDES]) + Error ("script file exceeded MAX_INCLUDES"); + + // get tokens + char *cp = pnext->macrobuffer; + + pnext->nummacroparams = pmacro->nummacroparams; + + for (i = 0; i < pnext->nummacroparams; i++) + { + GetToken(false); + + strcpy( cp, token ); + pnext->macroparam[i] = pmacro->macroparam[i]; + pnext->macrovalue[i] = cp; + + cp += strlen( token ) + 1; + + if (cp >= pnext->macrobuffer + sizeof( pnext->macrobuffer )) + Error("Macro buffer overflow\n"); + } + + script = pnext; + strcpy( script->filename, pmacro->filename ); + + int size = pmacro->end_p - pmacro->buffer; + script->buffer = (char *)malloc( size + 1 ); + memcpy( script->buffer, pmacro->buffer, size ); + pmacro->buffer[size] = '\0'; + script->script_p = script->buffer; + script->end_p = script->buffer + size; + script->line = pmacro->line; + + return true; +} + + + +bool ExpandMacroToken( char *&token_p ) +{ + if ( script->nummacroparams && *script->script_p == '$' ) + { + char *cp = script->script_p + 1; + + while ( *cp > 32 && *cp != '$' ) + { + cp++; + } + + // found a word with $'s on either end? + if (*cp != '$') + return false; + + // get token pointer + char *tp = script->script_p + 1; + int len = (cp - tp); + *(tp + len) = '\0'; + + // lookup macro parameter + int index = 0; + for (index = 0; index < script->nummacroparams; index++) + { + if (stricmp( script->macroparam[index], tp ) == 0) + break; + } + if (index >= script->nummacroparams) + { + Error("unknown macro token \"%s\" in %s\n", tp, script->filename ); + } + + // paste token into + len = strlen( script->macrovalue[index] ); + strcpy( token_p, script->macrovalue[index] ); + token_p += len; + + script->script_p = cp + 1; + + if (script->script_p >= script->end_p) + Error ("Macro expand overflow\n"); + + if (token_p >= &token[MAXTOKEN]) + Error ("Token too large on line %i\n",scriptline); + + return true; + } + return false; +} + + + +/* +============== +============== +*/ +// FIXME: this should create a new script context so the individual tokens in the variable can be parsed +bool ExpandVariableToken( char *&token_p ) +{ + if ( *script->script_p == '$' ) + { + char *cp = script->script_p + 1; + + while ( *cp > 32 && *cp != '$' ) + { + cp++; + } + + // found a word with $'s on either end? + if (*cp != '$') + return false; + + // get token pointer + char *tp = script->script_p + 1; + int len = (cp - tp); + *(tp + len) = '\0'; + + // lookup macro parameter + + int index; + for (index = 0; index < g_definevariable.Count(); index++) + { + if (Q_strnicmp( g_definevariable[index].param, tp, len ) == 0) + break; + } + + if (index >= g_definevariable.Count() ) + { + Error("unknown variable token \"%s\" in %s\n", tp, script->filename ); + } + + // paste token into + len = strlen( g_definevariable[index].value ); + strcpy( token_p, g_definevariable[index].value ); + token_p += len; + + script->script_p = cp + 1; + + if (script->script_p >= script->end_p) + Error ("Macro expand overflow\n"); + + if (token_p >= &token[MAXTOKEN]) + Error ("Token too large on line %i\n",scriptline); + + return true; + } + return false; +} + + + +/* +============== +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 = false; + tokenready = false; +} + + +//----------------------------------------------------------------------------- +// Used instead of ParseFromMemory to temporarily add a memory buffer +// to the script stack. ParseFromMemory just blows away the stack. +//----------------------------------------------------------------------------- +void PushMemoryScript( char *pszBuffer, const int nSize ) +{ + if ( script == NULL ) + { + script = scriptstack; + } + script++; + if ( script == &scriptstack[MAX_INCLUDES] ) + { + Error ( "script file exceeded MAX_INCLUDES" ); + } + strcpy (script->filename, "memory buffer" ); + + script->buffer = pszBuffer; + script->line = 1; + script->script_p = script->buffer; + script->end_p = script->buffer + nSize; + + endofscript = false; + tokenready = false; +} + + +//----------------------------------------------------------------------------- +// Used after calling PushMemoryScript to clean up the memory buffer +// added to the script stack. The normal end of script terminates +// all parsing at the end of a memory buffer even if there are more scripts +// remaining on the script stack +//----------------------------------------------------------------------------- +bool PopMemoryScript() +{ + if ( V_stricmp( script->filename, "memory buffer" ) ) + return false; + + if ( script == scriptstack ) + { + endofscript = true; + return false; + } + script--; + scriptline = script->line; + + endofscript = false; + + return true; +} + + +/* +============== +UnGetToken + +Signals that the current token was not used, and should be reported +for the next GetToken. Note that + +GetToken (true); +UnGetToken (); +GetToken (false); + +could cross a line boundary. +============== +*/ +void UnGetToken (void) +{ + tokenready = true; +} + + +qboolean EndOfScript (qboolean crossline) +{ + if (!crossline) + Error ("Line %i is incomplete\n",scriptline); + + if (!strcmp (script->filename, "memory buffer")) + { + endofscript = true; + return false; + } + + free (script->buffer); + script->buffer = NULL; + if (script == scriptstack+1) + { + endofscript = true; + return false; + } + script--; + scriptline = script->line; + // printf ("returning to %s\n", script->filename); + return GetToken (crossline); +} + + +//----------------------------------------------------------------------------- +// Purpose: Given an absolute path, do a find first find next on it and build +// a list of files. Physical file system only +//----------------------------------------------------------------------------- +static void FindFileAbsoluteList( CUtlVector< CUtlString > &outAbsolutePathNames, const char *pszFindName ) +{ + char szPath[MAX_PATH]; + V_strncpy( szPath, pszFindName, sizeof( szPath ) ); + V_StripFilename( szPath ); + + char szResult[MAX_PATH]; + FileFindHandle_t hFile = FILESYSTEM_INVALID_FIND_HANDLE; + + for ( const char *pszFoundFile = g_pFullFileSystem->FindFirst( pszFindName, &hFile ); pszFoundFile && hFile != FILESYSTEM_INVALID_FIND_HANDLE; pszFoundFile = g_pFullFileSystem->FindNext( hFile ) ) + { + V_ComposeFileName( szPath, pszFoundFile, szResult, sizeof( szResult ) ); + outAbsolutePathNames.AddToTail( szResult ); + } + + g_pFullFileSystem->FindClose( hFile ); +} + + +//----------------------------------------------------------------------------- +// Data for checking for single character tokens while parsing +//----------------------------------------------------------------------------- +bool g_bCheckSingleCharTokens = false; +CUtlString g_sSingleCharTokens; + + +//----------------------------------------------------------------------------- +// Sets whether the scriplib parser will do a special check for single +// character tokens. Returns previous state of whether single character +// tokens will be checked. +//----------------------------------------------------------------------------- +bool SetCheckSingleCharTokens( bool bCheck ) +{ + const bool bRetVal = g_bCheckSingleCharTokens; + + g_bCheckSingleCharTokens = bCheck; + + return bRetVal; +} + + +//----------------------------------------------------------------------------- +// Sets the list of single character tokens to check if SetCheckSingleCharTokens +// is turned on. +//----------------------------------------------------------------------------- +CUtlString SetSingleCharTokenList( const char *pszSingleCharTokenList ) +{ + const CUtlString sRetVal = g_sSingleCharTokens; + + if ( pszSingleCharTokenList ) + { + g_sSingleCharTokens = pszSingleCharTokenList; + } + + return sRetVal; +} + + +/* +============== +GetToken +============== +*/ +qboolean GetToken (qboolean crossline) +{ + char *token_p; + + if (tokenready) // is a token allready waiting? + { + tokenready = false; + return true; + } + + // printf("script_p %x (%x)\n", script->script_p, script->end_p ); fflush( stdout ); + + if (script->script_p >= script->end_p) + { + return EndOfScript (crossline); + } + + tokenready = false; + + // skip space, ctrl chars +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); + } + + // strip single line comments + if (*script->script_p == ';' || *script->script_p == '#' || // semicolon and # is comment field + (*script->script_p == '/' && *((script->script_p)+1) == '/')) // also make // a comment field + { + 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; + } + + // strip out matching /* */ comments + if (*script->script_p == '/' && *((script->script_p)+1) == '*') + { + script->script_p += 2; + while (*script->script_p != '*' || *((script->script_p)+1) != '/') + { + if (*script->script_p++ != '\n') + { + if (script->script_p >= script->end_p) + { + return EndOfScript (crossline); + } + + scriptline = ++script->line; + } + } + script->script_p += 2; + goto skipspace; + } + + // copy token to buffer + 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 if ( g_bCheckSingleCharTokens && !g_sSingleCharTokens.IsEmpty() && strchr( g_sSingleCharTokens.String(), *script->script_p ) != NULL ) + { + *token_p++ = *script->script_p++; + } + else // regular token + while ( *script->script_p > 32 && *script->script_p != ';') + { + if ( !ExpandMacroToken( token_p ) ) + { + if ( !ExpandVariableToken( token_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); + + } + } + } + + // add null to end of token + *token_p = 0; + + // check for other commands + if ( !stricmp( token, "$include" ) ) + { + GetToken( false ); + + bool bFallbackToToken = true; + + CUtlVector< CUtlString > expandedPathList; + + if ( CmdLib_ExpandWithBasePaths( expandedPathList, token ) > 0 ) + { + for ( int i = 0; i < expandedPathList.Count(); ++i ) + { + CUtlVector< CUtlString > findFileList; + FindFileAbsoluteList( findFileList, expandedPathList[i].String() ); + + if ( findFileList.Count() > 0 ) + { + bFallbackToToken = false; + + // Only add the first set of glob matches from the first base path + for ( int j = 0; j < findFileList.Count(); ++j ) + { + AddScriptToStack( const_cast< char * >( findFileList[j].String() ) ); + } + + break; + } + } + } + + if ( bFallbackToToken ) + { + AddScriptToStack( token ); + } + + return GetToken( crossline ); + } + else if (!stricmp (token, "$definemacro")) + { + GetToken (false); + DefineMacro(token); + return GetToken (crossline); + } + else if (!stricmp (token, "$definevariable")) + { + GetToken (false); + DefineVariable(token); + return GetToken (crossline); + } + else if (AddMacroToStack( token )) + { + return GetToken (crossline); + } + + return true; +} + + +/* +============== +GetExprToken - use C mathematical operator parsing rules to split tokens instead of whitespace +============== +*/ +qboolean GetExprToken (qboolean crossline) +{ + char *token_p; + + if (tokenready) // is a token allready waiting? + { + tokenready = false; + return true; + } + + if (script->script_p >= script->end_p) + return EndOfScript (crossline); + + tokenready = false; + +// +// 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); + + if (*script->script_p == ';' || *script->script_p == '#' || // semicolon and # is comment field + (*script->script_p == '/' && *((script->script_p)+1) == '/')) // also make // a comment field + { + if (!crossline) + Error ("Line %i is incomplete\n",scriptline); + while (*script->script_p++ != '\n') + if (script->script_p >= script->end_p) + return EndOfScript (crossline); + 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 + { + if ( V_isalpha( *script->script_p ) || *script->script_p == '_' ) + { + // regular token + while ( V_isalnum( *script->script_p ) || *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); + } + } + else if ( V_isdigit( *script->script_p ) || *script->script_p == '.' ) + { + // regular token + while ( V_isdigit( *script->script_p ) || *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); + } + } + else + { + // single char + *token_p++ = *script->script_p++; + } + } + + *token_p = 0; + + if (!stricmp (token, "$include")) + { + GetToken (false); + AddScriptToStack (token); + return GetToken (crossline); + } + + return true; +} + + +/* +============== +TokenAvailable + +Returns true if there is another token on the line +============== +*/ +qboolean TokenAvailable (void) +{ + char *search_p; + + if (tokenready) // is a token allready waiting? + { + return true; + } + + search_p = script->script_p; + + if (search_p >= script->end_p) + return false; + + while ( *search_p <= 32) + { + if (*search_p == '\n') + return false; + search_p++; + if (search_p == script->end_p) + return false; + + } + + if (*search_p == ';' || *search_p == '#' || // semicolon and # is comment field + (*search_p == '/' && *((search_p)+1) == '/')) // also make // a comment field + return false; + + return true; +} + +qboolean GetTokenizerStatus( char **pFilename, int *pLine ) +{ + // is this the default state? + if (!script) + return false; + + if (script->script_p >= script->end_p) + return false; + + if (pFilename) + { + *pFilename = script->filename; + } + if (pLine) + { + *pLine = script->line; + } + return true; +} + + +#include +#include +#ifdef WIN32 +#include +#include +#include +#endif +#include +#include +#include +#include +#include "tier1/utlbuffer.h" + +class CScriptLib : public IScriptLib +{ +public: + virtual bool ReadFileToBuffer( const char *pSourceName, CUtlBuffer &buffer, bool bText = false, bool bNoOpenFailureWarning = false ); + virtual bool WriteBufferToFile( const char *pTargetName, CUtlBuffer &buffer, DiskWriteMode_t writeMode ); + virtual int FindFiles( char* pFileMask, bool bRecurse, CUtlVector &fileList ); + virtual char *MakeTemporaryFilename( char const *pchModPath, char *pPath, int pathSize ); + virtual void DeleteTemporaryFiles( const char *pFileMask ); + virtual int CompareFileTime( const char *pFilenameA, const char *pFilenameB ); + virtual bool DoesFileExist( const char *pFilename ); + +private: + + int GetFileList( const char* pDirPath, const char* pPattern, CUtlVector< fileList_t > &fileList ); + void RecurseFileTree_r( const char* pDirPath, int depth, CUtlVector< CUtlString > &dirList ); +}; + +static CScriptLib g_ScriptLib; +IScriptLib *scriptlib = &g_ScriptLib; +IScriptLib *g_pScriptLib = &g_ScriptLib; + +//----------------------------------------------------------------------------- +// Existence check +//----------------------------------------------------------------------------- +bool CScriptLib::DoesFileExist( const char *pFilename ) +{ + return g_pFullFileSystem->FileExists( pFilename ); +} + +//----------------------------------------------------------------------------- +// Purpose: Helper utility, read file into buffer +//----------------------------------------------------------------------------- +bool CScriptLib::ReadFileToBuffer( const char *pSourceName, CUtlBuffer &buffer, bool bText, bool bNoOpenFailureWarning ) +{ + bool bSuccess = true; + + if ( !g_pFullFileSystem->ReadFile( pSourceName, NULL, buffer ) ) + { + if ( !bNoOpenFailureWarning ) + { + Msg( "ReadFileToBuffer(): Error opening %s: %s\n", pSourceName, strerror( errno ) ); + } + return false; + } + + if ( bText ) + { + // force it into text mode + buffer.SetBufferType( true, true ); + } + else + { + buffer.SetBufferType( false, false ); + } + + return bSuccess; +} + +//----------------------------------------------------------------------------- +// Purpose: Helper utility, Write buffer to file +//----------------------------------------------------------------------------- +bool CScriptLib::WriteBufferToFile( const char *pTargetName, CUtlBuffer &buffer, DiskWriteMode_t writeMode ) +{ + char* ptr; + char dirPath[MAX_PATH]; + + bool bSuccess = true; + + // create path + // prime and skip to first seperator + strcpy( dirPath, pTargetName ); + ptr = strchr( dirPath, '\\' ); + while ( ptr ) + { + ptr = strchr( ptr+1, '\\' ); + if ( ptr ) + { + *ptr = '\0'; + _mkdir( dirPath ); + *ptr = '\\'; + } + } + + bool bDoWrite = false; + if ( writeMode == WRITE_TO_DISK_ALWAYS ) + { + bDoWrite = true; + } + else if ( writeMode == WRITE_TO_DISK_UPDATE ) + { + if ( DoesFileExist( pTargetName ) ) + { + bDoWrite = true; + } + } + + if ( bDoWrite ) + { + bSuccess = g_pFullFileSystem->WriteFile( pTargetName, NULL, buffer ); + } + + return bSuccess; +} + +//----------------------------------------------------------------------------- +// Returns -1, 0, or 1. +//----------------------------------------------------------------------------- +int CScriptLib::CompareFileTime( const char *pFilenameA, const char *pFilenameB ) +{ + int timeA = g_pFullFileSystem->GetFileTime( (char *)pFilenameA ); + int timeB = g_pFullFileSystem->GetFileTime( (char *)pFilenameB ); + + if ( timeA == -1) + { + // file a not exist + timeA = 0; + } + if ( timeB == -1 ) + { + // file b not exist + timeB = 0; + } + + if ( (unsigned int)timeA < (unsigned int)timeB ) + { + return -1; + } + else if ( (unsigned int)timeA > (unsigned int)timeB ) + { + return 1; + } + + return 0; +} + +//----------------------------------------------------------------------------- +// Make a temporary filename +//----------------------------------------------------------------------------- +char *CScriptLib::MakeTemporaryFilename( char const *pchModPath, char *pPath, int pathSize ) +{ + char *pBuffer = _tempnam( pchModPath, "mgd_" ); + if ( pBuffer[0] == '\\' ) + { + pBuffer++; + } + if ( pBuffer[strlen( pBuffer )-1] == '.' ) + { + pBuffer[strlen( pBuffer )-1] = '\0'; + } + V_snprintf( pPath, pathSize, "%s.tmp", pBuffer ); + + free( pBuffer ); + + return pPath; +} + +//----------------------------------------------------------------------------- +// Delete temporary files +//----------------------------------------------------------------------------- +void CScriptLib::DeleteTemporaryFiles( const char *pFileMask ) +{ +#if !defined( _X360 ) + const char *pEnv = getenv( "temp" ); + if ( !pEnv ) + { + pEnv = getenv( "tmp" ); + } + + if ( pEnv ) + { + char tempPath[MAX_PATH]; + strcpy( tempPath, pEnv ); + V_AppendSlash( tempPath, sizeof( tempPath ) ); + strcat( tempPath, pFileMask ); + + CUtlVector fileList; + FindFiles( tempPath, false, fileList ); + for ( int i=0; i &fileList ) +{ + char sourcePath[MAX_PATH]; + char fullPath[MAX_PATH]; + bool bFindDirs; + + fileList.Purge(); + + strcpy( sourcePath, pDirPath ); + int len = (int)strlen( sourcePath ); + if ( !len ) + { + strcpy( sourcePath, ".\\" ); + } + else if ( sourcePath[len-1] != '\\' ) + { + sourcePath[len] = '\\'; + sourcePath[len+1] = '\0'; + } + + strcpy( fullPath, sourcePath ); + if ( pPattern[0] == '\\' && pPattern[1] == '\0' ) + { + // find directories only + bFindDirs = true; + strcat( fullPath, "*" ); + } + else + { + // find files, use provided pattern + bFindDirs = false; + strcat( fullPath, pPattern ); + } + +#ifdef WIN32 + struct _finddata_t findData; + intptr_t h = _findfirst( fullPath, &findData ); + if ( h == -1 ) + { + return 0; + } + + do + { + // dos attribute complexities i.e. _A_NORMAL is 0 + if ( bFindDirs ) + { + // skip non dirs + if ( !( findData.attrib & _A_SUBDIR ) ) + continue; + } + else + { + // skip dirs + if ( findData.attrib & _A_SUBDIR ) + continue; + } + + if ( !stricmp( findData.name, "." ) ) + continue; + + if ( !stricmp( findData.name, ".." ) ) + continue; + + char fileName[MAX_PATH]; + strcpy( fileName, sourcePath ); + strcat( fileName, findData.name ); + + int j = fileList.AddToTail(); + fileList[j].fileName.Set( fileName ); + fileList[j].timeWrite = findData.time_write; + } + while ( !_findnext( h, &findData ) ); + + _findclose( h ); +#elif defined(POSIX) + FIND_DATA findData; + Q_FixSlashes( fullPath ); + void *h = FindFirstFile( fullPath, &findData ); + if ( (int)h == -1 ) + { + return 0; + } + + do + { + // dos attribute complexities i.e. _A_NORMAL is 0 + if ( bFindDirs ) + { + // skip non dirs + if ( !( findData.dwFileAttributes & S_IFDIR ) ) + continue; + } + else + { + // skip dirs + if ( findData.dwFileAttributes & S_IFDIR ) + continue; + } + + if ( !stricmp( findData.cFileName, "." ) ) + continue; + + if ( !stricmp( findData.cFileName, ".." ) ) + continue; + + char fileName[MAX_PATH]; + strcpy( fileName, sourcePath ); + strcat( fileName, findData.cFileName ); + + int j = fileList.AddToTail(); + fileList[j].fileName.Set( fileName ); + struct stat statbuf; + if ( stat( fileName, &statbuf ) ) +#ifdef OSX + fileList[j].timeWrite = statbuf.st_mtimespec.tv_sec; +#else + fileList[j].timeWrite = statbuf.st_mtime; +#endif + else + fileList[j].timeWrite = 0; + } + while ( !FindNextFile( h, &findData ) ); + + FindClose( h ); + +#else +#error +#endif + + + return fileList.Count(); +} + +//----------------------------------------------------------------------------- +// Purpose: Recursively determine directory tree +//----------------------------------------------------------------------------- +void CScriptLib::RecurseFileTree_r( const char* pDirPath, int depth, CUtlVector< CUtlString > &dirList ) +{ + // recurse from source directory, get directories only + CUtlVector< fileList_t > fileList; + int dirCount = GetFileList( pDirPath, "\\", fileList ); + if ( !dirCount ) + { + // add directory name to search tree + int j = dirList.AddToTail(); + dirList[j].Set( pDirPath ); + return; + } + + for ( int i=0; i &fileList ) +{ + char dirPath[MAX_PATH]; + char pattern[MAX_PATH]; + char extension[MAX_PATH]; + + // get path only + strcpy( dirPath, pFileMask ); + V_StripFilename( dirPath ); + + // get pattern only + V_FileBase( pFileMask, pattern, sizeof( pattern ) ); + V_ExtractFileExtension( pFileMask, extension, sizeof( extension ) ); + if ( extension[0] ) + { + strcat( pattern, "." ); + strcat( pattern, extension ); + } + + if ( !bRecurse ) + { + GetFileList( dirPath, pattern, fileList ); + } + else + { + // recurse and get the tree + CUtlVector< fileList_t > tempList; + CUtlVector< CUtlString > dirList; + RecurseFileTree_r( dirPath, 0, dirList ); + for ( int i=0; i