summaryrefslogtreecommitdiff
path: root/utils/vmtcheck/vmtcheck.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/vmtcheck/vmtcheck.cpp')
-rw-r--r--utils/vmtcheck/vmtcheck.cpp279
1 files changed, 279 insertions, 0 deletions
diff --git a/utils/vmtcheck/vmtcheck.cpp b/utils/vmtcheck/vmtcheck.cpp
new file mode 100644
index 0000000..241a1d0
--- /dev/null
+++ b/utils/vmtcheck/vmtcheck.cpp
@@ -0,0 +1,279 @@
+//========= 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;
+}