]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/debugging/debugging.h
Merge branch 'NateEag-master-patch-12920' into 'master'
[xonotic/netradiant.git] / libs / debugging / debugging.h
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #if !defined( INCLUDED_DEBUGGING_DEBUGGING_H )
23 #define INCLUDED_DEBUGGING_DEBUGGING_H
24
25 /// \file
26 /// \brief Debugging macros for fatal error/assert messages.
27
28 #include "globaldefs.h"
29 #include "stream/textstream.h"
30 #include "warnings.h"
31 #include "generic/static.h"
32
33 #if GDEF_COMPILER_MSVC && ( defined( _M_IX86 ) || defined( _M_AMD64 ) )
34 #define DEBUGGER_BREAKPOINT() __asm { int 3 }
35 #elif GDEF_COMPILER_GNU && __GNUC__ >= 2 && ( defined ( __i386__ ) || defined ( __x86_64__ ) )
36 #define DEBUGGER_BREAKPOINT() __asm__ __volatile__ ( "int $03" )
37 #else
38 #include <signal.h>
39
40 #define DEBUGGER_BREAKPOINT() raise( SIGTRAP );
41 #endif
42
43 #define STR( x )  #x
44 #define STR2( x ) STR( x )
45 #define FILE_LINE __FILE__ ":" STR2( __LINE__ )
46
47 #define DEBUG_ASSERTS
48
49 class DebugMessageHandler
50 {
51 public:
52 virtual TextOutputStream& getOutputStream() = 0;
53 virtual bool handleMessage() = 0;
54 };
55
56 class NullDebugMessageHandler : public NullOutputStream, public DebugMessageHandler
57 {
58 public:
59 virtual TextOutputStream& getOutputStream(){
60         return *this;
61 }
62 virtual bool handleMessage(){
63         return false;
64 }
65 };
66
67 class DefaultDebugMessageHandler : public DebugMessageHandler
68 {
69 public:
70 virtual TextOutputStream& getOutputStream(){
71         return globalErrorStream();
72 }
73 virtual bool handleMessage(){
74 #if GDEF_DEBUG
75         return false; // send debug-break
76 #else
77         return true;
78 #endif
79 }
80 };
81
82 class DebugMessageHandlerRef : public DefaultDebugMessageHandler
83 {
84 DebugMessageHandler* m_handler;
85 public:
86 DebugMessageHandlerRef()
87         : m_handler( this ){
88 }
89 void setHandler( DebugMessageHandler& handler ){
90         m_handler = &handler;
91 }
92 DebugMessageHandler& getHandler(){
93         return *m_handler;
94 }
95 };
96
97 typedef Static<DebugMessageHandlerRef> GlobalDebugMessageHandler;
98
99 inline DebugMessageHandler& globalDebugMessageHandler(){
100         return GlobalDebugMessageHandler::instance().getHandler();
101 }
102
103 #if defined( DEBUG_ASSERTS )
104
105 /// \brief Sends a \p message to the current debug-message-handler text-output-stream if \p condition evaluates to false.
106 #define ASSERT_MESSAGE( condition, message ) do { \
107                 if ( !( condition ) ) \
108                 { \
109                         globalDebugMessageHandler().getOutputStream() << FILE_LINE "\nassertion failure: " << message << "\n"; \
110                         if ( !globalDebugMessageHandler().handleMessage() ) { DEBUGGER_BREAKPOINT(); } \
111                 }} while ( 0 )
112
113 /// \brief Sends a \p message to the current debug-message-handler text-output-stream.
114 #define ERROR_MESSAGE( message ) do { \
115                 globalDebugMessageHandler().getOutputStream() << FILE_LINE "\nruntime error: " << message << "\n"; \
116                 if ( !globalDebugMessageHandler().handleMessage() ) { DEBUGGER_BREAKPOINT(); }} while ( 0 )
117
118 #define ASSERT_NOTNULL( ptr ) ASSERT_MESSAGE( ptr != 0, "pointer \"" #ptr "\" is null" )
119 #define ASSERT_TRUE( flag ) ASSERT_MESSAGE( !!(flag) == true, "condition \"" #flag "\" is false" )
120
121 #else
122
123 #define ASSERT_MESSAGE( condition, message )
124 #define ERROR_MESSAGE( message )
125 #define ASSERT_NOTNULL( ptr )
126
127 #endif
128
129 #endif