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