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 _UDF_DEBUG_H
10#define _UDF_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
26#define DEBUG_TO_FILE 0
27
28#	include <stdio.h>
29#if DEBUG_TO_FILE
30//#	include <stdio.h>
31#	include <stdarg.h>
32extern "C" int 	vsprintf(char *s, const char *format, va_list arg);
33#	include <fcntl.h>
34#	define __out dbg_printf
35	void dbg_printf(const char *format,...);
36	void initialize_debugger(const char *filename);
37#else
38#	if !_KERNEL_MODE
39//#		include <stdio.h>
40#		define __out printf
41#	else
42//#		include <null.h>
43#		define __out dprintf
44#	endif
45#	include <stdio.h>
46#	include <malloc.h>
47//#	define __out printf
48#endif
49
50class DebugHelper;
51
52int32 _get_debug_indent_level();
53
54/*! \brief Helper class that is allocated on the stack by
55	the \c DEBUG_INIT() macro. On creation, it increases the
56	current indentation level by the amount specified via its
57	constructor's \c tabCount parameter; on destruction, it
58	decreases it.
59*/
60class DebugHelper
61{
62public:
63	DebugHelper(const char *className = NULL, uint8 tabCount = 1);
64	~DebugHelper();
65
66	uint8 TabCount() const { return fTabCount; }
67	const char* ClassName() const { return fClassName; }
68
69private:
70	uint8 fTabCount;
71	char *fClassName;
72};
73
74//----------------------------------------------------------------------
75// NOTE: See Debug.cpp for complete descriptions of the following
76// debug macros.
77//----------------------------------------------------------------------
78
79
80//----------------------------------------------------------------------
81// DEBUG-independent macros
82//----------------------------------------------------------------------
83#define INFORM(x) { __out("udf: "); __out x; }
84#if !_KERNEL_MODE
85#	define DIE(x) debugger x
86#else
87#	define DIE(x) kernel_debugger x
88#endif
89
90//----------------------------------------------------------------------
91// DEBUG-dependent macros
92//----------------------------------------------------------------------
93#ifdef DEBUG
94	#if DEBUG_TO_FILE
95		#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) initialize_debugger(filename);
96	#else
97		#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) ;
98	#endif
99
100	#define DEBUG_INIT_SILENT(className)			\
101		DebugHelper _debugHelper(className, 2);
102
103	#define DEBUG_INIT(className)		\
104		DEBUG_INIT_SILENT(className);	\
105		PRINT(("\n"));
106
107	#define DEBUG_INIT_ETC(className, arguments)							\
108		DEBUG_INIT_SILENT(className)										\
109		{																	\
110			PRINT_INDENT();													\
111			if (_debugHelper.ClassName()) {									\
112				__out("udf: %s::%s(", 									\
113				      _debugHelper.ClassName(), __FUNCTION__);				\
114			} else 	{														\
115				__out("udf: %s(", __FUNCTION__);						\
116			}																\
117			__out arguments;												\
118			__out("):\n");													\
119		}
120
121	#define DUMP_INIT(className)	\
122		DEBUG_INIT_SILENT(className);
123
124	#define PRINT(x) { 														\
125		{																	\
126			PRINT_INDENT();													\
127			if (_debugHelper.ClassName()) {									\
128				__out("udf: %s::%s(): ", 								\
129				      _debugHelper.ClassName(), __FUNCTION__);				\
130			} else 	{														\
131				__out("udf: %s(): ",  __FUNCTION__);					\
132			}																\
133			__out x; 														\
134		} 																	\
135	}
136
137	#define LPRINT(x) { 													\
138		{																	\
139			PRINT_INDENT();													\
140			if (_debugHelper.ClassName()) {									\
141				__out("udf: %s::%s(): line %d: ", 						\
142				      _debugHelper.ClassName(), __FUNCTION__, __LINE__);	\
143			} else {														\
144				__out("udf: %s(): line %d: ", 							\
145				      __FUNCTION__, __LINE__);								\
146			}																\
147			__out x;														\
148		} 																	\
149	}
150
151	#define SIMPLE_PRINT(x) { 									\
152		{														\
153			__out x; 											\
154		} 														\
155	}
156
157	#define PRINT_INDENT() { 									\
158		{														\
159			int32 _level = _get_debug_indent_level();			\
160			for (int32 i = 0; i < _level-_debugHelper.TabCount(); i++) {				\
161				__out(" ");										\
162			}													\
163		}														\
164	}
165
166	#define PRINT_DIVIDER()	\
167		PRINT_INDENT(); 	\
168		SIMPLE_PRINT(("------------------------------------------------------------\n"));
169
170	#define DUMP(object)				\
171		{								\
172			(object).dump();			\
173		}
174
175	#define PDUMP(objectPointer)		\
176		{								\
177			(objectPointer)->dump();	\
178		}
179
180	#define REPORT_ERROR(error) {									\
181		LPRINT(("returning error 0x%" B_PRIx32 ", `%s'\n", error,	\
182			strerror(error)));										\
183	}
184
185	#define RETURN_ERROR(error) { 		\
186		status_t _status = error; 		\
187		if (_status < (status_t)B_OK)	\
188			REPORT_ERROR(_status);		\
189		return _status;					\
190	}
191
192	#define RETURN(error) { 										\
193		status_t _status = error; 									\
194		if (_status < (status_t)B_OK) {								\
195			REPORT_ERROR(_status); 									\
196		} else if (_status == (status_t)B_OK) {						\
197			LPRINT(("returning B_OK\n"));							\
198		} else {													\
199			LPRINT(("returning 0x%" B_PRIx32 " = %" PRId32 "\n",	\
200				_status, _status));									\
201		}															\
202		return _status; 											\
203	}
204
205	#define FATAL(x) { 								\
206		PRINT(("fatal error: ")); SIMPLE_PRINT(x);	\
207	}
208
209	#define DBG(x) x ;
210
211#else	// ifdef DEBUG
212	#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) ;
213	#define DEBUG_INIT_SILENT(className)	;
214	#define DEBUG_INIT(className) ;
215	#define DEBUG_INIT_ETC(className, arguments) ;
216	#define DUMP_INIT(className)	;
217	#define PRINT(x) ;
218	#define LPRINT(x) ;
219	#define SIMPLE_PRINT(x) ;
220	#define PRINT_INDENT(x) ;
221	#define PRINT_DIVIDER()	;
222	#define DUMP(object) ;
223	#define PDUMP(objectPointer) ;
224	#define REPORT_ERROR(status) ;
225	#define RETURN_ERROR(status) return status;
226	#define RETURN(status) return status;
227	#define FATAL(x) { __out("udf: fatal error: "); __out x; }
228	#define DBG(x) ;
229#endif	// ifdef DEBUG else
230
231#define TRACE(x) /*dprintf x*/
232
233#ifdef TEST_HAIKU
234	#define TRACE_ERROR(x) printf x
235#else
236	#define TRACE_ERROR(x) dprintf x
237#endif
238
239// These macros turn on or off extensive and generally unnecessary
240// debugging output regarding table of contents parsing
241//#define WARN(x) (dprintf x)
242//#define WARN(x)
243#define WARN(x) DBG(dprintf x)
244
245#endif	// _UDF_DEBUG_H
246