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.

820 lines
30 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #ifndef DBG_H
  9. #define DBG_H
  10. #ifdef _WIN32
  11. #pragma once
  12. #endif
  13. #include "basetypes.h"
  14. #include "dbgflag.h"
  15. #include "platform.h"
  16. #include <math.h>
  17. #include <stdio.h>
  18. #include <stdarg.h>
  19. #ifdef POSIX
  20. #define __cdecl
  21. #endif
  22. //-----------------------------------------------------------------------------
  23. // dll export stuff
  24. //-----------------------------------------------------------------------------
  25. #ifndef STATIC_TIER0
  26. #ifdef TIER0_DLL_EXPORT
  27. #define DBG_INTERFACE DLL_EXPORT
  28. #define DBG_OVERLOAD DLL_GLOBAL_EXPORT
  29. #define DBG_CLASS DLL_CLASS_EXPORT
  30. #else
  31. #define DBG_INTERFACE DLL_IMPORT
  32. #define DBG_OVERLOAD DLL_GLOBAL_IMPORT
  33. #define DBG_CLASS DLL_CLASS_IMPORT
  34. #endif
  35. #else // BUILD_AS_DLL
  36. #define DBG_INTERFACE extern
  37. #define DBG_OVERLOAD
  38. #define DBG_CLASS
  39. #endif // BUILD_AS_DLL
  40. class Color;
  41. //-----------------------------------------------------------------------------
  42. // Usage model for the Dbg library
  43. //
  44. // 1. Spew.
  45. //
  46. // Spew can be used in a static and a dynamic mode. The static
  47. // mode allows us to display assertions and other messages either only
  48. // in debug builds, or in non-release builds. The dynamic mode allows us to
  49. // turn on and off certain spew messages while the application is running.
  50. //
  51. // Static Spew messages:
  52. //
  53. // Assertions are used to detect and warn about invalid states
  54. // Spews are used to display a particular status/warning message.
  55. //
  56. // To use an assertion, use
  57. //
  58. // Assert( (f == 5) );
  59. // AssertMsg( (f == 5), ("F needs to be %d here!\n", 5) );
  60. // AssertFunc( (f == 5), BadFunc() );
  61. // AssertEquals( f, 5 );
  62. // AssertFloatEquals( f, 5.0f, 1e-3 );
  63. //
  64. // The first will simply report that an assertion failed on a particular
  65. // code file and line. The second version will display a print-f formatted message
  66. // along with the file and line, the third will display a generic message and
  67. // will also cause the function BadFunc to be executed, and the last two
  68. // will report an error if f is not equal to 5 (the last one asserts within
  69. // a particular tolerance).
  70. //
  71. // To use a warning, use
  72. //
  73. // Warning("Oh I feel so %s all over\n", "yummy");
  74. //
  75. // Warning will do its magic in only Debug builds. To perform spew in *all*
  76. // builds, use RelWarning.
  77. //
  78. // Three other spew types, Msg, Log, and Error, are compiled into all builds.
  79. // These error types do *not* need two sets of parenthesis.
  80. //
  81. // Msg( "Isn't this exciting %d?", 5 );
  82. // Error( "I'm just thrilled" );
  83. //
  84. // Dynamic Spew messages
  85. //
  86. // It is possible to dynamically turn spew on and off. Dynamic spew is
  87. // identified by a spew group and priority level. To turn spew on for a
  88. // particular spew group, use SpewActivate( "group", level ). This will
  89. // cause all spew in that particular group with priority levels <= the
  90. // level specified in the SpewActivate function to be printed. Use DSpew
  91. // to perform the spew:
  92. //
  93. // DWarning( "group", level, "Oh I feel even yummier!\n" );
  94. //
  95. // Priority level 0 means that the spew will *always* be printed, and group
  96. // '*' is the default spew group. If a DWarning is encountered using a group
  97. // whose priority has not been set, it will use the priority of the default
  98. // group. The priority of the default group is initially set to 0.
  99. //
  100. // Spew output
  101. //
  102. // The output of the spew system can be redirected to an externally-supplied
  103. // function which is responsible for outputting the spew. By default, the
  104. // spew is simply printed using printf.
  105. //
  106. // To redirect spew output, call SpewOutput.
  107. //
  108. // SpewOutputFunc( OutputFunc );
  109. //
  110. // This will cause OutputFunc to be called every time a spew message is
  111. // generated. OutputFunc will be passed a spew type and a message to print.
  112. // It must return a value indicating whether the debugger should be invoked,
  113. // whether the program should continue running, or whether the program
  114. // should abort.
  115. //
  116. // 2. Code activation
  117. //
  118. // To cause code to be run only in debug builds, use DBG_CODE:
  119. // An example is below.
  120. //
  121. // DBG_CODE(
  122. // {
  123. // int x = 5;
  124. // ++x;
  125. // }
  126. // );
  127. //
  128. // Code can be activated based on the dynamic spew groups also. Use
  129. //
  130. // DBG_DCODE( "group", level,
  131. // { int x = 5; ++x; }
  132. // );
  133. //
  134. // 3. Breaking into the debugger.
  135. //
  136. // To cause an unconditional break into the debugger in debug builds only, use DBG_BREAK
  137. //
  138. // DBG_BREAK();
  139. //
  140. // You can force a break in any build (release or debug) using
  141. //
  142. // DebuggerBreak();
  143. //-----------------------------------------------------------------------------
  144. /* Various types of spew messages */
  145. // I'm sure you're asking yourself why SPEW_ instead of DBG_ ?
  146. // It's because DBG_ is used all over the place in windows.h
  147. // For example, DBG_CONTINUE is defined. Feh.
  148. enum SpewType_t
  149. {
  150. SPEW_MESSAGE = 0,
  151. SPEW_WARNING,
  152. SPEW_ASSERT,
  153. SPEW_ERROR,
  154. SPEW_LOG,
  155. SPEW_TYPE_COUNT
  156. };
  157. enum SpewRetval_t
  158. {
  159. SPEW_DEBUGGER = 0,
  160. SPEW_CONTINUE,
  161. SPEW_ABORT
  162. };
  163. /* type of externally defined function used to display debug spew */
  164. typedef SpewRetval_t (*SpewOutputFunc_t)( SpewType_t spewType, const tchar *pMsg );
  165. /* Used to redirect spew output */
  166. DBG_INTERFACE void SpewOutputFunc( SpewOutputFunc_t func );
  167. /* Used to get the current spew output function */
  168. DBG_INTERFACE SpewOutputFunc_t GetSpewOutputFunc( void );
  169. /* This is the default spew fun, which is used if you don't specify one */
  170. DBG_INTERFACE SpewRetval_t DefaultSpewFunc( SpewType_t type, const tchar *pMsg );
  171. /* Same as the default spew func, but returns SPEW_ABORT for asserts */
  172. DBG_INTERFACE SpewRetval_t DefaultSpewFuncAbortOnAsserts( SpewType_t type, const tchar *pMsg );
  173. /* Should be called only inside a SpewOutputFunc_t, returns groupname, level, color */
  174. DBG_INTERFACE const tchar* GetSpewOutputGroup( void );
  175. DBG_INTERFACE int GetSpewOutputLevel( void );
  176. DBG_INTERFACE const Color* GetSpewOutputColor( void );
  177. /* Used to manage spew groups and subgroups */
  178. DBG_INTERFACE void SpewActivate( const tchar* pGroupName, int level );
  179. DBG_INTERFACE bool IsSpewActive( const tchar* pGroupName, int level );
  180. /* Used to display messages, should never be called directly. */
  181. DBG_INTERFACE void _SpewInfo( SpewType_t type, const tchar* pFile, int line );
  182. DBG_INTERFACE SpewRetval_t _SpewMessage( PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
  183. DBG_INTERFACE SpewRetval_t _DSpewMessage( const tchar *pGroupName, int level, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 3, 4 );
  184. DBG_INTERFACE SpewRetval_t ColorSpewMessage( SpewType_t type, const Color *pColor, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 3, 4 );
  185. DBG_INTERFACE void _ExitOnFatalAssert( const tchar* pFile, int line );
  186. DBG_INTERFACE bool ShouldUseNewAssertDialog();
  187. DBG_INTERFACE bool SetupWin32ConsoleIO();
  188. // Returns true if they want to break in the debugger.
  189. DBG_INTERFACE bool DoNewAssertDialog( const tchar *pFile, int line, const tchar *pExpression );
  190. // Allows the assert dialogs to be turned off from code
  191. DBG_INTERFACE bool AreAllAssertsDisabled();
  192. DBG_INTERFACE void SetAllAssertsDisabled( bool bAssertsEnabled );
  193. // Provides a callback that is called on asserts regardless of spew levels
  194. typedef void (*AssertFailedNotifyFunc_t)( const char *pchFile, int nLine, const char *pchMessage );
  195. DBG_INTERFACE void SetAssertFailedNotifyFunc( AssertFailedNotifyFunc_t func );
  196. DBG_INTERFACE void CallAssertFailedNotifyFunc( const char *pchFile, int nLine, const char *pchMessage );
  197. /* True if -hushasserts was passed on command line. */
  198. DBG_INTERFACE bool HushAsserts();
  199. #if defined( USE_SDL )
  200. DBG_INTERFACE void SetAssertDialogParent( struct SDL_Window *window );
  201. DBG_INTERFACE struct SDL_Window * GetAssertDialogParent();
  202. #endif
  203. /* Used to define macros, never use these directly. */
  204. #ifdef _PREFAST_
  205. // When doing /analyze builds define _AssertMsg to be __analysis_assume. This tells
  206. // the compiler to assume that the condition is true, which helps to suppress many
  207. // warnings. This define is done in debug and release builds.
  208. // The unfortunate !! is necessary because otherwise /analyze is incapable of evaluating
  209. // all of the logical expressions that the regular compiler can handle.
  210. // Include _msg in the macro so that format errors in it are detected.
  211. #define _AssertMsg( _exp, _msg, _executeExp, _bFatal ) do { __analysis_assume( !!(_exp) ); _msg; } while (0)
  212. #define _AssertMsgOnce( _exp, _msg, _bFatal ) do { __analysis_assume( !!(_exp) ); _msg; } while (0)
  213. // Force asserts on for /analyze so that we get a __analysis_assume of all of the constraints.
  214. #define DBGFLAG_ASSERT
  215. #define DBGFLAG_ASSERTFATAL
  216. #define DBGFLAG_ASSERTDEBUG
  217. #else
  218. #define _AssertMsg( _exp, _msg, _executeExp, _bFatal ) \
  219. do { \
  220. if (!(_exp)) \
  221. { \
  222. _SpewInfo( SPEW_ASSERT, __TFILE__, __LINE__ ); \
  223. SpewRetval_t retAssert = _SpewMessage("%s", static_cast<const char*>( _msg )); \
  224. CallAssertFailedNotifyFunc( __TFILE__, __LINE__, _msg ); \
  225. _executeExp; \
  226. if ( retAssert == SPEW_DEBUGGER) \
  227. { \
  228. if ( !ShouldUseNewAssertDialog() || DoNewAssertDialog( __TFILE__, __LINE__, _msg ) ) \
  229. { \
  230. DebuggerBreak(); \
  231. } \
  232. if ( _bFatal ) \
  233. { \
  234. _ExitOnFatalAssert( __TFILE__, __LINE__ ); \
  235. } \
  236. } \
  237. } \
  238. } while (0)
  239. #define _AssertMsgOnce( _exp, _msg, _bFatal ) \
  240. do { \
  241. static bool fAsserted; \
  242. if (!fAsserted ) \
  243. { \
  244. _AssertMsg( _exp, _msg, (fAsserted = true), _bFatal ); \
  245. } \
  246. } while (0)
  247. #endif
  248. /* Spew macros... */
  249. // AssertFatal macros
  250. // AssertFatal is used to detect an unrecoverable error condition.
  251. // If enabled, it may display an assert dialog (if DBGFLAG_ASSERTDLG is turned on or running under the debugger),
  252. // and always terminates the application
  253. #ifdef DBGFLAG_ASSERTFATAL
  254. #define AssertFatal( _exp ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), ((void)0), true )
  255. #define AssertFatalOnce( _exp ) _AssertMsgOnce( _exp, _T("Assertion Failed: ") _T(#_exp), true )
  256. #define AssertFatalMsg( _exp, _msg, ... ) _AssertMsg( _exp, (const tchar *)CDbgFmtMsg( _msg, ##__VA_ARGS__ ), ((void)0), true )
  257. #define AssertFatalMsgOnce( _exp, _msg ) _AssertMsgOnce( _exp, _msg, true )
  258. #define AssertFatalFunc( _exp, _f ) _AssertMsg( _exp, _T("Assertion Failed: " _T(#_exp), _f, true )
  259. #define AssertFatalEquals( _exp, _expectedValue ) AssertFatalMsg2( (_exp) == (_expectedValue), _T("Expected %d but got %d!"), (_expectedValue), (_exp) )
  260. #define AssertFatalFloatEquals( _exp, _expectedValue, _tol ) AssertFatalMsg2( fabs((_exp) - (_expectedValue)) <= (_tol), _T("Expected %f but got %f!"), (_expectedValue), (_exp) )
  261. #define VerifyFatal( _exp ) AssertFatal( _exp )
  262. #define VerifyEqualsFatal( _exp, _expectedValue ) AssertFatalEquals( _exp, _expectedValue )
  263. #define AssertFatalMsg1( _exp, _msg, a1 ) AssertFatalMsg( _exp, _msg, a1 )
  264. #define AssertFatalMsg2( _exp, _msg, a1, a2 ) AssertFatalMsg( _exp, _msg, a1, a2 )
  265. #define AssertFatalMsg3( _exp, _msg, a1, a2, a3 ) AssertFatalMsg( _exp, _msg, a1, a2, a3 )
  266. #define AssertFatalMsg4( _exp, _msg, a1, a2, a3, a4 ) AssertFatalMsg( _exp, _msg, a1, a2, a3, a4 )
  267. #define AssertFatalMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) AssertFatalMsg( _exp, _msg, a1, a2, a3, a4, a5 )
  268. #define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) AssertFatalMsg( _exp, _msg, a1, a2, a3, a4, a5, a6 )
  269. #define AssertFatalMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) AssertFatalMsg( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 )
  270. #define AssertFatalMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) AssertFatalMsg( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 )
  271. #define AssertFatalMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) AssertFatalMsg( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 )
  272. #else // DBGFLAG_ASSERTFATAL
  273. #define AssertFatal( _exp ) ((void)0)
  274. #define AssertFatalOnce( _exp ) ((void)0)
  275. #define AssertFatalMsg( _exp, _msg ) ((void)0)
  276. #define AssertFatalMsgOnce( _exp, _msg ) ((void)0)
  277. #define AssertFatalFunc( _exp, _f ) ((void)0)
  278. #define AssertFatalEquals( _exp, _expectedValue ) ((void)0)
  279. #define AssertFatalFloatEquals( _exp, _expectedValue, _tol ) ((void)0)
  280. #define VerifyFatal( _exp ) (_exp)
  281. #define VerifyEqualsFatal( _exp, _expectedValue ) (_exp)
  282. #define AssertFatalMsg1( _exp, _msg, a1 ) ((void)0)
  283. #define AssertFatalMsg2( _exp, _msg, a1, a2 ) ((void)0)
  284. #define AssertFatalMsg3( _exp, _msg, a1, a2, a3 ) ((void)0)
  285. #define AssertFatalMsg4( _exp, _msg, a1, a2, a3, a4 ) ((void)0)
  286. #define AssertFatalMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) ((void)0)
  287. #define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0)
  288. #define AssertFatalMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) ((void)0)
  289. #define AssertFatalMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) ((void)0)
  290. #define AssertFatalMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) ((void)0)
  291. #endif // DBGFLAG_ASSERTFATAL
  292. // Assert macros
  293. // Assert is used to detect an important but survivable error.
  294. // It's only turned on when DBGFLAG_ASSERT is true.
  295. #ifdef DBGFLAG_ASSERT
  296. #define Assert( _exp ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), ((void)0), false )
  297. #define AssertMsg( _exp, _msg, ... ) _AssertMsg( _exp, (const tchar *)CDbgFmtMsg( _msg, ##__VA_ARGS__ ), ((void)0), false )
  298. #define AssertOnce( _exp ) _AssertMsgOnce( _exp, _T("Assertion Failed: ") _T(#_exp), false )
  299. #define AssertMsgOnce( _exp, _msg ) _AssertMsgOnce( _exp, _msg, false )
  300. #define AssertFunc( _exp, _f ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), _f, false )
  301. #define AssertEquals( _exp, _expectedValue ) AssertMsg2( (_exp) == (_expectedValue), _T("Expected %d but got %d!"), (_expectedValue), (_exp) )
  302. #define AssertFloatEquals( _exp, _expectedValue, _tol ) AssertMsg2( fabs((_exp) - (_expectedValue)) <= (_tol), _T("Expected %f but got %f!"), (_expectedValue), (_exp) )
  303. #define Verify( _exp ) Assert( _exp )
  304. #define VerifyMsg1( _exp, _msg, a1 ) AssertMsg1( _exp, _msg, a1 )
  305. #define VerifyMsg2( _exp, _msg, a1, a2 ) AssertMsg2( _exp, _msg, a1, a2 )
  306. #define VerifyMsg3( _exp, _msg, a1, a2, a3 ) AssertMsg3( _exp, _msg, a1, a2, a3 )
  307. #define VerifyEquals( _exp, _expectedValue ) AssertEquals( _exp, _expectedValue )
  308. #define DbgVerify( _exp ) Assert( _exp )
  309. #define AssertMsg1( _exp, _msg, a1 ) AssertMsg( _exp, _msg, a1 )
  310. #define AssertMsg2( _exp, _msg, a1, a2 ) AssertMsg( _exp, _msg, a1, a2 )
  311. #define AssertMsg3( _exp, _msg, a1, a2, a3 ) AssertMsg( _exp, _msg, a1, a2, a3 )
  312. #define AssertMsg4( _exp, _msg, a1, a2, a3, a4 ) AssertMsg( _exp, _msg, a1, a2, a3, a4 )
  313. #define AssertMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) AssertMsg( _exp, _msg, a1, a2, a3, a4, a5 )
  314. #define AssertMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) AssertMsg( _exp, _msg, a1, a2, a3, a4, a5, a6 )
  315. #define AssertMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) AssertMsg( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 )
  316. #define AssertMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) AssertMsg( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 )
  317. #define AssertMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) AssertMsg( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 )
  318. #else // DBGFLAG_ASSERT
  319. #define Assert( _exp ) ((void)0)
  320. #define AssertOnce( _exp ) ((void)0)
  321. #define AssertMsg( _exp, _msg, ... ) ((void)0)
  322. #define AssertMsgOnce( _exp, _msg ) ((void)0)
  323. #define AssertFunc( _exp, _f ) ((void)0)
  324. #define AssertEquals( _exp, _expectedValue ) ((void)0)
  325. #define AssertFloatEquals( _exp, _expectedValue, _tol ) ((void)0)
  326. #define Verify( _exp ) (_exp)
  327. #define VerifyMsg1( _exp, _msg, a1 ) (_exp)
  328. #define VerifyMsg2( _exp, _msg, a1, a2 ) (_exp)
  329. #define VerifyMsg3( _exp, _msg, a1, a2, a3 ) (_exp)
  330. #define VerifyEquals( _exp, _expectedValue ) (_exp)
  331. #define DbgVerify( _exp ) (_exp)
  332. #define AssertMsg1( _exp, _msg, a1 ) ((void)0)
  333. #define AssertMsg2( _exp, _msg, a1, a2 ) ((void)0)
  334. #define AssertMsg3( _exp, _msg, a1, a2, a3 ) ((void)0)
  335. #define AssertMsg4( _exp, _msg, a1, a2, a3, a4 ) ((void)0)
  336. #define AssertMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) ((void)0)
  337. #define AssertMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0)
  338. #define AssertMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0)
  339. #define AssertMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) ((void)0)
  340. #define AssertMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) ((void)0)
  341. #define AssertMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) ((void)0)
  342. #endif // DBGFLAG_ASSERT
  343. // The Always version of the assert macros are defined even when DBGFLAG_ASSERT is not,
  344. // so they will be available even in release.
  345. #define AssertAlways( _exp ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), ((void)0), false )
  346. #define AssertMsgAlways( _exp, _msg ) _AssertMsg( _exp, _msg, ((void)0), false )
  347. // Stringify a number
  348. #define V_STRINGIFY_INTERNAL(x) #x
  349. // Extra level of indirection needed when passing in a macro to avoid getting the macro name instead of value
  350. #define V_STRINGIFY(x) V_STRINGIFY_INTERNAL(x)
  351. // Macros to help decorate warnings or errors with the location in code
  352. #define FILE_LINE_FUNCTION_STRING __FILE__ "(" V_STRINGIFY(__LINE__) "):" __FUNCTION__ ":"
  353. #define FILE_LINE_STRING __FILE__ "(" V_STRINGIFY(__LINE__) "):"
  354. #define FUNCTION_LINE_STRING __FUNCTION__ "(" V_STRINGIFY(__LINE__) "): "
  355. // Handy define for inserting clickable messages into the build output.
  356. // Use like this:
  357. // #pragma MESSAGE("Some message")
  358. #define MESSAGE(msg) message(__FILE__ "(" V_STRINGIFY(__LINE__) "): " msg)
  359. #if !defined( _X360 ) || !defined( _RETAIL )
  360. /* These are always compiled in */
  361. DBG_INTERFACE void Msg( PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
  362. DBG_INTERFACE void DMsg( const tchar *pGroupName, int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 3, 4 );
  363. DBG_INTERFACE void MsgV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist );
  364. DBG_INTERFACE void Warning( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
  365. DBG_INTERFACE void DWarning( const tchar *pGroupName, int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 3, 4 );
  366. DBG_INTERFACE void WarningV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist );
  367. DBG_INTERFACE void Log( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
  368. DBG_INTERFACE void DLog( const tchar *pGroupName, int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 3, 4 );
  369. DBG_INTERFACE void LogV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist );
  370. #ifdef Error
  371. // p4.cpp does a #define Error Warning and in that case the Error prototype needs to
  372. // be consistent with the Warning prototype.
  373. DBG_INTERFACE void Error( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
  374. #else
  375. DBG_INTERFACE void NORETURN Error( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
  376. DBG_INTERFACE void NORETURN ErrorV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist );
  377. #endif
  378. #else
  379. inline void Msg( ... ) {}
  380. inline void DMsg( ... ) {}
  381. inline void MsgV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ) {}
  382. inline void Warning( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) {}
  383. inline void WarningV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ) {}
  384. inline void DWarning( ... ) {}
  385. inline void Log( ... ) {}
  386. inline void DLog( ... ) {}
  387. inline void LogV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ) {}
  388. inline void Error( ... ) {}
  389. inline void ErrorV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ) {}
  390. #endif
  391. // You can use this macro like a runtime assert macro.
  392. // If the condition fails, then Error is called with the message. This macro is called
  393. // like AssertMsg, where msg must be enclosed in parenthesis:
  394. //
  395. // ErrorIfNot( bCondition, ("a b c %d %d %d", 1, 2, 3) );
  396. #define ErrorIfNot( condition, msg ) \
  397. if ( condition ) \
  398. ; \
  399. else \
  400. { \
  401. Error msg; \
  402. }
  403. #if !defined( _X360 ) || !defined( _RETAIL )
  404. /* A couple of super-common dynamic spew messages, here for convenience */
  405. /* These looked at the "developer" group */
  406. DBG_INTERFACE void DevMsg( int level, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
  407. DBG_INTERFACE void DevWarning( int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
  408. DBG_INTERFACE void DevLog( int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
  409. /* default level versions (level 1) */
  410. DBG_OVERLOAD void DevMsg( PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
  411. DBG_OVERLOAD void DevWarning( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
  412. DBG_OVERLOAD void DevLog( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
  413. /* These looked at the "console" group */
  414. DBG_INTERFACE void ConColorMsg( int level, const Color& clr, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 3, 4 );
  415. DBG_INTERFACE void ConMsg( int level, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
  416. DBG_INTERFACE void ConWarning( int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
  417. DBG_INTERFACE void ConLog( int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
  418. /* default console version (level 1) */
  419. DBG_OVERLOAD void ConColorMsg( const Color& clr, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
  420. DBG_OVERLOAD void ConMsg( PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
  421. DBG_OVERLOAD void ConWarning( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
  422. DBG_OVERLOAD void ConLog( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
  423. /* developer console version (level 2) */
  424. DBG_INTERFACE void ConDColorMsg( const Color& clr, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
  425. DBG_INTERFACE void ConDMsg( PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
  426. DBG_INTERFACE void ConDWarning( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
  427. DBG_INTERFACE void ConDLog( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
  428. /* These looked at the "network" group */
  429. DBG_INTERFACE void NetMsg( int level, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
  430. DBG_INTERFACE void NetWarning( int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
  431. DBG_INTERFACE void NetLog( int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
  432. void ValidateSpew( class CValidator &validator );
  433. #else
  434. inline void DevMsg( ... ) {}
  435. inline void DevWarning( ... ) {}
  436. inline void DevLog( ... ) {}
  437. inline void ConMsg( ... ) {}
  438. inline void ConLog( ... ) {}
  439. inline void NetMsg( ... ) {}
  440. inline void NetWarning( ... ) {}
  441. inline void NetLog( ... ) {}
  442. #endif
  443. DBG_INTERFACE void COM_TimestampedLog( PRINTF_FORMAT_STRING char const *fmt, ... ) FMTFUNCTION( 1, 2 );
  444. /* Code macros, debugger interface */
  445. #ifdef DBGFLAG_ASSERT
  446. #define DBG_CODE( _code ) if (0) ; else { _code }
  447. #define DBG_CODE_NOSCOPE( _code ) _code
  448. #define DBG_DCODE( _g, _l, _code ) if (IsSpewActive( _g, _l )) { _code } else {}
  449. #define DBG_BREAK() DebuggerBreak() /* defined in platform.h */
  450. #else /* not _DEBUG */
  451. #define DBG_CODE( _code ) ((void)0)
  452. #define DBG_CODE_NOSCOPE( _code )
  453. #define DBG_DCODE( _g, _l, _code ) ((void)0)
  454. #define DBG_BREAK() ((void)0)
  455. #endif /* _DEBUG */
  456. //-----------------------------------------------------------------------------
  457. #ifndef _RETAIL
  458. class CScopeMsg
  459. {
  460. public:
  461. CScopeMsg( const char *pszScope )
  462. {
  463. m_pszScope = pszScope;
  464. Msg( "%s { ", pszScope );
  465. }
  466. ~CScopeMsg()
  467. {
  468. Msg( "} %s", m_pszScope );
  469. }
  470. const char *m_pszScope;
  471. };
  472. #define SCOPE_MSG( msg ) CScopeMsg scopeMsg( msg )
  473. #else
  474. #define SCOPE_MSG( msg )
  475. #endif
  476. //-----------------------------------------------------------------------------
  477. // This macro predates universal static_assert support in our toolchains
  478. #define COMPILE_TIME_ASSERT( pred ) static_assert( pred, "Compile time assert constraint is not true: " #pred )
  479. // ASSERT_INVARIANT used to be needed in order to allow COMPILE_TIME_ASSERTs at global
  480. // scope. However the new COMPILE_TIME_ASSERT macro supports that by default.
  481. #define ASSERT_INVARIANT( pred ) COMPILE_TIME_ASSERT( pred )
  482. // NOTE: On GCC / Clang, assert_cast can sometimes fire even if the type is correct. We should just workaround these.
  483. // The situation where this would occur is
  484. // 1. You create an object of a low level type in a DLL, and it really gets created there.
  485. // 2. You pass it across a DLL boundary
  486. // 3. You use assert_cast to verify it in the second DLL boundary (where it also could've been created).
  487. #ifdef _DEBUG
  488. template<typename DEST_POINTER_TYPE, typename SOURCE_POINTER_TYPE>
  489. inline DEST_POINTER_TYPE assert_cast(SOURCE_POINTER_TYPE* pSource)
  490. {
  491. Assert( static_cast<DEST_POINTER_TYPE>(pSource) == dynamic_cast<DEST_POINTER_TYPE>(pSource) );
  492. return static_cast<DEST_POINTER_TYPE>(pSource);
  493. }
  494. #else
  495. #define assert_cast static_cast
  496. #endif
  497. //-----------------------------------------------------------------------------
  498. // Templates to assist in validating pointers:
  499. // Have to use these stubs so we don't have to include windows.h here.
  500. DBG_INTERFACE void _AssertValidReadPtr( void* ptr, int count = 1 );
  501. DBG_INTERFACE void _AssertValidWritePtr( void* ptr, int count = 1 );
  502. DBG_INTERFACE void _AssertValidReadWritePtr( void* ptr, int count = 1 );
  503. DBG_INTERFACE void AssertValidStringPtr( const tchar* ptr, int maxchar = 0xFFFFFF );
  504. #ifdef DBGFLAG_ASSERT
  505. FORCEINLINE void AssertValidReadPtr( const void* ptr, int count = 1 ) { _AssertValidReadPtr( (void*)ptr, count ); }
  506. FORCEINLINE void AssertValidWritePtr( const void* ptr, int count = 1 ) { _AssertValidWritePtr( (void*)ptr, count ); }
  507. FORCEINLINE void AssertValidReadWritePtr( const void* ptr, int count = 1 ) { _AssertValidReadWritePtr( (void*)ptr, count ); }
  508. #else
  509. FORCEINLINE void AssertValidReadPtr( const void* ptr, int count = 1 ) { }
  510. FORCEINLINE void AssertValidWritePtr( const void* ptr, int count = 1 ) { }
  511. FORCEINLINE void AssertValidReadWritePtr( const void* ptr, int count = 1 ) { }
  512. #define AssertValidStringPtr AssertValidReadPtr
  513. #endif
  514. #define AssertValidThis() AssertValidReadWritePtr(this,sizeof(*this))
  515. //-----------------------------------------------------------------------------
  516. // Macro to protect functions that are not reentrant
  517. #ifdef _DEBUG
  518. class CReentryGuard
  519. {
  520. public:
  521. CReentryGuard(int *pSemaphore)
  522. : m_pSemaphore(pSemaphore)
  523. {
  524. ++(*m_pSemaphore);
  525. }
  526. ~CReentryGuard()
  527. {
  528. --(*m_pSemaphore);
  529. }
  530. private:
  531. int *m_pSemaphore;
  532. };
  533. #define ASSERT_NO_REENTRY() \
  534. static int fSemaphore##__LINE__; \
  535. Assert( !fSemaphore##__LINE__ ); \
  536. CReentryGuard ReentryGuard##__LINE__( &fSemaphore##__LINE__ )
  537. #else
  538. #define ASSERT_NO_REENTRY()
  539. #endif
  540. //-----------------------------------------------------------------------------
  541. //
  542. // Purpose: Inline string formatter
  543. //
  544. #include "tier0/valve_off.h"
  545. class CDbgFmtMsg
  546. {
  547. public:
  548. CDbgFmtMsg(PRINTF_FORMAT_STRING const tchar *pszFormat, ...) FMTFUNCTION( 2, 3 )
  549. {
  550. va_list arg_ptr;
  551. va_start(arg_ptr, pszFormat);
  552. _vsntprintf(m_szBuf, sizeof(m_szBuf)-1, pszFormat, arg_ptr);
  553. va_end(arg_ptr);
  554. m_szBuf[sizeof(m_szBuf)-1] = 0;
  555. }
  556. operator const tchar *() const
  557. {
  558. return m_szBuf;
  559. }
  560. private:
  561. tchar m_szBuf[256];
  562. };
  563. #include "tier0/valve_on.h"
  564. //-----------------------------------------------------------------------------
  565. //
  566. // Purpose: Embed debug info in each file.
  567. //
  568. #if defined( _WIN32 ) && !defined( _X360 )
  569. #ifdef _DEBUG
  570. #pragma comment(compiler)
  571. #endif
  572. #endif
  573. //-----------------------------------------------------------------------------
  574. //
  575. // Purpose: Wrap around a variable to create a simple place to put a breakpoint
  576. //
  577. #ifdef _DEBUG
  578. template< class Type >
  579. class CDataWatcher
  580. {
  581. public:
  582. const Type& operator=( const Type &val )
  583. {
  584. return Set( val );
  585. }
  586. const Type& operator=( const CDataWatcher<Type> &val )
  587. {
  588. return Set( val.m_Value );
  589. }
  590. const Type& Set( const Type &val )
  591. {
  592. // Put your breakpoint here
  593. m_Value = val;
  594. return m_Value;
  595. }
  596. Type& GetForModify()
  597. {
  598. return m_Value;
  599. }
  600. const Type& operator+=( const Type &val )
  601. {
  602. return Set( m_Value + val );
  603. }
  604. const Type& operator-=( const Type &val )
  605. {
  606. return Set( m_Value - val );
  607. }
  608. const Type& operator/=( const Type &val )
  609. {
  610. return Set( m_Value / val );
  611. }
  612. const Type& operator*=( const Type &val )
  613. {
  614. return Set( m_Value * val );
  615. }
  616. const Type& operator^=( const Type &val )
  617. {
  618. return Set( m_Value ^ val );
  619. }
  620. const Type& operator|=( const Type &val )
  621. {
  622. return Set( m_Value | val );
  623. }
  624. const Type& operator++()
  625. {
  626. return (*this += 1);
  627. }
  628. Type operator--()
  629. {
  630. return (*this -= 1);
  631. }
  632. Type operator++( int ) // postfix version..
  633. {
  634. Type val = m_Value;
  635. (*this += 1);
  636. return val;
  637. }
  638. Type operator--( int ) // postfix version..
  639. {
  640. Type val = m_Value;
  641. (*this -= 1);
  642. return val;
  643. }
  644. // For some reason the compiler only generates type conversion warnings for this operator when used like
  645. // CNetworkVarBase<unsigned tchar> = 0x1
  646. // (it warns about converting from an int to an unsigned char).
  647. template< class C >
  648. const Type& operator&=( C val )
  649. {
  650. return Set( m_Value & val );
  651. }
  652. operator const Type&() const
  653. {
  654. return m_Value;
  655. }
  656. const Type& Get() const
  657. {
  658. return m_Value;
  659. }
  660. const Type* operator->() const
  661. {
  662. return &m_Value;
  663. }
  664. Type m_Value;
  665. };
  666. #else
  667. template< class Type >
  668. class CDataWatcher
  669. {
  670. private:
  671. CDataWatcher(); // refuse to compile in non-debug builds
  672. };
  673. #endif
  674. //-----------------------------------------------------------------------------
  675. // This is horrible, but we don't want to integrate CS:GO new logging system atm.
  676. #define Log_Warning( ignore, ... ) ::Msg( __VA_ARGS__ ); ::Log( __VA_ARGS__ );
  677. #define Log_Msg( ignore, ... ) ::Warning( __VA_ARGS__ ); ::Log( __VA_ARGS__ );
  678. #define Log_Error( ignore, ... ) ::Error( __VA_ARGS__ );
  679. #define DEFINE_LOGGING_CHANNEL_NO_TAGS( ... );
  680. #define Plat_FatalError( ... ) do { Log_Error( LOG_GENERAL, __VA_ARGS__ ); Plat_ExitProcess( EXIT_FAILURE ); } while( 0 )
  681. #endif /* DBG_H */