00001 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */ 00002 00003 /* AbiSource Program Utilities 00004 * Copyright (C) 1998 AbiSource, Inc. 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00019 * 02110-1301 USA. 00020 */ 00021 00022 #ifndef UT_ASSERT_H 00023 #define UT_ASSERT_H 00024 00025 #ifdef HAVE_CONFIG_H 00026 #include "config.h" 00027 #endif 00028 00029 #include "ut_debugmsg.h" 00030 00031 // TODO move these declarations into platform directories. 00032 00033 #if (defined (WIN32) || defined (_WIN32) || defined (_WIN64)) 00034 // The 'cool' win32 assert, at least with VC6, corrups memory (probably calling sprintf on 00035 // a static buffer without checking bounds), so we implement our own assert dialog, which 00036 // is even cooler. TF 00037 00038 #include "ut_types.h" 00039 00040 #ifdef NDEBUG 00041 # define UT_ASSERT(x) 00042 #else 00043 // This function is implemented in ut_Win32Misc.cpp. It is not declared in any header file (it is 00044 // only to be referenced from here and we want to reduce the files we include here to a 00045 // bare minimum for performance reasons, as this file gets included from pretty much 00046 // everywhere). 00047 extern int ABI_EXPORT UT_Win32ThrowAssert(const char * pCondition, const char * pFile, int iLine, int iCount); 00048 00049 // The best way of stepping into debugger is by generating the appropriate interupt 00050 // instruction, so if we are on Intel x86, we will issue int 3. If we are not on x86, we 00051 // will use the win32 DebugBreak() function (the disadvantage of that is that the 00052 // execution is interupted not in our code, but in one of the system libs, so you have to 00053 // step out of that system function to get into our code; its rather non-intuitive. 00054 00055 # undef UT_DEBUG_BREAK 00056 00057 // I am not sure which is the standard GCC macro for the x86 platform; we are supposed to 00058 // be able to get all the predefined macros by running 'cpp -dM' but it would not work on 00059 // my cygwin 00060 # if defined(__GNUC__) && (defined(_X86) || defined(__i386) || defined(i386)) 00061 // Inline assembly for GCC on x86 00062 # define UT_DEBUG_BREAK asm("int3"); 00063 # elif defined(__GNUC__) && (defined(__ia64) || defined(ia64)) 00064 # error "This branch has not been tested." 00065 // On Itanium we use the intrinsic function __break(); defined in ia64intrin.h 00066 // I am not sure whether we need to tell the compiler this one is intrinsic (MSVC 00067 // uses a #pragma for this 00068 void __break(int); 00069 # define UT_DEBUG_BREAK __break(0x80016); 00070 # elif defined(_MSC_VER) && defined(_M_IX86) 00071 // inline assmebly for MSVC on x86 00072 # define UT_DEBUG_BREAK _asm {int 3} 00073 # elif defined(_MSC_VER) && (defined(_M_IA64) || defined(_M_AMD64)) 00074 # error "This branch has not been tested." 00075 // On Itanium we use the intrinsic function __break(); 00076 // I assume this will also work for AMD64, but I am not 100% sure 00077 void __break(int); 00078 // this forces __break() to be generated as inline code (see MSDN) 00079 # pragma intrinsic (__break) 00080 # define UT_DEBUG_BREAK __break(0x80016); 00081 # endif 00082 00083 # ifndef UT_DEBUG_BREAK 00084 // Some compiler/architecture for which we do not know how to generate inline assembly to pass 00085 // control to the debugger; we use win32s DebugBreak(). 00086 // 00087 // TODO !!! This currently does not work; if someone one day wants to build AW on non-x86 00088 // win32 architecture, they will need to fix this (including <windows.h> from here, which 00089 // is what would work, screws up things in MS Word importer, because the wv library 00090 // redefines some of the win32 structures; but we probably do not want to include 00091 // windows.h from here anyway because of the overhead -- ut_assert.h gets included in 00092 // almost everything.). Really, we want to do something similar as we do for x86. 00093 # error "Proper implementation needed for this compiler/architecture" 00094 00095 # ifndef _WINBASE_ 00096 __declspec(dllimport) void __stdcall DebugBreak(void); 00097 # endif /* ifdef _WINBASE_ */ 00098 00099 # define UT_DEBUG_BREAK DebugBreak(); 00100 # endif /* ifndef UT_DEBUG_BREAK */ 00101 00102 // We want to track the number of times we have been through this assert and have the 00103 // option of disabling this assert for the rest of the session; we use the __iCount and 00104 // __bOnceOnly vars for this (this adds a few bytes to the code and footprint, but on 00105 // large scale of things, this is quite negligible for the debug build). 00106 #define UT_ASSERT(x) \ 00107 { \ 00108 static bool __bOnceOnly = false; \ 00109 static long __iCount = 0; \ 00110 if(!__bOnceOnly && !(x)) \ 00111 { \ 00112 __iCount++; \ 00113 int __iRet = UT_Win32ThrowAssert(#x,__FILE__, __LINE__, __iCount); \ 00114 if(__iRet == 0) \ 00115 { \ 00116 UT_DEBUG_BREAK \ 00117 } \ 00118 else if(__iRet < 0) \ 00119 { \ 00120 __bOnceOnly = true; \ 00121 } \ 00122 } \ 00123 } 00124 00125 #endif // ifdef NDEBUG 00126 00127 #else 00128 00129 // A Unix variant, possibly Gnome. 00130 00131 # ifdef NDEBUG 00132 00133 // When NDEBUG is defined, assert() does nothing. 00134 // So we let the system header files take care of it. 00135 # if 0 //defined(TOOLKIT_COCOA) 00136 // Please keep the "/**/" to stop MSVC dependency generator complaining. 00137 # include "xap_CocoaAssert.h" 00138 # define UT_ASSERT(expr) \ 00139 ((void) ((expr) || \ 00140 (XAP_CocoaAssertMsg(#expr, \ 00141 __FILE__, __LINE__), \ 00142 0))) 00143 00144 # else 00145 # include <assert.h> 00146 # define UT_ASSERT assert 00147 # endif 00148 # else 00149 // Otherwise, we want a slighly modified behavior. 00150 // We'd like assert() to ask us before crashing. 00151 // We treat asserts as logic flaws, which are sometimes 00152 // recoverable, but that should be noted. 00153 00154 # include <assert.h> 00155 // Please keep the "/**/" to stop MSVC dependency generator complaining. 00156 # include "ut_unixAssert.h" 00157 # define UT_ASSERT(expr) \ 00158 { \ 00159 if (!ut_g_silent) { \ 00160 static bool __bOnceOnly = false; \ 00161 if (!__bOnceOnly && !(expr)) { \ 00162 if (UT_UnixAssertMsg(#expr, __FILE__, __LINE__) == -1) { \ 00163 __bOnceOnly = true; \ 00164 } \ 00165 } \ 00166 } \ 00167 } 00168 # endif 00169 00170 #endif 00171 00172 00176 #define UT_NOT_IMPLEMENTED 0 00177 00181 #define UT_SHOULD_NOT_HAPPEN 0 00182 00186 #define UT_TODO 0 00187 00191 #define UT_NOT_REACHED 0 00192 00196 #define UT_ASSERT_NOT_REACHED() UT_ASSERT(UT_NOT_REACHED) 00197 00201 #define UT_ASSERT_HARMLESS(cond) UT_ASSERT(cond) 00202 00206 #define UT_return_if_fail(cond) if (!(cond)) { UT_ASSERT(cond); return; } 00207 00211 #define UT_return_val_if_fail(cond, val) if (!(cond)) { UT_ASSERT(cond); return (val); } 00212 00216 #define UT_throw_if_fail(cond, val) if (!(cond)) { UT_ASSERT(cond); throw val; } 00217 00221 #define UT_continue_if_fail(cond) if (!(cond)) { UT_ASSERT(cond); continue; } 00222 00223 #endif /* UT_ASSERT_H */