some cosmetics
[nobug.git] / src / nobug.h
blob630ef28e30ad2f842d0876c67015c72b6a529185
1 /*
2 This file is part of the NoBug debugging library.
4 Copyright (C) 2007, 2008, Christian Thaeter <chth@gmx.net>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, contact Christian Thaeter <ct@pipapo.org>.
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>
57 #include <stdarg.h>
59 #ifdef HAVE_EXECINFO_H
60 # ifndef NOBUG_USE_EXECINFO
61 # define NOBUG_USE_EXECINFO 1
62 # endif
63 #else
64 # undef NOBUG_USE_EXECINFO
65 # define NOBUG_USE_EXECINFO 0
66 #endif
68 #if NOBUG_USE_EXECINFO
69 #include <execinfo.h>
70 #endif
72 #if defined(HAVE_VALGRIND_VALGRIND_H) && !defined(NVALGRIND)
73 # ifndef NOBUG_USE_VALGRIND
74 # define NOBUG_USE_VALGRIND 1
75 # endif
76 #else
77 # undef NOBUG_USE_VALGRIND
78 # define NOBUG_USE_VALGRIND 0
79 #endif
81 #if NOBUG_USE_VALGRIND
82 #include <valgrind/valgrind.h>
83 #endif
85 #ifdef HAVE_PTHREAD
86 # ifndef NOBUG_USE_PTHREAD
87 # define NOBUG_USE_PTHREAD 1
88 # endif
89 #else
90 # ifdef NOBUG_USE_PTHREAD
91 # undef NOBUG_USE_PTHREAD
92 # endif
93 # define NOBUG_USE_PTHREAD 0
94 #endif
96 #if NOBUG_USE_PTHREAD
97 #include <pthread.h>
98 #endif
101 #ifndef NOBUG_LIBNOBUG_C /* not when building libnobug */
103 MACROS
105 #if NOBUG_MODE_RELEASE==0
106 #undef assert
107 #define assert(expr) NOBUG_ASSERT(expr)
108 #endif
111 check preconditions (incoming parameters)
114 #define NOBUG_REQUIRE(expr, ...) \
115 NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_(expr, "PRECONDITION", \
116 NOBUG_LOCATION_INFO, ## __VA_ARGS__))
119 #define NOBUG_REQUIRE_DBG(expr, ...) \
120 NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_DBG_(expr, "PRECONDITION", \
121 NOBUG_LOCATION_INFO, ## __VA_ARGS__))
124 #define NOBUG_REQUIRE_IF(when, expr, ...) \
125 NOBUG_WHEN(when, NOBUG_REQUIRE(expr, ## __VA_ARGS__))
127 #define NOBUG_REQUIRE_IF_DBG(when, expr, ...) \
128 NOBUG_WHEN(when, NOBUG_REQUIRE_DBG(expr, ## __VA_ARGS__))
131 check postcondistions (computation outcomes)
133 #define NOBUG_ENSURE(expr, ...) \
134 NOBUG_MODE_SWITCH( \
135 NOBUG_ASSERT_(expr, "POSTCONDITION", \
136 NOBUG_LOCATION_INFO, ## __VA_ARGS__), \
137 NOBUG_BLOCK ( \
138 if (NOBUG_SCOPE_UNCHECKED) \
140 NOBUG_ASSERT_(expr, "POSTCONDITION", \
141 NOBUG_LOCATION_INFO, ## __VA_ARGS__); \
143 ), \
144 NOBUG_PASS \
147 #define NOBUG_ENSURE_DBG(expr, ...) \
148 NOBUG_MODE_SWITCH( \
149 NOBUG_ASSERT_DBG_(expr, "POSTCONDITION", \
150 NOBUG_LOCATION_INFO, ## __VA_ARGS__), \
151 NOBUG_BLOCK ( \
152 if (NOBUG_SCOPE_UNCHECKED) \
154 NOBUG_ASSERT_DBG_(expr, "POSTCONDITION", \
155 NOBUG_LOCATION_INFO, ## __VA_ARGS__); \
157 ), \
158 NOBUG_PASS \
161 #define NOBUG_ENSURE_IF(when, expr, ...) \
162 NOBUG_WHEN(when, NOBUG_ENSURE(expr, ## __VA_ARGS__))
164 #define NOBUG_ENSURE_IF_DBG(when, expr, ...) \
165 NOBUG_WHEN(when, NOBUG_ENSURE_DBG(expr, ## __VA_ARGS__))
169 generic assertion
172 #define NOBUG_ASSERT(expr, ...) \
173 NOBUG_IF_NOT_RELEASE( \
174 NOBUG_BLOCK ( \
175 NOBUG_ASSERT_(expr, "ASSERTION", NOBUG_LOCATION_INFO, ## __VA_ARGS__) \
178 #define NOBUG_ASSERT_DBG(expr, ...) \
179 NOBUG_IF_NOT_RELEASE( \
180 NOBUG_BLOCK ( \
181 NOBUG_ASSERT_DBG_(expr, "ASSERTION", \
182 NOBUG_LOCATION_INFO, ## __VA_ARGS__); \
183 } while(0) \
186 #define NOBUG_ASSERT_IF(when, expr, ...) \
187 NOBUG_WHEN(when, NOBUG_ASSERT(expr, ## __VA_ARGS__))
189 #define NOBUG_ASSERT_IF_DBG(when, expr, ...) \
190 NOBUG_WHEN(when, NOBUG_ASSERT_DBG(expr, ## __VA_ARGS__))
193 low level assert
195 #define NOBUG_ASSERT_(expr, what, location, ...) \
196 if (NOBUG_EXPECT_FALSE(!(expr))) \
198 NOBUG_LOG_( NOBUG_ON, LOG_EMERG, \
199 location, what, "(%s) " \
200 NOBUG_HEAD(__VA_ARGS__), \
201 #expr NOBUG_TAIL(__VA_ARGS__)); \
202 NOBUG_BACKTRACE; \
203 NOBUG_ABORT; \
206 #define NOBUG_ASSERT_DBG_(expr, what, location, ...) \
207 NOBUG_IF_DBG_ACTIVE( \
208 if (NOBUG_EXPECT_FALSE(!(expr))) \
210 NOBUG_LOG_( NOBUG_ON, LOG_EMERG, \
211 location, what, "(%s) " \
212 NOBUG_HEAD(__VA_ARGS__), \
213 #expr NOBUG_TAIL(__VA_ARGS__)); \
214 NOBUG_BACKTRACE; \
215 NOBUG_ABORT; \
218 #define NOBUG_ASSERTN_(expr, what, location, ...) \
219 if (NOBUG_EXPECT_FALSE(!(expr))) \
221 NOBUG_LOG_( NOBUG_ON, LOG_EMERG, \
222 location, what, \
223 ## __VA_ARGS__); \
224 NOBUG_BACKTRACE; \
225 NOBUG_ABORT; \
230 invariant check
233 #define NOBUG_INVARIANT(type, pointer, depth) \
234 NOBUG_MODE_SWITCH( \
235 NOBUG_BLOCK ( \
236 if (NOBUG_SCOPE_UNCHECKED) \
238 NOBUG_CAT(type,_invariant)(pointer, depth, \
239 NOBUG_LOCATION_ARGS); \
241 ), \
242 NOBUG_PASS, NOBUG_PASS \
245 #define NOBUG_INVARIANT_DBG(type, pointer, ...) \
246 NOBUG_MODE_SWITCH( \
247 NOBUG_IF_DBG_ACTIVE ( \
248 if (NOBUG_SCOPE_UNCHECKED) \
250 NOBUG_CAT(type,_invariant)(pointer, depth, NOBUG_LOCATION_ARGS); \
252 ), \
253 NOBUG_PASS, NOBUG_PASS \
256 #define NOBUG_INVARIANT_IF(when, type, pointer, ...) \
257 NOBUG_WHEN(when, NOBUG_INVARIANT(type, pointer, ## __VA_ARGS__))
259 #define NOBUG_INVARIANT_IF_DBG(when, type, pointer, ...) \
260 NOBUG_WHEN(when, NOBUG_INVARIANT_DBG(type, pointer, ## __VA_ARGS__))
262 #define NOBUG_INVARIANT_ASSERT(expr, ...) \
263 NOBUG_ASSERT_(expr, "INVARIANT", (file, line, func), ## __VA_ARGS__)
267 dumping datastructures
269 /*TODO dump-level for flags instead limits[0]*/
270 #define NOBUG_DUMP(flag, type, pointer, depth) \
271 NOBUG_IF_NOT_RELEASE( \
272 NOBUG_BLOCK( \
273 if (NOBUG_EXPECT_FALSE (NOBUG_DUMP_LEVEL <= nobug_flag_##flag.limits[0])) \
275 NOBUG_BLOCK ( \
276 NOBUG_CAT3(nobug_, type, _dump)(pointer, depth, \
277 NOBUG_LOCATION_ARGS); \
278 ); \
281 #define NOBUG_DUMP_DBG(flag, type, pointer, depth) \
282 NOBUG_IF_NOT_RELEASE( \
283 NOBUG_BLOCK( \
284 NOBUG_IF_DBG_ACTIVE ( \
285 if (NOBUG_EXPECT_FALSE(NOBUG_DUMP_LEVEL <= nobug_flag_##flag.limits[0])) \
287 NOBUG_CAT3(nobug_, type, _dump)(pointer, depth, \
288 NOBUG_LOCATION_ARGS); \
289 } ) \
292 #define NOBUG_DUMP_IF(expr, flag, type, pointer, depth) \
293 NOBUG_BLOCK ( \
294 if (NOBUG_EXPECT_FALSE(NOBUG_DUMP_LEVEL <= nobug_flag_##flag.limits[0])) \
296 if (NOBUG_EXPECT_FALSE(expr)) \
298 NOBUG_CAT3(nobug_, type,_dump)(pointer, depth, \
299 NOBUG_LOCATION_ARGS); \
303 #define NOBUG_DUMP_IF_DBG(expr, flag, type, pointer, depth) \
304 NOBUG_IF_NOT_RELEASE( \
305 NOBUG_IF_DBG_ACTIVE ( \
306 if (NOBUG_EXPECT_FALSE(NOBUG_DUMP_LEVEL <= nobug_flag_##flag.limits[0])) \
308 if (NOBUG_EXPECT_FALSE(expr)) \
310 NOBUG_CAT(nobug_, type,_dump)(pointer, depth, \
311 NOBUG_LOCATION_ARGS); \
315 #ifndef NOBUG_DUMP_LEVEL
316 #define NOBUG_DUMP_LEVEL LOG_DEBUG
317 #endif
319 #define NOBUG_DUMP_LOG(fmt, ...) \
320 NOBUG_LOG_( NOBUG_ON, NOBUG_DUMP_LEVEL, \
321 (file, line, func), "DUMP", \
322 fmt, ## __VA_ARGS__)
325 #define NOBUG_DUMP_LOG_DBG(fmt, ...) \
326 NOBUG_IF_DBG_ACTIVE ( \
327 NOBUG_LOG_( NOBUG_ON, NOBUG_DUMP_LEVEL, \
328 (file, line, func), "DUMP", \
329 fmt, ## __VA_ARGS__) \
332 #define NOBUG_DUMP_LOG_IF(expr, fmt, ...) \
333 NOBUG_BLOCK ( \
334 if (NOBUG_EXPECT_FALSE(expr)) { \
335 NOBUG_LOG_( NOBUG_ON, NOBUG_DUMP_LEVEL, \
336 (file, line, func), "DUMP", \
337 fmt, ## __VA_ARGS__) \
341 #define NOBUG_DUMP_LOG_IF_DBG(expr, fmt, ...) \
342 NOBUG_IF_DBG_ACTIVE ( \
343 if (NOBUG_EXPECT_FALSE(expr)) { \
344 NOBUG_LOG_( NOBUG_ON, NOBUG_DUMP_LEVEL, \
345 (file), line, func), "DUMP", \
346 fmt, ## __VA_ARGS__) \
352 Logging
354 #define NOBUG_LOG(flag, lvl, ...) \
355 NOBUG_BLOCK ( \
356 NOBUG_LOG_(flag, lvl, NOBUG_LOCATION_INFO, \
357 NOBUG_LVL(lvl), ## __VA_ARGS__); \
360 #define NOBUG_LOG_DBG(flag, lvl, ...) \
361 NOBUG_IF_DBG_ACTIVE ( \
362 NOBUG_LOG_(flag, lvl, NOBUG_LOCATION_INFO, \
363 NOBUG_LVL(lvl), ## __VA_ARGS__); \
366 #define NOBUG_LOG_IF(expr, flag, lvl, ...) \
367 NOBUG_BLOCK ( \
368 if (NOBUG_EXPECT_FALSE(expr)) { \
369 NOBUG_LOG_(flag, lvl, NOBUG_LOCATION_INFO, \
370 NOBUG_LVL(lvl), ## __VA_ARGS__); \
374 #define NOBUG_LOG_IF_DBG(expr, flag, lvl, ...) \
375 NOBUG_IF_DBG_ACTIVE ( \
376 if (NOBUG_EXPECT_FALSE(expr)) { \
377 NOBUG_LOG_(flag, lvl, NOBUG_LOCATION_INFO, \
378 NOBUG_LVL(lvl), ## __VA_ARGS__); \
382 #define NOBUG_LVL(lvl) NOBUG_LVL_##lvl
383 #define NOBUG_LVL_0 "EMERG"
384 #define NOBUG_LVL_1 "ALERT"
385 #define NOBUG_LVL_2 "CRIT"
386 #define NOBUG_LVL_3 "ERR"
387 #define NOBUG_LVL_4 "WARNING"
388 #define NOBUG_LVL_5 "NOTICE"
389 #define NOBUG_LVL_6 "INFO"
390 #define NOBUG_LVL_7 "TRACE"
394 low level logging handler
396 #define NOBUG_LOG_(flag, lvl, location, what, ...) \
397 do { \
398 if (NOBUG_EXPECT_FALSE(lvl <= NOBUG_FLAG(flag).limits[NOBUG_TARGET_RINGBUFFER])) \
400 NOBUG_LOCK; \
401 nobug_log (&NOBUG_FLAG(flag), lvl, \
402 "%0.8llu: %s:%d: %s:"NOBUG_THREAD_ID_FMT(" ",":")" %s: "NOBUG_HEAD(__VA_ARGS__), \
403 ++nobug_counter, NOBUG_LOCATION_FILE location, NOBUG_LOCATION_LINE location, \
404 what NOBUG_THREAD_ID_COMMA, \
405 NOBUG_LOCATION_FUNC location NOBUG_TAIL(__VA_ARGS__)); \
406 NOBUG_UNLOCK; \
408 } while (0)
411 #define NOBUG_LOCATION_ARGS NOBUG_BASENAME(__FILE__), __LINE__, __func__
412 #define NOBUG_LOCATION_INFO (NOBUG_LOCATION_ARGS)
414 #define NOBUG_LOCATION_FILE(file, _1, _2) file
415 #define NOBUG_LOCATION_LINE(_1, line, _2) line
416 #define NOBUG_LOCATION_FUNC(_1, _2, func) func
419 /*TODO better location handling, no text? empty on RELEASE*/
420 #define NOBUG_LOCATION(text) \
421 NOBUG_MODE_SWITCH( \
422 NOBUG_BASENAME(__FILE__ ":" NOBUG_STRINGIZE(__LINE__)":" text), \
423 NOBUG_BASENAME(__FILE__ ":" NOBUG_STRINGIZE(__LINE__)":" text), \
424 "" \
427 #define NOBUG_ERROR(flag, ...) \
428 NOBUG_LOG(flag, LOG_ERR, ## __VA_ARGS__)
429 #define NOBUG_ERROR_IF(expr, flag, ...) \
430 NOBUG_LOG_IF(expr, flag, LOG_ERR, ## __VA_ARGS__)
431 #define NOBUG_ERROR_DBG(flag, ...) \
432 NOBUG_LOG_DBG(flag, LOG_ERR, ## __VA_ARGS__)
433 #define NOBUG_ERROR_IF_DBG(expr, flag, ...) \
434 NOBUG_LOG_IF_DBG(expr, flag, LOG_ERR, ## __VA_ARGS__)
436 #define NOBUG_WARN(flag, ...) \
437 NOBUG_LOG(flag, LOG_WARNING, ## __VA_ARGS__)
438 #define NOBUG_WARN_IF(expr, flag, ...) \
439 NOBUG_LOG_IF(expr, flag, LOG_WARNING, ## __VA_ARGS__)
440 #define NOBUG_WARN_DBG(flag, ...) \
441 NOBUG_LOG_DBG(flag, LOG_WARNING, ## __VA_ARGS__)
442 #define NOBUG_WARN_IF_DBG(expr, flag, ...) \
443 NOBUG_LOG_IF_DBG(expr, flag, LOG_WARNING, ## __VA_ARGS__)
445 #define NOBUG_INFO(flag, ...) \
446 NOBUG_LOG(flag, LOG_INFO, ## __VA_ARGS__)
447 #define NOBUG_INFO_IF(expr, flag, ...) \
448 NOBUG_LOG_IF(expr, flag, LOG_INFO, ## __VA_ARGS__)
449 #define NOBUG_INFO_DBG(flag, ...) \
450 NOBUG_LOG_DBG(flag, LOG_INFO, ## __VA_ARGS__)
451 #define NOBUG_INFO_IF_DBG(expr, flag, ...) \
452 NOBUG_LOG_IF_DBG(expr, flag, LOG_INFO, ## __VA_ARGS__)
454 #define NOBUG_NOTICE(flag, ...) \
455 NOBUG_LOG(flag, LOG_NOTICE, ## __VA_ARGS__)
456 #define NOBUG_NOTICE_IF(expr, flag, ...) \
457 NOBUG_LOG_IF(expr, flag, LOG_NOTICE, ## __VA_ARGS__)
458 #define NOBUG_NOTICE_DBG(flag, ...) \
459 NOBUG_LOG_DBG(flag, LOG_NOTICE, ## __VA_ARGS__)
460 #define NOBUG_NOTICE_IF_DBG(expr, flag, ...) \
461 NOBUG_LOG_IF_DBG(expr, flag, LOG_NOTICE, ## __VA_ARGS__)
463 #define NOBUG_TRACE(flag, ...) \
464 NOBUG_LOG(flag, LOG_DEBUG, ## __VA_ARGS__)
465 #define NOBUG_TRACE_IF(expr, flag, ...) \
466 NOBUG_LOG_IF(expr, flag, LOG_DEBUG, ## __VA_ARGS__)
467 #define NOBUG_TRACE_DBG(flag, ...) \
468 NOBUG_LOG_DBG(flag, LOG_DEBUG, ## __VA_ARGS__)
469 #define NOBUG_TRACE_IF_DBG(expr, flag, ...) \
470 NOBUG_LOG_IF_DBG(expr, flag, LOG_DEBUG, ## __VA_ARGS__)
472 #define NOBUG_BASENAME(name) (strrchr((name), '/')?strrchr((name), '/') + 1 : (name))
474 #define NOBUG_SCOPE_UNCHECKED NOBUG_CHECKED_VALUE == 0
476 #define NOBUG_DBG_ACTIVE \
477 NOBUG_IF(NOBUG_USE_VALGRIND, (RUNNING_ON_VALGRIND?2:0)) \
478 NOBUG_IFNOT(NOBUG_USE_VALGRIND, (0))
481 alpha beta release
482 unchecked Preconditions, Postconditions, Invariants Preconditions, Postconditions compiling will abort
483 checked Preconditions, Postconditions Preconditions
486 #define NOBUG_CHECKED NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=1})
488 #define NOBUG_UNCHECKED \
489 NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=0}) \
490 NOBUG_IF(NOBUG_MODE_RELEASE, NOBUG_UNCHECKED_NOT_ALLOWED_IN_RELEASE_BUILD)
492 #define NOBUG_ABORT abort()
494 #define NOBUG_DBG_GDB 1
495 #define NOBUG_DBG_VALGRIND 2
497 #define NOBUG_BACKTRACE \
498 NOBUG_MODE_SWITCH( \
499 switch (NOBUG_DBG_ACTIVE) { \
500 case NOBUG_DBG_VALGRIND: \
501 NOBUG_BACKTRACE_VALGRIND; \
502 break; \
503 default: \
504 NOBUG_BACKTRACE_GLIBC; \
505 }, \
506 NOBUG_BACKTRACE_GLIBC, \
507 NOBUG_BACKTRACE_GLIBC \
510 #define NOBUG_BACKTRACE_DBG \
511 NOBUG_IF_NOT_RELEASE( \
512 switch (NOBUG_DBG_ACTIVE) { \
513 case NOBUG_DBG_VALGRIND: \
514 NOBUG_BACKTRACE_VALGRIND; \
515 break; \
518 #define NOBUG_BACKTRACE_GDB fprintf(stderr, "UNIMPLEMENTED : GDB Backtraces\n")
520 #define NOBUG_BACKTRACE_VALGRIND \
521 NOBUG_IF(NOBUG_USE_VALGRIND, \
522 VALGRIND_PRINTF_BACKTRACE("BACKTRACE : %s@%d %s", \
523 NOBUG_LOCATION_INFO))
526 #ifndef NOBUG_BACKTRACE_DEPTH
527 #define NOBUG_BACKTRACE_DEPTH 256
528 #endif
530 #define NOBUG_BACKTRACE_GLIBC \
531 NOBUG_IF_NOT_RELEASE( \
532 NOBUG_BLOCK ( \
533 NOBUG_IF(NOBUG_USE_EXECINFO, \
534 void* nobug_backtrace_buffer[NOBUG_BACKTRACE_DEPTH]; \
535 backtrace_symbols_fd (nobug_backtrace_buffer, \
536 backtrace (nobug_backtrace_buffer, NOBUG_BACKTRACE_DEPTH), 2))))
540 alpha beta release
541 DEPRECATED log nothing wont compile
543 #define NOBUG_DEPRECATED(msg) \
544 NOBUG_MODE_SWITCH( \
545 NOBUG_ONCE ( \
546 NOBUG_LOG_ (NOBUG_ON, LOG_ALERT, NOBUG_LOCATION_INFO, \
547 "DEPRECATED", msg); \
548 ), \
549 NOBUG_PASS, \
550 NOBUG_DEPRECATED_NOT_ALLOWED_IN_RELEASE_BUILD(msg) \
554 alpha beta release
555 UNIMPLEMENTED abort abort wont compile
557 #define NOBUG_UNIMPLEMENTED(msg) \
558 NOBUG_IF_NOT_RELEASE ( \
559 NOBUG_BLOCK ( \
560 NOBUG_LOG_ (NOBUG_ON, LOG_EMERG, NOBUG_LOCATION_INFO, \
561 "UNIMPLEMENTED", msg); \
562 NOBUG_ABORT; \
563 )) \
564 NOBUG_IF(NOBUG_MODE_RELEASE, NOBUG_UNIMPLEMENTED_NOT_ALLOWED_IN_RELEASE_BUILD(msg);)
567 alpha beta release
568 FIXME log wont compile wont compile
570 #define NOBUG_FIXME(msg) \
571 NOBUG_MODE_SWITCH( \
572 NOBUG_ONCE ( \
573 NOBUG_LOG_ (NOBUG_ON, LOG_ALERT, NOBUG_LOCATION_INFO, \
574 "FIXME", msg); \
575 ), \
576 NOBUG_FIXME_NOT_ALLOWED_IN_BETA_BUILD(msg), \
577 NOBUG_FIXME_NOT_ALLOWED_IN_RELEASE_BUILD(msg) \
581 alpha beta release
582 TODO log log wont compile
584 #define NOBUG_TODO(msg) \
585 NOBUG_IF_NOT_RELEASE ( \
586 NOBUG_ONCE ( \
587 NOBUG_LOG_( NOBUG_ON, LOG_CRIT, NOBUG_LOCATION_INFO, \
588 "TODO", msg); \
589 )) \
590 NOBUG_IF(NOBUG_MODE_RELEASE, NOBUG_TODO_NOT_ALLOWED_IN_RELEASE_BUILD(msg);)
593 alpha beta release
594 PLANNED log nothing nothing
596 #define NOBUG_PLANNED(msg) \
597 NOBUG_MODE_SWITCH ( \
598 NOBUG_ONCE ( \
599 NOBUG_LOG_ (NOBUG_ON, LOG_INFO, NOBUG_LOCATION_INFO, \
600 "PLANNED", msg); \
601 ), \
602 NOBUG_PASS,NOBUG_PASS \
606 alpha beta release
607 NOTREACHED abort abort nothing
609 #define NOBUG_NOTREACHED \
610 NOBUG_IF_NOT_RELEASE ( \
611 NOBUG_BLOCK ( \
612 NOBUG_LOG_( NOBUG_ON, LOG_EMERG, NOBUG_LOCATION_INFO, \
613 "NOTREACHED"); \
614 NOBUG_ABORT; \
617 NOBUG_IF(NOBUG_MODE_RELEASE, NOBUG_PASS)
621 Resource registry macros
623 #ifndef NOBUG_RESOURCE_LOGGING
624 #define NOBUG_RESOURCE_LOGGING 1
625 #endif
627 #ifndef NOBUG_RESOURCE_LOG_LEVEL
628 #define NOBUG_RESOURCE_LOG_LEVEL LOG_DEBUG
629 #endif
631 #define NOBUG_RESOURCE_HANDLE(handle) \
632 NOBUG_IF(NOBUG_MODE_ALPHA, \
633 struct nobug_resource_record* handle)
635 #define NOBUG_RESOURCE_ANNOUNCE(flag, type, name, ptr, handle) \
636 NOBUG_IF(NOBUG_MODE_ALPHA, \
637 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
638 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
639 "RESOURCE_ANNOUNCE", "%s: %s@%p", type, name, ptr);) \
640 NOBUG_ASSERTN_(handle = nobug_resource_announce (type, name, ptr, \
641 NOBUG_BASENAME(__FILE__ ":" NOBUG_STRINGIZE(__LINE__))), \
642 "RESOURCE_ANNOUNCE", NOBUG_LOCATION_INFO, "%s: %s@%p %s", \
643 type, name, ptr, nobug_resource_error) \
646 #define NOBUG_RESOURCE_FORGET(flag, handle) \
647 NOBUG_IF(NOBUG_MODE_ALPHA, \
648 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
649 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
650 "RESOURCE_FORGET", "%s: %s@%p", handle?handle->type:"", \
651 handle?handle->name:"", handle?handle->object_id:NULL);) \
652 NOBUG_ASSERTN_(nobug_resource_forget (handle), \
653 "RESOURCE_FORGET", NOBUG_LOCATION_INFO, "%s: %s@%p: %s", \
654 handle?handle->type:"", handle?handle->name:"", \
655 handle?handle->object_id:NULL, nobug_resource_error); \
656 handle = NULL \
659 #define NOBUG_RESOURCE_ENTER(flag, resource, user, ptr, state, handle) \
660 NOBUG_IF(NOBUG_MODE_ALPHA, \
661 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
662 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
663 "RESOURCE_ENTER", "%s: %s@%p: %s@%p: %s", \
664 resource->type, resource->name, resource->object_id, \
665 user, ptr, nobug_resource_states[state]);) \
666 NOBUG_ASSERTN_(handle = nobug_resource_enter (resource, user, ptr, state, \
667 NOBUG_BASENAME(__FILE__ ":" NOBUG_STRINGIZE(__LINE__))), \
668 "RESOURCE_ENTER", NOBUG_LOCATION_INFO, "%s: %s@%p: %s@%p: %s: %s", \
669 resource?resource->type:"", resource?resource->name:"", \
670 resource?resource->object_id:NULL, \
671 user, ptr, nobug_resource_states[state], nobug_resource_error) \
674 #define NOBUG_RESOURCE_STATE(flag, resource, state) \
675 NOBUG_IF(NOBUG_MODE_ALPHA, \
676 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
677 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
678 "RESOURCE_STATE", "%s: %s@%p: %s@%p: %s->%s", \
679 resource?((struct nobug_resource_record*)resource->data)->type:"", \
680 resource?((struct nobug_resource_record*)resource->data)->name:"", \
681 resource?((struct nobug_resource_record*)resource->data)->object_id:"", \
682 resource?resource->name:NULL, \
683 resource?resource->object_id:NULL, \
684 resource?resource->type:"", nobug_resource_states[state]); \
686 NOBUG_ASSERTN_(nobug_resource_state (resource, state), \
687 "RESOURCE_ENTER", NOBUG_LOCATION_INFO, "%s: %s@%p: %s@%p: %s->%s: %s", \
688 resource?((struct nobug_resource_record*)resource->data)->type:"", \
689 resource?((struct nobug_resource_record*)resource->data)->name:"", \
690 resource?((struct nobug_resource_record*)resource->data)->object_id:"", \
691 resource?resource->name:NULL, \
692 resource?resource->object_id:NULL, \
693 resource?resource->type:"", nobug_resource_states[state], \
694 nobug_resource_error) \
697 #define NOBUG_RESOURCE_LEAVE(flag, handle) \
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_LEAVE", "%s: %s@%p: %s@%p: %s", \
702 handle?((struct nobug_resource_record*)handle->data)->type:"", \
703 handle?((struct nobug_resource_record*)handle->data)->name:"", \
704 handle?((struct nobug_resource_record*)handle->data)->object_id:"", \
705 handle?handle->name:"", \
706 handle?handle->object_id:NULL, \
707 handle?handle->type:""); \
709 NOBUG_ASSERTN_(nobug_resource_leave (handle), \
710 "RESOURCE_LEAVE", NOBUG_LOCATION_INFO, "%s: %s@%p: %s@%p: %s: %s", \
711 handle?((struct nobug_resource_record*)handle->data)->type:"", \
712 handle?((struct nobug_resource_record*)handle->data)->name:"", \
713 handle?((struct nobug_resource_record*)handle->data)->object_id:"", \
714 handle?handle->name:NULL, \
715 handle?handle->object_id:NULL, \
716 handle?handle->type:"", \
717 nobug_resource_error); \
718 handle = NULL)
720 #define NOBUG_RESOURCE_LEAVE_LOOKUP(flag, handle, ptr) \
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: @%p", \
725 handle?handle->type:"", \
726 handle?handle->name:"", \
727 handle?handle->object_id:"", \
728 ptr); \
730 NOBUG_ASSERTN_(nobug_resource_leave (nobug_resource_find(handle, ptr)), \
731 "RESOURCE_LEAVE", NOBUG_LOCATION_INFO, "%s: %s@%p: @%p: %s", \
732 handle?handle->type:"", \
733 handle?handle->name:"", \
734 handle?handle->object_id:"", \
735 ptr, nobug_resource_error) \
739 threading support
741 #if NOBUG_USE_PTHREAD
742 #define NOBUG_LOCK pthread_mutex_lock (&nobug_global_mutex)
743 #define NOBUG_UNLOCK pthread_mutex_unlock (&nobug_global_mutex)
745 #define NOBUG_THREAD_ID_SET(name) nobug_thread_id_set(name)
746 #define NOBUG_THREAD_ID_FMT(pre,post) pre "%s" post
747 #define NOBUG_THREAD_ID_COMMA , NOBUG_THREAD_ID_GET
748 #define NOBUG_THREAD_ID_GET nobug_thread_id_get()
750 #else
751 #define NOBUG_LOCK
752 #define NOBUG_UNLOCK
753 #define NOBUG_THREAD_ID_SET(name)
754 #define NOBUG_THREAD_ID_FMT(pre,post) ""
755 #define NOBUG_THREAD_ID_COMMA
756 #define NOBUG_THREAD_ID_GET ""
757 #endif
760 init
762 #define NOBUG_INIT nobug_init()
765 Tool macros
768 #ifdef __GNUC__
769 #define NOBUG_CLEANUP(fn) \
770 NOBUG_IF(NOBUG_MODE_ALPHA, \
771 __attribute__((cleanup(fn))) \
773 #else
774 #define NOBUG_CLEANUP(fn)
775 #endif
777 #define NOBUG_ONCE(code) \
778 NOBUG_BLOCK ( \
779 static int NOBUG_CAT(nobug_once_,__LINE__) = 0; \
780 if (NOBUG_EXPECT_FALSE(!NOBUG_CAT(nobug_once_,__LINE__))) \
782 NOBUG_CAT(nobug_once_,__LINE__) = 1; \
783 code; \
787 #define NOBUG_PASS ;
789 #define NOBUG_BLOCK(code) do { code; } while (0)
791 #define NOBUG_IF_DBG_ACTIVE(code) \
792 NOBUG_IF(NOBUG_MODE_ALPHA, \
793 NOBUG_BLOCK ( \
794 if (NOBUG_EXPECT_FALSE(NOBUG_DBG_ACTIVE)) \
796 code; \
800 NOBUG_IF(NOBUG_NOT(NOBUG_MODE_ALPHA), NOBUG_PASS)
802 #define NOBUG_WHEN(when, code) \
803 NOBUG_IF_NOT_RELEASE(do{ if (when){code;}}while(0))
805 #define NOBUG_IF_NOT_RELEASE(code) \
806 NOBUG_IF(NOBUG_NOT(NOBUG_MODE_RELEASE), code) \
807 NOBUG_IF(NOBUG_MODE_RELEASE, NOBUG_PASS)
809 #define NOBUG_MODE_SWITCH(alpha_code, beta_code, release_code) \
810 NOBUG_IF(NOBUG_MODE_ALPHA, alpha_code) \
811 NOBUG_IF(NOBUG_MODE_BETA, beta_code) \
812 NOBUG_IF(NOBUG_MODE_RELEASE, release_code)
815 Flag handling
817 #define NOBUG_FLAG(name) NOBUG_CAT(nobug_flag_,name)
819 #define NOBUG_DEFINE_FLAG(name) struct nobug_flag NOBUG_FLAG(name) = \
820 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
821 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
822 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
823 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
824 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
825 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL})
827 #define NOBUG_DEFINE_FLAG_PARENT(name, parent) \
828 NOBUG_DECLARE_FLAG(parent); \
829 struct nobug_flag NOBUG_FLAG(name) = \
830 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
831 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
832 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
833 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
834 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
835 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL})
837 #define NOBUG_DEFINE_FLAG_LIMIT(name, limit) struct nobug_flag NOBUG_FLAG(name) = \
838 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
839 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
840 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
841 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
842 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
843 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL})
845 #define NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, limit) \
846 NOBUG_DECLARE_FLAG(parent); \
847 struct nobug_flag NOBUG_FLAG(name) = \
848 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
849 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
850 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
851 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
852 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
853 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL})
856 /*TODO better FLAG_LIMIT handling, should respect LOG_TARGET */
859 #define NOBUG_DECLARE_FLAG(name) extern struct nobug_flag NOBUG_FLAG(name)
861 #define NOBUG_INIT_FLAG(name) \
862 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, NOBUG_LOG_LIMIT)
864 #define NOBUG_INIT_FLAG_LIMIT(name, default) \
865 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, default)
867 #ifdef __cplusplus
868 #define NOBUG_CPP_DEFINE_FLAG(name) \
869 NOBUG_DEFINE_FLAG(name); \
870 static int nobug_##name##_cppinit##__LINE__ = NOBUG_INIT_FLAG(name)
872 #define NOBUG_CPP_DEFINE_FLAG_PARENT(name, parent) \
873 NOBUG_DEFINE_FLAG_PARENT(name, parent); \
874 static int nobug_##name##_cppinit##__LINE__ = NOBUG_INIT_FLAG(name)
876 #define NOBUG_CPP_DEFINE_FLAG_LIMIT(name, default) \
877 NOBUG_DEFINE_FLAG_LIMIT(name, default); \
878 static int nobug_##name##_cppinit##__LINE__ = NOBUG_INIT_FLAG_LIMIT(name, default)
880 #define NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT(name, parent, default) \
881 NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, default); \
882 static int nobug_##name##_cppinit##__LINE__ = NOBUG_INIT_FLAG_LIMIT(name, default)
883 #endif
885 #ifndef NOBUG_LOG_LIMIT_ALPHA
886 # define NOBUG_LOG_LIMIT_ALPHA LOG_INFO
887 #endif
888 #ifndef NOBUG_LOG_LIMIT_BETA
889 # define NOBUG_LOG_LIMIT_BETA LOG_WARNING
890 #endif
891 #ifndef NOBUG_LOG_LIMIT_RELEASE
892 # define NOBUG_LOG_LIMIT_RELEASE LOG_CRIT
893 #endif
895 #ifndef NOBUG_LOG_LIMIT
896 # define NOBUG_LOG_LIMIT \
897 NOBUG_MODE_SWITCH( \
898 NOBUG_LOG_LIMIT_ALPHA, \
899 NOBUG_LOG_LIMIT_BETA, \
900 NOBUG_LOG_LIMIT_RELEASE)
901 #endif
903 #ifndef NOBUG_LOG_TARGET_ALPHA
904 # define NOBUG_LOG_TARGET_ALPHA NOBUG_TARGET_CONSOLE
905 #endif
906 #ifndef NOBUG_LOG_TARGET_BETA
907 # define NOBUG_LOG_TARGET_BETA NOBUG_TARGET_FILE
908 #endif
909 #ifndef NOBUG_LOG_TARGET_RELEASE
910 # define NOBUG_LOG_TARGET_RELEASE NOBUG_TARGET_SYSLOG
911 #endif
913 #ifndef NOBUG_LOG_TARGET
914 # define NOBUG_LOG_TARGET \
915 NOBUG_MODE_SWITCH( \
916 NOBUG_LOG_TARGET_ALPHA, \
917 NOBUG_LOG_TARGET_BETA, \
918 NOBUG_LOG_TARGET_RELEASE)
919 #endif
921 #define NOBUG_SET_LIMIT(flag, min) \
922 NOBUG_MODE_SWITCH( \
923 NOBUG_FLAG(flag) = (min), \
924 NOBUG_FLAG(flag) = (min), \
925 NOBUG_PASS)
929 short macros without NOBUG_
931 #ifndef NOBUG_DISABLE_SHORTNAMES
932 #ifndef REQUIRE
933 #define REQUIRE NOBUG_REQUIRE
934 #endif
935 #ifndef REQUIRE_DBG
936 #define REQUIRE_DBG NOBUG_REQUIRE_DBG
937 #endif
938 #ifndef REQUIRE_IF
939 #define REQUIRE_IF NOBUG_REQUIRE_IF
940 #endif
941 #ifndef REQUIRE_IF_DBG
942 #define REQUIRE_IF_DBG NOBUG_REQUIRE_IF_DBG
943 #endif
944 #ifndef ENSURE
945 #define ENSURE NOBUG_ENSURE
946 #endif
947 #ifndef ENSURE_DBG
948 #define ENSURE_DBG NOBUG_ENSURE_DBG
949 #endif
950 #ifndef ENSURE_IF
951 #define ENSURE_IF NOBUG_ENSURE_IF
952 #endif
953 #ifndef ENSURE_IF_DBG
954 #define ENSURE_IF_DBG NOBUG_ENSURE_IF_DBG
955 #endif
956 #ifndef ASSERT
957 #define ASSERT NOBUG_ASSERT
958 #endif
959 #ifndef ASSERT_DBG
960 #define ASSERT_DBG NOBUG_ASSERT_DBG
961 #endif
962 #ifndef ASSERT_IF
963 #define ASSERT_IF NOBUG_ASSERT_IF
964 #endif
965 #ifndef ASSERT_IF_DBG
966 #define ASSERT_IF_DBG NOBUG_ASSERT_IF_DBG
967 #endif
968 #ifndef INVARIANT
969 #define INVARIANT NOBUG_INVARIANT
970 #endif
971 #ifndef INVARIANT_DBG
972 #define INVARIANT_DBG NOBUG_INVARIANT_DBG
973 #endif
974 #ifndef INVARIANT_IF
975 #define INVARIANT_IF NOBUG_INVARIANT_IF
976 #endif
977 #ifndef INVARIANT_IF_DBG
978 #define INVARIANT_IF_DBG NOBUG_INVARIANT_IF_DBG
979 #endif
980 #ifndef INVARIANT_ASSERT
981 #define INVARIANT_ASSERT NOBUG_INVARIANT_ASSERT
982 #endif
983 #ifndef DUMP
984 #define DUMP NOBUG_DUMP
985 #endif
986 #ifndef DUMP_DBG
987 #define DUMP_DBG NOBUG_DUMP_DBG
988 #endif
989 #ifndef DUMP_IF
990 #define DUMP_IF NOBUG_DUMP_IF
991 #endif
992 #ifndef DUMP_IF_DBG
993 #define DUMP_IF_DBG NOBUG_DUMP_IF_DBG
994 #endif
995 #ifndef DUMP_LOG
996 #define DUMP_LOG NOBUG_DUMP_LOG
997 #endif
998 #ifndef DUMP_LOG_DBG
999 #define DUMP_LOG_DBG NOBUG_DUMP_LOG_DBG
1000 #endif
1001 #ifndef DUMP_LOG_IF
1002 #define DUMP_LOG_IF NOBUG_DUMP_LOG_IF
1003 #endif
1004 #ifndef DUMP_LOG_IF_DBG
1005 #define DUMP_LOG_IF_DBG NOBUG_DUMP_LOG_IF_DBG
1006 #endif
1007 #ifndef LOG
1008 #define LOG NOBUG_LOG
1009 #endif
1010 #ifndef LOG_DBG
1011 #define LOG_DBG NOBUG_LOG_DBG
1012 #endif
1013 #ifndef LOG_IF
1014 #define LOG_IF NOBUG_LOG_IF
1015 #endif
1016 #ifndef LOG_IF_DBG
1017 #define LOG_IF_DBG NOBUG_LOG_IF_DBG
1018 #endif
1019 #ifndef ERROR
1020 #define ERROR NOBUG_ERROR
1021 #endif
1022 #ifndef ERROR_DBG
1023 #define ERROR_DBG NOBUG_ERROR_DBG
1024 #endif
1025 #ifndef ERROR_IF
1026 #define ERROR_IF NOBUG_ERROR_IF
1027 #endif
1028 #ifndef ERROR_IF_DBG
1029 #define ERROR_IF_DBG NOBUG_ERROR_IF_DBG
1030 #endif
1031 #ifndef WARN
1032 #define WARN NOBUG_WARN
1033 #endif
1034 #ifndef WARN_DBG
1035 #define WARN_DBG NOBUG_WARN_DBG
1036 #endif
1037 #ifndef WARN_IF
1038 #define WARN_IF NOBUG_WARN_IF
1039 #endif
1040 #ifndef WARN_IF_DBG
1041 #define WARN_IF_DBG NOBUG_WARN_IF_DBG
1042 #endif
1043 #ifndef INFO
1044 #define INFO NOBUG_INFO
1045 #endif
1046 #ifndef INFO_DBG
1047 #define INFO_DBG NOBUG_INFO_DBG
1048 #endif
1049 #ifndef INFO_IF
1050 #define INFO_IF NOBUG_INFO_IF
1051 #endif
1052 #ifndef INFO_IF_DBG
1053 #define INFO_IF_DBG NOBUG_INFO_IF_DBG
1054 #endif
1055 #ifndef NOTICE
1056 #define NOTICE NOBUG_NOTICE
1057 #endif
1058 #ifndef NOTICE_DBG
1059 #define NOTICE_DBG NOBUG_NOTICE_DBG
1060 #endif
1061 #ifndef NOTICE_IF
1062 #define NOTICE_IF NOBUG_NOTICE_IF
1063 #endif
1064 #ifndef NOTICE_IF_DBG
1065 #define NOTICE_IF_DBG NOBUG_NOTICE_IF_DBG
1066 #endif
1067 #ifndef TRACE
1068 #define TRACE NOBUG_TRACE
1069 #endif
1070 #ifndef TRACE_DBG
1071 #define TRACE_DBG NOBUG_TRACE_DBG
1072 #endif
1073 #ifndef TRACE_IF
1074 #define TRACE_IF NOBUG_TRACE_IF
1075 #endif
1076 #ifndef TRACE_IF_DBG
1077 #define TRACE_IF_DBG NOBUG_TRACE_IF_DBG
1078 #endif
1079 #ifndef BACKTRACE
1080 #define BACKTRACE NOBUG_BACKTRACE
1081 #endif
1082 #ifndef BACKTRACE_DBG
1083 #define BACKTRACE_DBG NOBUG_BACKTRACE_DBG
1084 #endif
1085 #ifndef DEPRECATED
1086 #define DEPRECATED NOBUG_DEPRECATED
1087 #endif
1088 #ifndef UNIMPLEMENTED
1089 #define UNIMPLEMENTED NOBUG_UNIMPLEMENTED
1090 #endif
1091 #ifndef FIXME
1092 #define FIXME NOBUG_FIXME
1093 #endif
1094 #ifndef TODO
1095 #define TODO NOBUG_TODO
1096 #endif
1097 #ifndef PLANNED
1098 #define PLANNED NOBUG_PLANNED
1099 #endif
1100 #ifndef NOTREACHED
1101 #define NOTREACHED NOBUG_NOTREACHED
1102 #endif
1103 #ifndef CLEANUP
1104 #define CLEANUP NOBUG_CLEANUP
1105 #endif
1106 #ifndef CHECKED
1107 #define CHECKED NOBUG_CHECKED
1108 #endif
1109 #ifndef UNCHECKED
1110 #define UNCHECKED NOBUG_UNCHECKED
1111 #endif
1112 #ifndef RESOURCE_ANNOUNCE
1113 #define RESOURCE_ANNOUNCE NOBUG_RESOURCE_ANNOUNCE
1114 #endif
1115 #ifndef RESOURCE_FORGET
1116 #define RESOURCE_FORGET NOBUG_RESOURCE_FORGET
1117 #endif
1118 #ifndef RESOURCE_ENTER
1119 #define RESOURCE_ENTER NOBUG_RESOURCE_ENTER
1120 #endif
1121 #ifndef RESOURCE_STATE
1122 #define RESOURCE_STATE NOBUG_RESOURCE_STATE
1123 #endif
1124 #ifndef RESOURCE_LEAVE
1125 #define RESOURCE_LEAVE NOBUG_RESOURCE_LEAVE
1126 #endif
1127 #ifndef RESOURCE_LEAVE_LOOKUP
1128 #define RESOURCE_LEAVE_LOOKUP NOBUG_RESOURCE_LEAVE_LOOKUP
1129 #endif
1130 #ifndef RESOURCE_HANDLE
1131 #define RESOURCE_HANDLE NOBUG_RESOURCE_HANDLE
1132 #endif
1133 #endif /* NOBUG_DISABLE_SHORTNAMES */
1134 #endif /* NOBUG_LIBNOBUG_C */
1137 TOOL MACROS
1140 // branch prediction on bools
1141 #if __GNUC__
1142 #define NOBUG_EXPECT_FALSE(x) __builtin_expect(!!(x),0)
1143 #else
1144 #define NOBUG_EXPECT_FALSE(x) x
1145 #endif
1147 #define NOBUG_IF(bool, ...) NOBUG_CAT(NOBUG_IF_,bool)(__VA_ARGS__)
1148 #define NOBUG_IF_1(...) __VA_ARGS__
1149 #define NOBUG_IF_0(...)
1151 #define NOBUG_IFNOT(bool, ...) NOBUG_CAT(NOBUG_IF_, NOBUG_NOT(bool))(__VA_ARGS__)
1153 #define NOBUG_NOT(bool) NOBUG_CAT(NOBUG_NOT_, bool)
1154 #define NOBUG_NOT_1 0
1155 #define NOBUG_NOT_0 1
1157 #define NOBUG_AND(a,b) NOBUG_CAT3(NOBUG_AND_, a, b)
1158 #define NOBUG_AND_00 0
1159 #define NOBUG_AND_01 0
1160 #define NOBUG_AND_10 0
1161 #define NOBUG_AND_11 1
1163 #define NOBUG_OR(a,b) NOBUG_CAT3(NOBUG_OR_, a, b)
1164 #define NOBUG_OR_00 0
1165 #define NOBUG_OR_01 1
1166 #define NOBUG_OR_10 1
1167 #define NOBUG_OR_11 1
1169 #define NOBUG_XOR(a,b) NOBUG_CAT( NOBUG_XOR_, NOBUG_CAT(a,b))
1170 #define NOBUG_XOR_00 0
1171 #define NOBUG_XOR_01 1
1172 #define NOBUG_XOR_10 1
1173 #define NOBUG_XOR_11 0
1175 #define NOBUG_CAT(a,b) NOBUG_CAT_(a,b)
1176 #define NOBUG_CAT_(a,b) a##b
1178 #define NOBUG_CAT3(a,b,c) NOBUG_CAT3_(a,b,c)
1179 #define NOBUG_CAT3_(a,b,c) a##b##c
1181 #define NOBUG_HEAD(head, ...) head
1182 #define NOBUG_TAIL(_, ...) , ## __VA_ARGS__
1184 #define NOBUG_STRINGIZE(s) NOBUG_STRINGIZE_(s)
1185 #define NOBUG_STRINGIZE_(s) #s
1189 LIBNOBUG DECLARATIONS
1191 #ifdef __cplusplus
1192 extern "C" {
1193 #endif
1196 envvar control
1198 enum nobug_log_targets
1200 NOBUG_TARGET_RINGBUFFER,
1201 NOBUG_TARGET_CONSOLE,
1202 NOBUG_TARGET_FILE,
1203 NOBUG_TARGET_SYSLOG,
1204 NOBUG_TARGET_APPLICATION
1207 struct nobug_flag
1209 const char* name;
1210 struct nobug_flag* parent;
1211 int initialized;
1212 int limits[5];
1213 struct nobug_ringbuffer* ringbuffer_target;
1214 FILE* console_target;
1215 FILE* file_target;
1219 nobug_env_parse_flag (const char* env, struct nobug_flag* flag, int default_target, int default_limit);
1222 nobug_env_init_flag (struct nobug_flag* flag, int default_target, int default_limit);
1226 ringbuffer
1228 struct nobug_ringbuffer
1230 char* pos;
1231 char* start;
1232 size_t size;
1233 size_t maxmsg;
1234 char name[256];
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 struct nobug_ringbuffer*
1250 nobug_ringbuffer_init (struct nobug_ringbuffer* self, size_t size,
1251 const char * name, int flags);
1253 struct nobug_ringbuffer*
1254 nobug_ringbuffer_new (size_t size, const char * name, int flags);
1256 struct nobug_ringbuffer*
1257 nobug_ringbuffer_destroy (struct nobug_ringbuffer* self);
1259 void
1260 nobug_ringbuffer_delete (struct nobug_ringbuffer* self);
1263 nobug_ringbuffer_vprintf (struct nobug_ringbuffer* self, const char* fmt, va_list ap);
1266 nobug_ringbuffer_printf (struct nobug_ringbuffer* self, const char* fmt, ...);
1268 char*
1269 nobug_ringbuffer_prev (struct nobug_ringbuffer* self, char* pos);
1271 char*
1272 nobug_ringbuffer_next (struct nobug_ringbuffer* self, char* pos);
1275 nobug_ringbuffer_save (struct nobug_ringbuffer* self, FILE* out);
1278 nobug_ringbuffer_load (struct nobug_ringbuffer* self, FILE* in);
1280 char*
1281 nobug_ringbuffer_pos (struct nobug_ringbuffer* self);
1283 void
1284 nobug_ringbuffer_pop (struct nobug_ringbuffer* self);
1288 multithreading extras
1290 #if NOBUG_USE_PTHREAD
1292 struct nobug_tls_data
1294 const char * thread_id;
1295 struct nobug_resource_record* lock_stack;
1298 extern pthread_key_t nobug_tls_key;
1300 const char*
1301 nobug_thread_id_set (const char* name);
1303 const char*
1304 nobug_thread_id_get (void);
1306 extern pthread_mutex_t nobug_global_mutex;
1307 #define NOBUG_LOCK pthread_mutex_lock (&nobug_global_mutex)
1308 #define NOBUG_UNLOCK pthread_mutex_unlock (&nobug_global_mutex)
1309 #else
1310 #define NOBUG_LOCK
1311 #define NOBUG_UNLOCK
1312 #endif
1316 resource registry
1318 struct nobug_resource_record
1320 const char* type; /* type or state */
1321 const char* name; /* name */
1322 void* object_id; /* unique identifer, usually a this pointer or similar */
1323 void* data; /* tree of holders in resouces, backpointer to resource in holders */
1324 const char* extra; /* extra information, file/line usually */
1325 unsigned long counter; /* users or recursive enters */
1326 #if NOBUG_USE_PTHREAD
1327 const char* thread_id;
1328 struct nobug_resource_record* link; /* used by the deadlock detector */
1329 #endif
1332 enum nobug_resource_state
1334 NOBUG_RESOURCE_WAITING,
1335 //NOBUG_RESOURCE_TRYING,
1336 NOBUG_RESOURCE_EXCLUSIVE,
1337 NOBUG_RESOURCE_RECURSIVE
1340 extern void* nobug_resource_registry;
1341 extern FILE* nobug_resource_dump_target;
1343 extern const char* nobug_resource_error;
1345 extern const char* nobug_resource_states[];
1349 struct nobug_resource_record*
1350 nobug_resource_announce (const char* type, const char* name, const void* object_id, const char* extra);
1353 nobug_resource_forget (struct nobug_resource_record* node);
1355 struct nobug_resource_record*
1356 nobug_resource_find (const struct nobug_resource_record* resource, const void* object_id);
1358 struct nobug_resource_record*
1359 nobug_resource_enter (struct nobug_resource_record* resource,
1360 const char* name,
1361 const void* object_id,
1362 enum nobug_resource_state state,
1363 const char* extra);
1366 nobug_resource_state (struct nobug_resource_record* resource,
1367 enum nobug_resource_state state);
1370 nobug_resource_leave (struct nobug_resource_record* handle);
1372 void
1373 nobug_resource_dump (struct nobug_resource_record* resource, FILE* target);
1375 void
1376 nobug_resource_dump_all (FILE* target);
1378 void
1379 nobug_resource_dump_resources (FILE* target);
1383 global config, data and defaults
1385 extern const char* nobug_resource_acquired;
1387 void nobug_init ();
1389 void
1390 nobug_log (struct nobug_flag* flag, int lvl, const char* fmt, ...);
1392 typedef void (*nobug_application_cb)(struct nobug_flag* flag, int priority, const char *log, void* data);
1394 extern struct nobug_ringbuffer nobug_default_ringbuffer;
1395 extern FILE* nobug_default_file;
1396 extern struct nobug_flag nobug_flag_NOBUG_ON;
1397 extern unsigned long long nobug_counter;
1398 extern nobug_application_cb nobug_callback;
1399 extern void* nobug_callback_data;
1401 #ifdef __cplusplus
1402 } /* extern "C" */
1403 #endif
1405 #ifndef NOBUG_LIBNOBUG_C
1408 tag this translation unit as unchecked in ALPHA and BETA builds
1410 NOBUG_IF_NOT_RELEASE(NOBUG_UNCHECKED);
1412 #endif /* NOBUG_LIBNOBUG_C */
1413 #endif