|  | debug.h File Reference updated Sun May 12 2024 by Robert van Engelen |

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

Macros | Functions | Variables
debug.h File Reference

RE/flex debug logs and assertions. More...

`#include <cassert>`
`#include <cstdio>`
Include dependency graph for debug.h:
This graph shows which files directly or indirectly include this file:

## Macros
#define | ASSERT(c)
| If ASSERT not defined, make ASSERT a no-op. More...
#define | DBGXIFY(S) DBGIFY_(S)
#define | DBGIFY_(S) #S
#define | DBGFILE DBGXIFY(DEBUG) ".log"
#define | DBGSTR(S) (S?S:"(NULL)")
#define | _DBGLOG(...) ( REFLEX_DBGOUT_(DBGFILE, __FILE__, __LINE__), ::fprintf(REFLEX_DBGFD_, "" __VA_ARGS__), ::fflush(REFLEX_DBGFD_))
#define | _DBGLOGN(...) ( ::fprintf(REFLEX_DBGFD_, "\n " __VA_ARGS__), ::fflush(REFLEX_DBGFD_) )
#define | _DBGLOGA(...) ( ::fprintf(REFLEX_DBGFD_, "" __VA_ARGS__), ::fflush(REFLEX_DBGFD_) )
#define | DBGCHK(c) (void)0
#define | DBGLOG(...) (void)0
#define | DBGLOGN(...) (void)0
#define | DBGLOGA(...) (void)0

## Functions
void | REFLEX_DBGOUT_ (const char *log, const char *file, int line)

## Variables
FILE * | REFLEX_DBGFD_

## Detailed Description

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

#include <reflex/debug.h>
int main(int argc, char *argv[])
{
FILE *fd;
DBGLOG("Program start");
if ((fd = fopen("foo.bar", "r")) == NULL)
{
DBGLOG("Error %d: %s ", errno, DBGSTR(strerror(errno)));
for (int i = 1; i < argc; ++i)
DBGLOGA(" %s", argv[1]);
}
else
{
DBGCHK(fd != NULL);
// OK, so go ahead to read foo.bar ...
// ...
fclose(fd);
}
DBGLOG("Program end");
}

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

## Macro Definition Documentation

#define _DBGLOG | ( |  | ... | ) | ( REFLEX_DBGOUT_(DBGFILE, __FILE__, __LINE__), ::fprintf(REFLEX_DBGFD_, "" __VA_ARGS__), ::fflush(REFLEX_DBGFD_))

#define _DBGLOGA | ( |  | ... | ) | ( ::fprintf(REFLEX_DBGFD_, "" __VA_ARGS__), ::fflush(REFLEX_DBGFD_) )

#define _DBGLOGN | ( |  | ... | ) | ( ::fprintf(REFLEX_DBGFD_, "\n " __VA_ARGS__), ::fflush(REFLEX_DBGFD_) )

#define ASSERT | ( |  | c | ) |

If ASSERT not defined, make ASSERT a no-op.

#define DBGCHK | ( |  | c | ) | (void)0

#define DBGFILE DBGXIFY(DEBUG) ".log"

#define DBGIFY_ | ( |  | S | ) | #S

#define DBGLOG | ( |  | ... | ) | (void)0

#define DBGLOGA | ( |  | ... | ) | (void)0

#define DBGLOGN | ( |  | ... | ) | (void)0

#define DBGSTR | ( |  | S | ) | (S?S:"(NULL)")

#define DBGXIFY | ( |  | S | ) | DBGIFY_(S)

## Function Documentation

void REFLEX_DBGOUT_ | ( | const char * | log,
|  | const char * | file,
|  | int | line
| ) |  |

## Variable Documentation

FILE* REFLEX_DBGFD_