diff options
-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 |