//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #include "stdafx.h" #include #include #include "vmtcheck_util.h" #include "tier0/dbg.h" #include "utldict.h" #include "filesystem.h" #include "FileSystem_Tools.h" #include "KeyValues.h" #include "cmdlib.h" bool uselogfile = false; struct AnalysisData { CUtlSymbolTable symbols; }; static AnalysisData g_Analysis; static bool spewed = false; SpewRetval_t SpewFunc( SpewType_t type, char const *pMsg ) { spewed = true; printf( "%s", pMsg ); OutputDebugString( pMsg ); if ( type == SPEW_ERROR ) { printf( "\n" ); OutputDebugString( "\n" ); } return SPEW_CONTINUE; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void printusage( void ) { vprint( 0, "usage: vmtcheck \n\ \t-v = verbose output\n\ \t-l = log to file log.txt\n\ \ne.g.: vmtcheck -l u:/hl2/hl2/materials\n" ); // Exit app exit( 1 ); } void BuildFileList_R( CUtlVector< CUtlSymbol >& files, char const *dir, char const *extension ) { WIN32_FIND_DATA wfd; char directory[ 256 ]; char filename[ 256 ]; HANDLE ff; sprintf( directory, "%s\\*.*", dir ); if ( ( ff = FindFirstFile( directory, &wfd ) ) == INVALID_HANDLE_VALUE ) return; int extlen = strlen( extension ); do { if ( wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) { if ( wfd.cFileName[ 0 ] == '.' ) continue; // Recurse down directory sprintf( filename, "%s\\%s", dir, wfd.cFileName ); BuildFileList_R( files, filename, extension ); } else { int len = strlen( wfd.cFileName ); if ( len > extlen ) { if ( !stricmp( &wfd.cFileName[ len - extlen ], extension ) ) { char filename[ MAX_PATH ]; Q_snprintf( filename, sizeof( filename ), "%s\\%s", dir, wfd.cFileName ); _strlwr( filename ); Q_FixSlashes( filename ); CUtlSymbol sym = g_Analysis.symbols.AddString( filename ); files.AddToTail( sym ); if ( !( files.Count() % 3000 ) ) { vprint( 0, "...found %i .vmt files\n", files.Count() ); } } } } } while ( FindNextFile( ff, &wfd ) ); } void BuildFileList( CUtlVector< CUtlSymbol >& files, char const *rootdir, char const *extension ) { files.RemoveAll(); BuildFileList_R( files, rootdir, extension ); } bool ValidateVMTFile( char const *vmtname, int offset ) { bool valid = true; KeyValues *kv = new KeyValues( "Test" ); if ( kv->LoadFromFile( g_pFileSystem, &vmtname[offset] ) ) { // Do any custom checking here... } else { valid = false; } kv->deleteThis(); return valid; } void ProcessMaterialsDirectory( char const *basedir ) { vprint( 0, "building .vmt list\n" ); CUtlVector< CUtlSymbol > vmts; BuildFileList( vmts, basedir, ".vmt" ); vprint( 0, "found %i .vmt files\n\n", vmts.Count() ); int offset = strlen( basedir ) + 1; offset -= strlen( "materials/" ); if ( offset < 0 ) { Error( "Bogus offset\n" ); } // Now iterate vmts and load into memory, etc. int c = vmts.Count(); int valid = 0; for ( int i = 0; i < c; i++ ) { CUtlSymbol& sym = vmts[ i ]; char const *vmtfile = g_Analysis.symbols.String( sym ); if ( verbose ) { vprint( 0, "checking %i .vmt %s\n", i, vmtfile ); } spewed = false; if ( ValidateVMTFile( vmtfile, offset ) ) { if ( !spewed ) { valid++; } } if ( i > 0 && !( i % 1000 ) ) { vprint( 0, "Analyzed %i .vmt files (%.2f %%%%)\n", i, 100.0f * (float)i/(float)c ); } } int ecount = c - valid; vprint( 0, "\nSummary: found %i/%i (%.2f percent) .vmt errors\n", ecount, c, 100.0 * ecount / max( c, 1 ) ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CheckLogFile( void ) { if ( uselogfile ) { _unlink( "log.txt" ); vprint( 0, " Outputting to log.txt\n" ); } } void PrintHeader() { vprint( 0, "Valve Software - vmtcheck.exe (%s)\n", __DATE__ ); vprint( 0, "--- VMT File Consistency Checker ---\n" ); } //----------------------------------------------------------------------------- // Purpose: // Input : argc - // argv[] - // Output : int //----------------------------------------------------------------------------- int main( int argc, char* argv[] ) { SpewOutputFunc( SpewFunc ); SpewActivate( "vmtcheck", 2 ); int i=1; for ( i ; i