summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2023-11-16 12:25:09 -0500
committerTavian Barnes <tavianator@tavianator.com>2023-12-18 15:37:20 -0500
commit5b38f658ee42bef05cecb6cadec65b25d9e94993 (patch)
tree7ee304714729b360a3d45658ca27358e03cd54e3 /src
parentfd91097055f095fdd827ef8751d9534f59a89404 (diff)
downloadbfs-5b38f658ee42bef05cecb6cadec65b25d9e94993.tar.xz
config: New variadic attr(...) macro
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c2
-rw-r--r--src/alloc.h10
-rw-r--r--src/bar.c2
-rw-r--r--src/color.c4
-rw-r--r--src/color.h4
-rw-r--r--src/config.h74
-rw-r--r--src/diag.h37
-rw-r--r--src/dstring.h18
-rw-r--r--src/eval.c2
-rw-r--r--src/exec.c2
-rw-r--r--src/fsade.c6
-rw-r--r--src/ioq.c4
-rw-r--r--src/mtab.c2
-rw-r--r--src/opt.c4
-rw-r--r--src/parse.c14
-rw-r--r--src/trie.c2
-rw-r--r--src/xspawn.c2
17 files changed, 127 insertions, 62 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 467f0f0..b65d0c5 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -176,7 +176,7 @@ void arena_init(struct arena *arena, size_t align, size_t size) {
}
/** Allocate a new slab. */
-attr_cold
+attr(cold)
static int slab_alloc(struct arena *arena) {
// Make the initial allocation size ~4K
size_t size = 4096;
diff --git a/src/alloc.h b/src/alloc.h
index 7132470..f21ddb9 100644
--- a/src/alloc.h
+++ b/src/alloc.h
@@ -114,8 +114,7 @@ static inline size_t flex_size(size_t align, size_t min, size_t offset, size_t s
* @return
* The allocated memory, or NULL on failure.
*/
-attr_malloc(free, 1)
-attr_aligned_alloc(1, 2)
+attr(malloc(free, 1), aligned_alloc(1, 2))
void *alloc(size_t align, size_t size);
/**
@@ -128,8 +127,7 @@ void *alloc(size_t align, size_t size);
* @return
* The allocated memory, or NULL on failure.
*/
-attr_malloc(free, 1)
-attr_aligned_alloc(1, 2)
+attr(malloc(free, 1), aligned_alloc(1, 2))
void *zalloc(size_t align, size_t size);
/** Allocate memory for the given type. */
@@ -252,7 +250,7 @@ void arena_free(struct arena *arena, void *ptr);
/**
* Allocate an object out of the arena.
*/
-attr_malloc(arena_free, 2)
+attr(malloc(arena_free, 2))
void *arena_alloc(struct arena *arena);
/**
@@ -334,7 +332,7 @@ void varena_free(struct varena *varena, void *ptr, size_t count);
* @return
* The allocated struct, or NULL on failure.
*/
-attr_malloc(varena_free, 2)
+attr(malloc(varena_free, 2))
void *varena_alloc(struct varena *varena, size_t count);
/**
diff --git a/src/bar.c b/src/bar.c
index 2e50dbe..babadc3 100644
--- a/src/bar.c
+++ b/src/bar.c
@@ -127,7 +127,7 @@ static void reset_before_death_by(int sig) {
}
/** printf() to the status bar with a single write(). */
-attr_format(2, 3)
+attr(format(2, 3))
static int bfs_bar_printf(struct bfs_bar *bar, const char *format, ...) {
va_list args;
va_start(args, format);
diff --git a/src/color.c b/src/color.c
index 05ba1a3..4c2c8ca 100644
--- a/src/color.c
+++ b/src/color.c
@@ -1105,7 +1105,7 @@ static int print_link_target(CFILE *cfile, const struct BFTW *ftwbuf) {
}
/** Format some colored output to the buffer. */
-attr_format(2, 3)
+attr(format(2, 3))
static int cbuff(CFILE *cfile, const char *format, ...);
/** Dump a parsed expression tree, for debugging. */
@@ -1177,7 +1177,7 @@ static int print_expr(CFILE *cfile, const struct bfs_expr *expr, bool verbose) {
return 0;
}
-attr_format(2, 0)
+attr(format(2, 0))
static int cvbuff(CFILE *cfile, const char *format, va_list args) {
const struct colors *colors = cfile->colors;
int error = errno;
diff --git a/src/color.h b/src/color.h
index 8a81573..81f0e2a 100644
--- a/src/color.h
+++ b/src/color.h
@@ -100,13 +100,13 @@ int cfclose(CFILE *cfile);
* @return
* 0 on success, -1 on failure.
*/
-attr_format(2, 3)
+attr(format(2, 3))
int cfprintf(CFILE *cfile, const char *format, ...);
/**
* cfprintf() variant that takes a va_list.
*/
-attr_format(2, 0)
+attr(format(2, 0))
int cvfprintf(CFILE *cfile, const char *format, va_list args);
#endif // BFS_COLOR_H
diff --git a/src/config.h b/src/config.h
index 9f95674..aa03552 100644
--- a/src/config.h
+++ b/src/config.h
@@ -301,4 +301,78 @@ typedef long double max_align_t;
# define attr_target_clones(...)
#endif
+/**
+ * Shorthand for multiple attributes at once. attr(a, b(c), d) is equivalent to
+ *
+ * attr_a
+ * attr_b(c)
+ * attr_d
+ */
+#define attr(...) \
+ attr__(attr_##__VA_ARGS__, none, none, none, none, none, none, none, none, none)
+
+/**
+ * attr() helper. For exposition, pretend we support only 2 args, instead of 9.
+ * There are a few cases:
+ *
+ * attr()
+ * => attr__(attr_, none, none)
+ * => attr_ =>
+ * attr_none =>
+ * attr_too_many_none() =>
+ *
+ * attr(a)
+ * => attr__(attr_a, none, none)
+ * => attr_a => __attribute__((a))
+ * attr_none =>
+ * attr_too_many_none() =>
+ *
+ * attr(a, b(c))
+ * => attr__(attr_a, b(c), none, none)
+ * => attr_a => __attribute__((a))
+ * attr_b(c) => __attribute__((b(c)))
+ * attr_too_many_none(none) =>
+ *
+ * attr(a, b(c), d)
+ * => attr__(attr_a, b(c), d, none, none)
+ * => attr_a => __attribute__((a))
+ * attr_b(c) => __attribute__((b(c)))
+ * attr_too_many_d(none, none) => error
+ *
+ * Some attribute names are the same as standard library functions, e.g. printf.
+ * Standard libraries are permitted to define these functions as macros, like
+ *
+ * #define printf(...) __builtin_printf(__VA_ARGS__)
+ *
+ * The token paste in
+ *
+ * #define attr(...) attr__(attr_##__VA_ARGS__, none, none)
+ *
+ * is necessary to prevent macro expansion before evaluating attr__().
+ * Otherwise, we could get
+ *
+ * attr(printf(1, 2))
+ * => attr__(__builtin_printf(1, 2), none, none)
+ * => attr____builtin_printf(1, 2)
+ * => error
+ */
+#define attr__(a1, a2, a3, a4, a5, a6, a7, a8, a9, none, ...) \
+ a1 \
+ attr_##a2 \
+ attr_##a3 \
+ attr_##a4 \
+ attr_##a5 \
+ attr_##a6 \
+ attr_##a7 \
+ attr_##a8 \
+ attr_##a9 \
+ attr_too_many_##none(__VA_ARGS__)
+
+// Ignore `attr_none` from expanding 1-9 argument attr(a1, a2, ...)
+#define attr_none
+// Ignore `attr_` from expanding 0-argument attr()
+#define attr_
+// Only trigger an error on more than 9 arguments
+#define attr_too_many_none(...)
+
#endif // BFS_CONFIG_H
diff --git a/src/diag.h b/src/diag.h
index 981419e..aa6a44f 100644
--- a/src/diag.h
+++ b/src/diag.h
@@ -44,8 +44,7 @@ struct bfs_loc {
/**
* Print a message to standard error and abort.
*/
-attr_cold
-attr_format(2, 3)
+attr(cold, format(2, 3))
noreturn void bfs_abortf(const struct bfs_loc *loc, const char *format, ...);
/**
@@ -117,14 +116,13 @@ const char *debug_flag_name(enum debug_flags flag);
/**
* Like perror(), but decorated like bfs_error().
*/
-attr_cold
+attr(cold)
void bfs_perror(const struct bfs_ctx *ctx, const char *str);
/**
* Shorthand for printing error messages.
*/
-attr_cold
-attr_format(2, 3)
+attr(cold, format(2, 3))
void bfs_error(const struct bfs_ctx *ctx, const char *format, ...);
/**
@@ -132,8 +130,7 @@ void bfs_error(const struct bfs_ctx *ctx, const char *format, ...);
*
* @return Whether a warning was printed.
*/
-attr_cold
-attr_format(2, 3)
+attr(cold, format(2, 3))
bool bfs_warning(const struct bfs_ctx *ctx, const char *format, ...);
/**
@@ -141,71 +138,67 @@ bool bfs_warning(const struct bfs_ctx *ctx, const char *format, ...);
*
* @return Whether a debug message was printed.
*/
-attr_cold
-attr_format(3, 4)
+attr(cold, format(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.
*/
-attr_cold
-attr_format(2, 0)
+attr(cold, format(2, 0))
void bfs_verror(const struct bfs_ctx *ctx, const char *format, va_list args);
/**
* bfs_warning() variant that takes a va_list.
*/
-attr_cold
-attr_format(2, 0)
+attr(cold, format(2, 0))
bool bfs_vwarning(const struct bfs_ctx *ctx, const char *format, va_list args);
/**
* bfs_debug() variant that takes a va_list.
*/
-attr_cold
-attr_format(3, 0)
+attr(cold, format(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.
*/
-attr_cold
+attr(cold)
void bfs_error_prefix(const struct bfs_ctx *ctx);
/**
* Print the warning message prefix.
*/
-attr_cold
+attr(cold)
bool bfs_warning_prefix(const struct bfs_ctx *ctx);
/**
* Print the debug message prefix.
*/
-attr_cold
+attr(cold)
bool bfs_debug_prefix(const struct bfs_ctx *ctx, enum debug_flags flag);
/**
* Highlight parts of the command line in an error message.
*/
-attr_cold
+attr(cold)
void bfs_argv_error(const struct bfs_ctx *ctx, const bool args[]);
/**
* Highlight parts of an expression in an error message.
*/
-attr_cold
+attr(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.
*/
-attr_cold
+attr(cold)
bool bfs_argv_warning(const struct bfs_ctx *ctx, const bool args[]);
/**
* Highlight parts of an expression in a warning message.
*/
-attr_cold
+attr(cold)
bool bfs_expr_warning(const struct bfs_ctx *ctx, const struct bfs_expr *expr);
#endif // BFS_DIAG_H
diff --git a/src/dstring.h b/src/dstring.h
index 2a94438..1be1185 100644
--- a/src/dstring.h
+++ b/src/dstring.h
@@ -41,7 +41,7 @@ void dstrfree(dchar *dstr);
* @param cap
* The initial capacity of the string.
*/
-attr_malloc(dstrfree, 1)
+attr(malloc(dstrfree, 1))
dchar *dstralloc(size_t cap);
/**
@@ -50,7 +50,7 @@ dchar *dstralloc(size_t cap);
* @param str
* The NUL-terminated string to copy.
*/
-attr_malloc(dstrfree, 1)
+attr(malloc(dstrfree, 1))
dchar *dstrdup(const char *str);
/**
@@ -61,7 +61,7 @@ dchar *dstrdup(const char *str);
* @param n
* The maximum number of characters to copy from str.
*/
-attr_malloc(dstrfree, 1)
+attr(malloc(dstrfree, 1))
dchar *dstrndup(const char *str, size_t n);
/**
@@ -70,7 +70,7 @@ dchar *dstrndup(const char *str, size_t n);
* @param dstr
* The dynamic string to copy.
*/
-attr_malloc(dstrfree, 1)
+attr(malloc(dstrfree, 1))
dchar *dstrddup(const dchar *dstr);
/**
@@ -81,7 +81,7 @@ dchar *dstrddup(const dchar *dstr);
* @param len
* The length of the string, which may include internal NUL bytes.
*/
-attr_malloc(dstrfree, 1)
+attr(malloc(dstrfree, 1))
dchar *dstrxdup(const char *str, size_t len);
/**
@@ -243,7 +243,7 @@ int dstrxcpy(dchar **dest, const char *str, size_t len);
* @return
* The created string, or NULL on failure.
*/
-attr_format(1, 2)
+attr(format(1, 2))
char *dstrprintf(const char *format, ...);
/**
@@ -256,7 +256,7 @@ char *dstrprintf(const char *format, ...);
* @return
* The created string, or NULL on failure.
*/
-attr_format(1, 0)
+attr(format(1, 0))
char *dstrvprintf(const char *format, va_list args);
/**
@@ -271,7 +271,7 @@ char *dstrvprintf(const char *format, va_list args);
* @return
* 0 on success, -1 on failure.
*/
-attr_format(2, 3)
+attr(format(2, 3))
int dstrcatf(dchar **str, const char *format, ...);
/**
@@ -286,7 +286,7 @@ int dstrcatf(dchar **str, const char *format, ...);
* @return
* 0 on success, -1 on failure.
*/
-attr_format(2, 0)
+attr(format(2, 0))
int dstrvcatf(dchar **str, const char *format, va_list args);
/**
diff --git a/src/eval.c b/src/eval.c
index a990fd4..859ad7e 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -57,7 +57,7 @@ struct bfs_eval {
/**
* Print an error message.
*/
-attr_format(2, 3)
+attr(format(2, 3))
static void eval_error(struct bfs_eval *state, const char *format, ...) {
// By POSIX, any errors should be accompanied by a non-zero exit status
*state->ret = EXIT_FAILURE;
diff --git a/src/exec.c b/src/exec.c
index 90b3598..ba2fec8 100644
--- a/src/exec.c
+++ b/src/exec.c
@@ -22,7 +22,7 @@
#include <unistd.h>
/** Print some debugging info. */
-attr_format(2, 3)
+attr(format(2, 3))
static void bfs_exec_debug(const struct bfs_exec *execbuf, const char *format, ...) {
const struct bfs_ctx *ctx = execbuf->ctx;
diff --git a/src/fsade.c b/src/fsade.c
index 4d22d99..a48eeb0 100644
--- a/src/fsade.c
+++ b/src/fsade.c
@@ -32,7 +32,7 @@
* Many of the APIs used here don't have *at() variants, but we can try to
* emulate something similar if /proc/self/fd is available.
*/
-attr_maybe_unused
+attr(maybe_unused)
static const char *fake_at(const struct BFTW *ftwbuf) {
static atomic int proc_works = -1;
@@ -66,7 +66,7 @@ fail:
return ftwbuf->path;
}
-attr_maybe_unused
+attr(maybe_unused)
static void free_fake_at(const struct BFTW *ftwbuf, const char *path) {
if (path != ftwbuf->path) {
dstrfree((dchar *)path);
@@ -76,7 +76,7 @@ static void free_fake_at(const struct BFTW *ftwbuf, const char *path) {
/**
* Check if an error was caused by the absence of support or data for a feature.
*/
-attr_maybe_unused
+attr(maybe_unused)
static bool is_absence_error(int error) {
// If the OS doesn't support the feature, it's obviously not enabled for
// any files
diff --git a/src/ioq.c b/src/ioq.c
index bd8d111..2739338 100644
--- a/src/ioq.c
+++ b/src/ioq.c
@@ -273,7 +273,7 @@ static struct ioq_monitor *ioq_slot_monitor(struct ioqq *ioqq, ioq_slot *slot) {
}
/** Atomically wait for a slot to change. */
-attr_noinline
+attr(noinline)
static uintptr_t ioq_slot_wait(struct ioqq *ioqq, ioq_slot *slot, uintptr_t value) {
struct ioq_monitor *monitor = ioq_slot_monitor(ioqq, slot);
mutex_lock(&monitor->mutex);
@@ -303,7 +303,7 @@ done:
}
/** Wake up any threads waiting on a slot. */
-attr_noinline
+attr(noinline)
static void ioq_slot_wake(struct ioqq *ioqq, ioq_slot *slot) {
struct ioq_monitor *monitor = ioq_slot_monitor(ioqq, slot);
diff --git a/src/mtab.c b/src/mtab.c
index 082150c..cc726a2 100644
--- a/src/mtab.c
+++ b/src/mtab.c
@@ -61,7 +61,7 @@ struct bfs_mtab {
/**
* Add an entry to the mount table.
*/
-attr_maybe_unused
+attr(maybe_unused)
static int bfs_mtab_add(struct bfs_mtab *mtab, const char *path, const char *type) {
struct bfs_mount *mount = RESERVE(struct bfs_mount, &mtab->mounts, &mtab->nmounts);
if (!mount) {
diff --git a/src/opt.c b/src/opt.c
index 5da73d8..3ee5e81 100644
--- a/src/opt.c
+++ b/src/opt.c
@@ -305,7 +305,7 @@ struct opt_state {
};
/** Log an optimization. */
-attr_format(3, 4)
+attr(format(3, 4))
static bool opt_debug(const struct opt_state *state, int level, const char *format, ...) {
bfs_assert(state->ctx->optlevel >= level);
@@ -321,7 +321,7 @@ static bool opt_debug(const struct opt_state *state, int level, const char *form
}
/** Warn about an expression. */
-attr_format(3, 4)
+attr(format(3, 4))
static void opt_warning(const struct opt_state *state, const struct bfs_expr *expr, const char *format, ...) {
if (bfs_expr_warning(state->ctx, expr)) {
va_list args;
diff --git a/src/parse.c b/src/parse.c
index 778fc68..35d22fb 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -246,7 +246,7 @@ static void highlight_args(const struct bfs_ctx *ctx, char **argv, size_t argc,
/**
* Print an error message during parsing.
*/
-attr_format(2, 3)
+attr(format(2, 3))
static void parse_error(const struct parser_state *state, const char *format, ...) {
int error = errno;
const struct bfs_ctx *ctx = state->ctx;
@@ -266,7 +266,7 @@ static void parse_error(const struct parser_state *state, const char *format, ..
/**
* Print an error about some command line arguments.
*/
-attr_format(4, 5)
+attr(format(4, 5))
static void parse_argv_error(const struct parser_state *state, char **argv, size_t argc, const char *format, ...) {
int error = errno;
const struct bfs_ctx *ctx = state->ctx;
@@ -286,7 +286,7 @@ static void parse_argv_error(const struct parser_state *state, char **argv, size
/**
* Print an error about conflicting command line arguments.
*/
-attr_format(6, 7)
+attr(format(6, 7))
static void parse_conflict_error(const struct parser_state *state, char **argv1, size_t argc1, char **argv2, size_t argc2, const char *format, ...) {
int error = errno;
const struct bfs_ctx *ctx = state->ctx;
@@ -307,7 +307,7 @@ static void parse_conflict_error(const struct parser_state *state, char **argv1,
/**
* Print an error about an expression.
*/
-attr_format(3, 4)
+attr(format(3, 4))
static void parse_expr_error(const struct parser_state *state, const struct bfs_expr *expr, const char *format, ...) {
int error = errno;
const struct bfs_ctx *ctx = state->ctx;
@@ -324,7 +324,7 @@ static void parse_expr_error(const struct parser_state *state, const struct bfs_
/**
* Print a warning message during parsing.
*/
-attr_format(2, 3)
+attr(format(2, 3))
static bool parse_warning(const struct parser_state *state, const char *format, ...) {
int error = errno;
const struct bfs_ctx *ctx = state->ctx;
@@ -347,7 +347,7 @@ static bool parse_warning(const struct parser_state *state, const char *format,
/**
* Print a warning about conflicting command line arguments.
*/
-attr_format(6, 7)
+attr(format(6, 7))
static bool parse_conflict_warning(const struct parser_state *state, char **argv1, size_t argc1, char **argv2, size_t argc2, const char *format, ...) {
int error = errno;
const struct bfs_ctx *ctx = state->ctx;
@@ -371,7 +371,7 @@ static bool parse_conflict_warning(const struct parser_state *state, char **argv
/**
* Print a warning about an expression.
*/
-attr_format(3, 4)
+attr(format(3, 4))
static bool parse_expr_warning(const struct parser_state *state, const struct bfs_expr *expr, const char *format, ...) {
int error = errno;
const struct bfs_ctx *ctx = state->ctx;
diff --git a/src/trie.c b/src/trie.c
index cf55cee..bd5300d 100644
--- a/src/trie.c
+++ b/src/trie.c
@@ -95,7 +95,7 @@
bfs_static_assert(CHAR_WIDTH == 8);
#if __i386__ || __x86_64__
-# define trie_clones attr_target_clones("popcnt", "default")
+# define trie_clones attr(target_clones("popcnt", "default"))
#else
# define trie_clones
#endif
diff --git a/src/xspawn.c b/src/xspawn.c
index 03287c3..40115a1 100644
--- a/src/xspawn.c
+++ b/src/xspawn.c
@@ -83,7 +83,7 @@ int bfs_spawn_destroy(struct bfs_spawn *ctx) {
#if _POSIX_SPAWN > 0
/** Set some posix_spawnattr flags. */
-attr_maybe_unused
+attr(maybe_unused)
static int bfs_spawn_addflags(struct bfs_spawn *ctx, short flags) {
short prev;
errno = posix_spawnattr_getflags(&ctx->attr, &prev);