RE/flex debug logs and assertions.
- Author
- Robert van Engelen - engel.nosp@m.en@g.nosp@m.enivi.nosp@m.a.co.nosp@m.m
- Copyright
- (c) 2016-2020, Robert van Engelen, Genivia Inc. All rights reserved.
-
(c) BSD-3 License - see LICENSE.txt
Exploiting macro magic to simplify debug logging.
Usage
Enable macro DEBUG to debug the compiled source code:
Source files compiled with | DBGLOG(...) entry added to |
c++ -DDEBUG | DEBUG.log |
c++ -DDEBUG=TEST | TEST.log |
c++ -DDEBUG= | stderr |
DBGLOG(format, ...)
creates a timestamped log entry with a printf-formatted message. The log entry is added to a log file or sent to stderr
as specified:
DBGLOGN(format, ...)
creates a log entry without a timestamp.
DBGLOGA(format, ...)
appends the formatted string to the previous log entry.
DBGCHK(condition)
calls assert(condition)
when compiled in DEBUG mode.
The utility macro DBGSTR(const char *s)
returns string s
or "(null)"
when s == NULL
.
- Note
- to temporarily enable debugging a specific block of code without globally debugging all code, use a leading underscore, e.g.
_DBGLOG(format, ...)
. This appends the debugging information to DEBUG.log
.
- Warning
- Be careful to revert these statements by removing the leading underscore for production-quality code.
Example
int main(
int argc,
char *argv[])
{
FILE *fd;
if ((fd = fopen("foo.bar", "r")) == NULL)
{
for (int i = 1; i < argc; ++i)
}
else
{
fclose(fd);
}
}
Compiled with -DDEBUG
this example logs the following messages in DEBUG.log
:
140201/225654.692194 example.cpp:11 Program has started
140201/225654.692564 example.cpp:15 Error 2: No such file or directory
140201/225654.692577 example.cpp:17 Program ended
The first column records the date (140201 is February 1, 2014) and the time (225654 is 10:56PM + 54 seconds) with microsecond fraction. The second column records the source code file name and the line number of the DBGLOG
command. The third column shows the printf-formatted message.
The DEBUG.log
file is created in the current directory when it does not already exist.
Techniques used:
- Variadic macros with
__VA_ARGS__
.
- Standard predefined macros
__FILE__
and __LINE__
.
- Macro "stringification": expand content of macro
DEBUG
as a string in a macro body.
#if DEBUG + 0
to test whether macro DEBUG
is set to a value, since DEBUG
is 1 when set without a value (for example at the command line).
"" __VA_ARGS__
forces __VA_ARGS__
to start with a literal format string (printf security advisory).