#ifndef U_DEBUG_H_
#define U_DEBUG_H_
#include <stdarg.h>
#include <string.h>
#include "util/os_misc.h"
#include "util/detect_os.h"
#include "util/macros.h"
#if DETECT_OS_HAIKU
#include <OS.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__GNUC__)
#define _util_printf_format(fmt, list) __attribute__ ((format (printf, fmt, list)))
#else
#define _util_printf_format(fmt, list)
#endif
void _debug_vprintf(const char *format, va_list ap);
static inline void
_debug_printf(const char *format, ...)
{
va_list ap;
va_start(ap, format);
_debug_vprintf(format, ap);
va_end(ap);
}
#if !DETECT_OS_HAIKU
static inline void
debug_printf(const char *format, ...) _util_printf_format(1,2);
static inline void
debug_printf(const char *format, ...)
{
#ifdef DEBUG
va_list ap;
va_start(ap, format);
_debug_vprintf(format, ap);
va_end(ap);
#else
(void) format;
#endif
}
#endif
#define debug_printf_once(args) \
do { \
static bool once = true; \
if (once) { \
once = false; \
debug_printf args; \
} \
} while (0)
#ifdef DEBUG
#define debug_vprintf(_format, _ap) _debug_vprintf(_format, _ap)
#else
#define debug_vprintf(_format, _ap) ((void)0)
#endif
#ifdef DEBUG
void debug_print_blob( const char *name, const void *blob, unsigned size );
#else
#define debug_print_blob(_name, _blob, _size) ((void)0)
#endif
void
debug_disable_error_message_boxes(void);
#ifdef DEBUG
#define debug_break() os_break()
#else
#define debug_break() ((void)0)
#endif
long
debug_get_num_option(const char *name, long dfault);
#ifdef _MSC_VER
__declspec(noreturn)
#endif
void _debug_assert_fail(const char *expr,
const char *file,
unsigned line,
const char *function)
#if defined(__GNUC__) && !defined(DEBUG)
__attribute__((noreturn))
#endif
;
#ifndef NDEBUG
#define debug_assert(expr) ((expr) ? (void)0 : _debug_assert_fail(#expr, __FILE__, __LINE__, __FUNCTION__))
#else
#define debug_assert(expr) (void)(0 && (expr))
#endif
#ifdef assert
#undef assert
#endif
#define assert(expr) debug_assert(expr)
#ifdef DEBUG
#define debug_checkpoint() \
_debug_printf("%s\n", __FUNCTION__)
#else
#define debug_checkpoint() \
((void)0)
#endif
#ifdef DEBUG
#define debug_checkpoint_full() \
_debug_printf("%s:%u:%s\n", __FILE__, __LINE__, __FUNCTION__)
#else
#define debug_checkpoint_full() \
((void)0)
#endif
#ifdef DEBUG
#define debug_warning(__msg) \
_debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
#else
#define debug_warning(__msg) \
((void)0)
#endif
#ifdef DEBUG
#define debug_warn_once(__msg) \
do { \
static bool warned = false; \
if (!warned) { \
_debug_printf("%s:%u:%s: one time warning: %s\n", \
__FILE__, __LINE__, __FUNCTION__, __msg); \
warned = true; \
} \
} while (0)
#else
#define debug_warn_once(__msg) \
((void)0)
#endif
#ifdef DEBUG
#define debug_error(__msg) \
_debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
#else
#define debug_error(__msg) \
_debug_printf("error: %s\n", __msg)
#endif
#define pipe_debug_message(cb, type, fmt, ...) do { \
static unsigned id = 0; \
if ((cb) && (cb)->debug_message) { \
_pipe_debug_message(cb, &id, \
PIPE_DEBUG_TYPE_ ## type, \
fmt, ##__VA_ARGS__); \
} \
} while (0)
struct pipe_debug_callback;
void
_pipe_debug_message(
struct pipe_debug_callback *cb,
unsigned *id,
enum pipe_debug_type type,
const char *fmt, ...) _util_printf_format(4, 5);
struct debug_named_value
{
const char *name;
uint64_t value;
const char *desc;
};
#define DEBUG_NAMED_VALUE(__symbol) {#__symbol, (unsigned long)__symbol, NULL}
#define DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, __desc) {#__symbol, (unsigned long)__symbol, __desc}
#define DEBUG_NAMED_VALUE_END {NULL, 0, NULL}
const char *
debug_dump_enum(const struct debug_named_value *names,
unsigned long value);
const char *
debug_dump_enum_noprefix(const struct debug_named_value *names,
const char *prefix,
unsigned long value);
const char *
debug_dump_flags(const struct debug_named_value *names,
unsigned long value);
#ifdef DEBUG
int debug_funclog_enter(const char* f, const int line, const char* file);
void debug_funclog_exit(const char* f, const int line, const char* file);
void debug_funclog_enter_exit(const char* f, const int line, const char* file);
#define DEBUG_FUNCLOG_ENTER() \
int __debug_decleration_work_around = \
debug_funclog_enter(__FUNCTION__, __LINE__, __FILE__)
#define DEBUG_FUNCLOG_EXIT() \
do { \
(void)__debug_decleration_work_around; \
debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
return; \
} while(0)
#define DEBUG_FUNCLOG_EXIT_RET(ret) \
do { \
(void)__debug_decleration_work_around; \
debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
return ret; \
} while(0)
#define DEBUG_FUNCLOG_ENTER_EXIT() \
debug_funclog_enter_exit(__FUNCTION__, __LINE__, __FILE__)
#else
#define DEBUG_FUNCLOG_ENTER() \
int __debug_decleration_work_around
#define DEBUG_FUNCLOG_EXIT() \
do { (void)__debug_decleration_work_around; return; } while(0)
#define DEBUG_FUNCLOG_EXIT_RET(ret) \
do { (void)__debug_decleration_work_around; return ret; } while(0)
#define DEBUG_FUNCLOG_ENTER_EXIT()
#endif
const char *
debug_get_option(const char *name, const char *dfault);
bool
debug_get_bool_option(const char *name, bool dfault);
long
debug_get_num_option(const char *name, long dfault);
uint64_t
debug_get_flags_option(const char *name,
const struct debug_named_value *flags,
uint64_t dfault);
#define DEBUG_GET_ONCE_OPTION(suffix, name, dfault) \
static const char * \
debug_get_option_ ## suffix (void) \
{ \
static bool first = true; \
static const char * value; \
if (first) { \
first = false; \
value = debug_get_option(name, dfault); \
} \
return value; \
}
#define DEBUG_GET_ONCE_BOOL_OPTION(sufix, name, dfault) \
static bool \
debug_get_option_ ## sufix (void) \
{ \
static bool first = true; \
static bool value; \
if (first) { \
first = false; \
value = debug_get_bool_option(name, dfault); \
} \
return value; \
}
#define DEBUG_GET_ONCE_NUM_OPTION(sufix, name, dfault) \
static long \
debug_get_option_ ## sufix (void) \
{ \
static bool first = true; \
static long value; \
if (first) { \
first = false; \
value = debug_get_num_option(name, dfault); \
} \
return value; \
}
#define DEBUG_GET_ONCE_FLAGS_OPTION(sufix, name, flags, dfault) \
static unsigned long \
debug_get_option_ ## sufix (void) \
{ \
static bool first = true; \
static unsigned long value; \
if (first) { \
first = false; \
value = debug_get_flags_option(name, flags, dfault); \
} \
return value; \
}
#ifdef __cplusplus
}
#endif
#endif