Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2008 VMware, Inc.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. /**
  29.  * @file
  30.  * Cross-platform debugging helpers.
  31.  *
  32.  * For now it just has assert and printf replacements, but it might be extended
  33.  * with stack trace reports and more advanced logging in the near future.
  34.  *
  35.  * @author Jose Fonseca <jfonseca@vmware.com>
  36.  */
  37.  
  38. #ifndef U_DEBUG_H_
  39. #define U_DEBUG_H_
  40.  
  41.  
  42. #include "os/os_misc.h"
  43.  
  44. #include "pipe/p_format.h"
  45.  
  46.  
  47. #ifdef  __cplusplus
  48. extern "C" {
  49. #endif
  50.  
  51.  
  52. #if defined(__GNUC__)
  53. #define _util_printf_format(fmt, list) __attribute__ ((format (printf, fmt, list)))
  54. #else
  55. #define _util_printf_format(fmt, list)
  56. #endif
  57.  
  58. void _debug_vprintf(const char *format, va_list ap);
  59.    
  60.  
  61. static INLINE void
  62. _debug_printf(const char *format, ...)
  63. {
  64.    va_list ap;
  65.    va_start(ap, format);
  66.    _debug_vprintf(format, ap);
  67.    va_end(ap);
  68. }
  69.  
  70.  
  71. /**
  72.  * Print debug messages.
  73.  *
  74.  * The actual channel used to output debug message is platform specific. To
  75.  * avoid misformating or truncation, follow these rules of thumb:
  76.  * - output whole lines
  77.  * - avoid outputing large strings (512 bytes is the current maximum length
  78.  * that is guaranteed to be printed in all platforms)
  79.  */
  80. #if !defined(PIPE_OS_HAIKU)
  81. static INLINE void
  82. debug_printf(const char *format, ...) _util_printf_format(1,2);
  83.  
  84. static INLINE void
  85. debug_printf(const char *format, ...)
  86. {
  87. #ifdef DEBUG
  88.    va_list ap;
  89.    va_start(ap, format);
  90.    _debug_vprintf(format, ap);
  91.    va_end(ap);
  92. #else
  93.    (void) format; /* silence warning */
  94. #endif
  95. }
  96. #else /* is Haiku */
  97. /* Haiku provides debug_printf in libroot with OS.h */
  98. #include <OS.h>
  99. #endif
  100.  
  101.  
  102. /*
  103.  * ... isn't portable so we need to pass arguments in parentheses.
  104.  *
  105.  * usage:
  106.  *    debug_printf_once(("answer: %i\n", 42));
  107.  */
  108. #define debug_printf_once(args) \
  109.    do { \
  110.       static boolean once = TRUE; \
  111.       if (once) { \
  112.          once = FALSE; \
  113.          debug_printf args; \
  114.       } \
  115.    } while (0)
  116.  
  117.  
  118. #ifdef DEBUG
  119. #define debug_vprintf(_format, _ap) _debug_vprintf(_format, _ap)
  120. #else
  121. #define debug_vprintf(_format, _ap) ((void)0)
  122. #endif
  123.  
  124.  
  125. #ifdef DEBUG
  126. /**
  127.  * Dump a blob in hex to the same place that debug_printf sends its
  128.  * messages.
  129.  */
  130. void debug_print_blob( const char *name, const void *blob, unsigned size );
  131.  
  132. /* Print a message along with a prettified format string
  133.  */
  134. void debug_print_format(const char *msg, unsigned fmt );
  135. #else
  136. #define debug_print_blob(_name, _blob, _size) ((void)0)
  137. #define debug_print_format(_msg, _fmt) ((void)0)
  138. #endif
  139.  
  140.  
  141. /**
  142.  * Disable interactive error message boxes.
  143.  *
  144.  * Should be called as soon as possible for effectiveness.
  145.  */
  146. void
  147. debug_disable_error_message_boxes(void);
  148.  
  149.  
  150. /**
  151.  * Hard-coded breakpoint.
  152.  */
  153. #ifdef DEBUG
  154. #define debug_break() os_break()
  155. #else /* !DEBUG */
  156. #define debug_break() ((void)0)
  157. #endif /* !DEBUG */
  158.  
  159.  
  160. long
  161. debug_get_num_option(const char *name, long dfault);
  162.  
  163. #ifdef _MSC_VER
  164. __declspec(noreturn)
  165. #endif
  166. void _debug_assert_fail(const char *expr,
  167.                         const char *file,
  168.                         unsigned line,
  169.                         const char *function)
  170. #ifdef __GNUC__
  171.    __attribute__((__noreturn__))
  172. #endif
  173. ;
  174.  
  175.  
  176. /**
  177.  * Assert macro
  178.  *
  179.  * Do not expect that the assert call terminates -- errors must be handled
  180.  * regardless of assert behavior.
  181.  *
  182.  * For non debug builds the assert macro will expand to a no-op, so do not
  183.  * call functions with side effects in the assert expression.
  184.  */
  185. #ifdef DEBUG
  186. #define debug_assert(expr) ((expr) ? (void)0 : _debug_assert_fail(#expr, __FILE__, __LINE__, __FUNCTION__))
  187. #else
  188. #define debug_assert(expr) (void)(0 && (expr))
  189. #endif
  190.  
  191.  
  192. /** Override standard assert macro */
  193. #ifdef assert
  194. #undef assert
  195. #endif
  196. #define assert(expr) debug_assert(expr)
  197.  
  198.  
  199. /**
  200.  * Output the current function name.
  201.  */
  202. #ifdef DEBUG
  203. #define debug_checkpoint() \
  204.    _debug_printf("%s\n", __FUNCTION__)
  205. #else
  206. #define debug_checkpoint() \
  207.    ((void)0)
  208. #endif
  209.  
  210.  
  211. /**
  212.  * Output the full source code position.
  213.  */
  214. #ifdef DEBUG
  215. #define debug_checkpoint_full() \
  216.    _debug_printf("%s:%u:%s\n", __FILE__, __LINE__, __FUNCTION__)
  217. #else
  218. #define debug_checkpoint_full() \
  219.    ((void)0)
  220. #endif
  221.  
  222.  
  223. /**
  224.  * Output a warning message. Muted on release version.
  225.  */
  226. #ifdef DEBUG
  227. #define debug_warning(__msg) \
  228.    _debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
  229. #else
  230. #define debug_warning(__msg) \
  231.    ((void)0)
  232. #endif
  233.  
  234.  
  235. /**
  236.  * Emit a warning message, but only once.
  237.  */
  238. #ifdef DEBUG
  239. #define debug_warn_once(__msg) \
  240.    do { \
  241.       static bool warned = FALSE; \
  242.       if (!warned) { \
  243.          _debug_printf("%s:%u:%s: one time warning: %s\n", \
  244.                        __FILE__, __LINE__, __FUNCTION__, __msg); \
  245.          warned = TRUE; \
  246.       } \
  247.    } while (0)
  248. #else
  249. #define debug_warn_once(__msg) \
  250.    ((void)0)
  251. #endif
  252.  
  253.  
  254. /**
  255.  * Output an error message. Not muted on release version.
  256.  */
  257. #ifdef DEBUG
  258. #define debug_error(__msg) \
  259.    _debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
  260. #else
  261. #define debug_error(__msg) \
  262.    _debug_printf("error: %s\n", __msg)
  263. #endif
  264.  
  265.  
  266. /**
  267.  * Used by debug_dump_enum and debug_dump_flags to describe symbols.
  268.  */
  269. struct debug_named_value
  270. {
  271.    const char *name;
  272.    unsigned long value;
  273.    const char *desc;
  274. };
  275.  
  276.  
  277. /**
  278.  * Some C pre-processor magic to simplify creating named values.
  279.  *
  280.  * Example:
  281.  * @code
  282.  * static const debug_named_value my_names[] = {
  283.  *    DEBUG_NAMED_VALUE(MY_ENUM_VALUE_X),
  284.  *    DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Y),
  285.  *    DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Z),
  286.  *    DEBUG_NAMED_VALUE_END
  287.  * };
  288.  *
  289.  *    ...
  290.  *    debug_printf("%s = %s\n",
  291.  *                 name,
  292.  *                 debug_dump_enum(my_names, my_value));
  293.  *    ...
  294.  * @endcode
  295.  */
  296. #define DEBUG_NAMED_VALUE(__symbol) {#__symbol, (unsigned long)__symbol, NULL}
  297. #define DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, __desc) {#__symbol, (unsigned long)__symbol, __desc}
  298. #define DEBUG_NAMED_VALUE_END {NULL, 0, NULL}
  299.  
  300.  
  301. /**
  302.  * Convert a enum value to a string.
  303.  */
  304. const char *
  305. debug_dump_enum(const struct debug_named_value *names,
  306.                 unsigned long value);
  307.  
  308. const char *
  309. debug_dump_enum_noprefix(const struct debug_named_value *names,
  310.                          const char *prefix,
  311.                          unsigned long value);
  312.  
  313.  
  314. /**
  315.  * Convert binary flags value to a string.
  316.  */
  317. const char *
  318. debug_dump_flags(const struct debug_named_value *names,
  319.                  unsigned long value);
  320.  
  321.  
  322. /**
  323.  * Function enter exit loggers
  324.  */
  325. #ifdef DEBUG
  326. int debug_funclog_enter(const char* f, const int line, const char* file);
  327. void debug_funclog_exit(const char* f, const int line, const char* file);
  328. void debug_funclog_enter_exit(const char* f, const int line, const char* file);
  329.  
  330. #define DEBUG_FUNCLOG_ENTER() \
  331.    int __debug_decleration_work_around = \
  332.       debug_funclog_enter(__FUNCTION__, __LINE__, __FILE__)
  333. #define DEBUG_FUNCLOG_EXIT() \
  334.    do { \
  335.       (void)__debug_decleration_work_around; \
  336.       debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
  337.       return; \
  338.    } while(0)
  339. #define DEBUG_FUNCLOG_EXIT_RET(ret) \
  340.    do { \
  341.       (void)__debug_decleration_work_around; \
  342.       debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
  343.       return ret; \
  344.    } while(0)
  345. #define DEBUG_FUNCLOG_ENTER_EXIT() \
  346.    debug_funclog_enter_exit(__FUNCTION__, __LINE__, __FILE__)
  347.  
  348. #else
  349. #define DEBUG_FUNCLOG_ENTER() \
  350.    int __debug_decleration_work_around
  351. #define DEBUG_FUNCLOG_EXIT() \
  352.    do { (void)__debug_decleration_work_around; return; } while(0)
  353. #define DEBUG_FUNCLOG_EXIT_RET(ret) \
  354.    do { (void)__debug_decleration_work_around; return ret; } while(0)
  355. #define DEBUG_FUNCLOG_ENTER_EXIT()
  356. #endif
  357.  
  358.  
  359. /**
  360.  * Get option.
  361.  *
  362.  * It is an alias for getenv on Linux.
  363.  *
  364.  * On Windows it reads C:\gallium.cfg, which is a text file with CR+LF line
  365.  * endings with one option per line as
  366.  *  
  367.  *   NAME=value
  368.  *
  369.  * This file must be terminated with an extra empty line.
  370.  */
  371. const char *
  372. debug_get_option(const char *name, const char *dfault);
  373.  
  374. boolean
  375. debug_get_bool_option(const char *name, boolean dfault);
  376.  
  377. long
  378. debug_get_num_option(const char *name, long dfault);
  379.  
  380. unsigned long
  381. debug_get_flags_option(const char *name,
  382.                        const struct debug_named_value *flags,
  383.                        unsigned long dfault);
  384.  
  385. #define DEBUG_GET_ONCE_BOOL_OPTION(sufix, name, dfault) \
  386. static boolean \
  387. debug_get_option_ ## sufix (void) \
  388. { \
  389.    static boolean first = TRUE; \
  390.    static boolean value; \
  391.    if (first) { \
  392.       first = FALSE; \
  393.       value = debug_get_bool_option(name, dfault); \
  394.    } \
  395.    return value; \
  396. }
  397.  
  398. #define DEBUG_GET_ONCE_NUM_OPTION(sufix, name, dfault) \
  399. static long \
  400. debug_get_option_ ## sufix (void) \
  401. { \
  402.    static boolean first = TRUE; \
  403.    static long value; \
  404.    if (first) { \
  405.       first = FALSE; \
  406.       value = debug_get_num_option(name, dfault); \
  407.    } \
  408.    return value; \
  409. }
  410.  
  411. #define DEBUG_GET_ONCE_FLAGS_OPTION(sufix, name, flags, dfault) \
  412. static unsigned long \
  413. debug_get_option_ ## sufix (void) \
  414. { \
  415.    static boolean first = TRUE; \
  416.    static unsigned long value; \
  417.    if (first) { \
  418.       first = FALSE; \
  419.       value = debug_get_flags_option(name, flags, dfault); \
  420.    } \
  421.    return value; \
  422. }
  423.  
  424.  
  425. unsigned long
  426. debug_memory_begin(void);
  427.  
  428. void
  429. debug_memory_end(unsigned long beginning);
  430.  
  431.  
  432. #ifdef DEBUG
  433. struct pipe_context;
  434. struct pipe_surface;
  435. struct pipe_transfer;
  436. struct pipe_resource;
  437.  
  438. void debug_dump_image(const char *prefix,
  439.                       enum pipe_format format, unsigned cpp,
  440.                       unsigned width, unsigned height,
  441.                       unsigned stride,
  442.                       const void *data);
  443. void debug_dump_surface(struct pipe_context *pipe,
  444.                         const char *prefix,
  445.                         struct pipe_surface *surface);  
  446. void debug_dump_texture(struct pipe_context *pipe,
  447.                         const char *prefix,
  448.                         struct pipe_resource *texture);
  449. void debug_dump_surface_bmp(struct pipe_context *pipe,
  450.                             const char *filename,
  451.                             struct pipe_surface *surface);
  452. void debug_dump_transfer_bmp(struct pipe_context *pipe,
  453.                              const char *filename,
  454.                              struct pipe_transfer *transfer, void *ptr);
  455. void debug_dump_float_rgba_bmp(const char *filename,
  456.                                unsigned width, unsigned height,
  457.                                float *rgba, unsigned stride);
  458. #else
  459. #define debug_dump_image(prefix, format, cpp, width, height, stride, data) ((void)0)
  460. #define debug_dump_surface(pipe, prefix, surface) ((void)0)
  461. #define debug_dump_surface_bmp(pipe, filename, surface) ((void)0)
  462. #define debug_dump_transfer_bmp(filename, transfer, ptr) ((void)0)
  463. #define debug_dump_float_rgba_bmp(filename, width, height, rgba, stride) ((void)0)
  464. #endif
  465.  
  466.  
  467. void
  468. debug_print_transfer_flags(const char *msg, unsigned usage);
  469.  
  470. void
  471. debug_print_bind_flags(const char *msg, unsigned usage);
  472.  
  473. void
  474. debug_print_usage_enum(const char *msg, unsigned usage);
  475.  
  476.  
  477. #ifdef  __cplusplus
  478. }
  479. #endif
  480.  
  481. #endif /* U_DEBUG_H_ */
  482.