From fad224dbbcdf6744e57cbf0ca235f226e37f794a Mon Sep 17 00:00:00 2001 From: Cyril Hrubis Date: Sun, 3 Mar 2013 17:16:59 +0100 Subject: [PATCH] libs: core: debug: API for custom message handler. --- demos/c_simple/Makefile | 3 +- .../GP_Debug.c => demos/c_simple/debug_handler.c | 91 +++++++++------------- include/core/GP_Debug.h | 89 +++++++++++++++++---- libs/core/GP_Context.c | 11 ++- libs/core/GP_Debug.c | 43 ++++++++-- 5 files changed, 156 insertions(+), 81 deletions(-) copy libs/core/GP_Debug.c => demos/c_simple/debug_handler.c (55%) diff --git a/demos/c_simple/Makefile b/demos/c_simple/Makefile index bca6fa2b..3e741cc5 100644 --- a/demos/c_simple/Makefile +++ b/demos/c_simple/Makefile @@ -18,7 +18,8 @@ APPS=backend_example loaders_example loaders filters_symmetry gfx_koch\ virtual_backend_example meta_data meta_data_dump tmp_file showimage\ v4l2_show v4l2_grab convolution weighted_median shapetest koch \ input_example fileview linetest randomshapetest fonttest\ - loaders_register blittest textaligntest abort sin_AA x11_windows + loaders_register blittest textaligntest abort sin_AA x11_windows\ + debug_handler ifeq ($(HAVE_LIBSDL),yes) APPS+=SDL_glue diff --git a/libs/core/GP_Debug.c b/demos/c_simple/debug_handler.c similarity index 55% copy from libs/core/GP_Debug.c copy to demos/c_simple/debug_handler.c index 75a54f3e..9623645a 100644 --- a/libs/core/GP_Debug.c +++ b/demos/c_simple/debug_handler.c @@ -16,76 +16,59 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2012 Cyril Hrubis * + * Copyright (C) 2009-2013 Cyril Hrubis * * * *****************************************************************************/ -#include +/* + + Example on custom debug message handler. -#include "GP_Debug.h" + */ -static unsigned int debug_level = GP_DEFAULT_DEBUG_LEVEL; -static int env_used = 0; +#include -void GP_SetDebugLevel(unsigned int level) +static char level_to_c(int level) { - debug_level = level; + switch (level) { + case GP_DEBUG_TODO: + return 'T'; + case GP_DEBUG_WARN: + return 'W'; + case GP_DEBUG_BUG: + return 'B'; + case GP_DEBUG_FATAL: + return 'F'; + case 0 ... 9: + return '0' + level; + default: + return 'U'; + } } -unsigned int GP_GetDebugLevel(void) +void debug_handler(const struct GP_DebugMsg *msg) { - return debug_level; + printf("%c: %s->%s():%u: %s\n", level_to_c(msg->level), msg->file, + msg->fn, msg->line, msg->msg); } -void GP_DebugPrint(int level, const char *file, const char *function, int line, - const char *fmt, ...) +int main(void) { - int i; + /* Set custom debug handler */ + GP_SetDebugHandler(debug_handler); - if (!env_used) { - char *level = getenv("GP_DEBUG"); - - env_used = 1; - - if (level != NULL) { - int new_level = atoi(level); - - if (new_level >= 0) { - debug_level = new_level; + /* Print some debug messages */ + GP_WARN("This is a warning"); + GP_FATAL("This is a fatal condition"); - GP_DEBUG(1, "Using debug level GP_DEBUG=%i " - "from enviroment variable", - debug_level); - } - } - } - - if (level > (int)debug_level) - return; + /* Turn on verbose debug and call some library functions */ + GP_SetDebugLevel(10); - for (i = 1; i < level; i++) - fputc(' ', stderr); + GP_Context *ctx = GP_ContextAlloc(1000, 1000, 1); - switch (level) { - case -3: - fprintf(stderr, "*** BUG: %s:%s():%u: ", file, function, line); - break; - case -2: - fprintf(stderr, "*** WARNING: %s:%s():%u: ", file, function, line); - break; - case -1: - fprintf(stderr, "*** TODO: %s:%s():%u: ", file, function, line); - break; - default: - fprintf(stderr, "%u: %s:%s():%u: ", - level, file, function, line); - break; - } + GP_FilterGaussianBlur(ctx, ctx, 10, 10, NULL); + + GP_ContextFree(ctx); - va_list va; - va_start(va, fmt); - vfprintf(stderr, fmt, va); - va_end(va); - - fputc('\n', stderr); + return 0; } diff --git a/include/core/GP_Debug.h b/include/core/GP_Debug.h index a09ba69a..4008bcd6 100644 --- a/include/core/GP_Debug.h +++ b/include/core/GP_Debug.h @@ -16,37 +16,63 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2012 Cyril Hrubis * + * Copyright (C) 2009-2013 Cyril Hrubis * * * *****************************************************************************/ /* - - Debug messages and debug level. Debug level is an unsigned integer. - Messages with debug level 0 are always printed (you should generally avoid - using them unless you wan't user to see the message.) + Debug message layer. - Debug level 1 should be used on object initalization and generally rare and - important events. + Many places of the library uses debug messages to report warnings, bugs, or + generally important events (i.e. context has been allocated, filter function + has been called). - Debug level > 1 is intended for more verbose reporting, like inner cycles - or loop debugging. + Debug messages are printed into the stderr and could be redirected to custom + handler. - Debug levels with negative level are special. Debug level -1 means TODO, - level -2 says WARNING while -2 means BUG (i.e. library get into unconsistent - state). + The verbosity of the messages could be changed by the debug level. The debug + level is an unsigned integer (by default set to '0') and only messages that have + debug level lower or equal to debug level are printed. + + There are few special debug message types with negative debug level (that + means that they are always printed), and as so these are used on various error + conditions, see bellow for more information. */ -#ifndef GP_DEBUG_H -#define GP_DEBUG_H +#ifndef CORE_GP_DEBUG_H +#define CORE_GP_DEBUG_H #include #include #include #include +/* + * Messages with debug level 0 are always printed (you should generally avoid + * using them unless you wan't user to see the message.) + * + * Debug level 1 should be used on object initalization and generally rare and + * important events. + * + * Debug level > 1 is intended for more verbose reporting, like inner cycles + * or loop debugging. + * + * Debug levels with negative level are special. + * + * -1 TODO - not implemented feature + * -2 WARNING - generally error that can be recovered + * -3 BUG - library gets into unconsistent state + * -4 FATAL - fatal condition, not compiled with XYZ support etc. + */ +enum GP_DebugType { + GP_DEBUG_TODO = -1, + GP_DEBUG_WARN = -2, + GP_DEBUG_BUG = -3, + GP_DEBUG_FATAL = -4, +}; + #define GP_DEFAULT_DEBUG_LEVEL 0 #define GP_DEBUG(level, ...) \ @@ -61,11 +87,40 @@ #define GP_BUG(...) \ GP_DebugPrint(-3, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__) +#define GP_FATAL(...) \ + GP_DebugPrint(-4, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__) + +void GP_DebugPrint(int level, const char *file, const char *function, int line, + const char *fmt, ...) __attribute__ ((format (printf, 5, 6))); + +/* + * Sets debug level. + */ void GP_SetDebugLevel(unsigned int level); +/* + * Returns current debug level. + */ unsigned int GP_GetDebugLevel(void); -void GP_DebugPrint(int level, const char *file, const char *function, int line, - const char *fmt, ...) __attribute__ ((format (printf, 5, 6))); -#endif /* GP_DEBUG_H */ +/* + * Custom debug message handler structure. + */ +struct GP_DebugMsg { + int level; + const char *file; + const char *fn; + unsigned int line; + const char *msg; +}; + +/* + * Sets custom debug message handler. + * + * If NULL is passed, custom handler is disabled and debug messages are printed + * into the stderr. + */ +void GP_SetDebugHandler(void (*handler)(const struct GP_DebugMsg *msg)); + +#endif /* CORE_GP_DEBUG_H */ diff --git a/libs/core/GP_Context.c b/libs/core/GP_Context.c index 6cb08a59..ff658848 100644 --- a/libs/core/GP_Context.c +++ b/libs/core/GP_Context.c @@ -47,6 +47,9 @@ GP_Context *GP_ContextAlloc(GP_Size w, GP_Size h, GP_PixelType type) uint32_t bpr = get_bpr(bpp, w); void *pixels; + GP_DEBUG(1, "Allocating context %u x %u - %s", + w, h, GP_PixelTypeName(type)); + pixels = malloc(bpr * h); context = malloc(sizeof(GP_Context)); @@ -58,10 +61,10 @@ GP_Context *GP_ContextAlloc(GP_Size w, GP_Size h, GP_PixelType type) return NULL; } - context->pixels = pixels; - context->bpp = bpp; - context->bytes_per_row = bpr; - context->offset = 0; + context->pixels = pixels; + context->bpp = bpp; + context->bytes_per_row = bpr; + context->offset = 0; context->w = w; context->h = h; diff --git a/libs/core/GP_Debug.c b/libs/core/GP_Debug.c index 75a54f3e..db1ed266 100644 --- a/libs/core/GP_Debug.c +++ b/libs/core/GP_Debug.c @@ -16,17 +16,20 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2012 Cyril Hrubis * + * Copyright (C) 2009-2013 Cyril Hrubis * * * *****************************************************************************/ #include -#include "GP_Debug.h" +#include "core/GP_Debug.h" static unsigned int debug_level = GP_DEFAULT_DEBUG_LEVEL; + static int env_used = 0; +static void (*debug_handler)(const struct GP_DebugMsg *msg) = NULL; + void GP_SetDebugLevel(unsigned int level) { debug_level = level; @@ -37,6 +40,11 @@ unsigned int GP_GetDebugLevel(void) return debug_level; } +void GP_SetDebugHandler(void (*handler)(const struct GP_DebugMsg *msg)) +{ + debug_handler = handler; +} + void GP_DebugPrint(int level, const char *file, const char *function, int line, const char *fmt, ...) { @@ -63,17 +71,42 @@ void GP_DebugPrint(int level, const char *file, const char *function, int line, if (level > (int)debug_level) return; + /* If handler is set, fill struct msg and call it */ + if (debug_handler) { + char buf[256]; + + va_list va; + va_start(va, fmt); + vsnprintf(buf, sizeof(buf), fmt, va); + va_end(va); + + struct GP_DebugMsg msg = { + .level = level, + .file = file, + .fn = function, + .line = line, + .msg = buf, + }; + + debug_handler(&msg); + + return; + } + for (i = 1; i < level; i++) fputc(' ', stderr); switch (level) { - case -3: + case GP_DEBUG_FATAL: + fprintf(stderr, "*** FATAL: %s:%s():%u: ", file, function, line); + break; + case GP_DEBUG_BUG: fprintf(stderr, "*** BUG: %s:%s():%u: ", file, function, line); break; - case -2: + case GP_DEBUG_WARN: fprintf(stderr, "*** WARNING: %s:%s():%u: ", file, function, line); break; - case -1: + case GP_DEBUG_TODO: fprintf(stderr, "*** TODO: %s:%s():%u: ", file, function, line); break; default: -- 2.11.4.GIT