⛏️ index : haiku.git

//----------------------------------------------------------------------
//  This software is part of the Haiku distribution and is covered
//  by the MIT License.
//
//  This version copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net
//  Initial version copyright (c) 2002 Axel DΓΆrfler, axeld@pinc-software.de
//	dbg_printf() function copyright (c) 2003 Ingo Weinhold, bonefish@cs.tu-berlin.edu
//----------------------------------------------------------------------
#ifndef _UDF_DEBUG_H
#define _UDF_DEBUG_H

/*! \file Debug.h

	Handy debugging macros.
*/

#include <KernelExport.h>

#include <OS.h>
#ifdef DEBUG
//#	include <string.h>
#endif
#include <unistd.h>


#define DEBUG_TO_FILE 0

#	include <stdio.h>
#if DEBUG_TO_FILE
//#	include <stdio.h>
#	include <stdarg.h>
extern "C" int 	vsprintf(char *s, const char *format, va_list arg);
#	include <fcntl.h>
#	define __out dbg_printf
	void dbg_printf(const char *format,...);
	void initialize_debugger(const char *filename);
#else
#	if !_KERNEL_MODE
//#		include <stdio.h>
#		define __out printf
#	else
//#		include <null.h>
#		define __out dprintf
#	endif
#	include <stdio.h>
#	include <malloc.h>
//#	define __out printf
#endif

class DebugHelper;

int32 _get_debug_indent_level();

/*! \brief Helper class that is allocated on the stack by
	the \c DEBUG_INIT() macro. On creation, it increases the
	current indentation level by the amount specified via its
	constructor's \c tabCount parameter; on destruction, it
	decreases it.
*/
class DebugHelper
{
public:
	DebugHelper(const char *className = NULL, uint8 tabCount = 1);
	~DebugHelper();

	uint8 TabCount() const { return fTabCount; }
	const char* ClassName() const { return fClassName; }

private:
	uint8 fTabCount;
	char *fClassName;
};

//----------------------------------------------------------------------
// NOTE: See Debug.cpp for complete descriptions of the following
// debug macros.
//----------------------------------------------------------------------


//----------------------------------------------------------------------
// DEBUG-independent macros
//----------------------------------------------------------------------
#define INFORM(x) { __out("udf: "); __out x; }
#if !_KERNEL_MODE
#	define DIE(x) debugger x
#else
#	define DIE(x) kernel_debugger x
#endif

//----------------------------------------------------------------------
// DEBUG-dependent macros
//----------------------------------------------------------------------
#ifdef DEBUG
	#if DEBUG_TO_FILE
		#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) initialize_debugger(filename);
	#else
		#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) ;
	#endif

	#define DEBUG_INIT_SILENT(className)			\
		DebugHelper _debugHelper(className, 2);

	#define DEBUG_INIT(className)		\
		DEBUG_INIT_SILENT(className);	\
		PRINT(("\n"));

	#define DEBUG_INIT_ETC(className, arguments)							\
		DEBUG_INIT_SILENT(className)										\
		{																	\
			PRINT_INDENT();													\
			if (_debugHelper.ClassName()) {									\
				__out("udf: %s::%s(", 									\
				      _debugHelper.ClassName(), __FUNCTION__);				\
			} else 	{														\
				__out("udf: %s(", __FUNCTION__);						\
			}																\
			__out arguments;												\
			__out("):\n");													\
		}

	#define DUMP_INIT(className)	\
		DEBUG_INIT_SILENT(className);

	#define PRINT(x) { 														\
		{																	\
			PRINT_INDENT();													\
			if (_debugHelper.ClassName()) {									\
				__out("udf: %s::%s(): ", 								\
				      _debugHelper.ClassName(), __FUNCTION__);				\
			} else 	{														\
				__out("udf: %s(): ",  __FUNCTION__);					\
			}																\
			__out x; 														\
		} 																	\
	}

	#define LPRINT(x) { 													\
		{																	\
			PRINT_INDENT();													\
			if (_debugHelper.ClassName()) {									\
				__out("udf: %s::%s(): line %d: ", 						\
				      _debugHelper.ClassName(), __FUNCTION__, __LINE__);	\
			} else {														\
				__out("udf: %s(): line %d: ", 							\
				      __FUNCTION__, __LINE__);								\
			}																\
			__out x;														\
		} 																	\
	}

	#define SIMPLE_PRINT(x) { 									\
		{														\
			__out x; 											\
		} 														\
	}

	#define PRINT_INDENT() { 									\
		{														\
			int32 _level = _get_debug_indent_level();			\
			for (int32 i = 0; i < _level-_debugHelper.TabCount(); i++) {				\
				__out(" ");										\
			}													\
		}														\
	}

	#define PRINT_DIVIDER()	\
		PRINT_INDENT(); 	\
		SIMPLE_PRINT(("------------------------------------------------------------\n"));

	#define DUMP(object)				\
		{								\
			(object).dump();			\
		}

	#define PDUMP(objectPointer)		\
		{								\
			(objectPointer)->dump();	\
		}

	#define REPORT_ERROR(error) {									\
		LPRINT(("returning error 0x%" B_PRIx32 ", `%s'\n", error,	\
			strerror(error)));										\
	}

	#define RETURN_ERROR(error) { 		\
		status_t _status = error; 		\
		if (_status < (status_t)B_OK)	\
			REPORT_ERROR(_status);		\
		return _status;					\
	}

	#define RETURN(error) { 										\
		status_t _status = error; 									\
		if (_status < (status_t)B_OK) {								\
			REPORT_ERROR(_status); 									\
		} else if (_status == (status_t)B_OK) {						\
			LPRINT(("returning B_OK\n"));							\
		} else {													\
			LPRINT(("returning 0x%" B_PRIx32 " = %" PRId32 "\n",	\
				_status, _status));									\
		}															\
		return _status; 											\
	}

	#define FATAL(x) { 								\
		PRINT(("fatal error: ")); SIMPLE_PRINT(x);	\
	}

	#define DBG(x) x ;

#else	// ifdef DEBUG
	#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) ;
	#define DEBUG_INIT_SILENT(className)	;
	#define DEBUG_INIT(className) ;
	#define DEBUG_INIT_ETC(className, arguments) ;
	#define DUMP_INIT(className)	;
	#define PRINT(x) ;
	#define LPRINT(x) ;
	#define SIMPLE_PRINT(x) ;
	#define PRINT_INDENT(x) ;
	#define PRINT_DIVIDER()	;
	#define DUMP(object) ;
	#define PDUMP(objectPointer) ;
	#define REPORT_ERROR(status) ;
	#define RETURN_ERROR(status) return status;
	#define RETURN(status) return status;
	#define FATAL(x) { __out("udf: fatal error: "); __out x; }
	#define DBG(x) ;
#endif	// ifdef DEBUG else

#define TRACE(x) /*dprintf x*/

#ifdef TEST_HAIKU
	#define TRACE_ERROR(x) printf x
#else
	#define TRACE_ERROR(x) dprintf x
#endif

// These macros turn on or off extensive and generally unnecessary
// debugging output regarding table of contents parsing
//#define WARN(x) (dprintf x)
//#define WARN(x)
#define WARN(x) DBG(dprintf x)

#endif	// _UDF_DEBUG_H