You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
279 lines
5.5 KiB
279 lines
5.5 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
#include "stdafx.h" |
|
#include <stdio.h> |
|
#include <windows.h> |
|
#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 <materials/.vmt root directory>\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<argc ; i++) |
|
{ |
|
if ( argv[ i ][ 0 ] == '-' ) |
|
{ |
|
switch( argv[ i ][ 1 ] ) |
|
{ |
|
case 'l': |
|
uselogfile = true; |
|
break; |
|
case 'v': |
|
verbose = true; |
|
break; |
|
default: |
|
printusage(); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
if ( argc < 2 || ( i != argc ) ) |
|
{ |
|
PrintHeader(); |
|
printusage(); |
|
} |
|
|
|
CheckLogFile(); |
|
|
|
PrintHeader(); |
|
|
|
vprint( 0, " Looking for messed up .vmt files...\n" ); |
|
|
|
char vmtdir[ 256 ]; |
|
strcpy( vmtdir, argv[ i - 1 ] ); |
|
|
|
if ( !strstr( vmtdir, "materials" ) ) |
|
{ |
|
vprint( 0, "Materials dir %s looks invalid (format: u:/tf2/hl2/materials)\n", vmtdir ); |
|
|
|
return 0; |
|
} |
|
|
|
char workingdir[ 256 ]; |
|
workingdir[0] = 0; |
|
Q_getwd( workingdir, sizeof( workingdir ) ); |
|
|
|
// If they didn't specify -game on the command line, use VPROJECT. |
|
CmdLib_InitFileSystem( workingdir ); |
|
|
|
vprint( 0, "game dir %s\nmaterials dir %s\n\n", |
|
gamedir, |
|
vmtdir ); |
|
|
|
Q_StripTrailingSlash( vmtdir ); |
|
ProcessMaterialsDirectory( vmtdir ); |
|
|
|
FileSystem_Term(); |
|
|
|
return 0; |
|
}
|
|
|