3 Nobug is a simple debugging library (only a single nobug.h header) similar to
4 gnu-nana and Design-by-Contract ideas.
8 Nobug provides you with:
10 * Three different levels for checks (in depth to final no-overhead)
11 * Scope tags (tell whenever a function or loop is considered to be bug free)
12 * Pre-, Postcondition and Invariant checks, generic Assertions
13 * Debugger support (actions are only executed while running under a
14 debugger), currently only valgrind
15 * Dumping of your datastructures
16 * Logging your application's activities
17 * Runtime customizable logging via an enviromnet variable
18 * Different logging targets (stderr, syslog, debugger...)
19 * Annotation of your sourcecode about known bugs, things to do and planned
26 Nobug uses different levels of checks:
29 + for expensive testing and logging while developing the software
31 + for testers and users who want to try the software
33 + finished version for end users
35 Release builds remove all assertions (but some logging is kept) we make the
36 assumption that bugs which where not covered in alpha and beta builds won't be
37 easily show up in releases because the assertions there where not sufficent.
38 Further end users are not test bunnies and wont provide good bug reports
39 anyways. If there is a problem in a release build, then try to investigate the
40 cause with a beta build from the same source.
42 To define a debug level for compilation just use '-DEBUG_ALPHA', '-DEBUG_BETA'
43 for Debug Builds or the standard '-DNDEBUG' for a release build. Nobug will
44 complain if none of this is defined.
48 The programmer can tag any Scope as UNCHECKED or CHECKED. In ALPHA and BETA
49 builds a global UNCHECKED is implied, while in RELEASE builds a global CHECKED
50 is used and UNCHECKED Scopes are not allowed.
54 Here is a table which basic assertions gets checked on each level/scope
58 UNCHECKED Preconditions, Postconditions, Preconditions, compiling will
59 Invariants Postconditions abort
60 CHECKED Preconditions, Postconditions Preconditions
64 Nobug is almost completely implemented in preprocessor macros, this is needed
65 because it uses the __FILE__ and __LINE__ macros for logging. All its flat
66 namespace uppercase identifiers make it good recognizeable in a source too.
68 All macros are unconditionally available with NOBUG_ prefixed, for convinience
69 there are also macros without this prefix unless such a macro was already
70 defined. For each Assertion and Logging macro there is a form with _DBG as
71 suffix which will be only active under a debugger. The _DBG versions are only
72 enabled in alpha builds.
74 There are also assertions with a _IF suffix taking a 'when' parameter as first
77 * REQUIRE_IF(foo!=NULL, foo->something == constrained)
79 they only perform the assertion when when is true. The debugger versions are
80 available as _IF_DBG prefixed macros.
84 when assertion is only performed if expression 'when' is true at runtime
85 expr test without side effects
86 fmt printf like formatstring
87 ... if not preceeded by 'fmt' then printf like formatstring else only its
89 what reason for a failure as string literal
90 flag flag for enabling custom logging groups
91 type type of the to be checked data as single identifier name
92 pointer pointer to type
94 depth depth for invariants and dumps
99 + Precondition (input) check
101 + Postcondition (progress/output) check
102 ASSERT(expr, what, ...)
104 INVARIANT(type, pointer, depth)
105 + Checking invariants
109 Logging is controlled by user defined flags and a log limit.
113 Each Log macro has a explicit or implicit Log-Level which correspondends to
114 syslog levels. Logging is only emitted when the current NOBUG_LOG_LIMIT is more
115 servere than the one of the Log message.
117 * In ALPHA builds, NOBUG_LOG_LIMIT_ALPHA is used which defaults to LOG_INFO
118 * In BETA builds, NOBUG_LOG_LIMIT_BETA is used and defaults to LOG_WARNING
119 * In RELEASE builds, NOBUG_LOG_LIMIT_RELEASE is used and defaults to LOG_CRIT
121 You can override all of those three with your own preference. Alternatively
122 NOBUG_LOG_LIMIT can be defined by the user to override all defaults.
124 Further the NOBUG_LOG_LIMIT can be initialized in ALPHA and BETA builds by the
125 NOBUG_LIMIT enviroment variable. The NOBUG_INIT_FLAG below takes care of this.
129 Flag is just a C identifier and should be declared with
131 * NOBUG_DECLARE_FLAG(flagname)
133 preferably in one of your headers
135 Further it must be defined with
137 * NOBUG_DEFINE_FLAG(flagname)
139 in one of your source files
143 * NOBUG_INIT_FLAG(flagname)
145 once at the start of your program
147 Flags are initially set to -1 (nothing gets logged), NOBUG_INIT_FLAG(flagname)
148 checks if flagname is present in the environment variable 'NOBUG_LOG' and then
149 sets the flag to the current limit. You can query the flag state with
150 NOBUG_FLAG(flagname).
152 There is a predefined flag NOBUG_ON which is always enabled.
157 2 NOBUG_DEFINE_FLAG (test);
160 5 NOBUG_INIT_FLAG (test);
162 7 INFO (test, "Logging enabled");
163 8 INFO (NOBUG_ON, "Always on");
168 $ tcc -DEBUG_ALPHA -run example.c
169 DEBUG: main : Always on
170 $ NOBUG_LOG=test tcc -DEBUG_ALPHA -run example.c
171 DEBUG: main : Logging enabled
172 DEBUG: main : Always on
173 $ NOBUG_LIMIT=CRIT NOBUG_LOG=test tcc -DEBUG_ALPHA -run example.c
178 These macros log with implicit Log Level, note that there are no more servere
179 levels than LOG_ERROR since these should be handled by Assertions in a
182 * ERROR(flag, fmt, ...)
183 ERROR_IF(expr, rflag, fmt, ...)
184 + Application takes a error handling brach
187 WARN_IF(expr, flag, fmt, ...)
188 + Rare, handled but unexpected branch
191 INFO_IF(expr, flag, fmt, ...)
192 + Message about program progress
194 NOTICE(flag, fmt, ...)
195 NOTICE_IF(expr, flag, fmt, ...)
198 TRACE(flag, fmt, ...)
199 TRACE_IF(expr, flag, fmt, ...)
200 + Very fine grained messages
202 Note that TRACE correspondends to LOG_DEBUG, using 'DEBUG' could be ambiguous.
204 There is one generic LOG macro which takes the level explicitly:
206 * LOG(flag, lvl, fmt, ...)
207 LOG_IF(expr, flag, lvl, fmt, ...)
209 Dumping Datastructures
211 * DUMP(type, pointer, depth)
212 + Dump a datastructure
213 DUMP_IF(expr, type, pointer, depth)
214 + Dump datastructure if expr is true
218 One can tagging features as:
221 + important, not yet finished feature
223 + planned for future feature
225 + known bug to be fixed later
227 + enhancement to be done soon
229 + used to tag code-path which shall be never executed (defaults in switch
230 statements, else NOTREACHED after series of if's)
232 The advantage of this tagging over plain source comments is that we can take
233 some actions if we run in such a tag at compile or runtime:
235 the action to be taken when such a macro is hit depends on the build level:
238 UNIMPLEMENTED abort abort wont compile
239 BUG log abort wont compile
240 TODO log log wont compile
241 PLANNED log nothing nothing
242 NOTREACHED abort abort removed
246 * abort means first log and then abort
247 * log will only log once for each sourceline (not on each hit)
248 * wont compile will abort compilation with a error message
249 * nothing optimized out, sane way
250 * removed optimized out for performance reasons
257 This Documentation is maintained at:
259 * http://www.pipapo.org/pipawiki/NoBug/Documentation
261 NoBug/Documentation (last edited 2007-01-16 15:18:28 by ct)