diff options
Diffstat (limited to 'src/diag.h')
-rw-r--r-- | src/diag.h | 144 |
1 files changed, 105 insertions, 39 deletions
@@ -8,93 +8,147 @@ #ifndef BFS_DIAG_H #define BFS_DIAG_H -#include "ctx.h" -#include "config.h" +#include "bfs.h" +#include "bfstd.h" + #include <stdarg.h> /** - * static_assert() with an optional second argument. + * Wrap a diagnostic format string so it looks like + * + * bfs: func@src/file.c:0: Message */ -#if __STDC_VERSION__ >= 202311L -# define bfs_static_assert static_assert -#else -# define bfs_static_assert(...) bfs_static_assert_(__VA_ARGS__, #__VA_ARGS__, ) -# define bfs_static_assert_(expr, msg, ...) _Static_assert(expr, msg) -#endif +// Use (format) ? "..." : "" so the format string is required +#define BFS_DIAG_FORMAT_(format) \ + ((format) ? "%s: %s@%s:%d: " format "%s" : "") /** - * A source code location. + * Add arguments to match a BFS_DIAG_FORMAT string. */ -struct bfs_loc { - const char *file; - int line; - const char *func; -}; +#define BFS_DIAG_ARGS_(...) \ + xgetprogname(), __func__, __FILE__, __LINE__, __VA_ARGS__ __VA_OPT__(,) "\n" + +/** + * Print a low-level diagnostic message to standard error. + */ +[[_printf(1, 2)]] +void bfs_diagf(const char *format, ...); -#define BFS_LOC_INIT { .file = __FILE__, .line = __LINE__, .func = __func__ } +/** + * Unconditional diagnostic message. + */ +#define bfs_diag(format, ...) \ + bfs_diagf(BFS_DIAG_FORMAT_(format), BFS_DIAG_ARGS_(__VA_ARGS__)) /** - * Get the current source code location. + * Print a diagnostic message including the last error. */ -#if __STDC_VERSION__ >= 202311L -# define bfs_location() (&(static const struct bfs_loc)BFS_LOC_INIT) -#else -# define bfs_location() (&(const struct bfs_loc)BFS_LOC_INIT) -#endif +#define bfs_ediag(format, ...) \ + BFS_VA_IF(format) \ + (bfs_diag(format ": %s", __VA_ARGS__ __VA_OPT__(,) errstr())) \ + (bfs_diag("%s", errstr())) /** * Print a message to standard error and abort. */ -BFS_FORMATTER(2, 3) -noreturn void bfs_abortf(const struct bfs_loc *loc, const char *format, ...); +[[_cold]] +[[_printf(1, 2)]] +[[_noreturn]] +void bfs_abortf(const char *format, ...); /** * Unconditional abort with a message. */ -#define bfs_abort(...) bfs_abortf(bfs_location(), __VA_ARGS__) +#define bfs_abort(format, ...) \ + bfs_abortf(BFS_DIAG_FORMAT_(format), BFS_DIAG_ARGS_(__VA_ARGS__)) + +/** + * Abort with a message including the last error. + */ +#define bfs_eabort(format, ...) \ + BFS_VA_IF(__VA_ARGS__) \ + (bfs_abort(format ": %s", __VA_ARGS__ __VA_OPT__(,) errstr())) \ + (bfs_abort("%s", errstr())) /** * Abort in debug builds; no-op in release builds. */ #ifdef NDEBUG # define bfs_bug(...) ((void)0) +# define bfs_ebug(...) ((void)0) #else # define bfs_bug bfs_abort +# define bfs_ebug bfs_eabort #endif /** * Unconditional assert. */ -#define bfs_verify(...) \ - bfs_verify_(#__VA_ARGS__, __VA_ARGS__, "", "") +#define bfs_verify(cond, ...) \ + ((cond) ? (void)0 : BFS_VA_IF(__VA_ARGS__) \ + (bfs_abort(__VA_ARGS__)) \ + (bfs_abort("Assertion failed: `%s`", #cond))) -#define bfs_verify_(str, cond, format, ...) \ - ((cond) ? (void)0 : bfs_abort( \ - sizeof(format) > 1 \ - ? "%.0s" format "%s%s" \ - : "Assertion failed: `%s`%s", \ - str, __VA_ARGS__)) +/** + * Unconditional assert, including the last error. + */ +#define bfs_everify(cond, ...) \ + ((cond) ? (void)0 : BFS_VA_IF(__VA_ARGS__) \ + (bfs_eabort(__VA_ARGS__)) \ + (bfs_eabort("Assertion failed: `%s`", #cond))) /** * Assert in debug builds; no-op in release builds. */ #ifdef NDEBUG # define bfs_assert(...) ((void)0) +# define bfs_eassert(...) ((void)0) #else # define bfs_assert bfs_verify +# define bfs_eassert bfs_everify #endif +struct bfs_ctx; struct bfs_expr; /** + * Various debugging flags. + */ +enum debug_flags { + /** Print cost estimates. */ + DEBUG_COST = 1 << 0, + /** Print executed command details. */ + DEBUG_EXEC = 1 << 1, + /** Print optimization details. */ + DEBUG_OPT = 1 << 2, + /** Print rate information. */ + DEBUG_RATES = 1 << 3, + /** Trace the filesystem traversal. */ + DEBUG_SEARCH = 1 << 4, + /** Trace all stat() calls. */ + DEBUG_STAT = 1 << 5, + /** Print the parse tree. */ + DEBUG_TREE = 1 << 6, + /** All debug flags. */ + DEBUG_ALL = (1 << 7) - 1, +}; + +/** + * Convert a debug flag to a string. + */ +const char *debug_flag_name(enum debug_flags flag); + +/** * Like perror(), but decorated like bfs_error(). */ +[[_cold]] void bfs_perror(const struct bfs_ctx *ctx, const char *str); /** * Shorthand for printing error messages. */ -BFS_FORMATTER(2, 3) +[[_cold]] +[[_printf(2, 3)]] void bfs_error(const struct bfs_ctx *ctx, const char *format, ...); /** @@ -102,7 +156,8 @@ void bfs_error(const struct bfs_ctx *ctx, const char *format, ...); * * @return Whether a warning was printed. */ -BFS_FORMATTER(2, 3) +[[_cold]] +[[_printf(2, 3)]] bool bfs_warning(const struct bfs_ctx *ctx, const char *format, ...); /** @@ -110,60 +165,71 @@ bool bfs_warning(const struct bfs_ctx *ctx, const char *format, ...); * * @return Whether a debug message was printed. */ -BFS_FORMATTER(3, 4) +[[_cold]] +[[_printf(3, 4)]] bool bfs_debug(const struct bfs_ctx *ctx, enum debug_flags flag, const char *format, ...); /** * bfs_error() variant that takes a va_list. */ -BFS_FORMATTER(2, 0) +[[_cold]] +[[_printf(2, 0)]] void bfs_verror(const struct bfs_ctx *ctx, const char *format, va_list args); /** * bfs_warning() variant that takes a va_list. */ -BFS_FORMATTER(2, 0) +[[_cold]] +[[_printf(2, 0)]] bool bfs_vwarning(const struct bfs_ctx *ctx, const char *format, va_list args); /** * bfs_debug() variant that takes a va_list. */ -BFS_FORMATTER(3, 0) +[[_cold]] +[[_printf(3, 0)]] bool bfs_vdebug(const struct bfs_ctx *ctx, enum debug_flags flag, const char *format, va_list args); /** * Print the error message prefix. */ +[[_cold]] void bfs_error_prefix(const struct bfs_ctx *ctx); /** * Print the warning message prefix. */ +[[_cold]] bool bfs_warning_prefix(const struct bfs_ctx *ctx); /** * Print the debug message prefix. */ +[[_cold]] bool bfs_debug_prefix(const struct bfs_ctx *ctx, enum debug_flags flag); /** * Highlight parts of the command line in an error message. */ +[[_cold]] void bfs_argv_error(const struct bfs_ctx *ctx, const bool args[]); /** * Highlight parts of an expression in an error message. */ +[[_cold]] void bfs_expr_error(const struct bfs_ctx *ctx, const struct bfs_expr *expr); /** * Highlight parts of the command line in a warning message. */ +[[_cold]] bool bfs_argv_warning(const struct bfs_ctx *ctx, const bool args[]); /** * Highlight parts of an expression in a warning message. */ +[[_cold]] bool bfs_expr_warning(const struct bfs_ctx *ctx, const struct bfs_expr *expr); #endif // BFS_DIAG_H |