1 // This code is in the public domain -- castanyo@yahoo.es
2 
3 #ifndef NV_CORE_DEBUG_H
4 #define NV_CORE_DEBUG_H
5 
6 #include <nvcore/nvcore.h>
7 
8 #if defined(HAVE_STDARG_H)
9 #	include <stdarg.h>	// va_list
10 #endif
11 
12 #define NV_ABORT_DEBUG		1
13 #define NV_ABORT_IGNORE		2
14 #define NV_ABORT_EXIT		3
15 
16 #undef assert	// avoid conflicts with assert method.
17 
18 #define nvNoAssert(exp) \
19 	do { \
20 		(void)sizeof(exp); \
21 	} while(0)
22 
23 #if NV_NO_ASSERT
24 
25 #	define nvAssert(exp) nvNoAssert(exp)
26 #	define nvCheck(exp) nvNoAssert(exp)
27 #	define nvDebugAssert(exp) nvNoAssert(exp)
28 #	define nvDebugCheck(exp) nvNoAssert(exp)
29 #	define nvDebugBreak() nvNoAssert(0)
30 
31 #else // NV_NO_ASSERT
32 
33 #	if NV_CC_MSVC
34 		// @@ Does this work in msvc-6 and earlier?
35 		// @@ Do I have to include <intrin.h> ?
36 #		define nvDebugBreak()		__debugbreak()
37 		// define nvDebugBreak()		__asm int 3
38 #	elif NV_CC_GNUC && NV_CPU_PPC && NV_OS_DARWIN
39 #		define nvDebugBreak()		__asm__ volatile ("trap");
40 #	elif NV_CC_GNUC && NV_CPU_X86 && NV_OS_DARWIN
41 #		define nvDebugBreak()		__asm__ volatile ("int3");
42 #	elif NV_CC_GNUC && NV_CPU_X86
43 #		define nvDebugBreak()		__asm__ ( "int %0" : :"I"(3) )
44 #	else
45 #		include <signal.h>
46 #		define nvDebugBreak()		raise(SIGTRAP);
47 		// define nvDebugBreak() 		*((int *)(0)) = 0
48 #	endif
49 
50 #	define nvAssertMacro(exp) \
51 		do { \
52 			if(!(exp)) { \
53 				if( nvAbort(#exp, __FILE__, __LINE__, __FUNC__) == NV_ABORT_DEBUG ) { \
54 					nvDebugBreak(); \
55 				} \
56 			} \
57 		} while(false)
58 
59 #	define nvAssert(exp)	nvAssertMacro(exp)
60 #	define nvCheck(exp)		nvAssertMacro(exp)
61 
62 #	if defined(_DEBUG)
63 #		define nvDebugAssert(exp)	nvAssertMacro(exp)
64 #		define nvDebugCheck(exp)	nvAssertMacro(exp)
65 #	else // _DEBUG
66 #		define nvDebugAssert(exp)	nvNoAssert(exp)
67 #		define nvDebugCheck(exp)	nvNoAssert(exp)
68 #	endif // _DEBUG
69 
70 #endif // NV_NO_ASSERT
71 
72 // Use nvAssume for very simple expresions only: nvAssume(0), nvAssume(value == true), etc.
73 #if defined(_DEBUG)
74 #	if NV_CC_MSVC
75 #		define nvAssume(exp)	__assume(exp)
76 #	else
77 #		define nvAssume(exp)	nvCheck(exp)
78 #	endif
79 #else
80 #	define nvAssume(exp)	nvCheck(exp)
81 #endif
82 
83 
84 #define nvError(x)		nvAbort(x, __FILE__, __LINE__, __FUNC__)
85 #define nvWarning(x)	nvDebug("*** Warning %s/%d: %s\n", __FILE__, __LINE__, (x))
86 
87 
88 #if PI_CC_MSVC
89 // @@ I'm not sure it's a good idea to use the default static assert.
90 #	define nvStaticCheck(x) _STATIC_ASSERT(x)
91 #else
92 #	define nvStaticCheck(x) typedef char NV_DO_STRING_JOIN2(__static_assert_,__LINE__)[(x)]
93 // 	define nvStaticCheck(x) switch(0) { case 0: case x:; }
94 #endif
95 
96 NVCORE_API int nvAbort(const char *exp, const char *file, int line, const char * func = 0);
97 NVCORE_API void NV_CDECL nvDebug( const char *msg, ... ) __attribute__((format (printf, 1, 2)));
98 
99 namespace nv
100 {
101 	/** Message handler interface. */
102 	struct MessageHandler {
103 		virtual void log(const char * str, va_list arg) = 0;
~MessageHandlerMessageHandler104 		virtual ~MessageHandler() {}
105 	};
106 
107 	/** Assert handler interface. */
108 	struct AssertHandler {
109 		virtual int assert(const char *exp, const char *file, int line, const char *func = 0) = 0;
~AssertHandlerAssertHandler110 		virtual ~AssertHandler() {}
111 	};
112 
113 
114 	namespace debug
115 	{
116 		NVCORE_API void dumpInfo();
117 
118 		// These functions are not thread safe.
119 		NVCORE_API void setMessageHandler( MessageHandler * messageHandler );
120 		NVCORE_API void resetMessageHandler();
121 
122 		NVCORE_API void setAssertHandler( AssertHandler * assertHanlder );
123 		NVCORE_API void resetAssertHandler();
124 
125 		NVCORE_API void enableSigHandler();
126 		NVCORE_API void disableSigHandler();
127 	}
128 
129 } // nv namespace
130 
131 #endif	// NV_CORE_DEBUG_H
132