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