/* Copyright (C) 2001-2006, William Joseph. All Rights Reserved. This file is part of GtkRadiant. GtkRadiant is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GtkRadiant is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GtkRadiant; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined(INCLUDED_DEBUGGING_DEBUGGING_H) #define INCLUDED_DEBUGGING_DEBUGGING_H /// \file /// \brief Debugging macros for fatal error/assert messages. #include "stream/textstream.h" #include "warnings.h" #include "generic/static.h" #if defined(_MSC_VER) && defined(_M_IX86) #define DEBUGGER_BREAKPOINT() __asm { int 3 } #elif defined (__i386__) && defined (__GNUC__) && __GNUC__ >= 2 #define DEBUGGER_BREAKPOINT() __asm__ __volatile__ ("int $03") #else #include #define DEBUGGER_BREAKPOINT() raise(SIGTRAP); #endif #define STR(x) #x #define STR2(x) STR(x) #define FILE_LINE __FILE__ ":" STR2(__LINE__) #if defined(_DEBUG) || 1 #define DEBUG_ASSERTS #endif class DebugMessageHandler { public: virtual TextOutputStream& getOutputStream() = 0; virtual bool handleMessage() = 0; }; class NullDebugMessageHandler : public NullOutputStream, public DebugMessageHandler { public: virtual TextOutputStream& getOutputStream() { return *this; } virtual bool handleMessage() { return false; } }; class DefaultDebugMessageHandler : public DebugMessageHandler { public: virtual TextOutputStream& getOutputStream() { return globalErrorStream(); } virtual bool handleMessage() { #if defined(_DEBUG) return false; // send debug-break #else return true; #endif } }; class DebugMessageHandlerRef : public DefaultDebugMessageHandler { DebugMessageHandler* m_handler; public: DebugMessageHandlerRef() : m_handler(this) { } void setHandler(DebugMessageHandler& handler) { m_handler = &handler; } DebugMessageHandler& getHandler() { return *m_handler; } }; typedef Static GlobalDebugMessageHandler; inline DebugMessageHandler& globalDebugMessageHandler() { return GlobalDebugMessageHandler::instance().getHandler(); } #if defined(DEBUG_ASSERTS) /// \brief Sends a \p message to the current debug-message-handler text-output-stream if \p condition evaluates to false. #define ASSERT_MESSAGE(condition, message) do{\ if(!(condition))\ {\ globalDebugMessageHandler().getOutputStream() << FILE_LINE "\nassertion failure: " << message << "\n";\ if(!globalDebugMessageHandler().handleMessage()) { DEBUGGER_BREAKPOINT(); }\ }} while(0) /// \brief Sends a \p message to the current debug-message-handler text-output-stream. #define ERROR_MESSAGE(message) do{\ globalDebugMessageHandler().getOutputStream() << FILE_LINE "\nruntime error: " << message << "\n";\ if(!globalDebugMessageHandler().handleMessage()) { DEBUGGER_BREAKPOINT(); }} while(0) #define ASSERT_NOTNULL(ptr) ASSERT_MESSAGE(ptr != 0, "pointer \"" #ptr "\" is null") #else #define ASSERT_MESSAGE(condition, message) #define ERROR_MESSAGE(message) #define ASSERT_NOTNULL(ptr) #endif #endif