mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-07 17:29:36 +00:00
1
This commit is contained in:
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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
|
||||
@@ -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_)
|
||||
Reference in New Issue
Block a user