diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2025-03-03 16:57:28 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2025-03-04 11:46:00 -0500 |
commit | 5c5ae3962c46cf4051bcd6d4e2355422e63de42b (patch) | |
tree | 6552fb22344d8385fc1b253448d5a29982488f3a | |
parent | 1aefb830360e43b6e5ddee96791eb83cdad766cc (diff) | |
download | bfs-5c5ae3962c46cf4051bcd6d4e2355422e63de42b.tar.xz |
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.
-rw-r--r-- | build/has/compound-literal-storage.c | 6 | ||||
-rw-r--r-- | build/header.mk | 1 | ||||
-rw-r--r-- | src/diag.c | 18 | ||||
-rw-r--r-- | src/diag.h | 73 | ||||
-rw-r--r-- | tests/tests.h | 28 |
5 files changed, 56 insertions, 70 deletions
diff --git a/build/has/compound-literal-storage.c b/build/has/compound-literal-storage.c deleted file mode 100644 index e2281e1..0000000 --- a/build/has/compound-literal-storage.c +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright © Tavian Barnes <tavianator@tavianator.com> -// SPDX-License-Identifier: 0BSD - -int main(void) { - return (static int){0}; -} diff --git a/build/header.mk b/build/header.mk index 19cb175..0e3af14 100644 --- a/build/header.mk +++ b/build/header.mk @@ -19,7 +19,6 @@ HEADERS := \ gen/has/acl-is-trivial-np.h \ gen/has/acl-trivial.h \ gen/has/builtin-riscv-pause.h \ - gen/has/compound-literal-storage.h \ gen/has/confstr.h \ gen/has/dprintf.h \ gen/has/extattr-get-file.h \ @@ -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(); @@ -14,69 +14,68 @@ #include <stdarg.h> /** - * 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. diff --git a/tests/tests.h b/tests/tests.h index 4c6b3d2..8b7d691 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -45,26 +45,30 @@ bool bfs_check_impl(bool result); * Check a condition, logging a message on failure but continuing. */ #define bfs_check(...) \ - bfs_check_impl(bfs_check_(#__VA_ARGS__, __VA_ARGS__, "", "")) + bfs_check_(#__VA_ARGS__, __VA_ARGS__, "", ) #define bfs_check_(str, cond, format, ...) \ - ((cond) ? true : (bfs_diag( \ - sizeof(format) > 1 \ - ? "%.0s" format "%s%s" \ - : "Check failed: `%s`%s", \ - str, __VA_ARGS__), false)) + bfs_check_impl((cond) || (bfs_check__(str, format, __VA_ARGS__), false)) + +#define bfs_check__(str, format, ...) \ + bfs_diagf(sizeof(format) > 1 \ + ? BFS_DIAG_FORMAT_("%.0s" format "%s") \ + : BFS_DIAG_FORMAT_("Check failed: `%s`"), \ + BFS_DIAG_ARGS_(str, __VA_ARGS__)) /** * Check a condition, logging the current error string on failure. */ #define bfs_echeck(...) \ - bfs_check_impl(bfs_echeck_(#__VA_ARGS__, __VA_ARGS__, "", errstr())) + bfs_echeck_(#__VA_ARGS__, __VA_ARGS__, "", ) #define bfs_echeck_(str, cond, format, ...) \ - ((cond) ? true : (bfs_diag( \ - sizeof(format) > 1 \ - ? "%.0s" format "%s: %s" \ - : "Check failed: `%s`: %s", \ - str, __VA_ARGS__), false)) + bfs_check_impl((cond) || (bfs_echeck__(str, format, __VA_ARGS__), false)) + +#define bfs_echeck__(str, format, ...) \ + bfs_diagf(sizeof(format) > 1 \ + ? BFS_DIAG_FORMAT_("%.0s" format "%s: %s") \ + : BFS_DIAG_FORMAT_("Check failed: `%s`: %s"), \ + BFS_DIAG_ARGS_(str, __VA_ARGS__ errstr(), )) #endif // BFS_TESTS_H |