summaryrefslogtreecommitdiff
path: root/utils/depcheck
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/depcheck
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'utils/depcheck')
-rw-r--r--utils/depcheck/codeprocessor.h74
-rw-r--r--utils/depcheck/depcheck.cpp122
-rw-r--r--utils/depcheck/depcheck.vpc27
-rw-r--r--utils/depcheck/depcheck_util.cpp363
-rw-r--r--utils/depcheck/depcheck_util.h29
-rw-r--r--utils/depcheck/icodeprocessor.h28
-rw-r--r--utils/depcheck/processmodule.cpp536
-rw-r--r--utils/depcheck/stdafx.cpp15
-rw-r--r--utils/depcheck/stdafx.h26
9 files changed, 1220 insertions, 0 deletions
diff --git a/utils/depcheck/codeprocessor.h b/utils/depcheck/codeprocessor.h
new file mode 100644
index 0000000..6a309f0
--- /dev/null
+++ b/utils/depcheck/codeprocessor.h
@@ -0,0 +1,74 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+#if !defined( CODEPROCESSOR_H )
+#define CODEPROCESSOR_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "icodeprocessor.h"
+
+class CCodeProcessor : public ICodeProcessor
+{
+public:
+ CCodeProcessor( void );
+ ~CCodeProcessor( void );
+
+ void Process( const char *gamespecific, const char *root, const char *dsp, const char *config );
+
+ void SetQuiet( bool quiet );
+ bool GetQuiet( void ) const;
+
+ void SetLogFile( bool log );
+ bool GetLogFile( void ) const;
+
+private:
+ void ProcessModule( bool forcequiet, int depth, int& maxdepth, int& numheaders, int& skippedfiles, const char *baseroot, const char *root, const char *module );
+ void ProcessModules( const char *root, const char *rootmodule );
+ void PrintResults( void );
+ void ConstructModuleList_R( int level, const char *gamespecific, const char *root );
+
+ void AddHeader( int depth, const char *filename, const char *rootmodule );
+
+ void CreateBackup( const char *filename, bool& wasreadonly );
+ void RestoreBackup( const char *filename, bool makereadonly );
+
+ bool TryBuild( const char *rootdir, const char *filename, unsigned char *buffer, int filelength );
+
+ int m_nModuleCount;
+
+ typedef struct
+ {
+ char name[ 256 ];
+ bool skipped;
+ } CODE_MODULE;
+
+ CODE_MODULE m_Modules[ 16384 ];
+
+ int m_nHeaderCount;
+ CODE_MODULE m_Headers[ 16384 ];
+
+ bool m_bQuiet;
+ bool m_bLogToFile;
+
+ int m_nFilesProcessed;
+ int m_nHeadersProcessed;
+ int m_nOffset;
+ int m_nBytesProcessed;
+ int m_nLinesOfCode;
+
+ double m_flStart;
+ double m_flEnd;
+
+ char m_szCurrentCPP[ 128 ];
+ char m_szDSP[ 128 ];
+ char m_szConfig[ 128 ];
+};
+
+extern ICodeProcessor *processor;
+
+#endif // CODEPROCESSOR_H \ No newline at end of file
diff --git a/utils/depcheck/depcheck.cpp b/utils/depcheck/depcheck.cpp
new file mode 100644
index 0000000..9711ee5
--- /dev/null
+++ b/utils/depcheck/depcheck.cpp
@@ -0,0 +1,122 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+#include <stdio.h>
+#include <windows.h>
+#include "depcheck_util.h"
+#include "icodeprocessor.h"
+#include "tier1/strtools.h"
+
+char *va(char *format, ...)
+{
+ va_list argptr;
+ static char string[1024];
+
+ va_start (argptr, format);
+ Q_vsnprintf( string, 1024, format, argptr );
+ va_end (argptr);
+
+ return string;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void printusage( void )
+{
+ vprint( 0, "usage: depcheck -q -l <root source directory> <game: hl2 | tf2>\n\
+ \t-q = quiet\n\
+ \t-l = log to file log.txt\n" );
+
+ // Exit app
+ exit( 1 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *sourcetreebase -
+// *subdir -
+// *baseentityclass -
+//-----------------------------------------------------------------------------
+void ProcessDirectory( const char *game, const char *sourcetreebase, const char *subdir, const char *dsp, const char *config )
+{
+ char rootdirectory[ 256 ];
+ sprintf( rootdirectory, "%s\\%s", sourcetreebase, subdir );
+
+ // check for existence
+ if ( COM_DirectoryExists( rootdirectory ) )
+ {
+ processor->Process( game, rootdirectory, dsp, config );
+ }
+ else
+ {
+ vprint( 0, "Couldn't find directory %s, check path %s\n", rootdirectory, sourcetreebase );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CheckLogFile( void )
+{
+ if ( processor->GetLogFile() )
+ {
+ _unlink( "log.txt" );
+ vprint( 0, " Outputting to log.txt\n" );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : argc -
+// argv[] -
+// Output : int
+//-----------------------------------------------------------------------------
+int main( int argc, char* argv[] )
+{
+ vprint( 0, "Valve Software - depcheck.exe (%s)\n", __DATE__ );
+ vprint( 0, "--- Game Code Simple Build Dependency Analyzer ---\n" );
+
+ int i=1;
+ for ( i ; i<argc ; i++)
+ {
+ if ( argv[ i ][ 0 ] == '-' )
+ {
+ switch( argv[ i ][ 1 ] )
+ {
+ case 'q':
+ processor->SetQuiet( true );
+ break;
+ case 'l':
+ processor->SetLogFile( true );
+ break;
+ default:
+ printusage();
+ break;
+ }
+ }
+ }
+
+ if ( argc < 3 || ( i != argc ) )
+ {
+ printusage();
+ }
+
+ CheckLogFile();
+
+ vprint( 0, " Looking for unneeded header includes...\n" );
+
+ char sourcetreebase[ 256 ];
+ strcpy( sourcetreebase, argv[i-2] );
+
+ Q_StripTrailingSlash( sourcetreebase );
+
+// ProcessDirectory( argv[ i-1 ], sourcetreebase, "engine", "engdll.dsp", "quiver - Win32 GL Debug" );
+// ProcessDirectory( argv[ i-1 ], sourcetreebase, "dlls", "hl.dsp", va( "hl - Win32 %s Debug", argv[ i - 1 ] ) );
+ ProcessDirectory( argv[ i-1 ], sourcetreebase, "cl_dll", "client.dsp", va( "client - Win32 Debug %s", argv[ i - 1 ] ) );
+
+ return 0;
+}
diff --git a/utils/depcheck/depcheck.vpc b/utils/depcheck/depcheck.vpc
new file mode 100644
index 0000000..95708cd
--- /dev/null
+++ b/utils/depcheck/depcheck.vpc
@@ -0,0 +1,27 @@
+//-----------------------------------------------------------------------------
+// DEPCHECK.VPC
+//
+// Project Script
+//-----------------------------------------------------------------------------
+
+$Macro SRCDIR "..\.."
+$Macro OUTBINDIR "$SRCDIR\devtools\bin"
+
+$Include "$SRCDIR\vpc_scripts\source_exe_con_base.vpc"
+
+$Project "Depcheck"
+{
+ $Folder "Source Files"
+ {
+ $File "depcheck.cpp"
+ $File "depcheck_util.cpp"
+ $File "processmodule.cpp"
+ }
+
+ $Folder "Header Files"
+ {
+ $File "codeprocessor.h"
+ $File "depcheck_util.h"
+ $File "icodeprocessor.h"
+ }
+}
diff --git a/utils/depcheck/depcheck_util.cpp b/utils/depcheck/depcheck_util.cpp
new file mode 100644
index 0000000..bcff5ba
--- /dev/null
+++ b/utils/depcheck/depcheck_util.cpp
@@ -0,0 +1,363 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+#include "stdafx.h"
+#include <assert.h>
+#include <io.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <windows.h>
+#include "depcheck_util.h"
+#include "icodeprocessor.h"
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : depth -
+// *fmt -
+// ... -
+//-----------------------------------------------------------------------------
+void vprint( int depth, const char *fmt, ... )
+{
+ char string[ 8192 ];
+ va_list va;
+ va_start( va, fmt );
+ vsprintf( string, fmt, va );
+ va_end( va );
+
+ FILE *fp = NULL;
+
+ if ( processor->GetLogFile() )
+ {
+ fp = fopen( "log.txt", "ab" );
+ }
+
+ while ( depth-- > 0 )
+ {
+ printf( " " );
+ OutputDebugString( " " );
+ if ( fp )
+ {
+ fprintf( fp, " " );
+ }
+ }
+
+ ::printf( "%s", string );
+ OutputDebugString( string );
+
+ if ( fp )
+ {
+ char *p = string;
+ while ( *p )
+ {
+ if ( *p == '\n' )
+ {
+ fputc( '\r', fp );
+ }
+ fputc( *p, fp );
+ p++;
+ }
+ fclose( fp );
+ }
+}
+
+
+bool com_ignorecolons = false; // YWB: Ignore colons as token separators in COM_Parse
+bool com_ignoreinlinecomment = false;
+static bool s_com_token_unget = false;
+char com_token[1024];
+int linesprocessed = 0;
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CC_UngetToken( void )
+{
+ s_com_token_unget = true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : ch -
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool CC_IsBreakChar( char ch )
+{
+ bool brk = false;
+ switch ( ch )
+ {
+ case '{':
+ case '}':
+ case ')':
+ case '(':
+ case '[':
+ case ']':
+ case '\'':
+ case '/':
+ case ',':
+ case ';':
+ brk = true;
+ break;
+
+ case ':':
+ if ( !com_ignorecolons )
+ brk = true;
+ break;
+ default:
+ break;
+ }
+ return brk;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *data -
+// Output : char
+//-----------------------------------------------------------------------------
+char *CC_ParseToken(char *data)
+{
+ int c;
+ int len;
+
+ if ( s_com_token_unget )
+ {
+ s_com_token_unget = false;
+ return data;
+ }
+
+ len = 0;
+ com_token[0] = 0;
+
+ if (!data)
+ return NULL;
+
+// skip whitespace
+skipwhite:
+ while ( (c = *data) <= ' ')
+ {
+ if (c == 0)
+ {
+ return NULL; // end of file;
+ }
+ if ( c== '\n' )
+ {
+ linesprocessed++;
+ }
+ data++;
+ }
+
+// skip // comments
+ if ( !com_ignoreinlinecomment )
+ {
+ if (c=='/' && data[1] == '/')
+ {
+ while (*data && *data != '\n')
+ {
+ data++;
+ }
+ goto skipwhite;
+ }
+ }
+
+ if ( c == '/' && data[1] == '*' )
+ {
+ while (data[0] && data[1] && !( data[0] == '*' && data[1] == '/' ) )
+ {
+ if ( *data == '\n' )
+ {
+ linesprocessed++;
+ }
+ data++;
+ }
+
+ if ( data[0] == '*' && data[1] == '/' )
+ {
+ data+=2;
+ }
+ goto skipwhite;
+ }
+
+// handle quoted strings specially
+ if (c == '\"')
+ {
+ data++;
+ while (1)
+ {
+ c = *data++;
+ if (c=='\"' || !c || c =='\n' || len >= (sizeof( com_token ) - 1 ))
+ {
+ com_token[len] = 0;
+ return data;
+ }
+ com_token[len] = c;
+ len++;
+ }
+ }
+
+// parse single characters
+ if ( CC_IsBreakChar( c ) )
+ {
+ com_token[len] = c;
+ len++;
+ com_token[len] = 0;
+ return data+1;
+ }
+
+// parse a regular word
+ do
+ {
+ com_token[len] = c;
+ data++;
+ len++;
+ c = *data;
+ if ( CC_IsBreakChar( c ) )
+ break;
+ } while (c>32);
+ com_token[len] = 0;
+ return data;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// *len -
+// Output : unsigned char
+//-----------------------------------------------------------------------------
+
+static int allocated = 0;
+
+unsigned char *COM_LoadFile( const char *name, int *len)
+{
+ FILE *fp;
+ fp = fopen( name, "rb" );
+ if ( !fp )
+ {
+ *len = 0;
+ return NULL;
+ }
+
+ fseek( fp, 0, SEEK_END );
+ *len = ftell( fp );
+ fseek( fp, 0, SEEK_SET );
+
+ unsigned char *buffer = new unsigned char[ *len + 1 ];
+ fread( buffer, *len, 1, fp );
+ fclose( fp );
+ buffer[ *len ] = 0;
+
+ size_t nsize = _msize( buffer );
+ assert( nsize <= 5000000 );
+ allocated += nsize;
+
+
+ return buffer;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *buffer -
+//-----------------------------------------------------------------------------
+void COM_FreeFile( unsigned char *buffer )
+{
+ size_t nsize = _msize( buffer );
+ assert( nsize <= 5000000 );
+
+ allocated -= nsize;
+
+ delete[] buffer;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *dir -
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool COM_DirectoryExists( const char *dir )
+{
+ if ( !_access( dir, 0 ) )
+ return true;
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *input -
+// Output : char
+//-----------------------------------------------------------------------------
+char *CC_ParseUntilEndOfLine( char *input )
+{
+ while (*input && *input != '\n')
+ input++;
+
+ return input;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *input -
+// *ch -
+// *breakchar -
+// Output : char
+//-----------------------------------------------------------------------------
+char *CC_RawParseChar( char *input, const char *ch, char *breakchar )
+{
+ bool done = false;
+ int listlen = strlen( ch );
+
+ do
+ {
+ input = CC_ParseToken( input );
+ if ( strlen( com_token ) <= 0 )
+ break;
+
+ if ( strlen( com_token ) == 1 )
+ {
+ for ( int i = 0; i < listlen; i++ )
+ {
+ if ( com_token[ 0 ] == ch[ i ] )
+ {
+ *breakchar = ch [ i ];
+ done = true;
+ break;
+ }
+ }
+ }
+ } while ( !done );
+
+ return input;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *input -
+// *pairing -
+// Output : char
+//-----------------------------------------------------------------------------
+char *CC_DiscardUntilMatchingCharIncludingNesting( char *input, const char *pairing )
+{
+ int nestcount = 1;
+
+ do
+ {
+ input = CC_ParseToken( input );
+ if ( strlen( com_token ) <= 0 )
+ break;
+
+ if ( strlen( com_token ) == 1 )
+ {
+ if ( com_token[ 0 ] == pairing[ 0 ] )
+ {
+ nestcount++;
+ }
+ else if ( com_token[ 0 ] == pairing[ 1 ] )
+ {
+ nestcount--;
+ }
+ }
+ } while ( nestcount != 0 );
+
+ return input;
+} \ No newline at end of file
diff --git a/utils/depcheck/depcheck_util.h b/utils/depcheck/depcheck_util.h
new file mode 100644
index 0000000..9765db8
--- /dev/null
+++ b/utils/depcheck/depcheck_util.h
@@ -0,0 +1,29 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+#ifndef DEPCHECK_UTIL_H
+#define DEPCHECK_UTIL_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+void vprint( int depth, PRINTF_FORMAT_STRING const char *fmt, ... );
+void CC_UngetToken( void );
+char *CC_ParseToken(char *data);
+char *CC_DiscardUntilMatchingCharIncludingNesting( char *input, const char *pairing );
+char *CC_RawParseChar( char *input, const char *ch, char *breakchar );
+char *CC_ParseUntilEndOfLine( char *input );
+
+extern char com_token[1024];
+extern bool com_ignoreinlinecomment;
+extern int linesprocessed;
+
+unsigned char *COM_LoadFile( const char *name, int *len);
+void COM_FreeFile( unsigned char *buffer );
+bool COM_DirectoryExists( const char *dir );
+
+#endif // DEPCHECK_UTIL_H
diff --git a/utils/depcheck/icodeprocessor.h b/utils/depcheck/icodeprocessor.h
new file mode 100644
index 0000000..d6507db
--- /dev/null
+++ b/utils/depcheck/icodeprocessor.h
@@ -0,0 +1,28 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+#if !defined( ICODEPROCESSOR_H )
+#define ICODEPROCESSOR_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+class ICodeProcessor
+{
+public:
+ virtual void Process( const char *gamespecific, const char *root, const char *dsp, const char *config ) = 0;
+
+ virtual void SetQuiet( bool quiet ) = 0;
+ virtual bool GetQuiet( void ) const = 0;
+
+ virtual void SetLogFile( bool log ) = 0;
+ virtual bool GetLogFile( void ) const = 0;
+};
+
+extern ICodeProcessor *processor;
+
+#endif // ICODEPROCESSOR_H \ No newline at end of file
diff --git a/utils/depcheck/processmodule.cpp b/utils/depcheck/processmodule.cpp
new file mode 100644
index 0000000..11f21b9
--- /dev/null
+++ b/utils/depcheck/processmodule.cpp
@@ -0,0 +1,536 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+#include <assert.h>
+#include <time.h>
+#include "stdafx.h"
+#include <stdio.h>
+#include <windows.h>
+#include "depcheck_util.h"
+#include "codeprocessor.h"
+
+/*
+================
+UTIL_FloatTime
+================
+*/
+double UTIL_FloatTime (void)
+{
+// more precise, less portable
+ clock_t current;
+ static clock_t base;
+ static bool first = true;
+
+ current = clock();
+
+ if ( first )
+ {
+ first = false;
+
+ base = current;
+ }
+
+ return (double)(current - base)/(double)CLOCKS_PER_SEC;
+}
+
+void CCodeProcessor::AddHeader( int depth, const char *filename, const char *rootmodule )
+{
+// if ( depth < 1 )
+// return;
+ if ( depth != 1 )
+ return;
+
+ // Check header list
+ for ( int i = 0; i < m_nHeaderCount; i++ )
+ {
+ if ( !stricmp( m_Headers[ i ].name, filename ) )
+ {
+ vprint( 0, "%s included twice in module %s\n", filename, rootmodule );
+ return;
+ }
+ }
+
+ // Add to list
+ strcpy( m_Headers[ m_nHeaderCount++ ].name, filename );
+}
+
+void CCodeProcessor::CreateBackup( const char *filename, bool& wasreadonly )
+{
+ assert( strstr( filename, ".cpp" ) );
+
+ // attrib it, change extension, save it
+ if ( GetFileAttributes( filename ) & FILE_ATTRIBUTE_READONLY )
+ {
+ wasreadonly = true;
+
+ SetFileAttributes( filename, FILE_ATTRIBUTE_NORMAL );
+ }
+ else
+ {
+ wasreadonly = false;
+ }
+
+ char backupname[ 256 ];
+ strcpy( backupname, filename );
+ strcpy( (char *)&backupname[ strlen( filename ) - 4 ], ".bak" );
+
+ unlink( backupname );
+ rename( filename, backupname );
+
+}
+
+void CCodeProcessor::RestoreBackup( const char *filename, bool makereadonly )
+{
+ assert( strstr( filename, ".cpp" ) );
+
+ char backupname[ 256 ];
+ strcpy( backupname, filename );
+ strcpy( (char *)&backupname[ strlen( filename ) - 4 ], ".bak" );
+
+ SetFileAttributes( filename, FILE_ATTRIBUTE_NORMAL );
+
+ unlink( filename );
+ rename( backupname, filename );
+
+ if ( makereadonly )
+ {
+ SetFileAttributes( filename, FILE_ATTRIBUTE_READONLY );
+ }
+
+ unlink( backupname );
+}
+
+bool CCodeProcessor::TryBuild( const char *rootdir, const char *filename, unsigned char *buffer, int filelength )
+{
+// vprintf( "trying build\n" );
+
+ FILE *fp;
+ fp = fopen( filename, "wb" );
+ if ( !fp )
+ {
+ assert( 0 );
+ return false;
+ }
+
+ fwrite( buffer, filelength, 1, fp );
+ fclose( fp );
+
+ // if build is successful, return true
+ //
+ // return true;
+ char commandline[ 512 ];
+ char directory[ 512 ];
+
+ sprintf( directory, rootdir );
+
+ // sprintf( commandline, "msdev engdll.dsw /MAKE \"quiver - Win32 GL Debug\" /OUT log.txt" );
+
+ // Builds the default configuration
+ sprintf( commandline, "\"C:\\Program Files\\Microsoft Visual Studio\\Common\\MSDev98\\Bin\\msdev.exe\" %s /MAKE \"%s\" /OUT log.txt", m_szDSP, m_szConfig );
+
+ PROCESS_INFORMATION pi;
+ memset( &pi, 0, sizeof( pi ) );
+
+ STARTUPINFO si;
+ memset( &si, 0, sizeof( si ) );
+ si.cb = sizeof( si );
+
+ if ( !CreateProcess( NULL, commandline, NULL, NULL, TRUE, 0, NULL, directory, &si, &pi ) )
+ {
+LPVOID lpMsgBuf;
+FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL
+);
+// Process any inserts in lpMsgBuf.
+// ...
+// Display the string.
+MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
+// Free the buffer.
+LocalFree( lpMsgBuf );
+ return false;
+ }
+
+ // Wait until child process exits.
+ WaitForSingleObject( pi.hProcess, INFINITE );
+
+ bool retval = false;
+ DWORD exitCode = -1;
+ if ( GetExitCodeProcess( pi.hProcess, &exitCode ) )
+ {
+ if ( !exitCode )
+ {
+ retval = true;
+ }
+ }
+
+ // Close process and thread handles.
+ CloseHandle( pi.hProcess );
+ CloseHandle( pi.hThread );
+
+ return retval;
+}
+
+void CCodeProcessor::ProcessModule( bool forcequiet, int depth, int& maxdepth, int& numheaders, int& skippedfiles, const char *baseroot, const char *root, const char *module )
+{
+ char filename[ 256 ];
+
+ bool checkroot = false;
+
+ if ( depth > maxdepth )
+ {
+ maxdepth = depth;
+ }
+
+ // Load the base module
+ sprintf( filename, "%s\\%s", root, module );
+ strlwr( filename );
+
+ bool firstheader = true;
+retry:
+
+ // Check module list
+ for ( int i = 0; i < m_nModuleCount; i++ )
+ {
+ if ( !stricmp( m_Modules[ i ].name, filename ) )
+ {
+ if ( forcequiet )
+ {
+ m_nHeadersProcessed++;
+ numheaders++;
+
+ if ( m_Modules[ i ].skipped )
+ {
+ skippedfiles++;
+ }
+ }
+
+ AddHeader( depth, filename, m_szCurrentCPP );
+
+ return;
+ }
+ }
+
+ int filelength;
+ char *buffer = (char *)COM_LoadFile( filename, &filelength );
+ if ( !buffer )
+ {
+ if ( !checkroot )
+ {
+ checkroot = true;
+ // Load the base module
+ sprintf( filename, "%s\\%s", baseroot, module );
+ goto retry;
+ }
+ m_Modules[ m_nModuleCount ].skipped = true;
+ strcpy( m_Modules[ m_nModuleCount++ ].name, filename );
+
+ skippedfiles++;
+ return;
+ }
+
+ m_nBytesProcessed += filelength;
+
+ m_Modules[ m_nModuleCount ].skipped = false;
+ strcpy( m_Modules[ m_nModuleCount++ ].name, filename );
+
+ bool readonly = false;
+ bool madechanges = false;
+ CreateBackup( filename, readonly );
+
+ if ( !forcequiet )
+ {
+ strcpy( m_szCurrentCPP, filename );
+
+ vprint( 0, "- %s\n", (char *)&filename[ m_nOffset ] );
+ }
+
+ // Parse tokens looking for #include directives or class starts
+ char *current = buffer;
+ char *startofline;
+
+ current = CC_ParseToken( current );
+ while ( current )
+ {
+ // No more tokens
+ if ( strlen( com_token ) <= 0 )
+ break;
+
+ if ( !stricmp( com_token, "#include" ) )
+ {
+ startofline = current - strlen( "#include" );
+
+ current = CC_ParseToken( current );
+
+ if ( strlen( com_token ) > 0)
+ {
+ vprint( 1, "#include %s", com_token );
+ m_nHeadersProcessed++;
+ numheaders++;
+
+ AddHeader( depth, filename, m_szCurrentCPP );
+
+ bool dobuild = true;
+ if ( firstheader )
+ {
+ if ( !stricmp( com_token, "cbase.h" ) )
+ {
+ dobuild = false;
+ }
+
+ if ( !TryBuild( baseroot, filename, (unsigned char *)buffer, filelength ) )
+ {
+ // build is broken, stop
+ assert( 0 );
+ }
+ }
+
+ firstheader = false;
+
+ if ( dobuild )
+ {
+ // Try removing the header and compiling
+ char saveinfo[2];
+ memcpy( saveinfo, startofline, 2 );
+ startofline[ 0 ] = '/';
+ startofline[ 1 ] = '/';
+
+ if ( TryBuild( baseroot, filename, (unsigned char *)buffer, filelength ) )
+ {
+ vprint( 0, ", unnecessary\n" );
+ madechanges = true;
+ }
+ else
+ {
+ // Restore line
+ memcpy( startofline, saveinfo, 2 );
+ vprint( 0, "\n" );
+ }
+ }
+ else
+ {
+ vprint( 0, "\n" );
+ }
+ }
+ }
+
+ current = CC_ParseToken( current );
+ }
+
+ // Save out last set of changes
+ {
+ FILE *fp;
+ fp = fopen( filename, "wb" );
+ if ( fp )
+ {
+ fwrite( buffer, filelength, 1, fp );
+ fclose( fp );
+ }
+ }
+
+ COM_FreeFile( (unsigned char *)buffer );
+
+ if ( !madechanges )
+ {
+ RestoreBackup( filename, readonly );
+ }
+
+ if ( !forcequiet && !GetQuiet() )
+ {
+ vprint( 0, " %s: headers (%i)", (char *)&filename[ m_nOffset ], numheaders );
+ if ( maxdepth > 1 )
+ {
+ vprint( 0, ", depth %i", maxdepth );
+ }
+ vprint( 0, "\n" );
+ }
+
+ m_nLinesOfCode += linesprocessed;
+ linesprocessed = 0;
+}
+
+void CCodeProcessor::ProcessModules( const char *root, const char *rootmodule )
+{
+ m_nFilesProcessed++;
+
+ // Reset header list per module
+ m_nHeaderCount = 0;
+ m_nModuleCount = 0;
+
+ int numheaders = 0;
+ int maxdepth = 0;
+ int skippedfiles = 0;
+
+ bool canstart = false;
+
+ if ( strstr( root, "tf2_hud" ) )
+ {
+ canstart = true;
+ }
+ if ( !canstart )
+ {
+ vprint( 0, "skipping %s\n", rootmodule );
+ return;
+ }
+ ProcessModule( false, 0, maxdepth, numheaders, skippedfiles, root, root, rootmodule );
+}
+
+void CCodeProcessor::PrintResults( void )
+{
+ vprint( 0, "\nChecking for errors and totaling...\n\n" );
+
+ vprint( 0, "parsed from %i files ( %i headers parsed )\n",
+ m_nFilesProcessed,
+ m_nHeadersProcessed );
+
+ vprint( 0, "%.3f K lines of code processed\n",
+ (double)m_nLinesOfCode / 1024.0 );
+
+ double elapsed = ( m_flEnd - m_flStart );
+
+ if ( elapsed > 0.0 )
+ {
+ vprint( 0, "%.2f K processed in %.3f seconds, throughput %.2f KB/sec\n\n",
+ (double)m_nBytesProcessed / 1024.0, elapsed, (double)m_nBytesProcessed / ( 1024.0 * elapsed ) );
+ }
+}
+
+CCodeProcessor::CCodeProcessor( void )
+{
+ m_nModuleCount = 0;
+
+ m_bQuiet = false;
+ m_bLogToFile = false;
+
+ m_nFilesProcessed = 0;
+ m_nHeadersProcessed = 0;
+ m_nOffset = 0;
+ m_nBytesProcessed = 0;
+ m_nLinesOfCode = 0;
+ m_flStart = 0.0;
+ m_flEnd = 0.0;
+
+ m_szCurrentCPP[ 0 ] = 0;
+}
+
+CCodeProcessor::~CCodeProcessor( void )
+{
+}
+
+char const *stristr( char const *src, char const *search )
+{
+ char buf1[ 512 ];
+ char buf2[ 512 ];
+
+ strcpy( buf1, src );
+ _strlwr( buf1 );
+
+ strcpy( buf2, search );
+ _strlwr( buf2 );
+
+ char *p = strstr( buf1, buf2 );
+ if ( p )
+ {
+ int len = p - buf1;
+ return src + len;
+ }
+ return NULL;
+}
+
+void CCodeProcessor::ConstructModuleList_R( int level, const char *gamespecific, const char *root )
+{
+ char directory[ 256 ];
+ char filename[ 256 ];
+ WIN32_FIND_DATA wfd;
+ HANDLE ff;
+
+ sprintf( directory, "%s\\*.*", root );
+
+ if ( ( ff = FindFirstFile( directory, &wfd ) ) == INVALID_HANDLE_VALUE )
+ return;
+
+ do
+ {
+ if ( wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
+ {
+
+ if ( wfd.cFileName[ 0 ] == '.' )
+ continue;
+
+ // Once we descend down a branch, don't keep looking for hl2/tf2 in name, just recurse through all children
+ if ( level == 0 && !stristr( wfd.cFileName, gamespecific ) )
+ continue;
+
+ // Recurse down directory
+ sprintf( filename, "%s\\%s", root, wfd.cFileName );
+ ConstructModuleList_R( level+1, gamespecific, filename );
+ }
+ else
+ {
+ if ( strstr( wfd.cFileName, ".cpp" ) )
+ {
+ ProcessModules( root, wfd.cFileName );
+ }
+ }
+ } while ( FindNextFile( ff, &wfd ) );
+}
+
+void CCodeProcessor::Process( const char *gamespecific, const char *root, const char *dsp, const char *config )
+{
+ strcpy( m_szDSP, dsp );
+ strcpy( m_szConfig, config );
+
+ m_nBytesProcessed = 0;
+ m_nFilesProcessed = 0;
+ m_nHeadersProcessed = 0;
+ m_nLinesOfCode = 0;
+
+ linesprocessed = 0;
+
+ m_nOffset = strlen( root ) + 1;
+
+ m_nModuleCount = 0;
+ m_nHeaderCount = 0;
+ m_flStart = UTIL_FloatTime();
+
+ vprint( 0, "--- Processing %s\n\n", root );
+
+ ConstructModuleList_R( 0, gamespecific, root );
+
+ m_flEnd = UTIL_FloatTime();
+
+ PrintResults();
+}
+
+void CCodeProcessor::SetQuiet( bool quiet )
+{
+ m_bQuiet = quiet;
+}
+
+bool CCodeProcessor::GetQuiet( void ) const
+{
+ return m_bQuiet;
+}
+
+void CCodeProcessor::SetLogFile( bool log )
+{
+ m_bLogToFile = log;
+}
+
+bool CCodeProcessor::GetLogFile( void ) const
+{
+ return m_bLogToFile;
+}
+
+static CCodeProcessor g_Processor;
+ICodeProcessor *processor = ( ICodeProcessor * )&g_Processor; \ No newline at end of file
diff --git a/utils/depcheck/stdafx.cpp b/utils/depcheck/stdafx.cpp
new file mode 100644
index 0000000..091b109
--- /dev/null
+++ b/utils/depcheck/stdafx.cpp
@@ -0,0 +1,15 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+// stdafx.cpp : source file that includes just the standard includes
+// depcheck.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/utils/depcheck/stdafx.h b/utils/depcheck/stdafx.h
new file mode 100644
index 0000000..c906e25
--- /dev/null
+++ b/utils/depcheck/stdafx.h
@@ -0,0 +1,26 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__CFA05F67_DD26_4A89_97BF_1704A49209A6__INCLUDED_)
+#define AFX_STDAFX_H__CFA05F67_DD26_4A89_97BF_1704A49209A6__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+
+// TODO: reference additional headers your program requires here
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__CFA05F67_DD26_4A89_97BF_1704A49209A6__INCLUDED_)