fd98aa83f3d366ed6e61861b1f43bb71d90a9d26
[nobug] / src / nobug.h
1 /*
2  This file is part of the NoBug debugging library.
3
4  Copyright (C)
5    2006, 2007, 2008, 2009,      Christian Thaeter <ct@pipapo.org>
6    2010,                        Christian Thaeter <ct@pipapo.org>
7    2009,                        Francois Kubler <ih8tehuman@free.fr>
8
9  This program is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  GNU General Public License for more details.
18
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, contact Christian Thaeter <ct@pipapo.org>.
21 */
22 #ifndef NOBUG_H
23 #define NOBUG_H
24
25 #ifndef NOBUG_LIBNOBUG_C /* not when building libnobug */
26 #ifdef NDEBUG
27 #ifdef EBUG_ALPHA
28 #error NDEBUG incompatible with -DEBUG_ALPHA
29 #endif
30 #ifdef EBUG_BETA
31 #error NDEBUG incompatible with -DEBUG_BETA
32 #endif
33 #endif
34
35 #if defined(EBUG_ALPHA)
36 #       define NOBUG_MODE_ALPHA 1
37 #       define NOBUG_MODE_BETA 0
38 #       define NOBUG_MODE_RELEASE 0
39 #elif defined(EBUG_BETA)
40 #       define NOBUG_MODE_ALPHA 0
41 #       define NOBUG_MODE_BETA 1
42 #       define NOBUG_MODE_RELEASE 0
43 #elif defined(NDEBUG)
44 #       define NOBUG_MODE_ALPHA 0
45 #       define NOBUG_MODE_BETA 0
46 #       define NOBUG_MODE_RELEASE 1
47 #else
48 #error no debug level and no NDEBUG defined
49 #endif
50 #endif /* NOBUG_LIBNOBUG_C */
51
52 /*
53   HEADERS
54 */
55
56 #include <syslog.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <stdio.h>
60 #include <stdarg.h>
61
62 #ifdef HAVE_EXECINFO_H
63 # ifndef NOBUG_USE_EXECINFO
64 #  define NOBUG_USE_EXECINFO 1
65 # endif
66 #else
67 # undef NOBUG_USE_EXECINFO
68 # define NOBUG_USE_EXECINFO 0
69 #endif
70
71 #if NOBUG_USE_EXECINFO
72 #include <execinfo.h>
73 #endif
74
75 #if defined(HAVE_VALGRIND) && !defined(NVALGRIND)
76 # ifndef NOBUG_USE_VALGRIND
77 #  define NOBUG_USE_VALGRIND 1
78 # endif
79 #else
80 # undef NOBUG_USE_VALGRIND
81 # define NOBUG_USE_VALGRIND 0
82 #endif
83
84 #if NOBUG_USE_VALGRIND
85 #include <valgrind.h>
86 #endif
87
88 #ifdef HAVE_PTHREAD
89 # ifndef NOBUG_USE_PTHREAD
90 #  define NOBUG_USE_PTHREAD 1
91 # endif
92 #else
93 # ifdef NOBUG_USE_PTHREAD
94 #   undef NOBUG_USE_PTHREAD
95 # endif
96 # define NOBUG_USE_PTHREAD 0
97 #endif
98
99 #if NOBUG_USE_PTHREAD
100 #include <pthread.h>
101 #endif
102
103 /*
104 //assertions HEAD- Assertions;;
105 //assertions
106 //assertions PARA CHECK; CHECK; unnconditional assertion for testsuites
107 //assertions  CHECK(expr, ...)
108 //assertions  CHECK_IF(when, expr, ...)
109 //assertions
110 //assertions This assertion is never optimized out. Its main purpose is for implementing
111 //assertions testsuites where one want to assert tests independent of the build level
112 //assertions
113 */
114 #define NOBUG_CHECK(expr, ...) \
115   NOBUG_ASSERT_(expr, "CHECK", NOBUG_CONTEXT, ""__VA_ARGS__)
116
117 #define NOBUG_CHECK_IF(when, expr, ...) \
118   NOBUG_WHEN(when, NOBUG_CHECK(expr, ""__VA_ARGS__))
119
120
121 /*
122 //assertions PARA REQUIRE; REQUIRE; preconditions (input parameters)
123 //assertions  REQUIRE(expr, ...)
124 //assertions  REQUIRE_IF(when, expr, ...)
125 //assertions  NOBUG_REQUIRE_CTX(expr, context,...)
126 //assertions  NOBUG_REQUIRE_IF_CTX(when, expr, context, ...)
127 //assertions
128 //assertions Precondition (input) check. Use these macros to validate input a
129 //assertions function receives. The checks are enabled in *ALPHA* and *BETA* builds and
130 //assertions optimized out in *RELEASE* builds.
131 //assertions
132 */
133 #define NOBUG_REQUIRE(expr, ...) \
134   NOBUG_REQUIRE_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
135
136 #define NOBUG_REQUIRE_CTX(expr, context, ...) \
137   NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_(expr, "PRECONDITION", context, ""__VA_ARGS__))
138
139
140 #define NOBUG_REQUIRE_IF(when, expr, context,...) \
141   NOBUG_REQUIRE_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
142
143 #define NOBUG_REQUIRE_IF_CTX(when, expr, context,...)                   \
144   NOBUG_IF_NOT_RELEASE (                                                \
145     NOBUG_WHEN(when, NOBUG_REQUIRE_CTX(expr, context, ""__VA_ARGS__))   \
146   )
147
148
149 /*
150 //assertions PARA ENSURE; ENSURE; postconditions (computation outcomes)
151 //assertions  ENSURE(expr, ...)
152 //assertions  ENSURE_IF(when, expr, ...)
153 //assertions  NOBUG_ENSURE_CTX(expr, context, ...)
154 //assertions  NOBUG_ENSURE_IF_CTX(when, expr, context, ...)
155 //assertions
156 //assertions Postcondition (progress/output) check. Use these macros to validate the
157 //assertions data a function produces (example: return value). `ENSURE` is enabled
158 //assertions unconditionally in *ALPHA* builds and optimized out in *BETA* builds for
159 //assertions scopes which are tagged as `CHECKED`.
160 //assertions
161 //assertions The `ENSURE_IF` variants are enabled in *ALPHA* and *BETA* builds.
162 //assertions
163 //assertions In *RELEASE* builds this checks are
164 //assertions always optimized out, scopes tagged as `UNCHECKED` are not permitted.
165 //assertions
166 */
167 #define NOBUG_ENSURE(expr, ...) \
168   NOBUG_ENSURE_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
169
170 #define NOBUG_ENSURE_CTX(expr, context, ...)                            \
171   NOBUG_IF_ALPHA (NOBUG_ASSERT_(expr, "POSTCONDITION",                  \
172                                 context, ""__VA_ARGS__))                \
173   NOBUG_IF_BETA (                                                       \
174                  NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED,                     \
175                              NOBUG_ASSERT_(expr, "POSTCONDITION",       \
176                                            context, ""__VA_ARGS__)      \
177                              )                                          \
178   )
179
180
181 #define NOBUG_ENSURE_IF(when, expr, ...) \
182   NOBUG_ENSURE_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
183
184 #define NOBUG_ENSURE_IF_CTX(when, expr, context, ...) \
185   NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ENSURE(expr, context, ""__VA_ARGS__)))
186
187
188 /*
189 //assertions PARA ASSERT; ASSERT; generic assertion
190 //assertions  ASSERT(expr, ...)
191 //assertions  ASSERT_IF(when, expr, ...)
192 //assertions  NOBUG_ASSERT_CTX(expr, context, ...)
193 //assertions  NOBUG_ASSERT_IF_CTX(when, expr, context, ...)
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
202 */
203 #define NOBUG_ASSERT(expr, ...) \
204   NOBUG_ASSERT_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
205
206 #define NOBUG_ASSERT_CTX(expr, context, ...)                    \
207   NOBUG_IF_NOT_RELEASE(                                         \
208                        NOBUG_ASSERT_(expr, "ASSERTION",         \
209                                      context, ""__VA_ARGS__)    \
210   )
211
212
213 #define NOBUG_ASSERT_IF(when, expr, ...) \
214   NOBUG_ASSERT_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
215
216 #define NOBUG_ASSERT_IF_CTX(when, expr, context, ...) \
217   NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ASSERT_CTX(expr, context, ""__VA_ARGS__)))
218
219
220 /*
221 //assertions PARA assert; assert; C standard assertion
222 //assertions  assert(expr)
223 //assertions
224 //assertions NoBug overrides the standard `assert` macro, using `NOBUG_ASSERT`.
225 //assertions This is just a compatibility feature, its use is not suggested.
226 //assertions
227 */
228 #undef assert
229 #define assert(expr) NOBUG_ASSERT(expr)
230
231
232 /*
233   low level assert
234 */
235 #ifdef __GNUC__
236 #define NOBUG_ASSERT_(expr, what, context, fmt, ...)            \
237   NOBUG_WHEN (!(expr),                                          \
238               NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG,      \
239                           what, context, "(%s) " fmt,           \
240                           #expr, ## __VA_ARGS__);               \
241               NOBUG_BACKTRACE_CTX(context);                     \
242               NOBUG_ABORT                                       \
243   )
244 #else /* , ## __VA_ARGS__ eating the comma when the arglist is empty is a gcc extension, fallback for other compilers */
245 #define NOBUG_ASSERT_(expr, what, context, ...)                 \
246   NOBUG_WHEN (!(expr),                                          \
247               NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG,      \
248                           what, context,                        \
249                           ""__VA_ARGS__);                       \
250               NOBUG_BACKTRACE_CTX(context);                     \
251               NOBUG_ABORT                                       \
252   )
253 #endif
254
255 /*
256 //assertions PARA INVARIANT; INVARIANT; validate invariant state
257 //assertions  INVARIANT(type, pointer, depth)
258 //assertions  INVARIANT_IF(when,type, pointer, depth)
259 //assertions  INVARIANT_ASSERT(expr, ...)
260 //assertions
261 //assertions Checking invariants. You can provide more complex checking functions
262 //assertions which test the validity of datastructures. Invariants are only enabled
263 //assertions in *ALPHA* builds for scopes which are not tagged as `CHECKED` and
264 //assertions otherwise optimized out.
265 //assertions
266 //assertions  TODO: describe how to create invariant checks
267 //assertions
268 // 'invariant_context' must be passed in
269 */
270 #define NOBUG_INVARIANT(type, pointer, depth, extra)                                    \
271   NOBUG_IF_ALPHA(                                                                       \
272                  NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED,                                     \
273                              NOBUG_CAT3(nobug_, type,_invariant)(pointer, depth,        \
274                                                         NOBUG_CONTEXT, extra)           \
275                              )                                                          \
276   )
277
278
279 #define NOBUG_INVARIANT_IF(when, type, pointer, depth, extra)           \
280   NOBUG_IF_ALPHA(                                                       \
281     NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED,                                  \
282       NOBUG_WHEN (when,                                                 \
283                   NOBUG_CAT3(nobug_, type,_invariant)(pointer, depth,   \
284                                              NOBUG_CONTEXT,             \
285                                              extra)                     \
286                   )                                                     \
287   ))
288
289 #define NOBUG_INVARIANT_ASSERT(expr, ...) \
290  NOBUG_ASSERT_(expr, "INVARIANT", invariant_context, ""__VA_ARGS__)
291
292
293 /*
294   checked/unchecked tagged scopes
295  */
296 #define NOBUG_SCOPE_UNCHECKED NOBUG_CHECKED_VALUE == 0
297
298 #define NOBUG_CHECKED NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=1})
299
300 #define NOBUG_UNCHECKED                                                 \
301   NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=0})                    \
302   NOBUG_IF_RELEASE(NOBUG_UNCHECKED_NOT_ALLOWED_IN_RELEASE_BUILD)
303
304
305
306 /*TODO dump-level for flags instead limits[0]*/
307 /*
308 //dumpmacros PARA DUMP; DUMP; dumping datastructures
309 //dumpmacros  DUMP(flag, type, pointer, depth, extra)
310 //dumpmacros  DUMP_IF(when, flag, type, pointer, depth, extra)
311 //dumpmacros
312 //dumpmacros This macros call a datastructure dump of the object (`pointer`) in question.
313 //dumpmacros `DUMP` is only available in *ALPHA* and *BETA* builds, `DUMP_IF` is also
314 //dumpmacros enabled for the RELEASE builds.
315 //dumpmacros
316 //dumpmacros `extra` is a void* which is transparently passed around
317 //dumpmacros
318 */
319 #define NOBUG_DUMP(flag, type, pointer, depth, extra)                                                           \
320   NOBUG_IF_NOT_RELEASE(                                                                                         \
321                        NOBUG_WHEN (NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET],               \
322                                    NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth,  NOBUG_CONTEXT, extra)      \
323                                    )                                                                            \
324   )
325
326 #define NOBUG_DUMP_IF(when, flag, type, pointer, depth, extra)                                  \
327   NOBUG_WHEN (NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET] && when,            \
328               NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, NOBUG_CONTEXT, extra)            \
329   )
330
331
332 /*
333 //dumpmacros PARA DUMP_LOG; DUMP_LOG; logging helper for dumping
334 //dumpmacros  DUMP_LOG(...)
335 //dumpmacros  DUMP_LOG_IF(when, ...)
336 //dumpmacros
337 //dumpmacros Any output from `DUMP` handlers should be done by these macros.
338 //dumpmacros
339 //dumpmacros Dumping is by default done on level `LOG_DEBUG`, this can be overridden by
340 //dumpmacros defining `NOBUG_DUMP_LEVEL` to some other level.
341 //dumpmacros
342 // TODO document: 'dump_context' must be passed in
343 */
344
345 #define NOBUG_DUMP_LOG(...)                             \
346   NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL,   \
347               "DUMP", dump_context,                     \
348               ""__VA_ARGS__)
349
350 #define NOBUG_DUMP_LOG_IF(expr, ...)                                    \
351   NOBUG_WHEN (expr,                                                     \
352               NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL,       \
353                           "DUMP", dump_context,                         \
354                           ""__VA_ARGS__)                                \
355   )
356
357
358
359 #ifndef NOBUG_DUMP_LEVEL
360 #define NOBUG_DUMP_LEVEL LOG_DEBUG
361 #endif
362
363 /*
364 //logmacros HEAD- Logging Macros;;
365 //logmacros
366 //logmacros Logging targets a flag (except for `ECHO`) and is done at a log-level relating to syslog levels.
367 //logmacros
368 //logmacros NOTE: there is no logging macro for `LOG_EMERG`, this is only used by the assertions as fatal message
369 //logmacros
370 //logmacros PARA ECHO; ECHO; unconditional logging for tests
371 //logmacros  ECHO(...)
372 //logmacros
373 //logmacros Never optimized out, logs at LOG_NOTICE level. Its main purpose is for implementing
374 //logmacros testsuites where one want to print and log messages independent of the build level
375 //logmacros
376 */
377 #define NOBUG_ECHO(...) \
378   NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_NOTICE, "ECHO", NOBUG_CONTEXT, ""__VA_ARGS__)
379
380 /*
381 //logmacros PARA ALERT; ALERT; about to die
382 //logmacros  ALERT(flag, ...)
383 //logmacros  ALERT_IF(when, flag, ...)
384 //logmacros  NOBUG_ALERT_CTX(flag, context, ...)
385 //logmacros  NOBUG_ALERT_IF_CTX(when, flag, context, ...)
386 //logmacros
387 //logmacros This is the most critical condition an application might log. This might be used
388 //logmacros if an error occurs which can not be handled except a safe shutdown for example.
389 //logmacros
390 */
391 #define NOBUG_ALERT(flag, ...) \
392   NOBUG_ALERT_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
393
394 #define NOBUG_ALERT_IF(expr, flag, ...) \
395   NOBUG_ALERT_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
396
397
398 #define NOBUG_ALERT_CTX(flag, context, ...)      \
399   NOBUG_LOG_CTX(flag, LOG_ALERT, context, ""__VA_ARGS__)
400
401 #define NOBUG_ALERT_IF_CTX(expr, flag, context, ...)     \
402   NOBUG_LOG_IF(expr, flag, LOG_ALERT, context, ""__VA_ARGS__)
403
404
405
406 /*
407 //logmacros PARA CRITICAL; CRITICAL; can not continue
408 //logmacros  CRITICAL(flag, ...)
409 //logmacros  CRITICAL_IF(when, flag, ...)
410 //logmacros  NOBUG_CRITICAL_CTX(flag, context, ...)
411 //logmacros  NOBUG_CRITICAL_IF_CTX(when, flag, context, ...)
412 //logmacros
413 //logmacros An error which can not be handled occured but the application does not need to be
414 //logmacros shutdowen, perhaps waiting for an operator to fix the cause.
415 //logmacros
416 */
417 #define NOBUG_CRITICAL(flag, ...) \
418   NOBUG_CRITICAL_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
419
420 #define NOBUG_CRITICAL_CTX(flag, context, ...)   \
421   NOBUG_LOG_CTX(flag, LOG_CRIT, context, ""__VA_ARGS__)
422
423
424 #define NOBUG_CRITICAL_IF(expr, flag, ...) \
425   NOBUG_CRITICAL_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
426
427 #define NOBUG_CRITICAL_IF_CTX(expr, flag, context, ...)  \
428   NOBUG_LOG_IF_CTX(expr, flag, LOG_CRIT, context, ""__VA_ARGS__)
429
430
431 /*
432 //logmacros PARA ERROR; ERROR; something gone wrong
433 //logmacros  ERROR(flag, ...)
434 //logmacros  ERROR_IF(when, flag, ...)
435 //logmacros  NOBUG_ERROR_CTX(flag, context, ...)
436 //logmacros  NOBUG_ERROR_IF_CTX(when, flag, context, ...)
437 //logmacros
438 //logmacros Application takes a error handling brach
439 //logmacros
440 */
441 #define NOBUG_ERROR(flag, ...) \
442   NOBUG_ERROR_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
443
444 #define NOBUG_ERROR_CTX(flag, context, ...)      \
445   NOBUG_LOG_CTX(flag, LOG_ERR, context, ""__VA_ARGS__)
446
447
448 #define NOBUG_ERROR_IF(expr, flag, ...) \
449   NOBUG_ERROR_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
450
451 #define NOBUG_ERROR_IF_CTX(expr, flag, context, ...)     \
452   NOBUG_LOG_IF_CTX(expr, flag, LOG_ERR, context, ""__VA_ARGS__)
453
454
455 /*
456 //logmacros PARA WARN; WARN; unexpected fixable error
457 //logmacros  WARN(flag, ...)
458 //logmacros  WARN_IF(when, flag, ...)
459 //logmacros  NOBUG_WARN_CTX(flag, context, ...)
460 //logmacros  NOBUG_WARN_IF_CTX(when, flag, context, ...)
461 //logmacros
462 //logmacros Rare, handled but unexpected branch
463 //logmacros
464 */
465 #define NOBUG_WARN(flag, ...) \
466   NOBUG_WARN_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
467
468 #define NOBUG_WARN_CTX(flag, context, ...)       \
469   NOBUG_LOG_CTX(flag, LOG_WARNING, context, ""__VA_ARGS__)
470
471
472 #define NOBUG_WARN_IF(expr, flag, ...) \
473   NOBUG_WARN_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
474
475 #define NOBUG_WARN_IF_CTX(expr, flag, context, ...)      \
476   NOBUG_LOG_IF_CTX(expr, flag, LOG_WARNING, context, ""__VA_ARGS__)
477
478
479 /*
480 //logmacros PARA INFO; INFO; progress message
481 //logmacros  INFO(flag, ...)
482 //logmacros  INFO_IF(when, flag, ...)
483 //logmacros  NOBUG_INFO_CTX(flag, context, ...)
484 //logmacros  NOBUG_INFO_IF_CTX(when, flag, context, ...)
485 //logmacros
486 //logmacros Message about program progress
487 //logmacros
488 */
489 #define NOBUG_INFO(flag, ...) \
490   NOBUG_INFO_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
491
492 #define NOBUG_INFO_CTX(flag, context, ...)       \
493   NOBUG_LOG_CTX(flag, LOG_INFO, context, ""__VA_ARGS__)
494
495
496 #define NOBUG_INFO_IF(expr, flag, ...) \
497   NOBUG_INFO_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
498
499 #define NOBUG_INFO_IF_CTX(expr, flag, context, ...)      \
500   NOBUG_LOG_IF_CTX(expr, flag, LOG_INFO, context, ""__VA_ARGS__)
501
502
503 /*
504 //logmacros PARA NOTICE; NOTICE; detailed progress message
505 //logmacros  NOTICE(flag, ...)
506 //logmacros  NOTICE_IF(when, flag, ...)
507 //logmacros  NOBUG_NOTICE_CTX(flag, context, ...)
508 //logmacros  NOBUG_NOTICE_IF_CTX(when, flag, context, ...)
509 //logmacros
510 //logmacros More detailed progress message
511 //logmacros
512 */
513 #define NOBUG_NOTICE(flag, ...) \
514   NOBUG_NOTICE_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
515
516 #define NOBUG_NOTICE_CTX(flag, context, ...)     \
517   NOBUG_LOG_CTX(flag, LOG_NOTICE, context, ""__VA_ARGS__)
518
519
520 #define NOBUG_NOTICE_IF(expr, flag, ...) \
521   NOBUG_NOTICE_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
522
523 #define NOBUG_NOTICE_IF_CTX(expr, flag, context, ...)    \
524   NOBUG_LOG_IF_CTX(expr, flag, LOG_NOTICE, context, ""__VA_ARGS__)
525
526 /*
527 //logmacros PARA TRACE; TRACE; debugging level message
528 //logmacros  TRACE(flag, ...)
529 //logmacros  TRACE_IF(when, flag, ...)
530 //logmacros  NOBUG_TRACE_CTX(flag, context, ...)
531 //logmacros  NOBUG_TRACE_IF_CTX(when, flag, context, ...)
532 //logmacros
533 //logmacros Very fine grained messages
534 //logmacros
535 //logmacros NOTE: that `TRACE` corresponds to `LOG_DEBUG`, because using `DEBUG` could be ambiguous.
536 //logmacros
537 */
538 #define NOBUG_TRACE(flag, ...) \
539   NOBUG_TRACE_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
540
541 #define NOBUG_TRACE_CTX(flag, context, ...)      \
542   NOBUG_LOG_CTX(flag, LOG_DEBUG, context, ""__VA_ARGS__)
543
544
545 #define NOBUG_TRACE_IF(expr, flag, ...) \
546   NOBUG_TRACE_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
547
548 #define NOBUG_TRACE_IF_CTX(expr, flag, context, ...)     \
549   NOBUG_LOG_IF_CTX(expr, flag, LOG_DEBUG, context, ""__VA_ARGS__)
550
551
552 /*
553 //logmacros PARA LOG; LOG; generic logging
554 //logmacros  NOBUG_LOG_CTX(flag, lvl, context, ...)
555 //logmacros  NOBUG_LOG_IF_CTX(when, flag, lvl, context, ...)
556 //logmacros
557 //logmacros Generic logging macro which takes the level explicitly,
558 //logmacros avoid this, unless you implement your own logging facilities.
559 //logmacros
560 */
561 #define NOBUG_LOG_CTX(flag, lvl, context, ...) \
562   NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LVL(lvl), context, ""__VA_ARGS__)
563
564
565 #define NOBUG_LOG_IF_CTX(expr, flag, lvl, context, ...) \
566   NOBUG_WHEN (expr,                                     \
567     NOBUG_LOG_CTX(flag, lvl, context, ""__VA_ARGS__)    \
568   )
569
570
571 /*
572   low level logging handler
573
574   Note: all fmt concatenations use an empty string ""__VA_ARG__
575         except this one which must use a single space " " before __VA_ARGS__ for formatting the log message correctly (and silence a gcc warning)
576 */
577 #define NOBUG_LOG_(flag, lvl, what, context, ...)                                               \
578   NOBUG_WHEN (lvl <= NOBUG_LOG_BASELIMIT && lvl <= (flag)->limits[NOBUG_TARGET_RINGBUFFER],     \
579               nobug_log (flag, lvl, what, context, " "__VA_ARGS__)                              \
580   )
581
582
583 #define NOBUG_LVL(lvl) NOBUG_LVL_##lvl
584 #define NOBUG_LVL_0 "EMERG"
585 #define NOBUG_LVL_1 "ALERT"
586 #define NOBUG_LVL_2 "CRIT"
587 #define NOBUG_LVL_3 "ERR"
588 #define NOBUG_LVL_4 "WARNING"
589 #define NOBUG_LVL_5 "NOTICE"
590 #define NOBUG_LVL_6 "INFO"
591 #define NOBUG_LVL_7 "TRACE"
592
593 /*
594 //logmacros PARA LOG_BASELIMIT; LOG_BASELIMIT; minimum compliled-in logging limit
595 //logmacros  NOBUG_LOG_BASELIMIT_ALPHA
596 //logmacros  NOBUG_LOG_BASELIMIT_BETA
597 //logmacros  NOBUG_LOG_BASELIMIT_RELEASE
598 //logmacros  NOBUG_LOG_BASELIMIT
599 //logmacros
600 //logmacros anything more detailed than this base limits will be optimized out.
601 //logmacros This is used to reduce the logging overhead for *RELEASE* builds.
602 //logmacros By default the limit is set to `LOG_DEBUG` for *ALPHA* and *BETA*
603 //logmacros builds, so all logging is retained and `LOG_NOTICE` in *RELEASE*
604 //logmacros builds to log the application progress only coarsely then.
605 //logmacros
606 //logmacros This macros can be defined before including 'nobug.h' to some other
607 //logmacros log level (as defined in 'syslog.h').
608 //logmacros
609 */
610 #ifndef NOBUG_LOG_BASELIMIT_ALPHA
611 #define NOBUG_LOG_BASELIMIT_ALPHA LOG_DEBUG
612 #endif
613
614 #ifndef NOBUG_LOG_BASELIMIT_BETA
615 #define NOBUG_LOG_BASELIMIT_BETA LOG_DEBUG
616 #endif
617
618 #ifndef NOBUG_LOG_BASELIMIT_RELEASE
619 #define NOBUG_LOG_BASELIMIT_RELEASE LOG_NOTICE
620 #endif
621
622 #ifndef NOBUG_LOG_BASELIMIT
623 #define NOBUG_LOG_BASELIMIT                     \
624   NOBUG_IF_ALPHA(NOBUG_LOG_BASELIMIT_ALPHA)     \
625   NOBUG_IF_BETA(NOBUG_LOG_BASELIMIT_BETA)       \
626   NOBUG_IF_RELEASE(NOBUG_LOG_BASELIMIT_RELEASE)
627 #endif
628
629 /*
630 //srccontext HEAD~ Source Contexts; NOBUG_CONTEXT; pass information about the source location
631 //srccontext  NOBUG_CONTEXT
632 //srccontext  NOBUG_CONTEXT_NOFUNC
633 //srccontext
634 //srccontext NoBug passes information about the source location of a given statement in
635 //srccontext `const struct nobug_context` structures. These can be generated with
636 //srccontext `NOBUG_CONTEXT` or `NOBUG_CONTEXT_NOFUNC`. The later one doesn't define a
637 //srccontext function name and must be used when the function context is not available
638 //srccontext like in static initialization etc..
639 //srccontext
640 */
641
642 #define NOBUG_CONTEXT ((const struct nobug_context){__FILE__, __LINE__, __func__})
643
644 #define NOBUG_CONTEXT_NOFUNC ((const struct nobug_context){__FILE__, __LINE__, "-"})
645
646 #define NOBUG_CONTEXT_NIL ((const struct nobug_context){"-", 0, "-"})
647
648
649 /*
650 //annotations HEAD- Source Annotations;;
651 //annotations
652 //annotations One can tag features as:
653 //annotations
654 */
655
656 /*
657                 alpha           beta            release
658 DEPRECATED      log             nothing         wont compile
659
660 //annotations PARA DEPRECATED; DEPRECATED; to be discarded in future
661 //annotations  DEPRECATED(...)
662 //annotations
663 //annotations Something which shouldn't be used in future
664 //annotations
665 */
666 #define NOBUG_DEPRECATED(...)                                                   \
667   NOBUG_IF_ALPHA(NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_WARN,                    \
668                             "DEPRECATED", NOBUG_CONTEXT, ""__VA_ARGS__)         \
669                  )                                                              \
670   NOBUG_IF_RELEASE(NOBUG_DEPRECATED_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
671
672
673 /*
674                 alpha           beta            release
675 UNIMPLEMENTED   abort           abort           wont compile
676
677 //annotations PARA UNIMPLEMENTED; UNIMPLEMENTED; not yet implemented
678 //annotations  UNIMPLEMENTED(...)
679 //annotations
680 //annotations not yet finished feature
681 //annotations
682 */
683 #define NOBUG_UNIMPLEMENTED(...)                                                        \
684   NOBUG_IF_NOT_RELEASE ( do {                                                           \
685       NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_EMERG,                                     \
686                   "UNIMPLEMENTED", NOBUG_CONTEXT, ""__VA_ARGS__);                       \
687          NOBUG_ABORT;                                                                   \
688     } while (0))                                                                        \
689  NOBUG_IF_RELEASE( NOBUG_UNIMPLEMENTED_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
690
691
692 /*
693                 alpha           beta            release
694 FIXME           log             wont compile    wont compile
695
696 //annotations PARA FIXME; FIXME; known bug
697 //annotations  FIXME(...)
698 //annotations
699 //annotations known bug to be fixed later
700 //annotations
701 */
702 #define NOBUG_FIXME(...)                                                                \
703   NOBUG_IF_ALPHA( NOBUG_ONCE( NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_ALERT,              \
704                                          "FIXME", NOBUG_CONTEXT, ""__VA_ARGS__)))       \
705   NOBUG_IF_BETA( NOBUG_FIXME_NOT_ALLOWED_IN_BETA_BUILD(__VA_ARGS__))                    \
706   NOBUG_IF_RELEASE( NOBUG_FIXME_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
707
708
709 /*
710                 alpha           beta            release
711 TODO            log             log             wont compile
712
713 //annotations PARA TODO; TODO; things to be done
714 //annotations  TODO(...)
715 //annotations
716 //annotations enhancement to be done soon
717 //annotations
718 */
719 #define NOBUG_TODO(...)                                                         \
720   NOBUG_IF_NOT_RELEASE (                                                        \
721          NOBUG_ONCE (                                                           \
722          NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_NOTICE,                         \
723                      "TODO", NOBUG_CONTEXT, ""__VA_ARGS__);                     \
724          ))                                                                     \
725   NOBUG_IF_RELEASE(NOBUG_TODO_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
726
727
728 /*
729                 alpha           beta            release
730 PLANNED         log             nothing         nothing
731
732 //annotations PARA PLANNED; PLANNED; ideas for future
733 //annotations  PLANNED(...)
734 //annotations
735 //annotations future enhancement
736 //annotations
737 */
738 #define NOBUG_PLANNED(...)                                                              \
739 NOBUG_IF_ALPHA( NOBUG_ONCE(NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_INFO,                 \
740                                        "PLANNED", NOBUG_CONTEXT, ""__VA_ARGS__)))
741
742
743 /*
744                 alpha           beta            release
745 NOTREACHED      abort           abort           nothing
746
747 //annotations PARA NOTREACHED; NOTREACHED; code path never taken
748 //annotations  NOTREACHED(...)
749 //annotations
750 //annotations used to tag code-path which shall be never executed.
751 //annotations
752 */
753 #define NOBUG_NOTREACHED(...)                                   \
754   NOBUG_IF_NOT_RELEASE( do {                                    \
755       NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG,             \
756                   "NOTREACHED", NOBUG_CONTEXT, ""__VA_ARGS__);  \
757       NOBUG_ABORT;                                              \
758     } while (0))
759
760
761 /*
762 //annotations PARA ELSE_NOTREACHED; ELSE_NOTREACHED; alternative never taken
763 //annotations  ELSE_NOTREACHED(...)
764 //annotations
765 //annotations same as `else NOTREACHED()`, but wholly optimized out in release builds.
766 //annotations
767 */
768 #define NOBUG_ELSE_NOTREACHED(...)                                      \
769   NOBUG_IF_NOT_RELEASE( else do {                                       \
770       NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG,                     \
771                   "ELSE_NOTREACHED", NOBUG_CONTEXT, ""__VA_ARGS__);     \
772       NOBUG_ABORT;                                                      \
773     } while (0))
774
775
776 /*
777 //faultinjection HEAD- Fault injection;;
778 //faultinjection
779 //faultinjection NoBug has some macros which can be used to simulate errorneous behaviour:
780 //faultinjection
781 //faultinjection PARA INJECT_GOODBAD; INJECT_GOODBAD; fault injection expression
782 //faultinjection  INJECT_GOODBAD(expr, good, bad)
783 //faultinjection
784 //faultinjection substitutes to an expression and returns good when expr is false and
785 //faultinjection bad when expr is true. In BETA and RELEASE builds 'good' is always returned.
786 //faultinjection
787 */
788 #define NOBUG_INJECT_GOODBAD(expr, good, bad)                           \
789   NOBUG_IF_ALPHA((expr)?({NOBUG_INJECT_LOG(#expr": "#bad);bad;}):good)  \
790   NOBUG_IF_NOT_ALPHA(good)
791
792
793 /*
794 //faultinjection PARA INJECT_FAULT; INJECT_FAULT; fault injection statement
795 //faultinjection  INJECT_FAULT(expr, bad)
796 //faultinjection
797 //faultinjection substitutes to a statement which executes 'bad'
798 //faultinjection when expr is true. Optimitzed out in BETA and RELEASE builds.
799 //faultinjection
800 */
801 #define NOBUG_INJECT_FAULT(expr, bad)                                   \
802   NOBUG_IF_ALPHA(NOBUG_WHEN(expr,NOBUG_INJECT_LOG(#expr": "#bad); bad))
803
804
805 /*
806 //faultinjection PARA INJECT_LEVEL; INJECT_LEVEL; log level for fault injection
807 //faultinjection In both cases, when a fault is injected it will be logged at
808 //faultinjection `NOBUG_INJECT_LEVEL` (default: `LOG_NOTICE`). This can be defined
809 //faultinjection before including 'nobug.h' to override it.
810 //faultinjection
811 */
812 #define NOBUG_INJECT_LOG(msg)                           \
813   NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_INJECT_LEVEL, \
814               "INJECT_FAULT", NOBUG_CONTEXT,            \
815               msg)
816
817
818 #ifndef NOBUG_INJECT_LEVEL
819 #define NOBUG_INJECT_LEVEL LOG_NOTICE
820 #endif
821
822
823 /*
824   Flag handling
825 */
826 #define NOBUG_FLAG(name) NOBUG_CAT(nobug_flag_, name)
827
828 #define NOBUG_DECLARE_FLAG(name) extern struct nobug_flag NOBUG_FLAG(name)
829
830
831 #define NOBUG_DEFINE_FLAG(name)                                                                                 \
832   NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name))                                                           \
833   NOBUG_FLAG_IF_NOT_DECLAREONLY(                                                                                \
834   struct nobug_flag NOBUG_FLAG(name) =                                                                          \
835     NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0,                                                                 \
836           {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO},  &nobug_default_ringbuffer, NULL,NULL})               \
837     NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0,                                                                  \
838           {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL})   \
839     NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0,                                                               \
840           {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL})           \
841   )
842
843
844 #define NOBUG_DEFINE_FLAG_PARENT(name, parent)                                                                  \
845   NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name))                                                           \
846   NOBUG_FLAG_IF_NOT_DECLAREONLY(                                                                                \
847   NOBUG_DECLARE_FLAG(parent);                                                                                   \
848   struct nobug_flag NOBUG_FLAG(name) =                                                                          \
849     NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0,                                                  \
850           {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO},  &nobug_default_ringbuffer, NULL,NULL})               \
851     NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0,                                                   \
852           {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL})   \
853     NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0,                                                \
854           {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL})           \
855   )
856
857
858 #define NOBUG_DEFINE_FLAG_LIMIT(name, limit)                                                                    \
859   NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name))                                                           \
860   NOBUG_FLAG_IF_NOT_DECLAREONLY(                                                                                \
861   struct nobug_flag NOBUG_FLAG(name) =                                                                          \
862     NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0,                                                                 \
863           {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL})                   \
864     NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0,                                                                  \
865           {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL})        \
866     NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0,                                                               \
867           {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL})                 \
868   )
869
870
871 #define NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, limit)                                                     \
872   NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name))                                                           \
873   NOBUG_FLAG_IF_NOT_DECLAREONLY(                                                                                \
874   NOBUG_DECLARE_FLAG(parent);                                                                                   \
875   struct nobug_flag NOBUG_FLAG(name) =                                                                          \
876     NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0,                                                  \
877           {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL})                   \
878     NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0,                                                   \
879           {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL})        \
880     NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0,                                                \
881           {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL})                 \
882   )
883
884
885 #define NOBUG_INIT_FLAG(name)                                                   \
886   nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, NOBUG_LOG_LIMIT, NOBUG_CONTEXT_NOFUNC)
887
888
889 #define NOBUG_INIT_FLAG_LIMIT(name, default)                                    \
890   nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, default, NOBUG_CONTEXT_NOFUNC)
891
892
893 #define NOBUG_CPP_DEFINE_FLAG(name)                             \
894   NOBUG_FLAG_IF_DECLAREONLY(                                    \
895   NOBUG_DECLARE_FLAG(name);                                     \
896   extern int nobug_cppflag_##name                               \
897   )                                                             \
898   NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(                            \
899   NOBUG_DEFINE_FLAG(name);                                      \
900   int nobug_cppflag_##name = NOBUG_INIT_FLAG(name)              \
901   )
902
903
904 #define NOBUG_CPP_DEFINE_FLAG_PARENT(name, parent)              \
905   NOBUG_FLAG_IF_DECLAREONLY(                                    \
906   NOBUG_DECLARE_FLAG(name);                                     \
907   extern int nobug_cppflag_##name                               \
908   )                                                             \
909   NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(                            \
910   NOBUG_DEFINE_FLAG_PARENT(name, parent);                       \
911   int nobug_cppflag_##name = NOBUG_INIT_FLAG(name)              \
912   )
913
914
915 #define NOBUG_CPP_DEFINE_FLAG_LIMIT(name, default)                      \
916   NOBUG_FLAG_IF_DECLAREONLY(                                            \
917   NOBUG_DECLARE_FLAG(name);                                             \
918   extern int nobug_cppflag_##name                                       \
919   )                                                                     \
920   NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(                                    \
921   NOBUG_DEFINE_FLAG_LIMIT(name, default);                               \
922   int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default)       \
923   )
924
925
926 #define NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT(name, parent, default)       \
927   NOBUG_FLAG_IF_DECLAREONLY(                                            \
928   NOBUG_DECLARE_FLAG(name);                                             \
929   extern int nobug_cppflag_##name                                       \
930   )                                                                     \
931   NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(                                    \
932   NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, default);                \
933   int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default)       \
934   )
935
936
937 #ifndef NOBUG_DECLARE_ONLY
938 #define NOBUG_DECLARE_ONLY 0
939 #endif
940
941 #define NOBUG_FLAG_IF_DECLAREONLY(...)          \
942   NOBUG_IF(NOBUG_DECLARE_ONLY, __VA_ARGS__)
943
944 #define NOBUG_FLAG_IF_NOT_DECLAREONLY(...)      \
945   NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
946
947 #ifdef __cplusplus
948 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...)      \
949   NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
950 #else
951 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...)      \
952   NOBUG_IFNOT(NOBUG_DECLARE_ONLY, NOBUG_ERROR_CANT_DEFINE_AUTOINITIALIZED_CPP_FLAGS_IN_C)
953 #endif
954
955 #ifndef NOBUG_LOG_LIMIT_ALPHA
956 #       define NOBUG_LOG_LIMIT_ALPHA LOG_INFO
957 #endif
958 #ifndef NOBUG_LOG_LIMIT_BETA
959 #       define NOBUG_LOG_LIMIT_BETA LOG_WARNING
960 #endif
961 #ifndef NOBUG_LOG_LIMIT_RELEASE
962 #       define NOBUG_LOG_LIMIT_RELEASE LOG_CRIT
963 #endif
964
965 #ifndef NOBUG_LOG_LIMIT
966 #       define NOBUG_LOG_LIMIT                  \
967   NOBUG_IF_ALPHA( NOBUG_LOG_LIMIT_ALPHA)        \
968   NOBUG_IF_BETA( NOBUG_LOG_LIMIT_BETA)          \
969   NOBUG_IF_RELEASE( NOBUG_LOG_LIMIT_RELEASE)
970 #endif
971
972 #ifndef NOBUG_LOG_TARGET_ALPHA
973 #       define NOBUG_LOG_TARGET_ALPHA NOBUG_TARGET_CONSOLE
974 #endif
975 #ifndef NOBUG_LOG_TARGET_BETA
976 #       define NOBUG_LOG_TARGET_BETA NOBUG_TARGET_FILE
977 #endif
978 #ifndef NOBUG_LOG_TARGET_RELEASE
979 #       define NOBUG_LOG_TARGET_RELEASE NOBUG_TARGET_SYSLOG
980 #endif
981
982 #ifndef NOBUG_LOG_TARGET
983 #       define NOBUG_LOG_TARGET                 \
984   NOBUG_IF_ALPHA( NOBUG_LOG_TARGET_ALPHA)       \
985   NOBUG_IF_BETA( NOBUG_LOG_TARGET_BETA)         \
986   NOBUG_IF_RELEASE( NOBUG_LOG_TARGET_RELEASE)
987 #endif
988
989 #define NOBUG_SET_LIMIT(flag, min)              \
990   NOBUG_IF_NOT_RELEASE( NOBUG_FLAG(flag) = (min))
991
992
993 /*
994 //resourcemacros HEAD~ Resource tracking macros;;
995 //resourcemacros
996 //resourcemacros INDEX RESOURCE_LOGGING; RESOURCE_LOGGING; switch resource logging on and off
997 //resourcemacros INDEX RESOURCE_LOG_LEVEL; RESOURCE_LOG_LEVEL; select the log level for resource logging
998 //resourcemacros
999 //resourcemacros Unless the user defines `NOBUG_RESOURCE_LOGGING` to 0 each of the above macros
1000 //resourcemacros will emit a log message at `NOBUG_RESOURCE_LOG_LEVEL` which defaults to
1001 //resourcemacros `LOG_DEBUG`.
1002 //resourcemacros
1003 */
1004 #ifndef NOBUG_RESOURCE_LOGGING
1005 #define NOBUG_RESOURCE_LOGGING 1
1006 #endif
1007
1008 #ifndef NOBUG_RESOURCE_LOG_LEVEL
1009 #define NOBUG_RESOURCE_LOG_LEVEL LOG_DEBUG
1010 #endif
1011
1012
1013 /*
1014 //resourcemacros PARA RESOURCE_HANDLE; RESOURCE_HANDLE; define resource handles
1015 //resourcemacros  RESOURCE_HANDLE(name)
1016 //resourcemacros  RESOURCE_HANDLE_INIT(name)
1017 //resourcemacros  RESOURCE_USER(name)
1018 //resourcemacros  RESOURCE_USER_INIT(name)
1019 //resourcemacros
1020 //resourcemacros Define and initialize handles for to track resources.
1021 //resourcemacros
1022 //resourcemacros  `name`::
1023 //resourcemacros      identifer to be used for the handle
1024 //resourcemacros
1025 //resourcemacros There are two kinds of handles, each resource itself is abstracted with a
1026 //resourcemacros `RESOURCE_HANDLE` and every access to this resources is tracked through a
1027 //resourcemacros `RESOURCE_USER` handle. These macros takes care that the declaration is optimized
1028 //resourcemacros out in the same manner as the rest of the resource tracker would be disabled.
1029 //resourcemacros You can still instantiate handles as `struct nobug_resource_record*` or
1030 //resourcemacros `struct nobug_resource_user*` in structures which must have a constant size
1031 //resourcemacros unconditional of the build level. The two `*_INIT` macros can be used to initialize
1032 //resourcemacros resource handles and are optimized out when the resource tracker gets disabled.
1033 //resourcemacros
1034 */
1035 #define NOBUG_RESOURCE_HANDLE(handle) \
1036   NOBUG_IF_ALPHA(struct nobug_resource_record* handle)
1037
1038 #define NOBUG_RESOURCE_HANDLE_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
1039
1040 #define NOBUG_RESOURCE_USER(handle) \
1041   NOBUG_IF_ALPHA(struct nobug_resource_user* handle)
1042
1043 #define NOBUG_RESOURCE_USER_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
1044
1045
1046 /*
1047 //resourcemacros PARA RESOURCE_ANNOUNCE; RESOURCE_ANNOUNCE; publish new resources
1048 //resourcemacros  RESOURCE_ANNOUNCE(flag, type, name, identifier, handle)
1049 //resourcemacros  NOBUG_RESOURCE_ANNOUNCE_RAW(flagptr, type, name, ptr, handle)
1050 //resourcemacros  NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(flagptr, type, name, ptr, handle, context)
1051 //resourcemacros
1052 //resourcemacros Publishes resources.
1053 //resourcemacros
1054 //resourcemacros  `flag`::
1055 //resourcemacros      the NoBug flag name which turns logging on for this macro
1056 //resourcemacros  `type`::
1057 //resourcemacros      a string which should denote the domain of the resource,
1058 //resourcemacros      examples are "file", "mutex", "lock", "database" and so on
1059 //resourcemacros  `name`::
1060 //resourcemacros      the actual name of a named resource this as string which
1061 //resourcemacros      together with type forms a unique identifier of the resource. `type` and
1062 //resourcemacros      `name` must be available through the entire lifetime of the resource, using
1063 //resourcemacros      literal strings is recommended
1064 //resourcemacros  `identifier`::
1065 //resourcemacros      a pointer which should be unique for this resource, any
1066 //resourcemacros      kind of pointer will suffice, it is only used for identification. In
1067 //resourcemacros      multithreaded applications the thread identifier becomes an additional
1068 //resourcemacros      identifier
1069 //resourcemacros  `handle`::
1070 //resourcemacros      a `NOBUG_RESOURCE_HANDLE` which will be initialized to point to
1071 //resourcemacros      the newly created resource.
1072 //resourcemacros
1073 //resourcemacros Resources must be unique, it is a fatal error when a resource it tried to be
1074 //resourcemacros announced more than one time.
1075 //resourcemacros
1076 //resourcemacros 'RESOURCE_ANNOUNCE()' acts like the head of a C loop statement, it ties to the following
1077 //resourcemacros (block-) statement. Leaving and the user defined following statement are atomic.
1078 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1079 //resourcemacros
1080 */
1081 #define NOBUG_RESOURCE_ANNOUNCE(flag, type, name, ptr, handle) \
1082   NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(&NOBUG_FLAG(flag), type, name, ptr, handle, NOBUG_CONTEXT)
1083
1084
1085 #define NOBUG_RESOURCE_ANNOUNCE_RAW(flag, type, name, ptr, handle) \
1086   NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(flag, type, name, ptr, handle, NOBUG_CONTEXT)
1087
1088
1089 #define NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(flag, type, name, ptr, handle, context)                                 \
1090   NOBUG_IF_NOT_RELEASE( for (                                                                                   \
1091        int NOBUG_CLEANUP(nobug_section_cleaned) section_ =                                                      \
1092          ({                                                                                                     \
1093            NOBUG_REQUIRE_CTX(!handle, context, "Announced resource handle not initialized");                    \
1094            NOBUG_IF(NOBUG_RESOURCE_LOGGING,                                                                     \
1095                     NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL,                                                  \
1096                                "RESOURCE_ANNOUNCE", context,                                                    \
1097                                "%s: %s@%p", type, name, ptr);)                                                  \
1098            NOBUG_IF_ALPHA (                                                                                     \
1099                            NOBUG_RESOURCE_ASSERT_CTX(handle = nobug_resource_announce (type, name,              \
1100                                                                                        (const void*)ptr,        \
1101                                                                                        context),                \
1102                                                      "RESOURCE_ASSERT_ANNOUNCE", context,                       \
1103                                                      "%s: %s@%p %s", type, name, ptr, nobug_resource_error);    \
1104            )                                                                                                    \
1105              1;                                                                                                 \
1106          });                                                                                                    \
1107        section_;                                                                                                \
1108        ({                                                                                                       \
1109          NOBUG_IF_ALPHA (nobug_resource_announce_complete ();)                                                  \
1110          section_ = 0;                                                                                          \
1111        })))
1112
1113
1114 /*
1115 //resourcemacros PARA RESOURCE_FORGET; RESOURCE_FORGET; remove resources
1116 //resourcemacros  RESOURCE_FORGET(flag, handle)
1117 //resourcemacros  NOBUG_RESOURCE_FORGET_RAW(flagptr, handle)
1118 //resourcemacros  NOBUG_RESOURCE_FORGET_RAW_CTX(flagptr, handle, context)
1119 //resourcemacros
1120 //resourcemacros Removes resources that have become unavailable from the registry.
1121 //resourcemacros
1122 //resourcemacros `flag`::
1123 //resourcemacros     the NoBug flag which turns logging on for this macro
1124 //resourcemacros `handle`::
1125 //resourcemacros     the `NOBUG_RESOURCE_HANDLE` used to track this resource
1126 //resourcemacros
1127 //resourcemacros The resource must still exist and no users must be attached to it, else a fatal
1128 //resourcemacros error is raised.
1129 //resourcemacros
1130 //resourcemacros 'RESOURCE_FORGET()' acts like the head of a C loop statement, it ties to the following
1131 //resourcemacros (block-) statement. Leaving and the user defined following statement are atomic.
1132 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1133 //resourcemacros
1134 */
1135 #define NOBUG_RESOURCE_FORGET(flag, handle) \
1136   NOBUG_RESOURCE_FORGET_RAW_CTX(&NOBUG_FLAG(flag), handle, NOBUG_CONTEXT)
1137
1138 #define NOBUG_RESOURCE_FORGET_RAW(flag, handle) \
1139   NOBUG_RESOURCE_FORGET_RAW_CTX(flag, handle, NOBUG_CONTEXT)
1140
1141 #define NOBUG_RESOURCE_FORGET_RAW_CTX(flag, handle, context)                            \
1142   NOBUG_IF_NOT_RELEASE( for (                                                           \
1143     int NOBUG_CLEANUP(nobug_section_cleaned) section_ =                                 \
1144       ({                                                                                \
1145         NOBUG_IF(NOBUG_RESOURCE_LOGGING,                                                \
1146                  NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL,                             \
1147                             "RESOURCE_FORGET", context, "%s: %s@%p",                    \
1148                             (handle)?(handle)->type:"",                                 \
1149                             (handle)?(handle)->hdr.name:"",                             \
1150                             (handle)?(handle)->object_id:NULL);)                        \
1151         1;                                                                              \
1152       });                                                                               \
1153       section_;                                                                         \
1154       ({                                                                                \
1155         NOBUG_IF_ALPHA (                                                                \
1156           NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_forget (handle),                     \
1157                                 "RESOURCE_ASSERT_FORGET", context, "%s: %s@%p: %s",     \
1158                                 (handle)?(handle)->type:"",                             \
1159                                 (handle)?(handle)->hdr.name:"",                         \
1160                                 (handle)?(handle)->object_id:NULL,                      \
1161                                 nobug_resource_error);                                  \
1162           handle = NULL;)                                                               \
1163         section_ = 0;                                                                   \
1164       })                                                                                \
1165    ))
1166
1167
1168 /*
1169 //resourcemacros PARA RESOURCE_ENTER; RESOURCE_ENTER; claim a resource
1170 //resourcemacros  RESOURCE_ENTER(flag, announced, user, state, handle)
1171 //resourcemacros  NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, state, handle, context)
1172 //resourcemacros
1173 //resourcemacros Acquire a resource.
1174 //resourcemacros
1175 //resourcemacros `flag`::
1176 //resourcemacros     nobug flag which turns logging on for this macro
1177 //resourcemacros `announced`::
1178 //resourcemacros     the handle set by `RESOURCE_ANNOUNCE`
1179 //resourcemacros `user`::
1180 //resourcemacros     a free-form identifier
1181 //resourcemacros `state`::
1182 //resourcemacros     the initial state, one of `NOBUG_RESOURCE_WAITING`, `NOBUG_RESOURCE_TRYING`,
1183 //resourcemacros     `NOBUG_RESOURCE_EXCLUSIVE`, `NOBUG_RESOURCE_RECURSIVE` or `NOBUG_RESOURCE_SHARED`
1184 //resourcemacros `handle`::
1185 //resourcemacros     a `NOBUG_RESOURCE_HANDLE` which will be initialized to the
1186 //resourcemacros     entering node
1187 //resourcemacros
1188 //resourcemacros 'RESOURCE_ENTER()' acts like the head of a C loop statement, it ties to the following
1189 //resourcemacros (block-) statement. Leaving and the user defined following statement are atomic.
1190 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1191 //resourcemacros
1192 */
1193 #define NOBUG_RESOURCE_ENTER(flag, resource, user, state, handle)                       \
1194   NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, state, handle, NOBUG_CONTEXT)
1195
1196
1197 #define NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, state, handle, context)  \
1198   NOBUG_IF_NOT_RELEASE( for (                                                   \
1199     int NOBUG_CLEANUP(nobug_section_cleaned) section_ =                         \
1200       ({                                                                        \
1201         NOBUG_IF(NOBUG_RESOURCE_LOGGING,                                        \
1202              NOBUG_LOG_(&NOBUG_FLAG(flag), NOBUG_RESOURCE_LOG_LEVEL,            \
1203                         "RESOURCE_ENTER", context,                              \
1204                         "%s: %s@%p: %s: %s",                                    \
1205                         (resource)?(resource)->type:"",                         \
1206                         (resource)?(resource)->hdr.name:"",                     \
1207                         (resource)?(resource)->object_id:NULL,                  \
1208                         user,                                                   \
1209                         nobug_resource_states[state]);)                         \
1210         NOBUG_IF_ALPHA (                                                        \
1211          NOBUG_RESOURCE_ASSERT_CTX(handle =                                     \
1212                                    nobug_resource_enter (resource,              \
1213                                                          user, state,           \
1214                                                          context),              \
1215                                    "RESOURCE_ASSERT_ENTER", context,            \
1216                                    "%s: %s@%p: %s: %s: %s",                     \
1217                                    (resource)?(resource)->type:"",              \
1218                                    (resource)?(resource)->hdr.name:"",          \
1219                                    (resource)?(resource)->object_id:NULL,       \
1220                                    user, nobug_resource_states[state],          \
1221                                    nobug_resource_error);)                      \
1222         1;                                                                      \
1223       });                                                                       \
1224       section_;                                                                 \
1225       section_ = 0                                                              \
1226   ))
1227
1228
1229 //resourcemacros PARA RESOURCE_WAIT; RESOURCE_WAIT; wait for a resource to become available
1230 //resourcemacros  RESOURCE_WAIT(flag, resource, user, handle)
1231 //resourcemacros  NOBUG_RESOURCE_WAIT_CTX(flag, resource, user, handle, context)
1232 //resourcemacros
1233 //resourcemacros This is just an alias for RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_WAITING, handle)
1234 //resourcemacros
1235 //resourcemacros .How to use it
1236 //resourcemacros [source,c]
1237 //resourcemacros ----
1238 //resourcemacros RESOURCE_WAIT(flag, resource, user, handle);
1239 //resourcemacros if (lock_my_resource() == ERROR)
1240 //resourcemacros   NOBUG_RESOURCE_LEAVE(flag, handle);
1241 //resourcemacros else
1242 //resourcemacros   RESOURCE_STATE(flag, NOBUG_RESOURCE_EXCLUSIVE, handle);
1243 //resourcemacros ----
1244 //resourcemacros
1245 #define NOBUG_RESOURCE_WAIT(flag, resource, user, handle) \
1246   NOBUG_RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_WAITING, handle)
1247
1248 #define NOBUG_RESOURCE_WAIT_CTX(flag, resource, user, handle, context) \
1249   NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, NOBUG_RESOURCE_WAITING, handle, context)
1250
1251
1252 //resourcemacros PARA RESOURCE_TRY; RESOURCE_TRY; wait for a resource to become available
1253 //resourcemacros  RESOURCE_TRY(flag, resource, user, handle)
1254 //resourcemacros  NOBUG_RESOURCE_TRY_CTX(flag, resource, user, handle, context)
1255 //resourcemacros
1256 //resourcemacros This is just an alias for RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_TRYING, handle).
1257 //resourcemacros Trying on a resource is similar to waiting but will not trigger a deadlock check. This can be used
1258 //resourcemacros when a deadlock is expected at runtime and one handles this otherwise (by a timed wait or something like that).
1259 //resourcemacros
1260 #define NOBUG_RESOURCE_TRY(flag, resource, user, handle) \
1261   NOBUG_RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_TRYING, handle)
1262
1263 #define NOBUG_RESOURCE_TRY_CTX(flag, resource, user, handle, context) \
1264   NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, NOBUG_RESOURCE_TRYING, handle, context)
1265
1266
1267 /*
1268 //resourcemacros PARA RESOURCE_STATE; RESOURCE_STATE; change the state of a resource
1269 //resourcemacros  RESOURCE_STATE(flag, entered, state)
1270 //resourcemacros  NOBUG_RESOURCE_STATE_CTX(flag, state, entered, context)
1271 //resourcemacros  NOBUG_RESOURCE_STATE_RAW(flagptr, state, entered)
1272 //resourcemacros  NOBUG_RESOURCE_STATE_RAW_CTX(flagptr, nstate, entered, context)
1273 //resourcemacros
1274 //resourcemacros Changes resource's state.
1275 //resourcemacros
1276 //resourcemacros `flag`::
1277 //resourcemacros     is nobug flag which turns logging on for this macro
1278 //resourcemacros `state`::
1279 //resourcemacros     the new state Note that only certain state transitions are
1280 //resourcemacros     allowed, see discussion/diagram above
1281 //resourcemacros `entered`::
1282 //resourcemacros     the handle set by `RESOURCE_ENTER`
1283 //resourcemacros
1284 //resourcemacros 'RESOURCE_STATE()' acts like the head of a C loop statement, it ties to the following
1285 //resourcemacros (block-) statement. Leaving and the user defined following statement are atomic.
1286 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1287 //resourcemacros
1288 */
1289 #define NOBUG_RESOURCE_STATE(flag, state, entered) \
1290   NOBUG_RESOURCE_STATE_RAW_CTX(&NOBUG_FLAG(flag), state, entered, NOBUG_CONTEXT)
1291
1292 #define NOBUG_RESOURCE_STATE_CTX(flag, state, entered, context) \
1293   NOBUG_RESOURCE_STATE_RAW_CTX(&NOBUG_FLAG(flag), state, entered, context)
1294
1295 #define NOBUG_RESOURCE_STATE_RAW(flag, state, entered) \
1296   NOBUG_RESOURCE_STATE_RAW_CTX(flag, state, entered, NOBUG_CONTEXT)
1297
1298 #define NOBUG_RESOURCE_STATE_RAW_CTX(flag, nstate, entered, context)                    \
1299   NOBUG_IF_NOT_RELEASE( for (                                                           \
1300     int NOBUG_CLEANUP(nobug_section_cleaned) section_ =                                 \
1301       ({                                                                                \
1302         NOBUG_IF(NOBUG_RESOURCE_LOGGING,                                                \
1303              NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL,                                 \
1304                         "RESOURCE_STATE",  context,                                     \
1305                         "%s: %s@%p: %s: %s->%s",                                        \
1306                         (entered)?(entered)->current->resource->type:"",                \
1307                         (entered)?(entered)->current->resource->hdr.name:"",            \
1308                         (entered)?(entered)->current->resource->object_id:"",           \
1309                         (entered)?(entered)->hdr.name:"",                               \
1310                         nobug_resource_states[(entered)?(entered)->state                \
1311                                               :NOBUG_RESOURCE_INVALID],                 \
1312                         nobug_resource_states[nstate]);                                 \
1313              )                                                                          \
1314     NOBUG_IF_ALPHA(                                                                     \
1315       NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_state ((entered), nstate),               \
1316                             "RESOURCE_ASSERT_STATE", context,                           \
1317                             "%s: %s@%p: %s: %s->%s: %s",                                \
1318                             (entered)?(entered)->current->resource->type:"",            \
1319                             (entered)?(entered)->current->resource->hdr.name:"",        \
1320                             (entered)?(entered)->current->resource->object_id:"",       \
1321                             (entered)?(entered)->hdr.name:"",                           \
1322                             nobug_resource_states[(entered)?(entered)->state            \
1323                                                   :NOBUG_RESOURCE_INVALID],             \
1324                             nobug_resource_states[nstate],                              \
1325                             nobug_resource_error);                                      \
1326       )                                                                                 \
1327     1;                                                                                  \
1328   });                                                                                   \
1329   section_;                                                                             \
1330   section_ = 0))
1331
1332 /*
1333 //resourcemacros PARA RESOURCE_LEAVE; RESOURCE_LEAVE; relinquish a claimed resource
1334 //resourcemacros  RESOURCE_LEAVE(flag, handle){}
1335 //resourcemacros  NOBUG_RESOURCE_LEAVE_RAW(flagptr, handle){}
1336 //resourcemacros  NOBUG_RESOURCE_LEAVE_RAW_CTX(flagptr, handle, context){}
1337 //resourcemacros
1338 //resourcemacros Disconnect from a resource identified with its handle.
1339 //resourcemacros
1340 //resourcemacros `flag`::
1341 //resourcemacros     nobug flag which turns logging on for this macro
1342 //resourcemacros `handle`::
1343 //resourcemacros     the handle you got while entering the resource
1344 //resourcemacros
1345 //resourcemacros 'RESOURCE_LEAVE()' acts like the head of a C loop statement, it ties to the following
1346 //resourcemacros (block-) statement. Leaving and the user defined following statement are atomic.
1347 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1348 //resourcemacros
1349 //resourcemacros .How to use it
1350 //resourcemacros [source,c]
1351 //resourcemacros ----
1352 //resourcemacros NOBUG_RESOURCE_LEAVE(flag, handle)
1353 //resourcemacros   {
1354 //resourcemacros     unlock_my_resource();
1355 //resourcemacros   }
1356 //resourcemacros ----
1357 //resourcemacros
1358 */
1359 #define NOBUG_RESOURCE_LEAVE(flag, handle) \
1360   NOBUG_RESOURCE_LEAVE_RAW_CTX(&NOBUG_FLAG(flag), handle, NOBUG_CONTEXT)
1361
1362 #define NOBUG_RESOURCE_LEAVE_RAW(flag, handle) \
1363   NOBUG_RESOURCE_LEAVE_RAW_CTX(flag, handle, NOBUG_CONTEXT)
1364
1365 #define NOBUG_RESOURCE_LEAVE_RAW_CTX(flag, handle, context)                             \
1366   NOBUG_IF_NOT_RELEASE(                                                                 \
1367     for (                                                                               \
1368          int NOBUG_CLEANUP(nobug_section_cleaned) section_ = ({                         \
1369            nobug_resource_leave_pre();                                                  \
1370            1;                                                                           \
1371          });                                                                            \
1372          section_;                                                                      \
1373          ({                                                                             \
1374            NOBUG_IF(NOBUG_RESOURCE_LOGGING,                                             \
1375                     NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL,                          \
1376                                "RESOURCE_LEAVE", context,                               \
1377                                "%s: %s@%p: %s: %s",                                     \
1378                                (handle)?(handle)->current->resource->type:"",           \
1379                                (handle)?(handle)->current->resource->hdr.name:"",       \
1380                                (handle)?(handle)->current->resource->object_id:"",      \
1381                                (handle)?(handle)->hdr.name:"",                          \
1382                                nobug_resource_states[(handle)?(handle)->state           \
1383                                                      :NOBUG_RESOURCE_INVALID]);         \
1384                     )                                                                   \
1385            NOBUG_IF_ALPHA(                                                              \
1386              NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_leave (handle),                   \
1387                                    "RESOURCE_ASSERT_LEAVE", context,                    \
1388                                    "%s: %s@%p: %s: %s: %s",                             \
1389                                    (handle)?(handle)->current->resource->type:"",       \
1390                                    (handle)?(handle)->current->resource->hdr.name:"",   \
1391                                    (handle)?(handle)->current->resource->object_id:"",  \
1392                                    (handle)?(handle)->hdr.name:"",                      \
1393                                    nobug_resource_states[(handle)?(handle)->state       \
1394                                                          :NOBUG_RESOURCE_INVALID],      \
1395                                    nobug_resource_error);                               \
1396              handle = NULL;                                                             \
1397              )                                                                          \
1398            section_ = 0;                                                                \
1399          })))
1400
1401 /*
1402 //resourcemacros PARA RESOURCE_ASSERT_STATE; RESOURCE_ASSERT_STATE; assert the state of a resource
1403 //resourcemacros  RESOURCE_ASSERT_STATE(resource, state)
1404 //resourcemacros  RESOURCE_ASSERT_STATE_IF(when, resource, state)
1405 //resourcemacros  NOBUG_RESOURCE_ASSERT_STATE_CTX(resource, state, context)
1406 //resourcemacros  NOBUG_RESOURCE_ASSERT_STATE_IF_CTX(when, resource, state, context)
1407 //resourcemacros
1408 //resourcemacros Assert that we have a resource in a given state. For multithreaded programms the topmost
1409 //resourcemacros state of the calling thread is checked, for non threadeded programs the most recent state on
1410 //resourcemacros resource is used.
1411 //resourcemacros
1412 //resourcemacros `when`::
1413 //resourcemacros     Condition which must be true for testing the assertion
1414 //resourcemacros `resource`::
1415 //resourcemacros     Resource handle
1416 //resourcemacros `state`::
1417 //resourcemacros     The expected state
1418 //resourcemacros
1419 */
1420 #define NOBUG_RESOURCE_ASSERT_STATE(resource, state) \
1421   NOBUG_RESOURCE_ASSERT_STATE_CTX(resource, state, NOBUG_CONTEXT)
1422
1423 #define NOBUG_RESOURCE_ASSERT_STATE_CTX(resource, state, context)                                       \
1424   NOBUG_IF_ALPHA(                                                                                       \
1425   do {                                                                                                  \
1426   enum nobug_resource_state mystate = nobug_resource_mystate (resource);                                \
1427   NOBUG_RESOURCE_ASSERT_CTX(mystate == state,                                                           \
1428                             "RESOURCE_ASSERT_STATE",  context,                                          \
1429                             "resource %p has state %s but %s was expected",                             \
1430                             resource, nobug_resource_states[mystate], nobug_resource_states[state]);    \
1431   } while (0))
1432
1433
1434 #define NOBUG_RESOURCE_ASSERT_STATE_IF(when, resource, state)           \
1435   NOBUG_WHEN(when, NOBUG_RESOURCE_ASSERT_STATE (resource, state))
1436
1437
1438 /* assertion which dumps all resources */
1439 #define NOBUG_RESOURCE_ASSERT_CTX(expr, what, context, ...)             \
1440   NOBUG_IF_ALPHA(                                                       \
1441     NOBUG_WHEN (!(expr),                                                \
1442       NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG,                      \
1443                   what, context,                                        \
1444                   ""__VA_ARGS__);                                       \
1445       nobug_resource_dump_all ((struct nobug_resource_dump_context)     \
1446                                {                                        \
1447                                  &nobug_flag_NOBUG_ON,                  \
1448                                  LOG_EMERG,                             \
1449                                  context                                \
1450                                });                                      \
1451       NOBUG_BACKTRACE_CTX(context);                                     \
1452       NOBUG_ABORT))
1453
1454
1455 /*
1456 //resourcemacros PARA RESOURCE_DUMP; RESOURCE_DUMP; dump the state of a single resource
1457 //resourcemacros  NOBUG_RESOURCE_DUMP(flag, handle)
1458 //resourcemacros  NOBUG_RESOURCE_DUMP_IF(when, flag, handle)
1459 //resourcemacros
1460 //resourcemacros Dump the state of a single resource.
1461 //resourcemacros
1462 //resourcemacros `when`::
1463 //resourcemacros     Condition which must be true to dump the resource
1464 //resourcemacros `flag`::
1465 //resourcemacros     Nobug flag for the log channel
1466 //resourcemacros `handle`::
1467 //resourcemacros     handle of the resource to be dumped
1468 //resourcemacros
1469 */
1470 #define NOBUG_RESOURCE_DUMP(flag, handle)                                       \
1471   NOBUG_IF_ALPHA(                                                               \
1472     do {                                                                        \
1473       nobug_resource_dump (handle, (struct nobug_resource_dump_context)         \
1474                              {&NOBUG_FLAG(flag),                                \
1475                               NOBUG_RESOURCE_LOG_LEVEL,                         \
1476                               NOBUG_CONTEXT});                                  \
1477     } while (0))
1478
1479 #define NOBUG_RESOURCE_DUMP_IF(when, flag, handle)                              \
1480   NOBUG_IF_ALPHA(                                                               \
1481     NOBUG_WHEN(when,                                                            \
1482       nobug_resource_dump (handle, (struct nobug_resource_dump_context)         \
1483                              {&NOBUG_FLAG(flag),                                \
1484                               NOBUG_RESOURCE_LOG_LEVEL,                         \
1485                               NOBUG_CONTEXT});                                  \
1486     ))
1487
1488
1489 /*
1490 //resourcemacros PARA RESOURCE_DUMPALL; RESOURCE_DUMPALL; dump the state of all resources
1491 //resourcemacros  NOBUG_RESOURCE_DUMPALL(flag)
1492 //resourcemacros  NOBUG_RESOURCE_DUMPALL_IF(when, flag)
1493 //resourcemacros
1494 //resourcemacros Dump the state of all resources.
1495 //resourcemacros
1496 //resourcemacros `when`::
1497 //resourcemacros     Condition which must be true to dump the resources
1498 //resourcemacros `flag`::
1499 //resourcemacros     Nobug flag for the log channel
1500 //resourcemacros
1501 */
1502 #define NOBUG_RESOURCE_DUMPALL(flag)                                    \
1503   NOBUG_IF_ALPHA(                                                       \
1504     do {                                                                \
1505       nobug_resource_dump_all ((struct nobug_resource_dump_context)     \
1506                                {&NOBUG_FLAG(flag),                      \
1507                                    NOBUG_RESOURCE_LOG_LEVEL,            \
1508                                    NOBUG_CONTEXT});                     \
1509     } while (0))
1510
1511
1512 #define NOBUG_RESOURCE_DUMPALL_IF(when, flag)                           \
1513   NOBUG_IF_ALPHA(                                                       \
1514     NOBUG_WHEN(when,                                                    \
1515       nobug_resource_dump_all ((struct nobug_resource_dump_context)     \
1516                                {&NOBUG_FLAG(flag),                      \
1517                                    NOBUG_RESOURCE_LOG_LEVEL,            \
1518                                    NOBUG_CONTEXT});                     \
1519       ))
1520
1521 /*
1522 //resourcemacros PARA RESOURCE_LIST; RESOURCE_LIST; enumerate all registered resources
1523 //resourcemacros  NOBUG_RESOURCE_LIST(flag)
1524 //resourcemacros  NOBUG_RESOURCE_LIST_IF(when, flag)
1525 //resourcemacros
1526 //resourcemacros List all registered resources.
1527 //resourcemacros
1528 //resourcemacros `when`::
1529 //resourcemacros     Condition which must be true to list the resources
1530 //resourcemacros `flag`::
1531 //resourcemacros     Nobug flag for the log channel
1532 //resourcemacros
1533 */
1534 #define NOBUG_RESOURCE_LIST(flag)                                       \
1535   NOBUG_IF_ALPHA(                                                       \
1536     do {                                                                \
1537       nobug_resource_list ((struct nobug_resource_dump_context)         \
1538                            {&NOBUG_FLAG(flag),                          \
1539                                NOBUG_RESOURCE_LOG_LEVEL,                \
1540                                NOBUG_CONTEXT});                         \
1541     } while (0))
1542
1543
1544 #define NOBUG_RESOURCE_LIST_IF(when, flag)                              \
1545   NOBUG_IF_ALPHA(                                                       \
1546     NOBUG_WHEN(when,                                                    \
1547       nobug_resource_list ((struct nobug_resource_dump_context)         \
1548                                {&NOBUG_FLAG(flag),                      \
1549                                 NOBUG_RESOURCE_LOG_LEVEL,               \
1550                                 NOBUG_CONTEXT});                        \
1551     ))
1552
1553
1554 /*
1555  threading support
1556 */
1557 #if NOBUG_USE_PTHREAD
1558 #define NOBUG_THREAD_ID_SET(name) nobug_thread_id_set(name)
1559 #define NOBUG_THREAD_ID_GET nobug_thread_id_get()
1560
1561 #else
1562 #define NOBUG_THREAD_ID_SET(name)
1563 #define NOBUG_THREAD_ID_GET ""
1564 #endif
1565
1566 #define NOBUG_THREAD_DATA (*nobug_thread_data())
1567
1568
1569 /*
1570   Debuggers
1571  */
1572
1573 #define NOBUG_DBG_NONE 0
1574 #define NOBUG_DBG_GDB 1
1575 #define NOBUG_DBG_VALGRIND 2
1576
1577 #define NOBUG_ACTIVE_DBG                                \
1578 NOBUG_IF(NOBUG_USE_VALGRIND, (RUNNING_ON_VALGRIND?2:0)) \
1579 NOBUG_IFNOT(NOBUG_USE_VALGRIND, 0)
1580
1581 /*
1582 //toolmacros HEAD- Tool Macros;;
1583 //toolmacros
1584 //toolmacros PARA NOBUG_FLAG_RAW; NOBUG_FLAG_RAW; pass direct flag pointer
1585 //toolmacros  NOBUG_FLAG_RAW(ptr)
1586 //toolmacros
1587 //toolmacros Using this macro one can pass a direct pointer to a flag where a name would
1588 //toolmacros be expected. This is sometimes convinient when flag pointers are passed around
1589 //toolmacros in management strutures and one wants to tie logging to dynamic targets.
1590 //toolmacros
1591 //toolmacros [source,c]
1592 //toolmacros ----
1593 //toolmacros NOBUG_DEFINE_FLAG(myflag);
1594 //toolmacros ...
1595 //toolmacros struct nobug_flag* ptr = &NOBUG_FLAG(myflag);
1596 //toolmacros TRACE(NOBUG_FLAG_RAW(ptr), "Passed flag by pointer")
1597 //toolmacros ----
1598 //toolmacros
1599 */
1600 #define nobug_flag_NOBUG_FLAG_RAW(name) *name
1601
1602 /*
1603 //toolmacros PARA Backtraces; BACKTRACE; generate a backtrace
1604 //toolmacros  BACKTRACE
1605 //toolmacros  NOBUG_BACKTRACE_CTX(context)
1606 //toolmacros
1607 //toolmacros The backtrace macro logs a stacktrace using the NoBug facilities.
1608 //toolmacros This is automatically called when NoBug finds an error and is due
1609 //toolmacros to abort. But one might call it manually too.
1610 //toolmacros
1611 */
1612 #define NOBUG_BACKTRACE NOBUG_BACKTRACE_CTX(NOBUG_CONTEXT)
1613
1614 #define NOBUG_BACKTRACE_CTX(context)                    \
1615   NOBUG_IF_ALPHA(                                       \
1616                  switch (NOBUG_ACTIVE_DBG) {            \
1617                  case NOBUG_DBG_VALGRIND:               \
1618                    NOBUG_BACKTRACE_VALGRIND(context);   \
1619                    break;                               \
1620                  default:                               \
1621                    NOBUG_BACKTRACE_GLIBC(context);      \
1622                  })                                     \
1623   NOBUG_IF_NOT_ALPHA (NOBUG_BACKTRACE_GLIBC(context))
1624
1625 #define NOBUG_BACKTRACE_GDB(context) UNIMPLEMENTED
1626
1627 #define NOBUG_BACKTRACE_VALGRIND(context)                               \
1628   NOBUG_IF(NOBUG_USE_VALGRIND,                                          \
1629     nobug_backtrace_valgrind (context)                                  \
1630   )
1631
1632
1633 #ifndef NOBUG_BACKTRACE_DEPTH
1634 #define NOBUG_BACKTRACE_DEPTH 256
1635 #endif
1636
1637 #define NOBUG_BACKTRACE_GLIBC(context)          \
1638   NOBUG_IF_NOT_RELEASE(                         \
1639   NOBUG_IF(NOBUG_USE_EXECINFO, do {             \
1640     nobug_backtrace_glibc (context);            \
1641   } while (0)))
1642
1643
1644 #ifndef NOBUG_TAB
1645 #define NOBUG_TAB "        "
1646 #endif
1647
1648 //toolmacros PARA Aborting; ABORT; abort the program
1649 //toolmacros  NOBUG_ABORT_
1650 //toolmacros
1651 //toolmacros This is the default implementation for aborting the program, it first syncs all ringbuffers to disk, then
1652 //toolmacros calls the abort callback if defined and then `abort()`.
1653 //toolmacros
1654 //toolmacros  NOBUG_ABORT
1655 //toolmacros
1656 //toolmacros If not overridden, evaluates to `NOBUG_ABORT_`. One can override this before including
1657 //toolmacros `nobug.h` to customize abortion behaviour. This will be local to the translation unit then.
1658 //toolmacros
1659 #ifndef NOBUG_ABORT
1660 #define NOBUG_ABORT NOBUG_ABORT_
1661 #endif
1662
1663 #define NOBUG_ABORT_                                            \
1664   do {                                                          \
1665     nobug_ringbuffer_allsync ();                                \
1666     if (nobug_abort_callback)                                   \
1667       nobug_abort_callback (nobug_callback_data);               \
1668     abort();                                                    \
1669   } while(0)
1670
1671
1672 /*
1673   init and other function wrapers
1674 */
1675 #define NOBUG_INIT nobug_init(NOBUG_CONTEXT)
1676
1677 /*
1678   short macros without NOBUG_
1679 */
1680 #ifndef NOBUG_DISABLE_SHORTNAMES
1681 #ifndef REQUIRE
1682 #define REQUIRE NOBUG_REQUIRE
1683 #endif
1684 #ifndef REQUIRE_IF
1685 #define REQUIRE_IF NOBUG_REQUIRE_IF
1686 #endif
1687 #ifndef ENSURE
1688 #define ENSURE NOBUG_ENSURE
1689 #endif
1690 #ifndef ENSURE_IF
1691 #define ENSURE_IF NOBUG_ENSURE_IF
1692 #endif
1693 #ifndef ASSERT
1694 #define ASSERT NOBUG_ASSERT
1695 #endif
1696 #ifndef ASSERT_IF
1697 #define ASSERT_IF NOBUG_ASSERT_IF
1698 #endif
1699 #ifndef CHECK
1700 #define CHECK NOBUG_CHECK
1701 #endif
1702 #ifndef CHECK
1703 #define CHECK NOBUG_CHECK
1704 #endif
1705 #ifndef INVARIANT
1706 #define INVARIANT NOBUG_INVARIANT
1707 #endif
1708 #ifndef INVARIANT_IF
1709 #define INVARIANT_IF NOBUG_INVARIANT_IF
1710 #endif
1711 #ifndef INVARIANT_ASSERT
1712 #define INVARIANT_ASSERT NOBUG_INVARIANT_ASSERT
1713 #endif
1714 #ifndef DUMP
1715 #define DUMP NOBUG_DUMP
1716 #endif
1717 #ifndef DUMP_IF
1718 #define DUMP_IF NOBUG_DUMP_IF
1719 #endif
1720 #ifndef DUMP_LOG
1721 #define DUMP_LOG NOBUG_DUMP_LOG
1722 #endif
1723 #ifndef DUMP_LOG_IF
1724 #define DUMP_LOG_IF NOBUG_DUMP_LOG_IF
1725 #endif
1726 #ifndef LOG
1727 #define LOG NOBUG_LOG
1728 #endif
1729 #ifndef LOG_IF
1730 #define LOG_IF NOBUG_LOG_IF
1731 #endif
1732 #ifndef ECHO
1733 #define ECHO NOBUG_ECHO
1734 #endif
1735 #ifndef ALERT
1736 #define ALERT NOBUG_ALERT
1737 #endif
1738 #ifndef ALERT_IF
1739 #define ALERT_IF NOBUG_ALERT_IF
1740 #endif
1741 #ifndef CRITICAL
1742 #define CRITICAL NOBUG_CRITICAL
1743 #endif
1744 #ifndef CRITICAL_IF
1745 #define CRITICAL_IF NOBUG_CRITICAL_IF
1746 #endif
1747 #ifndef ERROR
1748 #define ERROR NOBUG_ERROR
1749 #endif
1750 #ifndef ERROR_IF
1751 #define ERROR_IF NOBUG_ERROR_IF
1752 #endif
1753 #ifndef WARN
1754 #define WARN NOBUG_WARN
1755 #endif
1756 #ifndef WARN_IF
1757 #define WARN_IF NOBUG_WARN_IF
1758 #endif
1759 #ifndef INFO
1760 #define INFO NOBUG_INFO
1761 #endif
1762 #ifndef INFO_IF
1763 #define INFO_IF NOBUG_INFO_IF
1764 #endif
1765 #ifndef NOTICE
1766 #define NOTICE NOBUG_NOTICE
1767 #endif
1768 #ifndef NOTICE_IF
1769 #define NOTICE_IF NOBUG_NOTICE_IF
1770 #endif
1771 #ifndef TRACE
1772 #define TRACE NOBUG_TRACE
1773 #endif
1774 #ifndef TRACE_IF
1775 #define TRACE_IF NOBUG_TRACE_IF
1776 #endif
1777 #ifndef BACKTRACE
1778 #define BACKTRACE NOBUG_BACKTRACE
1779 #endif
1780 #ifndef DEPRECATED
1781 #define DEPRECATED NOBUG_DEPRECATED
1782 #endif
1783 #ifndef UNIMPLEMENTED
1784 #define UNIMPLEMENTED NOBUG_UNIMPLEMENTED
1785 #endif
1786 #ifndef FIXME
1787 #define FIXME NOBUG_FIXME
1788 #endif
1789 #ifndef TODO
1790 #define TODO NOBUG_TODO
1791 #endif
1792 #ifndef PLANNED
1793 #define PLANNED NOBUG_PLANNED
1794 #endif
1795 #ifndef NOTREACHED
1796 #define NOTREACHED NOBUG_NOTREACHED
1797 #endif
1798 #ifndef ELSE_NOTREACHED
1799 #define ELSE_NOTREACHED NOBUG_ELSE_NOTREACHED
1800 #endif
1801 #ifndef INJECT_GOODBAD
1802 #define INJECT_GOODBAD NOBUG_INJECT_GOODBAD
1803 #endif
1804 #ifndef INJECT_FAULT
1805 #define INJECT_FAULT NOBUG_INJECT_FAULT
1806 #endif
1807 #ifndef CLEANUP
1808 #define CLEANUP NOBUG_CLEANUP
1809 #endif
1810 #ifndef CHECKED
1811 #define CHECKED NOBUG_CHECKED
1812 #endif
1813 #ifndef UNCHECKED
1814 #define UNCHECKED NOBUG_UNCHECKED
1815 #endif
1816 #ifndef RESOURCE_ANNOUNCE
1817 #define RESOURCE_ANNOUNCE NOBUG_RESOURCE_ANNOUNCE
1818 #endif
1819 #ifndef RESOURCE_FORGET
1820 #define RESOURCE_FORGET NOBUG_RESOURCE_FORGET
1821 #endif
1822 #ifndef RESOURCE_ENTER
1823 #define RESOURCE_ENTER NOBUG_RESOURCE_ENTER
1824 #endif
1825 #ifndef RESOURCE_WAIT
1826 #define RESOURCE_WAIT NOBUG_RESOURCE_WAIT
1827 #endif
1828 #ifndef RESOURCE_TRY
1829 #define RESOURCE_TRY NOBUG_RESOURCE_TRY
1830 #endif
1831 #ifndef RESOURCE_STATE
1832 #define RESOURCE_STATE NOBUG_RESOURCE_STATE
1833 #endif
1834 #ifndef RESOURCE_LEAVE
1835 #define RESOURCE_LEAVE NOBUG_RESOURCE_LEAVE
1836 #endif
1837 #ifndef RESOURCE_LEAVE_LOOKUP
1838 #define RESOURCE_LEAVE_LOOKUP NOBUG_RESOURCE_LEAVE_LOOKUP
1839 #endif
1840 #ifndef RESOURCE_HANDLE
1841 #define RESOURCE_HANDLE NOBUG_RESOURCE_HANDLE
1842 #endif
1843 #ifndef RESOURCE_HANDLE_INIT
1844 #define RESOURCE_HANDLE_INIT NOBUG_RESOURCE_HANDLE_INIT
1845 #endif
1846 #ifndef RESOURCE_USER
1847 #define RESOURCE_USER NOBUG_RESOURCE_USER
1848 #endif
1849 #ifndef RESOURCE_ASSERT_STATE
1850 #define RESOURCE_ASSERT_STATE NOBUG_RESOURCE_ASSERT_STATE
1851 #endif
1852 #ifndef RESOURCE_ASSERT_STATE_IF
1853 #define RESOURCE_ASSERT_STATE_IF NOBUG_RESOURCE_ASSERT_STATE_IF
1854 #endif
1855 #ifndef RESOURCE_USER_INIT
1856 #define RESOURCE_USER_INIT NOBUG_RESOURCE_USER_INIT
1857 #endif
1858 #ifndef RESOURCE_DUMP
1859 #define RESOURCE_DUMP NOBUG_RESOURCE_DUMP
1860 #endif
1861 #ifndef RESOURCE_DUMP_IF
1862 #define RESOURCE_DUMP_IF NOBUG_RESOURCE_DUMP_IF
1863 #endif
1864 #ifndef RESOURCE_DUMPALL
1865 #define RESOURCE_DUMPALL NOBUG_RESOURCE_DUMPALL
1866 #endif
1867 #ifndef RESOURCE_DUMPALL_IF
1868 #define RESOURCE_DUMPALL_IF NOBUG_RESOURCE_DUMPALL_IF
1869 #endif
1870 #ifndef RESOURCE_LIST
1871 #define RESOURCE_LIST NOBUG_RESOURCE_LIST
1872 #endif
1873 #ifndef RESOURCE_LIST_IF
1874 #define RESOURCE_LIST_IF NOBUG_RESOURCE_LIST_IF
1875 #endif
1876 #endif /* NOBUG_DISABLE_SHORTNAMES */
1877
1878
1879 /*
1880   Tool macros
1881 */
1882 #ifdef __GNUC__
1883 #define NOBUG_CLEANUP(fn) NOBUG_IF_ALPHA(__attribute__((cleanup(fn))))
1884 #define NOBUG_ATTR_PRINTF(fmt, ell) __attribute__ ((format (printf, fmt, ell)))
1885 #else
1886 #define NOBUG_CLEANUP(fn)
1887 #define NOBUG_ATTR_PRINTF(fmt, ell)
1888 #endif
1889
1890 /*
1891 //toolmacros PARA NOBUG_ALPHA_COMMA; NOBUG_ALPHA_COMMA; append something after a comma in *ALPHA* builds
1892 //toolmacros  NOBUG_ALPHA_COMMA(something)
1893 //toolmacros  NOBUG_ALPHA_COMMA_NULL
1894 //toolmacros
1895 //toolmacros Sometimes it is useful to have initializer code only in *ALPHA* builds, for example when you
1896 //toolmacros conditionally include resource handles only in *ALPHA* versions. An initializer can then
1897 //toolmacros use this macros to append a comman and something else only in *ALPHA* builds as in:
1898 //toolmacros  struct foo = {"foo", "bar" NOBUG_ALPHA_COMMA_NULL };
1899 //toolmacros
1900 */
1901 #define NOBUG_COMMA ,
1902 #define NOBUG_ALPHA_COMMA(something) NOBUG_IF_ALPHA(NOBUG_COMMA something)
1903 #define NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA(NULL)
1904
1905 #define NOBUG_ONCE(code)                                        \
1906   do {                                                          \
1907     static volatile int NOBUG_CAT(nobug_once_,__LINE__) = 1;    \
1908     if (NOBUG_EXPECT_FALSE(NOBUG_CAT(nobug_once_,__LINE__)))    \
1909       {                                                         \
1910         NOBUG_CAT(nobug_once_,__LINE__) = 0;                    \
1911         code;                                                   \
1912       }                                                         \
1913   } while (0)
1914
1915 #if __GNUC__
1916 #define NOBUG_EXPECT_FALSE(x) __builtin_expect(!!(x),0)
1917 #else
1918 #define NOBUG_EXPECT_FALSE(x) x
1919 #endif
1920
1921 #define NOBUG_WHEN(when, ...)                          \
1922   do{ if (NOBUG_EXPECT_FALSE(when)){ __VA_ARGS__;}} while(0)
1923
1924 /*
1925 //toolmacros PARA NOBUG_IF_*; NOBUG_IF; include code conditionally on build level
1926 //toolmacros  NOBUG_IF_ALPHA(...)
1927 //toolmacros  NOBUG_IF_NOT_ALPHA(...)
1928 //toolmacros  NOBUG_IF_BETA(...)
1929 //toolmacros  NOBUG_IF_NOT_BETA(...)
1930 //toolmacros  NOBUG_IF_RELEASE(...)
1931 //toolmacros  NOBUG_IF_NOT_RELEASE(...)
1932 //toolmacros
1933 //toolmacros This macros allow one to conditionally include the code in '(...)' only if the
1934 //toolmacros criteria on the build level is met. If not, nothing gets substituted. Mostly used
1935 //toolmacros internally, but can also be used for custom things.
1936 //toolmacros
1937 */
1938 #define NOBUG_IF_ALPHA(...)                     \
1939 NOBUG_IF(NOBUG_MODE_ALPHA, __VA_ARGS__)         \
1940
1941 #define NOBUG_IF_NOT_ALPHA(...)                 \
1942 NOBUG_IFNOT(NOBUG_MODE_ALPHA, __VA_ARGS__)      \
1943
1944 #define NOBUG_IF_BETA(...)                      \
1945 NOBUG_IF(NOBUG_MODE_BETA, __VA_ARGS__)          \
1946
1947 #define NOBUG_IF_NOT_BETA(...)                  \
1948 NOBUG_IFNOT(NOBUG_MODE_BETA, __VA_ARGS__)       \
1949
1950 #define NOBUG_IF_RELEASE(...)                   \
1951 NOBUG_IF(NOBUG_MODE_RELEASE, __VA_ARGS__)       \
1952
1953 #define NOBUG_IF_NOT_RELEASE(...)               \
1954 NOBUG_IFNOT(NOBUG_MODE_RELEASE, __VA_ARGS__)    \
1955
1956 /*
1957   preprocessor hacks/metaprogramming
1958  */
1959
1960 #define NOBUG_IF(bool, ...) NOBUG_CAT(NOBUG_IF_,bool)(__VA_ARGS__)
1961 #define NOBUG_IF_1(...) __VA_ARGS__
1962 #define NOBUG_IF_0(...)
1963
1964 #define NOBUG_IFNOT(bool, ...) NOBUG_CAT(NOBUG_IF_, NOBUG_NOT(bool))(__VA_ARGS__)
1965
1966 #define NOBUG_NOT(bool) NOBUG_CAT(NOBUG_NOT_, bool)
1967 #define NOBUG_NOT_1 0
1968 #define NOBUG_NOT_0 1
1969
1970 #define NOBUG_AND(a,b) NOBUG_CAT3(NOBUG_AND_, a, b)
1971 #define NOBUG_AND_00 0
1972 #define NOBUG_AND_01 0
1973 #define NOBUG_AND_10 0
1974 #define NOBUG_AND_11 1
1975
1976 #define NOBUG_OR(a,b) NOBUG_CAT3(NOBUG_OR_, a, b)
1977 #define NOBUG_OR_00 0
1978 #define NOBUG_OR_01 1
1979 #define NOBUG_OR_10 1
1980 #define NOBUG_OR_11 1
1981
1982 #define NOBUG_XOR(a,b) NOBUG_CAT( NOBUG_XOR_, NOBUG_CAT(a,b))
1983 #define NOBUG_XOR_00 0
1984 #define NOBUG_XOR_01 1
1985 #define NOBUG_XOR_10 1
1986 #define NOBUG_XOR_11 0
1987
1988 #define NOBUG_CAT(a,b) NOBUG_CAT_(a,b)
1989 #define NOBUG_CAT_(a,b) a##b
1990
1991 #define NOBUG_CAT3(a,b,c) NOBUG_CAT3_(a,b,c)
1992 #define NOBUG_CAT3_(a,b,c) a##b##c
1993
1994 #define NOBUG_STRINGIZE(s) NOBUG_STRINGIZE_(s)
1995 #define NOBUG_STRINGIZE_(s) #s
1996
1997
1998 /*
1999   LIBNOBUG DECLARATIONS
2000 */
2001 #ifdef __cplusplus
2002 extern "C" {
2003 #elif 0
2004 }       /* fix emacs indent */
2005 #endif
2006
2007 #ifndef LLIST_DEFINED
2008 #define LLIST_DEFINED
2009 struct llist_struct
2010 {
2011   struct llist_struct *next;
2012   struct llist_struct *prev;
2013 };
2014 #endif
2015
2016 /*
2017   source context
2018 */
2019
2020 struct nobug_context
2021 {
2022   const char* file;
2023   int line;
2024   const char* func;
2025 };
2026
2027 const char*
2028 nobug_basename (const char* const file);
2029
2030 /*
2031   envvar control
2032 */
2033 enum nobug_log_targets
2034   {
2035     NOBUG_TARGET_RINGBUFFER,
2036     NOBUG_TARGET_CONSOLE,
2037     NOBUG_TARGET_FILE,
2038     NOBUG_TARGET_SYSLOG,
2039     NOBUG_TARGET_APPLICATION
2040   };
2041
2042 struct nobug_flag
2043 {
2044   const char* name;
2045   struct nobug_flag* parent;
2046   volatile int initialized;
2047   int limits[5];
2048   struct nobug_ringbuffer* ringbuffer_target;
2049   FILE* console_target;
2050   FILE* file_target;
2051 };
2052
2053 int
2054 nobug_env_parse_flag (const char* env, struct nobug_flag* flag, int default_target, int default_limit, const struct nobug_context context);
2055
2056 int
2057 nobug_env_init_flag (struct nobug_flag* flag, int default_target, int default_limit, const struct nobug_context context);
2058
2059
2060 /*
2061   ringbuffer
2062 */
2063 struct nobug_ringbuffer
2064 {
2065   struct llist_struct node;             /* all ringbufers are chained together, needed for sync */
2066   char* pos;
2067   char* start;
2068   size_t size;
2069   size_t guard;
2070   char name[256];
2071 };
2072
2073 enum nobug_ringbuffer_flags
2074   {
2075     NOBUG_RINGBUFFER_DEFAULT,           /* Default is to overwrite file and delete it on nobug_ringbuffer_destroy */
2076     NOBUG_RINGBUFFER_APPEND = 1,        /* use existing backing file, append if possible */
2077     NOBUG_RINGBUFFER_TEMP = 2,          /* unlink file instantly */
2078     NOBUG_RINGBUFFER_KEEP = 4           /* dont unlink the file at destroy */
2079   };
2080 /*
2081   Note: some flags conflict (TEMP with KEEP) nobug_ringbuffer will not error on these but continue gracefully
2082   with sane (but undefined) semantics.
2083 */
2084
2085 struct nobug_ringbuffer*
2086 nobug_ringbuffer_init (struct nobug_ringbuffer* self, size_t size,
2087                        size_t guard, const char * name, int flags);
2088
2089 struct nobug_ringbuffer*
2090 nobug_ringbuffer_new (size_t size, size_t guard, const char * name, int flags);
2091
2092 struct nobug_ringbuffer*
2093 nobug_ringbuffer_destroy (struct nobug_ringbuffer* self);
2094
2095 void
2096 nobug_ringbuffer_delete (struct nobug_ringbuffer* self);
2097
2098 void
2099 nobug_ringbuffer_sync (struct nobug_ringbuffer* self);
2100
2101 void
2102 nobug_ringbuffer_allsync (void);
2103
2104 int
2105 nobug_ringbuffer_vprintf (struct nobug_ringbuffer* self, const char* fmt, va_list ap);
2106
2107 int
2108 nobug_ringbuffer_printf (struct nobug_ringbuffer* self, const char* fmt, ...);
2109
2110 char*
2111 nobug_ringbuffer_append (struct nobug_ringbuffer* self);
2112
2113 int
2114 nobug_ringbuffer_extend (struct nobug_ringbuffer* self, size_t newsize, const char fill);
2115
2116 char*
2117 nobug_ringbuffer_prev (struct nobug_ringbuffer* self, char* pos);
2118
2119 char*
2120 nobug_ringbuffer_next (struct nobug_ringbuffer* self, char* pos);
2121
2122 int
2123 nobug_ringbuffer_save (struct nobug_ringbuffer* self, FILE* out);
2124
2125 int
2126 nobug_ringbuffer_load (struct nobug_ringbuffer* self, FILE* in);
2127
2128 char*
2129 nobug_ringbuffer_pos (struct nobug_ringbuffer* self);
2130
2131 void
2132 nobug_ringbuffer_pop (struct nobug_ringbuffer* self);
2133
2134
2135 /*
2136   multithreading extras
2137 */
2138 #if NOBUG_USE_PTHREAD
2139
2140 struct nobug_tls_data
2141 {
2142   const char* thread_id;
2143   unsigned thread_num;                          /* thread counter at initialization, gives a unique thread number */
2144   unsigned thread_gen;                          /* incremented at each name reset, (currently unused) */
2145   void* data;
2146   struct llist_struct res_stack;                /* resources of this thread */
2147 };
2148
2149 extern pthread_key_t nobug_tls_key;
2150
2151 struct nobug_tls_data*
2152 nobug_thread_set (const char* name);
2153
2154 struct nobug_tls_data*
2155 nobug_thread_get (void);
2156
2157 const char*
2158 nobug_thread_id_set (const char* name);
2159
2160 const char*
2161 nobug_thread_id_get (void);
2162
2163 extern pthread_mutex_t nobug_logging_mutex;
2164 extern pthread_mutex_t nobug_resource_mutex;
2165 #endif
2166
2167 void**
2168 nobug_thread_data (void);
2169
2170 /*
2171   resource registry
2172 */
2173 enum nobug_resource_state
2174   {
2175     NOBUG_RESOURCE_INVALID,
2176     NOBUG_RESOURCE_WAITING,
2177     NOBUG_RESOURCE_TRYING,
2178     NOBUG_RESOURCE_EXCLUSIVE,
2179     NOBUG_RESOURCE_RECURSIVE,
2180     NOBUG_RESOURCE_SHARED
2181   };
2182
2183
2184 struct nobug_resource_header
2185 {
2186   struct llist_struct node;                     /* link node for resource registry or users */
2187   const char* name;                             /* name */
2188   struct nobug_context extra;                   /* context information */
2189 };
2190
2191 struct nobug_resource_node;
2192 struct nobug_resource_user;
2193
2194 struct nobug_resource_record
2195 {
2196   struct nobug_resource_header hdr;
2197
2198   struct llist_struct users;                    /* list of users of this resource */
2199   const void* object_id;                        /* unique identifer, usually a this pointer or similar */
2200   const char* type;                             /* type */
2201
2202 #if NOBUG_USE_PTHREAD
2203   struct llist_struct nodes;
2204 #endif
2205 };
2206
2207
2208 struct nobug_resource_node
2209 {
2210   struct llist_struct node;                     /* all nodes for one resource */
2211
2212   struct nobug_resource_record* resource;       /* backpointer */
2213   struct nobug_resource_node* parent;           /* upwards the tree */
2214
2215   struct llist_struct childs;                   /* down the tree, all nodes pointing to here (TODO make this a slist) */
2216   struct llist_struct cldnode;                  /* node to accumulate all childrens of a parent (TODO slist) */
2217 };
2218
2219
2220 struct nobug_resource_user
2221 {
2222   struct nobug_resource_header hdr;
2223
2224   struct nobug_resource_node* current;          /* this resource */
2225   enum nobug_resource_state state;              /* state */
2226
2227 #if NOBUG_USE_PTHREAD
2228   struct nobug_tls_data* thread;                /* pointer to this theads id */
2229   struct llist_struct res_stack;                /* resources of this thread */
2230 #endif
2231 };
2232
2233
2234 extern const char* nobug_resource_error;
2235
2236 extern const char* nobug_resource_states[];
2237
2238
2239 void
2240 nobug_resource_init (void);
2241
2242 void
2243 nobug_resource_destroy (void);
2244
2245
2246 struct nobug_resource_record*
2247 nobug_resource_announce (const char* type, const char* name, const void* object_id, const struct nobug_context extra);
2248
2249 void
2250 nobug_resource_announce_complete (void);
2251
2252 int
2253 nobug_resource_forget (struct nobug_resource_record* node);
2254
2255
2256 struct nobug_resource_user*
2257 nobug_resource_enter (struct nobug_resource_record* resource,
2258                       const char* name,
2259                       enum nobug_resource_state state,
2260                       const struct nobug_context extra);
2261
2262
2263 int
2264 nobug_resource_leave (struct nobug_resource_user* handle);
2265
2266
2267 void
2268 nobug_resource_leave_pre (void);
2269
2270
2271 unsigned
2272 nobug_resource_record_available (void);
2273
2274
2275 unsigned
2276 nobug_resource_user_available (void);
2277
2278
2279 #if NOBUG_USE_PTHREAD
2280 unsigned
2281 nobug_resource_node_available (void);
2282 #endif
2283
2284
2285 struct nobug_resource_dump_context
2286 {
2287   struct nobug_flag* flag;
2288   int level;
2289   struct nobug_context ctx;
2290 };
2291
2292 enum nobug_resource_state
2293 nobug_resource_mystate (struct nobug_resource_record* res);
2294
2295 void
2296 nobug_resource_dump (struct nobug_resource_record* resource, const struct nobug_resource_dump_context context);
2297
2298 void
2299 nobug_resource_dump_all (const struct nobug_resource_dump_context context);
2300
2301 int
2302 nobug_resource_state (struct nobug_resource_user* resource,
2303                       enum nobug_resource_state state);
2304
2305
2306 void
2307 nobug_resource_list (const struct nobug_resource_dump_context context);
2308
2309
2310 /*
2311   global config, data and defaults
2312 */
2313 void nobug_init (const struct nobug_context context);
2314
2315 /*
2316   the destroy function is optional, since nobug should stay alive for the whole application lifetime
2317   (and destroying is global!) it is only provided for the nobug testsuite itself
2318 */
2319 void nobug_destroy (const struct nobug_context context);
2320
2321 void
2322 nobug_backtrace_glibc (const struct nobug_context context);
2323
2324 void
2325 nobug_backtrace_valgrind (const struct nobug_context context);
2326
2327 char*
2328 nobug_log_begin (char* header, struct nobug_flag* flag, const char* what, const struct nobug_context ctx);
2329
2330
2331 void
2332 nobug_log_end (struct nobug_flag* flag, int lvl);
2333
2334
2335 /* must be called inbetween log_begin and log_end */
2336 void
2337 nobug_log_line (char** start, char* header, struct nobug_flag* flag, int lvl, const char* fmt, ...);
2338
2339
2340 void
2341 nobug_log (struct nobug_flag* flag, int lvl, const char* what,
2342            const struct nobug_context ctx,
2343            const char* fmt, ...) NOBUG_ATTR_PRINTF(5, 6);
2344
2345
2346 extern struct nobug_ringbuffer nobug_default_ringbuffer;
2347 extern FILE* nobug_default_file;
2348 extern struct nobug_flag nobug_flag_NOBUG_ON;
2349 extern struct nobug_flag nobug_flag_NOBUG_ANN;
2350 extern struct nobug_flag nobug_flag_nobug;
2351 extern unsigned long long nobug_counter;
2352
2353 //callbacks HEAD- Callbacks;;
2354 //callbacks
2355 //callbacks NoBug provides callbacks, applications can use these
2356 //callbacks to present logging information in some custom way or hook some special processing in.
2357 //callbacks The callbacks are initialized to NULL and never modified by NoBug, its the solve responsibility
2358 //callbacks of the user to manage them.
2359 //callbacks
2360 //callbacks CAUTION: There are certain constraints what and what not can be done in callbacks
2361 //callbacks          documented below which must be followed.
2362 //callbacks
2363 //callbacks PARA type of logging callbacks; logging_cb; type of a logging callback function
2364 typedef void (*nobug_logging_cb)(const struct nobug_flag* flag, int priority, const char *log, void* data);     //callbacks  VERBATIM;
2365 //callbacks
2366 //callbacks used for the logging callbacks
2367 //callbacks
2368 //callbacks  `flag`::
2369 //callbacks     Flag structure which defines the logging configuration for this event
2370 //callbacks  `priority`::
2371 //callbacks     Log level of the current event
2372 //callbacks  `log`::
2373 //callbacks     Pointing to the current log line in the ringbuffer or `NULL`
2374 //callbacks  `data`::
2375 //callbacks     Global pointer defined by the user, passed arround (see below)
2376 //callbacks
2377
2378 //callbacks PARA type of abort callback; abort_cb; type of a abort callback function
2379 typedef void (*nobug_abort_cb)(void* data);             //callbacks  VERBATIM;
2380 //callbacks
2381 //callbacks used for the abort callback
2382 //callbacks
2383 //callbacks  `data`::
2384 //callbacks     Global data defined by the user, passed arround (see below)
2385 //callbacks
2386
2387 //callbacks PARA passing data to callbacks; callback_data; data to be passed to callbacks
2388 extern
2389 void* nobug_callback_data;                              //callbacks  VERBATIM;
2390 //callbacks
2391 //callbacks This global variable is initialized to `NULL` and will never be touched by NoBug. One can use it
2392 //callbacks to pass extra data to the callback functions.
2393 //callbacks
2394
2395 //callbacks PARA callback when logging; logging_callback; hook when something get logged
2396 extern
2397 nobug_logging_cb nobug_logging_callback;                //callbacks  VERBATIM;
2398 //callbacks
2399 //callbacks This callback gets called when something gets logged.
2400 //callbacks NoBug will still hold its mutexes when calling this hook, calling NoBug logging or resource tracking
2401 //callbacks functions from here recursively will deadlock and must be avoided.
2402 //callbacks The `log` parameter points to the logging message in the ringbuffer.
2403 //callbacks Unlike other logging targets it is not automatically limited to the log level configured
2404 //callbacks in the flag but called unconditionally. The callback should implement its own limiting.
2405 //callbacks
2406 //callbacks When one wants to do complex calls which may include recursion into logging and resource tracking
2407 //callbacks functions, the intended way is to pass contextual information possibly including a __copy__ of the
2408 //callbacks `log` parameter in xref:THREAD_DATA[NOBUG_THREAD_DATA] to the postlogging callback (see below).
2409 //callbacks Other internal NoBug facilties, like the ringbuffer etc, are protected by the mutexes and may be accessed
2410 //callbacks from this function.
2411 //callbacks
2412
2413 //callbacks PARA callback after logging; postlogging_callback; hook after something get logged
2414 extern
2415 nobug_logging_cb nobug_postlogging_callback;            //callbacks  VERBATIM;
2416 //callbacks
2417 //callbacks This callback gets called after something got logged. The `log` parameter is always NULL and all
2418 //callbacks NoBug mutexes are released. This means that this function may call any complex things, including
2419 //callbacks calling logging and resource tracking, but may not call internal NoBug facilities.
2420 //callbacks Contextual created in the `nobug_logging_callback` and stored in xref:THREAD_DATA[NOBUG_THREAD_DATA] can be
2421 //callbacks retrieved here and may need to be cleaned up here.
2422 //callbacks
2423
2424 //callbacks PARA callback for aborting; abort_callback; hook to handle a termination
2425 extern
2426 nobug_abort_cb nobug_abort_callback;            //callbacks  VERBATIM;
2427 //callbacks
2428 //callbacks This callback gets called when the application shall be terminated due an error.
2429 //callbacks It can be used to hook exceptions or similar things in. When it returns, `abort()`
2430 //callbacks is called.
2431 //callbacks
2432 //callbacks IMPORTANT: Errors detected by NoBug are always fatal. If one handles and possible
2433 //callbacks            throws an exception here, the application must shut down as soon as possible.
2434 //callbacks            Most causes for aborts are optimitzed out in `RELEASE` builds.
2435 //callbacks
2436
2437
2438 /* block statement macros for sections must not be left by a jump this function will assert this with a NOBUG_CLEANUP attribute */
2439 static inline void
2440 nobug_section_cleaned (int* self)
2441 {
2442   if (!self)
2443     {
2444       nobug_log (&nobug_flag_NOBUG_ON,
2445                  LOG_EMERG, "RESOURCE_SECTION",
2446                  NOBUG_CONTEXT_NIL,
2447                  "illegal leaving of resource section (goto, return, ..)");
2448       abort();
2449     }
2450 }
2451
2452
2453 #ifdef __cplusplus
2454 } /* extern "C" */
2455 #endif
2456
2457 #ifndef NOBUG_LIBNOBUG_C
2458
2459 /*
2460   tag this translation unit as unchecked in ALPHA and BETA builds
2461 */
2462 NOBUG_IF_NOT_RELEASE(NOBUG_UNCHECKED);
2463
2464 #else
2465 /* some configuration when compiling nobug */
2466 /* Maximal length of a log line header (silently truncated if exceed) */
2467 #define NOBUG_MAX_LOG_HEADER_SIZE 128
2468 /* Maximal linebreaks in a single logging instruction which get translated to multiple lines */
2469 #define NOBUG_MAX_LOG_LINES 32
2470
2471 #endif /* NOBUG_LIBNOBUG_C */
2472 #endif