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.

716 lines
25 KiB

  1. //===== Copyright (c) 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 "tier0/platform.h"
  14. #include "tier0/basetypes.h"
  15. #include "dbgflag.h"
  16. #include "logging.h"
  17. #include <math.h>
  18. #include <stdio.h>
  19. #include <stdarg.h>
  20. //-----------------------------------------------------------------------------
  21. // dll export stuff
  22. //-----------------------------------------------------------------------------
  23. class Color;
  24. //-----------------------------------------------------------------------------
  25. // Usage model for the Dbg library
  26. //
  27. // 1. Assertions.
  28. //
  29. // Assertions are used to detect and warn about invalid states
  30. //
  31. // To use an assertion, use
  32. //
  33. // Assert( (f == 5) );
  34. // AssertMsg( (f == 5), ("F needs to be %d here!\n", 5) );
  35. // AssertFunc( (f == 5), BadFunc() );
  36. // AssertEquals( f, 5 );
  37. // AssertFloatEquals( f, 5.0f, 1e-3 );
  38. //
  39. // The first will simply report that an assertion failed on a particular
  40. // code file and line. The second version will display a print-f formatted message
  41. // along with the file and line, the third will display a generic message and
  42. // will also cause the function BadFunc to be executed, and the last two
  43. // will report an error if f is not equal to 5 (the last one asserts within
  44. // a particular tolerance).
  45. //
  46. // 2. Code activation
  47. //
  48. // To cause code to be run only in debug builds, use DBG_CODE:
  49. // An example is below.
  50. //
  51. // DBG_CODE(
  52. // {
  53. // int x = 5;
  54. // ++x;
  55. // }
  56. // );
  57. //
  58. // Code can be activated based on the dynamic spew groups also. Use
  59. //
  60. // DBG_DCODE( "group", level,
  61. // { int x = 5; ++x; }
  62. // );
  63. //
  64. // 3. Breaking into the debugger.
  65. //
  66. // To cause an unconditional break into the debugger in debug builds only, use DBG_BREAK
  67. //
  68. // DBG_BREAK();
  69. //
  70. // You can force a break in any build (release or debug) using
  71. //
  72. // DebuggerBreak();
  73. //-----------------------------------------------------------------------------
  74. PLATFORM_INTERFACE void _ExitOnFatalAssert( const tchar* pFile, int line );
  75. #if defined( DBGFLAG_STRINGS_STRIP )
  76. #define DbgFlagMacro_ExitOnFatalAssert( pFile, line ) _ExitOnFatalAssert( "", 0 )
  77. #else
  78. #define DbgFlagMacro_ExitOnFatalAssert( pFile, line ) _ExitOnFatalAssert( pFile, line )
  79. #endif
  80. PLATFORM_INTERFACE bool ShouldUseNewAssertDialog();
  81. PLATFORM_INTERFACE bool SetupWin32ConsoleIO();
  82. // Returns true if they want to break in the debugger.
  83. PLATFORM_INTERFACE bool DoNewAssertDialog( const tchar *pFile, int line, const tchar *pExpression );
  84. #if defined( DBGFLAG_STRINGS_STRIP )
  85. #define DbgFlagMacro_DoNewAssertDialog( pFile, line, pExpression ) DoNewAssertDialog( "", 0, "" )
  86. #else
  87. #define DbgFlagMacro_DoNewAssertDialog( pFile, line, pExpression ) DoNewAssertDialog( pFile, line, pExpression )
  88. #endif
  89. /* Used to define macros, never use these directly. */
  90. #ifdef _PREFAST_
  91. // When doing /analyze builds define the assert macros to be __analysis_assume. This tells
  92. // the compiler to assume that the condition is true, which helps to suppress many
  93. // warnings. This define is done in debug and release builds, but debug builds should be
  94. // preferred for static analysis because some asserts are compiled out in release.
  95. // The unfortunate !! is necessary because otherwise /analyze is incapable of evaluating
  96. // all of the logical expressions that the regular compiler can handle.
  97. #define _AssertMsg( _exp, _msg, _executeExp, _bFatal ) __analysis_assume( !!(_exp) )
  98. #define _AssertMsgOnce( _exp, _msg, _bFatal ) __analysis_assume( !!(_exp) )
  99. // Force asserts on for /analyze so that we get a __analysis_assume of all of the constraints.
  100. #define DBGFLAG_ASSERT
  101. #define DBGFLAG_ASSERTFATAL
  102. #else
  103. #define _AssertMsg( _exp, _msg, _executeExp, _bFatal ) \
  104. do { \
  105. if (!(_exp)) \
  106. { \
  107. LoggingResponse_t ret = Log_Assert( "%s (%d) : %s\n", __TFILE__, __LINE__, _msg ); \
  108. _executeExp; \
  109. if ( ret == LR_DEBUGGER ) \
  110. { \
  111. if ( !ShouldUseNewAssertDialog() || DbgFlagMacro_DoNewAssertDialog( __TFILE__, __LINE__, _msg ) ) \
  112. DebuggerBreak(); \
  113. if ( _bFatal ) \
  114. DbgFlagMacro_ExitOnFatalAssert( __TFILE__, __LINE__ ); \
  115. } \
  116. } \
  117. } while (0)
  118. #define _AssertMsgOnce( _exp, _msg, _bFatal ) \
  119. do { \
  120. static bool fAsserted; \
  121. if (!fAsserted ) \
  122. { \
  123. _AssertMsg( _exp, _msg, (fAsserted = true), _bFatal ); \
  124. } \
  125. } while (0)
  126. #endif
  127. /* Spew macros... */
  128. // AssertFatal macros
  129. // AssertFatal is used to detect an unrecoverable error condition.
  130. // If enabled, it may display an assert dialog (if DBGFLAG_ASSERTDLG is turned on or running under the debugger),
  131. // and always terminates the application
  132. #ifdef DBGFLAG_ASSERTFATAL
  133. #define AssertFatal( _exp ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), ((void)0), true )
  134. #define AssertFatalOnce( _exp ) _AssertMsgOnce( _exp, _T("Assertion Failed: ") _T(#_exp), true )
  135. #define AssertFatalMsg( _exp, _msg ) _AssertMsg( _exp, _msg, ((void)0), true )
  136. #define AssertFatalMsgOnce( _exp, _msg ) _AssertMsgOnce( _exp, _msg, true )
  137. #define AssertFatalFunc( _exp, _f ) _AssertMsg( _exp, _T("Assertion Failed: " _T(#_exp), _f, true )
  138. #define AssertFatalEquals( _exp, _expectedValue ) AssertFatalMsg2( (_exp) == (_expectedValue), _T("Expected %d but got %d!"), (_expectedValue), (_exp) )
  139. #define AssertFatalFloatEquals( _exp, _expectedValue, _tol ) AssertFatalMsg2( fabs((_exp) - (_expectedValue)) <= (_tol), _T("Expected %f but got %f!"), (_expectedValue), (_exp) )
  140. #define VerifyFatal( _exp ) AssertFatal( _exp )
  141. #define VerifyEqualsFatal( _exp, _expectedValue ) AssertFatalEquals( _exp, _expectedValue )
  142. #define AssertFatalMsg1( _exp, _msg, a1 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1 )))
  143. #define AssertFatalMsg2( _exp, _msg, a1, a2 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2 )))
  144. #define AssertFatalMsg3( _exp, _msg, a1, a2, a3 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3 )))
  145. #define AssertFatalMsg4( _exp, _msg, a1, a2, a3, a4 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4 )))
  146. #define AssertFatalMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5 )))
  147. #define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6 )))
  148. #define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6 )))
  149. #define AssertFatalMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6, a7 )))
  150. #define AssertFatalMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6, a7, a8 )))
  151. #define AssertFatalMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 )))
  152. #else // DBGFLAG_ASSERTFATAL
  153. #define AssertFatal( _exp ) ((void)0)
  154. #define AssertFatalOnce( _exp ) ((void)0)
  155. #define AssertFatalMsg( _exp, _msg ) ((void)0)
  156. #define AssertFatalMsgOnce( _exp, _msg ) ((void)0)
  157. #define AssertFatalFunc( _exp, _f ) ((void)0)
  158. #define AssertFatalEquals( _exp, _expectedValue ) ((void)0)
  159. #define AssertFatalFloatEquals( _exp, _expectedValue, _tol ) ((void)0)
  160. #define VerifyFatal( _exp ) (_exp)
  161. #define VerifyEqualsFatal( _exp, _expectedValue ) (_exp)
  162. #define AssertFatalMsg1( _exp, _msg, a1 ) ((void)0)
  163. #define AssertFatalMsg2( _exp, _msg, a1, a2 ) ((void)0)
  164. #define AssertFatalMsg3( _exp, _msg, a1, a2, a3 ) ((void)0)
  165. #define AssertFatalMsg4( _exp, _msg, a1, a2, a3, a4 ) ((void)0)
  166. #define AssertFatalMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) ((void)0)
  167. #define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0)
  168. #define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0)
  169. #define AssertFatalMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) ((void)0)
  170. #define AssertFatalMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) ((void)0)
  171. #define AssertFatalMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) ((void)0)
  172. #endif // DBGFLAG_ASSERTFATAL
  173. // lightweight assert macros: in theory, can be run in release without slowing it down
  174. #if defined(_CERT) || defined(_RETAIL)
  175. #define AssertAligned(PTR)
  176. #else
  177. # if defined( _X360 )
  178. # define AssertAligned(PTR) __twnei( intp(PTR) & 0xF, 0 ) // trap if not equal to immediate value; unsigned comparison
  179. # elif defined( DBGFLAG_ASSERT )
  180. # define AssertAligned( adr ) Assert( ( ( ( intp ) ( adr ) ) & 0xf ) == 0 )
  181. # else
  182. # define AssertAligned(PTR)
  183. # endif
  184. #endif
  185. // Assert macros
  186. // Assert is used to detect an important but survivable error.
  187. // It's only turned on when DBGFLAG_ASSERT is true.
  188. #ifdef DBGFLAG_ASSERT
  189. #define Assert( _exp ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), ((void)0), false )
  190. #define AssertMsg_( _exp, _msg ) _AssertMsg( _exp, _msg, ((void)0), false )
  191. #define AssertOnce( _exp ) _AssertMsgOnce( _exp, _T("Assertion Failed: ") _T(#_exp), false )
  192. #define AssertMsgOnce( _exp, _msg ) _AssertMsgOnce( _exp, _msg, false )
  193. #define AssertFunc( _exp, _f ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), _f, false )
  194. #define AssertEquals( _exp, _expectedValue ) AssertMsg2( (_exp) == (_expectedValue), _T("Expected %d but got %d!"), (_expectedValue), (_exp) )
  195. #define AssertFloatEquals( _exp, _expectedValue, _tol ) AssertMsg2( fabs((_exp) - (_expectedValue)) <= (_tol), _T("Expected %f but got %f!"), (_expectedValue), (_exp) )
  196. #define Verify( _exp ) Assert( _exp )
  197. #define VerifyEquals( _exp, _expectedValue ) AssertEquals( _exp, _expectedValue )
  198. #define AssertMsg( _exp, _msg ) AssertMsg_( _exp, _T( _msg ) )
  199. #define AssertMsg1( _exp, _msg, a1 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1 )) )
  200. #define AssertMsg2( _exp, _msg, a1, a2 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2 )) )
  201. #define AssertMsg3( _exp, _msg, a1, a2, a3 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3 )) )
  202. #define AssertMsg4( _exp, _msg, a1, a2, a3, a4 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4 )) )
  203. #define AssertMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4, a5 )) )
  204. #define AssertMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4, a5, a6 )) )
  205. #define AssertMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4, a5, a6, a7 )) )
  206. #define AssertMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4, a5, a6, a7, a8 )) )
  207. #define AssertMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4, a5, a6, a7, a8, a9 )) )
  208. #else // DBGFLAG_ASSERT
  209. #define Assert( _exp ) ((void)0)
  210. #define AssertOnce( _exp ) ((void)0)
  211. #define AssertMsg( _exp, _msg ) ((void)0)
  212. #define AssertMsgOnce( _exp, _msg ) ((void)0)
  213. #define AssertFunc( _exp, _f ) ((void)0)
  214. #define AssertEquals( _exp, _expectedValue ) ((void)0)
  215. #define AssertFloatEquals( _exp, _expectedValue, _tol ) ((void)0)
  216. #define Verify( _exp ) (_exp)
  217. #define VerifyEquals( _exp, _expectedValue ) (_exp)
  218. #define AssertMsg1( _exp, _msg, a1 ) ((void)0)
  219. #define AssertMsg2( _exp, _msg, a1, a2 ) ((void)0)
  220. #define AssertMsg3( _exp, _msg, a1, a2, a3 ) ((void)0)
  221. #define AssertMsg4( _exp, _msg, a1, a2, a3, a4 ) ((void)0)
  222. #define AssertMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) ((void)0)
  223. #define AssertMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0)
  224. #define AssertMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0)
  225. #define AssertMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) ((void)0)
  226. #define AssertMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) ((void)0)
  227. #define AssertMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) ((void)0)
  228. #endif // DBGFLAG_ASSERT
  229. #define STRINGIFY_INTERNAL(x) #x
  230. #define STRINGIFY(x) STRINGIFY_INTERNAL(x)
  231. #define FILE_LINE_FUNCTION_STRING __FILE__ "(" STRINGIFY(__LINE__) "):" __FUNCTION__ ":"
  232. #define FILE_LINE_STRING __FILE__ "(" STRINGIFY(__LINE__) "):"
  233. #define FUNCTION_LINE_STRING __FUNCTION__ "(" STRINGIFY(__LINE__) "): "
  234. //////////////////////////////////////////////////////////////////////////
  235. // Legacy Logging System
  236. //////////////////////////////////////////////////////////////////////////
  237. // Channels which map the legacy logging system to the new system.
  238. // Channel for all default Msg/Warning/Error commands.
  239. DECLARE_LOGGING_CHANNEL( LOG_GENERAL );
  240. // Channel for all asserts.
  241. DECLARE_LOGGING_CHANNEL( LOG_ASSERT );
  242. // Channel for all ConMsg and ConColorMsg commands.
  243. DECLARE_LOGGING_CHANNEL( LOG_CONSOLE );
  244. // Channel for all DevMsg and DevWarning commands with level < 2.
  245. DECLARE_LOGGING_CHANNEL( LOG_DEVELOPER );
  246. // Channel for ConDMsg commands.
  247. DECLARE_LOGGING_CHANNEL( LOG_DEVELOPER_CONSOLE );
  248. // Channel for all DevMsg and DevWarning commands with level >= 2.
  249. DECLARE_LOGGING_CHANNEL( LOG_DEVELOPER_VERBOSE );
  250. // Legacy logging functions
  251. PLATFORM_INTERFACE void Error( const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
  252. PLATFORM_INTERFACE void Error_SpewCallStack( int iMaxCallStackLength, const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
  253. #if defined( DBGFLAG_STRINGS_STRIP ) && !defined( TIER0_DLL_EXPORT )
  254. #define Msg( ... ) ((void)0)
  255. #define Warning( ... ) ((void)0)
  256. #define Warning_SpewCallStack( ... ) ((void)0)
  257. #define DevMsg( ... ) ((void)0)
  258. #define DevWarning( ... ) ((void)0)
  259. #define ConColorMsg( ... ) ((void)0)
  260. #define ConMsg( ... ) ((void)0)
  261. #define ConDMsg( ... ) ((void)0)
  262. #define COM_TimestampedLog( ... ) ((void)0)
  263. #else // #if defined( DBGFLAG_STRINGS_STRIP ) && !defined( TIER0_DLL_EXPORT )
  264. PLATFORM_INTERFACE void Msg( const tchar* pMsg, ... );
  265. PLATFORM_INTERFACE void Warning( const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
  266. PLATFORM_INTERFACE void Warning_SpewCallStack( int iMaxCallStackLength, const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
  267. #ifdef _PS3
  268. PLATFORM_OVERLOAD void DevMsg( int level, const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
  269. PLATFORM_OVERLOAD void DevWarning( int level, const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
  270. PLATFORM_INTERFACE void DevMsg( const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
  271. PLATFORM_INTERFACE void DevWarning( const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
  272. PLATFORM_INTERFACE void ConColorMsg( const Color& clr, const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
  273. PLATFORM_INTERFACE void ConMsg( const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
  274. #else // !_PS3
  275. PLATFORM_INTERFACE void DevMsg( int level, const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
  276. PLATFORM_INTERFACE void DevWarning( int level, const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
  277. PLATFORM_OVERLOAD void DevMsg( const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
  278. PLATFORM_OVERLOAD void DevWarning( const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
  279. PLATFORM_OVERLOAD void ConColorMsg( const Color& clr, const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
  280. PLATFORM_OVERLOAD void ConMsg( const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
  281. #endif // _PS3
  282. PLATFORM_INTERFACE void ConDMsg( const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
  283. PLATFORM_INTERFACE void COM_TimestampedLog( char const *fmt, ... ) FMTFUNCTION( 1, 2 );
  284. #endif // #if defined( DBGFLAG_STRINGS_STRIP ) && !defined( TIER0_DLL_EXPORT )
  285. // You can use this macro like a runtime assert macro.
  286. // If the condition fails, then Error is called with the message. This macro is called
  287. // like AssertMsg, where msg must be enclosed in parenthesis:
  288. //
  289. // ErrorIfNot( bCondition, ("a b c %d %d %d", 1, 2, 3) );
  290. #define ErrorIfNot( condition, msg ) \
  291. if ( (condition) ) \
  292. ; \
  293. else \
  294. { \
  295. Error msg; \
  296. }
  297. #ifdef _DEBUG
  298. #define DebugMsg(...) DevMsg(__VA_ARGS__)
  299. #else
  300. #define DebugMsg(...)
  301. #endif
  302. // @TODO: these callstack spew functions are currently disabled in the new logging system. Need to add support for these if desired.
  303. PLATFORM_INTERFACE void _Warning_AlwaysSpewCallStack_Enable( bool bEnable );
  304. PLATFORM_INTERFACE void _Warning_AlwaysSpewCallStack_Length( int iMaxCallStackLength );
  305. PLATFORM_INTERFACE void _Error_AlwaysSpewCallStack_Enable( bool bEnable );
  306. PLATFORM_INTERFACE void _Error_AlwaysSpewCallStack_Length( int iMaxCallStackLength );
  307. /* Code macros, debugger interface */
  308. #ifdef _DEBUG
  309. #define DBG_CODE( _code ) if (0) ; else { _code }
  310. #define DBG_CODE_NOSCOPE( _code ) _code
  311. #define DBG_DCODE( _g, _l, _code ) if (IsSpewActive( _g, _l )) { _code } else {}
  312. #define DBG_BREAK() DebuggerBreak() /* defined in platform.h */
  313. #else /* not _DEBUG */
  314. #define DBG_CODE( _code ) ((void)0)
  315. #define DBG_CODE_NOSCOPE( _code )
  316. #define DBG_DCODE( _g, _l, _code ) ((void)0)
  317. #define DBG_BREAK() ((void)0)
  318. #endif /* _DEBUG */
  319. //-----------------------------------------------------------------------------
  320. // Macro to assist in asserting constant invariants during compilation
  321. #ifdef _DEBUG
  322. #define COMPILE_TIME_ASSERT( pred ) switch(0){case 0:case pred:;}
  323. #define ASSERT_INVARIANT( pred ) static void UNIQUE_ID() { COMPILE_TIME_ASSERT( pred ) }
  324. #else
  325. #define COMPILE_TIME_ASSERT( pred )
  326. #define ASSERT_INVARIANT( pred )
  327. #endif
  328. #ifdef _DEBUG
  329. template<typename DEST_POINTER_TYPE, typename SOURCE_POINTER_TYPE>
  330. inline DEST_POINTER_TYPE assert_cast(SOURCE_POINTER_TYPE* pSource)
  331. {
  332. Assert( static_cast<DEST_POINTER_TYPE>(pSource) == dynamic_cast<DEST_POINTER_TYPE>(pSource) );
  333. return static_cast<DEST_POINTER_TYPE>(pSource);
  334. }
  335. #else
  336. #define assert_cast static_cast
  337. #endif
  338. //-----------------------------------------------------------------------------
  339. // Templates to assist in validating pointers:
  340. // Have to use these stubs so we don't have to include windows.h here.
  341. PLATFORM_INTERFACE void _AssertValidReadPtr( void* ptr, int count = 1 );
  342. PLATFORM_INTERFACE void _AssertValidWritePtr( void* ptr, int count = 1 );
  343. PLATFORM_INTERFACE void _AssertValidReadWritePtr( void* ptr, int count = 1 );
  344. PLATFORM_INTERFACE void _AssertValidStringPtr( const tchar* ptr, int maxchar );
  345. #ifdef DBGFLAG_ASSERT
  346. inline void AssertValidStringPtr( const tchar* ptr, int maxchar = 0xFFFFFF ) { _AssertValidStringPtr( ptr, maxchar ); }
  347. template<class T> inline void AssertValidReadPtr( T* ptr, int count = 1 ) { _AssertValidReadPtr( (void*)ptr, count ); }
  348. template<class T> inline void AssertValidWritePtr( T* ptr, int count = 1 ) { _AssertValidWritePtr( (void*)ptr, count ); }
  349. template<class T> inline void AssertValidReadWritePtr( T* ptr, int count = 1 ) { _AssertValidReadWritePtr( (void*)ptr, count ); }
  350. #define AssertValidThis() AssertValidReadWritePtr(this,sizeof(*this))
  351. #else
  352. inline void AssertValidStringPtr( const tchar* ptr, int maxchar = 0xFFFFFF ) { }
  353. template<class T> inline void AssertValidReadPtr( T* ptr, int count = 1 ) { }
  354. template<class T> inline void AssertValidWritePtr( T* ptr, int count = 1 ) { }
  355. template<class T> inline void AssertValidReadWritePtr( T* ptr, int count = 1 ) { }
  356. #define AssertValidThis()
  357. #endif
  358. //-----------------------------------------------------------------------------
  359. // Macro to protect functions that are not reentrant
  360. #ifdef _DEBUG
  361. class CReentryGuard
  362. {
  363. public:
  364. CReentryGuard(int *pSemaphore)
  365. : m_pSemaphore(pSemaphore)
  366. {
  367. ++(*m_pSemaphore);
  368. }
  369. ~CReentryGuard()
  370. {
  371. --(*m_pSemaphore);
  372. }
  373. private:
  374. int *m_pSemaphore;
  375. };
  376. #define ASSERT_NO_REENTRY() \
  377. static int fSemaphore##__LINE__; \
  378. Assert( !fSemaphore##__LINE__ ); \
  379. CReentryGuard ReentryGuard##__LINE__( &fSemaphore##__LINE__ )
  380. #else
  381. #define ASSERT_NO_REENTRY()
  382. #endif
  383. // Tier0 uses these for string functions since this abstraction is normally done in tier1.
  384. #ifdef POSIX
  385. #define Tier0Internal_sntprintf snprintf
  386. #define Tier0Internal_vsntprintf vsnprintf
  387. #define Tier0Internal_vsnprintf vsnprintf
  388. #else
  389. #define Tier0Internal_sntprintf _sntprintf
  390. #define Tier0Internal_vsntprintf _vsntprintf
  391. #define Tier0Internal_vsnprintf _vsnprintf
  392. #endif
  393. //-----------------------------------------------------------------------------
  394. //
  395. // Purpose: Inline string formatter
  396. //
  397. #include "tier0/valve_off.h"
  398. class CDbgFmtMsg
  399. {
  400. public:
  401. CDbgFmtMsg(const tchar *pszFormat, ...)
  402. {
  403. va_list arg_ptr;
  404. va_start(arg_ptr, pszFormat);
  405. Tier0Internal_vsntprintf(m_szBuf, sizeof(m_szBuf)-1, pszFormat, arg_ptr);
  406. va_end(arg_ptr);
  407. m_szBuf[sizeof(m_szBuf)-1] = 0;
  408. }
  409. operator const tchar *() const
  410. {
  411. return m_szBuf;
  412. }
  413. private:
  414. tchar m_szBuf[256];
  415. };
  416. #include "tier0/valve_on.h"
  417. //-----------------------------------------------------------------------------
  418. //
  419. // Purpose: Embed debug info in each file.
  420. //
  421. #if defined( _WIN32 ) && !defined( _X360 )
  422. #ifdef _DEBUG
  423. #pragma comment(compiler)
  424. #endif
  425. #endif
  426. //-----------------------------------------------------------------------------
  427. //
  428. // Purpose: Wrap around a variable to create a simple place to put a breakpoint
  429. //
  430. #ifdef _DEBUG
  431. template< class Type >
  432. class CDataWatcher
  433. {
  434. public:
  435. const Type& operator=( const Type &val )
  436. {
  437. return Set( val );
  438. }
  439. const Type& operator=( const CDataWatcher<Type> &val )
  440. {
  441. return Set( val.m_Value );
  442. }
  443. const Type& Set( const Type &val )
  444. {
  445. // Put your breakpoint here
  446. m_Value = val;
  447. return m_Value;
  448. }
  449. Type& GetForModify()
  450. {
  451. return m_Value;
  452. }
  453. const Type& operator+=( const Type &val )
  454. {
  455. return Set( m_Value + val );
  456. }
  457. const Type& operator-=( const Type &val )
  458. {
  459. return Set( m_Value - val );
  460. }
  461. const Type& operator/=( const Type &val )
  462. {
  463. return Set( m_Value / val );
  464. }
  465. const Type& operator*=( const Type &val )
  466. {
  467. return Set( m_Value * val );
  468. }
  469. const Type& operator^=( const Type &val )
  470. {
  471. return Set( m_Value ^ val );
  472. }
  473. const Type& operator|=( const Type &val )
  474. {
  475. return Set( m_Value | val );
  476. }
  477. const Type& operator++()
  478. {
  479. return (*this += 1);
  480. }
  481. Type operator--()
  482. {
  483. return (*this -= 1);
  484. }
  485. Type operator++( int ) // postfix version..
  486. {
  487. Type val = m_Value;
  488. (*this += 1);
  489. return val;
  490. }
  491. Type operator--( int ) // postfix version..
  492. {
  493. Type val = m_Value;
  494. (*this -= 1);
  495. return val;
  496. }
  497. // For some reason the compiler only generates type conversion warnings for this operator when used like
  498. // CNetworkVarBase<unsigned tchar> = 0x1
  499. // (it warns about converting from an int to an unsigned char).
  500. template< class C >
  501. const Type& operator&=( C val )
  502. {
  503. return Set( m_Value & val );
  504. }
  505. operator const Type&() const
  506. {
  507. return m_Value;
  508. }
  509. const Type& Get() const
  510. {
  511. return m_Value;
  512. }
  513. const Type* operator->() const
  514. {
  515. return &m_Value;
  516. }
  517. Type m_Value;
  518. };
  519. #else
  520. template< class Type >
  521. class CDataWatcher
  522. {
  523. private:
  524. CDataWatcher(); // refuse to compile in non-debug builds
  525. };
  526. #endif
  527. // Code for programmatically setting/unsetting hardware breakpoints (there's probably a 360 and
  528. #ifdef IS_WINDOWS_PC
  529. typedef void * HardwareBreakpointHandle_t;
  530. enum EHardwareBreakpointType
  531. {
  532. BREAKPOINT_EXECUTE = 0,
  533. BREAKPOINT_WRITE,
  534. BREAKPOINT_READWRITE,
  535. };
  536. enum EHardwareBreakpointSize
  537. {
  538. BREAKPOINT_SIZE_1 = 1,
  539. BREAKPOINT_SIZE_2 = 2,
  540. BREAKPOINT_SIZE_4 = 4,
  541. BREAKPOINT_SIZE_8 = 8,
  542. };
  543. PLATFORM_INTERFACE HardwareBreakpointHandle_t SetHardwareBreakpoint( EHardwareBreakpointType eType, EHardwareBreakpointSize eSize, const void *pvLocation );
  544. PLATFORM_INTERFACE bool ClearHardwareBreakpoint( HardwareBreakpointHandle_t handle );
  545. class CHardwareBreakPointScopeGuard
  546. {
  547. public:
  548. CHardwareBreakPointScopeGuard( const void *pvLocation, size_t nLocationSize, EHardwareBreakpointType eType = BREAKPOINT_WRITE )
  549. {
  550. EHardwareBreakpointSize eSize = BREAKPOINT_SIZE_4;
  551. switch ( nLocationSize )
  552. {
  553. case 1:
  554. eSize = BREAKPOINT_SIZE_1;
  555. break;
  556. case 2:
  557. eSize = BREAKPOINT_SIZE_2;
  558. break;
  559. case 4:
  560. eSize = BREAKPOINT_SIZE_4;
  561. break;
  562. case 8:
  563. eSize = BREAKPOINT_SIZE_8;
  564. break;
  565. default:
  566. Warning( _T( "SetHardwareBreakpoint can only work with 1, 2, 4 or 8 byte data fields." ) );
  567. break;
  568. }
  569. m_hBreakPoint = SetHardwareBreakpoint( eType, eSize, pvLocation );
  570. m_bActive = m_hBreakPoint != (HardwareBreakpointHandle_t)0;
  571. }
  572. ~CHardwareBreakPointScopeGuard()
  573. {
  574. Release();
  575. }
  576. void Release()
  577. {
  578. if ( !m_bActive )
  579. return;
  580. ClearHardwareBreakpoint( m_hBreakPoint );
  581. }
  582. private:
  583. bool m_bActive;
  584. HardwareBreakpointHandle_t m_hBreakPoint;
  585. };
  586. #endif // IS_WINDOWS_PC
  587. //-----------------------------------------------------------------------------
  588. #endif /* DBG_H */