]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/debugging/debugging.h
ok
[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 "stream/textstream.h"
29 #include "warnings.h"
30 #include "generic/static.h"
31
32 #if defined(_MSC_VER) && defined(_M_IX86)
33 #define DEBUGGER_BREAKPOINT() __asm { int 3 }
34 #elif defined (__i386__) && defined (__GNUC__) && __GNUC__ >= 2
35 #define DEBUGGER_BREAKPOINT() __asm__ __volatile__ ("int $03")
36 #else
37 #include <signal.h>
38
39 #define DEBUGGER_BREAKPOINT() raise(SIGTRAP);
40 #endif
41
42
43 #define FILE_LINE __FILE__ ":" << __LINE__
44
45 #if defined(_DEBUG) || 1
46 #define DEBUG_ASSERTS
47 #endif
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   {
61     return *this;
62   }
63   virtual bool handleMessage()
64   {
65     return false;
66   }
67 };
68
69 class DefaultDebugMessageHandler : public DebugMessageHandler
70 {
71 public:
72   virtual TextOutputStream& getOutputStream()
73   {
74     return globalErrorStream();
75   }
76   virtual bool handleMessage()
77   {
78 #if defined(_DEBUG)
79     return false; // send debug-break
80 #else
81     return true;
82 #endif
83   }
84 };
85
86 class DebugMessageHandlerRef : public DefaultDebugMessageHandler
87 {
88   DebugMessageHandler* m_handler;
89 public:
90   DebugMessageHandlerRef()
91     : m_handler(this)
92   {
93   }
94   void setHandler(DebugMessageHandler& handler)
95   {
96     m_handler = &handler;
97   }
98   DebugMessageHandler& getHandler()
99   {
100     return *m_handler;
101   }
102 };
103
104 typedef Static<DebugMessageHandlerRef> GlobalDebugMessageHandler;
105
106 inline DebugMessageHandler& globalDebugMessageHandler()
107 {
108   return GlobalDebugMessageHandler::instance().getHandler();
109 }
110
111 #if defined(DEBUG_ASSERTS)
112
113 /// \brief Sends a \p message to the current debug-message-handler text-output-stream if \p condition evaluates to false.
114 #define ASSERT_MESSAGE(condition, message)\
115 if(!(condition))\
116 {\
117   globalDebugMessageHandler().getOutputStream() << FILE_LINE << "\nassertion failure: " << message << "\n";\
118   if(!globalDebugMessageHandler().handleMessage()) { DEBUGGER_BREAKPOINT(); }\
119 } else\
120
121 /// \brief Sends a \p message to the current debug-message-handler text-output-stream.
122 #define ERROR_MESSAGE(message)\
123 globalDebugMessageHandler().getOutputStream() << FILE_LINE << "\nruntime error: " << message << "\n";\
124 if(!globalDebugMessageHandler().handleMessage()) { DEBUGGER_BREAKPOINT(); } else\
125
126 #define ASSERT_NOTNULL(ptr) ASSERT_MESSAGE(ptr != 0, "pointer \"" #ptr "\" is null")
127
128 #else
129
130 #define ASSERT_MESSAGE(condition, message)
131 #define ASSERT_NOTNULL(ptr)
132
133 #endif
134
135 #endif