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).