Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

216 lines
5.3 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "stdafx.h"
  8. #include <stdio.h>
  9. #include <windows.h>
  10. #include "classcheck_util.h"
  11. #include "icodeprocessor.h"
  12. #include "tier1/strtools.h"
  13. #include "tier0/dbg.h"
  14. SpewRetval_t SpewFunc( SpewType_t type, char const *pMsg )
  15. {
  16. printf( "%s", pMsg );
  17. OutputDebugString( pMsg );
  18. if ( type == SPEW_ERROR )
  19. {
  20. printf( "\n" );
  21. OutputDebugString( "\n" );
  22. }
  23. return SPEW_CONTINUE;
  24. }
  25. //-----------------------------------------------------------------------------
  26. // Purpose:
  27. //-----------------------------------------------------------------------------
  28. void printusage( void )
  29. {
  30. vprint( 0, "usage: classcheck -q -h -m -t <root source directory> <game: hl2 | tf2>\n\
  31. \t-q = quiet\n\
  32. \t-h = print class hierarchy\n\
  33. \t-m = don't print member functions/variables of class\n\
  34. \t-t = don't print type description errors\n\
  35. \t-p = don't print prediction description errors\n\
  36. \t-c = create missing save descriptions\n\
  37. \t-x = create missing prediction descriptions\n\
  38. \t-i = specify specific input file to parse\n\
  39. \t-b = similar to -i, allows specifying files outside client\\server directories\n\
  40. \t-j = check for Crazy Jay Stelly's mismatched Hungarian notation errors\n\
  41. \t-l = log to file log.txt\n" );
  42. // Exit app
  43. exit( 1 );
  44. }
  45. //-----------------------------------------------------------------------------
  46. // Purpose:
  47. // Input : *sourcetreebase -
  48. // *subdir -
  49. // *baseentityclass -
  50. //-----------------------------------------------------------------------------
  51. void ProcessDirectory( const char *game, const char *sourcetreebase, const char *subdir, const char *baseentityclass )
  52. {
  53. char rootdirectory[ 256 ];
  54. sprintf( rootdirectory, "%s\\%s", sourcetreebase, subdir );
  55. // check for existence
  56. if ( COM_DirectoryExists( rootdirectory ) )
  57. {
  58. processor->Process( baseentityclass, game, sourcetreebase, subdir );
  59. }
  60. else
  61. {
  62. vprint( 0, "Couldn't find directory %s, check path %s\n", rootdirectory, sourcetreebase );
  63. }
  64. }
  65. //-----------------------------------------------------------------------------
  66. // Purpose:
  67. // Input : *sourcetreebase -
  68. // *subdir -
  69. // *baseentityclass -
  70. //-----------------------------------------------------------------------------
  71. void ProcessFile( const char *game, const char *sourcetreebase, const char *subdir, const char *baseentityclass, const char *pFileName )
  72. {
  73. char rootdirectory[ 256 ];
  74. sprintf( rootdirectory, "%s\\%s", sourcetreebase, subdir );
  75. // check for existence
  76. if ( COM_DirectoryExists( rootdirectory ) )
  77. {
  78. processor->Process( baseentityclass, game, sourcetreebase, subdir, pFileName );
  79. }
  80. else
  81. {
  82. vprint( 0, "Couldn't find directory %s, check path %s\n", rootdirectory, sourcetreebase );
  83. }
  84. }
  85. //-----------------------------------------------------------------------------
  86. // Purpose:
  87. //-----------------------------------------------------------------------------
  88. void CheckLogFile( void )
  89. {
  90. if ( processor->GetLogFile() )
  91. {
  92. _unlink( "log.txt" );
  93. vprint( 0, " Outputting to log.txt\n" );
  94. }
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Purpose:
  98. // Input : argc -
  99. // argv[] -
  100. // Output : int
  101. //-----------------------------------------------------------------------------
  102. int main( int argc, char* argv[] )
  103. {
  104. SpewOutputFunc( SpewFunc );
  105. vprint( 0, "Valve Software - classcheck.exe (%s)\n", __DATE__ );
  106. vprint( 0, "--- Game Code Static Analysis ---\n" );
  107. char *pSpecificFile = NULL;
  108. bool bOutsideGamedir = false;
  109. int i = 1;
  110. for ( i ; i<argc ; i++)
  111. {
  112. if ( argv[ i ][ 0 ] == '-' )
  113. {
  114. switch( argv[ i ][ 1 ] )
  115. {
  116. case 'q':
  117. processor->SetQuiet( true );
  118. break;
  119. case 'h':
  120. processor->SetPrintHierarchy( true );
  121. break;
  122. case 'm':
  123. processor->SetPrintMembers( false );
  124. break;
  125. case 't':
  126. processor->SetPrintTDs( false );
  127. break;
  128. case 'p':
  129. processor->SetPrintPredTDs( false );
  130. break;
  131. case 'c':
  132. processor->SetPrintCreateMissingTDs( true );
  133. break;
  134. case 'x':
  135. processor->SetPrintCreateMissingPredTDs( true );
  136. break;
  137. case 'i':
  138. if (i < argc-1)
  139. {
  140. pSpecificFile = argv[i+1];
  141. ++i;
  142. }
  143. break;
  144. case 'b':
  145. if (i < argc-1)
  146. {
  147. pSpecificFile = argv[i+1];
  148. bOutsideGamedir = true;
  149. ++i;
  150. }
  151. break;
  152. case 'l':
  153. processor->SetLogFile( true );
  154. break;
  155. case 'j':
  156. processor->SetCheckHungarian( true );
  157. break;
  158. default:
  159. printusage();
  160. break;
  161. }
  162. }
  163. }
  164. if ( argc < 3 || ( i != argc ) )
  165. {
  166. printusage();
  167. }
  168. CheckLogFile();
  169. vprint( 0, " Looking for obvious screwups and boneheaded mistakes...\n" );
  170. char sourcetreebase[ 256 ];
  171. strcpy( sourcetreebase, argv[i-2] );
  172. Q_StripTrailingSlash( sourcetreebase );
  173. if ( !pSpecificFile )
  174. {
  175. ProcessDirectory( argv[ i-1 ], sourcetreebase, "server", "CBaseEntity" );
  176. ProcessDirectory( argv[ i-1 ], sourcetreebase, "client", "C_BaseEntity" );
  177. }
  178. else
  179. {
  180. if ( bOutsideGamedir )
  181. {
  182. ProcessFile( argv[ i-1 ], sourcetreebase, "", "", pSpecificFile );
  183. }
  184. else
  185. {
  186. ProcessFile( argv[ i-1 ], sourcetreebase, "server", "CBaseEntity", pSpecificFile );
  187. ProcessFile( argv[ i-1 ], sourcetreebase, "client", "C_BaseEntity", pSpecificFile );
  188. }
  189. }
  190. return 0;
  191. }