From 5c5ae3962c46cf4051bcd6d4e2355422e63de42b Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 3 Mar 2025 16:57:28 -0500 Subject: diag: Get rid of struct bfs_location Just add the standard prefix to the passed format string in the diagnostic macros themselves. This lets us write the whole message with one dprintf() call, minimizing interleaving. It's also a net win for binary size. --- src/diag.c | 18 ++++------------ src/diag.h | 73 +++++++++++++++++++++++++++++++------------------------------- 2 files changed, 40 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/diag.c b/src/diag.c index 4f1c84c..a86b060 100644 --- a/src/diag.c +++ b/src/diag.c @@ -21,33 +21,23 @@ * async-signal-safe in practice. */ #if BFS_HAS_DPRINTF -# define eprintf(...) dprintf(STDERR_FILENO, __VA_ARGS__) # define veprintf(...) vdprintf(STDERR_FILENO, __VA_ARGS__) #else -# define eprintf(...) fprintf(stderr, __VA_ARGS__) # define veprintf(...) vfprintf(stderr, __VA_ARGS__) #endif -/** bfs_diagf() implementation. */ -_printf(2, 0) -static void bfs_vdiagf(const struct bfs_loc *loc, const char *format, va_list args) { - eprintf("%s: %s@%s:%d: ", xgetprogname(), loc->func, loc->file, loc->line); - veprintf(format, args); - eprintf("\n"); -} - -void bfs_diagf(const struct bfs_loc *loc, const char *format, ...) { +void bfs_diagf(const char *format, ...) { va_list args; va_start(args, format); - bfs_vdiagf(loc, format, args); + veprintf(format, args); va_end(args); } _noreturn -void bfs_abortf(const struct bfs_loc *loc, const char *format, ...) { +void bfs_abortf(const char *format, ...) { va_list args; va_start(args, format); - bfs_vdiagf(loc, format, args); + veprintf(format, args); va_end(args); abort(); diff --git a/src/diag.h b/src/diag.h index 7b3e8a5..a8ee911 100644 --- a/src/diag.h +++ b/src/diag.h @@ -14,69 +14,68 @@ #include /** - * A source code location. + * Wrap a diagnostic format string so it looks like + * + * bfs: func@src/file.c:0: Message */ -struct bfs_loc { - const char *file; - int line; - const char *func; -}; - -#define BFS_LOC_INIT { .file = __FILE__, .line = __LINE__, .func = __func__ } +#define BFS_DIAG_FORMAT_(format) \ + ((format) ? "%s: %s@%s:%d: " format "%s" : "") /** - * Get the current source code location. + * Add arguments to match a BFS_DIAG_FORMAT string. */ -#if BFS_HAS_COMPOUND_LITERAL_STORAGE -# 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_DIAG_ARGS_(...) \ + xgetprogname(), __func__, __FILE__, __LINE__, __VA_ARGS__ "\n" /** - * Print a low-level diagnostic message to standard error, formatted like - * - * bfs: func@src/file.c:0: Message + * Print a low-level diagnostic message to standard error. */ -_printf(2, 3) -void bfs_diagf(const struct bfs_loc *loc, const char *format, ...); +_printf(1, 2) +void bfs_diagf(const char *format, ...); /** * Unconditional diagnostic message. */ -#define bfs_diag(...) bfs_diagf(bfs_location(), __VA_ARGS__) +#define bfs_diag(...) \ + bfs_diag_(__VA_ARGS__, ) + +#define bfs_diag_(format, ...) \ + bfs_diagf(BFS_DIAG_FORMAT_(format), BFS_DIAG_ARGS_(__VA_ARGS__)) /** * Print a diagnostic message including the last error. */ #define bfs_ediag(...) \ - bfs_ediag_("" __VA_ARGS__, errstr()) + bfs_ediag_(__VA_ARGS__, ) #define bfs_ediag_(format, ...) \ - bfs_diag(sizeof(format) > 1 ? format ": %s" : "%s", __VA_ARGS__) + bfs_diag_(format "%s%s", __VA_ARGS__ (sizeof("" format) > 1 ? ": " : ""), errstr(), ) /** * Print a message to standard error and abort. */ _cold -_printf(2, 3) +_printf(1, 2) _noreturn -void bfs_abortf(const struct bfs_loc *loc, const char *format, ...); +void bfs_abortf(const char *format, ...); /** * Unconditional abort with a message. */ #define bfs_abort(...) \ - bfs_abortf(bfs_location(), __VA_ARGS__) + bfs_abort_(__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(...) \ - bfs_eabort_("" __VA_ARGS__, errstr()) + bfs_eabort_(__VA_ARGS__, ) #define bfs_eabort_(format, ...) \ - bfs_abort(sizeof(format) > 1 ? format ": %s" : "%s", __VA_ARGS__) + ((format) ? bfs_abort_(format ": %s", __VA_ARGS__ errstr(), ) : (void)0) /** * Abort in debug builds; no-op in release builds. @@ -93,27 +92,27 @@ void bfs_abortf(const struct bfs_loc *loc, const char *format, ...); * Unconditional assert. */ #define bfs_verify(...) \ - bfs_verify_(#__VA_ARGS__, __VA_ARGS__, "", "") + bfs_verify_(#__VA_ARGS__, __VA_ARGS__, "", ) #define bfs_verify_(str, cond, format, ...) \ - ((cond) ? (void)0 : bfs_abort( \ + ((cond) ? (void)0 : bfs_abortf( \ sizeof(format) > 1 \ - ? "%.0s" format "%s%s" \ - : "Assertion failed: `%s`%s", \ - str, __VA_ARGS__)) + ? BFS_DIAG_FORMAT_("%.0s" format "%s") \ + : BFS_DIAG_FORMAT_("Assertion failed: `%s`"), \ + BFS_DIAG_ARGS_(str, __VA_ARGS__))) /** * Unconditional assert, including the last error. */ #define bfs_everify(...) \ - bfs_everify_(#__VA_ARGS__, __VA_ARGS__, "", errstr()) + bfs_everify_(#__VA_ARGS__, __VA_ARGS__, "", ) #define bfs_everify_(str, cond, format, ...) \ - ((cond) ? (void)0 : bfs_abort( \ + ((cond) ? (void)0 : bfs_abortf( \ sizeof(format) > 1 \ - ? "%.0s" format "%s: %s" \ - : "Assertion failed: `%s`: %s", \ - str, __VA_ARGS__)) + ? BFS_DIAG_FORMAT_("%.0s" format "%s: %s") \ + : BFS_DIAG_FORMAT_("Assertion failed: `%s`: %s"), \ + BFS_DIAG_ARGS_(str, __VA_ARGS__ errstr(), ))) /** * Assert in debug builds; no-op in release builds. -- cgit v1.2.3