diff options
Diffstat (limited to 'utils/depcheck')
| -rw-r--r-- | utils/depcheck/codeprocessor.h | 74 | ||||
| -rw-r--r-- | utils/depcheck/depcheck.cpp | 122 | ||||
| -rw-r--r-- | utils/depcheck/depcheck.vpc | 27 | ||||
| -rw-r--r-- | utils/depcheck/depcheck_util.cpp | 363 | ||||
| -rw-r--r-- | utils/depcheck/depcheck_util.h | 29 | ||||
| -rw-r--r-- | utils/depcheck/icodeprocessor.h | 28 | ||||
| -rw-r--r-- | utils/depcheck/processmodule.cpp | 536 | ||||
| -rw-r--r-- | utils/depcheck/stdafx.cpp | 15 | ||||
| -rw-r--r-- | utils/depcheck/stdafx.h | 26 |
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_) |