minor documentation fixes and cosmetics
[nobug.git] / src / nobug.h
blob30ab6f087bc1fa23062ff42aac967a1edc821710
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_H) && !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
101 #if NOBUG_MODE_RELEASE==0
103 //index.assert xref:assert[assert]:: C standard assertion
104 //assertions [[assert]]
105 //assertions .assert
106 //assertions assert(expr)
107 //assertions
108 //assertions NoBug overrides the standard assert macro in *ALPHA* and *BETA* builds.
109 //assertions This is just a compatibility feature, its use is not suggested.
110 //assertions
112 #undef assert
113 #define assert(expr) NOBUG_ASSERT(expr)
114 #endif
118 ASSERTIONS
122 //index.require xref:REQUIRE[REQUIRE]:: preconditions (incoming parameters)
123 //assertions [[REQUIRE]]
124 //assertions .REQUIRE
125 //assertions REQUIRE(expr, ...)
126 //assertions REQUIRE_DBG(expr, ...)
127 //assertions REQUIRE_IF(when, expr, ...)
128 //assertions REQUIRE_IF_DBG(when, expr, ...)
129 //assertions
130 //assertions Precondition (input) check. Use these macros to validate input a
131 //assertions function receives. The checks are enabled in *ALPHA* and *BETA* builds and
132 //assertions optimized out in *RELEASE* builds.
133 //assertions
135 #define NOBUG_REQUIRE(expr, ...) \
136 NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_(expr, "PRECONDITION", \
137 NOBUG_LOCATION_INFO, ## __VA_ARGS__))
140 #define NOBUG_REQUIRE_DBG(expr, ...) \
141 NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_DBG_(expr, "PRECONDITION", \
142 NOBUG_LOCATION_INFO, ## __VA_ARGS__))
145 #define NOBUG_REQUIRE_IF(when, expr, ...) \
146 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_REQUIRE(expr, ## __VA_ARGS__)))
148 #define NOBUG_REQUIRE_IF_DBG(when, expr, ...) \
149 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_REQUIRE_DBG(expr, ## __VA_ARGS__)))
153 //index.ensure xref:ENSURE[ENSURE]:: postconditions (computation outcomes)
154 //assertions [[ENSURE]]
155 //assertions .ENSURE
156 //assertions ENSURE(expr, ...)
157 //assertions ENSURE_DBG(expr, ...)
158 //assertions ENSURE_IF(when, expr, ...)
159 //assertions ENSURE_IF_DBG(when, expr, ...)
160 //assertions
161 //assertions Postcondition (progress/output) check. Use these macros to validate the
162 //assertions data a function produces (example: return value). The checks enabled
163 //assertions unconditionally in *ALPHA* builds and optimized out in *BETA* builds for
164 //assertions scopes which are tagged as `CHECKED`. In *RELEASE* builds this checks are
165 //assertions always optimized out, but scopes tagged as `UNCHECKED` are not permitted.
166 //assertions
168 #define NOBUG_ENSURE(expr, ...) \
169 NOBUG_IF_ALPHA (NOBUG_ASSERT_(expr, "POSTCONDITION", \
170 NOBUG_LOCATION_INFO, ## __VA_ARGS__)) \
171 NOBUG_IF_BETA ( \
172 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
173 NOBUG_ASSERT_(expr, "POSTCONDITION", \
174 NOBUG_LOCATION_INFO, ## __VA_ARGS__))\
177 #define NOBUG_ENSURE_DBG(expr, ...) \
178 NOBUG_IF_ALPHA (NOBUG_ASSERT_DBG_ (expr, "POSTCONDITION", \
179 NOBUG_LOCATION_INFO, ## __VA_ARGS__)) \
180 NOBUG_IF_BETA ( \
181 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
182 NOBUG_ASSERT_DBG_(expr, "POSTCONDITION", \
183 NOBUG_LOCATION_INFO, ## __VA_ARGS__)) \
187 #define NOBUG_ENSURE_IF(when, expr, ...) \
188 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ENSURE(expr, ## __VA_ARGS__)))
190 #define NOBUG_ENSURE_IF_DBG(when, expr, ...) \
191 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ENSURE_DBG(expr, ## __VA_ARGS__)))
195 generic assertion
197 //index.assert xref:ASSERT[ASSERT]:: generic assertion
198 //assertions [[ASSERT]]
199 //assertions .ASSERT
200 //assertions ASSERT(expr, ...)
201 //assertions ASSERT_DBG(expr, ...)
202 //assertions ASSERT_IF(when, expr, ...)
203 //assertions ASSERT_IF_DBG(when, expr, ...)
204 //assertions
205 //assertions Generic check. Use these macros when you want to validate something
206 //assertions which doesn't fall into one of the above categories. A example is when
207 //assertions a library function can return a unexpected result (scanf with syntax
208 //assertions error in the formatstring, when a constant/literal formatstring is
209 //assertions expected). The checks are enabled in *ALPHA* and *BETA* builds and
210 //assertions optimized out in *RELEASE* builds.
211 //assertions
213 #define NOBUG_ASSERT(expr, ...) \
214 NOBUG_IF_NOT_RELEASE( \
215 NOBUG_ASSERT_(expr, "ASSERTION", \
216 NOBUG_LOCATION_INFO, ## __VA_ARGS__) \
219 #define NOBUG_ASSERT_DBG(expr, ...) \
220 NOBUG_IF_NOT_RELEASE( \
221 NOBUG_ASSERT_DBG_(expr, "ASSERTION", \
222 NOBUG_LOCATION_INFO, ## __VA_ARGS__) \
225 #define NOBUG_ASSERT_IF(when, expr, ...) \
226 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ASSERT(expr, ## __VA_ARGS__)))
228 #define NOBUG_ASSERT_IF_DBG(when, expr, ...) \
229 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ASSERT_DBG(expr, ## __VA_ARGS__)))
234 //index.check xref:CHECK[CHECK]:: assertion for testsuites
235 //assertions [[CHECK]]
236 //assertions .CHECK
237 //assertions CHECK(expr, ...)
238 //assertions CHECK_IF(when, expr, ...)
239 //assertions
240 //assertions This assertion is never optimized out. Its main purpose is for implementing
241 //assertions testsuites where one want to assert tests independent of the build level
242 //assertions
244 #define NOBUG_CHECK(expr, ...) \
245 NOBUG_ASSERT_(expr, "CHECK", NOBUG_LOCATION_INFO, ## __VA_ARGS__)
247 #define NOBUG_CHECK_IF(when, expr, ...) \
248 NOBUG_WHEN(when, NOBUG_CHECK(expr, ## __VA_ARGS__))
253 low level assert
255 #define NOBUG_ASSERT_(expr, what, location, ...) \
256 NOBUG_WHEN (!(expr), \
257 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
258 location, what, "(%s) " \
259 NOBUG_HEAD(__VA_ARGS__), \
260 #expr NOBUG_TAIL(__VA_ARGS__)); \
261 NOBUG_BACKTRACE; \
262 NOBUG_ABORT \
265 #define NOBUG_ASSERT_DBG_(expr, what, location, ...) \
266 NOBUG_WHEN (NOBUG_ACTIVE_DBG && !(expr), \
267 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
268 location, what, "(%s) " \
269 NOBUG_HEAD(__VA_ARGS__), \
270 #expr NOBUG_TAIL(__VA_ARGS__)); \
271 NOBUG_BACKTRACE; \
272 NOBUG_ABORT \
275 #define NOBUG_ASSERTN_(expr, what, location, ...) \
276 NOBUG_WHEN (!(expr), \
277 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
278 location, what, \
279 ## __VA_ARGS__); \
280 NOBUG_BACKTRACE; \
281 NOBUG_ABORT \
286 //index.invariant xref:INVARIANT[INVARIANT]:: validate the state
287 //assertions [[INVARIANT]]
288 //assertions .INVARIANT
289 //assertions INVARIANT(type, pointer, depth)
290 //assertions INVARIANT_DBG(type, pointer, depth)
291 //assertions INVARIANT_IF(when,type, pointer, depth)
292 //assertions INVARIANT_IF_DBG(when, type, pointer, depth)
293 //assertions
294 //assertions Checking invariants. You can provide more complex checking functions
295 //assertions which test the validity of datastructures. Invariants are only enabled
296 //assertions in *ALPHA* builds for scopes which are not tagged as `CHECKED` and
297 //assertions otherwise optimized out.
298 //assertions
299 //assertions TODO: describe how to create invariant checks
300 //assertions
302 #define NOBUG_INVARIANT(type, pointer, depth) \
303 NOBUG_IF_ALPHA( \
304 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
305 NOBUG_CAT(type,_invariant)(pointer, depth, \
306 NOBUG_LOCATION_ARGS) \
310 #define NOBUG_INVARIANT_DBG(type, pointer, ...) \
311 NOBUG_IF_ALPHA( \
312 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED && NOBUG_ACTIVE_DBG, \
313 NOBUG_CAT(type,_invariant)(pointer, depth, \
314 NOBUG_LOCATION_ARGS) \
318 #define NOBUG_INVARIANT_IF(when, type, pointer, ...) \
319 NOBUG_IF_ALPHA (NOBUG_WHEN (when, \
320 NOBUG_INVARIANT(type, pointer, ## __VA_ARGS__)) \
323 #define NOBUG_INVARIANT_IF_DBG(when, type, pointer, ...) \
324 NOBUG_IF_ALPHA (NOBUG_WHEN (when, \
325 NOBUG_INVARIANT_DBG(type, pointer, ## __VA_ARGS__))\
328 #define NOBUG_INVARIANT_ASSERT(expr, ...) \
329 NOBUG_ASSERT_(expr, "INVARIANT", (file, line, func), ## __VA_ARGS__)
333 checked/unchecked tagged scopes
335 #define NOBUG_SCOPE_UNCHECKED NOBUG_CHECKED_VALUE == 0
337 #define NOBUG_CHECKED NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=1})
339 #define NOBUG_UNCHECKED \
340 NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=0}) \
341 NOBUG_IF_RELEASE(NOBUG_UNCHECKED_NOT_ALLOWED_IN_RELEASE_BUILD)
346 dumping datastructures
348 /*TODO dump-level for flags instead limits[0]*/
350 //index.dump xref:DUMP[DUMP]:: dumping datastructures
351 //dumpmacros [[DUMP]]
352 //dumpmacros * DUMP(flag, type, pointer, depth)
353 //dumpmacros + Dump a datastructure
354 //dumpmacros DUMP_IF(expr, flag, type, pointer, depth)
355 //dumpmacros + Dump datastructure if expr is true
356 //dumpmacros
357 //dumpmacros This macros call a datastructure dump of the object (`pointer`) in question.
358 //dumpmacros `DUMP_IF` is the only enabled dumping macro for the RELEASE build level.
359 //dumpmacros
361 #define NOBUG_DUMP(flag, type, pointer, depth) \
362 NOBUG_IF_NOT_RELEASE( \
363 NOBUG_WHEN (NOBUG_DUMP_LEVEL <= nobug_flag_##flag.limits[0], \
364 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
365 NOBUG_LOCATION_ARGS) \
369 #define NOBUG_DUMP_DBG(flag, type, pointer, depth) \
370 NOBUG_IF_NOT_RELEASE( \
371 NOBUG_WHEN (NOBUG_ACTIVE_DBG && NOBUG_DUMP_LEVEL <= nobug_flag_##flag.limits[0], \
372 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
373 NOBUG_LOCATION_ARGS) \
377 #define NOBUG_DUMP_IF(when, flag, type, pointer, depth) \
378 NOBUG_WHEN (when && NOBUG_DUMP_LEVEL <= nobug_flag_##flag.limits[0], \
379 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
380 NOBUG_LOCATION_ARGS) \
383 #define NOBUG_DUMP_IF_DBG(when, flag, type, pointer, depth) \
384 NOBUG_IF_NOT_RELEASE( \
385 NOBUG_WHEN (NOBUG_ACTIVE_DBG && when && NOBUG_DUMP_LEVEL <= nobug_flag_##flag.limits[0],\
386 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, \
387 NOBUG_LOCATION_ARGS) \
393 //index.dump_log xref:DUMP_LOG[DUMP_LOG]:: Logging functions for dumping
394 //dumpmacros [[DUMP_LOG]]
395 //dumpmacros .DUMP_LOG
396 //dumpmacros DUMP_LOG(fmt, ...)
397 //dumpmacros DUMP_LOG_DBG(fmt, ...)
398 //dumpmacros DUMP_LOG_IF(when, fmt, ...)
399 //dumpmacros DUMP_LOG_IF_DBG(when, fmt, ...)
400 //dumpmacros
401 //dumpmacros Any output from `DUMP` handlers should be done by these macros.
402 //dumpmacros
403 //dumpmacros Dumping is by default done on level `LOG_DEBUG`, this can be overridden by
404 //dumpmacros defining `NOBUG_DUMP_LEVEL` to some other level.
405 //dumpmacros
407 #define NOBUG_DUMP_LOG(fmt, ...) \
408 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
409 (file, line, func), "DUMP", \
410 fmt, ## __VA_ARGS__)
413 #define NOBUG_DUMP_LOG_DBG(fmt, ...) \
414 NOBUG_WHEN (NOBUG_ACTIVE_DBG, \
415 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
416 (file, line, func), "DUMP", \
417 fmt, ## __VA_ARGS__) \
420 #define NOBUG_DUMP_LOG_IF(expr, fmt, ...) \
421 NOBUG_WHEN (expr, \
422 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
423 (file, line, func), "DUMP", \
424 fmt, ## __VA_ARGS__) \
427 #define NOBUG_DUMP_LOG_IF_DBG(expr, fmt, ...) \
428 NOBUG_WHEN (NOBUG_ACTIVE_DBG && expr, \
429 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
430 (file, line, func), "DUMP", \
431 fmt, ## __VA_ARGS__) \
435 #ifndef NOBUG_DUMP_LEVEL
436 #define NOBUG_DUMP_LEVEL LOG_DEBUG
437 #endif
440 Logging
444 //index.echo xref:ECHO[ECHO]:: logging for tests
445 //logmacros [[ECHO]]
446 //logmacros .ECHO
447 //logmacros ECHO(...)
448 //logmacros
449 //logmacros Never optimized out, logs at LOG_NOTICE level. Its main purpose is for implementing
450 //logmacros testsuites where one want to print and log messages independent of the build level
451 //logmacros
453 #define NOBUG_ECHO(...) \
454 NOBUG_LOG_(&nobug_flag_NOBUG_ON, LOG_NOTICE, NOBUG_LOCATION_INFO, "ECHO", ## __VA_ARGS__)
457 //index.alert xref:ALERT[ALERT]:: about to die
458 //logmacros [[ALERT]]
459 //logmacros .ALERT
460 //logmacros ALERT(flag, ...)
461 //logmacros ALERT_DBG(flag, ...)
462 //logmacros ALERT_IF(when, flag, ...)
463 //logmacros ALERT_IF_DBG(when, flag, ...)
464 //logmacros
465 //logmacros This is the most critical condition an application might log. This might be used
466 //logmacros if an error occurs which can not be handled except a safe shutdown for example.
467 //logmacros
469 #define NOBUG_ALERT(flag, ...) \
470 NOBUG_LOG(flag, LOG_ALERT, ## __VA_ARGS__)
471 #define NOBUG_ALERT_IF(expr, flag, ...) \
472 NOBUG_LOG_IF(expr, flag, LOG_ALERT, ## __VA_ARGS__)
473 #define NOBUG_ALERT_DBG(flag, ...) \
474 NOBUG_LOG_DBG(flag, LOG_ALERT, ## __VA_ARGS__)
475 #define NOBUG_ALERT_IF_DBG(expr, flag, ...) \
476 NOBUG_LOG_IF_DBG(expr, flag, LOG_ALERT, ## __VA_ARGS__)
479 //index.critical xref:CRITICAL[CRITICAL]:: can not continue
480 //logmacros [[CRITICAL]]
481 //logmacros .CRITICAL
482 //logmacros CRITICAL(flag, ...)
483 //logmacros CRITICAL_DBG(flag, ...)
484 //logmacros CRITICAL_IF(when, flag, ...)
485 //logmacros CRITICAL_IF_DBG(when, flag, ...)
486 //logmacros
487 //logmacros An error which can not be handled occured but the application does not need to be
488 //logmacros shutdowen, perhaps waiting for an operator to fix the cause.
489 //logmacros
491 #define NOBUG_CRITICAL(flag, ...) \
492 NOBUG_LOG(flag, LOG_CRIT, ## __VA_ARGS__)
493 #define NOBUG_CRITICAL_IF(expr, flag, ...) \
494 NOBUG_LOG_IF(expr, flag, LOG_CRIT, ## __VA_ARGS__)
495 #define NOBUG_CRITICAL_DBG(flag, ...) \
496 NOBUG_LOG_DBG(flag, LOG_CRIT, ## __VA_ARGS__)
497 #define NOBUG_CRITICAL_IF_DBG(expr, flag, ...) \
498 NOBUG_LOG_IF_DBG(expr, flag, LOG_CRIT, ## __VA_ARGS__)
501 //index.error xref:ERROR[ERROR]:: something gone wrong
502 //logmacros [[ERROR]]
503 //logmacros .ERROR
504 //logmacros ERROR(flag, fmt, ...)
505 //logmacros ERROR_DBG(flag, fmt, ...)
506 //logmacros ERROR_IF(when, flag, fmt, ...)
507 //logmacros ERROR_IF_DBG(when, flag, fmt, ...)
508 //logmacros
509 //logmacros Application takes a error handling brach
510 //logmacros
512 #define NOBUG_ERROR(flag, ...) \
513 NOBUG_LOG(flag, LOG_ERR, ## __VA_ARGS__)
514 #define NOBUG_ERROR_IF(expr, flag, ...) \
515 NOBUG_LOG_IF(expr, flag, LOG_ERR, ## __VA_ARGS__)
516 #define NOBUG_ERROR_DBG(flag, ...) \
517 NOBUG_LOG_DBG(flag, LOG_ERR, ## __VA_ARGS__)
518 #define NOBUG_ERROR_IF_DBG(expr, flag, ...) \
519 NOBUG_LOG_IF_DBG(expr, flag, LOG_ERR, ## __VA_ARGS__)
522 //index.warn xref:WARN[WARN]:: unexpected fixable error
523 //logmacros [[WARN]]
524 //logmacros .WARN
525 //logmacros WARN(flag, fmt, ...)
526 //logmacros WARN_DBG(flag, fmt, ...)
527 //logmacros WARN_IF(when, flag, fmt, ...)
528 //logmacros WARN_IF_DBG(when, flag, fmt, ...)
529 //logmacros
530 //logmacros Rare, handled but unexpected branch
531 //logmacros
533 #define NOBUG_WARN(flag, ...) \
534 NOBUG_LOG(flag, LOG_WARNING, ## __VA_ARGS__)
535 #define NOBUG_WARN_IF(expr, flag, ...) \
536 NOBUG_LOG_IF(expr, flag, LOG_WARNING, ## __VA_ARGS__)
537 #define NOBUG_WARN_DBG(flag, ...) \
538 NOBUG_LOG_DBG(flag, LOG_WARNING, ## __VA_ARGS__)
539 #define NOBUG_WARN_IF_DBG(expr, flag, ...) \
540 NOBUG_LOG_IF_DBG(expr, flag, LOG_WARNING, ## __VA_ARGS__)
543 //index.info xref:INFO[INFO]:: progress message
544 //logmacros [[INFO]]
545 //logmacros .INFO
546 //logmacros INFO(flag, fmt, ...)
547 //logmacros INFO_DBG(flag, fmt, ...)
548 //logmacros INFO_IF(when, flag, fmt, ...)
549 //logmacros INFO_IF_DBG(when, flag, fmt, ...)
550 //logmacros
551 //logmacros Message about program progress
552 //logmacros
554 #define NOBUG_INFO(flag, ...) \
555 NOBUG_LOG(flag, LOG_INFO, ## __VA_ARGS__)
556 #define NOBUG_INFO_IF(expr, flag, ...) \
557 NOBUG_LOG_IF(expr, flag, LOG_INFO, ## __VA_ARGS__)
558 #define NOBUG_INFO_DBG(flag, ...) \
559 NOBUG_LOG_DBG(flag, LOG_INFO, ## __VA_ARGS__)
560 #define NOBUG_INFO_IF_DBG(expr, flag, ...) \
561 NOBUG_LOG_IF_DBG(expr, flag, LOG_INFO, ## __VA_ARGS__)
564 //index.notice xref:NOTICE[NOTICE]:: detailed progress message
565 //logmacros [[NOTICE]]
566 //logmacros .NOTICE
567 //logmacros NOTICE(flag, fmt, ...)
568 //logmacros NOTICE_DBG(flag, fmt, ...)
569 //logmacros NOTICE_IF(when, flag, fmt, ...)
570 //logmacros NOTICE_IF_DBG(when, flag, fmt, ...)
571 //logmacros
572 //logmacros More detailed progress message
573 //logmacros
575 #define NOBUG_NOTICE(flag, ...) \
576 NOBUG_LOG(flag, LOG_NOTICE, ## __VA_ARGS__)
577 #define NOBUG_NOTICE_IF(expr, flag, ...) \
578 NOBUG_LOG_IF(expr, flag, LOG_NOTICE, ## __VA_ARGS__)
579 #define NOBUG_NOTICE_DBG(flag, ...) \
580 NOBUG_LOG_DBG(flag, LOG_NOTICE, ## __VA_ARGS__)
581 #define NOBUG_NOTICE_IF_DBG(expr, flag, ...) \
582 NOBUG_LOG_IF_DBG(expr, flag, LOG_NOTICE, ## __VA_ARGS__)
585 //index.trace xref:TRACE[TRACE]:: debugging level message
586 //logmacros [[TRACE]]
587 //logmacros .TRACE
588 //logmacros TRACE(flag, fmt, ...)
589 //logmacros TRACE_DBG(flag, fmt, ...)
590 //logmacros TRACE_IF(when, flag, fmt, ...)
591 //logmacros TRACEIF_DBG(when, flag, fmt, ...)
592 //logmacros
593 //logmacros Very fine grained messages
594 //logmacros
595 //logmacros NOTE: that `TRACE` corresponds to `LOG_DEBUG`, because using `DEBUG` could be ambiguous.
596 //logmacros
598 #define NOBUG_TRACE(flag, ...) \
599 NOBUG_LOG(flag, LOG_DEBUG, ## __VA_ARGS__)
600 #define NOBUG_TRACE_IF(expr, flag, ...) \
601 NOBUG_LOG_IF(expr, flag, LOG_DEBUG, ## __VA_ARGS__)
602 #define NOBUG_TRACE_DBG(flag, ...) \
603 NOBUG_LOG_DBG(flag, LOG_DEBUG, ## __VA_ARGS__)
604 #define NOBUG_TRACE_IF_DBG(expr, flag, ...) \
605 NOBUG_LOG_IF_DBG(expr, flag, LOG_DEBUG, ## __VA_ARGS__)
609 //index.log xref:LOG[LOG]:: generic logging
610 //logmacros [[LOG]]
611 //logmacros .LOG
612 //logmacros LOG(flag, lvl, fmt, ...)
613 //logmacros LOG_DBG(flag, lvl, fmt, ...)
614 //logmacros LOG_IF(when, flag, lvl, fmt, ...)
615 //logmacros LOG_IF_DBG(when, flag, lvl, fmt, ...)
616 //logmacros
617 //logmacros Generic logging macro which takes the level explicitly,
618 //logmacros avoid this, unless you implement your own logging facilities.
619 //logmacros
621 #define NOBUG_LOG(flag, lvl, ...) \
622 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
623 NOBUG_LVL(lvl), ## __VA_ARGS__)
625 #define NOBUG_LOG_DBG(flag, lvl, ...) \
626 NOBUG_WHEN (NOBUG_ACTIVE_DBG, \
627 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
628 NOBUG_LVL(lvl), ## __VA_ARGS__) \
631 #define NOBUG_LOG_IF(expr, flag, lvl, ...) \
632 NOBUG_WHEN (expr, \
633 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
634 NOBUG_LVL(lvl), ## __VA_ARGS__) \
637 #define NOBUG_LOG_IF_DBG(expr, flag, lvl, ...) \
638 NOBUG_WHEN (NOBUG_ACTIVE_DBG && expr, \
639 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LOCATION_INFO, \
640 NOBUG_LVL(lvl), ## __VA_ARGS__) \
645 low level logging handler
647 #define NOBUG_LOG_(flag, lvl, location, what, ...) \
648 NOBUG_WHEN (lvl <= NOBUG_LOG_BASELIMIT && lvl <= (flag)->limits[NOBUG_TARGET_RINGBUFFER], \
649 nobug_log (flag, lvl, \
650 "%0.10llu: %s: %s:%d:"NOBUG_THREAD_ID_FMT(" ",":")" %s: " \
651 NOBUG_HEAD(__VA_ARGS__), ++nobug_counter, what, \
652 NOBUG_LOCATION_FILE location, \
653 NOBUG_LOCATION_LINE location NOBUG_THREAD_ID_COMMA, \
654 NOBUG_LOCATION_FUNC location NOBUG_TAIL(__VA_ARGS__)) \
657 #define NOBUG_LVL(lvl) NOBUG_LVL_##lvl
658 #define NOBUG_LVL_0 "EMERG"
659 #define NOBUG_LVL_1 "ALERT"
660 #define NOBUG_LVL_2 "CRIT"
661 #define NOBUG_LVL_3 "ERR"
662 #define NOBUG_LVL_4 "WARNING"
663 #define NOBUG_LVL_5 "NOTICE"
664 #define NOBUG_LVL_6 "INFO"
665 #define NOBUG_LVL_7 "TRACE"
668 //index.log_baselimit xref:LOG_BASELIMIT[LOG_BASELIMIT]:: minimum compliled-in logging limit
669 //logmacros [[LOG_BASELIMIT]]
670 //logmacros .LOG_BASELIMIT
671 //logmacros NOBUG_LOG_BASELIMIT_ALPHA
672 //logmacros NOBUG_LOG_BASELIMIT_BETA
673 //logmacros NOBUG_LOG_BASELIMIT_RELEASE
674 //logmacros NOBUG_LOG_BASELIMIT
675 //logmacros
676 //logmacros NoBug defines some logging base limits, anything more detailed
677 //logmacros than this base limits will be optimized out. This is used to
678 //logmacros reduce the logging overhead for *RELEASE* builds.
679 //logmacros By default the limit is set to `LOG_DEBUG` for *ALPHA* and *BETA*
680 //logmacros builds, so all logging is retained and `LOG_NOTICE` in *RELEASE*
681 //logmacros builds to log the application progress only coarsely then.
682 //logmacros
683 //logmacros This macros can be defined before including 'nobug.h' to some other
684 //logmacros log level (as defined in 'syslog.h').
685 //logmacros
687 #ifndef NOBUG_LOG_BASELIMIT_ALPHA
688 #define NOBUG_LOG_BASELIMIT_ALPHA LOG_DEBUG
689 #endif
691 #ifndef NOBUG_LOG_BASELIMIT_BETA
692 #define NOBUG_LOG_BASELIMIT_BETA LOG_DEBUG
693 #endif
695 #ifndef NOBUG_LOG_BASELIMIT_RELEASE
696 #define NOBUG_LOG_BASELIMIT_RELEASE LOG_NOTICE
697 #endif
699 #ifndef NOBUG_LOG_BASELIMIT
700 #define NOBUG_LOG_BASELIMIT \
701 NOBUG_IF_ALPHA(NOBUG_LOG_BASELIMIT_ALPHA) \
702 NOBUG_IF_BETA(NOBUG_LOG_BASELIMIT_BETA) \
703 NOBUG_IF_RELEASE(NOBUG_LOG_BASELIMIT_RELEASE)
704 #endif
707 Annotations
711 alpha beta release
712 DEPRECATED log nothing wont compile
714 //index.deprecated xref:DEPRECATED[DEPRECATED]:: to be discarded in future
715 //annotations [[DEPRECATED]]
716 //annotations * DEPRECATED(...)
717 //annotations + Something which shouldn't be used in future
718 //annotations
720 #define NOBUG_DEPRECATED(msg) \
721 NOBUG_IF_ALPHA(NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_WARN, \
722 NOBUG_LOCATION_INFO, "DEPRECATED", msg) \
724 NOBUG_IF_RELEASE(NOBUG_DEPRECATED_NOT_ALLOWED_IN_RELEASE_BUILD(msg))
728 alpha beta release
729 UNIMPLEMENTED abort abort wont compile
731 //index.unimplemented xref:UNIMPLEMENTED[UNIMPLEMENTED]:: not yet implemented
732 //annotations [[UNIMPLEMENTED]]
733 //annotations * UNIMPLEMENTED(...)
734 //annotations + not yet finished feature
735 //annotations
737 #define NOBUG_UNIMPLEMENTED(msg) \
738 NOBUG_IF_NOT_RELEASE ( do { \
739 NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_EMERG, NOBUG_LOCATION_INFO, \
740 "UNIMPLEMENTED", msg); \
741 NOBUG_ABORT; \
742 } while (0)) \
743 NOBUG_IF_RELEASE( NOBUG_UNIMPLEMENTED_NOT_ALLOWED_IN_RELEASE_BUILD(msg))
747 alpha beta release
748 FIXME log wont compile wont compile
750 //index.fixme xref:FIXME[FIXME]:: known Bug
751 //annotations [[FIXME]]
752 //annotations * FIXME(...)
753 //annotations + known bug to be fixed later
754 //annotations
756 #define NOBUG_FIXME(msg) \
757 NOBUG_IF_ALPHA( NOBUG_ONCE( NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_ALERT, \
758 NOBUG_LOCATION_INFO, "FIXME", msg))) \
759 NOBUG_IF_BETA( NOBUG_FIXME_NOT_ALLOWED_IN_BETA_BUILD(msg)) \
760 NOBUG_IF_RELEASE( NOBUG_FIXME_NOT_ALLOWED_IN_RELEASE_BUILD(msg))
764 alpha beta release
765 TODO log log wont compile
767 //index.todo xref:TODO[TODO]:: things to be done
768 //annotations [[TODO]]
769 //annotations * TODO(...)
770 //annotations + enhancement to be done soon
771 //annotations
773 #define NOBUG_TODO(msg) \
774 NOBUG_IF_NOT_RELEASE ( \
775 NOBUG_ONCE ( \
776 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_NOTICE, NOBUG_LOCATION_INFO, \
777 "TODO", msg); \
778 )) \
779 NOBUG_IF_RELEASE(NOBUG_TODO_NOT_ALLOWED_IN_RELEASE_BUILD(msg))
783 alpha beta release
784 PLANNED log nothing nothing
786 //index.planned xref:PLANNED[PLANNED]:: ideas for future
787 //annotations [[PLANNED]]
788 //annotations * PLANNED(...)
789 //annotations + future enhancement
790 //annotations
792 #define NOBUG_PLANNED(msg) \
793 NOBUG_IF_ALPHA( NOBUG_ONCE(NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_INFO, \
794 NOBUG_LOCATION_INFO, "PLANNED", msg)))
798 alpha beta release
799 NOTREACHED abort abort nothing
801 //index.notreached xref:NOTREACHED[NOTREACHED]:: code path never taken
802 //annotations [[NOTREACHED]]
803 //annotations * NOTREACHED
804 //annotations + used to tag code-path which shall be never executed (defaults in switch
805 //annotations statements, `else NOTREACHED;` after series of if's, etc.)
806 //annotations
808 #define NOBUG_NOTREACHED \
809 NOBUG_IF_NOT_RELEASE( do { \
810 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG, \
811 NOBUG_LOCATION_INFO, "NOTREACHED"); \
812 NOBUG_ABORT; \
813 } while (0))
817 Fault injection
819 //faultinjection NoBug has some macros which can be used to simulate errorneous behaviour:
820 //faultinjection
821 //index.inject_goodbad xref:INJECT_GOODBAD[INJECT_GOODBAD]:: fault injection expression
822 //faultinjection [[INJECT_GOODBAD]]
823 //faultinjection * INJECT_GOODBAD(expr, good, bad) substitutes to an expression and returns
824 //faultinjection good when expr is false and bad when expr is true. In BETA and RELEASE
825 //faultinjection builds 'good' is always returned.
826 //faultinjection
828 #define NOBUG_INJECT_GOODBAD(expr, good, bad) \
829 NOBUG_IF_ALPHA((expr)?({NOBUG_INJECT_LOG(#expr": "#bad);}),bad:good) \
830 NOBUG_IF_NOT_ALPHA(good)
834 //index.inject_fault xref:INJECT_FAULT[INJECT_FAULT]:: fault injection statement
835 //faultinjection [[INJECT_FAULT]]
836 //faultinjection * INJECT_FAULT(expr, bad) substitutes to a statement which executes 'bad'
837 //faultinjection when expr is true. Optimitzed out in BETA and RELEASE builds.
838 //faultinjection
840 #define NOBUG_INJECT_FAULT(expr, bad) \
841 NOBUG_IF_ALPHA(NOBUG_WHEN(expr,NOBUG_INJECT_LOG(#expr": "#bad); bad))
845 //faultinjection In both cases, when a fault is injected it will be logged at
846 //faultinjection NOBUG_INJECT_LEVEL (default: LOG_NOTICE). This can be defined
847 //faultinjection before including 'nobug.h' to override it.
848 //faultinjection
850 #define NOBUG_INJECT_LOG(msg) \
851 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_INJECT_LEVEL, \
852 NOBUG_LOCATION_INFO, "INJECT_FAULT", \
853 msg)
856 #ifndef NOBUG_INJECT_LEVEL
857 #define NOBUG_INJECT_LEVEL LOG_NOTICE
858 #endif
862 Flag handling
864 #define NOBUG_FLAG(name) NOBUG_CAT(nobug_flag_,name)
866 #define NOBUG_DEFINE_FLAG(name) struct nobug_flag NOBUG_FLAG(name) = \
867 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
868 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
869 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
870 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
871 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
872 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL})
874 #define NOBUG_DEFINE_FLAG_PARENT(name, parent) \
875 NOBUG_DECLARE_FLAG(parent); \
876 struct nobug_flag NOBUG_FLAG(name) = \
877 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
878 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
879 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
880 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
881 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
882 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL})
884 #define NOBUG_DEFINE_FLAG_LIMIT(name, limit) struct nobug_flag NOBUG_FLAG(name) = \
885 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
886 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
887 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
888 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
889 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
890 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL})
892 #define NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, limit) \
893 NOBUG_DECLARE_FLAG(parent); \
894 struct nobug_flag NOBUG_FLAG(name) = \
895 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
896 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
897 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
898 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
899 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
900 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL})
903 /*TODO better FLAG_LIMIT handling, should respect LOG_TARGET */
906 #define NOBUG_DECLARE_FLAG(name) extern struct nobug_flag NOBUG_FLAG(name)
908 #define NOBUG_INIT_FLAG(name) \
909 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, NOBUG_LOG_LIMIT)
911 #define NOBUG_INIT_FLAG_LIMIT(name, default) \
912 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, default)
914 #ifdef __cplusplus
915 #define NOBUG_CPP_DEFINE_FLAG(name) \
916 NOBUG_DEFINE_FLAG(name); \
917 static int nobug_##name##_cppinit##__LINE__ = NOBUG_INIT_FLAG(name)
919 #define NOBUG_CPP_DEFINE_FLAG_PARENT(name, parent) \
920 NOBUG_DEFINE_FLAG_PARENT(name, parent); \
921 static int nobug_##name##_cppinit##__LINE__ = NOBUG_INIT_FLAG(name)
923 #define NOBUG_CPP_DEFINE_FLAG_LIMIT(name, default) \
924 NOBUG_DEFINE_FLAG_LIMIT(name, default); \
925 static int nobug_##name##_cppinit##__LINE__ = NOBUG_INIT_FLAG_LIMIT(name, default)
927 #define NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT(name, parent, default) \
928 NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, default); \
929 static int nobug_##name##_cppinit##__LINE__ = NOBUG_INIT_FLAG_LIMIT(name, default)
930 #endif
932 #ifndef NOBUG_LOG_LIMIT_ALPHA
933 # define NOBUG_LOG_LIMIT_ALPHA LOG_INFO
934 #endif
935 #ifndef NOBUG_LOG_LIMIT_BETA
936 # define NOBUG_LOG_LIMIT_BETA LOG_WARNING
937 #endif
938 #ifndef NOBUG_LOG_LIMIT_RELEASE
939 # define NOBUG_LOG_LIMIT_RELEASE LOG_CRIT
940 #endif
942 #ifndef NOBUG_LOG_LIMIT
943 # define NOBUG_LOG_LIMIT \
944 NOBUG_IF_ALPHA( NOBUG_LOG_LIMIT_ALPHA) \
945 NOBUG_IF_BETA( NOBUG_LOG_LIMIT_BETA) \
946 NOBUG_IF_RELEASE( NOBUG_LOG_LIMIT_RELEASE)
947 #endif
949 #ifndef NOBUG_LOG_TARGET_ALPHA
950 # define NOBUG_LOG_TARGET_ALPHA NOBUG_TARGET_CONSOLE
951 #endif
952 #ifndef NOBUG_LOG_TARGET_BETA
953 # define NOBUG_LOG_TARGET_BETA NOBUG_TARGET_FILE
954 #endif
955 #ifndef NOBUG_LOG_TARGET_RELEASE
956 # define NOBUG_LOG_TARGET_RELEASE NOBUG_TARGET_SYSLOG
957 #endif
959 #ifndef NOBUG_LOG_TARGET
960 # define NOBUG_LOG_TARGET \
961 NOBUG_IF_ALPHA( NOBUG_LOG_TARGET_ALPHA) \
962 NOBUG_IF_BETA( NOBUG_LOG_TARGET_BETA) \
963 NOBUG_IF_RELEASE( NOBUG_LOG_TARGET_RELEASE)
964 #endif
966 #define NOBUG_SET_LIMIT(flag, min) \
967 NOBUG_IF_NOT_RELEASE( NOBUG_FLAG(flag) = (min))
971 Resource registry macros
975 //index.resource_logging xref:RESOURCE_LOGGING[RESOURCE_LOGGING]:: switch resource logging on and off
976 //index.resource_log_level xref:RESOURCE_LOGGING[RESOURCE_LOG_LEVEL]:: select the log level for resource logging
977 //resourcemacros [[RESOURCE_LOGGING]]
978 //resourcemacros
979 //resourcemacros Unless the user defines `NOBUG_RESOURCE_LOGGING` to 0 each of the above macros
980 //resourcemacros will emit a log message at `NOBUG_RESOURCE_LOG_LEVEL` which defaults to
981 //resourcemacros `LOG_DEBUG`.
982 //resourcemacros
984 #ifndef NOBUG_RESOURCE_LOGGING
985 #define NOBUG_RESOURCE_LOGGING 1
986 #endif
988 #ifndef NOBUG_RESOURCE_LOG_LEVEL
989 #define NOBUG_RESOURCE_LOG_LEVEL LOG_DEBUG
990 #endif
994 //index.resource_handle xref:RESOURCE_HANDLE[RESOURCE_HANDLE]:: define an resource handle
995 //resourcemacros [[RESOURCE_HANDLE]]
996 //resourcemacros Resources are accessed through handles.
997 //resourcemacros
998 //resourcemacros .RESOURCE_HANDLE
999 //resourcemacros RESOURCE_HANDLE(name)
1000 //resourcemacros
1001 //resourcemacros Defines handles to access resources.
1002 //resourcemacros
1003 //resourcemacros `name`::
1004 //resourcemacros identifer to be used for the handle
1005 //resourcemacros
1006 //resourcemacros This macro takes care that the declaration is optimized out in the same manner
1007 //resourcemacros the rest of the resource tracker would be disabled. You can still instantiate
1008 //resourcemacros handles as `struct nobug_resource_record*` in structures which must have a
1009 //resourcemacros constant size unconditional of the build level.
1010 //resourcemacros
1012 #define NOBUG_RESOURCE_HANDLE(handle) \
1013 NOBUG_IF_ALPHA(struct nobug_resource_record* handle)
1015 #define NOBUG_RESOURCE_HANDLE_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
1019 //index.resource_announce xref:RESOURCE_ANNOUNCE[RESOURCE_ANNOUNCE]:: publish new resources
1020 //resourcemacros [[RESOURCE_ANNOUNCE]]
1021 //resourcemacros
1022 //resourcemacros .RESOURCE_ANNOUNCE
1023 //resourcemacros RESOURCE_ANNOUNCE(flag, type, name, identifier, handle)
1024 //resourcemacros
1025 //resourcemacros Publishes resources.
1026 //resourcemacros
1027 //resourcemacros `flag`::
1028 //resourcemacros the NoBug flag which turns logging on for this macro
1029 //resourcemacros `type`::
1030 //resourcemacros a string which should denote the domain of the resource,
1031 //resourcemacros examples are "file", "mutex", "lock", "database" and so on
1032 //resourcemacros `name`::
1033 //resourcemacros the actual name of a named resource this as string which
1034 //resourcemacros together with type forms a unique identifier of the resource. `type` and
1035 //resourcemacros `name` must be available through the entire lifetime of the resource, using
1036 //resourcemacros literal strings is recommended
1037 //resourcemacros `identifier`::
1038 //resourcemacros a pointer which should be unique for this resource, any
1039 //resourcemacros kind of pointer will suffice, it is only used for identification. In
1040 //resourcemacros multithreaded applications the thread identifier becomes an additional
1041 //resourcemacros identifier
1042 //resourcemacros `handle`::
1043 //resourcemacros a `nobug_resource_record*` which will be initialized to point to
1044 //resourcemacros the newly created resource.
1045 //resourcemacros
1046 //resourcemacros Resources must be unique, it is a fatal error when a resource it tried to be
1047 //resourcemacros announced more than one time.
1048 //resourcemacros
1050 #define NOBUG_RESOURCE_ANNOUNCE(flag, type, name, ptr, handle) \
1051 NOBUG_RESOURCE_ANNOUNCE_RAW(&NOBUG_FLAG(flag), type, name, ptr, handle)
1053 #define NOBUG_RESOURCE_ANNOUNCE_RAW(flag, type, name, ptr, handle) \
1054 NOBUG_IF_ALPHA( do { \
1055 NOBUG_REQUIRE(!handle, "Announced resource handle not initialized"); \
1056 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1057 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1058 NOBUG_LOCATION_INFO, "RESOURCE_ANNOUNCE", \
1059 "%s: %s@%p", type, name, ptr);) \
1060 NOBUG_ASSERTN_(handle = nobug_resource_announce (type, name, ptr, \
1061 NOBUG_BASENAME(__FILE__ ":" NOBUG_STRINGIZE(__LINE__))), \
1062 "RESOURCE_ANNOUNCE", NOBUG_LOCATION_INFO, \
1063 "%s: %s@%p %s", type, name, ptr, nobug_resource_error); \
1064 } while (0))
1068 //index.resource_forget xref:RESOURCE_FORGET[RESOURCE_FORGET]:: remove resources
1069 //resourcemacros [[RESOURCE_FORGET]]
1070 //resourcemacros
1071 //resourcemacros .RESOURCE_FORGET
1072 //resourcemacros RESOURCE_FORGET(flag, handle)
1073 //resourcemacros
1074 //resourcemacros Removes resources that have become unavailable from the registry.
1075 //resourcemacros
1076 //resourcemacros `flag`::
1077 //resourcemacros the NoBug flag which turns logging on for this macro
1078 //resourcemacros `handle`::
1079 //resourcemacros the `nobug_resource_record*` used to track this resource
1080 //resourcemacros
1081 //resourcemacros The resource must still exist and no users must be attached to it, else a fatal
1082 //resourcemacros error is raised.
1083 //resourcemacros
1085 #define NOBUG_RESOURCE_FORGET(flag, handle) \
1086 NOBUG_RESOURCE_FORGET_RAW(&NOBUG_FLAG(flag), handle)
1088 #define NOBUG_RESOURCE_FORGET_RAW(flag, handle) \
1089 NOBUG_IF_ALPHA( do { \
1090 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1091 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
1092 "RESOURCE_FORGET", "%s: %s@%p", handle?handle->type:"", \
1093 handle?handle->name:"", handle?handle->object_id:NULL);) \
1094 NOBUG_ASSERTN_(nobug_resource_forget (handle), \
1095 "RESOURCE_FORGET", NOBUG_LOCATION_INFO, "%s: %s@%p: %s", \
1096 handle?handle->type:"", handle?handle->name:"", \
1097 handle?handle->object_id:NULL, nobug_resource_error); \
1098 handle = NULL; \
1099 } while (0))
1103 //index.resource_enter xref:RESOURCE_ENTER[RESOURCE_ENTER]:: claim a resource
1104 //resourcemacros [[RESOURCE_ENTER]]
1105 //resourcemacros
1106 //resourcemacros .RESOURCE_ENTER
1107 //resourcemacros RESOURCE_ENTER(flag, announced, name, identifier, state, handle)
1108 //resourcemacros
1109 //resourcemacros Attach a resource to code.
1110 //resourcemacros
1111 //resourcemacros `flag`::
1112 //resourcemacros nobug flag which turns logging on for this macro
1113 //resourcemacros `announced`::
1114 //resourcemacros the handle set by `RESOURCE_ANNOUNCE`
1115 //resourcemacros `name`::
1116 //resourcemacros a free-form identifier
1117 //resourcemacros `identifier`::
1118 //resourcemacros some pointer which must be unique for the user of the
1119 //resourcemacros resource (see above)
1120 //resourcemacros `state`::
1121 //resourcemacros the initial state, one of `NOBUG_RESOURCE_WAITING`,
1122 //resourcemacros `NOBUG_RESOURCE_EXCLUSIVE` or `NOBUG_RESOURCE_RECURSIVE`
1123 //resourcemacros `handle`::
1124 //resourcemacros a `nobug_resource_record*` which will be initialized to the
1125 //resourcemacros entering node
1126 //resourcemacros
1128 #define NOBUG_RESOURCE_ENTER(flag, resource, user, ptr, state, handle) \
1129 NOBUG_IF_ALPHA( do { \
1130 NOBUG_REQUIRE(resource, "Announced resource handle not initialized"); \
1131 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1132 NOBUG_LOG_(&NOBUG_FLAG(flag), NOBUG_RESOURCE_LOG_LEVEL, \
1133 NOBUG_LOCATION_INFO, "RESOURCE_ENTER", \
1134 "%s: %s@%p: %s@%p: %s", resource->type, resource->name, \
1135 resource->object_id, user, ptr, \
1136 nobug_resource_states[state]);) \
1137 NOBUG_ASSERTN_(handle = nobug_resource_enter (resource, user, ptr, state, \
1138 NOBUG_BASENAME(__FILE__ ":" NOBUG_STRINGIZE(__LINE__))), \
1139 "RESOURCE_ENTER", NOBUG_LOCATION_INFO, \
1140 "%s: %s@%p: %s@%p: %s: %s", \
1141 resource?resource->type:"", resource?resource->name:"", \
1142 resource?resource->object_id:NULL, \
1143 user, ptr, nobug_resource_states[state], \
1144 nobug_resource_error); \
1145 } while (0))
1149 //index.resource_state xref:RESOURCE_STATE[RESOURCE_STATE]:: change the state of a resource
1150 //resourcemacros [[RESOURCE_STATE]]
1151 //resourcemacros
1152 //resourcemacros .NOBUG_RESOURCE_STATE
1153 //resourcemacros NOBUG_RESOURCE_STATE(flag, entered, state)
1154 //resourcemacros
1155 //resourcemacros Changes resource's state.
1156 //resourcemacros
1157 //resourcemacros `flag`::
1158 //resourcemacros is nobug flag which turns logging on for this macro
1159 //resourcemacros `entered`::
1160 //resourcemacros the handle set by `RESOURCE_ENTER`
1161 //resourcemacros `state`::
1162 //resourcemacros the new state Note that only certain state transitions are
1163 //resourcemacros allowed, see discussion/diagram above
1164 //resourcemacros
1166 #define NOBUG_RESOURCE_STATE(flag, resource, state) \
1167 NOBUG_RESOURCE_STATE_RAW(&NOBUG_FLAG(flag), resource, state)
1169 #define NOBUG_RESOURCE_STATE_RAW(flag, resource, state) \
1170 NOBUG_IF_ALPHA( do { \
1171 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1172 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
1173 "RESOURCE_STATE", "%s: %s@%p: %s@%p: %s->%s", \
1174 resource?((struct nobug_resource_record*)resource->data)->type:"", \
1175 resource?((struct nobug_resource_record*)resource->data)->name:"", \
1176 resource?((struct nobug_resource_record*)resource->data)->object_id:"", \
1177 resource?resource->name:NULL, \
1178 resource?resource->object_id:NULL, \
1179 resource?resource->type:"", nobug_resource_states[state]); \
1181 NOBUG_ASSERTN_(nobug_resource_state (resource, state), \
1182 "RESOURCE_STATE", NOBUG_LOCATION_INFO, "%s: %s@%p: %s@%p: %s->%s: %s", \
1183 resource?((struct nobug_resource_record*)resource->data)->type:"", \
1184 resource?((struct nobug_resource_record*)resource->data)->name:"", \
1185 resource?((struct nobug_resource_record*)resource->data)->object_id:"", \
1186 resource?resource->name:NULL, \
1187 resource?resource->object_id:NULL, \
1188 resource?resource->type:"", nobug_resource_states[state], \
1189 nobug_resource_error); \
1190 } while (0))
1194 //index.resource_leave xref:RESOURCE_LEAVE[RESOURCE_LEAVE]:: relinquish a claimed resource
1195 //resourcemacros [[RESOURCE_LEAVE]]
1196 //resourcemacros
1197 //resourcemacros .RESOURCE_LEAVE
1198 //resourcemacros RESOURCE_LEAVE(flag, handle)
1199 //resourcemacros
1200 //resourcemacros Disconnect from a resource identified with its handle.
1201 //resourcemacros
1202 //resourcemacros `flag`::
1203 //resourcemacros nobug flag which turns logging on for this macro
1204 //resourcemacros `handle`::
1205 //resourcemacros the handle you got while entering the resource
1206 //resourcemacros
1208 #define NOBUG_RESOURCE_LEAVE(flag, handle) \
1209 NOBUG_RESOURCE_LEAVE_RAW(&NOBUG_FLAG(flag), handle)
1211 #define NOBUG_RESOURCE_LEAVE_RAW(flag, handle) \
1212 NOBUG_IF_ALPHA( do { \
1213 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1214 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
1215 "RESOURCE_LEAVE", "%s: %s@%p: %s@%p: %s", \
1216 handle?((struct nobug_resource_record*)handle->data)->type:"", \
1217 handle?((struct nobug_resource_record*)handle->data)->name:"", \
1218 handle?((struct nobug_resource_record*)handle->data)->object_id:"", \
1219 handle?handle->name:"", \
1220 handle?handle->object_id:NULL, \
1221 handle?handle->type:""); \
1223 NOBUG_ASSERTN_(nobug_resource_leave (handle), \
1224 "RESOURCE_LEAVE", NOBUG_LOCATION_INFO, "%s: %s@%p: %s@%p: %s: %s", \
1225 handle?((struct nobug_resource_record*)handle->data)->type:"", \
1226 handle?((struct nobug_resource_record*)handle->data)->name:"", \
1227 handle?((struct nobug_resource_record*)handle->data)->object_id:"", \
1228 handle?handle->name:NULL, \
1229 handle?handle->object_id:NULL, \
1230 handle?handle->type:"", \
1231 nobug_resource_error); \
1232 handle = NULL; \
1233 } while (0))
1237 //index.resource_leave_lookup xref:RESOURCE_LEAVE_LOOKUP[RESOURCE_LEAVE_LOOKUP]:: relinquish a claimed resource w/o handle
1238 //resourcemacros [[RESOURCE_LEAVE_LOOKUP]]
1239 //resourcemacros
1240 //resourcemacros .RESOURCE_LEAVE_LOOKUP
1241 //resourcemacros RESOURCE_LEAVE_LOOKUP(flag, resource, identifier)
1242 //resourcemacros
1243 //resourcemacros Disconnect from a resource identified by its identifier.
1244 //resourcemacros
1245 //resourcemacros `flag`::
1246 //resourcemacros nobug flag which turns logging on for this macro
1247 //resourcemacros `resource`::
1248 //resourcemacros the handle you got from announcing the resource
1249 //resourcemacros `identifier`::
1250 //resourcemacros the pointer you gave it when creating it
1251 //resourcemacros
1252 //resourcemacros Resources keep track of the thread which used them, you cant ANNOUNCE/FORGET
1253 //resourcemacros ENTER/LEAVE the same handle from different threads.
1254 //resourcemacros
1256 #define NOBUG_RESOURCE_LEAVE_LOOKUP(flag, handle, ptr) \
1257 NOBUG_IF_ALPHA( do { \
1258 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1259 NOBUG_LOG_(&NOBUG_FLAG(flag), NOBUG_RESOURCE_LOG_LEVEL, NOBUG_LOCATION_INFO, \
1260 "RESOURCE_LEAVE", "%s: %s@%p: @%p", \
1261 handle?handle->type:"", \
1262 handle?handle->name:"", \
1263 handle?handle->object_id:"", \
1264 ptr); \
1266 NOBUG_ASSERTN_(nobug_resource_leave (nobug_resource_find(handle, ptr)), \
1267 "RESOURCE_LEAVE", NOBUG_LOCATION_INFO, "%s: %s@%p: @%p: %s", \
1268 handle?handle->type:"", \
1269 handle?handle->name:"", \
1270 handle?handle->object_id:"", \
1271 ptr, nobug_resource_error); \
1272 } while (0))
1276 //index.resource_dump xref:NOBUG_RESOURCE_DUMP[NOBUG_RESOURCE_DUMP]:: dump the state of a single resource
1277 //resourcemacros [[NOBUG_RESOURCE_DUMP]]
1278 //resourcemacros
1279 //resourcemacros .NOBUG_RESOURCE_DUMP
1280 //resourcemacros NOBUG_RESOURCE_DUMP(flag, handle)
1281 //resourcemacros
1282 //resourcemacros Dump the state of a single resource.
1283 //resourcemacros
1284 //resourcemacros `flag`::
1285 //resourcemacros Nobug flag for the log channel
1286 //resourcemacros `handle`::
1287 //resourcemacros handle of the resource to be dumped
1288 //resourcemacros
1290 #define NOBUG_RESOURCE_DUMP(flag, handle) \
1291 do { NOBUG_RESOURCE_LOCK; \
1292 nobug_resource_dump (handle, &(struct nobug_resource_dump_context) \
1293 {&NOBUG_FLAG(flag), \
1294 NOBUG_RESOURCE_LOG_LEVEL, \
1295 __FILE__, __LINE__, __func__}); \
1296 NOBUG_RESOURCE_UNLOCK; } while (0)
1298 #define NOBUG_RESOURCE_DUMP_IF(when, flag, handle) \
1299 NOBUG_WHEN(when, NOBUG_RESOURCE_LOCK; \
1300 nobug_resource_dump (handle, &(struct nobug_resource_dump_context) \
1301 {&NOBUG_FLAG(flag), \
1302 NOBUG_RESOURCE_LOG_LEVEL, \
1303 __FILE__, __LINE__, __func__}); \
1304 NOBUG_RESOURCE_UNLOCK)
1308 //index.resource_dumpall xref:NOBUG_RESOURCE_DUMPALL[NOBUG_RESOURCE_DUMPALL]:: dump the state of all resources
1309 //resourcemacros [[NOBUG_RESOURCE_DUMPALL]]
1310 //resourcemacros
1311 //resourcemacros .NOBUG_RESOURCE_DUMPALL
1312 //resourcemacros NOBUG_RESOURCE_DUMPALL(flag)
1313 //resourcemacros
1314 //resourcemacros Dump the state of all resources.
1315 //resourcemacros
1316 //resourcemacros `flag`::
1317 //resourcemacros Nobug flag for the log channel
1318 //resourcemacros
1320 #define NOBUG_RESOURCE_DUMPALL(flag) \
1321 do { NOBUG_RESOURCE_LOCK; \
1322 nobug_resource_dump_all (&(struct nobug_resource_dump_context) \
1323 {&NOBUG_FLAG(flag), \
1324 NOBUG_RESOURCE_LOG_LEVEL, \
1325 __FILE__, __LINE__, __func__}); \
1326 NOBUG_RESOURCE_UNLOCK; } while (0)
1328 #define NOBUG_RESOURCE_DUMPALL_IF(when, flag) \
1329 NOBUG_WHEN(when, NOBUG_RESOURCE_LOCK; \
1330 nobug_resource_dump_all (&(struct nobug_resource_dump_context) \
1331 {&NOBUG_FLAG(flag), \
1332 NOBUG_RESOURCE_LOG_LEVEL, \
1333 __FILE__, __LINE__, __func__}); \
1334 NOBUG_RESOURCE_UNLOCK)
1338 //index.resource_list xref:NOBUG_RESOURCE_LIST[NOBUG_RESOURCE_LIST]:: enumerate all registered resources
1339 //resourcemacros [[NOBUG_RESOURCE_LIST]]
1340 //resourcemacros
1341 //resourcemacros .NOBUG_RESOURCE_LIST
1342 //resourcemacros NOBUG_RESOURCE_LIST(flag)
1343 //resourcemacros
1344 //resourcemacros List all registered resources.
1345 //resourcemacros
1346 //resourcemacros `flag`::
1347 //resourcemacros Nobug flag for the log channel
1348 //resourcemacros
1350 #define NOBUG_RESOURCE_LIST(flag) \
1351 do { NOBUG_RESOURCE_LOCK; \
1352 nobug_resource_list (&(struct nobug_resource_dump_context) \
1353 {&NOBUG_FLAG(flag), \
1354 NOBUG_RESOURCE_LOG_LEVEL, \
1355 __FILE__, __LINE__, __func__}); \
1356 NOBUG_RESOURCE_UNLOCK; } while (0)
1358 #define NOBUG_RESOURCE_LIST_IF(when, flag) \
1359 NOBUG_WHEN(when, NOBUG_RESOURCE_LOCK; \
1360 nobug_resource_list (&(struct nobug_resource_dump_context) \
1361 {&NOBUG_FLAG(flag), \
1362 NOBUG_RESOURCE_LOG_LEVEL, \
1363 __FILE__, __LINE__, __func__}); \
1364 NOBUG_RESOURCE_UNLOCK)
1368 threading support
1370 #if NOBUG_USE_PTHREAD
1371 #define NOBUG_THREAD_ID_SET(name) nobug_thread_id_set(name)
1372 #define NOBUG_THREAD_ID_FMT(pre,post) pre "%s" post
1373 #define NOBUG_THREAD_ID_COMMA , NOBUG_THREAD_ID_GET
1374 #define NOBUG_THREAD_ID_GET nobug_thread_id_get()
1376 #else
1377 #define NOBUG_THREAD_ID_SET(name)
1378 #define NOBUG_THREAD_ID_FMT(pre,post) ""
1379 #define NOBUG_THREAD_ID_COMMA
1380 #define NOBUG_THREAD_ID_GET ""
1381 #endif
1385 Source location
1387 #define NOBUG_LOCATION_ARGS NOBUG_BASENAME(__FILE__), __LINE__, __func__
1388 #define NOBUG_LOCATION_INFO (NOBUG_LOCATION_ARGS)
1390 #define NOBUG_LOCATION_FILE(file, _1, _2) file
1391 #define NOBUG_LOCATION_LINE(_1, line, _2) line
1392 #define NOBUG_LOCATION_FUNC(_1, _2, func) func
1396 Debuggers
1399 #define NOBUG_DBG_NONE 0
1400 #define NOBUG_DBG_GDB 1
1401 #define NOBUG_DBG_VALGRIND 2
1403 #define NOBUG_ACTIVE_DBG \
1404 NOBUG_IF(NOBUG_USE_VALGRIND, (RUNNING_ON_VALGRIND?2:0)) \
1405 NOBUG_IFNOT(NOBUG_USE_VALGRIND, 0)
1408 //index.backtrace xref:BACKTRACE[BACKTRACE]:: generate a backtrace
1409 //toolmacros [[BACKTRACE]]
1410 //toolmacros .BACKTRACE
1411 //toolmacros BACKTRACE
1412 //toolmacros
1413 //toolmacros The backtrace macro logs a stacktrace using the NoBug facilities.
1414 //toolmacros This is automatically called when NoBug finds an error and is due
1415 //toolmacros to abort. But one might call it manually too.
1416 //toolmacros
1418 #define NOBUG_BACKTRACE \
1419 NOBUG_IF_ALPHA( \
1420 switch (NOBUG_ACTIVE_DBG) { \
1421 case NOBUG_DBG_VALGRIND: \
1422 NOBUG_BACKTRACE_VALGRIND; \
1423 break; \
1424 default: \
1425 NOBUG_BACKTRACE_GLIBC; \
1426 }) \
1427 NOBUG_IF_NOT_ALPHA (NOBUG_BACKTRACE_GLIBC)
1429 #define NOBUG_BACKTRACE_DBG \
1430 NOBUG_IF_NOT_RELEASE( \
1431 switch (NOBUG_ACTIVE_DBG) { \
1432 case NOBUG_DBG_VALGRIND: \
1433 NOBUG_BACKTRACE_VALGRIND; \
1434 break; \
1437 #define NOBUG_BACKTRACE_GDB fprintf(stderr, "UNIMPLEMENTED : GDB Backtraces\n")
1439 #define NOBUG_BACKTRACE_VALGRIND \
1440 NOBUG_IF(NOBUG_USE_VALGRIND, \
1441 VALGRIND_PRINTF_BACKTRACE("BACKTRACE: %s@%d %s", \
1442 NOBUG_LOCATION_ARGS))
1445 #ifndef NOBUG_BACKTRACE_DEPTH
1446 #define NOBUG_BACKTRACE_DEPTH 256
1447 #endif
1449 #define NOBUG_BACKTRACE_GLIBC \
1450 NOBUG_IF_NOT_RELEASE( \
1451 NOBUG_IF(NOBUG_USE_EXECINFO, do { \
1452 NOBUG_LOG_(&nobug_flag_NOBUG_ON, LOG_NOTICE, NOBUG_LOCATION_INFO, "BACKTRACE"); \
1453 nobug_backtrace_glibc (); \
1454 } while (0)))
1458 init and other function wrapers
1460 #define NOBUG_INIT nobug_init()
1461 #define NOBUG_BASENAME(name) (strrchr((name), '/')?strrchr((name), '/') + 1 : (name))
1462 #define NOBUG_ABORT abort()
1466 short macros without NOBUG_
1468 #ifndef NOBUG_DISABLE_SHORTNAMES
1469 #ifndef REQUIRE
1470 #define REQUIRE NOBUG_REQUIRE
1471 #endif
1472 #ifndef REQUIRE_DBG
1473 #define REQUIRE_DBG NOBUG_REQUIRE_DBG
1474 #endif
1475 #ifndef REQUIRE_IF
1476 #define REQUIRE_IF NOBUG_REQUIRE_IF
1477 #endif
1478 #ifndef REQUIRE_IF_DBG
1479 #define REQUIRE_IF_DBG NOBUG_REQUIRE_IF_DBG
1480 #endif
1481 #ifndef ENSURE
1482 #define ENSURE NOBUG_ENSURE
1483 #endif
1484 #ifndef ENSURE_DBG
1485 #define ENSURE_DBG NOBUG_ENSURE_DBG
1486 #endif
1487 #ifndef ENSURE_IF
1488 #define ENSURE_IF NOBUG_ENSURE_IF
1489 #endif
1490 #ifndef ENSURE_IF_DBG
1491 #define ENSURE_IF_DBG NOBUG_ENSURE_IF_DBG
1492 #endif
1493 #ifndef ASSERT
1494 #define ASSERT NOBUG_ASSERT
1495 #endif
1496 #ifndef ASSERT_DBG
1497 #define ASSERT_DBG NOBUG_ASSERT_DBG
1498 #endif
1499 #ifndef ASSERT_IF
1500 #define ASSERT_IF NOBUG_ASSERT_IF
1501 #endif
1502 #ifndef ASSERT_IF_DBG
1503 #define ASSERT_IF_DBG NOBUG_ASSERT_IF_DBG
1504 #endif
1505 #ifndef CHECK
1506 #define CHECK NOBUG_CHECK
1507 #endif
1508 #ifndef CHECK
1509 #define CHECK NOBUG_CHECK
1510 #endif
1511 #ifndef INVARIANT
1512 #define INVARIANT NOBUG_INVARIANT
1513 #endif
1514 #ifndef INVARIANT_DBG
1515 #define INVARIANT_DBG NOBUG_INVARIANT_DBG
1516 #endif
1517 #ifndef INVARIANT_IF
1518 #define INVARIANT_IF NOBUG_INVARIANT_IF
1519 #endif
1520 #ifndef INVARIANT_IF_DBG
1521 #define INVARIANT_IF_DBG NOBUG_INVARIANT_IF_DBG
1522 #endif
1523 #ifndef INVARIANT_ASSERT
1524 #define INVARIANT_ASSERT NOBUG_INVARIANT_ASSERT
1525 #endif
1526 #ifndef DUMP
1527 #define DUMP NOBUG_DUMP
1528 #endif
1529 #ifndef DUMP_DBG
1530 #define DUMP_DBG NOBUG_DUMP_DBG
1531 #endif
1532 #ifndef DUMP_IF
1533 #define DUMP_IF NOBUG_DUMP_IF
1534 #endif
1535 #ifndef DUMP_IF_DBG
1536 #define DUMP_IF_DBG NOBUG_DUMP_IF_DBG
1537 #endif
1538 #ifndef DUMP_LOG
1539 #define DUMP_LOG NOBUG_DUMP_LOG
1540 #endif
1541 #ifndef DUMP_LOG_DBG
1542 #define DUMP_LOG_DBG NOBUG_DUMP_LOG_DBG
1543 #endif
1544 #ifndef DUMP_LOG_IF
1545 #define DUMP_LOG_IF NOBUG_DUMP_LOG_IF
1546 #endif
1547 #ifndef DUMP_LOG_IF_DBG
1548 #define DUMP_LOG_IF_DBG NOBUG_DUMP_LOG_IF_DBG
1549 #endif
1550 #ifndef LOG
1551 #define LOG NOBUG_LOG
1552 #endif
1553 #ifndef LOG_DBG
1554 #define LOG_DBG NOBUG_LOG_DBG
1555 #endif
1556 #ifndef LOG_IF
1557 #define LOG_IF NOBUG_LOG_IF
1558 #endif
1559 #ifndef LOG_IF_DBG
1560 #define LOG_IF_DBG NOBUG_LOG_IF_DBG
1561 #endif
1562 #ifndef ECHO
1563 #define ECHO NOBUG_ECHO
1564 #endif
1565 #ifndef ALERT
1566 #define ALERT NOBUG_ALERT
1567 #endif
1568 #ifndef ALERT_DBG
1569 #define ALERT_DBG NOBUG_ALERT_DBG
1570 #endif
1571 #ifndef ALERT_IF
1572 #define ALERT_IF NOBUG_ALERT_IF
1573 #endif
1574 #ifndef ALERT_IF_DBG
1575 #define ALERT_IF_DBG NOBUG_ALERT_IF_DBG
1576 #endif
1577 #ifndef CRITICAL
1578 #define CRITICAL NOBUG_CRITICAL
1579 #endif
1580 #ifndef CRITICAL_DBG
1581 #define CRITICAL_DBG NOBUG_CRITICAL_DBG
1582 #endif
1583 #ifndef CRITICAL_IF
1584 #define CRITICAL_IF NOBUG_CRITICAL_IF
1585 #endif
1586 #ifndef CRITICAL_IF_DBG
1587 #define CRITICAL_IF_DBG NOBUG_CRITICAL_IF_DBG
1588 #endif
1589 #ifndef ERROR
1590 #define ERROR NOBUG_ERROR
1591 #endif
1592 #ifndef ERROR_DBG
1593 #define ERROR_DBG NOBUG_ERROR_DBG
1594 #endif
1595 #ifndef ERROR_IF
1596 #define ERROR_IF NOBUG_ERROR_IF
1597 #endif
1598 #ifndef ERROR_IF_DBG
1599 #define ERROR_IF_DBG NOBUG_ERROR_IF_DBG
1600 #endif
1601 #ifndef WARN
1602 #define WARN NOBUG_WARN
1603 #endif
1604 #ifndef WARN_DBG
1605 #define WARN_DBG NOBUG_WARN_DBG
1606 #endif
1607 #ifndef WARN_IF
1608 #define WARN_IF NOBUG_WARN_IF
1609 #endif
1610 #ifndef WARN_IF_DBG
1611 #define WARN_IF_DBG NOBUG_WARN_IF_DBG
1612 #endif
1613 #ifndef INFO
1614 #define INFO NOBUG_INFO
1615 #endif
1616 #ifndef INFO_DBG
1617 #define INFO_DBG NOBUG_INFO_DBG
1618 #endif
1619 #ifndef INFO_IF
1620 #define INFO_IF NOBUG_INFO_IF
1621 #endif
1622 #ifndef INFO_IF_DBG
1623 #define INFO_IF_DBG NOBUG_INFO_IF_DBG
1624 #endif
1625 #ifndef NOTICE
1626 #define NOTICE NOBUG_NOTICE
1627 #endif
1628 #ifndef NOTICE_DBG
1629 #define NOTICE_DBG NOBUG_NOTICE_DBG
1630 #endif
1631 #ifndef NOTICE_IF
1632 #define NOTICE_IF NOBUG_NOTICE_IF
1633 #endif
1634 #ifndef NOTICE_IF_DBG
1635 #define NOTICE_IF_DBG NOBUG_NOTICE_IF_DBG
1636 #endif
1637 #ifndef TRACE
1638 #define TRACE NOBUG_TRACE
1639 #endif
1640 #ifndef TRACE_DBG
1641 #define TRACE_DBG NOBUG_TRACE_DBG
1642 #endif
1643 #ifndef TRACE_IF
1644 #define TRACE_IF NOBUG_TRACE_IF
1645 #endif
1646 #ifndef TRACE_IF_DBG
1647 #define TRACE_IF_DBG NOBUG_TRACE_IF_DBG
1648 #endif
1649 #ifndef BACKTRACE
1650 #define BACKTRACE NOBUG_BACKTRACE
1651 #endif
1652 #ifndef BACKTRACE_DBG
1653 #define BACKTRACE_DBG NOBUG_BACKTRACE_DBG
1654 #endif
1655 #ifndef DEPRECATED
1656 #define DEPRECATED NOBUG_DEPRECATED
1657 #endif
1658 #ifndef UNIMPLEMENTED
1659 #define UNIMPLEMENTED NOBUG_UNIMPLEMENTED
1660 #endif
1661 #ifndef FIXME
1662 #define FIXME NOBUG_FIXME
1663 #endif
1664 #ifndef TODO
1665 #define TODO NOBUG_TODO
1666 #endif
1667 #ifndef PLANNED
1668 #define PLANNED NOBUG_PLANNED
1669 #endif
1670 #ifndef NOTREACHED
1671 #define NOTREACHED NOBUG_NOTREACHED
1672 #endif
1673 #ifndef INJECT_GOODBAD
1674 #define INJECT_GOODBAD NOBUG_INJECT_GOODBAD
1675 #endif
1676 #ifndef INJECT_FAULT
1677 #define INJECT_FAULT NOBUG_INJECT_FAULT
1678 #endif
1679 #ifndef CLEANUP
1680 #define CLEANUP NOBUG_CLEANUP
1681 #endif
1682 #ifndef CHECKED
1683 #define CHECKED NOBUG_CHECKED
1684 #endif
1685 #ifndef UNCHECKED
1686 #define UNCHECKED NOBUG_UNCHECKED
1687 #endif
1688 #ifndef RESOURCE_ANNOUNCE
1689 #define RESOURCE_ANNOUNCE NOBUG_RESOURCE_ANNOUNCE
1690 #endif
1691 #ifndef RESOURCE_FORGET
1692 #define RESOURCE_FORGET NOBUG_RESOURCE_FORGET
1693 #endif
1694 #ifndef RESOURCE_ENTER
1695 #define RESOURCE_ENTER NOBUG_RESOURCE_ENTER
1696 #endif
1697 #ifndef RESOURCE_STATE
1698 #define RESOURCE_STATE NOBUG_RESOURCE_STATE
1699 #endif
1700 #ifndef RESOURCE_LEAVE
1701 #define RESOURCE_LEAVE NOBUG_RESOURCE_LEAVE
1702 #endif
1703 #ifndef RESOURCE_LEAVE_LOOKUP
1704 #define RESOURCE_LEAVE_LOOKUP NOBUG_RESOURCE_LEAVE_LOOKUP
1705 #endif
1706 #ifndef RESOURCE_HANDLE
1707 #define RESOURCE_HANDLE NOBUG_RESOURCE_HANDLE
1708 #endif
1709 #ifndef RESOURCE_HANDLE_INIT
1710 #define RESOURCE_HANDLE_INIT NOBUG_RESOURCE_HANDLE_INIT
1711 #endif
1712 #ifndef RESOURCE_DUMP
1713 #define RESOURCE_DUMP NOBUG_RESOURCE_DUMP
1714 #endif
1715 #ifndef RESOURCE_DUMP_IF
1716 #define RESOURCE_DUMP_IF NOBUG_RESOURCE_DUMP_IF
1717 #endif
1718 #ifndef RESOURCE_DUMPALL
1719 #define RESOURCE_DUMPALL NOBUG_RESOURCE_DUMPALL
1720 #endif
1721 #ifndef RESOURCE_DUMPALL_IF
1722 #define RESOURCE_DUMPALL_IF NOBUG_RESOURCE_DUMPALL_IF
1723 #endif
1724 #ifndef RESOURCE_LIST
1725 #define RESOURCE_LIST NOBUG_RESOURCE_LIST
1726 #endif
1727 #ifndef RESOURCE_LIST_IF
1728 #define RESOURCE_LIST_IF NOBUG_RESOURCE_LIST_IF
1729 #endif
1730 #endif /* NOBUG_DISABLE_SHORTNAMES */
1734 Tool macros
1736 #ifdef __GNUC__
1737 #define NOBUG_CLEANUP(fn) NOBUG_IF_ALPHA(__attribute__((cleanup(fn))))
1738 #else
1739 #define NOBUG_CLEANUP(fn)
1740 #endif
1743 //index.comma xref:NOBUG_ALPHA_COMMA[NOBUG_ALPHA_COMMA]:: append something after a comma in *ALPHA* builds
1744 //toolmacros [[NOBUG_ALPHA_COMMA]]
1745 //toolmacros .NOBUG_ALPHA_COMMA
1746 //toolmacros NOBUG_ALPHA_COMMA(something)
1747 //toolmacros NOBUG_ALPHA_COMMA_NULL
1748 //toolmacros
1749 //toolmacros Sometimes it is useful to have initializer code only in *ALPHA* builds, for example when you
1750 //toolmacros conditionally include resource handles only in *ALPHA* versions. An initializer can then
1751 //toolmacros use this macros to append a comman and something else only in *ALPHA* builds as in:
1752 //toolmacros struct foo = {"foo", "bar" NOBUG_ALPHA_COMMA_NULL };
1753 //toolmacros
1755 #define NOBUG_COMMA ,
1756 #define NOBUG_ALPHA_COMMA(something) NOBUG_IF_ALPHA(NOBUG_COMMA something)
1757 #define NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA(NULL)
1759 #define NOBUG_ONCE(code) \
1760 do { \
1761 static volatile int NOBUG_CAT(nobug_once_,__LINE__) = 0; \
1762 if (NOBUG_EXPECT_FALSE(!NOBUG_CAT(nobug_once_,__LINE__))) \
1764 NOBUG_CAT(nobug_once_,__LINE__) = 1; \
1765 code; \
1767 } while (0)
1769 #if __GNUC__
1770 #define NOBUG_EXPECT_FALSE(x) __builtin_expect(!!(x),0)
1771 #else
1772 #define NOBUG_EXPECT_FALSE(x) x
1773 #endif
1775 #define NOBUG_WHEN(when, ...) \
1776 do{ if (NOBUG_EXPECT_FALSE(when)){ __VA_ARGS__;}} while(0)
1779 //index.if xref:NOBUG_IF[NOBUG_IF_*]:: include code conditionally on build level
1780 //toolmacros [[NOBUG_IF]]
1781 //toolmacros .NOBUG_IF_*
1782 //toolmacros NOBUG_IF_ALPHA(...)
1783 //toolmacros NOBUG_IF_NOT_ALPHA(...)
1784 //toolmacros NOBUG_IF_BETA(...)
1785 //toolmacros NOBUG_IF_NOT_BETA(...)
1786 //toolmacros NOBUG_IF_RELEASE(...)
1787 //toolmacros NOBUG_IF_NOT_RELEASE(...)
1788 //toolmacros
1789 //toolmacros This macros allow one to conditionally include the code in '(...)' only if the
1790 //toolmacros criteria on the build level is met. If not, nothing gets substituted. Mostly used
1791 //toolmacros internally, but can also be used for custom things.
1792 //toolmacros
1794 #define NOBUG_IF_ALPHA(...) \
1795 NOBUG_IF(NOBUG_MODE_ALPHA, __VA_ARGS__) \
1797 #define NOBUG_IF_NOT_ALPHA(...) \
1798 NOBUG_IFNOT(NOBUG_MODE_ALPHA, __VA_ARGS__) \
1800 #define NOBUG_IF_BETA(...) \
1801 NOBUG_IF(NOBUG_MODE_BETA, __VA_ARGS__) \
1803 #define NOBUG_IF_NOT_BETA(...) \
1804 NOBUG_IFNOT(NOBUG_MODE_BETA, __VA_ARGS__) \
1806 #define NOBUG_IF_RELEASE(...) \
1807 NOBUG_IF(NOBUG_MODE_RELEASE, __VA_ARGS__) \
1809 #define NOBUG_IF_NOT_RELEASE(...) \
1810 NOBUG_IFNOT(NOBUG_MODE_RELEASE, __VA_ARGS__) \
1813 preprocessor hacks/metaprogramming
1816 #define NOBUG_IF(bool, ...) NOBUG_CAT(NOBUG_IF_,bool)(__VA_ARGS__)
1817 #define NOBUG_IF_1(...) __VA_ARGS__
1818 #define NOBUG_IF_0(...)
1820 #define NOBUG_IFNOT(bool, ...) NOBUG_CAT(NOBUG_IF_, NOBUG_NOT(bool))(__VA_ARGS__)
1822 #define NOBUG_NOT(bool) NOBUG_CAT(NOBUG_NOT_, bool)
1823 #define NOBUG_NOT_1 0
1824 #define NOBUG_NOT_0 1
1826 #define NOBUG_AND(a,b) NOBUG_CAT3(NOBUG_AND_, a, b)
1827 #define NOBUG_AND_00 0
1828 #define NOBUG_AND_01 0
1829 #define NOBUG_AND_10 0
1830 #define NOBUG_AND_11 1
1832 #define NOBUG_OR(a,b) NOBUG_CAT3(NOBUG_OR_, a, b)
1833 #define NOBUG_OR_00 0
1834 #define NOBUG_OR_01 1
1835 #define NOBUG_OR_10 1
1836 #define NOBUG_OR_11 1
1838 #define NOBUG_XOR(a,b) NOBUG_CAT( NOBUG_XOR_, NOBUG_CAT(a,b))
1839 #define NOBUG_XOR_00 0
1840 #define NOBUG_XOR_01 1
1841 #define NOBUG_XOR_10 1
1842 #define NOBUG_XOR_11 0
1844 #define NOBUG_CAT(a,b) NOBUG_CAT_(a,b)
1845 #define NOBUG_CAT_(a,b) a##b
1847 #define NOBUG_CAT3(a,b,c) NOBUG_CAT3_(a,b,c)
1848 #define NOBUG_CAT3_(a,b,c) a##b##c
1850 #define NOBUG_HEAD(head, ...) head
1851 #define NOBUG_TAIL(_, ...) , ## __VA_ARGS__
1853 #define NOBUG_STRINGIZE(s) NOBUG_STRINGIZE_(s)
1854 #define NOBUG_STRINGIZE_(s) #s
1858 LIBNOBUG DECLARATIONS
1860 #ifdef __cplusplus
1861 extern "C" {
1862 #endif
1865 envvar control
1867 enum nobug_log_targets
1869 NOBUG_TARGET_RINGBUFFER,
1870 NOBUG_TARGET_CONSOLE,
1871 NOBUG_TARGET_FILE,
1872 NOBUG_TARGET_SYSLOG,
1873 NOBUG_TARGET_APPLICATION
1876 struct nobug_flag
1878 const char* name;
1879 struct nobug_flag* parent;
1880 int initialized;
1881 int limits[5];
1882 struct nobug_ringbuffer* ringbuffer_target;
1883 FILE* console_target;
1884 FILE* file_target;
1888 nobug_env_parse_flag (const char* env, struct nobug_flag* flag, int default_target, int default_limit);
1891 nobug_env_init_flag (struct nobug_flag* flag, int default_target, int default_limit);
1895 ringbuffer
1897 struct nobug_ringbuffer
1899 char* pos;
1900 char* start;
1901 size_t size;
1902 size_t maxmsg;
1903 char name[256];
1906 enum nobug_ringbuffer_flags
1908 NOBUG_RINGBUFFER_DEFAULT, /* Default is to overwrite file and delete it on nobug_ringbuffer_destroy */
1909 NOBUG_RINGBUFFER_APPEND = 1, /* use existing backing file, append if possible */
1910 NOBUG_RINGBUFFER_TEMP = 2, /* unlink file instantly */
1911 NOBUG_RINGBUFFER_KEEP = 4 /* dont unlink the file at destroy */
1915 Note: some flags conflict (TEMP with KEEP) nobug_ringbuffer will not error on these but continue gracefully
1916 with sane (but undefined) semantics.
1918 struct nobug_ringbuffer*
1919 nobug_ringbuffer_init (struct nobug_ringbuffer* self, size_t size,
1920 const char * name, int flags);
1922 struct nobug_ringbuffer*
1923 nobug_ringbuffer_new (size_t size, const char * name, int flags);
1925 struct nobug_ringbuffer*
1926 nobug_ringbuffer_destroy (struct nobug_ringbuffer* self);
1928 void
1929 nobug_ringbuffer_delete (struct nobug_ringbuffer* self);
1932 nobug_ringbuffer_vprintf (struct nobug_ringbuffer* self, const char* fmt, va_list ap);
1935 nobug_ringbuffer_printf (struct nobug_ringbuffer* self, const char* fmt, ...);
1937 char*
1938 nobug_ringbuffer_prev (struct nobug_ringbuffer* self, char* pos);
1940 char*
1941 nobug_ringbuffer_next (struct nobug_ringbuffer* self, char* pos);
1944 nobug_ringbuffer_save (struct nobug_ringbuffer* self, FILE* out);
1947 nobug_ringbuffer_load (struct nobug_ringbuffer* self, FILE* in);
1949 char*
1950 nobug_ringbuffer_pos (struct nobug_ringbuffer* self);
1952 void
1953 nobug_ringbuffer_pop (struct nobug_ringbuffer* self);
1957 multithreading extras
1959 #if NOBUG_USE_PTHREAD
1961 struct nobug_tls_data
1963 const char * thread_id;
1964 struct nobug_resource_record* lock_stack;
1967 extern pthread_key_t nobug_tls_key;
1969 const char*
1970 nobug_thread_id_set (const char* name);
1972 const char*
1973 nobug_thread_id_get (void);
1975 extern pthread_mutex_t nobug_logging_mutex;
1976 extern pthread_mutex_t nobug_resource_mutex;
1977 #endif
1981 resource registry
1984 #if NOBUG_USE_PTHREAD
1985 #define NOBUG_RESOURCE_LOCK pthread_mutex_lock (&nobug_resource_mutex)
1986 #define NOBUG_RESOURCE_UNLOCK pthread_mutex_unlock (&nobug_resource_mutex)
1988 Note: errors are all fatal, we dont unlock the mutex when returning an error,
1989 this should be handled better in future but does not hurt
1991 #else
1992 #define NOBUG_RESOURCE_LOCK
1993 #define NOBUG_RESOURCE_UNLOCK
1994 #endif
1998 struct nobug_resource_record
2000 const char* type; /* type or state */
2001 const char* name; /* name */
2002 void* object_id; /* unique identifer, usually a this pointer or similar */
2003 void* data; /* tree of holders in resouces, backpointer to resource in holders */
2004 const char* extra; /* extra information, file/line usually */
2005 unsigned long counter; /* users or recursive enters */
2006 #if NOBUG_USE_PTHREAD
2007 const char* thread_id;
2008 struct nobug_resource_record* link; /* used by the deadlock detector */
2009 #endif
2012 enum nobug_resource_state
2014 NOBUG_RESOURCE_WAITING,
2015 //NOBUG_RESOURCE_TRYING,
2016 NOBUG_RESOURCE_EXCLUSIVE,
2017 NOBUG_RESOURCE_RECURSIVE
2020 extern void* nobug_resource_registry;
2022 extern const char* nobug_resource_error;
2024 extern const char* nobug_resource_states[];
2026 struct nobug_resource_record*
2027 nobug_resource_announce (const char* type, const char* name, const void* object_id, const char* extra);
2030 nobug_resource_forget (struct nobug_resource_record* node);
2032 struct nobug_resource_record*
2033 nobug_resource_find (const struct nobug_resource_record* resource, const void* object_id);
2035 struct nobug_resource_record*
2036 nobug_resource_enter (struct nobug_resource_record* resource,
2037 const char* name,
2038 const void* object_id,
2039 enum nobug_resource_state state,
2040 const char* extra);
2043 nobug_resource_state (struct nobug_resource_record* resource,
2044 enum nobug_resource_state state);
2047 nobug_resource_leave (struct nobug_resource_record* handle);
2050 struct nobug_resource_dump_context
2052 struct nobug_flag* flag;
2053 int level;
2054 const char* file;
2055 int line;
2056 const char* func;
2059 void
2060 nobug_resource_dump (struct nobug_resource_record* resource, struct nobug_resource_dump_context* context);
2062 void
2063 nobug_resource_dump_all (struct nobug_resource_dump_context* context);
2065 void
2066 nobug_resource_list (struct nobug_resource_dump_context* context);
2070 global config, data and defaults
2072 extern const char* nobug_resource_acquired;
2074 void nobug_init (void);
2076 void
2077 nobug_backtrace_glibc (void);
2079 void
2080 nobug_log (struct nobug_flag* flag, int lvl, const char* fmt, ...);
2082 typedef void (*nobug_application_cb)(struct nobug_flag* flag, int priority, const char *log, void* data);
2084 extern struct nobug_ringbuffer nobug_default_ringbuffer;
2085 extern FILE* nobug_default_file;
2086 extern struct nobug_flag nobug_flag_NOBUG_ON;
2087 extern struct nobug_flag nobug_flag_NOBUG_ANN;
2088 extern struct nobug_flag nobug_flag_nobug;
2089 extern unsigned long long nobug_counter;
2090 extern nobug_application_cb nobug_callback;
2091 extern void* nobug_callback_data;
2093 #ifdef __cplusplus
2094 } /* extern "C" */
2095 #endif
2097 #ifndef NOBUG_LIBNOBUG_C
2100 tag this translation unit as unchecked in ALPHA and BETA builds
2102 NOBUG_IF_NOT_RELEASE(NOBUG_UNCHECKED);
2104 #endif /* NOBUG_LIBNOBUG_C */
2105 #endif