WIP: preparation for the new deadlock checker, structures init/destroy
[nobug.git] / src / nobug.h
blob7387aa8d43c1f3703d55e096516d922b4e1e15ad
1 /*
2 This file is part of the NoBug debugging library.
4 Copyright (C)
5 2007, 2008, 2009 Christian Thaeter <ct@pipapo.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, contact Christian Thaeter <ct@pipapo.org>.
20 #ifndef NOBUG_H
21 #define NOBUG_H
23 #ifndef NOBUG_LIBNOBUG_C /* not when building libnobug */
24 #ifdef NDEBUG
25 #ifdef EBUG_ALPHA
26 #error NDEBUG incompatible with -DEBUG_ALPHA
27 #endif
28 #ifdef EBUG_BETA
29 #error NDEBUG incompatible with -DEBUG_BETA
30 #endif
31 #endif
33 #if defined(EBUG_ALPHA)
34 # define NOBUG_MODE_ALPHA 1
35 # define NOBUG_MODE_BETA 0
36 # define NOBUG_MODE_RELEASE 0
37 #elif defined(EBUG_BETA)
38 # define NOBUG_MODE_ALPHA 0
39 # define NOBUG_MODE_BETA 1
40 # define NOBUG_MODE_RELEASE 0
41 #elif defined(NDEBUG)
42 # define NOBUG_MODE_ALPHA 0
43 # define NOBUG_MODE_BETA 0
44 # define NOBUG_MODE_RELEASE 1
45 #else
46 #error no debug level and no NDEBUG defined
47 #endif
48 #endif /* NOBUG_LIBNOBUG_C */
51 HEADERS
54 #include <syslog.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <stdio.h>
58 #include <stdarg.h>
60 #ifdef HAVE_EXECINFO_H
61 # ifndef NOBUG_USE_EXECINFO
62 # define NOBUG_USE_EXECINFO 1
63 # endif
64 #else
65 # undef NOBUG_USE_EXECINFO
66 # define NOBUG_USE_EXECINFO 0
67 #endif
69 #if NOBUG_USE_EXECINFO
70 #include <execinfo.h>
71 #endif
73 #if defined(HAVE_VALGRIND) && !defined(NVALGRIND)
74 # ifndef NOBUG_USE_VALGRIND
75 # define NOBUG_USE_VALGRIND 1
76 # endif
77 #else
78 # undef NOBUG_USE_VALGRIND
79 # define NOBUG_USE_VALGRIND 0
80 #endif
82 #if NOBUG_USE_VALGRIND
83 #include <valgrind.h>
84 #endif
86 #ifdef HAVE_PTHREAD
87 # ifndef NOBUG_USE_PTHREAD
88 # define NOBUG_USE_PTHREAD 1
89 # endif
90 #else
91 # ifdef NOBUG_USE_PTHREAD
92 # undef NOBUG_USE_PTHREAD
93 # endif
94 # define NOBUG_USE_PTHREAD 0
95 #endif
97 #if NOBUG_USE_PTHREAD
98 #include <pthread.h>
99 #endif
102 ASSERTIONS
105 #if NOBUG_MODE_RELEASE==0
107 //assertions PARA assert; assert; C standard assertion
108 //assertions assert(expr)
109 //assertions
110 //assertions NoBug overrides the standard assert macro in *ALPHA* and *BETA* builds.
111 //assertions This is just a compatibility feature, its use is not suggested.
112 //assertions
114 #undef assert
115 #define assert(expr) NOBUG_ASSERT(expr)
116 #endif
120 //assertions PARA REQUIRE; REQUIRE; preconditions (input parameters)
121 //assertions REQUIRE(expr, ...)
122 //assertions REQUIRE_DBG(expr, ...)
123 //assertions REQUIRE_IF(when, expr, ...)
124 //assertions REQUIRE_IF_DBG(when, expr, ...)
125 //assertions
126 //assertions Precondition (input) check. Use these macros to validate input a
127 //assertions function receives. The checks are enabled in *ALPHA* and *BETA* builds and
128 //assertions optimized out in *RELEASE* builds.
129 //assertions
131 #define NOBUG_REQUIRE(expr, ...) \
132 NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_(expr, "PRECONDITION", \
133 NOBUG_LOCATION_INFO, ## __VA_ARGS__))
136 #define NOBUG_REQUIRE_DBG(expr, ...) \
137 NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_DBG_(expr, "PRECONDITION", \
138 NOBUG_LOCATION_INFO, ## __VA_ARGS__))
141 #define NOBUG_REQUIRE_IF(when, expr, ...) \
142 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_REQUIRE(expr, ## __VA_ARGS__)))
144 #define NOBUG_REQUIRE_IF_DBG(when, expr, ...) \
145 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_REQUIRE_DBG(expr, ## __VA_ARGS__)))
149 //assertions PARA ENSURE; ENSURE; postconditions (computation outcomes)
150 //assertions ENSURE(expr, ...)
151 //assertions ENSURE_DBG(expr, ...)
152 //assertions ENSURE_IF(when, expr, ...)
153 //assertions ENSURE_IF_DBG(when, expr, ...)
154 //assertions
155 //assertions Postcondition (progress/output) check. Use these macros to validate the
156 //assertions data a function produces (example: return value). The checks enabled
157 //assertions unconditionally in *ALPHA* builds and optimized out in *BETA* builds for
158 //assertions scopes which are tagged as `CHECKED`. In *RELEASE* builds this checks are
159 //assertions always optimized out, but scopes tagged as `UNCHECKED` are not permitted.
160 //assertions
162 #define NOBUG_ENSURE(expr, ...) \
163 NOBUG_IF_ALPHA (NOBUG_ASSERT_(expr, "POSTCONDITION", \
164 NOBUG_LOCATION_INFO, ## __VA_ARGS__)) \
165 NOBUG_IF_BETA ( \
166 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
167 NOBUG_ASSERT_(expr, "POSTCONDITION", \
168 NOBUG_LOCATION_INFO, ## __VA_ARGS__))\
171 #define NOBUG_ENSURE_DBG(expr, ...) \
172 NOBUG_IF_ALPHA (NOBUG_ASSERT_DBG_ (expr, "POSTCONDITION", \
173 NOBUG_LOCATION_INFO, ## __VA_ARGS__)) \
174 NOBUG_IF_BETA ( \
175 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
176 NOBUG_ASSERT_DBG_(expr, "POSTCONDITION", \
177 NOBUG_LOCATION_INFO, ## __VA_ARGS__)) \
181 #define NOBUG_ENSURE_IF(when, expr, ...) \
182 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ENSURE(expr, ## __VA_ARGS__)))
184 #define NOBUG_ENSURE_IF_DBG(when, expr, ...) \
185 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ENSURE_DBG(expr, ## __VA_ARGS__)))
189 //assertions PARA ASSERT; ASSERT; generic assertion
190 //assertions ASSERT(expr, ...)
191 //assertions ASSERT_DBG(expr, ...)
192 //assertions ASSERT_IF(when, expr, ...)
193 //assertions ASSERT_IF_DBG(when, expr, ...)
194 //assertions
195 //assertions Generic check. Use these macros when you want to validate something
196 //assertions which doesn't fall into one of the above categories. A example is when
197 //assertions a library function can return a unexpected result (scanf with syntax
198 //assertions error in the formatstring, when a constant/literal formatstring is
199 //assertions expected). The checks are enabled in *ALPHA* and *BETA* builds and
200 //assertions optimized out in *RELEASE* builds.
201 //assertions
203 #define NOBUG_ASSERT(expr, ...) \
204 NOBUG_IF_NOT_RELEASE( \
205 NOBUG_ASSERT_(expr, "ASSERTION", \
206 NOBUG_LOCATION_INFO, ## __VA_ARGS__) \
209 #define NOBUG_ASSERT_DBG(expr, ...) \
210 NOBUG_IF_NOT_RELEASE( \
211 NOBUG_ASSERT_DBG_(expr, "ASSERTION", \
212 NOBUG_LOCATION_INFO, ## __VA_ARGS__) \
215 #define NOBUG_ASSERT_IF(when, expr, ...) \
216 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ASSERT(expr, ## __VA_ARGS__)))
218 #define NOBUG_ASSERT_IF_DBG(when, expr, ...) \
219 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ASSERT_DBG(expr, ## __VA_ARGS__)))
224 //assertions PARA CHECK; CHECK; unnconditional assertion for testsuites
225 //assertions CHECK(expr, ...)
226 //assertions CHECK_IF(when, expr, ...)
227 //assertions
228 //assertions This assertion is never optimized out. Its main purpose is for implementing
229 //assertions testsuites where one want to assert tests independent of the build level
230 //assertions
232 #define NOBUG_CHECK(expr, ...) \
233 NOBUG_ASSERT_(expr, "CHECK", NOBUG_LOCATION_INFO, ## __VA_ARGS__)
235 #define NOBUG_CHECK_IF(when, expr, ...) \
236 NOBUG_WHEN(when, NOBUG_CHECK(expr, ## __VA_ARGS__))
241 low level assert
243 #define NOBUG_ASSERT_(expr, what, location, ...) \
244 NOBUG_WHEN (!(expr), \
245 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
246 location, what, "(%s) " \
247 NOBUG_HEAD(__VA_ARGS__), \
248 #expr NOBUG_TAIL(__VA_ARGS__)); \
249 NOBUG_BACKTRACE; \
250 NOBUG_ABORT \
253 #define NOBUG_ASSERT_DBG_(expr, what, location, ...) \
254 NOBUG_WHEN (NOBUG_ACTIVE_DBG && !(expr), \
255 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
256 location, what, "(%s) " \
257 NOBUG_HEAD(__VA_ARGS__), \
258 #expr NOBUG_TAIL(__VA_ARGS__)); \
259 NOBUG_BACKTRACE; \
260 NOBUG_ABORT \
265 //assertions PARA INVARIANT; INVARIANT; validate invariant state
266 //assertions INVARIANT(type, pointer, depth)
267 //assertions INVARIANT_DBG(type, pointer, depth)
268 //assertions INVARIANT_IF(when,type, pointer, depth)
269 //assertions INVARIANT_IF_DBG(when, type, pointer, depth)
270 //assertions
271 //assertions Checking invariants. You can provide more complex checking functions
272 //assertions which test the validity of datastructures. Invariants are only enabled
273 //assertions in *ALPHA* builds for scopes which are not tagged as `CHECKED` and
274 //assertions otherwise optimized out.
275 //assertions
276 //assertions TODO: describe how to create invariant checks
277 //assertions
279 #define NOBUG_INVARIANT(type, pointer, depth) \
280 NOBUG_IF_ALPHA( \
281 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
282 NOBUG_CAT(type,_invariant)(pointer, depth, \
283 NOBUG_LOCATION_ARGS) \
287 #define NOBUG_INVARIANT_DBG(type, pointer, ...) \
288 NOBUG_IF_ALPHA( \
289 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED && NOBUG_ACTIVE_DBG, \
290 NOBUG_CAT(type,_invariant)(pointer, depth, \
291 NOBUG_LOCATION_ARGS) \
295 #define NOBUG_INVARIANT_IF(when, type, pointer, ...) \
296 NOBUG_IF_ALPHA (NOBUG_WHEN (when, \
297 NOBUG_INVARIANT(type, pointer, ## __VA_ARGS__)) \
300 #define NOBUG_INVARIANT_IF_DBG(when, type, pointer, ...) \
301 NOBUG_IF_ALPHA (NOBUG_WHEN (when, \
302 NOBUG_INVARIANT_DBG(type, pointer, ## __VA_ARGS__))\
305 #define NOBUG_INVARIANT_ASSERT(expr, ...) \
306 NOBUG_ASSERT_(expr, "INVARIANT", (file, line, func), ## __VA_ARGS__)
310 checked/unchecked tagged scopes
312 #define NOBUG_SCOPE_UNCHECKED NOBUG_CHECKED_VALUE == 0
314 #define NOBUG_CHECKED NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=1})
316 #define NOBUG_UNCHECKED \
317 NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=0}) \
318 NOBUG_IF_RELEASE(NOBUG_UNCHECKED_NOT_ALLOWED_IN_RELEASE_BUILD)
322 /*TODO dump-level for flags instead limits[0]*/
324 //dumpmacros PARA DUMP; DUMP; dumping datastructures
325 //dumpmacros DUMP(flag, type, pointer, depth)
326 //dumpmacros DUMP_IF(when, flag, type, pointer, depth)
327 //dumpmacros
328 //dumpmacros This macros call a datastructure dump of the object (`pointer`) in question.
329 //dumpmacros `DUMP_IF` is the only enabled dumping macro for the RELEASE build level.
330 //dumpmacros
332 #define NOBUG_DUMP(flag, type, pointer, depth) \
333 NOBUG_IF_NOT_RELEASE( \
334 NOBUG_WHEN (NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET], \
335 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
336 NOBUG_LOCATION_ARGS) \
340 #define NOBUG_DUMP_DBG(flag, type, pointer, depth) \
341 NOBUG_IF_NOT_RELEASE( \
342 NOBUG_WHEN (NOBUG_ACTIVE_DBG && NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET], \
343 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
344 NOBUG_LOCATION_ARGS) \
348 #define NOBUG_DUMP_IF(when, flag, type, pointer, depth) \
349 NOBUG_WHEN (when && NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET], \
350 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
351 NOBUG_LOCATION_ARGS) \
354 #define NOBUG_DUMP_IF_DBG(when, flag, type, pointer, depth) \
355 NOBUG_IF_NOT_RELEASE( \
356 NOBUG_WHEN (NOBUG_ACTIVE_DBG && when && NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET],\
357 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
358 NOBUG_LOCATION_ARGS) \
364 //dumpmacros PARA DUMP_LOG; DUMP_LOG; logging helper for dumping
365 //dumpmacros DUMP_LOG(fmt, ...)
366 //dumpmacros DUMP_LOG_DBG(fmt, ...)
367 //dumpmacros DUMP_LOG_IF(when, fmt, ...)
368 //dumpmacros DUMP_LOG_IF_DBG(when, fmt, ...)
369 //dumpmacros
370 //dumpmacros Any output from `DUMP` handlers should be done by these macros.
371 //dumpmacros
372 //dumpmacros Dumping is by default done on level `LOG_DEBUG`, this can be overridden by
373 //dumpmacros defining `NOBUG_DUMP_LEVEL` to some other level.
374 //dumpmacros
376 #define NOBUG_DUMP_LOG(fmt, ...) \
377 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
378 (file, line, func), "DUMP", \
379 fmt, ## __VA_ARGS__)
382 #define NOBUG_DUMP_LOG_DBG(fmt, ...) \
383 NOBUG_WHEN (NOBUG_ACTIVE_DBG, \
384 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
385 (file, line, func), "DUMP", \
386 fmt, ## __VA_ARGS__) \
389 #define NOBUG_DUMP_LOG_IF(expr, fmt, ...) \
390 NOBUG_WHEN (expr, \
391 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
392 (file, line, func), "DUMP", \
393 fmt, ## __VA_ARGS__) \
396 #define NOBUG_DUMP_LOG_IF_DBG(expr, fmt, ...) \
397 NOBUG_WHEN (NOBUG_ACTIVE_DBG && expr, \
398 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
399 (file, line, func), "DUMP", \
400 fmt, ## __VA_ARGS__) \
404 #ifndef NOBUG_DUMP_LEVEL
405 #define NOBUG_DUMP_LEVEL LOG_DEBUG
406 #endif
409 Logging
413 //logmacros PARA ECHO; ECHO; unconditional logging for tests
414 //logmacros ECHO(...)
415 //logmacros
416 //logmacros Never optimized out, logs at LOG_NOTICE level. Its main purpose is for implementing
417 //logmacros testsuites where one want to print and log messages independent of the build level
418 //logmacros
420 #define NOBUG_ECHO(...) \
421 NOBUG_LOG_(&nobug_flag_NOBUG_ON, LOG_NOTICE, NOBUG_LOCATION_INFO, "ECHO", ## __VA_ARGS__)
424 //logmacros PARA ALERT; ALERT; about to die
425 //logmacros ALERT(flag, ...)
426 //logmacros ALERT_DBG(flag, ...)
427 //logmacros ALERT_IF(when, flag, ...)
428 //logmacros ALERT_IF_DBG(when, flag, ...)
429 //logmacros
430 //logmacros This is the most critical condition an application might log. This might be used
431 //logmacros if an error occurs which can not be handled except a safe shutdown for example.
432 //logmacros
434 #define NOBUG_ALERT(flag, ...) \
435 NOBUG_LOG(flag, LOG_ALERT, ## __VA_ARGS__)
436 #define NOBUG_ALERT_IF(expr, flag, ...) \
437 NOBUG_LOG_IF(expr, flag, LOG_ALERT, ## __VA_ARGS__)
438 #define NOBUG_ALERT_DBG(flag, ...) \
439 NOBUG_LOG_DBG(flag, LOG_ALERT, ## __VA_ARGS__)
440 #define NOBUG_ALERT_IF_DBG(expr, flag, ...) \
441 NOBUG_LOG_IF_DBG(expr, flag, LOG_ALERT, ## __VA_ARGS__)
444 //logmacros PARA CRITICAL; CRITICAL; can not continue
445 //logmacros CRITICAL(flag, ...)
446 //logmacros CRITICAL_DBG(flag, ...)
447 //logmacros CRITICAL_IF(when, flag, ...)
448 //logmacros CRITICAL_IF_DBG(when, flag, ...)
449 //logmacros
450 //logmacros An error which can not be handled occured but the application does not need to be
451 //logmacros shutdowen, perhaps waiting for an operator to fix the cause.
452 //logmacros
454 #define NOBUG_CRITICAL(flag, ...) \
455 NOBUG_LOG(flag, LOG_CRIT, ## __VA_ARGS__)
456 #define NOBUG_CRITICAL_IF(expr, flag, ...) \
457 NOBUG_LOG_IF(expr, flag, LOG_CRIT, ## __VA_ARGS__)
458 #define NOBUG_CRITICAL_DBG(flag, ...) \
459 NOBUG_LOG_DBG(flag, LOG_CRIT, ## __VA_ARGS__)
460 #define NOBUG_CRITICAL_IF_DBG(expr, flag, ...) \
461 NOBUG_LOG_IF_DBG(expr, flag, LOG_CRIT, ## __VA_ARGS__)
464 //logmacros PARA ERROR; ERROR; something gone wrong
465 //logmacros ERROR(flag, fmt, ...)
466 //logmacros ERROR_DBG(flag, fmt, ...)
467 //logmacros ERROR_IF(when, flag, fmt, ...)
468 //logmacros ERROR_IF_DBG(when, flag, fmt, ...)
469 //logmacros
470 //logmacros Application takes a error handling brach
471 //logmacros
473 #define NOBUG_ERROR(flag, ...) \
474 NOBUG_LOG(flag, LOG_ERR, ## __VA_ARGS__)
475 #define NOBUG_ERROR_IF(expr, flag, ...) \
476 NOBUG_LOG_IF(expr, flag, LOG_ERR, ## __VA_ARGS__)
477 #define NOBUG_ERROR_DBG(flag, ...) \
478 NOBUG_LOG_DBG(flag, LOG_ERR, ## __VA_ARGS__)
479 #define NOBUG_ERROR_IF_DBG(expr, flag, ...) \
480 NOBUG_LOG_IF_DBG(expr, flag, LOG_ERR, ## __VA_ARGS__)
483 //logmacros PARA WARN; WARN; unexpected fixable error
484 //logmacros WARN(flag, fmt, ...)
485 //logmacros WARN_DBG(flag, fmt, ...)
486 //logmacros WARN_IF(when, flag, fmt, ...)
487 //logmacros WARN_IF_DBG(when, flag, fmt, ...)
488 //logmacros
489 //logmacros Rare, handled but unexpected branch
490 //logmacros
492 #define NOBUG_WARN(flag, ...) \
493 NOBUG_LOG(flag, LOG_WARNING, ## __VA_ARGS__)
494 #define NOBUG_WARN_IF(expr, flag, ...) \
495 NOBUG_LOG_IF(expr, flag, LOG_WARNING, ## __VA_ARGS__)
496 #define NOBUG_WARN_DBG(flag, ...) \
497 NOBUG_LOG_DBG(flag, LOG_WARNING, ## __VA_ARGS__)
498 #define NOBUG_WARN_IF_DBG(expr, flag, ...) \
499 NOBUG_LOG_IF_DBG(expr, flag, LOG_WARNING, ## __VA_ARGS__)
502 //logmacros PARA INFO; INFO; progress message
503 //logmacros INFO(flag, fmt, ...)
504 //logmacros INFO_DBG(flag, fmt, ...)
505 //logmacros INFO_IF(when, flag, fmt, ...)
506 //logmacros INFO_IF_DBG(when, flag, fmt, ...)
507 //logmacros
508 //logmacros Message about program progress
509 //logmacros
511 #define NOBUG_INFO(flag, ...) \
512 NOBUG_LOG(flag, LOG_INFO, ## __VA_ARGS__)
513 #define NOBUG_INFO_IF(expr, flag, ...) \
514 NOBUG_LOG_IF(expr, flag, LOG_INFO, ## __VA_ARGS__)
515 #define NOBUG_INFO_DBG(flag, ...) \
516 NOBUG_LOG_DBG(flag, LOG_INFO, ## __VA_ARGS__)
517 #define NOBUG_INFO_IF_DBG(expr, flag, ...) \
518 NOBUG_LOG_IF_DBG(expr, flag, LOG_INFO, ## __VA_ARGS__)
521 //logmacros PARA NOTICE; NOTICE; detailed progress message
522 //logmacros NOTICE(flag, fmt, ...)
523 //logmacros NOTICE_DBG(flag, fmt, ...)
524 //logmacros NOTICE_IF(when, flag, fmt, ...)
525 //logmacros NOTICE_IF_DBG(when, flag, fmt, ...)
526 //logmacros
527 //logmacros More detailed progress message
528 //logmacros
530 #define NOBUG_NOTICE(flag, ...) \
531 NOBUG_LOG(flag, LOG_NOTICE, ## __VA_ARGS__)
532 #define NOBUG_NOTICE_IF(expr, flag, ...) \
533 NOBUG_LOG_IF(expr, flag, LOG_NOTICE, ## __VA_ARGS__)
534 #define NOBUG_NOTICE_DBG(flag, ...) \
535 NOBUG_LOG_DBG(flag, LOG_NOTICE, ## __VA_ARGS__)
536 #define NOBUG_NOTICE_IF_DBG(expr, flag, ...) \
537 NOBUG_LOG_IF_DBG(expr, flag, LOG_NOTICE, ## __VA_ARGS__)
540 //logmacros PARA TRACE; TRACE; debugging level message
541 //logmacros TRACE(flag, fmt, ...)
542 //logmacros TRACE_DBG(flag, fmt, ...)
543 //logmacros TRACE_IF(when, flag, fmt, ...)
544 //logmacros TRACEIF_DBG(when, flag, fmt, ...)
545 //logmacros
546 //logmacros Very fine grained messages
547 //logmacros
548 //logmacros NOTE: that `TRACE` corresponds to `LOG_DEBUG`, because using `DEBUG` could be ambiguous.
549 //logmacros
551 #define NOBUG_TRACE(flag, ...) \
552 NOBUG_LOG(flag, LOG_DEBUG, ## __VA_ARGS__)
553 #define NOBUG_TRACE_IF(expr, flag, ...) \
554 NOBUG_LOG_IF(expr, flag, LOG_DEBUG, ## __VA_ARGS__)
555 #define NOBUG_TRACE_DBG(flag, ...) \
556 NOBUG_LOG_DBG(flag, LOG_DEBUG, ## __VA_ARGS__)
557 #define NOBUG_TRACE_IF_DBG(expr, flag, ...) \
558 NOBUG_LOG_IF_DBG(expr, flag, LOG_DEBUG, ## __VA_ARGS__)
562 //logmacros PARA LOG; LOG; generic logging
563 //logmacros LOG(flag, lvl, fmt, ...)
564 //logmacros LOG_DBG(flag, lvl, fmt, ...)
565 //logmacros LOG_IF(when, flag, lvl, fmt, ...)
566 //logmacros LOG_IF_DBG(when, flag, lvl, fmt, ...)
567 //logmacros
568 //logmacros Generic logging macro which takes the level explicitly,
569 //logmacros avoid this, unless you implement your own logging facilities.
570 //logmacros
572 #define NOBUG_LOG(flag, lvl, ...) \
573 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
574 NOBUG_LVL(lvl), ## __VA_ARGS__)
576 #define NOBUG_LOG_DBG(flag, lvl, ...) \
577 NOBUG_WHEN (NOBUG_ACTIVE_DBG, \
578 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
579 NOBUG_LVL(lvl), ## __VA_ARGS__) \
582 #define NOBUG_LOG_IF(expr, flag, lvl, ...) \
583 NOBUG_WHEN (expr, \
584 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
585 NOBUG_LVL(lvl), ## __VA_ARGS__) \
588 #define NOBUG_LOG_IF_DBG(expr, flag, lvl, ...) \
589 NOBUG_WHEN (NOBUG_ACTIVE_DBG && expr, \
590 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
591 NOBUG_LVL(lvl), ## __VA_ARGS__) \
596 low level logging handler
598 #define NOBUG_LOG_(flag, lvl, location, what, ...) \
599 NOBUG_WHEN (lvl <= NOBUG_LOG_BASELIMIT && lvl <= (flag)->limits[NOBUG_TARGET_RINGBUFFER], \
600 nobug_log (flag, lvl, \
601 "%0.10llu: %s: %s:%d:"NOBUG_THREAD_ID_FMT(" ",":")" %s: " \
602 NOBUG_HEAD(__VA_ARGS__), ++nobug_counter, what, \
603 NOBUG_LOCATION_FILE location, \
604 NOBUG_LOCATION_LINE location NOBUG_THREAD_ID_COMMA, \
605 NOBUG_LOCATION_FUNC location NOBUG_TAIL(__VA_ARGS__)) \
608 #define NOBUG_LVL(lvl) NOBUG_LVL_##lvl
609 #define NOBUG_LVL_0 "EMERG"
610 #define NOBUG_LVL_1 "ALERT"
611 #define NOBUG_LVL_2 "CRIT"
612 #define NOBUG_LVL_3 "ERR"
613 #define NOBUG_LVL_4 "WARNING"
614 #define NOBUG_LVL_5 "NOTICE"
615 #define NOBUG_LVL_6 "INFO"
616 #define NOBUG_LVL_7 "TRACE"
619 //logmacros PARA LOG_BASELIMIT; LOG_BASELIMIT; minimum compliled-in logging limit
620 //logmacros NOBUG_LOG_BASELIMIT_ALPHA
621 //logmacros NOBUG_LOG_BASELIMIT_BETA
622 //logmacros NOBUG_LOG_BASELIMIT_RELEASE
623 //logmacros NOBUG_LOG_BASELIMIT
624 //logmacros
625 //logmacros NoBug defines some logging base limits, anything more detailed
626 //logmacros than this base limits will be optimized out. This is used to
627 //logmacros reduce the logging overhead for *RELEASE* builds.
628 //logmacros By default the limit is set to `LOG_DEBUG` for *ALPHA* and *BETA*
629 //logmacros builds, so all logging is retained and `LOG_NOTICE` in *RELEASE*
630 //logmacros builds to log the application progress only coarsely then.
631 //logmacros
632 //logmacros This macros can be defined before including 'nobug.h' to some other
633 //logmacros log level (as defined in 'syslog.h').
634 //logmacros
636 #ifndef NOBUG_LOG_BASELIMIT_ALPHA
637 #define NOBUG_LOG_BASELIMIT_ALPHA LOG_DEBUG
638 #endif
640 #ifndef NOBUG_LOG_BASELIMIT_BETA
641 #define NOBUG_LOG_BASELIMIT_BETA LOG_DEBUG
642 #endif
644 #ifndef NOBUG_LOG_BASELIMIT_RELEASE
645 #define NOBUG_LOG_BASELIMIT_RELEASE LOG_NOTICE
646 #endif
648 #ifndef NOBUG_LOG_BASELIMIT
649 #define NOBUG_LOG_BASELIMIT \
650 NOBUG_IF_ALPHA(NOBUG_LOG_BASELIMIT_ALPHA) \
651 NOBUG_IF_BETA(NOBUG_LOG_BASELIMIT_BETA) \
652 NOBUG_IF_RELEASE(NOBUG_LOG_BASELIMIT_RELEASE)
653 #endif
656 Annotations
660 alpha beta release
661 DEPRECATED log nothing wont compile
663 //annotations PARA DEPRECATED; DEPRECATED; to be discarded in future
664 //annotations DEPRECATED(...)
665 //annotations
666 //annotations Something which shouldn't be used in future
667 //annotations
669 #define NOBUG_DEPRECATED(msg) \
670 NOBUG_IF_ALPHA(NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_WARN, \
671 NOBUG_LOCATION_INFO, "DEPRECATED", msg) \
673 NOBUG_IF_RELEASE(NOBUG_DEPRECATED_NOT_ALLOWED_IN_RELEASE_BUILD(msg))
677 alpha beta release
678 UNIMPLEMENTED abort abort wont compile
680 //annotations PARA UNIMPLEMENTED; UNIMPLEMENTED; not yet implemented
681 //annotations UNIMPLEMENTED(...)
682 //annotations
683 //annotations not yet finished feature
684 //annotations
686 #define NOBUG_UNIMPLEMENTED(msg) \
687 NOBUG_IF_NOT_RELEASE ( do { \
688 NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_EMERG, NOBUG_LOCATION_INFO, \
689 "UNIMPLEMENTED", msg); \
690 NOBUG_ABORT; \
691 } while (0)) \
692 NOBUG_IF_RELEASE( NOBUG_UNIMPLEMENTED_NOT_ALLOWED_IN_RELEASE_BUILD(msg))
696 alpha beta release
697 FIXME log wont compile wont compile
699 //annotations PARA FIXME; FIXME; known bug
700 //annotations FIXME(...)
701 //annotations
702 //annotations known bug to be fixed later
703 //annotations
705 #define NOBUG_FIXME(msg) \
706 NOBUG_IF_ALPHA( NOBUG_ONCE( NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_ALERT, \
707 NOBUG_LOCATION_INFO, "FIXME", msg))) \
708 NOBUG_IF_BETA( NOBUG_FIXME_NOT_ALLOWED_IN_BETA_BUILD(msg)) \
709 NOBUG_IF_RELEASE( NOBUG_FIXME_NOT_ALLOWED_IN_RELEASE_BUILD(msg))
713 alpha beta release
714 TODO log log wont compile
716 //annotations PARA TODO; TODO; things to be done
717 //annotations TODO(...)
718 //annotations
719 //annotations enhancement to be done soon
720 //annotations
722 #define NOBUG_TODO(msg) \
723 NOBUG_IF_NOT_RELEASE ( \
724 NOBUG_ONCE ( \
725 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_NOTICE, NOBUG_LOCATION_INFO, \
726 "TODO", msg); \
727 )) \
728 NOBUG_IF_RELEASE(NOBUG_TODO_NOT_ALLOWED_IN_RELEASE_BUILD(msg))
732 alpha beta release
733 PLANNED log nothing nothing
735 //annotations PARA PLANNED; PLANNED; ideas for future
736 //annotations PLANNED(...)
737 //annotations
738 //annotations future enhancement
739 //annotations
741 #define NOBUG_PLANNED(msg) \
742 NOBUG_IF_ALPHA( NOBUG_ONCE(NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_INFO, \
743 NOBUG_LOCATION_INFO, "PLANNED", msg)))
747 alpha beta release
748 NOTREACHED abort abort nothing
750 //annotations PARA NOTREACHED; NOTREACHED; code path never taken
751 //annotations NOTREACHED
752 //annotations
753 //annotations used to tag code-path which shall be never executed (defaults in switch
754 //annotations statements, `else NOTREACHED;` after series of if's, etc.)
755 //annotations
757 #define NOBUG_NOTREACHED \
758 NOBUG_IF_NOT_RELEASE( do { \
759 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG, \
760 NOBUG_LOCATION_INFO, "NOTREACHED"); \
761 NOBUG_ABORT; \
762 } while (0))
766 Fault injection
768 //faultinjection NoBug has some macros which can be used to simulate errorneous behaviour:
769 //faultinjection
771 //faultinjection PARA INJECT_GOODBAD; INJECT_GOODBAD; fault injection expression
772 //faultinjection INJECT_GOODBAD(expr, good, bad)
773 //faultinjection
774 //faultinjection substitutes to an expression and returns good when expr is false and
775 //faultinjection bad when expr is true. In BETA and RELEASE builds 'good' is always returned.
776 //faultinjection
778 #define NOBUG_INJECT_GOODBAD(expr, good, bad) \
779 NOBUG_IF_ALPHA((expr)?({NOBUG_INJECT_LOG(#expr": "#bad);}),bad:good) \
780 NOBUG_IF_NOT_ALPHA(good)
784 //faultinjection PARA INJECT_FAULT; INJECT_FAULT; fault injection statement
785 //faultinjection INJECT_FAULT(expr, bad)
786 //faultinjection
787 //faultinjection substitutes to a statement which executes 'bad'
788 //faultinjection when expr is true. Optimitzed out in BETA and RELEASE builds.
789 //faultinjection
791 #define NOBUG_INJECT_FAULT(expr, bad) \
792 NOBUG_IF_ALPHA(NOBUG_WHEN(expr,NOBUG_INJECT_LOG(#expr": "#bad); bad))
796 //faultinjection PARA INJECT_LEVEL; INJECT_LEVEL; log level for fault injection
797 //faultinjection In both cases, when a fault is injected it will be logged at
798 //faultinjection `NOBUG_INJECT_LEVEL` (default: `LOG_NOTICE`). This can be defined
799 //faultinjection before including 'nobug.h' to override it.
800 //faultinjection
802 #define NOBUG_INJECT_LOG(msg) \
803 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_INJECT_LEVEL, \
804 NOBUG_LOCATION_INFO, "INJECT_FAULT", \
805 msg)
808 #ifndef NOBUG_INJECT_LEVEL
809 #define NOBUG_INJECT_LEVEL LOG_NOTICE
810 #endif
814 Flag handling
816 #define NOBUG_FLAG(name) NOBUG_CAT(nobug_flag_, name)
819 //predefflags PARA NOBUG_FLAG_RAW; NOBUG_FLAG_RAW; pass direct flag pointer
820 //predefflags NOBUG_FLAG_RAW(ptr)
821 //predefflags
822 //predefflags Using this macro one can pass a direct pointer to a flag where a name would
823 //predefflags be expected. This is sometimes convinient when flag pointers are passed around
824 //predefflags in management strutures and one wants to tie logging to dynamic targets.
825 //predefflags
826 //predefflags [source,c]
827 //predefflags ----
828 //predefflags NOBUG_DEFINE_FLAG(myflag);
829 //predefflags ...
830 //predefflags struct nobug_flag* ptr = &NOBUG_FLAG(myflag);
831 //predefflags TRACE(NOBUG_FLAG_RAW(ptr), "Passed flag by pointer")
832 //predefflags ----
833 //predefflags
835 #define nobug_flag_NOBUG_FLAG_RAW(name) *name
837 #define NOBUG_DECLARE_FLAG(name) extern struct nobug_flag NOBUG_FLAG(name)
840 #define NOBUG_DEFINE_FLAG(name) \
841 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
842 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
843 struct nobug_flag NOBUG_FLAG(name) = \
844 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
845 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
846 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
847 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
848 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
849 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
853 #define NOBUG_DEFINE_FLAG_PARENT(name, parent) \
854 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
855 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
856 NOBUG_DECLARE_FLAG(parent); \
857 struct nobug_flag NOBUG_FLAG(name) = \
858 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
859 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
860 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
861 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
862 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
863 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
867 #define NOBUG_DEFINE_FLAG_LIMIT(name, limit) \
868 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
869 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
870 struct nobug_flag NOBUG_FLAG(name) = \
871 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
872 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
873 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
874 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
875 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
876 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
880 #define NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, limit) \
881 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
882 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
883 NOBUG_DECLARE_FLAG(parent); \
884 struct nobug_flag NOBUG_FLAG(name) = \
885 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
886 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
887 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
888 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
889 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
890 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
894 #define NOBUG_INIT_FLAG(name) \
895 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, NOBUG_LOG_LIMIT)
898 #define NOBUG_INIT_FLAG_LIMIT(name, default) \
899 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, default)
902 #define NOBUG_CPP_DEFINE_FLAG(name) \
903 NOBUG_FLAG_IF_DECLAREONLY( \
904 NOBUG_DECLARE_FLAG(name); \
905 extern int nobug_cppflag_##name \
907 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
908 NOBUG_DEFINE_FLAG(name); \
909 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
913 #define NOBUG_CPP_DEFINE_FLAG_PARENT(name, parent) \
914 NOBUG_FLAG_IF_DECLAREONLY( \
915 NOBUG_DECLARE_FLAG(name); \
916 extern int nobug_cppflag_##name \
918 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
919 NOBUG_DEFINE_FLAG_PARENT(name, parent); \
920 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
924 #define NOBUG_CPP_DEFINE_FLAG_LIMIT(name, default) \
925 NOBUG_FLAG_IF_DECLAREONLY( \
926 NOBUG_DECLARE_FLAG(name); \
927 extern int nobug_cppflag_##name \
929 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
930 NOBUG_DEFINE_FLAG_LIMIT(name, default); \
931 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
935 #define NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT(name, parent, default) \
936 NOBUG_FLAG_IF_DECLAREONLY( \
937 NOBUG_DECLARE_FLAG(name); \
938 extern int nobug_cppflag_##name \
940 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
941 NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, default); \
942 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
946 #ifndef NOBUG_DECLARE_ONLY
947 #define NOBUG_DECLARE_ONLY 0
948 #endif
950 #define NOBUG_FLAG_IF_DECLAREONLY(...) \
951 NOBUG_IF(NOBUG_DECLARE_ONLY, __VA_ARGS__)
953 #define NOBUG_FLAG_IF_NOT_DECLAREONLY(...) \
954 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
956 #ifdef __cplusplus
957 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
958 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
959 #else
960 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
961 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, NOBUG_ERROR_CANT_DEFINE_AUTOINITIALIZED_CPP_FLAGS_IN_C)
962 #endif
964 #ifndef NOBUG_LOG_LIMIT_ALPHA
965 # define NOBUG_LOG_LIMIT_ALPHA LOG_INFO
966 #endif
967 #ifndef NOBUG_LOG_LIMIT_BETA
968 # define NOBUG_LOG_LIMIT_BETA LOG_WARNING
969 #endif
970 #ifndef NOBUG_LOG_LIMIT_RELEASE
971 # define NOBUG_LOG_LIMIT_RELEASE LOG_CRIT
972 #endif
974 #ifndef NOBUG_LOG_LIMIT
975 # define NOBUG_LOG_LIMIT \
976 NOBUG_IF_ALPHA( NOBUG_LOG_LIMIT_ALPHA) \
977 NOBUG_IF_BETA( NOBUG_LOG_LIMIT_BETA) \
978 NOBUG_IF_RELEASE( NOBUG_LOG_LIMIT_RELEASE)
979 #endif
981 #ifndef NOBUG_LOG_TARGET_ALPHA
982 # define NOBUG_LOG_TARGET_ALPHA NOBUG_TARGET_CONSOLE
983 #endif
984 #ifndef NOBUG_LOG_TARGET_BETA
985 # define NOBUG_LOG_TARGET_BETA NOBUG_TARGET_FILE
986 #endif
987 #ifndef NOBUG_LOG_TARGET_RELEASE
988 # define NOBUG_LOG_TARGET_RELEASE NOBUG_TARGET_SYSLOG
989 #endif
991 #ifndef NOBUG_LOG_TARGET
992 # define NOBUG_LOG_TARGET \
993 NOBUG_IF_ALPHA( NOBUG_LOG_TARGET_ALPHA) \
994 NOBUG_IF_BETA( NOBUG_LOG_TARGET_BETA) \
995 NOBUG_IF_RELEASE( NOBUG_LOG_TARGET_RELEASE)
996 #endif
998 #define NOBUG_SET_LIMIT(flag, min) \
999 NOBUG_IF_NOT_RELEASE( NOBUG_FLAG(flag) = (min))
1003 Resource registry macros
1007 //index.resource_logging xref:RESOURCE_LOGGING[RESOURCE_LOGGING]:: switch resource logging on and off
1008 //index.resource_log_level xref:RESOURCE_LOGGING[RESOURCE_LOG_LEVEL]:: select the log level for resource logging
1009 //resourcemacros [[RESOURCE_LOGGING]]
1010 //resourcemacros
1011 //resourcemacros Unless the user defines `NOBUG_RESOURCE_LOGGING` to 0 each of the above macros
1012 //resourcemacros will emit a log message at `NOBUG_RESOURCE_LOG_LEVEL` which defaults to
1013 //resourcemacros `LOG_DEBUG`.
1014 //resourcemacros
1016 #ifndef NOBUG_RESOURCE_LOGGING
1017 #define NOBUG_RESOURCE_LOGGING 1
1018 #endif
1020 #ifndef NOBUG_RESOURCE_LOG_LEVEL
1021 #define NOBUG_RESOURCE_LOG_LEVEL LOG_DEBUG
1022 #endif
1026 //index.resource_handle xref:RESOURCE_HANDLE[RESOURCE_HANDLE]:: define an resource handle
1027 //resourcemacros [[RESOURCE_HANDLE]]
1028 //resourcemacros Resources are accessed through handles.
1029 //resourcemacros
1030 //resourcemacros .RESOURCE_HANDLE
1031 //resourcemacros RESOURCE_HANDLE(name)
1032 //resourcemacros
1033 //resourcemacros Defines handles to access resources.
1034 //resourcemacros
1035 //resourcemacros `name`::
1036 //resourcemacros identifer to be used for the handle
1037 //resourcemacros
1038 //resourcemacros This macro takes care that the declaration is optimized out in the same manner
1039 //resourcemacros the rest of the resource tracker would be disabled. You can still instantiate
1040 //resourcemacros handles as `struct nobug_resource_header*` in structures which must have a
1041 //resourcemacros constant size unconditional of the build level.
1042 //resourcemacros
1044 #define NOBUG_RESOURCE_HANDLE(handle) \
1045 NOBUG_IF_ALPHA(struct nobug_resource_header* handle)
1047 #define NOBUG_RESOURCE_HANDLE_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
1051 //index.resource_announce xref:RESOURCE_ANNOUNCE[RESOURCE_ANNOUNCE]:: publish new resources
1052 //resourcemacros [[RESOURCE_ANNOUNCE]]
1053 //resourcemacros
1054 //resourcemacros .RESOURCE_ANNOUNCE
1055 //resourcemacros RESOURCE_ANNOUNCE(flag, type, name, identifier, handle)
1056 //resourcemacros
1057 //resourcemacros Publishes resources.
1058 //resourcemacros
1059 //resourcemacros `flag`::
1060 //resourcemacros the NoBug flag which turns logging on for this macro
1061 //resourcemacros `type`::
1062 //resourcemacros a string which should denote the domain of the resource,
1063 //resourcemacros examples are "file", "mutex", "lock", "database" and so on
1064 //resourcemacros `name`::
1065 //resourcemacros the actual name of a named resource this as string which
1066 //resourcemacros together with type forms a unique identifier of the resource. `type` and
1067 //resourcemacros `name` must be available through the entire lifetime of the resource, using
1068 //resourcemacros literal strings is recommended
1069 //resourcemacros `identifier`::
1070 //resourcemacros a pointer which should be unique for this resource, any
1071 //resourcemacros kind of pointer will suffice, it is only used for identification. In
1072 //resourcemacros multithreaded applications the thread identifier becomes an additional
1073 //resourcemacros identifier
1074 //resourcemacros `handle`::
1075 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to point to
1076 //resourcemacros the newly created resource.
1077 //resourcemacros
1078 //resourcemacros Resources must be unique, it is a fatal error when a resource it tried to be
1079 //resourcemacros announced more than one time.
1080 //resourcemacros
1082 #define NOBUG_RESOURCE_ANNOUNCE(flag, type, name, ptr, handle) \
1083 NOBUG_RESOURCE_ANNOUNCE_RAW(&NOBUG_FLAG(flag), type, name, ptr, handle)
1085 #define NOBUG_RESOURCE_ANNOUNCE_RAW(flag, type, name, ptr, handle) \
1086 NOBUG_IF_ALPHA( do { \
1087 NOBUG_REQUIRE(!handle, "Announced resource handle not initialized"); \
1088 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1089 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1090 NOBUG_LOCATION_INFO, "RESOURCE_ANNOUNCE", \
1091 "%s: %s@%p", type, name, ptr);) \
1092 NOBUG_RESOURCE_ASSERT(handle = &nobug_resource_announce (type, name, ptr, \
1093 NOBUG_BASENAME(__FILE__ ":" NOBUG_STRINGIZE(__LINE__)))->hdr, \
1094 "RESOURCE_ASSERT_ANNOUNCE", NOBUG_LOCATION_INFO, \
1095 "%s: %s@%p %s", type, name, ptr, nobug_resource_error); \
1096 } while (0))
1100 //index.resource_forget xref:RESOURCE_FORGET[RESOURCE_FORGET]:: remove resources
1101 //resourcemacros [[RESOURCE_FORGET]]
1102 //resourcemacros
1103 //resourcemacros .RESOURCE_FORGET
1104 //resourcemacros RESOURCE_FORGET(flag, handle)
1105 //resourcemacros
1106 //resourcemacros Removes resources that have become unavailable from the registry.
1107 //resourcemacros
1108 //resourcemacros `flag`::
1109 //resourcemacros the NoBug flag which turns logging on for this macro
1110 //resourcemacros `handle`::
1111 //resourcemacros the `NOBUG_RESOURCE_HANDLE` used to track this resource
1112 //resourcemacros
1113 //resourcemacros The resource must still exist and no users must be attached to it, else a fatal
1114 //resourcemacros error is raised.
1115 //resourcemacros
1117 #define NOBUG_RESOURCE_FORGET(flag, handle) \
1118 NOBUG_RESOURCE_FORGET_RAW(&NOBUG_FLAG(flag), handle)
1120 #define NOBUG_RESOURCE_FORGET_RAW(flag, handle) \
1121 NOBUG_IF_ALPHA( do { \
1122 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1123 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
1124 "RESOURCE_FORGET", "%s: %s@%p", \
1125 handle?((struct nobug_resource_record*)handle)->type:"", \
1126 handle?handle->name:"", \
1127 handle?((struct nobug_resource_record*)handle)->object_id:NULL);) \
1128 NOBUG_RESOURCE_ASSERT(nobug_resource_forget ((struct nobug_resource_record*)handle), \
1129 "RESOURCE_ASSERT_FORGET", NOBUG_LOCATION_INFO, "%s: %s@%p: %s", \
1130 handle?((struct nobug_resource_record*)handle)->type:"", \
1131 handle?handle->name:"", \
1132 handle?((struct nobug_resource_record*)handle)->object_id:NULL, \
1133 nobug_resource_error); \
1134 handle = NULL; \
1135 } while (0))
1139 //index.resource_enter xref:RESOURCE_ENTER[RESOURCE_ENTER]:: claim a resource
1140 //resourcemacros [[RESOURCE_ENTER]]
1141 //resourcemacros
1142 //resourcemacros .RESOURCE_ENTER
1143 //resourcemacros RESOURCE_ENTER(flag, announced, name, identifier, state, handle)
1144 //resourcemacros
1145 //resourcemacros Attach a resource to code.
1146 //resourcemacros
1147 //resourcemacros `flag`::
1148 //resourcemacros nobug flag which turns logging on for this macro
1149 //resourcemacros `announced`::
1150 //resourcemacros the handle set by `RESOURCE_ANNOUNCE`
1151 //resourcemacros `name`::
1152 //resourcemacros a free-form identifier
1153 //resourcemacros `identifier`::
1154 //resourcemacros some pointer which must be unique for the user of the
1155 //resourcemacros resource (see above)
1156 //resourcemacros `state`::
1157 //resourcemacros the initial state, one of `NOBUG_RESOURCE_WAITING`,
1158 //resourcemacros `NOBUG_RESOURCE_EXCLUSIVE` or `NOBUG_RESOURCE_RECURSIVE`
1159 //resourcemacros `handle`::
1160 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to the
1161 //resourcemacros entering node
1162 //resourcemacros
1164 #define NOBUG_RESOURCE_ENTER(flag, resource, user, state, handle) \
1165 NOBUG_IF_ALPHA( do { \
1166 NOBUG_REQUIRE(resource, "Announced resource handle not initialized"); \
1167 NOBUG_REQUIRE(!handle, "Resource handle already entered"); \
1168 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1169 NOBUG_LOG_(&NOBUG_FLAG(flag), NOBUG_RESOURCE_LOG_LEVEL, \
1170 NOBUG_LOCATION_INFO, "RESOURCE_ENTER", \
1171 "%s: %s@%p: %s: %s", \
1172 resource?((struct nobug_resource_record*)resource)->type:"", \
1173 resource?resource->name:"", \
1174 resource?((struct nobug_resource_record*)resource)->object_id:NULL, \
1175 user, \
1176 nobug_resource_states[state]);) \
1177 NOBUG_RESOURCE_ASSERT(handle = &nobug_resource_enter ((struct nobug_resource_record*)resource, \
1178 user, state, \
1179 NOBUG_BASENAME(__FILE__ ":" NOBUG_STRINGIZE(__LINE__)))->hdr, \
1180 "RESOURCE_ASSERT_ENTER", NOBUG_LOCATION_INFO, \
1181 "%s: %s@%p: %s: %s: %s", \
1182 resource?((struct nobug_resource_record*)resource)->type:"", \
1183 resource?resource->name:"", \
1184 resource?((struct nobug_resource_record*)resource)->object_id:NULL, \
1185 user, nobug_resource_states[state], \
1186 nobug_resource_error); \
1187 } while (0))
1191 //index.resource_state xref:RESOURCE_STATE[RESOURCE_STATE]:: change the state of a resource
1192 //resourcemacros [[RESOURCE_STATE]]
1193 //resourcemacros
1194 //resourcemacros .NOBUG_RESOURCE_STATE
1195 //resourcemacros NOBUG_RESOURCE_STATE(flag, entered, state)
1196 //resourcemacros
1197 //resourcemacros Changes resource's state.
1198 //resourcemacros
1199 //resourcemacros `flag`::
1200 //resourcemacros is nobug flag which turns logging on for this macro
1201 //resourcemacros `state`::
1202 //resourcemacros the new state Note that only certain state transitions are
1203 //resourcemacros allowed, see discussion/diagram above
1204 //resourcemacros `entered`::
1205 //resourcemacros the handle set by `RESOURCE_ENTER`
1206 //resourcemacros
1208 #define NOBUG_RESOURCE_STATE(flag, state, entered) \
1209 NOBUG_RESOURCE_STATE_RAW(&NOBUG_FLAG(flag), state, entered)
1211 #define NOBUG_RESOURCE_STATE_RAW(flag, nstate, entered) \
1212 NOBUG_IF_ALPHA( do { \
1213 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1214 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
1215 "RESOURCE_STATE", "%s: %s@%p: %s: %s->%s", \
1216 entered?((struct nobug_resource_user*)entered)->resource->type:"", \
1217 entered?((struct nobug_resource_user*)entered)->resource->hdr.name:"", \
1218 entered?((struct nobug_resource_user*)entered)->resource->object_id:"", \
1219 entered?entered->name:"", \
1220 nobug_resource_states[entered?((struct nobug_resource_user*)entered)->state \
1221 :NOBUG_RESOURCE_INVALID], \
1222 nobug_resource_states[nstate]); \
1224 NOBUG_RESOURCE_ASSERT(nobug_resource_state ((struct nobug_resource_user*)entered, nstate), \
1225 "RESOURCE_ASSERT_STATE", NOBUG_LOCATION_INFO, \
1226 "%s: %s@%p: %s: %s->%s: %s", \
1227 entered?((struct nobug_resource_user*)entered)->resource->type:"", \
1228 entered?((struct nobug_resource_user*)entered)->resource->hdr.name:"", \
1229 entered?((struct nobug_resource_user*)entered)->resource->object_id:"", \
1230 entered?entered->name:"", \
1231 nobug_resource_states[entered?((struct nobug_resource_user*)entered)->state \
1232 :NOBUG_RESOURCE_INVALID], \
1233 nobug_resource_states[nstate], \
1234 nobug_resource_error); \
1235 } while (0))
1239 //index.resource_leave xref:RESOURCE_LEAVE[RESOURCE_LEAVE]:: relinquish a claimed resource
1240 //resourcemacros [[RESOURCE_LEAVE]]
1241 //resourcemacros
1242 //resourcemacros .RESOURCE_LEAVE
1243 //resourcemacros RESOURCE_LEAVE(flag, handle)
1244 //resourcemacros
1245 //resourcemacros Disconnect from a resource identified with its handle.
1246 //resourcemacros
1247 //resourcemacros `flag`::
1248 //resourcemacros nobug flag which turns logging on for this macro
1249 //resourcemacros `handle`::
1250 //resourcemacros the handle you got while entering the resource
1251 //resourcemacros
1253 #define NOBUG_RESOURCE_LEAVE(flag, handle) \
1254 NOBUG_RESOURCE_LEAVE_RAW(&NOBUG_FLAG(flag), handle)
1256 #define NOBUG_RESOURCE_LEAVE_RAW(flag, handle) \
1257 NOBUG_IF_ALPHA( do { \
1258 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1259 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
1260 "RESOURCE_LEAVE", "%s: %s@%p: %s: %s", \
1261 handle?((struct nobug_resource_user*)handle)->resource->type:"", \
1262 handle?((struct nobug_resource_user*)handle)->resource->hdr.name:"", \
1263 handle?((struct nobug_resource_user*)handle)->resource->object_id:"", \
1264 handle?handle->name:"", \
1265 nobug_resource_states[handle?((struct nobug_resource_user*)handle)->state \
1266 :NOBUG_RESOURCE_INVALID]); \
1268 NOBUG_RESOURCE_ASSERT(nobug_resource_leave ((struct nobug_resource_user*)handle), \
1269 "RESOURCE_ASSERT_LEAVE", NOBUG_LOCATION_INFO, "%s: %s@%p: %s: %s: %s", \
1270 handle?((struct nobug_resource_user*)handle)->resource->type:"", \
1271 handle?((struct nobug_resource_user*)handle)->resource->hdr.name:"", \
1272 handle?((struct nobug_resource_user*)handle)->resource->object_id:"", \
1273 handle?handle->name:"", \
1274 nobug_resource_states[handle?((struct nobug_resource_user*)handle)->state \
1275 :NOBUG_RESOURCE_INVALID], \
1276 nobug_resource_error); \
1277 handle = NULL; \
1278 } while (0))
1282 /* assertion which dumps all resources */
1283 #define NOBUG_RESOURCE_ASSERT(resource, what, location, ...) \
1284 NOBUG_WHEN (!(resource), \
1285 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
1286 location, what, \
1287 ## __VA_ARGS__); \
1288 nobug_resource_dump_all (&(struct nobug_resource_dump_context) \
1289 {&nobug_flag_NOBUG_ON, \
1290 LOG_EMERG, \
1291 NOBUG_LOCATION_ARGS}); \
1292 NOBUG_BACKTRACE; \
1293 NOBUG_ABORT \
1298 //index.resource_dump xref:NOBUG_RESOURCE_DUMP[NOBUG_RESOURCE_DUMP]:: dump the state of a single resource
1299 //resourcemacros [[NOBUG_RESOURCE_DUMP]]
1300 //resourcemacros
1301 //resourcemacros .NOBUG_RESOURCE_DUMP
1302 //resourcemacros NOBUG_RESOURCE_DUMP(flag, handle)
1303 //resourcemacros
1304 //resourcemacros Dump the state of a single resource.
1305 //resourcemacros
1306 //resourcemacros `flag`::
1307 //resourcemacros Nobug flag for the log channel
1308 //resourcemacros `handle`::
1309 //resourcemacros handle of the resource to be dumped
1310 //resourcemacros
1312 #define NOBUG_RESOURCE_DUMP(flag, handle) \
1313 do { NOBUG_RESOURCE_LOCK; \
1314 nobug_resource_dump (handle, &(struct nobug_resource_dump_context) \
1315 {&NOBUG_FLAG(flag), \
1316 NOBUG_RESOURCE_LOG_LEVEL, \
1317 NOBUG_LOCATION_ARGS}); \
1318 NOBUG_RESOURCE_UNLOCK; } while (0)
1320 #define NOBUG_RESOURCE_DUMP_IF(when, flag, handle) \
1321 NOBUG_WHEN(when, NOBUG_RESOURCE_LOCK; \
1322 nobug_resource_dump (handle, &(struct nobug_resource_dump_context) \
1323 {&NOBUG_FLAG(flag), \
1324 NOBUG_RESOURCE_LOG_LEVEL, \
1325 NOBUG_LOCATION_ARGS}); \
1326 NOBUG_RESOURCE_UNLOCK)
1330 //index.resource_dumpall xref:NOBUG_RESOURCE_DUMPALL[NOBUG_RESOURCE_DUMPALL]:: dump the state of all resources
1331 //resourcemacros [[NOBUG_RESOURCE_DUMPALL]]
1332 //resourcemacros
1333 //resourcemacros .NOBUG_RESOURCE_DUMPALL
1334 //resourcemacros NOBUG_RESOURCE_DUMPALL(flag)
1335 //resourcemacros
1336 //resourcemacros Dump the state of all resources.
1337 //resourcemacros
1338 //resourcemacros `flag`::
1339 //resourcemacros Nobug flag for the log channel
1340 //resourcemacros
1342 #define NOBUG_RESOURCE_DUMPALL(flag) \
1343 do { NOBUG_RESOURCE_LOCK; \
1344 nobug_resource_dump_all (&(struct nobug_resource_dump_context) \
1345 {&NOBUG_FLAG(flag), \
1346 NOBUG_RESOURCE_LOG_LEVEL, \
1347 NOBUG_LOCATION_ARGS}); \
1348 NOBUG_RESOURCE_UNLOCK; } while (0)
1351 #define NOBUG_RESOURCE_DUMPALL_IF(when, flag) \
1352 NOBUG_WHEN(when, NOBUG_RESOURCE_LOCK; \
1353 nobug_resource_dump_all (&(struct nobug_resource_dump_context) \
1354 {&NOBUG_FLAG(flag), \
1355 NOBUG_RESOURCE_LOG_LEVEL, \
1356 NOBUG_LOCATION_ARGS}); \
1357 NOBUG_RESOURCE_UNLOCK)
1361 //index.resource_list xref:NOBUG_RESOURCE_LIST[NOBUG_RESOURCE_LIST]:: enumerate all registered resources
1362 //resourcemacros [[NOBUG_RESOURCE_LIST]]
1363 //resourcemacros
1364 //resourcemacros .NOBUG_RESOURCE_LIST
1365 //resourcemacros NOBUG_RESOURCE_LIST(flag)
1366 //resourcemacros
1367 //resourcemacros List all registered resources.
1368 //resourcemacros
1369 //resourcemacros `flag`::
1370 //resourcemacros Nobug flag for the log channel
1371 //resourcemacros
1373 #define NOBUG_RESOURCE_LIST(flag) \
1374 do { NOBUG_RESOURCE_LOCK; \
1375 nobug_resource_list (&(struct nobug_resource_dump_context) \
1376 {&NOBUG_FLAG(flag), \
1377 NOBUG_RESOURCE_LOG_LEVEL, \
1378 NOBUG_LOCATION_ARGS}); \
1379 NOBUG_RESOURCE_UNLOCK; } while (0)
1381 #define NOBUG_RESOURCE_LIST_IF(when, flag) \
1382 NOBUG_WHEN(when, NOBUG_RESOURCE_LOCK; \
1383 nobug_resource_list (&(struct nobug_resource_dump_context) \
1384 {&NOBUG_FLAG(flag), \
1385 NOBUG_RESOURCE_LOG_LEVEL, \
1386 NOBUG_LOCATION_ARGS}); \
1387 NOBUG_RESOURCE_UNLOCK)
1391 threading support
1393 #if NOBUG_USE_PTHREAD
1394 #define NOBUG_THREAD_ID_SET(name) nobug_thread_id_set(name)
1395 #define NOBUG_THREAD_ID_FMT(pre,post) pre "%s" post
1396 #define NOBUG_THREAD_ID_COMMA , NOBUG_THREAD_ID_GET
1397 #define NOBUG_THREAD_ID_GET nobug_thread_id_get()
1399 #else
1400 #define NOBUG_THREAD_ID_SET(name)
1401 #define NOBUG_THREAD_ID_FMT(pre,post) ""
1402 #define NOBUG_THREAD_ID_COMMA
1403 #define NOBUG_THREAD_ID_GET ""
1404 #endif
1408 Source location
1410 #define NOBUG_LOCATION_ARGS NOBUG_BASENAME(__FILE__), __LINE__, __func__
1411 #define NOBUG_LOCATION_INFO (NOBUG_LOCATION_ARGS)
1413 #define NOBUG_LOCATION_FILE(file, _1, _2) file
1414 #define NOBUG_LOCATION_LINE(_1, line, _2) line
1415 #define NOBUG_LOCATION_FUNC(_1, _2, func) func
1419 Debuggers
1422 #define NOBUG_DBG_NONE 0
1423 #define NOBUG_DBG_GDB 1
1424 #define NOBUG_DBG_VALGRIND 2
1426 #define NOBUG_ACTIVE_DBG \
1427 NOBUG_IF(NOBUG_USE_VALGRIND, (RUNNING_ON_VALGRIND?2:0)) \
1428 NOBUG_IFNOT(NOBUG_USE_VALGRIND, 0)
1431 //toolmacros PARA BACKTRACE; BACKTRACE; generate a backtrace
1432 //toolmacros BACKTRACE
1433 //toolmacros
1434 //toolmacros The backtrace macro logs a stacktrace using the NoBug facilities.
1435 //toolmacros This is automatically called when NoBug finds an error and is due
1436 //toolmacros to abort. But one might call it manually too.
1437 //toolmacros
1439 #define NOBUG_BACKTRACE \
1440 NOBUG_IF_ALPHA( \
1441 switch (NOBUG_ACTIVE_DBG) { \
1442 case NOBUG_DBG_VALGRIND: \
1443 NOBUG_BACKTRACE_VALGRIND; \
1444 break; \
1445 default: \
1446 NOBUG_BACKTRACE_GLIBC; \
1447 }) \
1448 NOBUG_IF_NOT_ALPHA (NOBUG_BACKTRACE_GLIBC)
1450 #define NOBUG_BACKTRACE_DBG \
1451 NOBUG_IF_NOT_RELEASE( \
1452 switch (NOBUG_ACTIVE_DBG) { \
1453 case NOBUG_DBG_VALGRIND: \
1454 NOBUG_BACKTRACE_VALGRIND; \
1455 break; \
1458 #define NOBUG_BACKTRACE_GDB fprintf(stderr, "UNIMPLEMENTED : GDB Backtraces\n")
1460 #define NOBUG_BACKTRACE_VALGRIND \
1461 NOBUG_IF(NOBUG_USE_VALGRIND, \
1462 VALGRIND_PRINTF_BACKTRACE("BACKTRACE: %s@%d %s", \
1463 NOBUG_LOCATION_ARGS))
1466 #ifndef NOBUG_BACKTRACE_DEPTH
1467 #define NOBUG_BACKTRACE_DEPTH 256
1468 #endif
1470 #define NOBUG_BACKTRACE_GLIBC \
1471 NOBUG_IF_NOT_RELEASE( \
1472 NOBUG_IF(NOBUG_USE_EXECINFO, do { \
1473 NOBUG_LOG_(&nobug_flag_NOBUG_ON, LOG_NOTICE, NOBUG_LOCATION_INFO, "BACKTRACE"); \
1474 nobug_backtrace_glibc (); \
1475 } while (0)))
1479 init and other function wrapers
1481 #define NOBUG_INIT nobug_init()
1482 #define NOBUG_BASENAME(name) (strrchr((name), '/')?strrchr((name), '/') + 1 : (name))
1483 #define NOBUG_ABORT abort()
1487 short macros without NOBUG_
1489 #ifndef NOBUG_DISABLE_SHORTNAMES
1490 #ifndef REQUIRE
1491 #define REQUIRE NOBUG_REQUIRE
1492 #endif
1493 #ifndef REQUIRE_DBG
1494 #define REQUIRE_DBG NOBUG_REQUIRE_DBG
1495 #endif
1496 #ifndef REQUIRE_IF
1497 #define REQUIRE_IF NOBUG_REQUIRE_IF
1498 #endif
1499 #ifndef REQUIRE_IF_DBG
1500 #define REQUIRE_IF_DBG NOBUG_REQUIRE_IF_DBG
1501 #endif
1502 #ifndef ENSURE
1503 #define ENSURE NOBUG_ENSURE
1504 #endif
1505 #ifndef ENSURE_DBG
1506 #define ENSURE_DBG NOBUG_ENSURE_DBG
1507 #endif
1508 #ifndef ENSURE_IF
1509 #define ENSURE_IF NOBUG_ENSURE_IF
1510 #endif
1511 #ifndef ENSURE_IF_DBG
1512 #define ENSURE_IF_DBG NOBUG_ENSURE_IF_DBG
1513 #endif
1514 #ifndef ASSERT
1515 #define ASSERT NOBUG_ASSERT
1516 #endif
1517 #ifndef ASSERT_DBG
1518 #define ASSERT_DBG NOBUG_ASSERT_DBG
1519 #endif
1520 #ifndef ASSERT_IF
1521 #define ASSERT_IF NOBUG_ASSERT_IF
1522 #endif
1523 #ifndef ASSERT_IF_DBG
1524 #define ASSERT_IF_DBG NOBUG_ASSERT_IF_DBG
1525 #endif
1526 #ifndef CHECK
1527 #define CHECK NOBUG_CHECK
1528 #endif
1529 #ifndef CHECK
1530 #define CHECK NOBUG_CHECK
1531 #endif
1532 #ifndef INVARIANT
1533 #define INVARIANT NOBUG_INVARIANT
1534 #endif
1535 #ifndef INVARIANT_DBG
1536 #define INVARIANT_DBG NOBUG_INVARIANT_DBG
1537 #endif
1538 #ifndef INVARIANT_IF
1539 #define INVARIANT_IF NOBUG_INVARIANT_IF
1540 #endif
1541 #ifndef INVARIANT_IF_DBG
1542 #define INVARIANT_IF_DBG NOBUG_INVARIANT_IF_DBG
1543 #endif
1544 #ifndef INVARIANT_ASSERT
1545 #define INVARIANT_ASSERT NOBUG_INVARIANT_ASSERT
1546 #endif
1547 #ifndef DUMP
1548 #define DUMP NOBUG_DUMP
1549 #endif
1550 #ifndef DUMP_DBG
1551 #define DUMP_DBG NOBUG_DUMP_DBG
1552 #endif
1553 #ifndef DUMP_IF
1554 #define DUMP_IF NOBUG_DUMP_IF
1555 #endif
1556 #ifndef DUMP_IF_DBG
1557 #define DUMP_IF_DBG NOBUG_DUMP_IF_DBG
1558 #endif
1559 #ifndef DUMP_LOG
1560 #define DUMP_LOG NOBUG_DUMP_LOG
1561 #endif
1562 #ifndef DUMP_LOG_DBG
1563 #define DUMP_LOG_DBG NOBUG_DUMP_LOG_DBG
1564 #endif
1565 #ifndef DUMP_LOG_IF
1566 #define DUMP_LOG_IF NOBUG_DUMP_LOG_IF
1567 #endif
1568 #ifndef DUMP_LOG_IF_DBG
1569 #define DUMP_LOG_IF_DBG NOBUG_DUMP_LOG_IF_DBG
1570 #endif
1571 #ifndef LOG
1572 #define LOG NOBUG_LOG
1573 #endif
1574 #ifndef LOG_DBG
1575 #define LOG_DBG NOBUG_LOG_DBG
1576 #endif
1577 #ifndef LOG_IF
1578 #define LOG_IF NOBUG_LOG_IF
1579 #endif
1580 #ifndef LOG_IF_DBG
1581 #define LOG_IF_DBG NOBUG_LOG_IF_DBG
1582 #endif
1583 #ifndef ECHO
1584 #define ECHO NOBUG_ECHO
1585 #endif
1586 #ifndef ALERT
1587 #define ALERT NOBUG_ALERT
1588 #endif
1589 #ifndef ALERT_DBG
1590 #define ALERT_DBG NOBUG_ALERT_DBG
1591 #endif
1592 #ifndef ALERT_IF
1593 #define ALERT_IF NOBUG_ALERT_IF
1594 #endif
1595 #ifndef ALERT_IF_DBG
1596 #define ALERT_IF_DBG NOBUG_ALERT_IF_DBG
1597 #endif
1598 #ifndef CRITICAL
1599 #define CRITICAL NOBUG_CRITICAL
1600 #endif
1601 #ifndef CRITICAL_DBG
1602 #define CRITICAL_DBG NOBUG_CRITICAL_DBG
1603 #endif
1604 #ifndef CRITICAL_IF
1605 #define CRITICAL_IF NOBUG_CRITICAL_IF
1606 #endif
1607 #ifndef CRITICAL_IF_DBG
1608 #define CRITICAL_IF_DBG NOBUG_CRITICAL_IF_DBG
1609 #endif
1610 #ifndef ERROR
1611 #define ERROR NOBUG_ERROR
1612 #endif
1613 #ifndef ERROR_DBG
1614 #define ERROR_DBG NOBUG_ERROR_DBG
1615 #endif
1616 #ifndef ERROR_IF
1617 #define ERROR_IF NOBUG_ERROR_IF
1618 #endif
1619 #ifndef ERROR_IF_DBG
1620 #define ERROR_IF_DBG NOBUG_ERROR_IF_DBG
1621 #endif
1622 #ifndef WARN
1623 #define WARN NOBUG_WARN
1624 #endif
1625 #ifndef WARN_DBG
1626 #define WARN_DBG NOBUG_WARN_DBG
1627 #endif
1628 #ifndef WARN_IF
1629 #define WARN_IF NOBUG_WARN_IF
1630 #endif
1631 #ifndef WARN_IF_DBG
1632 #define WARN_IF_DBG NOBUG_WARN_IF_DBG
1633 #endif
1634 #ifndef INFO
1635 #define INFO NOBUG_INFO
1636 #endif
1637 #ifndef INFO_DBG
1638 #define INFO_DBG NOBUG_INFO_DBG
1639 #endif
1640 #ifndef INFO_IF
1641 #define INFO_IF NOBUG_INFO_IF
1642 #endif
1643 #ifndef INFO_IF_DBG
1644 #define INFO_IF_DBG NOBUG_INFO_IF_DBG
1645 #endif
1646 #ifndef NOTICE
1647 #define NOTICE NOBUG_NOTICE
1648 #endif
1649 #ifndef NOTICE_DBG
1650 #define NOTICE_DBG NOBUG_NOTICE_DBG
1651 #endif
1652 #ifndef NOTICE_IF
1653 #define NOTICE_IF NOBUG_NOTICE_IF
1654 #endif
1655 #ifndef NOTICE_IF_DBG
1656 #define NOTICE_IF_DBG NOBUG_NOTICE_IF_DBG
1657 #endif
1658 #ifndef TRACE
1659 #define TRACE NOBUG_TRACE
1660 #endif
1661 #ifndef TRACE_DBG
1662 #define TRACE_DBG NOBUG_TRACE_DBG
1663 #endif
1664 #ifndef TRACE_IF
1665 #define TRACE_IF NOBUG_TRACE_IF
1666 #endif
1667 #ifndef TRACE_IF_DBG
1668 #define TRACE_IF_DBG NOBUG_TRACE_IF_DBG
1669 #endif
1670 #ifndef BACKTRACE
1671 #define BACKTRACE NOBUG_BACKTRACE
1672 #endif
1673 #ifndef BACKTRACE_DBG
1674 #define BACKTRACE_DBG NOBUG_BACKTRACE_DBG
1675 #endif
1676 #ifndef DEPRECATED
1677 #define DEPRECATED NOBUG_DEPRECATED
1678 #endif
1679 #ifndef UNIMPLEMENTED
1680 #define UNIMPLEMENTED NOBUG_UNIMPLEMENTED
1681 #endif
1682 #ifndef FIXME
1683 #define FIXME NOBUG_FIXME
1684 #endif
1685 #ifndef TODO
1686 #define TODO NOBUG_TODO
1687 #endif
1688 #ifndef PLANNED
1689 #define PLANNED NOBUG_PLANNED
1690 #endif
1691 #ifndef NOTREACHED
1692 #define NOTREACHED NOBUG_NOTREACHED
1693 #endif
1694 #ifndef INJECT_GOODBAD
1695 #define INJECT_GOODBAD NOBUG_INJECT_GOODBAD
1696 #endif
1697 #ifndef INJECT_FAULT
1698 #define INJECT_FAULT NOBUG_INJECT_FAULT
1699 #endif
1700 #ifndef CLEANUP
1701 #define CLEANUP NOBUG_CLEANUP
1702 #endif
1703 #ifndef CHECKED
1704 #define CHECKED NOBUG_CHECKED
1705 #endif
1706 #ifndef UNCHECKED
1707 #define UNCHECKED NOBUG_UNCHECKED
1708 #endif
1709 #ifndef RESOURCE_ANNOUNCE
1710 #define RESOURCE_ANNOUNCE NOBUG_RESOURCE_ANNOUNCE
1711 #endif
1712 #ifndef RESOURCE_FORGET
1713 #define RESOURCE_FORGET NOBUG_RESOURCE_FORGET
1714 #endif
1715 #ifndef RESOURCE_ENTER
1716 #define RESOURCE_ENTER NOBUG_RESOURCE_ENTER
1717 #endif
1718 #ifndef RESOURCE_STATE
1719 #define RESOURCE_STATE NOBUG_RESOURCE_STATE
1720 #endif
1721 #ifndef RESOURCE_LEAVE
1722 #define RESOURCE_LEAVE NOBUG_RESOURCE_LEAVE
1723 #endif
1724 #ifndef RESOURCE_LEAVE_LOOKUP
1725 #define RESOURCE_LEAVE_LOOKUP NOBUG_RESOURCE_LEAVE_LOOKUP
1726 #endif
1727 #ifndef RESOURCE_HANDLE
1728 #define RESOURCE_HANDLE NOBUG_RESOURCE_HANDLE
1729 #endif
1730 #ifndef RESOURCE_HANDLE_INIT
1731 #define RESOURCE_HANDLE_INIT NOBUG_RESOURCE_HANDLE_INIT
1732 #endif
1733 #ifndef RESOURCE_DUMP
1734 #define RESOURCE_DUMP NOBUG_RESOURCE_DUMP
1735 #endif
1736 #ifndef RESOURCE_DUMP_IF
1737 #define RESOURCE_DUMP_IF NOBUG_RESOURCE_DUMP_IF
1738 #endif
1739 #ifndef RESOURCE_DUMPALL
1740 #define RESOURCE_DUMPALL NOBUG_RESOURCE_DUMPALL
1741 #endif
1742 #ifndef RESOURCE_DUMPALL_IF
1743 #define RESOURCE_DUMPALL_IF NOBUG_RESOURCE_DUMPALL_IF
1744 #endif
1745 #ifndef RESOURCE_LIST
1746 #define RESOURCE_LIST NOBUG_RESOURCE_LIST
1747 #endif
1748 #ifndef RESOURCE_LIST_IF
1749 #define RESOURCE_LIST_IF NOBUG_RESOURCE_LIST_IF
1750 #endif
1751 #endif /* NOBUG_DISABLE_SHORTNAMES */
1755 Tool macros
1757 #ifdef __GNUC__
1758 #define NOBUG_CLEANUP(fn) NOBUG_IF_ALPHA(__attribute__((cleanup(fn))))
1759 #else
1760 #define NOBUG_CLEANUP(fn)
1761 #endif
1764 //toolmacros PARA NOBUG_ALPHA_COMMA; NOBUG_ALPHA_COMMA; append something after a comma in *ALPHA* builds
1765 //toolmacros NOBUG_ALPHA_COMMA(something)
1766 //toolmacros NOBUG_ALPHA_COMMA_NULL
1767 //toolmacros
1768 //toolmacros Sometimes it is useful to have initializer code only in *ALPHA* builds, for example when you
1769 //toolmacros conditionally include resource handles only in *ALPHA* versions. An initializer can then
1770 //toolmacros use this macros to append a comman and something else only in *ALPHA* builds as in:
1771 //toolmacros struct foo = {"foo", "bar" NOBUG_ALPHA_COMMA_NULL };
1772 //toolmacros
1774 #define NOBUG_COMMA ,
1775 #define NOBUG_ALPHA_COMMA(something) NOBUG_IF_ALPHA(NOBUG_COMMA something)
1776 #define NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA(NULL)
1778 #define NOBUG_ONCE(code) \
1779 do { \
1780 static volatile int NOBUG_CAT(nobug_once_,__LINE__) = 0; \
1781 if (NOBUG_EXPECT_FALSE(!NOBUG_CAT(nobug_once_,__LINE__))) \
1783 NOBUG_CAT(nobug_once_,__LINE__) = 1; \
1784 code; \
1786 } while (0)
1788 #if __GNUC__
1789 #define NOBUG_EXPECT_FALSE(x) __builtin_expect(!!(x),0)
1790 #else
1791 #define NOBUG_EXPECT_FALSE(x) x
1792 #endif
1794 #define NOBUG_WHEN(when, ...) \
1795 do{ if (NOBUG_EXPECT_FALSE(when)){ __VA_ARGS__;}} while(0)
1798 //toolmacros PARA NOBUG_IF_*; NOBUG_IF; include code conditionally on build level
1799 //toolmacros NOBUG_IF_ALPHA(...)
1800 //toolmacros NOBUG_IF_NOT_ALPHA(...)
1801 //toolmacros NOBUG_IF_BETA(...)
1802 //toolmacros NOBUG_IF_NOT_BETA(...)
1803 //toolmacros NOBUG_IF_RELEASE(...)
1804 //toolmacros NOBUG_IF_NOT_RELEASE(...)
1805 //toolmacros
1806 //toolmacros This macros allow one to conditionally include the code in '(...)' only if the
1807 //toolmacros criteria on the build level is met. If not, nothing gets substituted. Mostly used
1808 //toolmacros internally, but can also be used for custom things.
1809 //toolmacros
1811 #define NOBUG_IF_ALPHA(...) \
1812 NOBUG_IF(NOBUG_MODE_ALPHA, __VA_ARGS__) \
1814 #define NOBUG_IF_NOT_ALPHA(...) \
1815 NOBUG_IFNOT(NOBUG_MODE_ALPHA, __VA_ARGS__) \
1817 #define NOBUG_IF_BETA(...) \
1818 NOBUG_IF(NOBUG_MODE_BETA, __VA_ARGS__) \
1820 #define NOBUG_IF_NOT_BETA(...) \
1821 NOBUG_IFNOT(NOBUG_MODE_BETA, __VA_ARGS__) \
1823 #define NOBUG_IF_RELEASE(...) \
1824 NOBUG_IF(NOBUG_MODE_RELEASE, __VA_ARGS__) \
1826 #define NOBUG_IF_NOT_RELEASE(...) \
1827 NOBUG_IFNOT(NOBUG_MODE_RELEASE, __VA_ARGS__) \
1830 preprocessor hacks/metaprogramming
1833 #define NOBUG_IF(bool, ...) NOBUG_CAT(NOBUG_IF_,bool)(__VA_ARGS__)
1834 #define NOBUG_IF_1(...) __VA_ARGS__
1835 #define NOBUG_IF_0(...)
1837 #define NOBUG_IFNOT(bool, ...) NOBUG_CAT(NOBUG_IF_, NOBUG_NOT(bool))(__VA_ARGS__)
1839 #define NOBUG_NOT(bool) NOBUG_CAT(NOBUG_NOT_, bool)
1840 #define NOBUG_NOT_1 0
1841 #define NOBUG_NOT_0 1
1843 #define NOBUG_AND(a,b) NOBUG_CAT3(NOBUG_AND_, a, b)
1844 #define NOBUG_AND_00 0
1845 #define NOBUG_AND_01 0
1846 #define NOBUG_AND_10 0
1847 #define NOBUG_AND_11 1
1849 #define NOBUG_OR(a,b) NOBUG_CAT3(NOBUG_OR_, a, b)
1850 #define NOBUG_OR_00 0
1851 #define NOBUG_OR_01 1
1852 #define NOBUG_OR_10 1
1853 #define NOBUG_OR_11 1
1855 #define NOBUG_XOR(a,b) NOBUG_CAT( NOBUG_XOR_, NOBUG_CAT(a,b))
1856 #define NOBUG_XOR_00 0
1857 #define NOBUG_XOR_01 1
1858 #define NOBUG_XOR_10 1
1859 #define NOBUG_XOR_11 0
1861 #define NOBUG_CAT(a,b) NOBUG_CAT_(a,b)
1862 #define NOBUG_CAT_(a,b) a##b
1864 #define NOBUG_CAT3(a,b,c) NOBUG_CAT3_(a,b,c)
1865 #define NOBUG_CAT3_(a,b,c) a##b##c
1867 #define NOBUG_HEAD(head, ...) head
1868 #define NOBUG_TAIL(_, ...) , ## __VA_ARGS__
1870 #define NOBUG_STRINGIZE(s) NOBUG_STRINGIZE_(s)
1871 #define NOBUG_STRINGIZE_(s) #s
1875 LIBNOBUG DECLARATIONS
1877 #ifdef __cplusplus
1878 extern "C" {
1879 #endif
1882 envvar control
1884 enum nobug_log_targets
1886 NOBUG_TARGET_RINGBUFFER,
1887 NOBUG_TARGET_CONSOLE,
1888 NOBUG_TARGET_FILE,
1889 NOBUG_TARGET_SYSLOG,
1890 NOBUG_TARGET_APPLICATION
1893 struct nobug_flag
1895 const char* name;
1896 struct nobug_flag* parent;
1897 volatile int initialized;
1898 int limits[5];
1899 struct nobug_ringbuffer* ringbuffer_target;
1900 FILE* console_target;
1901 FILE* file_target;
1905 nobug_env_parse_flag (const char* env, struct nobug_flag* flag, int default_target, int default_limit);
1908 nobug_env_init_flag (struct nobug_flag* flag, int default_target, int default_limit);
1912 ringbuffer
1914 struct nobug_ringbuffer
1916 char* pos;
1917 char* start;
1918 size_t size;
1919 size_t maxmsg;
1920 char name[256];
1923 enum nobug_ringbuffer_flags
1925 NOBUG_RINGBUFFER_DEFAULT, /* Default is to overwrite file and delete it on nobug_ringbuffer_destroy */
1926 NOBUG_RINGBUFFER_APPEND = 1, /* use existing backing file, append if possible */
1927 NOBUG_RINGBUFFER_TEMP = 2, /* unlink file instantly */
1928 NOBUG_RINGBUFFER_KEEP = 4 /* dont unlink the file at destroy */
1932 Note: some flags conflict (TEMP with KEEP) nobug_ringbuffer will not error on these but continue gracefully
1933 with sane (but undefined) semantics.
1935 struct nobug_ringbuffer*
1936 nobug_ringbuffer_init (struct nobug_ringbuffer* self, size_t size,
1937 const char * name, int flags);
1939 struct nobug_ringbuffer*
1940 nobug_ringbuffer_new (size_t size, const char * name, int flags);
1942 struct nobug_ringbuffer*
1943 nobug_ringbuffer_destroy (struct nobug_ringbuffer* self);
1945 void
1946 nobug_ringbuffer_delete (struct nobug_ringbuffer* self);
1949 nobug_ringbuffer_vprintf (struct nobug_ringbuffer* self, const char* fmt, va_list ap);
1952 nobug_ringbuffer_printf (struct nobug_ringbuffer* self, const char* fmt, ...);
1954 char*
1955 nobug_ringbuffer_prev (struct nobug_ringbuffer* self, char* pos);
1957 char*
1958 nobug_ringbuffer_next (struct nobug_ringbuffer* self, char* pos);
1961 nobug_ringbuffer_save (struct nobug_ringbuffer* self, FILE* out);
1964 nobug_ringbuffer_load (struct nobug_ringbuffer* self, FILE* in);
1966 char*
1967 nobug_ringbuffer_pos (struct nobug_ringbuffer* self);
1969 void
1970 nobug_ringbuffer_pop (struct nobug_ringbuffer* self);
1974 multithreading extras
1977 #ifndef LLIST_DEFINED
1978 #define LLIST_DEFINED
1979 struct llist_struct
1981 struct llist_struct *next;
1982 struct llist_struct *prev;
1984 #endif
1986 #if NOBUG_USE_PTHREAD
1988 struct nobug_tls_data
1990 const char * thread_id;
1991 struct llist_struct res_stack; /* resources of this thread */
1994 extern pthread_key_t nobug_tls_key;
1996 const char*
1997 nobug_thread_id_set (const char* name);
1999 struct nobug_tls_data*
2000 nobug_thread_set (const char* name);
2002 struct nobug_tls_data*
2003 nobug_thread_get (void);
2005 const char*
2006 nobug_thread_id_get (void);
2008 extern pthread_mutex_t nobug_logging_mutex;
2009 extern pthread_mutex_t nobug_resource_mutex;
2010 #endif
2014 resource registry
2016 #if NOBUG_USE_PTHREAD
2017 #define NOBUG_RESOURCE_LOCK pthread_mutex_lock (&nobug_resource_mutex)
2018 #define NOBUG_RESOURCE_UNLOCK pthread_mutex_unlock (&nobug_resource_mutex)
2020 Note: errors are all fatal, we dont unlock the mutex when returning an error,
2021 this should be handled better in future but does not hurt
2023 #else
2024 #define NOBUG_RESOURCE_LOCK
2025 #define NOBUG_RESOURCE_UNLOCK
2026 #endif
2029 enum nobug_resource_state
2031 NOBUG_RESOURCE_INVALID,
2032 NOBUG_RESOURCE_WAITING,
2033 NOBUG_RESOURCE_EXCLUSIVE,
2034 NOBUG_RESOURCE_RECURSIVE,
2035 NOBUG_RESOURCE_SHARED
2039 struct nobug_resource_header
2041 struct llist_struct node; /* link node for resource registry or users */
2042 const char* name; /* name */
2043 const char* extra; /* extra information, file/line usually */
2046 struct nobug_resource_node;
2047 struct nobug_resource_user;
2049 struct nobug_resource_record
2051 struct nobug_resource_header hdr;
2052 struct llist_struct users; /* list of users of this resource */
2053 const void* object_id; /* unique identifer, usually a this pointer or similar */
2054 const char* type; /* type */
2056 #if NOBUG_USE_PTHREAD
2057 struct llist_struct nodes;
2058 #endif
2062 struct nobug_resource_node
2064 struct llist_struct node; /* all nodes for one resource */
2066 struct nobug_resource_record* resource; /* backpointer */
2067 struct nobug_resource_node* parent; /* upwards the tree */
2069 struct llist_struct childs; /* down the tree, all nodes pointing to here (TODO make this a slist) */
2070 struct llist_struct cldnode; /* node to accumulate all childrens of a parent (TODO slist) */
2074 struct nobug_resource_user
2076 struct nobug_resource_header hdr;
2078 struct nobug_resource_node* current; /* this resource */
2079 enum nobug_resource_state state; /* state */
2082 #if NOBUG_USE_PTHREAD
2083 struct nobug_tls_data* thread; /* pointer to this theads id */
2084 struct llist_struct res_stack; /* resources of this thread */
2085 #endif
2089 extern const char* nobug_resource_error;
2091 extern const char* nobug_resource_states[];
2094 void
2095 nobug_resource_init (void);
2097 void
2098 nobug_resource_destroy (void);
2101 struct nobug_resource_record*
2102 nobug_resource_announce (const char* type, const char* name, const void* object_id, const char* extra);
2105 nobug_resource_forget (struct nobug_resource_record* node);
2107 struct nobug_resource_user*
2108 nobug_resource_enter (struct nobug_resource_record* resource,
2109 const char* name,
2110 enum nobug_resource_state state,
2111 const char* extra);
2114 nobug_resource_state (struct nobug_resource_user* resource,
2115 enum nobug_resource_state state);
2118 nobug_resource_leave (struct nobug_resource_user* handle);
2121 struct nobug_resource_dump_context
2123 struct nobug_flag* flag;
2124 int level;
2125 const char* file;
2126 int line;
2127 const char* func;
2130 void
2131 nobug_resource_dump (struct nobug_resource_record* resource, struct nobug_resource_dump_context* context);
2133 void
2134 nobug_resource_dump_all (struct nobug_resource_dump_context* context);
2136 void
2137 nobug_resource_list (struct nobug_resource_dump_context* context);
2139 #if NOBUG_USE_PTHREAD
2140 void
2141 nobug_resource_dump_thread (struct nobug_resource_dump_context* context);
2142 #endif
2145 global config, data and defaults
2147 extern const char* nobug_resource_acquired;
2149 void nobug_init (void);
2151 void
2152 nobug_backtrace_glibc (void);
2154 void
2155 nobug_log (struct nobug_flag* flag, int lvl, const char* fmt, ...);
2157 typedef void (*nobug_application_cb)(struct nobug_flag* flag, int priority, const char *log, void* data);
2159 extern struct nobug_ringbuffer nobug_default_ringbuffer;
2160 extern FILE* nobug_default_file;
2161 extern struct nobug_flag nobug_flag_NOBUG_ON;
2162 extern struct nobug_flag nobug_flag_NOBUG_ANN;
2163 extern struct nobug_flag nobug_flag_nobug;
2164 extern unsigned long long nobug_counter;
2165 extern nobug_application_cb nobug_callback;
2166 extern void* nobug_callback_data;
2168 #ifdef __cplusplus
2169 } /* extern "C" */
2170 #endif
2172 #ifndef NOBUG_LIBNOBUG_C
2175 tag this translation unit as unchecked in ALPHA and BETA builds
2177 NOBUG_IF_NOT_RELEASE(NOBUG_UNCHECKED);
2179 #endif /* NOBUG_LIBNOBUG_C */
2180 #endif