Counter Strike : Global Offensive Source Code
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.

701 lines
18 KiB

  1. //========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "tier0/platform.h"
  7. #include "tier0/valve_off.h"
  8. #ifdef _X360
  9. #include "xbox/xbox_console.h"
  10. #include "xbox/xbox_vxconsole.h"
  11. #elif defined( _PS3 )
  12. #include "ps3/ps3_console.h"
  13. #elif defined( _WIN32 )
  14. #include <windows.h>
  15. #elif POSIX
  16. char *GetCommandLine();
  17. #endif
  18. #include "resource.h"
  19. #include "tier0/valve_on.h"
  20. #include "tier0/threadtools.h"
  21. #include "tier0/icommandline.h"
  22. #if defined( LINUX ) || defined( OSX )
  23. #include <dlfcn.h>
  24. #endif
  25. #if defined( LINUX ) || defined( USE_SDL )
  26. // We lazily load the SDL shared object, and only reference functions if it's
  27. // available, so this can be included on the dedicated server too.
  28. #include "SDL.h"
  29. typedef int ( SDLCALL FUNC_SDL_ShowMessageBox )( const SDL_MessageBoxData *messageboxdata, int *buttonid );
  30. typedef SDL_Window* ( SDLCALL FUNC_SDL_GetKeyboardFocus )();
  31. #endif
  32. // NOTE: This has to be the last file included!
  33. #include "tier0/memdbgon.h"
  34. class CDialogInitInfo
  35. {
  36. public:
  37. const tchar *m_pFilename;
  38. int m_iLine;
  39. const tchar *m_pExpression;
  40. };
  41. class CAssertDisable
  42. {
  43. public:
  44. tchar m_Filename[512];
  45. // If these are not -1, then this CAssertDisable only disables asserts on lines between
  46. // these values (inclusive).
  47. int m_LineMin;
  48. int m_LineMax;
  49. // Decremented each time we hit this assert and ignore it, until it's 0.
  50. // Then the CAssertDisable is removed.
  51. // If this is -1, then we always ignore this assert.
  52. int m_nIgnoreTimes;
  53. CAssertDisable *m_pNext;
  54. };
  55. #ifdef _WIN32
  56. static HINSTANCE g_hTier0Instance = 0;
  57. #endif
  58. static bool g_bAssertsEnabled = true;
  59. static bool g_bAssertDialogEnabled = true;
  60. static CAssertDisable *g_pAssertDisables = NULL;
  61. #if ( defined( _WIN32 ) && !defined( _X360 ) )
  62. static int g_iLastLineRange = 5;
  63. static int g_nLastIgnoreNumTimes = 1;
  64. #endif
  65. #if defined( _X360 ) || defined( _PS3 )
  66. static int g_VXConsoleAssertReturnValue = -1;
  67. #endif
  68. // Set to true if they want to break in the debugger.
  69. static bool g_bBreak = false;
  70. static CDialogInitInfo g_Info;
  71. static bool g_bDisableAsserts = false;
  72. // -------------------------------------------------------------------------------- //
  73. // Internal functions.
  74. // -------------------------------------------------------------------------------- //
  75. #if defined(_WIN32) && !defined(STATIC_TIER0)
  76. BOOL WINAPI DllMain(
  77. HINSTANCE hinstDLL, // handle to the DLL module
  78. DWORD fdwReason, // reason for calling function
  79. LPVOID lpvReserved // reserved
  80. )
  81. {
  82. g_hTier0Instance = hinstDLL;
  83. return true;
  84. }
  85. #endif
  86. static bool IsDebugBreakEnabled()
  87. {
  88. static bool bResult = ( _tcsstr( Plat_GetCommandLine(), _T("-debugbreak") ) != NULL );
  89. return bResult;
  90. }
  91. static bool AssertStack()
  92. {
  93. static bool bResult = ( _tcsstr( Plat_GetCommandLine(), _T("-assertstack") ) != NULL );
  94. return bResult;
  95. }
  96. static bool AreAssertsDisabled()
  97. {
  98. static bool bResult = ( _tcsstr( Plat_GetCommandLine(), _T("-noassert") ) != NULL );
  99. return bResult || g_bDisableAsserts;
  100. }
  101. static bool AllAssertOnce()
  102. {
  103. static bool bResult = ( _tcsstr( Plat_GetCommandLine(), _T("-assertonce") ) != NULL );
  104. return bResult;
  105. }
  106. static bool AreAssertsEnabledInFileLine( const tchar *pFilename, int iLine )
  107. {
  108. CAssertDisable **pPrev = &g_pAssertDisables;
  109. CAssertDisable *pNext;
  110. for ( CAssertDisable *pCur=g_pAssertDisables; pCur; pCur=pNext )
  111. {
  112. pNext = pCur->m_pNext;
  113. if ( _tcsicmp( pFilename, pCur->m_Filename ) == 0 )
  114. {
  115. // Are asserts disabled in the whole file?
  116. bool bAssertsEnabled = true;
  117. if ( pCur->m_LineMin == -1 && pCur->m_LineMax == -1 )
  118. bAssertsEnabled = false;
  119. // Are asserts disabled on the specified line?
  120. if ( iLine >= pCur->m_LineMin && iLine <= pCur->m_LineMax )
  121. bAssertsEnabled = false;
  122. if ( !bAssertsEnabled )
  123. {
  124. // If this assert is only disabled for the next N times, then countdown..
  125. if ( pCur->m_nIgnoreTimes > 0 )
  126. {
  127. --pCur->m_nIgnoreTimes;
  128. if ( pCur->m_nIgnoreTimes == 0 )
  129. {
  130. // Remove this one from the list.
  131. *pPrev = pNext;
  132. delete pCur;
  133. continue;
  134. }
  135. }
  136. return false;
  137. }
  138. }
  139. pPrev = &pCur->m_pNext;
  140. }
  141. return true;
  142. }
  143. CAssertDisable* CreateNewAssertDisable( const tchar *pFilename )
  144. {
  145. CAssertDisable *pDisable = new CAssertDisable;
  146. pDisable->m_pNext = g_pAssertDisables;
  147. g_pAssertDisables = pDisable;
  148. pDisable->m_LineMin = pDisable->m_LineMax = -1;
  149. pDisable->m_nIgnoreTimes = -1;
  150. _tcsncpy( pDisable->m_Filename, g_Info.m_pFilename, sizeof( pDisable->m_Filename ) - 1 );
  151. pDisable->m_Filename[ sizeof( pDisable->m_Filename ) - 1 ] = 0;
  152. return pDisable;
  153. }
  154. void IgnoreAssertsInCurrentFile()
  155. {
  156. CreateNewAssertDisable( g_Info.m_pFilename );
  157. }
  158. CAssertDisable* IgnoreAssertsNearby( int nRange )
  159. {
  160. CAssertDisable *pDisable = CreateNewAssertDisable( g_Info.m_pFilename );
  161. pDisable->m_LineMin = g_Info.m_iLine - nRange;
  162. pDisable->m_LineMax = g_Info.m_iLine - nRange;
  163. return pDisable;
  164. }
  165. #if ( defined( _WIN32 ) && !defined( _X360 ) )
  166. INT_PTR CALLBACK AssertDialogProc(
  167. HWND hDlg, // handle to dialog box
  168. UINT uMsg, // message
  169. WPARAM wParam, // first message parameter
  170. LPARAM lParam // second message parameter
  171. )
  172. {
  173. switch( uMsg )
  174. {
  175. case WM_INITDIALOG:
  176. {
  177. #ifdef TCHAR_IS_WCHAR
  178. SetDlgItemTextW( hDlg, IDC_ASSERT_MSG_CTRL, g_Info.m_pExpression );
  179. SetDlgItemTextW( hDlg, IDC_FILENAME_CONTROL, g_Info.m_pFilename );
  180. #else
  181. SetDlgItemText( hDlg, IDC_ASSERT_MSG_CTRL, g_Info.m_pExpression );
  182. SetDlgItemText( hDlg, IDC_FILENAME_CONTROL, g_Info.m_pFilename );
  183. #endif
  184. SetDlgItemInt( hDlg, IDC_LINE_CONTROL, g_Info.m_iLine, false );
  185. SetDlgItemInt( hDlg, IDC_IGNORE_NUMLINES, g_iLastLineRange, false );
  186. SetDlgItemInt( hDlg, IDC_IGNORE_NUMTIMES, g_nLastIgnoreNumTimes, false );
  187. // Center the dialog.
  188. RECT rcDlg, rcDesktop;
  189. GetWindowRect( hDlg, &rcDlg );
  190. GetWindowRect( GetDesktopWindow(), &rcDesktop );
  191. SetWindowPos(
  192. hDlg,
  193. HWND_TOP,
  194. ((rcDesktop.right-rcDesktop.left) - (rcDlg.right-rcDlg.left)) / 2,
  195. ((rcDesktop.bottom-rcDesktop.top) - (rcDlg.bottom-rcDlg.top)) / 2,
  196. 0,
  197. 0,
  198. SWP_NOSIZE );
  199. }
  200. return true;
  201. case WM_COMMAND:
  202. {
  203. switch( LOWORD( wParam ) )
  204. {
  205. case IDC_IGNORE_FILE:
  206. {
  207. IgnoreAssertsInCurrentFile();
  208. EndDialog( hDlg, 0 );
  209. return true;
  210. }
  211. // Ignore this assert N times.
  212. case IDC_IGNORE_THIS:
  213. {
  214. BOOL bTranslated = false;
  215. UINT value = GetDlgItemInt( hDlg, IDC_IGNORE_NUMTIMES, &bTranslated, false );
  216. if ( bTranslated && value > 1 )
  217. {
  218. CAssertDisable *pDisable = IgnoreAssertsNearby( 0 );
  219. pDisable->m_nIgnoreTimes = value - 1;
  220. g_nLastIgnoreNumTimes = value;
  221. }
  222. EndDialog( hDlg, 0 );
  223. return true;
  224. }
  225. // Always ignore this assert.
  226. case IDC_IGNORE_ALWAYS:
  227. {
  228. IgnoreAssertsNearby( 0 );
  229. EndDialog( hDlg, 0 );
  230. return true;
  231. }
  232. case IDC_IGNORE_NEARBY:
  233. {
  234. BOOL bTranslated = false;
  235. UINT value = GetDlgItemInt( hDlg, IDC_IGNORE_NUMLINES, &bTranslated, false );
  236. if ( !bTranslated || value < 1 )
  237. return true;
  238. IgnoreAssertsNearby( value );
  239. EndDialog( hDlg, 0 );
  240. return true;
  241. }
  242. case IDC_IGNORE_ALL:
  243. {
  244. g_bAssertsEnabled = false;
  245. EndDialog( hDlg, 0 );
  246. return true;
  247. }
  248. case IDC_BREAK:
  249. {
  250. g_bBreak = true;
  251. EndDialog( hDlg, 0 );
  252. return true;
  253. }
  254. }
  255. case WM_KEYDOWN:
  256. {
  257. // Escape?
  258. if ( wParam == 2 )
  259. {
  260. // Ignore this assert.
  261. EndDialog( hDlg, 0 );
  262. return true;
  263. }
  264. }
  265. }
  266. return true;
  267. }
  268. return FALSE;
  269. }
  270. static HWND g_hBestParentWindow;
  271. static BOOL CALLBACK ParentWindowEnumProc(
  272. HWND hWnd, // handle to parent window
  273. LPARAM lParam // application-defined value
  274. )
  275. {
  276. if ( IsWindowVisible( hWnd ) )
  277. {
  278. DWORD procID;
  279. GetWindowThreadProcessId( hWnd, &procID );
  280. if ( procID == (DWORD)lParam )
  281. {
  282. g_hBestParentWindow = hWnd;
  283. return FALSE; // don't iterate any more.
  284. }
  285. }
  286. return TRUE;
  287. }
  288. static HWND FindLikelyParentWindow()
  289. {
  290. // Enumerate top-level windows and take the first visible one with our processID.
  291. g_hBestParentWindow = NULL;
  292. EnumWindows( ParentWindowEnumProc, GetCurrentProcessId() );
  293. return g_hBestParentWindow;
  294. }
  295. #endif
  296. // -------------------------------------------------------------------------------- //
  297. // Interface functions.
  298. // -------------------------------------------------------------------------------- //
  299. // provides access to the global that turns asserts on and off
  300. PLATFORM_INTERFACE bool AreAllAssertsDisabled()
  301. {
  302. return !g_bAssertsEnabled;
  303. }
  304. PLATFORM_INTERFACE void SetAllAssertsDisabled( bool bAssertsDisabled )
  305. {
  306. g_bAssertsEnabled = !bAssertsDisabled;
  307. }
  308. // provides access to the global that turns asserts on and off
  309. PLATFORM_INTERFACE bool IsAssertDialogDisabled()
  310. {
  311. return !g_bAssertDialogEnabled;
  312. }
  313. PLATFORM_INTERFACE void SetAssertDialogDisabled( bool bAssertDialogDisabled )
  314. {
  315. g_bAssertDialogEnabled = !bAssertDialogDisabled;
  316. }
  317. #if defined( LINUX ) || ( defined( USE_SDL ) && defined( OSX ) )
  318. SDL_Window *g_SDLWindow = NULL;
  319. PLATFORM_INTERFACE void SetAssertDialogParent( struct SDL_Window *window )
  320. {
  321. g_SDLWindow = window;
  322. }
  323. PLATFORM_INTERFACE struct SDL_Window * GetAssertDialogParent()
  324. {
  325. return g_SDLWindow;
  326. }
  327. #endif
  328. PLATFORM_INTERFACE bool ShouldUseNewAssertDialog()
  329. {
  330. static bool bMPIWorker = ( _tcsstr( Plat_GetCommandLine(), _T("-mpi_worker") ) != NULL );
  331. if ( bMPIWorker )
  332. {
  333. return false;
  334. }
  335. #ifdef DBGFLAG_ASSERTDLG
  336. return true; // always show an assert dialog
  337. #else
  338. return Plat_IsInDebugSession(); // only show an assert dialog if the process is being debugged
  339. #endif // DBGFLAG_ASSERTDLG
  340. }
  341. PLATFORM_INTERFACE bool DoNewAssertDialog( const tchar *pFilename, int line, const tchar *pExpression )
  342. {
  343. LOCAL_THREAD_LOCK();
  344. if ( AreAssertsDisabled() )
  345. return false;
  346. // If they have the old mode enabled (always break immediately), then just break right into
  347. // the debugger like we used to do.
  348. if ( IsDebugBreakEnabled() )
  349. return true;
  350. // Have ALL Asserts been disabled?
  351. if ( !g_bAssertsEnabled )
  352. return false;
  353. // Has this specific Assert been disabled?
  354. if ( !AreAssertsEnabledInFileLine( pFilename, line ) )
  355. return false;
  356. // Now create the dialog.
  357. g_Info.m_pFilename = pFilename;
  358. g_Info.m_iLine = line;
  359. g_Info.m_pExpression = pExpression;
  360. if ( AssertStack() )
  361. {
  362. IgnoreAssertsNearby( 0 );
  363. // @TODO: add-back callstack spew support
  364. Warning( "%s (%d) : Assertion callstack...(NOT IMPLEMENTED IN NEW LOGGING SYSTEM.)\n", pFilename, line );
  365. // Warning_SpewCallStack( 10, "%s (%d) : Assertion callstack...\n", pFilename, line );
  366. return false;
  367. }
  368. if( AllAssertOnce() )
  369. {
  370. IgnoreAssertsNearby( 0 );
  371. }
  372. g_bBreak = false;
  373. #if defined( _X360 )
  374. char cmdString[XBX_MAX_RCMDLENGTH];
  375. // Before calling VXConsole, init the global variable that receives the result
  376. g_VXConsoleAssertReturnValue = -1;
  377. // Message VXConsole to pop up a PC-side Assert dialog
  378. _snprintf( cmdString, sizeof(cmdString), "Assert() 0x%.8x File: %s\tLine: %d\t%s",
  379. &g_VXConsoleAssertReturnValue, pFilename, line, pExpression );
  380. XBX_SendRemoteCommand( cmdString, false );
  381. // We sent a synchronous message, so g_xbx_dbgVXConsoleAssertReturnValue should have been overwritten by now
  382. if ( g_VXConsoleAssertReturnValue == -1 )
  383. {
  384. // VXConsole isn't connected/running - default to the old behaviour (break)
  385. g_bBreak = true;
  386. }
  387. else
  388. {
  389. // Respond to what the user selected
  390. switch( g_VXConsoleAssertReturnValue )
  391. {
  392. case ASSERT_ACTION_IGNORE_FILE:
  393. IgnoreAssertsInCurrentFile();
  394. break;
  395. case ASSERT_ACTION_IGNORE_THIS:
  396. // Ignore this Assert once
  397. break;
  398. case ASSERT_ACTION_BREAK:
  399. // Break on this Assert
  400. g_bBreak = true;
  401. break;
  402. case ASSERT_ACTION_IGNORE_ALL:
  403. // Ignore all Asserts from now on
  404. g_bAssertsEnabled = false;
  405. break;
  406. case ASSERT_ACTION_IGNORE_ALWAYS:
  407. // Ignore this Assert from now on
  408. IgnoreAssertsNearby( 0 );
  409. break;
  410. case ASSERT_ACTION_OTHER:
  411. default:
  412. // Error... just break
  413. XBX_Error( "DoNewAssertDialog: invalid Assert response returned from VXConsole - breaking to debugger" );
  414. g_bBreak = true;
  415. break;
  416. }
  417. }
  418. #elif defined( _PS3 )
  419. // There are a few ways to handle this sort of assert behavior with the PS3 / Target Manager API.
  420. // One is to use a DebuggerBreak per usual, and then SNProcessContinue in the TMAPI to make
  421. // the game resume after a breakpoint. (You can use snIsDebuggerPresent() to determine if
  422. // the debugger is attached, although really it doesn't matter here.)
  423. // This doesn't work because the DebuggerBreak() is actually an interrupt op, and so Continue()
  424. // won't continue past it -- you need to do that from inside the ProDG debugger itself.
  425. // Another is to wait on a mutex here and then trip it from the TMAPI, but there isn't
  426. // a clean way to trip sync primitives from TMAPI.
  427. // Another way is to suspend the thread here and have TMAPI resume it.
  428. // The simplest way is to spin-wait on a shared variable that you expect the
  429. // TMAPI to poke into memory. I'm trying that.
  430. char cmdString[XBX_MAX_RCMDLENGTH];
  431. // Before calling VXConsole, init the global variable that receives the result
  432. g_VXConsoleAssertReturnValue = -1;
  433. // Message VXConsole to pop up a PC-side Assert dialog
  434. _snprintf( cmdString, sizeof(cmdString), "Assert() 0x%.8x File: %s\tLine: %d\t%s",
  435. &g_VXConsoleAssertReturnValue, pFilename, line, pExpression );
  436. XBX_SendRemoteCommand( cmdString, false );
  437. if ( g_pValvePS3Console->IsConsoleConnected() )
  438. {
  439. // DebuggerBreak();
  440. while ( g_VXConsoleAssertReturnValue == -1 )
  441. {
  442. ThreadSleep( 1000 );
  443. }
  444. // assume that the VX has poked the return value
  445. // Respond to what the user selected
  446. switch( g_VXConsoleAssertReturnValue )
  447. {
  448. case ASSERT_ACTION_IGNORE_FILE:
  449. IgnoreAssertsInCurrentFile();
  450. break;
  451. case ASSERT_ACTION_IGNORE_THIS:
  452. // Ignore this Assert once
  453. break;
  454. case ASSERT_ACTION_BREAK:
  455. // Break on this Assert
  456. g_bBreak = true;
  457. break;
  458. case ASSERT_ACTION_IGNORE_ALL:
  459. // Ignore all Asserts from now on
  460. g_bAssertsEnabled = false;
  461. break;
  462. case ASSERT_ACTION_IGNORE_ALWAYS:
  463. // Ignore this Assert from now on
  464. IgnoreAssertsNearby( 0 );
  465. break;
  466. case ASSERT_ACTION_OTHER:
  467. default:
  468. // nothing.
  469. break;
  470. }
  471. }
  472. else if ( g_pValvePS3Console->IsDebuggerPresent() )
  473. {
  474. g_bBreak = true;
  475. }
  476. else
  477. {
  478. // ignore the assert
  479. }
  480. #elif defined( _WIN32 )
  481. if ( !g_hTier0Instance || !ThreadInMainThread() )
  482. {
  483. int result = MessageBox( NULL, pExpression, "Assertion Failed", MB_SYSTEMMODAL | MB_CANCELTRYCONTINUE );
  484. if ( result == IDCANCEL )
  485. {
  486. IgnoreAssertsNearby( 0 );
  487. }
  488. else if ( result == IDCONTINUE )
  489. {
  490. g_bBreak = true;
  491. }
  492. }
  493. else
  494. {
  495. HWND hParentWindow = FindLikelyParentWindow();
  496. DialogBox( g_hTier0Instance, MAKEINTRESOURCE( IDD_ASSERT_DIALOG ), hParentWindow, AssertDialogProc );
  497. }
  498. #elif defined( LINUX ) || defined( USE_SDL )
  499. #define COLOR_YELLOW "\033[1;33m"
  500. #define COLOR_GREEN "\033[1;32m"
  501. #define COLOR_RED "\033[1;31m"
  502. #define COLOR_END "\033[0m"
  503. fprintf(stderr, COLOR_YELLOW "ASSERT: " COLOR_RED "%s" COLOR_GREEN ":%i:" COLOR_RED "%s" COLOR_END "\n", pFilename, line, pExpression);
  504. static FUNC_SDL_ShowMessageBox *pfnSDLShowMessageBox = NULL;
  505. static FUNC_SDL_GetKeyboardFocus *pfnSDLGetKeyboardFocus = NULL;
  506. if( getenv( "GAME_ASSERT_DIALOG" ) && !pfnSDLShowMessageBox )
  507. {
  508. #if defined( WIN32 )
  509. HMODULE ret = LoadLibrary( "SDL2.lib" );
  510. pfnSDLShowMessageBox = ( FUNC_SDL_ShowMessageBox * )GetProcAddress( ret, "SDL_ShowMessageBox" );
  511. pfnSDLGetKeyboardFocus = ( FUNC_SDL_GetKeyboardFocus * )GetProcAddress( ret, "SDL_GetKeyboardFocus" );
  512. #else
  513. #if defined( OSX )
  514. void *ret = dlopen( "libSDL2-2.0.0.dylib", RTLD_LAZY );
  515. #else
  516. void *ret = dlopen( "libSDL2-2.0.so.0", RTLD_LAZY );
  517. #endif
  518. pfnSDLShowMessageBox = ( FUNC_SDL_ShowMessageBox * )dlsym( ret, "SDL_ShowMessageBox" );
  519. pfnSDLGetKeyboardFocus = ( FUNC_SDL_GetKeyboardFocus * )dlsym( ret, "SDL_GetKeyboardFocus" );
  520. #endif
  521. }
  522. if( pfnSDLShowMessageBox )
  523. {
  524. int buttonid;
  525. char text[ 4096 ];
  526. SDL_MessageBoxData messageboxdata = { 0 };
  527. const char *DefaultAction = Plat_IsInDebugSession() ? "Break" : "Corefile";
  528. SDL_MessageBoxButtonData buttondata[] =
  529. {
  530. { SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, IDC_BREAK, DefaultAction },
  531. { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, IDC_IGNORE_THIS, "Ignore" },
  532. { 0, IDC_IGNORE_FILE, "Ignore This File" },
  533. { 0, IDC_IGNORE_ALWAYS, "Always Ignore" },
  534. { 0, IDC_IGNORE_ALL, "Ignore All Asserts" },
  535. };
  536. _snprintf( text, sizeof( text ), "File: %s\nLine: %i\nExpr: %s\n", pFilename, line, pExpression );
  537. text[ sizeof( text ) - 1 ] = 0;
  538. messageboxdata.window = g_SDLWindow;
  539. messageboxdata.title = "Assertion Failed";
  540. messageboxdata.message = text;
  541. messageboxdata.numbuttons = ARRAYSIZE( buttondata );
  542. messageboxdata.buttons = buttondata;
  543. int Ret = ( *pfnSDLShowMessageBox )( &messageboxdata, &buttonid );
  544. if( Ret == -1 )
  545. {
  546. buttonid = IDC_BREAK;
  547. }
  548. switch( buttonid )
  549. {
  550. default:
  551. case IDC_BREAK:
  552. // Break on this Assert
  553. g_bBreak = true;
  554. break;
  555. case IDC_IGNORE_THIS:
  556. // Ignore this Assert once
  557. break;
  558. case IDC_IGNORE_FILE:
  559. IgnoreAssertsInCurrentFile();
  560. break;
  561. case IDC_IGNORE_ALWAYS:
  562. // Ignore this Assert from now on
  563. IgnoreAssertsNearby( 0 );
  564. break;
  565. case IDC_IGNORE_ALL:
  566. // Ignore all Asserts from now on
  567. g_bAssertsEnabled = false;
  568. break;
  569. }
  570. }
  571. else if ( getenv( "RAISE_ON_ASSERT" ) )
  572. {
  573. g_bBreak = true;
  574. }
  575. #elif defined( POSIX )
  576. fprintf(stderr, "%s %i %s\n", pFilename, line, pExpression);
  577. if ( getenv( "RAISE_ON_ASSERT" ) )
  578. {
  579. g_bBreak = true;
  580. }
  581. #endif
  582. return g_bBreak;
  583. }