1//----------------------------------------------------------------------
2//  This software is part of the OpenBeOS distribution and is covered
3//  by the OpenBeOS 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
50#include "kernel_cpp.h"
51
52class DebugHelper;
53
54int32 _get_debug_indent_level();
55
56/*! \brief Helper class that is allocated on the stack by
57	the \c DEBUG_INIT() macro. On creation, it increases the
58	current indentation level by the amount specified via its
59	constructor's \c tabCount parameter; on destruction, it
60	decreases it.
61*/
62class DebugHelper
63{
64public:
65	DebugHelper(const char *className = NULL, uint8 tabCount = 1);
66	~DebugHelper();
67
68	uint8 TabCount() const { return fTabCount; }
69	const char* ClassName() const { return fClassName; }
70
71private:
72	uint8 fTabCount;
73	char *fClassName;
74};
75
76//----------------------------------------------------------------------
77// NOTE: See Debug.cpp for complete descriptions of the following
78// debug macros.
79//----------------------------------------------------------------------
80
81
82//----------------------------------------------------------------------
83// DEBUG-independent macros
84//----------------------------------------------------------------------
85#define INFORM(x) { __out("udf: "); __out x; }
86#if !_KERNEL_MODE
87#	define DIE(x) debugger x
88#else
89#	define DIE(x) kernel_debugger x
90#endif
91
92//----------------------------------------------------------------------
93// DEBUG-dependent macros
94//----------------------------------------------------------------------
95#ifdef DEBUG
96	#if DEBUG_TO_FILE
97		#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) initialize_debugger(filename);
98	#else
99		#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) ;
100	#endif
101
102	#define DEBUG_INIT_SILENT(className)			\
103		DebugHelper _debugHelper(className, 2);
104
105	#define DEBUG_INIT(className)		\
106		DEBUG_INIT_SILENT(className);	\
107		PRINT(("\n"));
108
109	#define DEBUG_INIT_ETC(className, arguments)							\
110		DEBUG_INIT_SILENT(className)										\
111		{																	\
112			PRINT_INDENT();													\
113			if (_debugHelper.ClassName()) {									\
114				__out("udf: %s::%s(", 									\
115				      _debugHelper.ClassName(), __FUNCTION__);				\
116			} else 	{														\
117				__out("udf: %s(", __FUNCTION__);						\
118			}																\
119			__out arguments;												\
120			__out("):\n");													\
121		}
122
123	#define DUMP_INIT(className)	\
124		DEBUG_INIT_SILENT(className);
125
126	#define PRINT(x) { 														\
127		{																	\
128			PRINT_INDENT();													\
129			if (_debugHelper.ClassName()) {									\
130				__out("udf: %s::%s(): ", 								\
131				      _debugHelper.ClassName(), __FUNCTION__);				\
132			} else 	{														\
133				__out("udf: %s(): ",  __FUNCTION__);					\
134			}																\
135			__out x; 														\
136		} 																	\
137	}
138
139	#define LPRINT(x) { 													\
140		{																	\
141			PRINT_INDENT();													\
142			if (_debugHelper.ClassName()) {									\
143				__out("udf: %s::%s(): line %d: ", 						\
144				      _debugHelper.ClassName(), __FUNCTION__, __LINE__);	\
145			} else {														\
146				__out("udf: %s(): line %d: ", 							\
147				      __FUNCTION__, __LINE__);								\
148			}																\
149			__out x;														\
150		} 																	\
151	}
152
153	#define SIMPLE_PRINT(x) { 									\
154		{														\
155			__out x; 											\
156		} 														\
157	}
158
159	#define PRINT_INDENT() { 									\
160		{														\
161			int32 _level = _get_debug_indent_level();			\
162			for (int32 i = 0; i < _level-_debugHelper.TabCount(); i++) {				\
163				__out(" ");										\
164			}													\
165		}														\
166	}
167
168	#define PRINT_DIVIDER()	\
169		PRINT_INDENT(); 	\
170		SIMPLE_PRINT(("------------------------------------------------------------\n"));
171
172	#define DUMP(object)				\
173		{								\
174			(object).dump();			\
175		}
176
177	#define PDUMP(objectPointer)		\
178		{								\
179			(objectPointer)->dump();	\
180		}
181
182	#define REPORT_ERROR(error) {											\
183		LPRINT(("returning error 0x%lx, `%s'\n", error, strerror(error)));	\
184	}
185
186	#define RETURN_ERROR(error) { 		\
187		status_t _status = error; 		\
188		if (_status < (status_t)B_OK)	\
189			REPORT_ERROR(_status);		\
190		return _status;					\
191	}
192
193	#define RETURN(error) { 										\
194		status_t _status = error; 									\
195		if (_status < (status_t)B_OK) {								\
196			REPORT_ERROR(_status); 									\
197		} else if (_status == (status_t)B_OK) {						\
198			LPRINT(("returning B_OK\n"));							\
199		} else {													\
200			LPRINT(("returning 0x%lx = %ld\n", _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	#define DUMP(x) ;
230#endif	// ifdef DEBUG else
231
232#define TRACE(x) DBG(dprintf x)
233
234// These macros turn on or off extensive and generally unnecessary
235// debugging output regarding table of contents parsing
236//#define WARN(x) (dprintf x)
237//#define WARN(x)
238#define WARN(x) DBG(dprintf x)
239
240#endif	// _UDF_DEBUG_H
241