2 This file is part of the NoBug debugging library.
5 2006, 2007, 2008, 2009, Christian Thaeter <ct@pipapo.org>
6 2010, Christian Thaeter <ct@pipapo.org>
7 2009, Francois Kubler <ih8tehuman@free.fr>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, contact Christian Thaeter <ct@pipapo.org>.
25 #ifndef NOBUG_LIBNOBUG_C /* not when building libnobug */
28 #error NDEBUG incompatible with -DEBUG_ALPHA
31 #error NDEBUG incompatible with -DEBUG_BETA
35 #if defined(EBUG_ALPHA)
36 # define NOBUG_MODE_ALPHA 1
37 # define NOBUG_MODE_BETA 0
38 # define NOBUG_MODE_RELEASE 0
39 #elif defined(EBUG_BETA)
40 # define NOBUG_MODE_ALPHA 0
41 # define NOBUG_MODE_BETA 1
42 # define NOBUG_MODE_RELEASE 0
44 # define NOBUG_MODE_ALPHA 0
45 # define NOBUG_MODE_BETA 0
46 # define NOBUG_MODE_RELEASE 1
48 #error no debug level and no NDEBUG defined
50 #endif /* NOBUG_LIBNOBUG_C */
62 #ifdef HAVE_EXECINFO_H
63 # ifndef NOBUG_USE_EXECINFO
64 # define NOBUG_USE_EXECINFO 1
67 # undef NOBUG_USE_EXECINFO
68 # define NOBUG_USE_EXECINFO 0
71 #if NOBUG_USE_EXECINFO
75 #if defined(HAVE_VALGRIND) && !defined(NVALGRIND)
76 # ifndef NOBUG_USE_VALGRIND
77 # define NOBUG_USE_VALGRIND 1
80 # undef NOBUG_USE_VALGRIND
81 # define NOBUG_USE_VALGRIND 0
84 #if NOBUG_USE_VALGRIND
89 # ifndef NOBUG_USE_PTHREAD
90 # define NOBUG_USE_PTHREAD 1
93 # ifdef NOBUG_USE_PTHREAD
94 # undef NOBUG_USE_PTHREAD
96 # define NOBUG_USE_PTHREAD 0
105 figure out how to find out the current function name, this is compiler and language dependent
107 #if !defined(NOBUG_FUNC) && defined(__STDC_VERSION__)
108 /* C99 defines __func__ */
109 # if __STDC_VERSION__ >= 199901L
110 # define NOBUG_FUNC __func__
114 #if !defined(NOBUG_FUNC) && defined(__GNUC__)
115 /* the gnu compiler (since 2.x) defines __FUNCTION__ */
117 # define NOBUG_FUNC __FUNCTION__
121 #if !defined(NOBUG_FUNC) && defined(__SUNPRO_C)
122 /* the sun C compiler defines __FUNCTION__, the version is determined by a sochastic test, please report! */
123 # if __SUNPRO_C >= 0x5100
124 # define NOBUG_FUNC __FUNCTION__
128 /* add more heuristics here... */
131 /* generic fallback, check for some common definitions (its not guranteed that this symbols are preprocessor defines), just some guesswork */
134 # define NOBUG_FUNC __func__
135 # elif defined(__FUNCTION__)
136 # define NOBUG_FUNC __FUNCTION__
138 /* finally a fallback when nothing found */
139 # define NOBUG_FUNC "-"
145 //assertions HEAD- Assertions;;
147 //assertions PARA CHECK; CHECK; unnconditional assertion for testsuites
148 //assertions CHECK(expr, ...)
149 //assertions CHECK_IF(when, expr, ...)
151 //assertions This assertion is never optimized out. Its main purpose is for implementing
152 //assertions testsuites where one want to assert tests independent of the build level
155 #define NOBUG_CHECK(expr, ...) \
156 NOBUG_ASSERT_(expr, "CHECK", NOBUG_CONTEXT, ""__VA_ARGS__)
158 #define NOBUG_CHECK_IF(when, expr, ...) \
159 NOBUG_WHEN(when, NOBUG_CHECK(expr, ""__VA_ARGS__))
163 //assertions PARA REQUIRE; REQUIRE; preconditions (input parameters)
164 //assertions REQUIRE(expr, ...)
165 //assertions REQUIRE_IF(when, expr, ...)
166 //assertions NOBUG_REQUIRE_CTX(expr, context,...)
167 //assertions NOBUG_REQUIRE_IF_CTX(when, expr, context, ...)
169 //assertions Precondition (input) check. Use these macros to validate input a
170 //assertions function receives. The checks are enabled in *ALPHA* and *BETA* builds and
171 //assertions optimized out in *RELEASE* builds.
174 #define NOBUG_REQUIRE(expr, ...) \
175 NOBUG_REQUIRE_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
177 #define NOBUG_REQUIRE_CTX(expr, context, ...) \
178 NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_(expr, "PRECONDITION", context, ""__VA_ARGS__))
181 #define NOBUG_REQUIRE_IF(when, expr, context,...) \
182 NOBUG_REQUIRE_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
184 #define NOBUG_REQUIRE_IF_CTX(when, expr, context,...) \
185 NOBUG_IF_NOT_RELEASE ( \
186 NOBUG_WHEN(when, NOBUG_REQUIRE_CTX(expr, context, ""__VA_ARGS__)) \
191 //assertions PARA ENSURE; ENSURE; postconditions (computation outcomes)
192 //assertions ENSURE(expr, ...)
193 //assertions ENSURE_IF(when, expr, ...)
194 //assertions NOBUG_ENSURE_CTX(expr, context, ...)
195 //assertions NOBUG_ENSURE_IF_CTX(when, expr, context, ...)
197 //assertions Postcondition (progress/output) check. Use these macros to validate the
198 //assertions data a function produces (example: return value). `ENSURE` is enabled
199 //assertions unconditionally in *ALPHA* builds and optimized out in *BETA* builds for
200 //assertions scopes which are tagged as `CHECKED`.
202 //assertions The `ENSURE_IF` variants are enabled in *ALPHA* and *BETA* builds.
204 //assertions In *RELEASE* builds this checks are
205 //assertions always optimized out, scopes tagged as `UNCHECKED` are not permitted.
208 #define NOBUG_ENSURE(expr, ...) \
209 NOBUG_ENSURE_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
211 #define NOBUG_ENSURE_CTX(expr, context, ...) \
212 NOBUG_IF_ALPHA (NOBUG_ASSERT_(expr, "POSTCONDITION", \
213 context, ""__VA_ARGS__)) \
215 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
216 NOBUG_ASSERT_(expr, "POSTCONDITION", \
217 context, ""__VA_ARGS__) \
222 #define NOBUG_ENSURE_IF(when, expr, ...) \
223 NOBUG_ENSURE_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
225 #define NOBUG_ENSURE_IF_CTX(when, expr, context, ...) \
226 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ENSURE(expr, context, ""__VA_ARGS__)))
230 //assertions PARA ASSERT; ASSERT; generic assertion
231 //assertions ASSERT(expr, ...)
232 //assertions ASSERT_IF(when, expr, ...)
233 //assertions NOBUG_ASSERT_CTX(expr, context, ...)
234 //assertions NOBUG_ASSERT_IF_CTX(when, expr, context, ...)
236 //assertions Generic check. Use these macros when you want to validate something
237 //assertions which doesn't fall into one of the above categories. A example is when
238 //assertions a library function can return a unexpected result (scanf with syntax
239 //assertions error in the formatstring, when a constant/literal formatstring is
240 //assertions expected). The checks are enabled in *ALPHA* and *BETA* builds and
241 //assertions optimized out in *RELEASE* builds.
244 #define NOBUG_ASSERT(expr, ...) \
245 NOBUG_ASSERT_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
247 #define NOBUG_ASSERT_CTX(expr, context, ...) \
248 NOBUG_IF_NOT_RELEASE( \
249 NOBUG_ASSERT_(expr, "ASSERTION", \
250 context, ""__VA_ARGS__) \
254 #define NOBUG_ASSERT_IF(when, expr, ...) \
255 NOBUG_ASSERT_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
257 #define NOBUG_ASSERT_IF_CTX(when, expr, context, ...) \
258 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ASSERT_CTX(expr, context, ""__VA_ARGS__)))
262 //assertions PARA assert; assert; C standard assertion
263 //assertions assert(expr)
265 //assertions NoBug overrides the standard `assert` macro, using `NOBUG_ASSERT`.
266 //assertions This is just a compatibility feature, its use is not suggested.
270 #define assert(expr) NOBUG_ASSERT(expr)
277 #define NOBUG_ASSERT_(expr, what, context, fmt, ...) \
278 NOBUG_WHEN (!(expr), \
279 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
280 what, context, "(%s) " fmt, \
281 #expr, ## __VA_ARGS__); \
282 NOBUG_BACKTRACE_CTX(context); \
285 #else /* , ## __VA_ARGS__ eating the comma when the arglist is empty is a gcc extension, fallback for other compilers */
286 #define NOBUG_ASSERT_(expr, what, context, ...) \
287 NOBUG_WHEN (!(expr), \
288 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
291 NOBUG_BACKTRACE_CTX(context); \
297 //assertions PARA INVARIANT; INVARIANT; validate invariant state
298 //assertions INVARIANT(type, pointer, depth)
299 //assertions INVARIANT_IF(when,type, pointer, depth)
300 //assertions INVARIANT_ASSERT(expr, ...)
302 //assertions Checking invariants. You can provide more complex checking functions
303 //assertions which test the validity of datastructures. Invariants are only enabled
304 //assertions in *ALPHA* builds for scopes which are not tagged as `CHECKED` and
305 //assertions otherwise optimized out.
307 //assertions TODO: describe how to create invariant checks
309 // 'invariant_context' must be passed in
311 #define NOBUG_INVARIANT(type, pointer, depth, extra) \
313 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
314 NOBUG_CAT3(nobug_, type,_invariant)(pointer, depth, \
315 NOBUG_CONTEXT, extra) \
320 #define NOBUG_INVARIANT_IF(when, type, pointer, depth, extra) \
322 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
324 NOBUG_CAT3(nobug_, type,_invariant)(pointer, depth, \
330 #define NOBUG_INVARIANT_ASSERT(expr, ...) \
331 NOBUG_ASSERT_(expr, "INVARIANT", invariant_context, ""__VA_ARGS__)
335 checked/unchecked tagged scopes
337 #define NOBUG_SCOPE_UNCHECKED NOBUG_CHECKED_VALUE == 0
339 #define NOBUG_CHECKED NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=1})
341 #define NOBUG_UNCHECKED \
342 NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=0}) \
343 NOBUG_IF_RELEASE(NOBUG_UNCHECKED_NOT_ALLOWED_IN_RELEASE_BUILD)
347 /*TODO dump-level for flags instead limits[0]*/
349 //dumpmacros PARA DUMP; DUMP; dumping datastructures
350 //dumpmacros DUMP(flag, type, pointer, depth, extra)
351 //dumpmacros DUMP_IF(when, flag, type, pointer, depth, extra)
353 //dumpmacros This macros call a datastructure dump of the object (`pointer`) in question.
354 //dumpmacros `DUMP` is only available in *ALPHA* and *BETA* builds, `DUMP_IF` is also
355 //dumpmacros enabled for the RELEASE builds.
357 //dumpmacros `extra` is a void* which is transparently passed around and can be used to
358 //dumpmacros pass some state around. NoBug does not touch it.
361 #define NOBUG_DUMP(flag, type, pointer, depth, extra) \
362 NOBUG_IF_NOT_RELEASE( \
363 NOBUG_WHEN (NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET], \
364 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, NOBUG_CONTEXT, extra) \
368 #define NOBUG_DUMP_IF(when, flag, type, pointer, depth, extra) \
369 NOBUG_WHEN (NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET] && when, \
370 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, NOBUG_CONTEXT, extra) \
375 //dumpmacros PARA DUMP_LOG; DUMP_LOG; logging helper for dumping
376 //dumpmacros DUMP_LOG(...)
377 //dumpmacros DUMP_LOG_IF(when, ...)
379 //dumpmacros Any output from `DUMP` handlers should be done by these macros.
381 //dumpmacros Dumping is by default done on level `LOG_DEBUG`, this can be overridden by
382 //dumpmacros defining `NOBUG_DUMP_LEVEL` to some other level.
386 #define NOBUG_DUMP_LOG(...) \
387 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
388 "DUMP", dump_context, \
391 #define NOBUG_DUMP_LOG_IF(expr, ...) \
393 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
394 "DUMP", dump_context, \
399 #ifndef NOBUG_DUMP_LEVEL
400 #define NOBUG_DUMP_LEVEL LOG_DEBUG
404 //logmacros HEAD- Logging Macros;;
406 //logmacros Logging targets a flag (except for `ECHO`) and is done at a log-level relating to syslog levels.
408 //logmacros NOTE: there is no logging macro for `LOG_EMERG`, this is only used by the assertions as fatal message
410 //logmacros PARA ECHO; ECHO; unconditional logging for tests
411 //logmacros ECHO(...)
413 //logmacros Never optimized out, logs at LOG_NOTICE level. Its main purpose is for implementing
414 //logmacros testsuites where one want to print and log messages independent of the build level
417 #define NOBUG_ECHO(...) \
418 NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_NOTICE, "ECHO", NOBUG_CONTEXT, ""__VA_ARGS__)
421 //logmacros PARA ALERT; ALERT; about to die
422 //logmacros ALERT(flag, ...)
423 //logmacros ALERT_IF(when, flag, ...)
424 //logmacros NOBUG_ALERT_CTX(flag, context, ...)
425 //logmacros NOBUG_ALERT_IF_CTX(when, flag, context, ...)
427 //logmacros This is the most critical condition an application might log. This might be used
428 //logmacros if an error occurs which can not be handled except a safe shutdown for example.
431 #define NOBUG_ALERT(flag, ...) \
432 NOBUG_ALERT_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
434 #define NOBUG_ALERT_IF(expr, flag, ...) \
435 NOBUG_ALERT_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
438 #define NOBUG_ALERT_CTX(flag, context, ...) \
439 NOBUG_LOG_CTX(flag, LOG_ALERT, context, ""__VA_ARGS__)
441 #define NOBUG_ALERT_IF_CTX(expr, flag, context, ...) \
442 NOBUG_LOG_IF(expr, flag, LOG_ALERT, context, ""__VA_ARGS__)
447 //logmacros PARA CRITICAL; CRITICAL; can not continue
448 //logmacros CRITICAL(flag, ...)
449 //logmacros CRITICAL_IF(when, flag, ...)
450 //logmacros NOBUG_CRITICAL_CTX(flag, context, ...)
451 //logmacros NOBUG_CRITICAL_IF_CTX(when, flag, context, ...)
453 //logmacros An error which can not be handled occured but the application does not need to be
454 //logmacros shutdowen, perhaps waiting for an operator to fix the cause.
457 #define NOBUG_CRITICAL(flag, ...) \
458 NOBUG_CRITICAL_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
460 #define NOBUG_CRITICAL_CTX(flag, context, ...) \
461 NOBUG_LOG_CTX(flag, LOG_CRIT, context, ""__VA_ARGS__)
464 #define NOBUG_CRITICAL_IF(expr, flag, ...) \
465 NOBUG_CRITICAL_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
467 #define NOBUG_CRITICAL_IF_CTX(expr, flag, context, ...) \
468 NOBUG_LOG_IF_CTX(expr, flag, LOG_CRIT, context, ""__VA_ARGS__)
472 //logmacros PARA ERROR; ERROR; something gone wrong
473 //logmacros ERROR(flag, ...)
474 //logmacros ERROR_IF(when, flag, ...)
475 //logmacros NOBUG_ERROR_CTX(flag, context, ...)
476 //logmacros NOBUG_ERROR_IF_CTX(when, flag, context, ...)
478 //logmacros Application takes a error handling brach
481 #define NOBUG_ERROR(flag, ...) \
482 NOBUG_ERROR_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
484 #define NOBUG_ERROR_CTX(flag, context, ...) \
485 NOBUG_LOG_CTX(flag, LOG_ERR, context, ""__VA_ARGS__)
488 #define NOBUG_ERROR_IF(expr, flag, ...) \
489 NOBUG_ERROR_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
491 #define NOBUG_ERROR_IF_CTX(expr, flag, context, ...) \
492 NOBUG_LOG_IF_CTX(expr, flag, LOG_ERR, context, ""__VA_ARGS__)
496 //logmacros PARA WARN; WARN; unexpected fixable error
497 //logmacros WARN(flag, ...)
498 //logmacros WARN_IF(when, flag, ...)
499 //logmacros NOBUG_WARN_CTX(flag, context, ...)
500 //logmacros NOBUG_WARN_IF_CTX(when, flag, context, ...)
502 //logmacros Rare, handled but unexpected branch
505 #define NOBUG_WARN(flag, ...) \
506 NOBUG_WARN_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
508 #define NOBUG_WARN_CTX(flag, context, ...) \
509 NOBUG_LOG_CTX(flag, LOG_WARNING, context, ""__VA_ARGS__)
512 #define NOBUG_WARN_IF(expr, flag, ...) \
513 NOBUG_WARN_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
515 #define NOBUG_WARN_IF_CTX(expr, flag, context, ...) \
516 NOBUG_LOG_IF_CTX(expr, flag, LOG_WARNING, context, ""__VA_ARGS__)
520 //logmacros PARA INFO; INFO; progress message
521 //logmacros INFO(flag, ...)
522 //logmacros INFO_IF(when, flag, ...)
523 //logmacros NOBUG_INFO_CTX(flag, context, ...)
524 //logmacros NOBUG_INFO_IF_CTX(when, flag, context, ...)
526 //logmacros Message about program progress
529 #define NOBUG_INFO(flag, ...) \
530 NOBUG_INFO_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
532 #define NOBUG_INFO_CTX(flag, context, ...) \
533 NOBUG_LOG_CTX(flag, LOG_INFO, context, ""__VA_ARGS__)
536 #define NOBUG_INFO_IF(expr, flag, ...) \
537 NOBUG_INFO_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
539 #define NOBUG_INFO_IF_CTX(expr, flag, context, ...) \
540 NOBUG_LOG_IF_CTX(expr, flag, LOG_INFO, context, ""__VA_ARGS__)
544 //logmacros PARA NOTICE; NOTICE; detailed progress message
545 //logmacros NOTICE(flag, ...)
546 //logmacros NOTICE_IF(when, flag, ...)
547 //logmacros NOBUG_NOTICE_CTX(flag, context, ...)
548 //logmacros NOBUG_NOTICE_IF_CTX(when, flag, context, ...)
550 //logmacros More detailed progress message
553 #define NOBUG_NOTICE(flag, ...) \
554 NOBUG_NOTICE_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
556 #define NOBUG_NOTICE_CTX(flag, context, ...) \
557 NOBUG_LOG_CTX(flag, LOG_NOTICE, context, ""__VA_ARGS__)
560 #define NOBUG_NOTICE_IF(expr, flag, ...) \
561 NOBUG_NOTICE_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
563 #define NOBUG_NOTICE_IF_CTX(expr, flag, context, ...) \
564 NOBUG_LOG_IF_CTX(expr, flag, LOG_NOTICE, context, ""__VA_ARGS__)
567 //logmacros PARA TRACE; TRACE; debugging level message
568 //logmacros TRACE(flag, ...)
569 //logmacros TRACE_IF(when, flag, ...)
570 //logmacros NOBUG_TRACE_CTX(flag, context, ...)
571 //logmacros NOBUG_TRACE_IF_CTX(when, flag, context, ...)
573 //logmacros Very fine grained messages
575 //logmacros NOTE: that `TRACE` corresponds to `LOG_DEBUG`, because using `DEBUG` could be ambiguous.
578 #define NOBUG_TRACE(flag, ...) \
579 NOBUG_TRACE_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
581 #define NOBUG_TRACE_CTX(flag, context, ...) \
582 NOBUG_LOG_CTX(flag, LOG_DEBUG, context, ""__VA_ARGS__)
585 #define NOBUG_TRACE_IF(expr, flag, ...) \
586 NOBUG_TRACE_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
588 #define NOBUG_TRACE_IF_CTX(expr, flag, context, ...) \
589 NOBUG_LOG_IF_CTX(expr, flag, LOG_DEBUG, context, ""__VA_ARGS__)
593 //logmacros PARA LOG; LOG; generic logging
594 //logmacros NOBUG_LOG_CTX(flag, lvl, context, ...)
595 //logmacros NOBUG_LOG_IF_CTX(when, flag, lvl, context, ...)
597 //logmacros Generic logging macro which takes the level explicitly,
598 //logmacros avoid this, unless you implement your own logging facilities.
601 #define NOBUG_LOG_CTX(flag, lvl, context, ...) \
602 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LVL(lvl), context, ""__VA_ARGS__)
605 #define NOBUG_LOG_IF_CTX(expr, flag, lvl, context, ...) \
607 NOBUG_LOG_CTX(flag, lvl, context, ""__VA_ARGS__) \
612 low level logging handler
614 Note: all fmt concatenations use an empty string ""__VA_ARG__
615 except this one which must use a single space " " before __VA_ARGS__ for formatting the log message correctly (and silence a gcc warning)
617 #define NOBUG_LOG_(flag, lvl, what, context, ...) \
618 NOBUG_WHEN (lvl <= NOBUG_LOG_BASELIMIT && lvl <= (flag)->limits[NOBUG_TARGET_RINGBUFFER], \
619 nobug_log (flag, lvl, what, context, " "__VA_ARGS__) \
623 #define NOBUG_LVL(lvl) NOBUG_LVL_##lvl
624 #define NOBUG_LVL_0 "EMERG"
625 #define NOBUG_LVL_1 "ALERT"
626 #define NOBUG_LVL_2 "CRIT"
627 #define NOBUG_LVL_3 "ERR"
628 #define NOBUG_LVL_4 "WARNING"
629 #define NOBUG_LVL_5 "NOTICE"
630 #define NOBUG_LVL_6 "INFO"
631 #define NOBUG_LVL_7 "TRACE"
634 //logmacros PARA LOG_BASELIMIT; LOG_BASELIMIT; minimum compliled-in logging limit
635 //logmacros NOBUG_LOG_BASELIMIT_ALPHA
636 //logmacros NOBUG_LOG_BASELIMIT_BETA
637 //logmacros NOBUG_LOG_BASELIMIT_RELEASE
638 //logmacros NOBUG_LOG_BASELIMIT
640 //logmacros anything more detailed than this base limits will be optimized out.
641 //logmacros This is used to reduce the logging overhead for *RELEASE* builds.
642 //logmacros By default the limit is set to `LOG_DEBUG` for *ALPHA* and *BETA*
643 //logmacros builds, so all logging is retained and `LOG_NOTICE` in *RELEASE*
644 //logmacros builds to log the application progress only coarsely then.
646 //logmacros This macros can be defined before including 'nobug.h' to some other
647 //logmacros log level (as defined in 'syslog.h').
650 #ifndef NOBUG_LOG_BASELIMIT_ALPHA
651 #define NOBUG_LOG_BASELIMIT_ALPHA LOG_DEBUG
654 #ifndef NOBUG_LOG_BASELIMIT_BETA
655 #define NOBUG_LOG_BASELIMIT_BETA LOG_DEBUG
658 #ifndef NOBUG_LOG_BASELIMIT_RELEASE
659 #define NOBUG_LOG_BASELIMIT_RELEASE LOG_NOTICE
662 #ifndef NOBUG_LOG_BASELIMIT
663 #define NOBUG_LOG_BASELIMIT \
664 NOBUG_IF_ALPHA(NOBUG_LOG_BASELIMIT_ALPHA) \
665 NOBUG_IF_BETA(NOBUG_LOG_BASELIMIT_BETA) \
666 NOBUG_IF_RELEASE(NOBUG_LOG_BASELIMIT_RELEASE)
671 //srccontext HEAD~ Source Contexts; NOBUG_CONTEXT; pass information about the source location
672 //srccontext NOBUG_CONTEXT
673 //srccontext NOBUG_CONTEXT_NOFUNC
675 //srccontext NoBug passes information about the source location of a given statement in
676 //srccontext `const struct nobug_context` structures. These can be generated with
677 //srccontext `NOBUG_CONTEXT` or `NOBUG_CONTEXT_NOFUNC`. The later one doesn't define a
678 //srccontext function name and must be used when the function context is not available
679 //srccontext like in static initialization etc..
684 #define NOBUG_CONTEXT ((const struct nobug_context){__FILE__, __LINE__, NOBUG_FUNC})
686 #define NOBUG_CONTEXT_NOFUNC ((const struct nobug_context){__FILE__, __LINE__, "-"})
688 #define NOBUG_CONTEXT_NIL ((const struct nobug_context){"-", 0, "-"})
691 #define NOBUG_CONTEXT (nobug_context(__FILE__, __LINE__, NOBUG_FUNC))
693 #define NOBUG_CONTEXT_NOFUNC (nobug_context(__FILE__, __LINE__, "-"))
695 #define NOBUG_CONTEXT_NIL (nobug_context("-", 0, "-"))
699 //annotations HEAD- Source Annotations;;
701 //annotations One can tag features as:
707 DEPRECATED log nothing wont compile
709 //annotations PARA DEPRECATED; DEPRECATED; to be discarded in future
710 //annotations DEPRECATED(...)
712 //annotations Something which shouldn't be used in future
715 #define NOBUG_DEPRECATED(...) \
716 NOBUG_IF_ALPHA(NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_WARN, \
717 "DEPRECATED", NOBUG_CONTEXT, ""__VA_ARGS__) \
719 NOBUG_IF_RELEASE(NOBUG_DEPRECATED_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
724 UNIMPLEMENTED abort abort wont compile
726 //annotations PARA UNIMPLEMENTED; UNIMPLEMENTED; not yet implemented
727 //annotations UNIMPLEMENTED(...)
729 //annotations not yet finished feature
732 #define NOBUG_UNIMPLEMENTED(...) \
733 NOBUG_IF_NOT_RELEASE ( do { \
734 NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_EMERG, \
735 "UNIMPLEMENTED", NOBUG_CONTEXT, ""__VA_ARGS__); \
738 NOBUG_IF_RELEASE( NOBUG_UNIMPLEMENTED_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
743 FIXME log wont compile wont compile
745 //annotations PARA FIXME; FIXME; known bug
746 //annotations FIXME(...)
748 //annotations known bug to be fixed later
751 #define NOBUG_FIXME(...) \
752 NOBUG_IF_ALPHA( NOBUG_ONCE( NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_ALERT, \
753 "FIXME", NOBUG_CONTEXT, ""__VA_ARGS__))) \
754 NOBUG_IF_BETA( NOBUG_FIXME_NOT_ALLOWED_IN_BETA_BUILD(__VA_ARGS__)) \
755 NOBUG_IF_RELEASE( NOBUG_FIXME_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
760 TODO log log wont compile
762 //annotations PARA TODO; TODO; things to be done
763 //annotations TODO(...)
765 //annotations enhancement to be done soon
768 #define NOBUG_TODO(...) \
769 NOBUG_IF_NOT_RELEASE ( \
771 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_NOTICE, \
772 "TODO", NOBUG_CONTEXT, ""__VA_ARGS__); \
774 NOBUG_IF_RELEASE(NOBUG_TODO_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
779 PLANNED log nothing nothing
781 //annotations PARA PLANNED; PLANNED; ideas for future
782 //annotations PLANNED(...)
784 //annotations future enhancement
787 #define NOBUG_PLANNED(...) \
788 NOBUG_IF_ALPHA( NOBUG_ONCE(NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_INFO, \
789 "PLANNED", NOBUG_CONTEXT, ""__VA_ARGS__)))
794 NOTREACHED abort abort nothing
796 //annotations PARA NOTREACHED; NOTREACHED; code path never taken
797 //annotations NOTREACHED(...)
799 //annotations used to tag code-path which shall be never executed.
802 #define NOBUG_NOTREACHED(...) \
803 NOBUG_IF_NOT_RELEASE( do { \
804 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG, \
805 "NOTREACHED", NOBUG_CONTEXT, ""__VA_ARGS__); \
811 //annotations PARA ELSE_NOTREACHED; ELSE_NOTREACHED; alternative never taken
812 //annotations ELSE_NOTREACHED(...)
814 //annotations same as `else NOTREACHED()`, but wholly optimized out in release builds.
817 #define NOBUG_ELSE_NOTREACHED(...) \
818 NOBUG_IF_NOT_RELEASE( else do { \
819 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG, \
820 "ELSE_NOTREACHED", NOBUG_CONTEXT, ""__VA_ARGS__); \
826 //faultinjection HEAD- Fault injection;;
828 //faultinjection NoBug has some macros which can be used to simulate errorneous behaviour:
830 //faultinjection PARA INJECT_GOODBAD; INJECT_GOODBAD; fault injection expression
831 //faultinjection INJECT_GOODBAD(expr, good, bad)
833 //faultinjection substitutes to an expression and returns good when expr is false and
834 //faultinjection bad when expr is true. In BETA and RELEASE builds 'good' is always returned.
837 #define NOBUG_INJECT_GOODBAD(expr, good, bad) \
838 NOBUG_IF_ALPHA((expr)?({NOBUG_INJECT_LOG(#expr": "#bad);bad;}):good) \
839 NOBUG_IF_NOT_ALPHA(good)
843 //faultinjection PARA INJECT_FAULT; INJECT_FAULT; fault injection statement
844 //faultinjection INJECT_FAULT(expr, bad)
846 //faultinjection substitutes to a statement which executes 'bad'
847 //faultinjection when expr is true. Optimitzed out in BETA and RELEASE builds.
850 #define NOBUG_INJECT_FAULT(expr, bad) \
851 NOBUG_IF_ALPHA(NOBUG_WHEN(expr,NOBUG_INJECT_LOG(#expr": "#bad); bad))
855 //faultinjection PARA INJECT_LEVEL; INJECT_LEVEL; log level for fault injection
856 //faultinjection In both cases, when a fault is injected it will be logged at
857 //faultinjection `NOBUG_INJECT_LEVEL` (default: `LOG_NOTICE`). This can be defined
858 //faultinjection before including 'nobug.h' to override it.
861 #define NOBUG_INJECT_LOG(msg) \
862 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_INJECT_LEVEL, \
863 "INJECT_FAULT", NOBUG_CONTEXT, \
867 #ifndef NOBUG_INJECT_LEVEL
868 #define NOBUG_INJECT_LEVEL LOG_NOTICE
875 #define NOBUG_FLAG(name) NOBUG_CAT(nobug_flag_, name)
877 #define NOBUG_DECLARE_FLAG(name) extern struct nobug_flag NOBUG_FLAG(name)
880 #define NOBUG_DEFINE_FLAG(name) \
881 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
882 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
883 struct nobug_flag NOBUG_FLAG(name) = \
884 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
885 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
886 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
887 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
888 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
889 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
893 #define NOBUG_DEFINE_FLAG_PARENT(name, parent) \
894 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
895 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
896 NOBUG_DECLARE_FLAG(parent); \
897 struct nobug_flag NOBUG_FLAG(name) = \
898 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
899 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
900 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
901 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
902 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
903 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
907 #define NOBUG_DEFINE_FLAG_LIMIT(name, limit) \
908 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
909 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
910 struct nobug_flag NOBUG_FLAG(name) = \
911 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
912 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
913 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
914 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
915 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
916 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
920 #define NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, limit) \
921 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
922 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
923 NOBUG_DECLARE_FLAG(parent); \
924 struct nobug_flag NOBUG_FLAG(name) = \
925 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
926 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
927 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
928 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
929 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
930 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
934 #define NOBUG_INIT_FLAG(name) \
935 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, NOBUG_LOG_LIMIT, NOBUG_CONTEXT_NOFUNC)
938 #define NOBUG_INIT_FLAG_LIMIT(name, default) \
939 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, default, NOBUG_CONTEXT_NOFUNC)
942 #define NOBUG_CPP_DEFINE_FLAG(name) \
943 NOBUG_FLAG_IF_DECLAREONLY( \
944 NOBUG_DECLARE_FLAG(name); \
945 extern int nobug_cppflag_##name \
947 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
948 NOBUG_DEFINE_FLAG(name); \
949 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
953 #define NOBUG_CPP_DEFINE_FLAG_PARENT(name, parent) \
954 NOBUG_FLAG_IF_DECLAREONLY( \
955 NOBUG_DECLARE_FLAG(name); \
956 extern int nobug_cppflag_##name \
958 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
959 NOBUG_DEFINE_FLAG_PARENT(name, parent); \
960 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
964 #define NOBUG_CPP_DEFINE_FLAG_LIMIT(name, default) \
965 NOBUG_FLAG_IF_DECLAREONLY( \
966 NOBUG_DECLARE_FLAG(name); \
967 extern int nobug_cppflag_##name \
969 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
970 NOBUG_DEFINE_FLAG_LIMIT(name, default); \
971 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
975 #define NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT(name, parent, default) \
976 NOBUG_FLAG_IF_DECLAREONLY( \
977 NOBUG_DECLARE_FLAG(name); \
978 extern int nobug_cppflag_##name \
980 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
981 NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, default); \
982 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
986 #ifndef NOBUG_DECLARE_ONLY
987 #define NOBUG_DECLARE_ONLY 0
990 #define NOBUG_FLAG_IF_DECLAREONLY(...) \
991 NOBUG_IF(NOBUG_DECLARE_ONLY, __VA_ARGS__)
993 #define NOBUG_FLAG_IF_NOT_DECLAREONLY(...) \
994 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
997 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
998 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
1000 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
1001 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, NOBUG_ERROR_CANT_DEFINE_AUTOINITIALIZED_CPP_FLAGS_IN_C)
1004 #ifndef NOBUG_LOG_LIMIT_ALPHA
1005 # define NOBUG_LOG_LIMIT_ALPHA LOG_INFO
1007 #ifndef NOBUG_LOG_LIMIT_BETA
1008 # define NOBUG_LOG_LIMIT_BETA LOG_WARNING
1010 #ifndef NOBUG_LOG_LIMIT_RELEASE
1011 # define NOBUG_LOG_LIMIT_RELEASE LOG_CRIT
1014 #ifndef NOBUG_LOG_LIMIT
1015 # define NOBUG_LOG_LIMIT \
1016 NOBUG_IF_ALPHA( NOBUG_LOG_LIMIT_ALPHA) \
1017 NOBUG_IF_BETA( NOBUG_LOG_LIMIT_BETA) \
1018 NOBUG_IF_RELEASE( NOBUG_LOG_LIMIT_RELEASE)
1021 #ifndef NOBUG_LOG_TARGET_ALPHA
1022 # define NOBUG_LOG_TARGET_ALPHA NOBUG_TARGET_CONSOLE
1024 #ifndef NOBUG_LOG_TARGET_BETA
1025 # define NOBUG_LOG_TARGET_BETA NOBUG_TARGET_FILE
1027 #ifndef NOBUG_LOG_TARGET_RELEASE
1028 # define NOBUG_LOG_TARGET_RELEASE NOBUG_TARGET_SYSLOG
1031 #ifndef NOBUG_LOG_TARGET
1032 # define NOBUG_LOG_TARGET \
1033 NOBUG_IF_ALPHA( NOBUG_LOG_TARGET_ALPHA) \
1034 NOBUG_IF_BETA( NOBUG_LOG_TARGET_BETA) \
1035 NOBUG_IF_RELEASE( NOBUG_LOG_TARGET_RELEASE)
1038 #define NOBUG_SET_LIMIT(flag, min) \
1039 NOBUG_IF_NOT_RELEASE( NOBUG_FLAG(flag) = (min))
1043 //resourcemacros HEAD~ Resource tracking macros;;
1045 //resourcemacros INDEX RESOURCE_LOGGING; RESOURCE_LOGGING; switch resource logging on and off
1046 //resourcemacros INDEX RESOURCE_LOG_LEVEL; RESOURCE_LOG_LEVEL; select the log level for resource logging
1048 //resourcemacros Unless the user defines `NOBUG_RESOURCE_LOGGING` to 0 each of the above macros
1049 //resourcemacros will emit a log message at `NOBUG_RESOURCE_LOG_LEVEL` which defaults to
1050 //resourcemacros `LOG_DEBUG`.
1053 #ifndef NOBUG_RESOURCE_LOGGING
1054 #define NOBUG_RESOURCE_LOGGING 1
1057 #ifndef NOBUG_RESOURCE_LOG_LEVEL
1058 #define NOBUG_RESOURCE_LOG_LEVEL LOG_DEBUG
1063 //resourcemacros PARA RESOURCE_HANDLE; RESOURCE_HANDLE; define resource handles
1064 //resourcemacros RESOURCE_HANDLE(name)
1065 //resourcemacros RESOURCE_HANDLE_INIT(name)
1066 //resourcemacros RESOURCE_USER(name)
1067 //resourcemacros RESOURCE_USER_INIT(name)
1069 //resourcemacros Define and initialize handles for to track resources.
1071 //resourcemacros `name`::
1072 //resourcemacros identifer to be used for the handle
1074 //resourcemacros There are two kinds of handles, each resource itself is abstracted with a
1075 //resourcemacros `RESOURCE_HANDLE` and every access to this resources is tracked through a
1076 //resourcemacros `RESOURCE_USER` handle. These macros takes care that the declaration is optimized
1077 //resourcemacros out in the same manner as the rest of the resource tracker would be disabled.
1078 //resourcemacros You can still instantiate handles as `struct nobug_resource_record*` or
1079 //resourcemacros `struct nobug_resource_user*` in structures which must have a constant size
1080 //resourcemacros unconditional of the build level. The two `*_INIT` macros can be used to initialize
1081 //resourcemacros resource handles and are optimized out when the resource tracker gets disabled.
1084 #define NOBUG_RESOURCE_HANDLE(handle) \
1085 NOBUG_IF_ALPHA(struct nobug_resource_record* handle)
1087 #define NOBUG_RESOURCE_HANDLE_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
1089 #define NOBUG_RESOURCE_USER(handle) \
1090 NOBUG_IF_ALPHA(struct nobug_resource_user* handle)
1092 #define NOBUG_RESOURCE_USER_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
1096 //resourcemacros PARA RESOURCE_ANNOUNCE; RESOURCE_ANNOUNCE; publish new resources
1097 //resourcemacros RESOURCE_ANNOUNCE(flag, type, name, identifier, handle)
1098 //resourcemacros NOBUG_RESOURCE_ANNOUNCE_RAW(flagptr, type, name, ptr, handle)
1099 //resourcemacros NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(flagptr, type, name, ptr, handle, context)
1101 //resourcemacros Publishes resources.
1103 //resourcemacros `flag`::
1104 //resourcemacros the NoBug flag name which turns logging on for this macro
1105 //resourcemacros `type`::
1106 //resourcemacros a string which should denote the domain of the resource,
1107 //resourcemacros examples are "file", "mutex", "lock", "database" and so on
1108 //resourcemacros `name`::
1109 //resourcemacros the actual name of a named resource this as string which
1110 //resourcemacros together with type forms a unique identifier of the resource. `type` and
1111 //resourcemacros `name` must be available through the entire lifetime of the resource, using
1112 //resourcemacros literal strings is recommended
1113 //resourcemacros `identifier`::
1114 //resourcemacros a pointer which should be unique for this resource, any
1115 //resourcemacros kind of pointer will suffice, it is only used for identification. In
1116 //resourcemacros multithreaded applications the thread identifier becomes an additional
1117 //resourcemacros identifier
1118 //resourcemacros `handle`::
1119 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to point to
1120 //resourcemacros the newly created resource.
1122 //resourcemacros Resources must be unique, it is a fatal error when a resource it tried to be
1123 //resourcemacros announced more than one time.
1125 //resourcemacros 'RESOURCE_ANNOUNCE()' acts like the head of a C loop statement, it ties to the following
1126 //resourcemacros (block-) statement. Leaving and the user defined following statement are atomic.
1127 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1130 #define NOBUG_RESOURCE_ANNOUNCE(flag, type, name, ptr, handle) \
1131 NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(&NOBUG_FLAG(flag), type, name, ptr, handle, NOBUG_CONTEXT)
1134 #define NOBUG_RESOURCE_ANNOUNCE_RAW(flag, type, name, ptr, handle) \
1135 NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(flag, type, name, ptr, handle, NOBUG_CONTEXT)
1138 #define NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(flag, type, name, ptr, handle, context) \
1139 NOBUG_IF_NOT_RELEASE( for ( \
1140 int NOBUG_CLEANUP(nobug_section_cleaned) section_ = \
1142 NOBUG_REQUIRE_CTX(!handle, context, "Announced resource handle not initialized"); \
1143 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1144 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1145 "RESOURCE_ANNOUNCE", context, \
1146 "%s: %s@%p", type, name, ptr);) \
1148 NOBUG_RESOURCE_ASSERT_CTX(handle = nobug_resource_announce (type, name, \
1151 "RESOURCE_ASSERT_ANNOUNCE", context, \
1152 "%s: %s@%p %s", type, name, ptr, nobug_resource_error); \
1158 NOBUG_IF_ALPHA (nobug_resource_announce_complete ();) \
1164 //resourcemacros PARA RESOURCE_FORGET; RESOURCE_FORGET; remove resources
1165 //resourcemacros RESOURCE_FORGET(flag, handle)
1166 //resourcemacros NOBUG_RESOURCE_FORGET_RAW(flagptr, handle)
1167 //resourcemacros NOBUG_RESOURCE_FORGET_RAW_CTX(flagptr, handle, context)
1169 //resourcemacros Removes resources that have become unavailable from the registry.
1171 //resourcemacros `flag`::
1172 //resourcemacros the NoBug flag which turns logging on for this macro
1173 //resourcemacros `handle`::
1174 //resourcemacros the `NOBUG_RESOURCE_HANDLE` used to track this resource
1176 //resourcemacros The resource must still exist and no users must be attached to it, else a fatal
1177 //resourcemacros error is raised.
1179 //resourcemacros 'RESOURCE_FORGET()' acts like the head of a C loop statement, it ties to the following
1180 //resourcemacros (block-) statement. Leaving and the user defined following statement are atomic.
1181 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1184 #define NOBUG_RESOURCE_FORGET(flag, handle) \
1185 NOBUG_RESOURCE_FORGET_RAW_CTX(&NOBUG_FLAG(flag), handle, NOBUG_CONTEXT)
1187 #define NOBUG_RESOURCE_FORGET_RAW(flag, handle) \
1188 NOBUG_RESOURCE_FORGET_RAW_CTX(flag, handle, NOBUG_CONTEXT)
1190 #define NOBUG_RESOURCE_FORGET_RAW_CTX(flag, handle, context) \
1191 NOBUG_IF_NOT_RELEASE( for ( \
1192 int NOBUG_CLEANUP(nobug_section_cleaned) section_ = \
1194 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1195 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1196 "RESOURCE_FORGET", context, "%s: %s@%p", \
1197 (handle)?(handle)->type:"", \
1198 (handle)?(handle)->hdr.name:"", \
1199 (handle)?(handle)->object_id:NULL);) \
1205 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_forget (handle), \
1206 "RESOURCE_ASSERT_FORGET", context, "%s: %s@%p: %s", \
1207 (handle)?(handle)->type:"", \
1208 (handle)?(handle)->hdr.name:"", \
1209 (handle)?(handle)->object_id:NULL, \
1210 nobug_resource_error); \
1218 //resourcemacros PARA RESOURCE_ENTER; RESOURCE_ENTER; claim a resource
1219 //resourcemacros RESOURCE_ENTER(flag, announced, user, state, handle)
1220 //resourcemacros NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, state, handle, context)
1222 //resourcemacros Acquire a resource.
1224 //resourcemacros `flag`::
1225 //resourcemacros nobug flag which turns logging on for this macro
1226 //resourcemacros `announced`::
1227 //resourcemacros the handle set by `RESOURCE_ANNOUNCE`
1228 //resourcemacros `user`::
1229 //resourcemacros a free-form identifier
1230 //resourcemacros `state`::
1231 //resourcemacros the initial state, one of `NOBUG_RESOURCE_WAITING`, `NOBUG_RESOURCE_TRYING`,
1232 //resourcemacros `NOBUG_RESOURCE_EXCLUSIVE`, `NOBUG_RESOURCE_RECURSIVE` or `NOBUG_RESOURCE_SHARED`
1233 //resourcemacros `handle`::
1234 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to the
1235 //resourcemacros entering node
1237 //resourcemacros 'RESOURCE_ENTER()' acts like the head of a C loop statement, it ties to the following
1238 //resourcemacros (block-) statement. Leaving and the user defined following statement are atomic.
1239 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1242 #define NOBUG_RESOURCE_ENTER(flag, resource, user, state, handle) \
1243 NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, state, handle, NOBUG_CONTEXT)
1246 #define NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, state, handle, context) \
1247 NOBUG_IF_NOT_RELEASE( for ( \
1248 int NOBUG_CLEANUP(nobug_section_cleaned) section_ = \
1250 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1251 NOBUG_LOG_(&NOBUG_FLAG(flag), NOBUG_RESOURCE_LOG_LEVEL, \
1252 "RESOURCE_ENTER", context, \
1253 "%s: %s@%p: %s: %s", \
1254 (resource)?(resource)->type:"", \
1255 (resource)?(resource)->hdr.name:"", \
1256 (resource)?(resource)->object_id:NULL, \
1258 nobug_resource_states[state]);) \
1260 NOBUG_RESOURCE_ASSERT_CTX(handle = \
1261 nobug_resource_enter (resource, \
1264 "RESOURCE_ASSERT_ENTER", context, \
1265 "%s: %s@%p: %s: %s: %s", \
1266 (resource)?(resource)->type:"", \
1267 (resource)?(resource)->hdr.name:"", \
1268 (resource)?(resource)->object_id:NULL, \
1269 user, nobug_resource_states[state], \
1270 nobug_resource_error);) \
1278 //resourcemacros PARA RESOURCE_WAIT; RESOURCE_WAIT; wait for a resource to become available
1279 //resourcemacros RESOURCE_WAIT(flag, resource, user, handle)
1280 //resourcemacros NOBUG_RESOURCE_WAIT_CTX(flag, resource, user, handle, context)
1282 //resourcemacros This is just an alias for RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_WAITING, handle)
1284 //resourcemacros .How to use it
1285 //resourcemacros [source,c]
1286 //resourcemacros ----
1287 //resourcemacros RESOURCE_WAIT(flag, resource, user, handle);
1288 //resourcemacros if (lock_my_resource() == ERROR)
1289 //resourcemacros NOBUG_RESOURCE_LEAVE(flag, handle);
1290 //resourcemacros else
1291 //resourcemacros RESOURCE_STATE(flag, NOBUG_RESOURCE_EXCLUSIVE, handle);
1292 //resourcemacros ----
1294 #define NOBUG_RESOURCE_WAIT(flag, resource, user, handle) \
1295 NOBUG_RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_WAITING, handle)
1297 #define NOBUG_RESOURCE_WAIT_CTX(flag, resource, user, handle, context) \
1298 NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, NOBUG_RESOURCE_WAITING, handle, context)
1301 //resourcemacros PARA RESOURCE_TRY; RESOURCE_TRY; wait for a resource to become available
1302 //resourcemacros RESOURCE_TRY(flag, resource, user, handle)
1303 //resourcemacros NOBUG_RESOURCE_TRY_CTX(flag, resource, user, handle, context)
1305 //resourcemacros This is just an alias for RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_TRYING, handle).
1306 //resourcemacros Trying on a resource is similar to waiting but will not trigger a deadlock check. This can be used
1307 //resourcemacros when a deadlock is expected at runtime and one handles this otherwise (by a timed wait or something like that).
1309 #define NOBUG_RESOURCE_TRY(flag, resource, user, handle) \
1310 NOBUG_RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_TRYING, handle)
1312 #define NOBUG_RESOURCE_TRY_CTX(flag, resource, user, handle, context) \
1313 NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, NOBUG_RESOURCE_TRYING, handle, context)
1317 //resourcemacros PARA RESOURCE_STATE; RESOURCE_STATE; change the state of a resource
1318 //resourcemacros RESOURCE_STATE(flag, entered, state)
1319 //resourcemacros NOBUG_RESOURCE_STATE_CTX(flag, state, entered, context)
1320 //resourcemacros NOBUG_RESOURCE_STATE_RAW(flagptr, state, entered)
1321 //resourcemacros NOBUG_RESOURCE_STATE_RAW_CTX(flagptr, nstate, entered, context)
1323 //resourcemacros Changes resource's state.
1325 //resourcemacros `flag`::
1326 //resourcemacros is nobug flag which turns logging on for this macro
1327 //resourcemacros `state`::
1328 //resourcemacros the new state Note that only certain state transitions are
1329 //resourcemacros allowed, see discussion/diagram above
1330 //resourcemacros `entered`::
1331 //resourcemacros the handle set by `RESOURCE_ENTER`
1333 //resourcemacros 'RESOURCE_STATE()' acts like the head of a C loop statement, it ties to the following
1334 //resourcemacros (block-) statement. Leaving and the user defined following statement are atomic.
1335 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1338 #define NOBUG_RESOURCE_STATE(flag, state, entered) \
1339 NOBUG_RESOURCE_STATE_RAW_CTX(&NOBUG_FLAG(flag), state, entered, NOBUG_CONTEXT)
1341 #define NOBUG_RESOURCE_STATE_CTX(flag, state, entered, context) \
1342 NOBUG_RESOURCE_STATE_RAW_CTX(&NOBUG_FLAG(flag), state, entered, context)
1344 #define NOBUG_RESOURCE_STATE_RAW(flag, state, entered) \
1345 NOBUG_RESOURCE_STATE_RAW_CTX(flag, state, entered, NOBUG_CONTEXT)
1347 #define NOBUG_RESOURCE_STATE_RAW_CTX(flag, nstate, entered, context) \
1348 NOBUG_IF_NOT_RELEASE( for ( \
1349 int NOBUG_CLEANUP(nobug_section_cleaned) section_ = \
1351 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1352 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1353 "RESOURCE_STATE", context, \
1354 "%s: %s@%p: %s: %s->%s", \
1355 (entered)?(entered)->current->resource->type:"", \
1356 (entered)?(entered)->current->resource->hdr.name:"", \
1357 (entered)?(entered)->current->resource->object_id:"", \
1358 (entered)?(entered)->hdr.name:"", \
1359 nobug_resource_states[(entered)?(entered)->state \
1360 :NOBUG_RESOURCE_INVALID], \
1361 nobug_resource_states[nstate]); \
1364 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_state ((entered), nstate), \
1365 "RESOURCE_ASSERT_STATE", context, \
1366 "%s: %s@%p: %s: %s->%s: %s", \
1367 (entered)?(entered)->current->resource->type:"", \
1368 (entered)?(entered)->current->resource->hdr.name:"", \
1369 (entered)?(entered)->current->resource->object_id:"", \
1370 (entered)?(entered)->hdr.name:"", \
1371 nobug_resource_states[(entered)?(entered)->state \
1372 :NOBUG_RESOURCE_INVALID], \
1373 nobug_resource_states[nstate], \
1374 nobug_resource_error); \
1382 //resourcemacros PARA RESOURCE_LEAVE; RESOURCE_LEAVE; relinquish a claimed resource
1383 //resourcemacros RESOURCE_LEAVE(flag, handle){}
1384 //resourcemacros NOBUG_RESOURCE_LEAVE_RAW(flagptr, handle){}
1385 //resourcemacros NOBUG_RESOURCE_LEAVE_RAW_CTX(flagptr, handle, context){}
1387 //resourcemacros Disconnect from a resource identified with its handle.
1389 //resourcemacros `flag`::
1390 //resourcemacros nobug flag which turns logging on for this macro
1391 //resourcemacros `handle`::
1392 //resourcemacros the handle you got while entering the resource
1394 //resourcemacros 'RESOURCE_LEAVE()' acts like the head of a C loop statement, it ties to the following
1395 //resourcemacros (block-) statement. Leaving and the user defined following statement are atomic.
1396 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1398 //resourcemacros .How to use it
1399 //resourcemacros [source,c]
1400 //resourcemacros ----
1401 //resourcemacros NOBUG_RESOURCE_LEAVE(flag, handle)
1403 //resourcemacros unlock_my_resource();
1405 //resourcemacros ----
1408 #define NOBUG_RESOURCE_LEAVE(flag, handle) \
1409 NOBUG_RESOURCE_LEAVE_RAW_CTX(&NOBUG_FLAG(flag), handle, NOBUG_CONTEXT)
1411 #define NOBUG_RESOURCE_LEAVE_RAW(flag, handle) \
1412 NOBUG_RESOURCE_LEAVE_RAW_CTX(flag, handle, NOBUG_CONTEXT)
1414 #define NOBUG_RESOURCE_LEAVE_RAW_CTX(flag, handle, context) \
1415 NOBUG_IF_NOT_RELEASE( \
1417 int NOBUG_CLEANUP(nobug_section_cleaned) section_ = ({ \
1418 nobug_resource_leave_pre(); \
1423 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1424 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1425 "RESOURCE_LEAVE", context, \
1426 "%s: %s@%p: %s: %s", \
1427 (handle)?(handle)->current->resource->type:"", \
1428 (handle)?(handle)->current->resource->hdr.name:"", \
1429 (handle)?(handle)->current->resource->object_id:"", \
1430 (handle)?(handle)->hdr.name:"", \
1431 nobug_resource_states[(handle)?(handle)->state \
1432 :NOBUG_RESOURCE_INVALID]); \
1435 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_leave (handle), \
1436 "RESOURCE_ASSERT_LEAVE", context, \
1437 "%s: %s@%p: %s: %s: %s", \
1438 (handle)?(handle)->current->resource->type:"", \
1439 (handle)?(handle)->current->resource->hdr.name:"", \
1440 (handle)?(handle)->current->resource->object_id:"", \
1441 (handle)?(handle)->hdr.name:"", \
1442 nobug_resource_states[(handle)?(handle)->state \
1443 :NOBUG_RESOURCE_INVALID], \
1444 nobug_resource_error); \
1451 //resourcemacros PARA RESOURCE_ASSERT_STATE; RESOURCE_ASSERT_STATE; assert the state of a resource
1452 //resourcemacros RESOURCE_ASSERT_STATE(resource, state)
1453 //resourcemacros RESOURCE_ASSERT_STATE_IF(when, resource, state)
1454 //resourcemacros NOBUG_RESOURCE_ASSERT_STATE_CTX(resource, state, context)
1455 //resourcemacros NOBUG_RESOURCE_ASSERT_STATE_IF_CTX(when, resource, state, context)
1457 //resourcemacros Assert that we have a resource in a given state. For multithreaded programms the topmost
1458 //resourcemacros state of the calling thread is checked, for non threadeded programs the most recent state on
1459 //resourcemacros resource is used.
1461 //resourcemacros `when`::
1462 //resourcemacros Condition which must be true for testing the assertion
1463 //resourcemacros `resource`::
1464 //resourcemacros Resource handle
1465 //resourcemacros `state`::
1466 //resourcemacros The expected state
1469 #define NOBUG_RESOURCE_ASSERT_STATE(resource, state) \
1470 NOBUG_RESOURCE_ASSERT_STATE_CTX(resource, state, NOBUG_CONTEXT)
1472 #define NOBUG_RESOURCE_ASSERT_STATE_CTX(resource, state, context) \
1475 enum nobug_resource_state mystate = nobug_resource_mystate (resource); \
1476 NOBUG_RESOURCE_ASSERT_CTX(mystate == state, \
1477 "RESOURCE_ASSERT_STATE", context, \
1478 "resource %p has state %s but %s was expected", \
1479 resource, nobug_resource_states[mystate], nobug_resource_states[state]); \
1483 #define NOBUG_RESOURCE_ASSERT_STATE_IF(when, resource, state) \
1484 NOBUG_WHEN(when, NOBUG_RESOURCE_ASSERT_STATE (resource, state))
1487 /* assertion which dumps all resources */
1488 #define NOBUG_RESOURCE_ASSERT_CTX(expr, what, context, ...) \
1490 NOBUG_WHEN (!(expr), \
1491 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
1494 nobug_resource_dump_all (NOBUG_RESOURCE_DUMP_CONTEXT( \
1495 &nobug_flag_NOBUG_ON, \
1498 NOBUG_BACKTRACE_CTX(context); \
1503 //resourcemacros PARA RESOURCE_DUMP; RESOURCE_DUMP; dump the state of a single resource
1504 //resourcemacros NOBUG_RESOURCE_DUMP(flag, handle)
1505 //resourcemacros NOBUG_RESOURCE_DUMP_IF(when, flag, handle)
1507 //resourcemacros Dump the state of a single resource.
1509 //resourcemacros `when`::
1510 //resourcemacros Condition which must be true to dump the resource
1511 //resourcemacros `flag`::
1512 //resourcemacros Nobug flag for the log channel
1513 //resourcemacros `handle`::
1514 //resourcemacros handle of the resource to be dumped
1517 #define NOBUG_RESOURCE_DUMP(flag, handle) \
1520 nobug_resource_dump (handle, NOBUG_RESOURCE_DUMP_CONTEXT( \
1521 &NOBUG_FLAG(flag), \
1522 NOBUG_RESOURCE_LOG_LEVEL, \
1526 #define NOBUG_RESOURCE_DUMP_IF(when, flag, handle) \
1529 nobug_resource_dump (handle, NOBUG_RESOURCE_DUMP_CONTEXT( \
1530 &NOBUG_FLAG(flag), \
1531 NOBUG_RESOURCE_LOG_LEVEL, \
1537 //resourcemacros PARA RESOURCE_DUMPALL; RESOURCE_DUMPALL; dump the state of all resources
1538 //resourcemacros NOBUG_RESOURCE_DUMPALL(flag)
1539 //resourcemacros NOBUG_RESOURCE_DUMPALL_IF(when, flag)
1541 //resourcemacros Dump the state of all resources.
1543 //resourcemacros `when`::
1544 //resourcemacros Condition which must be true to dump the resources
1545 //resourcemacros `flag`::
1546 //resourcemacros Nobug flag for the log channel
1549 #define NOBUG_RESOURCE_DUMPALL(flag) \
1552 nobug_resource_dump_all (NOBUG_RESOURCE_DUMP_CONTEXT( \
1553 &NOBUG_FLAG(flag), \
1554 NOBUG_RESOURCE_LOG_LEVEL, \
1559 #define NOBUG_RESOURCE_DUMPALL_IF(when, flag) \
1562 nobug_resource_dump_all (NOBUG_RESOURCE_DUMP_CONTEXT( \
1563 &NOBUG_FLAG(flag), \
1564 NOBUG_RESOURCE_LOG_LEVEL, \
1569 //resourcemacros PARA RESOURCE_LIST; RESOURCE_LIST; enumerate all registered resources
1570 //resourcemacros NOBUG_RESOURCE_LIST(flag)
1571 //resourcemacros NOBUG_RESOURCE_LIST_IF(when, flag)
1573 //resourcemacros List all registered resources.
1575 //resourcemacros `when`::
1576 //resourcemacros Condition which must be true to list the resources
1577 //resourcemacros `flag`::
1578 //resourcemacros Nobug flag for the log channel
1581 #define NOBUG_RESOURCE_LIST(flag) \
1584 nobug_resource_list (NOBUG_RESOURCE_DUMP_CONTEXT( \
1585 &NOBUG_FLAG(flag), \
1586 NOBUG_RESOURCE_LOG_LEVEL, \
1591 #define NOBUG_RESOURCE_LIST_IF(when, flag) \
1594 nobug_resource_list (NOBUG_RESOURCE_DUMP_CONTEXT( \
1595 &NOBUG_FLAG(flag), \
1596 NOBUG_RESOURCE_LOG_LEVEL, \
1601 /* constructing a resource-dump context */
1603 #define NOBUG_RESOURCE_DUMP_CONTEXT(flag, level, context) \
1604 ((struct nobug_resource_dump_context){ \
1609 #define NOBUG_CONTEXT (nobug_context(__FILE__, __LINE__, NOBUG_FUNC))
1610 #define NOBUG_RESOURCE_DUMP_CONTEXT(flag, level, context) \
1611 (nobug_resource_dump_context(flag, level, context))
1618 #if NOBUG_USE_PTHREAD
1619 #define NOBUG_THREAD_ID_SET(name) nobug_thread_id_set(name)
1620 #define NOBUG_THREAD_ID_GET nobug_thread_id_get()
1623 #define NOBUG_THREAD_ID_SET(name)
1624 #define NOBUG_THREAD_ID_GET ""
1627 #define NOBUG_THREAD_DATA (*nobug_thread_data())
1634 #define NOBUG_DBG_NONE 0
1635 #define NOBUG_DBG_GDB 1
1636 #define NOBUG_DBG_VALGRIND 2
1638 #define NOBUG_ACTIVE_DBG \
1639 NOBUG_IF(NOBUG_USE_VALGRIND, (RUNNING_ON_VALGRIND?2:0)) \
1640 NOBUG_IFNOT(NOBUG_USE_VALGRIND, 0)
1643 //toolmacros HEAD- Tool Macros;;
1645 //toolmacros PARA NOBUG_FLAG_RAW; NOBUG_FLAG_RAW; pass direct flag pointer
1646 //toolmacros NOBUG_FLAG_RAW(ptr)
1648 //toolmacros Using this macro one can pass a direct pointer to a flag where a name would
1649 //toolmacros be expected. This is sometimes convinient when flag pointers are passed around
1650 //toolmacros in management strutures and one wants to tie logging to dynamic targets.
1652 //toolmacros [source,c]
1654 //toolmacros NOBUG_DEFINE_FLAG(myflag);
1656 //toolmacros struct nobug_flag* ptr = &NOBUG_FLAG(myflag);
1657 //toolmacros TRACE(NOBUG_FLAG_RAW(ptr), "Passed flag by pointer")
1661 #define nobug_flag_NOBUG_FLAG_RAW(name) *name
1664 //toolmacros PARA Backtraces; BACKTRACE; generate a backtrace
1665 //toolmacros BACKTRACE
1666 //toolmacros NOBUG_BACKTRACE_CTX(context)
1668 //toolmacros The backtrace macro logs a stacktrace using the NoBug facilities.
1669 //toolmacros This is automatically called when NoBug finds an error and is due
1670 //toolmacros to abort. But one might call it manually too.
1673 #define NOBUG_BACKTRACE NOBUG_BACKTRACE_CTX(NOBUG_CONTEXT)
1675 #define NOBUG_BACKTRACE_CTX(context) \
1677 switch (NOBUG_ACTIVE_DBG) { \
1678 case NOBUG_DBG_VALGRIND: \
1679 NOBUG_BACKTRACE_VALGRIND(context); \
1682 NOBUG_BACKTRACE_GLIBC(context); \
1684 NOBUG_IF_NOT_ALPHA (NOBUG_BACKTRACE_GLIBC(context))
1686 #define NOBUG_BACKTRACE_GDB(context) UNIMPLEMENTED
1688 #define NOBUG_BACKTRACE_VALGRIND(context) \
1689 NOBUG_IF(NOBUG_USE_VALGRIND, \
1690 nobug_backtrace_valgrind (context) \
1694 #ifndef NOBUG_BACKTRACE_DEPTH
1695 #define NOBUG_BACKTRACE_DEPTH 256
1698 #define NOBUG_BACKTRACE_GLIBC(context) \
1699 NOBUG_IF_NOT_RELEASE( \
1700 NOBUG_IF(NOBUG_USE_EXECINFO, do { \
1701 nobug_backtrace_glibc (context); \
1706 #define NOBUG_TAB " "
1709 //toolmacros PARA Aborting; ABORT; abort the program
1710 //toolmacros NOBUG_ABORT_
1712 //toolmacros This is the default implementation for aborting the program, it first syncs all ringbuffers to disk, then
1713 //toolmacros calls the abort callback if defined and then `abort()`.
1715 //toolmacros NOBUG_ABORT
1717 //toolmacros If not overridden, evaluates to `NOBUG_ABORT_`. One can override this before including
1718 //toolmacros `nobug.h` to customize abortion behaviour. This will be local to the translation unit then.
1721 #define NOBUG_ABORT NOBUG_ABORT_
1724 #define NOBUG_ABORT_ \
1726 nobug_ringbuffer_allsync (); \
1727 if (nobug_abort_callback) \
1728 nobug_abort_callback (nobug_callback_data); \
1734 init and other function wrapers
1736 #define NOBUG_INIT nobug_init(NOBUG_CONTEXT)
1739 short macros without NOBUG_
1741 #ifndef NOBUG_DISABLE_SHORTNAMES
1743 #define REQUIRE NOBUG_REQUIRE
1746 #define REQUIRE_IF NOBUG_REQUIRE_IF
1749 #define ENSURE NOBUG_ENSURE
1752 #define ENSURE_IF NOBUG_ENSURE_IF
1755 #define ASSERT NOBUG_ASSERT
1758 #define ASSERT_IF NOBUG_ASSERT_IF
1761 #define CHECK NOBUG_CHECK
1764 #define CHECK NOBUG_CHECK
1767 #define INVARIANT NOBUG_INVARIANT
1769 #ifndef INVARIANT_IF
1770 #define INVARIANT_IF NOBUG_INVARIANT_IF
1772 #ifndef INVARIANT_ASSERT
1773 #define INVARIANT_ASSERT NOBUG_INVARIANT_ASSERT
1776 #define DUMP NOBUG_DUMP
1779 #define DUMP_IF NOBUG_DUMP_IF
1782 #define DUMP_LOG NOBUG_DUMP_LOG
1785 #define DUMP_LOG_IF NOBUG_DUMP_LOG_IF
1788 #define LOG NOBUG_LOG
1791 #define LOG_IF NOBUG_LOG_IF
1794 #define ECHO NOBUG_ECHO
1797 #define ALERT NOBUG_ALERT
1800 #define ALERT_IF NOBUG_ALERT_IF
1803 #define CRITICAL NOBUG_CRITICAL
1806 #define CRITICAL_IF NOBUG_CRITICAL_IF
1809 #define ERROR NOBUG_ERROR
1812 #define ERROR_IF NOBUG_ERROR_IF
1815 #define WARN NOBUG_WARN
1818 #define WARN_IF NOBUG_WARN_IF
1821 #define INFO NOBUG_INFO
1824 #define INFO_IF NOBUG_INFO_IF
1827 #define NOTICE NOBUG_NOTICE
1830 #define NOTICE_IF NOBUG_NOTICE_IF
1833 #define TRACE NOBUG_TRACE
1836 #define TRACE_IF NOBUG_TRACE_IF
1839 #define BACKTRACE NOBUG_BACKTRACE
1842 #define DEPRECATED NOBUG_DEPRECATED
1844 #ifndef UNIMPLEMENTED
1845 #define UNIMPLEMENTED NOBUG_UNIMPLEMENTED
1848 #define FIXME NOBUG_FIXME
1851 #define TODO NOBUG_TODO
1854 #define PLANNED NOBUG_PLANNED
1857 #define NOTREACHED NOBUG_NOTREACHED
1859 #ifndef ELSE_NOTREACHED
1860 #define ELSE_NOTREACHED NOBUG_ELSE_NOTREACHED
1862 #ifndef INJECT_GOODBAD
1863 #define INJECT_GOODBAD NOBUG_INJECT_GOODBAD
1865 #ifndef INJECT_FAULT
1866 #define INJECT_FAULT NOBUG_INJECT_FAULT
1869 #define CLEANUP NOBUG_CLEANUP
1872 #define CHECKED NOBUG_CHECKED
1875 #define UNCHECKED NOBUG_UNCHECKED
1877 #ifndef RESOURCE_ANNOUNCE
1878 #define RESOURCE_ANNOUNCE NOBUG_RESOURCE_ANNOUNCE
1880 #ifndef RESOURCE_FORGET
1881 #define RESOURCE_FORGET NOBUG_RESOURCE_FORGET
1883 #ifndef RESOURCE_ENTER
1884 #define RESOURCE_ENTER NOBUG_RESOURCE_ENTER
1886 #ifndef RESOURCE_WAIT
1887 #define RESOURCE_WAIT NOBUG_RESOURCE_WAIT
1889 #ifndef RESOURCE_TRY
1890 #define RESOURCE_TRY NOBUG_RESOURCE_TRY
1892 #ifndef RESOURCE_STATE
1893 #define RESOURCE_STATE NOBUG_RESOURCE_STATE
1895 #ifndef RESOURCE_LEAVE
1896 #define RESOURCE_LEAVE NOBUG_RESOURCE_LEAVE
1898 #ifndef RESOURCE_LEAVE_LOOKUP
1899 #define RESOURCE_LEAVE_LOOKUP NOBUG_RESOURCE_LEAVE_LOOKUP
1901 #ifndef RESOURCE_HANDLE
1902 #define RESOURCE_HANDLE NOBUG_RESOURCE_HANDLE
1904 #ifndef RESOURCE_HANDLE_INIT
1905 #define RESOURCE_HANDLE_INIT NOBUG_RESOURCE_HANDLE_INIT
1907 #ifndef RESOURCE_USER
1908 #define RESOURCE_USER NOBUG_RESOURCE_USER
1910 #ifndef RESOURCE_ASSERT_STATE
1911 #define RESOURCE_ASSERT_STATE NOBUG_RESOURCE_ASSERT_STATE
1913 #ifndef RESOURCE_ASSERT_STATE_IF
1914 #define RESOURCE_ASSERT_STATE_IF NOBUG_RESOURCE_ASSERT_STATE_IF
1916 #ifndef RESOURCE_USER_INIT
1917 #define RESOURCE_USER_INIT NOBUG_RESOURCE_USER_INIT
1919 #ifndef RESOURCE_DUMP
1920 #define RESOURCE_DUMP NOBUG_RESOURCE_DUMP
1922 #ifndef RESOURCE_DUMP_IF
1923 #define RESOURCE_DUMP_IF NOBUG_RESOURCE_DUMP_IF
1925 #ifndef RESOURCE_DUMPALL
1926 #define RESOURCE_DUMPALL NOBUG_RESOURCE_DUMPALL
1928 #ifndef RESOURCE_DUMPALL_IF
1929 #define RESOURCE_DUMPALL_IF NOBUG_RESOURCE_DUMPALL_IF
1931 #ifndef RESOURCE_LIST
1932 #define RESOURCE_LIST NOBUG_RESOURCE_LIST
1934 #ifndef RESOURCE_LIST_IF
1935 #define RESOURCE_LIST_IF NOBUG_RESOURCE_LIST_IF
1937 #endif /* NOBUG_DISABLE_SHORTNAMES */
1944 #define NOBUG_CLEANUP(fn) NOBUG_IF_ALPHA(__attribute__((cleanup(fn))))
1945 #define NOBUG_ATTR_PRINTF(fmt, ell) __attribute__ ((format (printf, fmt, ell)))
1947 #define NOBUG_CLEANUP(fn)
1948 #define NOBUG_ATTR_PRINTF(fmt, ell)
1952 //toolmacros PARA NOBUG_ALPHA_COMMA; NOBUG_ALPHA_COMMA; append something after a comma in *ALPHA* builds
1953 //toolmacros NOBUG_ALPHA_COMMA(something)
1954 //toolmacros NOBUG_ALPHA_COMMA_NULL
1956 //toolmacros Sometimes it is useful to have initializer code only in *ALPHA* builds, for example when you
1957 //toolmacros conditionally include resource handles only in *ALPHA* versions. An initializer can then
1958 //toolmacros use this macros to append a comman and something else only in *ALPHA* builds as in:
1959 //toolmacros struct foo = {"foo", "bar" NOBUG_ALPHA_COMMA_NULL };
1962 #define NOBUG_COMMA ,
1963 #define NOBUG_ALPHA_COMMA(something) NOBUG_IF_ALPHA(NOBUG_COMMA something)
1964 #define NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA(NULL)
1966 #define NOBUG_ONCE(code) \
1968 static volatile int NOBUG_CAT(nobug_once_,__LINE__) = 1; \
1969 if (NOBUG_EXPECT_FALSE(NOBUG_CAT(nobug_once_,__LINE__))) \
1971 NOBUG_CAT(nobug_once_,__LINE__) = 0; \
1977 #define NOBUG_EXPECT_FALSE(x) __builtin_expect(!!(x),0)
1979 #define NOBUG_EXPECT_FALSE(x) x
1982 #define NOBUG_WHEN(when, ...) \
1983 do{ if (NOBUG_EXPECT_FALSE(when)){ __VA_ARGS__;}} while(0)
1986 //toolmacros PARA NOBUG_IF_*; NOBUG_IF; include code conditionally on build level
1987 //toolmacros NOBUG_IF_ALPHA(...)
1988 //toolmacros NOBUG_IF_NOT_ALPHA(...)
1989 //toolmacros NOBUG_IF_BETA(...)
1990 //toolmacros NOBUG_IF_NOT_BETA(...)
1991 //toolmacros NOBUG_IF_RELEASE(...)
1992 //toolmacros NOBUG_IF_NOT_RELEASE(...)
1994 //toolmacros This macros allow one to conditionally include the code in '(...)' only if the
1995 //toolmacros criteria on the build level is met. If not, nothing gets substituted. Mostly used
1996 //toolmacros internally, but can also be used for custom things.
1999 #define NOBUG_IF_ALPHA(...) \
2000 NOBUG_IF(NOBUG_MODE_ALPHA, __VA_ARGS__) \
2002 #define NOBUG_IF_NOT_ALPHA(...) \
2003 NOBUG_IFNOT(NOBUG_MODE_ALPHA, __VA_ARGS__) \
2005 #define NOBUG_IF_BETA(...) \
2006 NOBUG_IF(NOBUG_MODE_BETA, __VA_ARGS__) \
2008 #define NOBUG_IF_NOT_BETA(...) \
2009 NOBUG_IFNOT(NOBUG_MODE_BETA, __VA_ARGS__) \
2011 #define NOBUG_IF_RELEASE(...) \
2012 NOBUG_IF(NOBUG_MODE_RELEASE, __VA_ARGS__) \
2014 #define NOBUG_IF_NOT_RELEASE(...) \
2015 NOBUG_IFNOT(NOBUG_MODE_RELEASE, __VA_ARGS__) \
2018 preprocessor hacks/metaprogramming
2021 #define NOBUG_IF(bool, ...) NOBUG_CAT(NOBUG_IF_,bool)(__VA_ARGS__)
2022 #define NOBUG_IF_1(...) __VA_ARGS__
2023 #define NOBUG_IF_0(...)
2025 #define NOBUG_IFNOT(bool, ...) NOBUG_CAT(NOBUG_IF_, NOBUG_NOT(bool))(__VA_ARGS__)
2027 #define NOBUG_NOT(bool) NOBUG_CAT(NOBUG_NOT_, bool)
2028 #define NOBUG_NOT_1 0
2029 #define NOBUG_NOT_0 1
2031 #define NOBUG_AND(a,b) NOBUG_CAT3(NOBUG_AND_, a, b)
2032 #define NOBUG_AND_00 0
2033 #define NOBUG_AND_01 0
2034 #define NOBUG_AND_10 0
2035 #define NOBUG_AND_11 1
2037 #define NOBUG_OR(a,b) NOBUG_CAT3(NOBUG_OR_, a, b)
2038 #define NOBUG_OR_00 0
2039 #define NOBUG_OR_01 1
2040 #define NOBUG_OR_10 1
2041 #define NOBUG_OR_11 1
2043 #define NOBUG_XOR(a,b) NOBUG_CAT( NOBUG_XOR_, NOBUG_CAT(a,b))
2044 #define NOBUG_XOR_00 0
2045 #define NOBUG_XOR_01 1
2046 #define NOBUG_XOR_10 1
2047 #define NOBUG_XOR_11 0
2049 #define NOBUG_CAT(a,b) NOBUG_CAT_(a,b)
2050 #define NOBUG_CAT_(a,b) a##b
2052 #define NOBUG_CAT3(a,b,c) NOBUG_CAT3_(a,b,c)
2053 #define NOBUG_CAT3_(a,b,c) a##b##c
2055 #define NOBUG_STRINGIZE(s) NOBUG_STRINGIZE_(s)
2056 #define NOBUG_STRINGIZE_(s) #s
2060 LIBNOBUG DECLARATIONS
2065 } /* fix emacs indent */
2068 #ifndef LLIST_DEFINED
2069 #define LLIST_DEFINED
2072 struct llist_struct
*next
;
2073 struct llist_struct
*prev
;
2081 struct nobug_context
2088 nobug_context (const char* file_
, int line_
, const char* func_
)
2089 : file(file_
), line(line_
), func(func_
) {}
2094 nobug_basename (const char* const file
);
2099 enum nobug_log_targets
2101 NOBUG_TARGET_RINGBUFFER
,
2102 NOBUG_TARGET_CONSOLE
,
2104 NOBUG_TARGET_SYSLOG
,
2105 NOBUG_TARGET_APPLICATION
2111 struct nobug_flag
* parent
;
2112 volatile int initialized
;
2114 struct nobug_ringbuffer
* ringbuffer_target
;
2115 FILE* console_target
;
2120 nobug_env_parse_flag (const char* env
, struct nobug_flag
* flag
, int default_target
, int default_limit
, const struct nobug_context context
);
2123 nobug_env_init_flag (struct nobug_flag
* flag
, int default_target
, int default_limit
, const struct nobug_context context
);
2129 struct nobug_ringbuffer
2131 struct llist_struct node
; /* all ringbufers are chained together, needed for sync */
2139 enum nobug_ringbuffer_flags
2141 NOBUG_RINGBUFFER_DEFAULT
, /* Default is to overwrite file and delete it on nobug_ringbuffer_destroy */
2142 NOBUG_RINGBUFFER_APPEND
= 1, /* use existing backing file, append if possible */
2143 NOBUG_RINGBUFFER_TEMP
= 2, /* unlink file instantly */
2144 NOBUG_RINGBUFFER_KEEP
= 4 /* dont unlink the file at destroy */
2147 Note: some flags conflict (TEMP with KEEP) nobug_ringbuffer will not error on these but continue gracefully
2148 with sane (but undefined) semantics.
2151 struct nobug_ringbuffer
*
2152 nobug_ringbuffer_init (struct nobug_ringbuffer
* self
, size_t size
,
2153 size_t guard
, const char * name
, int flags
);
2155 struct nobug_ringbuffer
*
2156 nobug_ringbuffer_new (size_t size
, size_t guard
, const char * name
, int flags
);
2158 struct nobug_ringbuffer
*
2159 nobug_ringbuffer_destroy (struct nobug_ringbuffer
* self
);
2162 nobug_ringbuffer_delete (struct nobug_ringbuffer
* self
);
2165 nobug_ringbuffer_sync (struct nobug_ringbuffer
* self
);
2168 nobug_ringbuffer_allsync (void);
2171 nobug_ringbuffer_vprintf (struct nobug_ringbuffer
* self
, const char* fmt
, va_list ap
);
2174 nobug_ringbuffer_printf (struct nobug_ringbuffer
* self
, const char* fmt
, ...);
2177 nobug_ringbuffer_append (struct nobug_ringbuffer
* self
);
2180 nobug_ringbuffer_extend (struct nobug_ringbuffer
* self
, size_t newsize
, const char fill
);
2183 nobug_ringbuffer_prev (struct nobug_ringbuffer
* self
, char* pos
);
2186 nobug_ringbuffer_next (struct nobug_ringbuffer
* self
, char* pos
);
2189 nobug_ringbuffer_save (struct nobug_ringbuffer
* self
, FILE* out
);
2192 nobug_ringbuffer_load (struct nobug_ringbuffer
* self
, FILE* in
);
2195 nobug_ringbuffer_pos (struct nobug_ringbuffer
* self
);
2198 nobug_ringbuffer_pop (struct nobug_ringbuffer
* self
);
2202 multithreading extras
2204 #if NOBUG_USE_PTHREAD
2206 struct nobug_tls_data
2208 const char* thread_id
;
2209 unsigned thread_num
; /* thread counter at initialization, gives a unique thread number */
2210 unsigned thread_gen
; /* incremented at each name reset, (currently unused) */
2212 struct llist_struct res_stack
; /* resources of this thread */
2215 extern pthread_key_t nobug_tls_key
;
2217 struct nobug_tls_data
*
2218 nobug_thread_set (const char* name
);
2220 struct nobug_tls_data
*
2221 nobug_thread_get (void);
2224 nobug_thread_id_set (const char* name
);
2227 nobug_thread_id_get (void);
2229 extern pthread_mutex_t nobug_logging_mutex
;
2230 extern pthread_mutex_t nobug_resource_mutex
;
2234 nobug_thread_data (void);
2239 enum nobug_resource_state
2241 NOBUG_RESOURCE_INVALID
,
2242 NOBUG_RESOURCE_WAITING
,
2243 NOBUG_RESOURCE_TRYING
,
2244 NOBUG_RESOURCE_EXCLUSIVE
,
2245 NOBUG_RESOURCE_RECURSIVE
,
2246 NOBUG_RESOURCE_SHARED
2250 struct nobug_resource_header
2252 struct llist_struct node
; /* link node for resource registry or users */
2253 const char* name
; /* name */
2254 struct nobug_context extra
; /* context information */
2257 struct nobug_resource_node
;
2258 struct nobug_resource_user
;
2260 struct nobug_resource_record
2262 struct nobug_resource_header hdr
;
2264 struct llist_struct users
; /* list of users of this resource */
2265 const void* object_id
; /* unique identifer, usually a this pointer or similar */
2266 const char* type
; /* type */
2268 #if NOBUG_USE_PTHREAD
2269 struct llist_struct nodes
;
2274 struct nobug_resource_node
2276 struct llist_struct node
; /* all nodes for one resource */
2278 struct nobug_resource_record
* resource
; /* backpointer */
2279 struct nobug_resource_node
* parent
; /* upwards the tree */
2281 struct llist_struct childs
; /* down the tree, all nodes pointing to here (TODO make this a slist) */
2282 struct llist_struct cldnode
; /* node to accumulate all childrens of a parent (TODO slist) */
2286 struct nobug_resource_user
2288 struct nobug_resource_header hdr
;
2290 struct nobug_resource_node
* current
; /* this resource */
2291 enum nobug_resource_state state
; /* state */
2293 #if NOBUG_USE_PTHREAD
2294 struct nobug_tls_data
* thread
; /* pointer to this theads id */
2295 struct llist_struct res_stack
; /* resources of this thread */
2300 extern const char* nobug_resource_error
;
2302 extern const char* nobug_resource_states
[];
2306 nobug_resource_init (void);
2309 nobug_resource_destroy (void);
2312 struct nobug_resource_record
*
2313 nobug_resource_announce (const char* type
, const char* name
, const void* object_id
, const struct nobug_context extra
);
2316 nobug_resource_announce_complete (void);
2319 nobug_resource_forget (struct nobug_resource_record
* node
);
2322 struct nobug_resource_user
*
2323 nobug_resource_enter (struct nobug_resource_record
* resource
,
2325 enum nobug_resource_state state
,
2326 const struct nobug_context extra
);
2330 nobug_resource_leave (struct nobug_resource_user
* handle
);
2334 nobug_resource_leave_pre (void);
2338 nobug_resource_record_available (void);
2342 nobug_resource_user_available (void);
2345 #if NOBUG_USE_PTHREAD
2347 nobug_resource_node_available (void);
2351 struct nobug_resource_dump_context
2353 struct nobug_flag
* flag
;
2355 struct nobug_context ctx
;
2358 nobug_resource_dump_context (struct nobug_flag
* flag_
,
2360 struct nobug_context ctx_
)
2361 : flag(flag_
), level(level_
), ctx(ctx_
) {}
2365 enum nobug_resource_state
2366 nobug_resource_mystate (struct nobug_resource_record
* res
);
2369 nobug_resource_dump (struct nobug_resource_record
* resource
, const struct nobug_resource_dump_context context
);
2372 nobug_resource_dump_all (const struct nobug_resource_dump_context context
);
2375 nobug_resource_state (struct nobug_resource_user
* resource
,
2376 enum nobug_resource_state state
);
2380 nobug_resource_list (const struct nobug_resource_dump_context context
);
2384 global config, data and defaults
2386 void nobug_init (const struct nobug_context context
);
2389 the destroy function is optional, since nobug should stay alive for the whole application lifetime
2390 (and destroying is global!) it is only provided for the nobug testsuite itself
2392 void nobug_destroy (const struct nobug_context context
);
2395 nobug_backtrace_glibc (const struct nobug_context context
);
2398 nobug_backtrace_valgrind (const struct nobug_context context
);
2401 nobug_log_begin (char* header
, struct nobug_flag
* flag
, const char* what
, const struct nobug_context ctx
);
2405 nobug_log_end (struct nobug_flag
* flag
, int lvl
);
2408 /* must be called inbetween log_begin and log_end */
2410 nobug_log_line (char** start
, char* header
, struct nobug_flag
* flag
, int lvl
, const char* fmt
, ...);
2414 nobug_log (struct nobug_flag
* flag
, int lvl
, const char* what
,
2415 const struct nobug_context ctx
,
2416 const char* fmt
, ...) NOBUG_ATTR_PRINTF(5, 6);
2419 extern struct nobug_ringbuffer nobug_default_ringbuffer
;
2420 extern FILE* nobug_default_file
;
2421 extern struct nobug_flag nobug_flag_NOBUG_ON
;
2422 extern struct nobug_flag nobug_flag_NOBUG_ANN
;
2423 extern struct nobug_flag nobug_flag_nobug
;
2424 extern unsigned long long nobug_counter
;
2426 //callbacks HEAD- Callbacks;;
2428 //callbacks NoBug provides callbacks, applications can use these
2429 //callbacks to present logging information in some custom way or hook some special processing in.
2430 //callbacks The callbacks are initialized to NULL and never modified by NoBug, its the solve responsibility
2431 //callbacks of the user to manage them.
2433 //callbacks CAUTION: There are certain constraints what and what not can be done in callbacks
2434 //callbacks documented below which must be followed.
2436 //callbacks PARA type of logging callbacks; logging_cb; type of a logging callback function
2437 typedef void (*nobug_logging_cb
)(const struct nobug_flag
* flag
, int priority
, const char *log
, void* data
); //callbacks VERBATIM;
2439 //callbacks used for the logging callbacks
2441 //callbacks `flag`::
2442 //callbacks Flag structure which defines the logging configuration for this event
2443 //callbacks `priority`::
2444 //callbacks Log level of the current event
2446 //callbacks Pointing to the current log line in the ringbuffer or `NULL`
2447 //callbacks `data`::
2448 //callbacks Global pointer defined by the user, passed arround (see below)
2451 //callbacks PARA type of abort callback; abort_cb; type of a abort callback function
2452 typedef void (*nobug_abort_cb
)(void* data
); //callbacks VERBATIM;
2454 //callbacks used for the abort callback
2456 //callbacks `data`::
2457 //callbacks Global data defined by the user, passed arround (see below)
2460 //callbacks PARA passing data to callbacks; callback_data; data to be passed to callbacks
2462 void* nobug_callback_data
; //callbacks VERBATIM;
2464 //callbacks This global variable is initialized to `NULL` and will never be touched by NoBug. One can use it
2465 //callbacks to pass extra data to the callback functions.
2468 //callbacks PARA callback when logging; logging_callback; hook when something get logged
2470 nobug_logging_cb nobug_logging_callback
; //callbacks VERBATIM;
2472 //callbacks This callback gets called when something gets logged.
2473 //callbacks NoBug will still hold its mutexes when calling this hook, calling NoBug logging or resource tracking
2474 //callbacks functions from here recursively will deadlock and must be avoided.
2475 //callbacks The `log` parameter points to the logging message in the ringbuffer.
2476 //callbacks Unlike other logging targets it is not automatically limited to the log level configured
2477 //callbacks in the flag but called unconditionally. The callback should implement its own limiting.
2479 //callbacks When one wants to do complex calls which may include recursion into logging and resource tracking
2480 //callbacks functions, the intended way is to pass contextual information possibly including a __copy__ of the
2481 //callbacks `log` parameter in xref:THREAD_DATA[NOBUG_THREAD_DATA] to the postlogging callback (see below).
2482 //callbacks Other internal NoBug facilties, like the ringbuffer etc, are protected by the mutexes and may be accessed
2483 //callbacks from this function.
2486 //callbacks PARA callback after logging; postlogging_callback; hook after something get logged
2488 nobug_logging_cb nobug_postlogging_callback
; //callbacks VERBATIM;
2490 //callbacks This callback gets called after something got logged. The `log` parameter is always NULL and all
2491 //callbacks NoBug mutexes are released. This means that this function may call any complex things, including
2492 //callbacks calling logging and resource tracking, but may not call internal NoBug facilities.
2493 //callbacks Contextual created in the `nobug_logging_callback` and stored in xref:THREAD_DATA[NOBUG_THREAD_DATA] can be
2494 //callbacks retrieved here and may need to be cleaned up here.
2497 //callbacks PARA callback for aborting; abort_callback; hook to handle a termination
2499 nobug_abort_cb nobug_abort_callback
; //callbacks VERBATIM;
2501 //callbacks This callback gets called when the application shall be terminated due an error.
2502 //callbacks It can be used to hook exceptions or similar things in. When it returns, `abort()`
2503 //callbacks is called.
2505 //callbacks IMPORTANT: Errors detected by NoBug are always fatal. If one handles and possible
2506 //callbacks throws an exception here, the application must shut down as soon as possible.
2507 //callbacks Most causes for aborts are optimitzed out in `RELEASE` builds.
2511 /* block statement macros for sections must not be left by a jump this function will assert this with a NOBUG_CLEANUP attribute */
2513 nobug_section_cleaned (int* self
)
2517 nobug_log (&nobug_flag_NOBUG_ON
,
2518 LOG_EMERG
, "RESOURCE_SECTION",
2520 "illegal leaving of resource section (goto, return, ..)");
2530 #ifndef NOBUG_LIBNOBUG_C
2533 tag this translation unit as unchecked in ALPHA and BETA builds
2535 NOBUG_IF_NOT_RELEASE(NOBUG_UNCHECKED
;)
2538 /* some configuration when compiling nobug */
2539 /* Maximal length of a log line header (silently truncated if exceed) */
2540 #define NOBUG_MAX_LOG_HEADER_SIZE 128
2541 /* Maximal linebreaks in a single logging instruction which get translated to multiple lines */
2542 #define NOBUG_MAX_LOG_LINES 32
2544 #endif /* NOBUG_LIBNOBUG_C */