summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2025-03-03 16:57:28 -0500
committerTavian Barnes <tavianator@tavianator.com>2025-03-04 11:46:00 -0500
commit5c5ae3962c46cf4051bcd6d4e2355422e63de42b (patch)
tree6552fb22344d8385fc1b253448d5a29982488f3a
parent1aefb830360e43b6e5ddee96791eb83cdad766cc (diff)
downloadbfs-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.c6
-rw-r--r--build/header.mk1
-rw-r--r--src/diag.c18
-rw-r--r--src/diag.h73
-rw-r--r--tests/tests.h28
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 \
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 <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