1//----------------------------------------------------------------------
2//  This software is part of the Haiku distribution and is covered
3//  by the MIT License.
4//
5//  This version copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net
6//  Initial version copyright (c) 2002 Axel D��rfler, axeld@pinc-software.de
7//	dbg_printf() function copyright (c) 2003 Ingo Weinhold, bonefish@cs.tu-berlin.edu
8//----------------------------------------------------------------------
9#ifndef MY_DEBUG_H
10#define MY_DEBUG_H
11
12/*! \file Debug.h
13
14	Handy debugging macros.
15*/
16
17#include <KernelExport.h>
18
19#include <OS.h>
20#ifdef DEBUG
21#	include <string.h>
22#endif
23#include <unistd.h>
24
25#define DEBUG_TO_FILE 0
26
27#if DEBUG_TO_FILE
28#	include <stdio.h>
29#	include <fcntl.h>
30#	define __out dbg_printf
31	void dbg_printf(const char *format,...);
32	void initialize_debugger(const char *filename);
33#else
34#	ifdef USER
35#		include <stdio.h>
36#		define __out printf
37#	else
38#		include <null.h>
39#		define __out dprintf
40#	endif
41#endif
42
43#include "util/kernel_cpp.h"
44
45class DebugHelper;
46
47int32 _get_debug_indent_level();
48
49/*! \brief Helper class that is allocated on the stack by
50	the \c DEBUG_INIT() macro. On creation, it increases the
51	current indentation level by the amount specified via its
52	constructor's \c tabCount parameter; on destruction, it
53	decreases it.
54*/
55class DebugHelper
56{
57public:
58	DebugHelper(const char *className = NULL, uint8 tabCount = 1);
59	~DebugHelper();
60
61	uint8 TabCount() const { return fTabCount; }
62	const char* ClassName() const { return fClassName; }
63
64private:
65	uint8 fTabCount;
66	char *fClassName;
67};
68
69//----------------------------------------------------------------------
70// NOTE: See Debug.cpp for complete descriptions of the following
71// debug macros.
72//----------------------------------------------------------------------
73
74
75//----------------------------------------------------------------------
76// DEBUG-independent macros
77//----------------------------------------------------------------------
78#define INFORM(x) { __out("session: "); __out x; }
79#ifdef USER
80#	define DIE(x) debugger x
81#else
82#	define DIE(x) kernel_debugger x
83#endif
84
85//----------------------------------------------------------------------
86// DEBUG-dependent macros
87//----------------------------------------------------------------------
88#ifdef DEBUG
89	#if DEBUG_TO_FILE
90		#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) initialize_debugger(filename);
91	#else
92		#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) ;
93	#endif
94
95	#define DEBUG_INIT_SILENT(className)			\
96		DebugHelper _debugHelper(className, 2);
97
98	#define DEBUG_INIT(className)		\
99		DEBUG_INIT_SILENT(className);	\
100		PRINT(("\n"));
101
102	#define DEBUG_INIT_ETC(className, arguments)							\
103		DEBUG_INIT_SILENT(className)										\
104		{																	\
105			PRINT_INDENT();													\
106			if (_debugHelper.ClassName()) {									\
107				__out("session: %s::%s(", 									\
108				      _debugHelper.ClassName(), __FUNCTION__);				\
109			} else 	{														\
110				__out("session: %s(", __FUNCTION__);						\
111			}																\
112			__out arguments;												\
113			__out("):\n");													\
114		}
115
116	#define DUMP_INIT(categoryFlags, className)	\
117		DEBUG_INIT_SILENT(className);
118
119	#define PRINT(x) { 														\
120		{																	\
121			PRINT_INDENT();													\
122			if (_debugHelper.ClassName()) {									\
123				__out("session: %s::%s(): ", 								\
124				      _debugHelper.ClassName(), __FUNCTION__);				\
125			} else 	{														\
126				__out("session: %s(): ",  __FUNCTION__);					\
127			}																\
128			__out x; 														\
129		} 																	\
130	}
131
132	#define LPRINT(x) { 													\
133		{																	\
134			PRINT_INDENT();													\
135			if (_debugHelper.ClassName()) {									\
136				__out("session: %s::%s(): line %d: ", 						\
137				      _debugHelper.ClassName(), __FUNCTION__, __LINE__);	\
138			} else {														\
139				__out("session: %s(): line %d: ", 							\
140				      __FUNCTION__, __LINE__);								\
141			}																\
142			__out x;														\
143		} 																	\
144	}
145
146	#define SIMPLE_PRINT(x) { 									\
147		{														\
148			__out x; 											\
149		} 														\
150	}
151
152	#define PRINT_INDENT() { 									\
153		{														\
154			int32 _level = _get_debug_indent_level();			\
155			for (int32 i = 0; i < _level-_debugHelper.TabCount(); i++) {				\
156				__out(" ");										\
157			}													\
158		}														\
159	}
160
161	#define PRINT_DIVIDER()	\
162		PRINT_INDENT(); 	\
163		SIMPLE_PRINT(("------------------------------------------------------------\n"));
164
165	#define DUMP(object)				\
166		{								\
167			(object).dump();			\
168		}
169
170	#define PDUMP(objectPointer)		\
171		{								\
172			(objectPointer)->dump();	\
173		}
174
175	#define REPORT_ERROR(error) {											\
176		LPRINT(("returning error 0x%" B_PRIx32 ", `%s'\n", error, strerror(error)));	\
177	}
178
179	#define RETURN_ERROR(error) { 		\
180		status_t _status = error; 		\
181		if (_status < (status_t)B_OK)	\
182			REPORT_ERROR(_status);		\
183		return _status;					\
184	}
185
186	#define RETURN(error) { 										\
187		status_t _status = error; 									\
188		if (_status < (status_t)B_OK) {								\
189			REPORT_ERROR(_status); 									\
190		} else if (_status == (status_t)B_OK) {						\
191			LPRINT(("returning B_OK\n"));							\
192		} else {													\
193			LPRINT(("returning 0x%" B_PRIx32 " = %" B_PRId32 "\n", _status, _status));	\
194		}															\
195		return _status; 											\
196	}
197
198	#define FATAL(x) { 								\
199		PRINT(("fatal error: ")); SIMPLE_PRINT(x);	\
200	}
201
202	#define DBG(x) x ;
203
204#else	// ifdef DEBUG
205	#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) ;
206	#define DEBUG_INIT_SILENT(className)	;
207	#define DEBUG_INIT(className) ;
208	#define DEBUG_INIT_ETC(className, arguments) ;
209	#define DUMP_INIT(className)	;
210	#define PRINT(x) ;
211	#define LPRINT(x) ;
212	#define SIMPLE_PRINT(x) ;
213	#define PRINT_INDENT(x) ;
214	#define PRINT_DIVIDER()	;
215	#define PDUMP(objectPointer) ;
216	#define REPORT_ERROR(status) ;
217	#define RETURN_ERROR(status) return status;
218	#define RETURN(status) return status;
219	#define FATAL(x) { __out("session: fatal error: "); __out x; }
220	#define DBG(x) ;
221	#define DUMP(x) ;
222#endif	// ifdef DEBUG else
223
224#define TRACE(x) DBG(dprintf x)
225
226// These macros turn on or off extensive and generally unnecessary
227// debugging output regarding table of contents parsing
228//#define WARN(x) (dprintf x)
229//#define WARN(x)
230#define WARN(x) DBG(dprintf x)
231
232#endif	// MY_DEBUG_H
233