2 * Debugging macros, DUK_DPRINT() and its variants in particular.
4 * DUK_DPRINT() allows formatted debug prints, and supports standard
5 * and Duktape specific formatters. See duk_debug_vsnprintf.c for details.
7 * DUK_D(x), DUK_DD(x), and DUK_DDD(x) are used together with log macros
8 * for technical reasons. They are concretely used to hide 'x' from the
9 * compiler when the corresponding log level is disabled. This allows
10 * clean builds on non-C99 compilers, at the cost of more verbose code.
13 * DUK_D(DUK_DPRINT("foo"));
14 * DUK_DD(DUK_DDPRINT("foo"));
15 * DUK_DDD(DUK_DDDPRINT("foo"));
17 * This approach is preferable to the old "double parentheses" hack because
18 * double parentheses make the C99 solution worse: __FILE__ and __LINE__ can
19 * no longer be added transparently without going through globals, which
20 * works poorly with threading.
23 #ifndef DUK_DEBUG_H_INCLUDED
24 #define DUK_DEBUG_H_INCLUDED
28 #if defined(DUK_USE_DPRINT)
31 #define DUK_D(x) do { } while (0) /* omit */
34 #if defined(DUK_USE_DDPRINT)
37 #define DUK_DD(x) do { } while (0) /* omit */
40 #if defined(DUK_USE_DDDPRINT)
43 #define DUK_DDD(x) do { } while (0) /* omit */
47 * Exposed debug macros: debugging enabled
50 #define DUK_LEVEL_DEBUG 1
51 #define DUK_LEVEL_DDEBUG 2
52 #define DUK_LEVEL_DDDEBUG 3
54 #ifdef DUK_USE_VARIADIC_MACROS
56 /* Note: combining __FILE__, __LINE__, and __func__ into fmt would be
57 * possible compile time, but waste some space with shared function names.
59 #define DUK__DEBUG_LOG(lev,...) duk_debug_log((duk_small_int_t) (lev), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, DUK_FUNC_MACRO, __VA_ARGS__);
61 #define DUK_DPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DEBUG, __VA_ARGS__)
63 #ifdef DUK_USE_DDPRINT
64 #define DUK_DDPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DDEBUG, __VA_ARGS__)
66 #define DUK_DDPRINT(...)
69 #ifdef DUK_USE_DDDPRINT
70 #define DUK_DDDPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DDDEBUG, __VA_ARGS__)
72 #define DUK_DDDPRINT(...)
75 #else /* DUK_USE_VARIADIC_MACROS */
77 #define DUK__DEBUG_STASH(lev) \
78 (void) DUK_SNPRINTF(duk_debug_file_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FILE_MACRO), \
79 duk_debug_file_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0; \
80 (void) DUK_SNPRINTF(duk_debug_line_stash, DUK_DEBUG_STASH_SIZE, "%ld", (long) DUK_LINE_MACRO), \
81 duk_debug_line_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0; \
82 (void) DUK_SNPRINTF(duk_debug_func_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FUNC_MACRO), \
83 duk_debug_func_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0; \
84 (void) (duk_debug_level_stash = (lev))
86 /* Without variadic macros resort to comma expression trickery to handle debug
87 * prints. This generates a lot of harmless warnings. These hacks are not
88 * needed normally because DUK_D() and friends will hide the entire debug log
89 * statement from the compiler.
93 #define DUK_DPRINT DUK__DEBUG_STASH(DUK_LEVEL_DEBUG), (void) duk_debug_log /* args go here in parens */
95 #define DUK_DPRINT 0 && /* args go here as a comma expression in parens */
98 #ifdef DUK_USE_DDPRINT
99 #define DUK_DDPRINT DUK__DEBUG_STASH(DUK_LEVEL_DDEBUG), (void) duk_debug_log /* args go here in parens */
101 #define DUK_DDPRINT 0 && /* args */
104 #ifdef DUK_USE_DDDPRINT
105 #define DUK_DDDPRINT DUK__DEBUG_STASH(DUK_LEVEL_DDDEBUG), (void) duk_debug_log /* args go here in parens */
107 #define DUK_DDDPRINT 0 && /* args */
110 #endif /* DUK_USE_VARIADIC_MACROS */
112 #else /* DUK_USE_DEBUG */
115 * Exposed debug macros: debugging disabled
118 #define DUK_D(x) do { } while (0) /* omit */
119 #define DUK_DD(x) do { } while (0) /* omit */
120 #define DUK_DDD(x) do { } while (0) /* omit */
122 #ifdef DUK_USE_VARIADIC_MACROS
124 #define DUK_DPRINT(...)
125 #define DUK_DDPRINT(...)
126 #define DUK_DDDPRINT(...)
128 #else /* DUK_USE_VARIADIC_MACROS */
130 #define DUK_DPRINT 0 && /* args go here as a comma expression in parens */
131 #define DUK_DDPRINT 0 && /* args */
132 #define DUK_DDDPRINT 0 && /* args */
134 #endif /* DUK_USE_VARIADIC_MACROS */
136 #endif /* DUK_USE_DEBUG */
143 struct duk_fixedbuffer
{
147 duk_bool_t truncated
;
156 DUK_INTERNAL_DECL duk_int_t
duk_debug_vsnprintf(char *str
, duk_size_t size
, const char *format
, va_list ap
);
158 DUK_INTERNAL_DECL duk_int_t
duk_debug_snprintf(char *str
, duk_size_t size
, const char *format
, ...);
160 DUK_INTERNAL_DECL
void duk_debug_format_funcptr(char *buf
, duk_size_t buf_size
, duk_uint8_t
*fptr
, duk_size_t fptr_size
);
162 #ifdef DUK_USE_VARIADIC_MACROS
163 DUK_INTERNAL_DECL
void duk_debug_log(duk_small_int_t level
, const char *file
, duk_int_t line
, const char *func
, const char *fmt
, ...);
164 #else /* DUK_USE_VARIADIC_MACROS */
165 /* parameter passing, not thread safe */
166 #define DUK_DEBUG_STASH_SIZE 128
167 #if !defined(DUK_SINGLE_FILE)
168 DUK_INTERNAL_DECL
char duk_debug_file_stash
[DUK_DEBUG_STASH_SIZE
];
169 DUK_INTERNAL_DECL
char duk_debug_line_stash
[DUK_DEBUG_STASH_SIZE
];
170 DUK_INTERNAL_DECL
char duk_debug_func_stash
[DUK_DEBUG_STASH_SIZE
];
171 DUK_INTERNAL_DECL duk_small_int_t duk_debug_level_stash
;
173 DUK_INTERNAL_DECL
void duk_debug_log(const char *fmt
, ...);
174 #endif /* DUK_USE_VARIADIC_MACROS */
176 DUK_INTERNAL_DECL
void duk_fb_put_bytes(duk_fixedbuffer
*fb
, const duk_uint8_t
*buffer
, duk_size_t length
);
177 DUK_INTERNAL_DECL
void duk_fb_put_byte(duk_fixedbuffer
*fb
, duk_uint8_t x
);
178 DUK_INTERNAL_DECL
void duk_fb_put_cstring(duk_fixedbuffer
*fb
, const char *x
);
179 DUK_INTERNAL_DECL
void duk_fb_sprintf(duk_fixedbuffer
*fb
, const char *fmt
, ...);
180 DUK_INTERNAL_DECL
void duk_fb_put_funcptr(duk_fixedbuffer
*fb
, duk_uint8_t
*fptr
, duk_size_t fptr_size
);
181 DUK_INTERNAL_DECL duk_bool_t
duk_fb_is_full(duk_fixedbuffer
*fb
);
183 #endif /* DUK_USE_DEBUG */
185 #endif /* DUK_DEBUG_H_INCLUDED */