fix some stupid bugs
[nobug.git] / nobug.h
blob1e0f8d2d0adcf1bf6bac437e2575d2799dba2f9e
1 /*
2 nobug.h - a small debugging library
4 Copyright (C) 2006, 2007, Christian Thaeter <ct@pipapo.org>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, contact me.
19 #ifndef NOBUG_H
20 #define NOBUG_H
22 #ifndef NOBUG_LIBNOBUG_C /* not when building libnobug */
23 #ifdef NDEBUG
24 #ifdef EBUG_ALPHA
25 #error NDEBUG incompatible with -DEBUG_ALPHA
26 #endif
27 #ifdef EBUG_BETA
28 #error NDEBUG incompatible with -DEBUG_BETA
29 #endif
30 #endif
32 #if defined(EBUG_ALPHA)
33 # define NOBUG_MODE_ALPHA 1
34 # define NOBUG_MODE_BETA 0
35 # define NOBUG_MODE_RELEASE 0
36 #elif defined(EBUG_BETA)
37 # define NOBUG_MODE_ALPHA 0
38 # define NOBUG_MODE_BETA 1
39 # define NOBUG_MODE_RELEASE 0
40 #elif defined(NDEBUG)
41 # define NOBUG_MODE_ALPHA 0
42 # define NOBUG_MODE_BETA 0
43 # define NOBUG_MODE_RELEASE 1
44 #else
45 #error no debug level and no NDEBUG defined
46 #endif
47 #endif /* NOBUG_LIBNOBUG_C */
50 HEADERS
53 #include <syslog.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <stdio.h>
58 #ifdef HAVE_EXECINFO_H
59 # ifndef NOBUG_USE_EXECINFO
60 # define NOBUG_USE_EXECINFO 1
61 # endif
62 #else
63 # undef NOBUG_USE_EXECINFO
64 # define NOBUG_USE_EXECINFO 0
65 #endif
67 #if NOBUG_USE_EXECINFO
68 #include <execinfo.h>
69 #endif
71 #if defined(HAVE_VALGRIND_VALGRIND_H) && !defined(NVALGRIND)
72 # ifndef NOBUG_USE_VALGRIND
73 # define NOBUG_USE_VALGRIND 1
74 # endif
75 #else
76 # undef NOBUG_USE_VALGRIND
77 # define NOBUG_USE_VALGRIND 0
78 #endif
80 #if NOBUG_USE_VALGRIND
81 #include <valgrind/valgrind.h>
82 #endif
84 #ifdef HAVE_PTHREAD_H
85 # ifndef NOBUG_USE_PTHREAD
86 # define NOBUG_USE_PTHREAD 1
87 # endif
88 #else
89 # undef NOBUG_USE_PTHREAD
90 # define NOBUG_USE_PTHREAD 0
91 #endif
93 #if NOBUG_USE_PTHREAD
94 #include <pthread.h>
95 #endif
98 #ifndef NOBUG_LIBNOBUG_C /* not when building libnobug */
100 MACROS
102 #if NOBUG_MODE_RELEASE==0
103 #undef assert
104 #define assert(expr) NOBUG_ASSERT(expr)
105 #endif
108 check preconditions (incoming parameters)
111 #define NOBUG_REQUIRE(expr, ...) \
112 NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_(expr, "PRECONDITION", \
113 NOBUG_LOCATION_INFO, ## __VA_ARGS__))
116 #define NOBUG_REQUIRE_DBG(expr, ...) \
117 NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_DBG_(expr, "PRECONDITION", \
118 NOBUG_LOCATION_INFO, ## __VA_ARGS__))
121 #define NOBUG_REQUIRE_IF(when, expr, ...) \
122 NOBUG_WHEN(when, NOBUG_REQUIRE(expr, ## __VA_ARGS__))
124 #define NOBUG_REQUIRE_IF_DBG(when, expr, ...) \
125 NOBUG_WHEN(when, NOBUG_REQUIRE_DBG(expr, ## __VA_ARGS__))
128 check postcondistions (computation outcomes)
130 #define NOBUG_ENSURE(expr, ...) \
131 NOBUG_MODE_SWITCH( \
132 NOBUG_ASSERT_(expr, "POSTCONDITION", \
133 NOBUG_LOCATION_INFO, ## __VA_ARGS__), \
134 NOBUG_BLOCK ( \
135 if (NOBUG_SCOPE_UNCHECKED) \
137 NOBUG_ASSERT_(expr, "POSTCONDITION", \
138 NOBUG_LOCATION_INFO, ## __VA_ARGS__); \
140 ), \
141 NOBUG_PASS \
144 #define NOBUG_ENSURE_DBG(expr, ...) \
145 NOBUG_MODE_SWITCH( \
146 NOBUG_ASSERT_DBG_(expr, "POSTCONDITION", \
147 NOBUG_LOCATION_INFO, ## __VA_ARGS__), \
148 NOBUG_BLOCK ( \
149 if (NOBUG_SCOPE_UNCHECKED) \
151 NOBUG_ASSERT_DBG_(expr, "POSTCONDITION", \
152 NOBUG_LOCATION_INFO, ## __VA_ARGS__); \
154 ), \
155 NOBUG_PASS \
158 #define NOBUG_ENSURE_IF(when, expr, ...) \
159 NOBUG_WHEN(when, NOBUG_ENSURE(expr, ## __VA_ARGS__))
161 #define NOBUG_ENSURE_IF_DBG(when, expr, ...) \
162 NOBUG_WHEN(when, NOBUG_ENSURE_DBG(expr, ## __VA_ARGS__))
166 generic assertion
169 #define NOBUG_ASSERT(expr, ...) \
170 NOBUG_IF_NOT_RELEASE( \
171 NOBUG_BLOCK ( \
172 NOBUG_ASSERT_(expr, "ASSERTION", NOBUG_LOCATION_INFO, ## __VA_ARGS__) \
175 #define NOBUG_ASSERT_DBG(expr, ...) \
176 NOBUG_IF_NOT_RELEASE( \
177 NOBUG_BLOCK ( \
178 NOBUG_ASSERT_DBG_(expr, "ASSERTION", \
179 NOBUG_LOCATION_INFO, ## __VA_ARGS__); \
180 } while(0) \
183 #define NOBUG_ASSERT_IF(when, expr, ...) \
184 NOBUG_WHEN(when, NOBUG_ASSERT(expr, ## __VA_ARGS__))
186 #define NOBUG_ASSERT_IF_DBG(when, expr, ...) \
187 NOBUG_WHEN(when, NOBUG_ASSERT_DBG(expr, ## __VA_ARGS__))
190 low level assert
192 #define NOBUG_ASSERT_(expr, what, location, ...) \
193 if (NOBUG_EXPECT_FALSE(!(expr))) \
195 NOBUG_LOG_( NOBUG_ON, LOG_EMERG, \
196 location, what, "(%s) " \
197 NOBUG_HEAD(__VA_ARGS__), \
198 #expr NOBUG_TAIL(__VA_ARGS__)); \
199 NOBUG_BACKTRACE; \
200 NOBUG_ABORT; \
203 #define NOBUG_ASSERT_DBG_(expr, what, location, ...) \
204 NOBUG_IF_DBG_ACTIVE( \
205 if (NOBUG_EXPECT_FALSE(!(expr))) \
207 NOBUG_LOG_( NOBUG_ON, LOG_EMERG, \
208 location, what, "(%s) " \
209 NOBUG_HEAD(__VA_ARGS__), \
210 #expr NOBUG_TAIL(__VA_ARGS__)); \
211 NOBUG_BACKTRACE; \
212 NOBUG_ABORT; \
215 #define NOBUG_ASSERTN_(expr, what, location, ...) \
216 if (NOBUG_EXPECT_FALSE(!(expr))) \
218 NOBUG_LOG_( NOBUG_ON, LOG_EMERG, \
219 location, what, \
220 ## __VA_ARGS__); \
221 NOBUG_BACKTRACE; \
222 NOBUG_ABORT; \
227 invariant check
230 #define NOBUG_INVARIANT(type, pointer, depth) \
231 NOBUG_MODE_SWITCH( \
232 NOBUG_BLOCK ( \
233 if (NOBUG_SCOPE_UNCHECKED) \
235 NOBUG_CAT(type,_invariant)(pointer, depth, \
236 NOBUG_LOCATION_ARGS); \
238 ), \
239 NOBUG_PASS, NOBUG_PASS \
242 #define NOBUG_INVARIANT_DBG(type, pointer, ...) \
243 NOBUG_MODE_SWITCH( \
244 NOBUG_IF_DBG_ACTIVE ( \
245 if (NOBUG_SCOPE_UNCHECKED) \
247 NOBUG_CAT(type,_invariant)(pointer, depth, NOBUG_LOCATION_ARGS); \
249 ), \
250 NOBUG_PASS, NOBUG_PASS \
253 #define NOBUG_INVARIANT_IF(when, type, pointer, ...) \
254 NOBUG_WHEN(when, NOBUG_INVARIANT(type, pointer, ## __VA_ARGS__))
256 #define NOBUG_INVARIANT_IF_DBG(when, type, pointer, ...) \
257 NOBUG_WHEN(when, NOBUG_INVARIANT_DBG(type, pointer, ## __VA_ARGS__))
259 #define NOBUG_INVARIANT_ASSERT(expr, ...) \
260 NOBUG_ASSERT_(expr, "INVARIANT", (file, line, func), ## __VA_ARGS__)
264 dumping datastructures
266 /*TODO dump-level for flags instead limits[0]*/
267 #define NOBUG_DUMP(flag, type, pointer, depth) \
268 NOBUG_IF_NOT_RELEASE( \
269 NOBUG_BLOCK( \
270 if (NOBUG_EXPECT_FALSE (NOBUG_DUMP_LEVEL <= nobug_flag_##flag.limits[0])) \
272 NOBUG_BLOCK ( \
273 NOBUG_CAT3(nobug_, type, _dump)(pointer, depth, \
274 NOBUG_LOCATION_ARGS); \
275 ); \
278 #define NOBUG_DUMP_DBG(flag, type, pointer, depth) \
279 NOBUG_IF_NOT_RELEASE( \
280 NOBUG_BLOCK( \
281 NOBUG_IF_DBG_ACTIVE ( \
282 if (NOBUG_EXPECT_FALSE(NOBUG_DUMP_LEVEL <= nobug_flag_##flag.limits[0])) \
284 NOBUG_CAT3(nobug_, type, _dump)(pointer, depth, \
285 NOBUG_LOCATION_ARGS); \
286 } ) \
289 #define NOBUG_DUMP_IF(expr, flag, type, pointer, depth) \
290 NOBUG_BLOCK ( \
291 if (NOBUG_EXPECT_FALSE(NOBUG_DUMP_LEVEL <= nobug_flag_##flag.limits[0])) \
293 if (NOBUG_EXPECT_FALSE(expr)) \
295 NOBUG_CAT3(nobug_, type,_dump)(pointer, depth, \
296 NOBUG_LOCATION_ARGS); \
300 #define NOBUG_DUMP_IF_DBG(expr, flag, type, pointer, depth) \
301 NOBUG_IF_NOT_RELEASE( \
302 NOBUG_IF_DBG_ACTIVE ( \
303 if (NOBUG_EXPECT_FALSE(NOBUG_DUMP_LEVEL <= nobug_flag_##flag.limits[0])) \
305 if (NOBUG_EXPECT_FALSE(expr)) \
307 NOBUG_CAT(nobug_, type,_dump)(pointer, depth, \
308 NOBUG_LOCATION_ARGS); \
312 #ifndef NOBUG_DUMP_LEVEL
313 #define NOBUG_DUMP_LEVEL LOG_DEBUG
314 #endif
316 #define NOBUG_DUMP_LOG(fmt, ...) \
317 NOBUG_LOG_( NOBUG_ON, NOBUG_DUMP_LEVEL, \
318 (file, line, func), "DUMP", \
319 fmt, ## __VA_ARGS__)
322 #define NOBUG_DUMP_LOG_DBG(fmt, ...) \
323 NOBUG_IF_DBG_ACTIVE ( \
324 NOBUG_LOG_( NOBUG_ON, NOBUG_DUMP_LEVEL, \
325 (file, line, func), "DUMP", \
326 fmt, ## __VA_ARGS__) \
329 #define NOBUG_DUMP_LOG_IF(expr, fmt, ...) \
330 NOBUG_BLOCK ( \
331 if (NOBUG_EXPECT_FALSE(expr)) { \
332 NOBUG_LOG_( NOBUG_ON, NOBUG_DUMP_LEVEL, \
333 (file, line, func), "DUMP", \
334 fmt, ## __VA_ARGS__) \
338 #define NOBUG_DUMP_LOG_IF_DBG(expr, fmt, ...) \
339 NOBUG_IF_DBG_ACTIVE ( \
340 if (NOBUG_EXPECT_FALSE(expr)) { \
341 NOBUG_LOG_( NOBUG_ON, NOBUG_DUMP_LEVEL, \
342 (file), line, func), "DUMP", \
343 fmt, ## __VA_ARGS__) \
349 Logging
351 #define NOBUG_LOG(flag, lvl, ...) \
352 NOBUG_BLOCK ( \
353 NOBUG_LOG_(flag, lvl, NOBUG_LOCATION_INFO, \
354 NOBUG_LVL(lvl), ## __VA_ARGS__); \
357 #define NOBUG_LOG_DBG(flag, lvl, ...) \
358 NOBUG_IF_DBG_ACTIVE ( \
359 NOBUG_LOG_(flag, lvl, NOBUG_LOCATION_INFO, \
360 NOBUG_LVL(lvl), ## __VA_ARGS__); \
363 #define NOBUG_LOG_IF(expr, flag, lvl, ...) \
364 NOBUG_BLOCK ( \
365 if (NOBUG_EXPECT_FALSE(expr)) { \
366 NOBUG_LOG_(flag, lvl, NOBUG_LOCATION_INFO, \
367 NOBUG_LVL(lvl), ## __VA_ARGS__); \
371 #define NOBUG_LOG_IF_DBG(expr, flag, lvl, ...) \
372 NOBUG_IF_DBG_ACTIVE ( \
373 if (NOBUG_EXPECT_FALSE(expr)) { \
374 NOBUG_LOG_(flag, lvl, NOBUG_LOCATION_INFO, \
375 NOBUG_LVL(lvl), ## __VA_ARGS__); \
379 #define NOBUG_LVL(lvl) NOBUG_LVL_##lvl
380 #define NOBUG_LVL_0 "EMERG"
381 #define NOBUG_LVL_1 "ALERT"
382 #define NOBUG_LVL_2 "CRIT"
383 #define NOBUG_LVL_3 "ERR"
384 #define NOBUG_LVL_4 "WARNING"
385 #define NOBUG_LVL_5 "NOTICE"
386 #define NOBUG_LVL_6 "INFO"
387 #define NOBUG_LVL_7 "TRACE"
391 low level logging handler
393 #define NOBUG_LOG_(flag, lvl, location, what, ...) \
394 if (NOBUG_EXPECT_FALSE(lvl <= NOBUG_FLAG(flag).limits[NOBUG_TARGET_RINGBUFFER])) \
396 NOBUG_LOCKED ( \
397 char * log = nobug_ringbuffer_pos (NOBUG_FLAG(flag).ringbuffer_target); \
398 nobug_ringbuffer_printf(NOBUG_FLAG(flag).ringbuffer_target, \
399 "%s:%d: %s:"NOBUG_THREAD_ID_FMT(" ",":")" %s: "NOBUG_HEAD(__VA_ARGS__), \
400 NOBUG_LOCATION_FILE location, NOBUG_LOCATION_LINE location, \
401 what NOBUG_THREAD_ID_COMMA, NOBUG_LOCATION_FUNC location NOBUG_TAIL(__VA_ARGS__)); \
402 if (NOBUG_EXPECT_FALSE(lvl <= NOBUG_FLAG(flag).limits[NOBUG_TARGET_CONSOLE])){ \
403 NOBUG_MODE_SWITCH ( \
404 NOBUG_IF(NOBUG_USE_VALGRIND, \
405 if (NOBUG_EXPECT_FALSE (NOBUG_DBG_ACTIVE)) { \
406 VALGRIND_PRINTF ("%s\n", log); \
407 } else ) { \
408 fprintf(NOBUG_FLAG(flag).console_target?NOBUG_FLAG(flag).console_target:stderr, \
409 "%s\n", log); \
410 }, \
411 fprintf(NOBUG_FLAG(flag).console_target?NOBUG_FLAG(flag).console_target:stderr, \
412 "%s\n", log); \
414 fprintf(NOBUG_FLAG(flag).console_target?NOBUG_FLAG(flag).console_target:stderr, \
415 "%s\n", log); \
416 )}; \
417 if (NOBUG_EXPECT_FALSE(lvl <= NOBUG_FLAG(flag).limits[NOBUG_TARGET_FILE] \
418 && NOBUG_FLAG(flag).file_target)){ \
419 fprintf(NOBUG_FLAG(flag).file_target, "%s\n", log); \
420 }; \
421 if (NOBUG_EXPECT_FALSE(lvl <= NOBUG_FLAG(flag).limits[NOBUG_TARGET_SYSLOG])){ \
422 syslog(lvl, "%s\n", log); \
423 }; \
426 /* TODO
428 NOBUG_IF(NOBUG_USE_XXXX_TARGET ...
430 NOBUG_TARGET_APPLICATION
433 #define NOBUG_LOCATION_ARGS NOBUG_BASENAME(__FILE__), __LINE__, __func__
434 #define NOBUG_LOCATION_INFO (NOBUG_LOCATION_ARGS)
436 #define NOBUG_LOCATION_FILE(file, _1, _2) file
437 #define NOBUG_LOCATION_LINE(_1, line, _2) line
438 #define NOBUG_LOCATION_FUNC(_1, _2, func) func
441 /*TODO better location handling, no text? empty on RELEASE*/
442 #define NOBUG_LOCATION(text) \
443 NOBUG_MODE_SWITCH( \
444 NOBUG_BASENAME(__FILE__ ":" NOBUG_STRINGIZE(__LINE__) text), \
445 NOBUG_BASENAME(__FILE__ ":" NOBUG_STRINGIZE(__LINE__) text), \
446 "" \
449 #define NOBUG_ERROR(flag, ...) \
450 NOBUG_LOG(flag, LOG_ERR, ## __VA_ARGS__)
451 #define NOBUG_ERROR_IF(expr, flag, ...) \
452 NOBUG_LOG_IF(expr, flag, LOG_ERR, ## __VA_ARGS__)
453 #define NOBUG_ERROR_DBG(flag, ...) \
454 NOBUG_LOG_DBG(flag, LOG_ERR, ## __VA_ARGS__)
455 #define NOBUG_ERROR_IF_DBG(expr, flag, ...) \
456 NOBUG_LOG_IF_DBG(expr, flag, LOG_ERR, ## __VA_ARGS__)
458 #define NOBUG_WARN(flag, ...) \
459 NOBUG_LOG(flag, LOG_WARNING, ## __VA_ARGS__)
460 #define NOBUG_WARN_IF(expr, flag, ...) \
461 NOBUG_LOG_IF(expr, flag, LOG_WARNING, ## __VA_ARGS__)
462 #define NOBUG_WARN_DBG(flag, ...) \
463 NOBUG_LOG_DBG(flag, LOG_WARNING, ## __VA_ARGS__)
464 #define NOBUG_WARN_IF_DBG(expr, flag, ...) \
465 NOBUG_LOG_IF_DBG(expr, flag, LOG_WARNING, ## __VA_ARGS__)
467 #define NOBUG_INFO(flag, ...) \
468 NOBUG_LOG(flag, LOG_INFO, ## __VA_ARGS__)
469 #define NOBUG_INFO_IF(expr, flag, ...) \
470 NOBUG_LOG_IF(expr, flag, LOG_INFO, ## __VA_ARGS__)
471 #define NOBUG_INFO_DBG(flag, ...) \
472 NOBUG_LOG_DBG(flag, LOG_INFO, ## __VA_ARGS__)
473 #define NOBUG_INFO_IF_DBG(expr, flag, ...) \
474 NOBUG_LOG_IF_DBG(expr, flag, LOG_INFO, ## __VA_ARGS__)
476 #define NOBUG_NOTICE(flag, ...) \
477 NOBUG_LOG(flag, LOG_NOTICE, ## __VA_ARGS__)
478 #define NOBUG_NOTICE_IF(expr, flag, ...) \
479 NOBUG_LOG_IF(expr, flag, LOG_NOTICE, ## __VA_ARGS__)
480 #define NOBUG_NOTICE_DBG(flag, ...) \
481 NOBUG_LOG_DBG(flag, LOG_NOTICE, ## __VA_ARGS__)
482 #define NOBUG_NOTICE_IF_DBG(expr, flag, ...) \
483 NOBUG_LOG_IF_DBG(expr, flag, LOG_NOTICE, ## __VA_ARGS__)
485 #define NOBUG_TRACE(flag, ...) \
486 NOBUG_LOG(flag, LOG_DEBUG, ## __VA_ARGS__)
487 #define NOBUG_TRACE_IF(expr, flag, ...) \
488 NOBUG_LOG_IF(expr, flag, LOG_DEBUG, ## __VA_ARGS__)
489 #define NOBUG_TRACE_DBG(flag, ...) \
490 NOBUG_LOG_DBG(flag, LOG_DEBUG, ## __VA_ARGS__)
491 #define NOBUG_TRACE_IF_DBG(expr, flag, ...) \
492 NOBUG_LOG_IF_DBG(expr, flag, LOG_DEBUG, ## __VA_ARGS__)
494 #define NOBUG_BASENAME(name) (strrchr((name), '/')?strrchr((name), '/') + 1 : (name))
496 #define NOBUG_SCOPE_UNCHECKED NOBUG_CHECKED_VALUE == 0
498 #define NOBUG_DBG_ACTIVE \
499 NOBUG_IF(NOBUG_USE_VALGRIND, (RUNNING_ON_VALGRIND?2:0)) \
500 NOBUG_IFNOT(NOBUG_USE_VALGRIND, (0))
503 alpha beta release
504 unchecked Preconditions, Postconditions, Invariants Preconditions, Postconditions compiling will abort
505 checked Preconditions, Postconditions Preconditions
508 #define NOBUG_CHECKED NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=1})
510 #define NOBUG_UNCHECKED \
511 NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=0}) \
512 NOBUG_IF(NOBUG_MODE_RELEASE, NOBUG_UNCHECKED_NOT_ALLOWED_IN_RELEASE_BUILD)
514 #define NOBUG_ABORT abort()
516 #define NOBUG_DBG_GDB 1
517 #define NOBUG_DBG_VALGRIND 2
519 #define NOBUG_BACKTRACE \
520 NOBUG_MODE_SWITCH( \
521 switch (NOBUG_DBG_ACTIVE) { \
522 case NOBUG_DBG_VALGRIND: \
523 NOBUG_BACKTRACE_VALGRIND; \
524 break; \
525 default: \
526 NOBUG_BACKTRACE_GLIBC; \
527 }, \
528 NOBUG_BACKTRACE_GLIBC, \
529 NOBUG_BACKTRACE_GLIBC \
532 #define NOBUG_BACKTRACE_DBG \
533 NOBUG_IF_NOT_RELEASE( \
534 switch (NOBUG_DBG_ACTIVE) { \
535 case NOBUG_DBG_VALGRIND: \
536 NOBUG_BACKTRACE_VALGRIND; \
537 break; \
540 #define NOBUG_BACKTRACE_GDB fprintf(stderr, "UNIMPLEMENTED : GDB Backtraces\n")
542 #define NOBUG_BACKTRACE_VALGRIND \
543 NOBUG_IF(NOBUG_USE_VALGRIND, \
544 VALGRIND_PRINTF_BACKTRACE("BACKTRACE : %s@%d %s", \
545 NOBUG_LOCATION_INFO))
548 #ifndef NOBUG_BACKTRACE_DEPTH
549 #define NOBUG_BACKTRACE_DEPTH 256
550 #endif
552 #define NOBUG_BACKTRACE_GLIBC \
553 NOBUG_IF_NOT_RELEASE( \
554 NOBUG_BLOCK ( \
555 NOBUG_IF(NOBUG_USE_EXECINFO, \
556 void* nobug_backtrace_buffer[NOBUG_BACKTRACE_DEPTH]; \
557 backtrace_symbols_fd (nobug_backtrace_buffer, \
558 backtrace (nobug_backtrace_buffer, NOBUG_BACKTRACE_DEPTH), 2))))
562 alpha beta release
563 DEPRECATED log nothing wont compile
565 #define NOBUG_DEPRECATED(msg) \
566 NOBUG_MODE_SWITCH( \
567 NOBUG_ONCE ( \
568 NOBUG_LOG_ (NOBUG_ON, LOG_ALERT, NOBUG_LOCATION_INFO, \
569 "DEPRECATED", msg); \
570 ), \
571 NOBUG_PASS, \
572 NOBUG_DEPRECATED_NOT_ALLOWED_IN_RELEASE_BUILD(msg) \
576 alpha beta release
577 UNIMPLEMENTED abort abort wont compile
579 #define NOBUG_UNIMPLEMENTED(msg) \
580 NOBUG_IF_NOT_RELEASE ( \
581 NOBUG_BLOCK ( \
582 NOBUG_LOG_ (NOBUG_ON, LOG_EMERG, NOBUG_LOCATION_INFO, \
583 "UNIMPLEMENTED", msg); \
584 NOBUG_ABORT; \
585 )) \
586 NOBUG_IF(NOBUG_MODE_RELEASE, NOBUG_UNIMPLEMENTED_NOT_ALLOWED_IN_RELEASE_BUILD(msg);)
589 alpha beta release
590 FIXME log wont compile wont compile
592 #define NOBUG_FIXME(msg) \
593 NOBUG_MODE_SWITCH( \
594 NOBUG_ONCE ( \
595 NOBUG_LOG_ (NOBUG_ON, LOG_ALERT, NOBUG_LOCATION_INFO, \
596 "FIXME", msg); \
597 ), \
598 NOBUG_FIXME_NOT_ALLOWED_IN_BETA_BUILD(msg), \
599 NOBUG_FIXME_NOT_ALLOWED_IN_RELEASE_BUILD(msg) \
603 alpha beta release
604 TODO log log wont compile
606 #define NOBUG_TODO(msg) \
607 NOBUG_IF_NOT_RELEASE ( \
608 NOBUG_ONCE ( \
609 NOBUG_LOG_( NOBUG_ON, LOG_CRIT, NOBUG_LOCATION_INFO, \
610 "TODO", msg); \
611 )) \
612 NOBUG_IF(NOBUG_MODE_RELEASE, NOBUG_TODO_NOT_ALLOWED_IN_RELEASE_BUILD(msg);)
615 alpha beta release
616 PLANNED log nothing nothing
618 #define NOBUG_PLANNED(msg) \
619 NOBUG_MODE_SWITCH ( \
620 NOBUG_ONCE ( \
621 NOBUG_LOG_ (NOBUG_ON, LOG_INFO, NOBUG_LOCATION_INFO, \
622 "PLANNED", msg); \
623 ), \
624 NOBUG_PASS,NOBUG_PASS \
628 alpha beta release
629 NOTREACHED abort abort nothing
631 #define NOBUG_NOTREACHED \
632 NOBUG_IF_NOT_RELEASE ( \
633 NOBUG_BLOCK ( \
634 NOBUG_LOG_( NOBUG_ON, LOG_EMERG, NOBUG_LOCATION_INFO, \
635 "NOTREACHED"); \
636 NOBUG_ABORT; \
639 NOBUG_IF(NOBUG_MODE_RELEASE, NOBUG_PASS)
643 Resource registry macros
645 #ifndef NOBUG_RESOURCE_LOGGING
646 #define NOBUG_RESOURCE_LOGGING 1
647 #endif
649 #ifndef NOBUG_RESOURCE_LOG_LEVEL
650 #define NOBUG_RESOURCE_LOG_LEVEL LOG_DEBUG
651 #endif
653 #define NOBUG_RESOURCE_HANDLE(handle) \
654 NOBUG_IF(NOBUG_MODE_ALPHA, \
655 struct nobug_resource_record* handle)
657 #define NOBUG_RESOURCE_ANNOUNCE(flag, type, name, ptr, handle) \
658 NOBUG_IF(NOBUG_MODE_ALPHA, \
659 NOBUG_ASSERTN_(handle = nobug_resource_announce (type, name, ptr, \
660 NOBUG_BASENAME(__FILE__ ":" NOBUG_STRINGIZE(__LINE__))), \
661 "RESOURCE_ANNOUNCE", NOBUG_LOCATION_INFO, "%s: %s@%p %s", \
662 type, name, ptr, nobug_resource_error) \
663 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
664 ; NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
665 "RESOURCE_ANNOUNCE", "%s: %s@%p", type, name, ptr) \
668 #define NOBUG_RESOURCE_FORGET(flag, handle) \
669 NOBUG_IF(NOBUG_MODE_ALPHA, \
670 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
671 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
672 "RESOURCE_FORGET", "%s: %s@%p", handle?handle->type:"", \
673 handle?handle->name:"", handle?handle->object_id:NULL); \
675 NOBUG_ASSERTN_(nobug_resource_forget (handle), \
676 "RESOURCE_FORGET", NOBUG_LOCATION_INFO, "%s: %s@%p: %s", \
677 handle?handle->type:"", handle?handle->name:"", \
678 handle?handle->object_id:NULL, nobug_resource_error); \
679 handle = NULL \
682 #define NOBUG_RESOURCE_ENTER(flag, resource, user, ptr, state, handle) \
683 NOBUG_IF(NOBUG_MODE_ALPHA, \
684 NOBUG_ASSERTN_(handle = nobug_resource_enter (resource, user, ptr, state, \
685 NOBUG_BASENAME(__FILE__ ":" NOBUG_STRINGIZE(__LINE__))), \
686 "RESOURCE_ENTER", NOBUG_LOCATION_INFO, "%s: %s@%p: %s@%p: %s: %s", \
687 resource?resource->type:"", resource?resource->name:"", \
688 resource?resource->object_id:NULL, \
689 user, ptr, nobug_resource_states[state], nobug_resource_error) \
690 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
691 ; NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
692 "RESOURCE_ENTER", "%s: %s@%p: %s@%p: %s", \
693 resource->type, resource->name, resource->object_id, \
694 user, ptr, nobug_resource_states[state]) \
697 #define NOBUG_RESOURCE_STATE(flag, resource, state) \
698 NOBUG_IF(NOBUG_MODE_ALPHA, \
699 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
700 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
701 "RESOURCE_STATE", "%s: %s@%p: %s@%p: %s->%s", \
702 resource?((struct nobug_resource_record*)resource->data)->type:"", \
703 resource?((struct nobug_resource_record*)resource->data)->name:"", \
704 resource?((struct nobug_resource_record*)resource->data)->object_id:"", \
705 resource?resource->name:NULL, \
706 resource?resource->object_id:NULL, \
707 resource?resource->type:"", nobug_resource_states[state]); \
709 NOBUG_ASSERTN_(nobug_resource_state (resource, state), \
710 "RESOURCE_ENTER", NOBUG_LOCATION_INFO, "%s: %s@%p: %s@%p: %s->%s: %s", \
711 resource?((struct nobug_resource_record*)resource->data)->type:"", \
712 resource?((struct nobug_resource_record*)resource->data)->name:"", \
713 resource?((struct nobug_resource_record*)resource->data)->object_id:"", \
714 resource?resource->name:NULL, \
715 resource?resource->object_id:NULL, \
716 resource?resource->type:"", nobug_resource_states[state], \
717 nobug_resource_error) \
720 #define NOBUG_RESOURCE_LEAVE(flag, handle) \
721 NOBUG_IF(NOBUG_MODE_ALPHA, \
722 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
723 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
724 "RESOURCE_LEAVE", "%s: %s@%p: %s@%p: %s", \
725 handle?((struct nobug_resource_record*)handle->data)->type:"", \
726 handle?((struct nobug_resource_record*)handle->data)->name:"", \
727 handle?((struct nobug_resource_record*)handle->data)->object_id:"", \
728 handle?handle->name:NULL, \
729 handle?handle->object_id:NULL, \
730 handle?handle->type:""); \
732 NOBUG_ASSERTN_(nobug_resource_leave (handle), \
733 "RESOURCE_LEAVE", NOBUG_LOCATION_INFO, "%s: %s@%p: %s@%p: %s: %s", \
734 handle?((struct nobug_resource_record*)handle->data)->type:"", \
735 handle?((struct nobug_resource_record*)handle->data)->name:"", \
736 handle?((struct nobug_resource_record*)handle->data)->object_id:"", \
737 handle?handle->name:NULL, \
738 handle?handle->object_id:NULL, \
739 handle?handle->type:"", \
740 nobug_resource_error); \
741 handle = NULL)
743 #define NOBUG_RESOURCE_LEAVE_LOOKUP(flag, handle, ptr) \
744 NOBUG_IF(NOBUG_MODE_ALPHA, \
745 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
746 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
747 "RESOURCE_LEAVE", "%s: %s@%p: @%p", \
748 handle?handle->type:"", \
749 handle?handle->name:"", \
750 handle?handle->object_id:"", \
751 ptr); \
753 NOBUG_ASSERTN_(nobug_resource_leave (nobug_resource_find(handle, ptr)), \
754 "RESOURCE_LEAVE", NOBUG_LOCATION_INFO, "%s: %s@%p: @%p: %s", \
755 handle?handle->type:"", \
756 handle?handle->name:"", \
757 handle?handle->object_id:"", \
758 ptr, nobug_resource_error) \
762 threading support
764 #if NOBUG_USE_PTHREAD
765 #define NOBUG_LOCK pthread_mutex_lock (&nobug_global_mutex)
766 #define NOBUG_UNLOCK pthread_mutex_unlock (&nobug_global_mutex)
768 #define NOBUG_LOCKED(code) \
769 NOBUG_LOCK; \
770 code; \
771 NOBUG_UNLOCK
774 #define NOBUG_THREAD_ID_SET(name) nobug_thread_id_set(name)
775 #define NOBUG_THREAD_ID_FMT(pre,post) pre "%s" post
776 #define NOBUG_THREAD_ID_COMMA , NOBUG_THREAD_ID_GET
777 #define NOBUG_THREAD_ID_GET nobug_thread_id_get()
779 #else
780 #define NOBUG_LOCKED(code) code
781 #define NOBUG_THREAD_ID_SET(name)
782 #define NOBUG_THREAD_ID_FMT(pre,post) ""
783 #define NOBUG_THREAD_ID_COMMA
784 #define NOBUG_THREAD_ID_GET ""
785 #endif
788 init
790 #define NOBUG_INIT nobug_init()
793 Tool macros
796 #ifdef __GNUC__
797 #define NOBUG_CLEANUP(fn) __attribute__((cleanup(fn)))
798 #else
799 #define NOBUG_CLEANUP(fn)
800 #endif
802 #define NOBUG_ONCE(code) \
803 NOBUG_BLOCK ( \
804 static int NOBUG_CAT(nobug_once_,__LINE__) = 0; \
805 if (NOBUG_EXPECT_FALSE(!NOBUG_CAT(nobug_once_,__LINE__))) \
807 NOBUG_CAT(nobug_once_,__LINE__) = 1; \
808 code; \
812 #define NOBUG_PASS ;
814 #define NOBUG_BLOCK(code) do { code; } while (0)
816 // branch prediction on bools
817 #if __GNUC__
818 #define NOBUG_EXPECT_FALSE(x) __builtin_expect(!!(x),0)
819 #else
820 #define NOBUG_EXPECT_FALSE(x) x
821 #endif
823 #define NOBUG_IF_DBG_ACTIVE(code) \
824 NOBUG_IF(NOBUG_MODE_ALPHA, \
825 NOBUG_BLOCK ( \
826 if (NOBUG_EXPECT_FALSE(NOBUG_DBG_ACTIVE)) \
828 code; \
832 NOBUG_IF(NOBUG_NOT(NOBUG_MODE_ALPHA), NOBUG_PASS)
834 #define NOBUG_WHEN(when, code) \
835 NOBUG_IF_NOT_RELEASE(do{ if (when){code;}}while(0))
837 #define NOBUG_IF_NOT_RELEASE(code) \
838 NOBUG_IF(NOBUG_NOT(NOBUG_MODE_RELEASE), code) \
839 NOBUG_IF(NOBUG_MODE_RELEASE, NOBUG_PASS)
841 #define NOBUG_MODE_SWITCH(alpha_code, beta_code, release_code) \
842 NOBUG_IF(NOBUG_MODE_ALPHA, alpha_code) \
843 NOBUG_IF(NOBUG_MODE_BETA, beta_code) \
844 NOBUG_IF(NOBUG_MODE_RELEASE, release_code)
847 Flag handling
849 #define NOBUG_FLAG(name) NOBUG_CAT(nobug_flag_,name)
851 #define NOBUG_DEFINE_FLAG(name) struct nobug_flag NOBUG_FLAG(name) = \
852 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, \
853 &nobug_default_ringbuffer, NULL,NULL}) \
854 NOBUG_IF(NOBUG_MODE_BETA, {#name, {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, \
855 &nobug_default_ringbuffer, NULL,NULL}) \
856 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERROR}, \
857 &nobug_default_ringbuffer, NULL,NULL})
859 #define NOBUG_DEFINE_FLAG_LIMIT(name, limit) struct nobug_flag NOBUG_FLAG(name) = \
860 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, \
861 &nobug_default_ringbuffer, NULL,NULL}) \
862 NOBUG_IF(NOBUG_MODE_BETA, {#name, {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, \
863 &nobug_default_ringbuffer, NULL,NULL}) \
864 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERROR}, \
865 &nobug_default_ringbuffer, NULL,NULL})
868 /*TODO better FLAG_LIMIT handling, should respect LOG_TARGET */
871 #define NOBUG_DECLARE_FLAG(name) extern struct nobug_flag NOBUG_FLAG(name)
873 #define NOBUG_INIT_FLAG(name) \
874 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, NOBUG_LOG_LIMIT)
876 #define NOBUG_INIT_FLAG_LIMIT(name, default) \
877 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, default)
879 #ifdef __cplusplus
880 #define NOBUG_CPP_DEFINE_FLAG(name) \
881 NOBUG_DEFINE_FLAG(name); \
882 static int nobug_##name##_cppinit##__LINE__ = NOBUG_INIT_FLAG(name)
884 #define NOBUG_CPP_DEFINE_FLAG_LIMIT(name, default) \
885 NOBUG_DEFINE_FLAG_LIMIT(name, default); \
886 static int nobug_##name##_cppinit##__LINE__ = NOBUG_INIT_FLAG_LIMIT(name, default)
887 #endif
889 #ifndef NOBUG_LOG_LIMIT_ALPHA
890 # define NOBUG_LOG_LIMIT_ALPHA LOG_INFO
891 #endif
892 #ifndef NOBUG_LOG_LIMIT_BETA
893 # define NOBUG_LOG_LIMIT_BETA LOG_WARNING
894 #endif
895 #ifndef NOBUG_LOG_LIMIT_RELEASE
896 # define NOBUG_LOG_LIMIT_RELEASE LOG_CRIT
897 #endif
899 #ifndef NOBUG_LOG_LIMIT
900 # define NOBUG_LOG_LIMIT \
901 NOBUG_MODE_SWITCH( \
902 NOBUG_LOG_LIMIT_ALPHA, \
903 NOBUG_LOG_LIMIT_BETA, \
904 NOBUG_LOG_LIMIT_RELEASE)
905 #endif
907 #ifndef NOBUG_LOG_TARGET_ALPHA
908 # define NOBUG_LOG_TARGET_ALPHA NOBUG_TARGET_CONSOLE
909 #endif
910 #ifndef NOBUG_LOG_TARGET_BETA
911 # define NOBUG_LOG_TARGET_BETA NOBUG_TARGET_FILE
912 #endif
913 #ifndef NOBUG_LOG_TARGET_RELEASE
914 # define NOBUG_LOG_TARGET_RELEASE NOBUG_TARGET_SYSLOG
915 #endif
917 #ifndef NOBUG_LOG_TARGET
918 # define NOBUG_LOG_TARGET \
919 NOBUG_MODE_SWITCH( \
920 NOBUG_LOG_TARGET_ALPHA, \
921 NOBUG_LOG_TARGET_BETA, \
922 NOBUG_LOG_TARGET_RELEASE)
923 #endif
925 #define NOBUG_SET_LIMIT(flag, min) \
926 NOBUG_MODE_SWITCH( \
927 NOBUG_FLAG(flag) = (min), \
928 NOBUG_FLAG(flag) = (min), \
929 NOBUG_PASS)
933 short macros without NOBUG_
935 #ifndef NOBUG_DISABLE_SHORTNAMES
936 #ifndef REQUIRE
937 #define REQUIRE NOBUG_REQUIRE
938 #endif
939 #ifndef REQUIRE_DBG
940 #define REQUIRE_DBG NOBUG_REQUIRE_DBG
941 #endif
942 #ifndef REQUIRE_IF
943 #define REQUIRE_IF NOBUG_REQUIRE_IF
944 #endif
945 #ifndef REQUIRE_IF_DBG
946 #define REQUIRE_IF_DBG NOBUG_REQUIRE_IF_DBG
947 #endif
948 #ifndef ENSURE
949 #define ENSURE NOBUG_ENSURE
950 #endif
951 #ifndef ENSURE_DBG
952 #define ENSURE_DBG NOBUG_ENSURE_DBG
953 #endif
954 #ifndef ENSURE_IF
955 #define ENSURE_IF NOBUG_ENSURE_IF
956 #endif
957 #ifndef ENSURE_IF_DBG
958 #define ENSURE_IF_DBG NOBUG_ENSURE_IF_DBG
959 #endif
960 #ifndef ASSERT
961 #define ASSERT NOBUG_ASSERT
962 #endif
963 #ifndef ASSERT_DBG
964 #define ASSERT_DBG NOBUG_ASSERT_DBG
965 #endif
966 #ifndef ASSERT_IF
967 #define ASSERT_IF NOBUG_ASSERT_IF
968 #endif
969 #ifndef ASSERT_IF_DBG
970 #define ASSERT_IF_DBG NOBUG_ASSERT_IF_DBG
971 #endif
972 #ifndef INVARIANT
973 #define INVARIANT NOBUG_INVARIANT
974 #endif
975 #ifndef INVARIANT_DBG
976 #define INVARIANT_DBG NOBUG_INVARIANT_DBG
977 #endif
978 #ifndef INVARIANT_IF
979 #define INVARIANT_IF NOBUG_INVARIANT_IF
980 #endif
981 #ifndef INVARIANT_IF_DBG
982 #define INVARIANT_IF_DBG NOBUG_INVARIANT_IF_DBG
983 #endif
984 #ifndef INVARIANT_ASSERT
985 #define INVARIANT_ASSERT NOBUG_INVARIANT_ASSERT
986 #endif
987 #ifndef DUMP
988 #define DUMP NOBUG_DUMP
989 #endif
990 #ifndef DUMP_DBG
991 #define DUMP_DBG NOBUG_DUMP_DBG
992 #endif
993 #ifndef DUMP_IF
994 #define DUMP_IF NOBUG_DUMP_IF
995 #endif
996 #ifndef DUMP_IF_DBG
997 #define DUMP_IF_DBG NOBUG_DUMP_IF_DBG
998 #endif
999 #ifndef DUMP_LOG
1000 #define DUMP_LOG NOBUG_DUMP_LOG
1001 #endif
1002 #ifndef DUMP_LOG_DBG
1003 #define DUMP_LOG_DBG NOBUG_DUMP_LOG_DBG
1004 #endif
1005 #ifndef DUMP_LOG_IF
1006 #define DUMP_LOG_IF NOBUG_DUMP_LOG_IF
1007 #endif
1008 #ifndef DUMP_LOG_IF_DBG
1009 #define DUMP_LOG_IF_DBG NOBUG_DUMP_LOG_IF_DBG
1010 #endif
1011 #ifndef LOG
1012 #define LOG NOBUG_LOG
1013 #endif
1014 #ifndef LOG_DBG
1015 #define LOG_DBG NOBUG_LOG_DBG
1016 #endif
1017 #ifndef LOG_IF
1018 #define LOG_IF NOBUG_LOG_IF
1019 #endif
1020 #ifndef LOG_IF_DBG
1021 #define LOG_IF_DBG NOBUG_LOG_IF_DBG
1022 #endif
1023 #ifndef ERROR
1024 #define ERROR NOBUG_ERROR
1025 #endif
1026 #ifndef ERROR_DBG
1027 #define ERROR_DBG NOBUG_ERROR_DBG
1028 #endif
1029 #ifndef ERROR_IF
1030 #define ERROR_IF NOBUG_ERROR_IF
1031 #endif
1032 #ifndef ERROR_IF_DBG
1033 #define ERROR_IF_DBG NOBUG_ERROR_IF_DBG
1034 #endif
1035 #ifndef WARN
1036 #define WARN NOBUG_WARN
1037 #endif
1038 #ifndef WARN_DBG
1039 #define WARN_DBG NOBUG_WARN_DBG
1040 #endif
1041 #ifndef WARN_IF
1042 #define WARN_IF NOBUG_WARN_IF
1043 #endif
1044 #ifndef WARN_IF_DBG
1045 #define WARN_IF_DBG NOBUG_WARN_IF_DBG
1046 #endif
1047 #ifndef INFO
1048 #define INFO NOBUG_INFO
1049 #endif
1050 #ifndef INFO_DBG
1051 #define INFO_DBG NOBUG_INFO_DBG
1052 #endif
1053 #ifndef INFO_IF
1054 #define INFO_IF NOBUG_INFO_IF
1055 #endif
1056 #ifndef INFO_IF_DBG
1057 #define INFO_IF_DBG NOBUG_INFO_IF_DBG
1058 #endif
1059 #ifndef NOTICE
1060 #define NOTICE NOBUG_NOTICE
1061 #endif
1062 #ifndef NOTICE_DBG
1063 #define NOTICE_DBG NOBUG_NOTICE_DBG
1064 #endif
1065 #ifndef NOTICE_IF
1066 #define NOTICE_IF NOBUG_NOTICE_IF
1067 #endif
1068 #ifndef NOTICE_IF_DBG
1069 #define NOTICE_IF_DBG NOBUG_NOTICE_IF_DBG
1070 #endif
1071 #ifndef TRACE
1072 #define TRACE NOBUG_TRACE
1073 #endif
1074 #ifndef TRACE_DBG
1075 #define TRACE_DBG NOBUG_TRACE_DBG
1076 #endif
1077 #ifndef TRACE_IF
1078 #define TRACE_IF NOBUG_TRACE_IF
1079 #endif
1080 #ifndef TRACE_IF_DBG
1081 #define TRACE_IF_DBG NOBUG_TRACE_IF_DBG
1082 #endif
1083 #ifndef BACKTRACE
1084 #define BACKTRACE NOBUG_BACKTRACE
1085 #endif
1086 #ifndef BACKTRACE_DBG
1087 #define BACKTRACE_DBG NOBUG_BACKTRACE_DBG
1088 #endif
1089 #ifndef DEPRECATED
1090 #define DEPRECATED NOBUG_DEPRECATED
1091 #endif
1092 #ifndef UNIMPLEMENTED
1093 #define UNIMPLEMENTED NOBUG_UNIMPLEMENTED
1094 #endif
1095 #ifndef FIXME
1096 #define FIXME NOBUG_FIXME
1097 #endif
1098 #ifndef TODO
1099 #define TODO NOBUG_TODO
1100 #endif
1101 #ifndef PLANNED
1102 #define PLANNED NOBUG_PLANNED
1103 #endif
1104 #ifndef NOTREACHED
1105 #define NOTREACHED NOBUG_NOTREACHED
1106 #endif
1107 #ifndef CLEANUP
1108 #define CLEANUP NOBUG_CLEANUP
1109 #endif
1110 #ifndef CHECKED
1111 #define CHECKED NOBUG_CHECKED
1112 #endif
1113 #ifndef UNCHECKED
1114 #define UNCHECKED NOBUG_UNCHECKED
1115 #endif
1116 #ifndef RESOURCE_ANNOUNCE
1117 #define RESOURCE_ANNOUNCE NOBUG_RESOURCE_ANNOUNCE
1118 #endif
1119 #ifndef RESOURCE_FORGET
1120 #define RESOURCE_FORGET NOBUG_RESOURCE_FORGET
1121 #endif
1122 #ifndef RESOURCE_ENTER
1123 #define RESOURCE_ENTER NOBUG_RESOURCE_ENTER
1124 #endif
1125 #ifndef RESOURCE_STATE
1126 #define RESOURCE_STATE NOBUG_RESOURCE_STATE
1127 #endif
1128 #ifndef RESOURCE_LEAVE
1129 #define RESOURCE_LEAVE NOBUG_RESOURCE_LEAVE
1130 #endif
1131 #ifndef RESOURCE_LEAVE_LOOKUP
1132 #define RESOURCE_LEAVE_LOOKUP NOBUG_RESOURCE_LEAVE_LOOKUP
1133 #endif
1134 #ifndef RESOURCE_HANDLE
1135 #define RESOURCE_HANDLE NOBUG_RESOURCE_HANDLE
1136 #endif
1137 #endif /* NOBUG_DISABLE_SHORTNAMES */
1138 #endif /* NOBUG_LIBNOBUG_C */
1141 TOOL MACROS
1144 #define NOBUG_IF(bool, ...) NOBUG_CAT(NOBUG_IF_,bool)(__VA_ARGS__)
1145 #define NOBUG_IF_1(...) __VA_ARGS__
1146 #define NOBUG_IF_0(...)
1148 #define NOBUG_IFNOT(bool, ...) NOBUG_CAT(NOBUG_IF_, NOBUG_NOT(bool))(__VA_ARGS__)
1150 #define NOBUG_NOT(bool) NOBUG_CAT(NOBUG_NOT_, bool)
1151 #define NOBUG_NOT_1 0
1152 #define NOBUG_NOT_0 1
1154 #define NOBUG_AND(a,b) NOBUG_CAT3(NOBUG_AND_, a, b)
1155 #define NOBUG_AND_00 0
1156 #define NOBUG_AND_01 0
1157 #define NOBUG_AND_10 0
1158 #define NOBUG_AND_11 1
1160 #define NOBUG_OR(a,b) NOBUG_CAT3(NOBUG_OR_, a, b)
1161 #define NOBUG_OR_00 0
1162 #define NOBUG_OR_01 1
1163 #define NOBUG_OR_10 1
1164 #define NOBUG_OR_11 1
1166 #define NOBUG_XOR(a,b) NOBUG_CAT( NOBUG_XOR_, NOBUG_CAT(a,b))
1167 #define NOBUG_XOR_00 0
1168 #define NOBUG_XOR_01 1
1169 #define NOBUG_XOR_10 1
1170 #define NOBUG_XOR_11 0
1172 #define NOBUG_CAT(a,b) NOBUG_CAT_(a,b)
1173 #define NOBUG_CAT_(a,b) a##b
1175 #define NOBUG_CAT3(a,b,c) NOBUG_CAT3_(a,b,c)
1176 #define NOBUG_CAT3_(a,b,c) a##b##c
1178 #define NOBUG_HEAD(head, ...) head
1179 #define NOBUG_TAIL(_, ...) , ## __VA_ARGS__
1181 #define NOBUG_STRINGIZE(s) NOBUG_STRINGIZE_(s)
1182 #define NOBUG_STRINGIZE_(s) #s
1186 LIBNOBUG DECLARATIONS
1188 #ifdef __cplusplus
1189 extern "C" {
1190 #endif
1193 envvar control
1195 enum nobug_log_targets
1197 NOBUG_TARGET_RINGBUFFER,
1198 NOBUG_TARGET_CONSOLE,
1199 NOBUG_TARGET_FILE,
1200 NOBUG_TARGET_SYSLOG,
1201 NOBUG_TARGET_APPLICATION
1204 struct nobug_flag
1206 const char* name;
1207 int limits[5];
1208 struct nobug_ringbuffer* ringbuffer_target;
1209 FILE* console_target;
1210 FILE* file_target;
1214 nobug_env_parse_flag (const char* env, struct nobug_flag* flag, int default_target, int default_limit);
1217 nobug_env_init_flag (struct nobug_flag* flag, int default_target, int default_limit);
1222 ringbuffer
1224 struct nobug_ringbuffer
1226 char* pos;
1227 char* start;
1228 size_t size;
1229 size_t maxmsg;
1230 char name[256];
1233 extern struct nobug_ringbuffer nobug_default_ringbuffer;
1234 extern FILE* nobug_default_file;
1235 extern struct nobug_flag nobug_flag_NOBUG_ON;
1237 enum nobug_ringbuffer_flags
1239 NOBUG_RINGBUFFER_DEFAULT, /* Default is to overwrite file and delete it on nobug_ringbuffer_destroy */
1240 NOBUG_RINGBUFFER_APPEND = 1, /* use existing backing file, append if possible */
1241 NOBUG_RINGBUFFER_TEMP = 2, /* unlink file instantly */
1242 NOBUG_RINGBUFFER_KEEP = 4 /* dont unlink the file at destroy */
1246 Note: some flags conflict (TEMP with KEEP) nobug_ringbuffer will not error on these but continue gracefully
1247 with sane (but undefined) semantics.
1249 void
1250 nobug_ringbuffer_init (struct nobug_ringbuffer* self, size_t size,
1251 const char * name, enum nobug_ringbuffer_flags flags);
1253 void
1254 nobug_ringbuffer_destroy (struct nobug_ringbuffer* self);
1257 nobug_ringbuffer_printf (struct nobug_ringbuffer* self, const char* fmt, ...);
1259 char*
1260 nobug_ringbuffer_prev (struct nobug_ringbuffer* self, char* pos);
1262 char*
1263 nobug_ringbuffer_next (struct nobug_ringbuffer* self, char* pos);
1266 nobug_ringbuffer_save (struct nobug_ringbuffer* self, FILE* out);
1269 nobug_ringbuffer_load (struct nobug_ringbuffer* self, FILE* in);
1271 char*
1272 nobug_ringbuffer_pos (struct nobug_ringbuffer* self);
1274 void
1275 nobug_ringbuffer_pop (struct nobug_ringbuffer* self);
1278 resource registry
1280 struct nobug_resource_record
1282 char* type; /* type or state */
1283 char* name; /* name */
1284 void* object_id; /* unique identifer, usually a this pointer or similar */
1285 #if NOBUG_USE_PTHREAD == 1
1286 char* thread_id;
1287 #endif
1288 void* data; /* tree of holders in resouces, backpointer to resource in holders */
1289 char* extra; /* extra information, file/line usually */
1290 unsigned long counter; /* users or recursive enters */
1293 enum nobug_resource_state
1295 NOBUG_RESOURCE_WAITING,
1296 NOBUG_RESOURCE_EXCLUSIVE,
1297 NOBUG_RESOURCE_RECURSIVE
1300 extern void* nobug_resource_registry;
1301 extern const char* nobug_resource_error;
1302 extern FILE* nobug_resource_dump_target;
1304 extern const char* nobug_resource_states[];
1308 struct nobug_resource_record*
1309 nobug_resource_announce (const char* type, const char* name, const void* object_id, const char* extra);
1312 nobug_resource_forget (struct nobug_resource_record* node);
1314 struct nobug_resource_record*
1315 nobug_resource_find (const struct nobug_resource_record* resource, const void* object_id);
1317 struct nobug_resource_record*
1318 nobug_resource_enter (struct nobug_resource_record* resource,
1319 const char* name,
1320 const void* object_id,
1321 enum nobug_resource_state state,
1322 const char* extra);
1325 nobug_resource_state (struct nobug_resource_record* resource,
1326 enum nobug_resource_state state);
1329 nobug_resource_leave (struct nobug_resource_record* handle);
1331 void
1332 nobug_resource_dump (struct nobug_resource_record* resource, FILE* target);
1334 void
1335 nobug_resource_dump_all (FILE* target);
1337 void
1338 nobug_resource_dump_resources (FILE* target);
1341 thread id handling
1343 #ifdef NOBUG_USE_PTHREAD
1344 extern pthread_key_t nobug_thread_id_key;
1346 const char*
1347 nobug_thread_id_set (const char* name);
1349 const char*
1350 nobug_thread_id_get (void);
1352 extern pthread_mutex_t nobug_global_mutex;
1353 #define NOBUG_LOCK pthread_mutex_lock (&nobug_global_mutex)
1354 #define NOBUG_UNLOCK pthread_mutex_unlock (&nobug_global_mutex)
1355 #else
1356 #define NOBUG_LOCK
1357 #define NOBUG_UNLOCK
1358 #endif
1362 global config and data
1364 extern const char* nobug_resource_acquired;
1366 void nobug_init ();
1368 #ifdef __cplusplus
1369 } /* extern "C" */
1370 #endif
1372 #ifndef NOBUG_LIBNOBUG_C
1375 tag this translation unit as unchecked in ALPHA and BETA builds
1377 NOBUG_IF_NOT_RELEASE(NOBUG_UNCHECKED);
1379 #endif /* NOBUG_LIBNOBUG_C */
1380 #endif