summaryrefslogtreecommitdiff
path: root/utils/classcheck/processmodule.cpp
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/classcheck/processmodule.cpp
downloadarchived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz
archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip
Diffstat (limited to 'utils/classcheck/processmodule.cpp')
-rw-r--r--utils/classcheck/processmodule.cpp1866
1 files changed, 1866 insertions, 0 deletions
diff --git a/utils/classcheck/processmodule.cpp b/utils/classcheck/processmodule.cpp
new file mode 100644
index 0000000..fd5c2b1
--- /dev/null
+++ b/utils/classcheck/processmodule.cpp
@@ -0,0 +1,1866 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+#include <assert.h>
+#include <time.h>
+#include "stdafx.h"
+#include <stdio.h>
+#include <windows.h>
+#include "classcheck_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;
+}
+
+CClass *CCodeProcessor::FindClass( const char *name ) const
+{
+ CClass *cl = m_pClassList;
+ while ( cl )
+ {
+ if ( !stricmp( cl->m_szName, name ) )
+ return cl;
+
+ cl = cl->m_pNext;
+ }
+ return NULL;
+}
+
+void ClearMissingTypes();
+
+void CCodeProcessor::Clear( void )
+{
+ ClearMissingTypes();
+
+ CClass *cl = m_pClassList, *next;
+ while ( cl )
+ {
+ next = cl->m_pNext;
+ delete cl;
+ cl = next;
+ }
+ m_pClassList = NULL;
+}
+
+
+
+int CCodeProcessor::Count( void ) const
+{
+ int c = 0;
+ CClass *cl = m_pClassList;
+ while ( cl )
+ {
+ c++;
+ cl = cl->m_pNext;
+ }
+ return c;
+}
+
+int FnClassSortCompare( const void *elem1, const void *elem2 )
+{
+ CClass *c1 = *(CClass **)elem1;
+ CClass *c2 = *(CClass **)elem2;
+
+ return ( stricmp( c1->m_szName, c2->m_szName ) );
+}
+
+void CCodeProcessor::SortClassList( void )
+{
+ int n = Count();
+ if ( n <= 1 )
+ return;
+
+ CClass **ppList = new CClass *[ n ];
+ if ( ppList )
+ {
+ CClass *cl;
+ int i;
+ for ( i = 0, cl = m_pClassList; i < n; i++, cl = cl->m_pNext )
+ {
+ ppList[ i ] = cl;
+ }
+
+ qsort( ppList, n, sizeof( CClass * ), FnClassSortCompare );
+
+ for ( i = 0; i < n - 1; i++ )
+ {
+ ppList[ i ]->m_pNext = ppList[ i + 1 ];
+ }
+ ppList[ i ]->m_pNext = NULL;
+ m_pClassList = ppList[ 0 ];
+ }
+ delete[] ppList;
+}
+
+void CCodeProcessor::ResolveBaseClasses( const char *baseentityclass )
+{
+ SortClassList();
+
+ CClass *cl = m_pClassList;
+ while ( cl )
+ {
+ if ( cl->m_szBaseClass[0] )
+ {
+ cl->m_pBaseClass = FindClass( cl->m_szBaseClass );
+ if ( !cl->m_pBaseClass )
+ {
+ //vprint( 0, "couldn't find base class %s for %s\n", cl->m_szBaseClass, cl->m_szName );
+ }
+ }
+
+ cl = cl->m_pNext;
+ }
+
+ cl = m_pClassList;
+ while ( cl )
+ {
+ cl->CheckChildOfBaseEntity( baseentityclass );
+ cl = cl->m_pNext;
+ }
+}
+
+void CCodeProcessor::PrintMissingTDFields( void ) const
+{
+ int classcount;
+ int fieldcount;
+ int c;
+
+ CClass *cl;
+
+ if ( GetPrintTDs() )
+ {
+ classcount = 0;
+ fieldcount = 0;
+ cl = m_pClassList;
+ while ( cl )
+ {
+ if ( cl->m_bDerivedFromCBaseEntity || cl->m_bHasSaveRestoreData )
+ {
+ if ( cl->CheckForMissingTypeDescriptionFields( c ) )
+ {
+ classcount++;
+ fieldcount += c;
+ }
+ }
+ cl = cl->m_pNext;
+ }
+
+ if ( fieldcount )
+ {
+ vprint( 0, "\nSummary: %i fields missing from %i classes\n", fieldcount, classcount );
+ }
+ else
+ {
+ if ( !classcount )
+ {
+ vprint( 0, "\nSummary: no saverestore info present\n");
+ }
+ else
+ {
+ vprint( 0, "\nSummary: no errors for %i classes\n", classcount );
+ }
+ }
+
+ vprint( 0, "\n" );
+ }
+
+ if ( GetPrintPredTDs() )
+ {
+ //Now check prediction stuff
+ classcount = 0;
+ fieldcount = 0;
+ cl = m_pClassList;
+ while ( cl )
+ {
+ if ( cl->m_bDerivedFromCBaseEntity || cl->m_bHasPredictionData )
+ {
+ if ( cl->CheckForMissingPredictionFields( c, false ) )
+ {
+ classcount++;
+ fieldcount += c;
+ }
+ }
+ cl = cl->m_pNext;
+ }
+
+ if ( fieldcount )
+ {
+ vprint( 0, "\nSummary: %i prediction fields missing from %i classes\n", fieldcount, classcount );
+ }
+ else
+ {
+ if ( !classcount )
+ {
+ vprint( 0, "\nSummary: no prediction info present\n");
+ }
+ else
+ {
+ vprint( 0, "\nSummary: no errors for %i predictable classes\n", classcount );
+ }
+ }
+
+ vprint( 0, "\n" );
+ }
+
+ if ( GetPrintCreateMissingTDs() )
+ {
+ //Now check prediction stuff
+ classcount = 0;
+ fieldcount = 0;
+ cl = m_pClassList;
+ while ( cl )
+ {
+ if ( cl->m_bDerivedFromCBaseEntity || cl->m_bHasSaveRestoreData )
+ {
+ if ( cl->CheckForMissingTypeDescriptionFields( c, true ) )
+ {
+ classcount++;
+ fieldcount += c;
+ }
+ }
+ cl = cl->m_pNext;
+ }
+
+ if ( fieldcount )
+ {
+ vprint( 0, "\nSummary: %i saverestore fields missing from %i classes\n", fieldcount, classcount );
+ }
+ else
+ {
+ if ( !classcount )
+ {
+ vprint( 0, "\nSummary: no saverestore info present\n");
+ }
+ else
+ {
+ vprint( 0, "\nSummary: no errors for %i classes\n", classcount );
+ }
+ }
+
+ vprint( 0, "\n" );
+ }
+
+ if ( GetPrintCreateMissingPredTDs() )
+ {
+ //Now check prediction stuff
+ classcount = 0;
+ fieldcount = 0;
+ cl = m_pClassList;
+ while ( cl )
+ {
+ if ( cl->m_bDerivedFromCBaseEntity || cl->m_bHasPredictionData )
+ {
+ if ( cl->CheckForMissingPredictionFields( c, true ) )
+ {
+ classcount++;
+ fieldcount += c;
+ }
+ }
+ cl = cl->m_pNext;
+ }
+
+ if ( fieldcount )
+ {
+ vprint( 0, "\nSummary: %i prediction fields missing from %i classes\n", fieldcount, classcount );
+ }
+ else
+ {
+ if ( !classcount )
+ {
+ vprint( 0, "\nSummary: no prediction info present\n");
+ }
+ else
+ {
+ vprint( 0, "\nSummary: no errors for %i predictable classes\n", classcount );
+ }
+ }
+
+ vprint( 0, "\n" );
+ }
+
+ // Now check for things that are in the prediction TD but not marked correctly as being part of the sendtable
+ {
+ //Now check prediction stuff
+ classcount = 0;
+ fieldcount = 0;
+ cl = m_pClassList;
+ while ( cl )
+ {
+ if ( cl->m_bDerivedFromCBaseEntity || cl->m_bHasPredictionData )
+ {
+ if ( cl->CheckForPredictionFieldsInRecvTableNotMarkedAsSuchCorrectly( c ) )
+ {
+ classcount++;
+ fieldcount += c;
+ }
+ }
+ cl = cl->m_pNext;
+ }
+
+ vprint( 0, "\n" );
+ }
+
+ // Print stuff derived from CBaseEntity that doesn't have save/restore data
+ vprint( 0, "\nMissing DATADESC tables:\n\n" );
+ cl = m_pClassList;
+ while ( cl )
+ {
+ if ( cl->m_bDerivedFromCBaseEntity && !cl->m_bHasSaveRestoreData && cl->m_nVarCount )
+ {
+ vprint( 0, "\t%s\n", cl->m_szName );
+ }
+ cl = cl->m_pNext;
+ }
+ vprint( 0, "\n" );
+}
+
+void CCodeProcessor::ReportHungarianNotationErrors()
+{
+ if ( !GetCheckHungarian() )
+ return;
+
+ vprint( 0, "\tChecking for hungarian notation issues\n" );
+
+ CClass *cl = m_pClassList;
+ int classcount = 0;
+ int warningcount = 0;
+ while ( cl )
+ {
+ int c = 0;
+
+ cl->CheckForHungarianErrors( c );
+
+ classcount++;
+ warningcount += c;
+
+ cl = cl->m_pNext;
+ }
+
+ vprint( 0, "\tFound %i notation errors across %i classes\n", classcount, warningcount );
+}
+
+void CCodeProcessor::PrintClassList( void ) const
+{
+ if ( GetPrintHierarchy() )
+ {
+ vprint( 0, "\nClass Summary\n\n" );
+ }
+
+ CClass *cl = m_pClassList;
+
+ while ( cl )
+ {
+ if ( cl->m_bDerivedFromCBaseEntity )
+ {
+ bool missing = false;
+ char missingwarning[ 128 ];
+
+ missingwarning[0]=0;
+ if ( cl->m_szTypedefBaseClass[0] )
+ {
+ if ( stricmp( cl->m_szBaseClass, cl->m_szTypedefBaseClass ) )
+ {
+ vprint( 0, "class %s has incorrect typedef %s BaseClass\n", cl->m_szName, cl->m_szTypedefBaseClass );
+ }
+ }
+ else if ( cl->m_szBaseClass[ 0 ] )
+ {
+ missing = true;
+ sprintf( missingwarning, ", missing typedef %s BaseClass", cl->m_szBaseClass );
+ }
+
+ if ( GetPrintHierarchy() || missing )
+ {
+ vprint( 0, "class %s%s\n", cl->m_szName, missing ? missingwarning : "" );
+ }
+
+ int level = 1;
+ CClass *base = cl->m_pBaseClass;
+ while ( base )
+ {
+ if ( GetPrintHierarchy() )
+ {
+ vprint( level++, "public %s\n", base->m_szName );
+ }
+ base = base->m_pBaseClass;
+ }
+
+ int i;
+
+ if ( GetPrintHierarchy() && GetPrintMembers() )
+ {
+
+ if ( cl->m_nMemberCount )
+ {
+ vprint( 1, "\nMember functions:\n\n" );
+ }
+
+ for ( i = 0; i < cl->m_nMemberCount; i++ )
+ {
+ CClassMemberFunction *member = cl->m_Members[ i ];
+
+ if ( member->m_szType[0] )
+ {
+ vprint( 1, "%s %s();\n", member->m_szType, member->m_szName );
+ }
+ else
+ {
+ char *p = member->m_szName;
+ if ( *p == '~' )
+ p++;
+
+ if ( stricmp( p, cl->m_szName ) )
+ {
+ vprint( 0, "class %s has member function %s with no return type!!!\n",
+ cl->m_szName, member->m_szName );
+ }
+ vprint( 1, "%s();\n", member->m_szName );
+ }
+ }
+
+ if ( cl->m_nVarCount )
+ {
+ vprint( 1, "\nMember Variables\n\n" );
+ }
+
+
+ for ( i = 0; i < cl->m_nVarCount; i++ )
+ {
+ CClassVariable *var = cl->m_Variables[ i ];
+
+ if ( var->m_bIsArray )
+ {
+ if ( var->m_szArraySize[0]==0 )
+ {
+ vprint( 1, "%s %s[];\n", var->m_szType, var->m_szName );
+ }
+ else
+ {
+ vprint( 1, "%s %s[ %s ];\n", var->m_szType, var->m_szName, var->m_szArraySize );
+ }
+ }
+ else
+ {
+ vprint( 1, "%s %s;\n", var->m_szType, var->m_szName );
+ }
+ }
+
+ if ( cl->m_nTDCount )
+ {
+ vprint( 1, "\nSave/Restore TYPEDESCRIPTION\n\n" );
+ }
+
+ for ( i = 0; i < cl->m_nTDCount; i++ )
+ {
+ CTypeDescriptionField *td = cl->m_TDFields[ i ];
+ if ( td->m_bCommentedOut )
+ {
+ vprint( 1, "// " );
+ }
+ else
+ {
+ vprint( 1, "" );
+ }
+
+ vprint( 0, "%s( %s, %s, %s, ... )\n", td->m_szDefineType, cl->m_szName, td->m_szVariableName, td->m_szType );
+ }
+
+ if ( !cl->m_bHasSaveRestoreData )
+ {
+ // vprint( 1, "\nSave/Restore TYPEDESCRIPTION not specified for class\n\n" );
+ }
+
+ if ( cl->m_nPredTDCount )
+ {
+ vprint( 1, "\nPrediction TYPEDESCRIPTION\n\n" );
+ }
+
+ for ( i = 0; i < cl->m_nPredTDCount; i++ )
+ {
+ CTypeDescriptionField *td = cl->m_PredTDFields[ i ];
+ if ( td->m_bCommentedOut )
+ {
+ vprint( 1, "// " );
+ }
+ else
+ {
+ vprint( 1, "" );
+ }
+
+ vprint( 0, "%s( %s, %s, %s, ... )\n", td->m_szDefineType, cl->m_szName, td->m_szVariableName, td->m_szType );
+ }
+
+ if ( !cl->m_bHasPredictionData )
+ {
+ // vprint( 1, "\nPrediction TYPEDESCRIPTION not specified for class\n\n" );
+ }
+ }
+
+ if ( GetPrintHierarchy() )
+ {
+ vprint( 0, "\n" );
+ }
+ }
+
+ cl = cl->m_pNext;
+ }
+}
+
+CClass *CCodeProcessor::AddClass( const char *classname )
+{
+ CClass *cl = FindClass( classname );
+ if ( !cl )
+ {
+ cl = new CClass( classname );
+
+ m_nClassesParsed++;
+
+ cl->m_pNext = m_pClassList;
+ m_pClassList = cl;
+ }
+ return cl;
+}
+
+
+
+char *CCodeProcessor::ParseTypeDescription( char *current, bool fIsMacroized )
+{
+ // Next token is classname then :: then variablename then braces then = then {
+ char classname[ 256 ];
+ char variablename[ 256 ];
+
+ if ( !fIsMacroized )
+ {
+ current = CC_ParseToken( current );
+ if ( strlen( com_token ) <= 0 )
+ return current;
+
+ strcpy( classname, com_token );
+ if ( classname[0]=='*' )
+ return current;
+
+ current = CC_ParseToken( current );
+ if (stricmp( com_token, ":" ) )
+ {
+ return current;
+ }
+
+ current = CC_ParseToken( current );
+ Assert( !stricmp( com_token, ":" ) );
+
+ current = CC_ParseToken( current );
+ if ( strlen( com_token ) <= 0 )
+ return current;
+
+ strcpy( variablename, com_token );
+ }
+ else
+ {
+ current = CC_ParseToken( current );
+ if (stricmp( com_token, "(" ) )
+ {
+ return current;
+ }
+
+ current = CC_ParseToken( current );
+ if ( strlen( com_token ) <= 0 )
+ return current;
+
+ strcpy( classname, com_token );
+ if ( classname[0]=='*' )
+ return current;
+
+ current = CC_ParseToken( current );
+ if (stricmp( com_token, ")" ) )
+ {
+ return current;
+ }
+
+ // It's macro-ized
+ strcpy( variablename, "m_DataDesc" );
+ }
+ if ( !fIsMacroized )
+ {
+ char ch;
+ current = CC_RawParseChar( current, "{", &ch );
+ Assert( ch == '{' );
+ if ( strlen( com_token ) <= 0 )
+ return current;
+ }
+
+ com_ignoreinlinecomment = true;
+ bool insidecomment = false;
+
+ // Now parse typedescription line by line
+ while ( 1 )
+ {
+ current = CC_ParseToken( current );
+ if ( strlen( com_token ) <= 0 )
+ break;
+
+ // Go to next line
+ if ( !stricmp( com_token, "," ) )
+ continue;
+
+ // end
+ if ( !fIsMacroized )
+ {
+ if ( !stricmp( com_token, "}" ) )
+ break;
+ }
+ else
+ {
+ if ( !stricmp( com_token, "END_DATADESC" ) ||
+ !stricmp( com_token, "END_BYTESWAP_DATADESC" ) )
+ break;
+ }
+
+ // skip #ifdef's inside of typedescs
+ if ( com_token[0]=='#' )
+ {
+ current = CC_ParseUntilEndOfLine( current );
+ continue;
+ }
+
+ if ( !stricmp( com_token, "/" ) )
+ {
+ current = CC_ParseToken( current );
+ if ( !stricmp( com_token, "/" ) )
+ {
+ // There are two styles supported. One is to have the member definition present but commented out:
+ // DEFINE_FIELD( m_member, FIELD_INTEGER ),
+ // the other is to have a comment where the first token of the comment is a member name:
+ // m_member
+ current = CC_ParseToken( current );
+ if ( !strnicmp( com_token, "DEFINE_", 7 ) )
+ {
+ CC_UngetToken();
+ insidecomment = true;
+ }
+ else
+ {
+ char commentedvarname[ 256 ];
+ strcpy( commentedvarname, com_token );
+
+ CClass *cl = FindClass( classname );
+ if ( cl )
+ {
+ if ( !cl->FindTD( commentedvarname ) )
+ {
+ cl->AddTD( commentedvarname, "", "", true );
+ }
+ // Mark that it has a data table
+ cl->m_bHasSaveRestoreData = true;
+ }
+ current = CC_ParseUntilEndOfLine( current );
+ }
+ continue;
+ }
+ }
+
+ com_ignoreinlinecomment = false;
+
+ // Parse a typedescription line
+ char definetype[ 256 ];
+ strcpy( definetype, com_token );
+
+ current = CC_ParseToken( current );
+ if ( stricmp( com_token, "(" ) )
+ break;
+
+ char varname[ 256 ];
+ current = CC_ParseToken( current );
+
+ strcpy( varname, com_token );
+
+
+ char vartype[ 256 ];
+
+ vartype[0]=0;
+
+ if ( !stricmp( definetype, "DEFINE_FUNCTION" ) ||
+ !stricmp( definetype, "DEFINE_THINKFUNC" ) ||
+ !stricmp( definetype, "DEFINE_ENTITYFUNC" ) ||
+ !stricmp( definetype, "DEFINE_USEFUNC" ) ||
+ !stricmp( definetype, "DEFINE_OUTPUT" ) ||
+ !stricmp( definetype, "DEFINE_INPUTFUNC" ) )
+ {
+ strcpy( vartype, "funcptr" );
+ }
+ else if ( !stricmp(definetype, "DEFINE_FIELD") ||
+ !stricmp(definetype, "DEFINE_INDEX") ||
+ !stricmp(definetype, "DEFINE_KEYFIELD") ||
+ !stricmp(definetype, "DEFINE_KEYFIELD_NOT_SAVED") ||
+ !stricmp(definetype, "DEFINE_UTLVECTOR") ||
+ !stricmp(definetype, "DEFINE_GLOBAL_FIELD") ||
+ !stricmp(definetype, "DEFINE_GLOBAL_KEYFIELD") ||
+ !stricmp(definetype, "DEFINE_CUSTOM_FIELD") ||
+ !stricmp(definetype, "DEFINE_INPUT") ||
+ !stricmp(definetype, "DEFINE_AUTO_ARRAY") ||
+ !stricmp(definetype, "DEFINE_AUTO_ARRAY_KEYFIELD") ||
+ !stricmp(definetype, "DEFINE_AUTO_ARRAY2D") ||
+ !stricmp(definetype, "DEFINE_ARRAY") )
+ {
+ // skip comma
+ current = CC_ParseToken( current );
+ if (!strcmp( com_token, "[" ))
+ {
+ // Read array...
+ current = CC_ParseToken( current );
+ strcat( varname, "[" );
+ strcat( varname, com_token );
+ current = CC_ParseToken( current );
+
+ // eat everything until the next "]"
+ while (strcmp( com_token, "]") != 0)
+ {
+ strcat( varname, com_token );
+ current = CC_ParseToken( current );
+ }
+
+ if ( strcmp( com_token, "]" ))
+ {
+ current = current;
+ }
+
+ strcat( varname, "]" );
+
+ // skip comma
+ current = CC_ParseToken( current );
+ }
+
+ current = CC_ParseToken( current );
+
+ strcpy( vartype, com_token );
+ }
+
+ // Jump to end of definition
+ int nParenCount = 1;
+ do
+ {
+ current = CC_ParseToken( current );
+ if ( strlen( com_token ) <= 0 )
+ break;
+
+ if ( !stricmp( com_token, "(" ) )
+ {
+ ++nParenCount;
+ }
+ else if ( !stricmp( com_token, ")" ) )
+ {
+ if ( --nParenCount == 0 )
+ {
+ break;
+ }
+ }
+
+ } while ( 1 );
+
+// vprint( 2, "%s%s::%s %s %s %s\n",
+// insidecomment ? "// " : "",
+// classname, variablename,
+// definetype, varname, vartype );
+
+ CClass *cl = FindClass( classname );
+ if ( cl )
+ {
+ if ( strcmp( vartype, "funcptr" ) && cl->FindTD( varname ) )
+ {
+ vprint( 0, "class %s::%s already has typedescription entry for field %s\n", classname, variablename, varname );
+ }
+ else
+ {
+ cl->AddTD( varname, vartype, definetype, insidecomment );
+ }
+ // Mark that it has a data table
+ cl->m_bHasSaveRestoreData = true;
+ }
+ insidecomment = false;
+ com_ignoreinlinecomment = true;
+ }
+
+ com_ignoreinlinecomment = false;
+
+ return current;
+}
+
+char *CCodeProcessor::ParseReceiveTable( char *current )
+{
+ // Next token is open paren, then classname close paren, then {
+ char classname[ 256 ];
+
+ current = CC_ParseToken( current );
+ if (stricmp( com_token, "(" ) )
+ {
+ return current;
+ }
+
+ current = CC_ParseToken( current );
+ if ( strlen( com_token ) <= 0 )
+ return current;
+
+ strcpy( classname, com_token );
+ if ( classname[0]=='*' )
+ return current;
+ if ( !strcmp( classname, "className" ) )
+ return current;
+ if ( !strcmp( classname, "clientClassName" ) )
+ return current;
+
+ CClass *cl = FindClass( classname );
+ if ( cl )
+ {
+ cl->m_bHasRecvTableData = true;
+ }
+
+ CClass *leafClass = cl;
+
+ // parse until end of line
+ current = CC_ParseUntilEndOfLine( current );
+
+ // Now parse recvtable entries line by line
+ while ( 1 )
+ {
+ cl = leafClass;
+
+ current = CC_ParseToken( current );
+ if ( strlen( com_token ) <= 0 )
+ break;
+
+ // Go to next line
+ if ( !stricmp( com_token, "," ) )
+ continue;
+
+ // end
+ if ( !stricmp( com_token, "END_RECV_TABLE" ) )
+ break;
+
+ // skip #ifdef's inside of recv tables
+ if ( com_token[0]=='#' )
+ {
+ current = CC_ParseUntilEndOfLine( current );
+ continue;
+ }
+
+ // Parse recproxy line
+ char recvproptype[ 256 ];
+ strcpy( recvproptype, com_token );
+
+ if ( strnicmp( recvproptype, "RecvProp", strlen( "RecvProp" ) ) )
+ {
+ current = CC_ParseUntilEndOfLine( current );
+ continue;
+ }
+
+ if ( !strcmp( recvproptype, "RecvPropArray" ) )
+ {
+ current = CC_ParseToken( current );
+ if ( stricmp( com_token, "(" ) )
+ break;
+
+ current = CC_ParseToken( current );
+ if ( strnicmp( recvproptype, "RecvProp", strlen( "RecvProp" ) ) )
+ {
+ current = CC_ParseUntilEndOfLine( current );
+ continue;
+ }
+ }
+
+ current = CC_ParseToken( current );
+ if ( stricmp( com_token, "(" ) )
+ break;
+
+ // Read macro or fieldname
+ current = CC_ParseToken( current );
+
+ char varname[ 256 ];
+
+ if ( !strnicmp( com_token, "RECVINFO", strlen( "RECVINFO" ) ) )
+ {
+ current = CC_ParseToken( current );
+ if ( stricmp( com_token, "(" ) )
+ break;
+ current = CC_ParseToken( current );
+ }
+ else
+ {
+ current = CC_ParseUntilEndOfLine( current );
+ continue;
+ }
+
+ strcpy( varname, com_token );
+
+ current = CC_ParseUntilEndOfLine( current );
+
+ if ( cl )
+ {
+ // Look up the var
+ CClassVariable *classVar = cl->FindVar( varname, true );
+ if ( classVar )
+ {
+ classVar->m_bInRecvTable = true;
+ }
+ else
+ {
+ char cropped[ 256 ];
+ char root[ 256 ];
+ strcpy( cropped, varname );
+
+ while ( 1 )
+ {
+ // See if varname is an embedded var
+ char *spot = strstr( cropped, "." );
+ if ( spot )
+ {
+ strcpy( root, cropped );
+ root[ spot - cropped ] = 0;
+ strcpy( cropped, spot + 1 );
+
+ classVar = cl->FindVar( root, true );
+ }
+ else
+ {
+ classVar = cl->FindVar( cropped, true );
+ break;
+ }
+
+ if ( classVar )
+ break;
+ }
+
+ if ( !classVar )
+ {
+ vprint( 0, "class %s::%s missing, but referenced by RecvTable!!!\n", classname, varname );
+ }
+ else
+ {
+ classVar->m_bInRecvTable = true;
+ }
+ }
+ }
+ else
+ {
+ vprint( 0, "class %s::%s found in RecvTable, but no such class is known!!!\n", classname, varname );
+ }
+ }
+
+ return current;
+}
+
+char *CCodeProcessor::ParsePredictionTypeDescription( char *current )
+{
+ // Next token is open paren, then classname close paren, then {
+ char classname[ 256 ];
+ char variablename[ 256 ];
+
+ current = CC_ParseToken( current );
+ if (stricmp( com_token, "(" ) )
+ {
+ return current;
+ }
+
+ current = CC_ParseToken( current );
+ if ( strlen( com_token ) <= 0 )
+ return current;
+
+ strcpy( classname, com_token );
+ if ( classname[0]=='*' )
+ return current;
+
+ CClass *cl = FindClass( classname );
+ if ( cl )
+ {
+ cl->m_bHasPredictionData = true;
+ }
+
+ current = CC_ParseToken( current );
+ if (stricmp( com_token, ")" ) )
+ {
+ return current;
+ }
+
+ // It's macro-ized
+ strcpy( variablename, "m_PredDesc" );
+
+ com_ignoreinlinecomment = true;
+ bool insidecomment = false;
+
+ // Now parse typedescription line by line
+ while ( 1 )
+ {
+ current = CC_ParseToken( current );
+ if ( strlen( com_token ) <= 0 )
+ break;
+
+ // Go to next line
+ if ( !stricmp( com_token, "," ) )
+ continue;
+
+ // end
+ if ( !stricmp( com_token, "END_PREDICTION_DATA" ) )
+ break;
+
+ // skip #ifdef's inside of typedescs
+ if ( com_token[0]=='#' )
+ {
+ current = CC_ParseUntilEndOfLine( current );
+ continue;
+ }
+
+ if ( !stricmp( com_token, "/" ) )
+ {
+ current = CC_ParseToken( current );
+ if ( !stricmp( com_token, "/" ) )
+ {
+ current = CC_ParseToken( current );
+ if ( !strnicmp( com_token, "DEFINE_", 7 ) )
+ {
+ CC_UngetToken();
+ insidecomment = true;
+ }
+ else
+ {
+ current = CC_ParseUntilEndOfLine( current );
+ }
+ continue;
+ }
+ }
+
+ com_ignoreinlinecomment = false;
+
+ // Parse a typedescription line
+ char definetype[ 256 ];
+ strcpy( definetype, com_token );
+
+ current = CC_ParseToken( current );
+ if ( stricmp( com_token, "(" ) )
+ break;
+
+ char varname[ 256 ];
+ current = CC_ParseToken( current );
+
+ strcpy( varname, com_token );
+
+
+ char vartype[ 256 ];
+
+ vartype[0]=0;
+
+ if ( stricmp( definetype, "DEFINE_FUNCTION" ) )
+ {
+ // skip comma
+ current = CC_ParseToken( current );
+
+ current = CC_ParseToken( current );
+
+ strcpy( vartype, com_token );
+ }
+ else
+ {
+ strcpy( vartype, "funcptr" );
+ }
+
+ bool inrecvtable = false;
+ // Jump to end of definition
+ int nParenCount = 1;
+ do
+ {
+ current = CC_ParseToken( current );
+ if ( strlen( com_token ) <= 0 )
+ break;
+
+ if ( !stricmp( com_token, "(" ) )
+ {
+ ++nParenCount;
+ }
+ else if ( !stricmp( com_token, ")" ) )
+ {
+ if ( --nParenCount == 0 )
+ {
+ break;
+ }
+ }
+
+ if ( !stricmp( com_token, "FTYPEDESC_INSENDTABLE" ) )
+ {
+ inrecvtable = true;
+ }
+
+ } while ( 1 );
+
+ /*
+ vprint( 2, "%s%s::%s %s %s %s\n",
+ insidecomment ? "// " : "",
+ classname, variablename,
+ definetype, varname, vartype );
+ */
+
+ if ( cl )
+ {
+ if ( cl->FindPredTD( varname ) )
+ {
+ vprint( 0, "class %s::%s already has prediction typedescription entry for field %s\n", classname, variablename, varname );
+ }
+ else
+ {
+ cl->AddPredTD( varname, vartype, definetype, insidecomment, inrecvtable );
+ }
+ }
+ insidecomment = false;
+ com_ignoreinlinecomment = true;
+ }
+
+ com_ignoreinlinecomment = false;
+
+ return current;
+}
+
+void CCodeProcessor::AddHeader( int depth, const char *filename, const char *rootmodule )
+{
+// if ( depth < 1 )
+// return;
+ if ( depth != 1 )
+ return;
+
+ // Check header list
+ int idx = m_Headers.Find( filename );
+ if ( idx != m_Headers.InvalidIndex() )
+ {
+ vprint( 0, "%s included twice in module %s\n", filename, rootmodule );
+ return;
+ }
+
+ CODE_MODULE module;
+ module.skipped = false;
+
+ m_Headers.Insert( filename, module );
+}
+
+bool CCodeProcessor::CheckShouldSkip( bool forcequiet, int depth, char const *filename, int& numheaders, int& skippedfiles)
+{
+ int idx = m_Modules.Find( filename );
+ if ( idx == m_Modules.InvalidIndex() )
+ return false;
+
+ CODE_MODULE *module = &m_Modules[ idx ];
+
+ if ( forcequiet )
+ {
+ m_nHeadersProcessed++;
+ numheaders++;
+
+ if ( module->skipped )
+ {
+ skippedfiles++;
+ }
+ }
+
+ AddHeader( depth, filename, m_szCurrentCPP );
+ return true;
+}
+
+bool CCodeProcessor::LoadFile( char **buffer, char *filename, char const *module, bool forcequiet,
+ int depth, int& filelength, int& numheaders, int& skippedfiles,
+ char const *srcroot, char const *root, char const *baseroot )
+{
+ for ( int i = 0; i < m_IncludePath.Count(); ++i )
+ {
+ // Load the base module
+ sprintf( filename, "%s\\%s", m_IncludePath[i], module );
+ strlwr( filename );
+
+ if ( CheckShouldSkip( forcequiet, depth, filename, numheaders, skippedfiles ) )
+ {
+ return false;
+ }
+
+ *buffer = (char *)COM_LoadFile( filename, &filelength );
+ if ( *buffer )
+ return true;
+ }
+
+ return false;
+}
+
+static bool SkipFile( char const *module )
+{
+ if ( !stricmp( module, "predictable_entity.h" ) )
+ return true;
+ if ( !stricmp( module, "baseentity_shared.h" ) )
+ return true;
+ if ( !stricmp( module, "baseplayer_shared.h" ) )
+ return true;
+ if ( !stricmp( module, "tf_tacticalmap.cpp" ) )
+ return true;
+ if ( !stricmp( module, "techtree.cpp" ) )
+ return true;
+ if ( !stricmp( module, "techtree_parse.cpp" ) )
+ return true;
+
+ return false;
+}
+
+void CCodeProcessor::ProcessModule( bool forcequiet, int depth, int& maxdepth, int& numheaders, int& skippedfiles,
+ const char *srcroot, const char *baseroot, const char *root, const char *module )
+{
+ char filename[ 256 ];
+
+ if ( depth > maxdepth )
+ {
+ maxdepth = depth;
+ }
+ int filelength;
+ char *buffer = NULL;
+
+ // Always skip these particular modules/headers
+ if ( SkipFile( module ) )
+ {
+ CODE_MODULE module;
+ module.skipped = true;
+
+ m_Modules.Insert( filename, module );
+
+ skippedfiles++;
+ return;
+ }
+
+ if ( !LoadFile( &buffer, filename, module, forcequiet, depth, filelength, numheaders, skippedfiles,
+ srcroot, root, baseroot ) )
+ {
+ CODE_MODULE module;
+ module.skipped = true;
+ m_Modules.Insert( filename, module );
+ skippedfiles++;
+ return;
+ }
+
+ Assert( buffer );
+
+ m_nBytesProcessed += filelength;
+
+ CODE_MODULE m;
+ m.skipped = false;
+ m_Modules.Insert( filename, m );
+
+ if ( !forcequiet )
+ {
+ strcpy( m_szCurrentCPP, filename );
+ }
+
+ AddHeader( depth, filename, m_szCurrentCPP );
+
+ bool onclient = !strnicmp( m_szBaseEntityClass, "C_", 2 ) ? true : false;
+
+ // Parse tokens looking for #include directives or class starts
+ char *current = buffer;
+
+ current = CC_ParseToken( current );
+ while ( 1 )
+ {
+ // No more tokens
+ if ( !current )
+ break;
+
+ if ( !stricmp( com_token, "#include" ) )
+ {
+ current = CC_ParseToken( current );
+ if ( strlen( com_token ) > 0 &&
+ com_token[ 0 ] != '<' )
+ {
+ //vprint( "#include %s\n", com_token );
+ m_nHeadersProcessed++;
+ numheaders++;
+ ProcessModule( true, depth + 1, maxdepth, numheaders, skippedfiles, srcroot, baseroot, root, com_token );
+ }
+ }
+ else if ( !stricmp( com_token, "class" ) ||
+ !stricmp( com_token, "struct" ) )
+ {
+ current = CC_ParseToken( current );
+ if ( strlen( com_token ) > 0 )
+ {
+ //vprint( depth, "class %s\n", com_token );
+
+ CClass *cl = AddClass( com_token );
+
+ // Now see if there's a base class
+ current = CC_ParseToken( current );
+ if ( !stricmp( com_token, ":" ) )
+ {
+ // Parse out public and then classname an
+ current = CC_ParseToken( current );
+ if ( !stricmp( com_token, "public" ) )
+ {
+ current = CC_ParseToken( current );
+ if ( strlen( com_token ) > 0 )
+ {
+ cl->SetBaseClass( com_token );
+
+ do
+ {
+ current = CC_ParseToken( current );
+ } while ( strlen( com_token ) && stricmp( com_token, "{" ) );
+
+ if ( !stricmp( com_token, "{" ) )
+ {
+ current = cl->ParseClassDeclaration( current );
+ }
+ }
+ }
+ }
+ else if ( !stricmp( com_token, "{" ) )
+ {
+ current = cl->ParseClassDeclaration( current );
+ }
+ }
+ }
+ else if ( !strnicmp( com_token, "PREDICTABLE_CLASS", strlen( "PREDICTABLE_CLASS" ) ) )
+ {
+ char prefix[ 32 ];
+ prefix[ 0 ] = 0;
+ int type = 0;
+ int bases = 1;
+ int usebase = 0;
+
+ if ( !stricmp( com_token, "PREDICTABLE_CLASS_ALIASED" ) )
+ {
+ type = 2;
+ bases = 2;
+ if ( onclient )
+ {
+ strcpy( prefix, "C_" );
+ }
+ else
+ {
+ strcpy( prefix, "C" );
+ usebase = 1;
+ }
+ }
+ else if ( !stricmp( com_token, "PREDICTABLE_CLASS_SHARED" ) )
+ {
+ type = 1;
+ bases = 1;
+ }
+ else if ( !stricmp( com_token, "PREDICTABLE_CLASS" ) )
+ {
+ type = 0;
+ bases = 1;
+ if ( onclient )
+ {
+ strcpy( prefix, "C_" );
+ }
+ else
+ {
+ strcpy( prefix, "C" );
+ }
+ }
+ else if ( !stricmp( com_token, "PREDICTABLE_CLASS_ALIASED_PREFIXED" ) )
+ {
+ // Nothing
+ }
+ else
+ {
+ vprint( 0, "PREDICTABLE_CLASS of unknown type!!! %s\n", com_token );
+ }
+
+ // parse the (
+ current = CC_ParseToken( current );
+ if ( !strcmp( com_token, "(" ) )
+ {
+ // Now the classname
+ current = CC_ParseToken( current );
+ if ( strlen( com_token ) > 0 )
+ {
+ //vprint( depth, "class %s\n", com_token );
+
+ CClass *cl = AddClass( com_token );
+
+ // Now see if there's a base class
+ current = CC_ParseToken( current );
+ if ( !stricmp( com_token, "," ) )
+ {
+ // Parse out public and then classname an
+ current = CC_ParseToken( current );
+ if ( strlen( com_token ) > 0 )
+ {
+ char basename[ 256 ];
+ sprintf( basename, "%s%s", prefix, com_token );
+
+ bool valid = true;
+
+ if ( bases == 2 )
+ {
+ valid = false;
+
+ current = CC_ParseToken( current );
+ if ( !stricmp( com_token, "," ) )
+ {
+ current = CC_ParseToken( current );
+ if ( strlen( com_token ) > 0 )
+ {
+ valid = true;
+ if ( usebase == 1 )
+ {
+ sprintf( basename, "%s%s", prefix, com_token );
+ }
+ }
+ }
+ }
+
+ if ( valid )
+ {
+ cl->SetBaseClass( basename );
+ strcpy( cl->m_szTypedefBaseClass, basename );
+ }
+
+ do
+ {
+ current = CC_ParseToken( current );
+ } while ( strlen( com_token ) && stricmp( com_token, ")" ) );
+
+ if ( !stricmp( com_token, ")" ) )
+ {
+ current = cl->ParseClassDeclaration( current );
+ }
+ }
+ }
+ else if ( !stricmp( com_token, ")" ) )
+ {
+ current = cl->ParseClassDeclaration( current );
+ }
+ }
+ }
+ }
+ else if ( !strcmp( com_token, "TYPEDESCRIPTION" ) ||
+ !strcmp( com_token, "typedescription_t" ) )
+ {
+ current = ParseTypeDescription( current, false );
+ }
+ else if ( !strcmp( com_token, "BEGIN_DATADESC" ) ||
+ !strcmp( com_token, "BEGIN_DATADESC_NO_BASE" ) ||
+ !strcmp( com_token, "BEGIN_SIMPLE_DATADESC" ) ||
+ !strcmp( com_token, "BEGIN_BYTESWAP_DATADESC" ) )
+ {
+ current = ParseTypeDescription( current, true );
+ }
+ else if ( !strcmp( com_token, "BEGIN_PREDICTION_DATA" ) ||
+ !strcmp( com_token, "BEGIN_EMBEDDED_PREDDESC" ) )
+ {
+ current = ParsePredictionTypeDescription( current );
+ }
+ else if ( !strcmp( com_token, "BEGIN_RECV_TABLE" ) ||
+ !strcmp( com_token, "BEGIN_RECV_TABLE_NOBASE" ) ||
+ !strcmp( com_token, "IMPLEMENT_CLIENTCLASS_DT" ) ||
+ !strcmp( com_token, "IMPLEMENT_CLIENTCLASS_DT_NOBASE" ) )
+ {
+ current = ParseReceiveTable( current );
+ }
+ else if ( !strcmp( com_token, "IMPLEMENT_PREDICTABLE_NODATA" ) )
+ {
+ current = CC_ParseToken( current );
+ if ( !strcmp( com_token, "(" ) )
+ {
+ current = CC_ParseToken( current );
+
+ CClass *cl = FindClass( com_token );
+ if ( cl )
+ {
+ if ( cl->m_bHasPredictionData )
+ {
+ if ( !forcequiet )
+ {
+ vprint( 0, "Class %s declared predictable and implemented with IMPLEMENT_PREDICTABLE_NODATA in typedescription\n",
+ cl->m_szName );
+ }
+
+ cl->m_bHasPredictionData = false;
+ }
+ }
+
+ current = CC_ParseToken( current );
+ }
+ }
+
+ current = CC_ParseToken( current );
+ }
+
+ COM_FreeFile( (unsigned char *)buffer );
+
+ if ( !forcequiet && !GetQuiet() )
+ {
+ vprint( 0, " %s: headers (%i game / %i total)", (char *)&filename[ m_nOffset ], numheaders - skippedfiles, numheaders );
+ if ( maxdepth > 1 )
+ {
+ vprint( 0, ", depth %i", maxdepth );
+ }
+ vprint( 0, "\n" );
+ }
+
+ m_nLinesOfCode += linesprocessed;
+ linesprocessed = 0;
+}
+
+void CCodeProcessor::ProcessModules( const char *srcroot, const char *root, const char *rootmodule )
+{
+ m_nFilesProcessed++;
+
+ // Reset header list per module
+ m_Headers.RemoveAll();
+
+ int numheaders = 0;
+ int maxdepth = 0;
+ int skippedfiles = 0;
+ ProcessModule( false, 0, maxdepth, numheaders, skippedfiles, srcroot, root, root, rootmodule );
+}
+
+void ReportMissingTypes();
+
+void CCodeProcessor::PrintResults( const char *baseentityclass )
+{
+ vprint( 0, "\nChecking for errors and totaling...\n\n" );
+
+ ResolveBaseClasses( baseentityclass );
+ PrintClassList();
+ PrintMissingTDFields();
+ ReportMissingTypes();
+ ReportHungarianNotationErrors();
+
+ vprint( 0, "%i total classes parsed from %i files ( %i headers parsed )\n",
+ m_nClassesParsed,
+ 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 ) );
+ }
+
+ Clear();
+}
+
+CCodeProcessor::CCodeProcessor( void )
+{
+ m_pClassList = NULL;
+
+ m_Modules.RemoveAll();
+
+ m_bQuiet = false;
+ m_bPrintHierarchy = false;
+ m_bPrintMembers = true;
+ m_bPrintTypedescriptionErrors = true;
+ m_bPrintPredictionDescErrors = true;
+ m_bCreateMissingTDs = false;
+ m_bLogToFile = false;
+ m_bCheckHungarian = false;
+
+ m_nFilesProcessed = 0;
+ m_nHeadersProcessed = 0;
+ m_nClassesParsed = 0;
+ m_nOffset = 0;
+ m_nBytesProcessed = 0;
+ m_nLinesOfCode = 0;
+ m_flStart = 0.0;
+ m_flEnd = 0.0;
+
+ m_szCurrentCPP[ 0 ] = 0;
+ m_szBaseEntityClass[ 0 ] = 0;
+}
+
+CCodeProcessor::~CCodeProcessor( void )
+{
+}
+
+void CCodeProcessor::ConstructModuleList_R( int level, const char *baseentityclass,
+ const char *gamespecific, const char *root, const char *srcroot )
+{
+ 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 && !strstr( wfd.cFileName, gamespecific ) )
+ continue;
+
+ // Recurse down directory
+ sprintf( filename, "%s\\%s", root, wfd.cFileName );
+ ConstructModuleList_R( level+1, baseentityclass, gamespecific, filename, srcroot );
+ }
+ else
+ {
+ if ( strstr( wfd.cFileName, ".cpp" ) )
+ {
+ ProcessModules( srcroot, root, wfd.cFileName );
+ }
+ }
+ } while ( FindNextFile( ff, &wfd ) );
+}
+
+void CCodeProcessor::CleanupIncludePath()
+{
+ for ( int i = m_IncludePath.Count(); --i >= 0; )
+ {
+ delete [] m_IncludePath[i];
+ }
+ m_IncludePath.RemoveAll();
+}
+
+void CCodeProcessor::AddIncludePath( const char *pPath )
+{
+ int i = m_IncludePath.AddToTail();
+ int nLen = strlen(pPath) + 1;
+ m_IncludePath[i] = new char[nLen];
+ memcpy( m_IncludePath[i], pPath, nLen );
+}
+
+void CCodeProcessor::SetupIncludePath( const char *sourcetreebase, const char *subdir, const char *gamespecific )
+{
+ CleanupIncludePath();
+
+ char path[MAX_PATH];
+ sprintf( path, "%s\\%s", sourcetreebase, subdir );
+ strlwr( path );
+ AddIncludePath( path );
+
+ char modsubdir[128];
+ if ( !stricmp(subdir, "dlls") )
+ {
+ sprintf(modsubdir,"%s\\%s_dll", subdir, gamespecific );
+ }
+ else if ( !stricmp(subdir, "cl_dll") )
+ {
+ sprintf(modsubdir,"%s\\%s_hud", subdir, gamespecific );
+ }
+ else
+ {
+ sprintf(modsubdir,"%s\\%s", subdir, gamespecific );
+ }
+
+ sprintf( path, "%s\\%s", sourcetreebase, modsubdir );
+ strlwr( path );
+ AddIncludePath( path );
+
+ // Game shared
+ sprintf( path, "%s\\game_shared", sourcetreebase );
+ strlwr( path );
+ AddIncludePath( path );
+
+ sprintf( path, "%s\\game_shared\\%s", sourcetreebase, gamespecific );
+ strlwr( path );
+ AddIncludePath( path );
+
+ sprintf( path, "%s\\public", sourcetreebase );
+ strlwr( path );
+ AddIncludePath( path );
+}
+
+
+void CCodeProcessor::Process( const char *baseentityclass, const char *gamespecific, const char *sourcetreebase, const char *subdir )
+{
+ SetupIncludePath( sourcetreebase, subdir, gamespecific );
+
+ strcpy( m_szBaseEntityClass, baseentityclass );
+
+ m_nBytesProcessed = 0;
+ m_nFilesProcessed = 0;
+ m_nHeadersProcessed = 0;
+ m_nClassesParsed = 0;
+ m_nLinesOfCode = 0;
+
+ linesprocessed = 0;
+
+ m_Modules.RemoveAll();
+ m_Headers.RemoveAll();
+
+ m_flStart = UTIL_FloatTime();
+
+ char rootdirectory[ 256 ];
+ sprintf( rootdirectory, "%s\\%s", sourcetreebase, subdir );
+
+ vprint( 0, "--- Processing %s\n\n", rootdirectory );
+
+ m_nOffset = strlen( rootdirectory ) + 1;
+
+ ConstructModuleList_R( 0, baseentityclass, gamespecific, rootdirectory, sourcetreebase );
+
+ sprintf( rootdirectory, "%s\\%s", sourcetreebase, "game_shared" );
+
+ vprint( 0, "--- Processing %s\n\n", rootdirectory );
+
+ m_nOffset = strlen( rootdirectory ) + 1;
+
+ ConstructModuleList_R( 0, baseentityclass, gamespecific, rootdirectory, sourcetreebase );
+
+ m_flEnd = UTIL_FloatTime();
+
+ PrintResults( baseentityclass );
+}
+
+void CCodeProcessor::Process( const char *baseentityclass, const char *gamespecific,
+ const char *sourcetreebase, const char *subdir, const char *pFileName )
+{
+ SetupIncludePath( sourcetreebase, subdir, gamespecific );
+
+ strcpy( m_szBaseEntityClass, baseentityclass );
+
+ m_nBytesProcessed = 0;
+ m_nFilesProcessed = 0;
+ m_nHeadersProcessed = 0;
+ m_nClassesParsed = 0;
+ m_nLinesOfCode = 0;
+
+ linesprocessed = 0;
+
+ m_Modules.RemoveAll();
+ m_Headers.RemoveAll();
+
+ m_flStart = UTIL_FloatTime();
+
+ char rootdirectory[ 256 ];
+ sprintf( rootdirectory, "%s\\%s", sourcetreebase, subdir );
+
+ vprint( 0, "--- Processing %s\n\n", rootdirectory );
+
+ m_nOffset = strlen( rootdirectory ) + 1;
+
+ ProcessModules( sourcetreebase, rootdirectory, pFileName );
+
+ m_flEnd = UTIL_FloatTime();
+
+ PrintResults( baseentityclass );
+}
+
+void CCodeProcessor::SetQuiet( bool quiet )
+{
+ m_bQuiet = quiet;
+}
+
+bool CCodeProcessor::GetQuiet( void ) const
+{
+ return m_bQuiet;
+}
+
+void CCodeProcessor::SetPrintHierarchy( bool print )
+{
+ m_bPrintHierarchy = print;
+}
+
+bool CCodeProcessor::GetPrintHierarchy( void ) const
+{
+ return m_bPrintHierarchy;
+}
+
+void CCodeProcessor::SetPrintMembers( bool print )
+{
+ m_bPrintMembers = print;
+}
+
+bool CCodeProcessor::GetPrintMembers( void ) const
+{
+ return m_bPrintMembers;
+}
+
+void CCodeProcessor::SetPrintTDs( bool print )
+{
+ m_bPrintTypedescriptionErrors = print;
+}
+
+bool CCodeProcessor::GetPrintTDs( void ) const
+{
+ return m_bPrintTypedescriptionErrors;
+}
+
+void CCodeProcessor::SetLogFile( bool log )
+{
+ m_bLogToFile = log;
+}
+
+bool CCodeProcessor::GetLogFile( void ) const
+{
+ return m_bLogToFile;
+}
+
+void CCodeProcessor::SetPrintPredTDs( bool print )
+{
+ m_bPrintPredictionDescErrors = print;
+}
+
+bool CCodeProcessor::GetPrintPredTDs( void ) const
+{
+ return m_bPrintPredictionDescErrors;
+}
+
+void CCodeProcessor::SetPrintCreateMissingTDs( bool print )
+{
+ m_bCreateMissingTDs = print;
+}
+
+bool CCodeProcessor::GetPrintCreateMissingTDs( void ) const
+{
+ return m_bCreateMissingTDs;
+}
+
+void CCodeProcessor::SetPrintCreateMissingPredTDs( bool print )
+{
+ m_bCreateMissingPredTDs = print;
+}
+
+bool CCodeProcessor::GetPrintCreateMissingPredTDs( void ) const
+{
+ return m_bCreateMissingPredTDs;
+}
+
+void CCodeProcessor::SetCheckHungarian( bool check )
+{
+ m_bCheckHungarian = check;
+}
+
+bool CCodeProcessor::GetCheckHungarian() const
+{
+ return m_bCheckHungarian;
+}
+
+static CCodeProcessor g_Processor;
+ICodeProcessor *processor = ( ICodeProcessor * )&g_Processor; \ No newline at end of file