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 /**
26 * @file
27 * @brief Debugging macros for fatal error/assert messages.
28 */
29
30 #include "../../../../shared/cxx.h"
31 #include "stream/textstream.h"
32 #include "generic/static.h"
33
34 #if defined __i386__ && GCC_ATLEAST(2, 0)
35 #define DEBUGGER_BREAKPOINT() __asm__ __volatile__ ("int $03")
36 #else
37 #include <signal.h>
38 #define DEBUGGER_BREAKPOINT() raise(SIGTRAP);
39 #endif
40
41 #define STR(x) #x
42 #define STR2(x) STR(x)
43 #define FILE_LINE __FILE__ ":" STR2(__LINE__)
44
45 class DebugMessageHandler {
46 public:
~DebugMessageHandler()47 virtual ~DebugMessageHandler(){}
48 virtual TextOutputStream& getOutputStream() = 0;
49 virtual bool handleMessage() = 0;
50 };
51
52 class NullDebugMessageHandler : public NullOutputStream, public DebugMessageHandler {
53 public:
getOutputStream()54 virtual TextOutputStream& getOutputStream() {
55 return *this;
56 }
handleMessage()57 virtual bool handleMessage() {
58 return false;
59 }
60 };
61
62 class DefaultDebugMessageHandler : public DebugMessageHandler {
63 public:
getOutputStream()64 virtual TextOutputStream& getOutputStream() {
65 return globalErrorStream();
66 }
handleMessage()67 virtual bool handleMessage() {
68 #if defined(DEBUG)
69 return false; // send debug-break
70 #else
71 return true;
72 #endif
73 }
74 };
75
76 class DebugMessageHandlerRef : public DefaultDebugMessageHandler {
77 DebugMessageHandler* m_handler;
78 public:
DebugMessageHandlerRef()79 DebugMessageHandlerRef()
80 : m_handler(this) {
81 }
setHandler(DebugMessageHandler & handler)82 void setHandler(DebugMessageHandler& handler) {
83 m_handler = &handler;
84 }
getHandler()85 DebugMessageHandler& getHandler() {
86 return *m_handler;
87 }
88 };
89
90 typedef Static<DebugMessageHandlerRef> GlobalDebugMessageHandler;
91
globalDebugMessageHandler()92 inline DebugMessageHandler& globalDebugMessageHandler() {
93 return GlobalDebugMessageHandler::instance().getHandler();
94 }
95
96 #ifdef DEBUG
97
98 /// \brief Sends a \p message to the current debug-message-handler text-output-stream if \p condition evaluates to false.
99 #define ASSERT_MESSAGE(condition, message) do{\
100 if(!(condition))\
101 {\
102 globalDebugMessageHandler().getOutputStream() << FILE_LINE "\nassertion failure: " << message << "\n";\
103 if(!globalDebugMessageHandler().handleMessage()) { DEBUGGER_BREAKPOINT(); }\
104 }} while(0)
105
106 /// \brief Sends a \p message to the current debug-message-handler text-output-stream.
107 #define ERROR_MESSAGE(message) do{\
108 globalDebugMessageHandler().getOutputStream() << FILE_LINE "\nruntime error: " << message << "\n";\
109 if(!globalDebugMessageHandler().handleMessage()) { DEBUGGER_BREAKPOINT(); }} while(0)
110
111 #define ASSERT_NOTNULL(ptr) ASSERT_MESSAGE(ptr != 0, "pointer \"" #ptr "\" is null")
112
113 #else
114
115 #define ASSERT_MESSAGE(condition, message)
116 #define ERROR_MESSAGE(message)
117 #define ASSERT_NOTNULL(ptr)
118
119 #endif
120
121 #endif
122