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., 59 Temple Place - Suite 330, Boston, MA 00019 * 02111-1307, 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 // TODO move these declarations into platform directories. 00030 00031 #if (defined (WIN32) || defined (_WIN32) || defined (_WIN64)) 00032 // The 'cool' win32 assert, at least with VC6, corrups memory (probably calling sprintf on 00033 // a static buffer without checking bounds), so we implement our own assert dialog, which 00034 // is even cooler. TF 00035 00036 #include "ut_types.h" 00037 00038 #ifdef NDEBUG 00039 # define UT_ASSERT(x) 00040 #else 00041 // This function is implemented in ut_Win32Misc.cpp. It is not declared in any header file (it is 00042 // only to be referenced from here and we want to reduce the files we include here to a 00043 // bare minimum for performance reasons, as this file gets included from pretty much 00044 // everywhere). 00045 extern int ABI_EXPORT UT_Win32ThrowAssert(const char * pCondition, const char * pFile, int iLine, int iCount); 00046 00047 // The best way of stepping into debugger is by generating the appropriate interupt 00048 // instruction, so if we are on Intel x86, we will issue int 3. If we are not on x86, we 00049 // will use the win32 DebugBreak() function (the disadvantage of that is that the 00050 // execution is interupted not in our code, but in one of the system libs, so you have to 00051 // step out of that system function to get into our code; its rather non-intuitive. 00052 00053 # undef UT_DEBUG_BREAK 00054 00055 // I am not sure which is the standard GCC macro for the x86 platform; we are supposed to 00056 // be able to get all the predefined macros by running 'cpp -dM' but it would not work on 00057 // my cygwin 00058 # if defined(__GNUC__) && (defined(_X86) || defined(__i386) || defined(i386)) 00059 // Inline assembly for GCC on x86 00060 # define UT_DEBUG_BREAK asm("int3"); 00061 # elif defined(__GNUC__) && (defined(__ia64) || defined(ia64)) 00062 # error "This branch has not been tested." 00063 // On Itanium we use the intrinsic function __break(); defined in ia64intrin.h 00064 // I am not sure whether we need to tell the compiler this one is intrinsic (MSVC 00065 // uses a #pragma for this 00066 void __break(int); 00067 # define UT_DEBUG_BREAK __break(0x80016); 00068 # elif defined(_MSC_VER) && defined(_M_IX86) 00069 // inline assmebly for MSVC on x86 00070 # define UT_DEBUG_BREAK _asm {int 3} 00071 # elif defined(_MSC_VER) && (defined(_M_IA64) || defined(_M_AMD64)) 00072 # error "This branch has not been tested." 00073 // On Itanium we use the intrinsic function __break(); 00074 // I assume this will also work for AMD64, but I am not 100% sure 00075 void __break(int); 00076 // this forces __break() to be generated as inline code (see MSDN) 00077 # pragma intrinsic (__break) 00078 # define UT_DEBUG_BREAK __break(0x80016); 00079 # endif 00080 00081 # ifndef UT_DEBUG_BREAK 00082 // Some compiler/architecture for which we do not know how to generate inline assembly to pass 00083 // control to the debugger; we use win32s DebugBreak(). 00084 // 00085 // TODO !!! This currently does not work; if someone one day wants to build AW on non-x86 00086 // win32 architecture, they will need to fix this (including <windows.h> from here, which 00087 // is what would work, screws up things in MS Word importer, because the wv library 00088 // redefines some of the win32 structures; but we probably do not want to include 00089 // windows.h from here anyway because of the overhead -- ut_assert.h gets included in 00090 // almost everything.). Really, we want to do something similar as we do for x86. 00091 # error "Proper implementation needed for this compiler/architecture" 00092 00093 # ifndef _WINBASE_ 00094 __declspec(dllimport) void __stdcall DebugBreak(void); 00095 # endif /* ifdef _WINBASE_ */ 00096 00097 # define UT_DEBUG_BREAK DebugBreak(); 00098 # endif /* ifndef UT_DEBUG_BREAK */ 00099 00100 // We want to track the number of times we have been through this assert and have the 00101 // option of disabling this assert for the rest of the session; we use the __iCount and 00102 // __bOnceOnly vars for this (this adds a few bytes to the code and footprint, but on 00103 // large scale of things, this is quite negligible for the debug build). 00104 #define UT_ASSERT(x) \ 00105 { \ 00106 static bool __bOnceOnly = false; \ 00107 static long __iCount = 0; \ 00108 if(!__bOnceOnly && !(x)) \ 00109 { \ 00110 __iCount++; \ 00111 int __iRet = UT_Win32ThrowAssert(#x,__FILE__, __LINE__, __iCount); \ 00112 if(__iRet == 0) \ 00113 { \ 00114 UT_DEBUG_BREAK \ 00115 } \ 00116 else if(__iRet < 0) \ 00117 { \ 00118 __bOnceOnly = true; \ 00119 } \ 00120 } \ 00121 } 00122 00123 #endif // ifdef NDEBUG 00124 00125 #else 00126 00127 // A Unix variant, possibly Gnome. 00128 00129 # ifdef NDEBUG 00130 00131 // When NDEBUG is defined, assert() does nothing. 00132 // So we let the system header files take care of it. 00133 # if defined(TOOLKIT_COCOA) 00134 // Please keep the "/**/" to stop MSVC dependency generator complaining. 00135 # include "xap_CocoaAssert.h" 00136 # define UT_ASSERT(expr) \ 00137 ((void) ((expr) || \ 00138 (XAP_CocoaAssertMsg(#expr, \ 00139 __FILE__, __LINE__), \ 00140 0))) 00141 00142 # else 00143 # include <assert.h> 00144 # define UT_ASSERT assert 00145 # endif 00146 # else 00147 // Otherwise, we want a slighly modified behavior. 00148 // We'd like assert() to ask us before crashing. 00149 // We treat asserts as logic flaws, which are sometimes 00150 // recoverable, but that should be noted. 00151 00152 # include <assert.h> 00153 // Please keep the "/**/" to stop MSVC dependency generator complaining. 00154 # include "ut_unixAssert.h" 00155 # define UT_ASSERT(expr) \ 00156 { \ 00157 static bool __bOnceOnly = false; \ 00158 if (!__bOnceOnly && !(expr)) \ 00159 if (UT_UnixAssertMsg(#expr, __FILE__, __LINE__) == -1) \ 00160 __bOnceOnly = true; \ 00161 } 00162 # endif 00163 00164 #endif 00165 00166 00170 #define UT_NOT_IMPLEMENTED 0 00171 00175 #define UT_SHOULD_NOT_HAPPEN 0 00176 00180 #define UT_TODO 0 00181 00185 #define UT_NOT_REACHED 0 00186 00190 #define UT_ASSERT_NOT_REACHED() UT_ASSERT(UT_NOT_REACHED) 00191 00195 #define UT_ASSERT_HARMLESS(cond) UT_ASSERT(cond) 00196 00200 #define UT_return_if_fail(cond) if (!(cond)) { UT_ASSERT(cond); return; } 00201 00205 #define UT_return_val_if_fail(cond, val) if (!(cond)) { UT_ASSERT(cond); return (val); } 00206 00210 #define UT_throw_if_fail(cond, val) if (!(cond)) { UT_ASSERT(cond); throw val; } 00211 00215 #define UT_continue_if_fail(cond) if (!(cond)) { UT_ASSERT(cond); continue; } 00216 00217 #endif /* UT_ASSERT_H */