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