From a201b3e237e1994e0ee3668b25287fc9fdd574f9 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 21 Nov 2022 10:43:26 -0500 Subject: config: Support target_clones on more platforms --- src/config.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index 5bd49de..0822e3c 100644 --- a/src/config.h +++ b/src/config.h @@ -186,4 +186,11 @@ # define BFS_FORMATTER(fmt, args) #endif +/** + * Check if function multiversioning via GNU indirect functions (ifunc) is supported. + */ +#if !defined(BFS_TARGET_CLONES) && __has_attribute(target_clones) && (__GLIBC__ || __FreeBSD__ || __NetBSD__) +# define BFS_TARGET_CLONES true +#endif + #endif // BFS_CONFIG_H -- cgit v1.2.3 From 2898d6b79d15c984f95977f7385dd4273087c61b Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 7 Dec 2022 10:21:19 -0500 Subject: config: New BFS_COUNTOF macro --- src/config.h | 5 +++++ src/fsade.c | 3 +-- tests/trie.c | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index 0822e3c..4a49b75 100644 --- a/src/config.h +++ b/src/config.h @@ -155,6 +155,11 @@ # define BFS_FALLTHROUGH ((void)0) #endif +/** + * Get the length of an array. + */ +#define BFS_COUNTOF(array) (sizeof(array) / sizeof(0[array])) + // Lower bound on BFS_FLEX_SIZEOF() #define BFS_FLEX_LB(type, member, length) (offsetof(type, member) + sizeof(((type *)NULL)->member[0]) * (length)) diff --git a/src/fsade.c b/src/fsade.c index a609b97..45969d1 100644 --- a/src/fsade.c +++ b/src/fsade.c @@ -206,7 +206,6 @@ int bfs_check_acl(const struct BFTW *ftwbuf) { ACL_TYPE_NFS4, #endif }; - static const size_t n_acl_types = sizeof(acl_types)/sizeof(acl_types[0]); if (ftwbuf->type == BFS_LNK) { return 0; @@ -215,7 +214,7 @@ int bfs_check_acl(const struct BFTW *ftwbuf) { const char *path = fake_at(ftwbuf); int ret = -1, error = 0; - for (size_t i = 0; i < n_acl_types && ret <= 0; ++i) { + for (size_t i = 0; i < BFS_COUNTOF(acl_types) && ret <= 0; ++i) { acl_type_t type = acl_types[i]; if (type == ACL_TYPE_DEFAULT && ftwbuf->type != BFS_DIR) { diff --git a/tests/trie.c b/tests/trie.c index 6bc7549..88e92da 100644 --- a/tests/trie.c +++ b/tests/trie.c @@ -17,6 +17,7 @@ #undef NDEBUG #include "../src/trie.h" +#include "../src/config.h" #include #include #include @@ -50,7 +51,7 @@ const char *keys[] = { ">>>", }; -const size_t nkeys = sizeof(keys) / sizeof(keys[0]); +const size_t nkeys = BFS_COUNTOF(keys); int main(void) { struct trie trie; -- cgit v1.2.3 From d0e8026d650bb4318ea8608865d5f5a011366dcc Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 9 Dec 2022 11:59:26 -0500 Subject: Turn on more aggressive format string warnings --- Makefile | 5 +++-- src/config.h | 15 ++++++++++++++ src/eval.c | 8 +++++--- src/printf.c | 67 +++++++++++++++++++++++++++++++++++++----------------------- 4 files changed, 65 insertions(+), 30 deletions(-) (limited to 'src/config.h') diff --git a/Makefile b/Makefile index a1144c9..afd3c77 100644 --- a/Makefile +++ b/Makefile @@ -46,11 +46,12 @@ OBJ := $(BUILDDIR)/obj DEFAULT_CFLAGS := \ -g \ -Wall \ + -Wformat=2 \ + -Wimplicit-fallthrough \ -Wmissing-declarations \ -Wshadow \ -Wsign-compare \ - -Wstrict-prototypes \ - -Wimplicit-fallthrough + -Wstrict-prototypes CFLAGS ?= $(DEFAULT_CFLAGS) LDFLAGS ?= diff --git a/src/config.h b/src/config.h index 4a49b75..229f593 100644 --- a/src/config.h +++ b/src/config.h @@ -198,4 +198,19 @@ # define BFS_TARGET_CLONES true #endif +/** + * Ignore a particular GCC warning for a region of code. + */ +#if __GNUC__ +# define BFS_PRAGMA_STRINGIFY(...) _Pragma(#__VA_ARGS__) +# define BFS_SUPPRESS(warning) \ + _Pragma("GCC diagnostic push"); \ + BFS_PRAGMA_STRINGIFY(GCC diagnostic ignored warning) +# define BFS_UNSUPPRESS() \ + _Pragma("GCC diagnostic pop") +#else +# define BFS_SUPPRESS(warning) +# define BFS_UNSUPPRESS() +#endif + #endif // BFS_CONFIG_H diff --git a/src/eval.c b/src/eval.c index e3257ce..89591b2 100644 --- a/src/eval.c +++ b/src/eval.c @@ -716,11 +716,13 @@ bool eval_fls(const struct bfs_expr *expr, struct bfs_eval *state) { goto error; } char time_str[256]; - const char *time_format = "%b %e %H:%M"; + size_t time_ret; if (time <= six_months_ago || time >= tomorrow) { - time_format = "%b %e %Y"; + time_ret = strftime(time_str, sizeof(time_str), "%b %e %Y", &tm); + } else { + time_ret = strftime(time_str, sizeof(time_str), "%b %e %H:%M", &tm); } - if (!strftime(time_str, sizeof(time_str), time_format, &tm)) { + if (time_ret == 0) { errno = EOVERFLOW; goto error; } diff --git a/src/printf.c b/src/printf.c index 6a7b9a9..5af8362 100644 --- a/src/printf.c +++ b/src/printf.c @@ -91,6 +91,21 @@ static bool should_color(CFILE *cfile, const struct bfs_printf *directive) { assert(ret >= 0 && (size_t)ret < sizeof(buf)); \ (void)ret +/** + * Common entry point for fprintf() with a dynamic format string. + */ +static int dyn_fprintf(FILE *file, const struct bfs_printf *directive, ...) { + va_list args; + va_start(args, directive); + + BFS_SUPPRESS("-Wformat-nonliteral"); + int ret = vfprintf(file, directive->str, args); + BFS_UNSUPPRESS(); + + va_end(args); + return ret; +} + /** %a, %c, %t: ctime() */ static int bfs_printf_ctime(CFILE *cfile, const struct bfs_printf *directive, const struct BFTW *ftwbuf) { // Not using ctime() itself because GNU find adds nanoseconds @@ -122,7 +137,7 @@ static int bfs_printf_ctime(CFILE *cfile, const struct bfs_printf *directive, co (long)ts->tv_nsec, 1900 + tm.tm_year); - return fprintf(cfile->file, directive->str, buf); + return dyn_fprintf(cfile->file, directive, buf); } /** %A, %B/%W, %C, %T: strftime() */ @@ -183,14 +198,16 @@ static int bfs_printf_strftime(CFILE *cfile, const struct bfs_printf *directive, // POSIX strftime() features default: format[1] = directive->c; + BFS_SUPPRESS("-Wformat-nonliteral"); ret = strftime(buf, sizeof(buf), format, &tm); + BFS_UNSUPPRESS(); break; } assert(ret >= 0 && (size_t)ret < sizeof(buf)); (void)ret; - return fprintf(cfile->file, directive->str, buf); + return dyn_fprintf(cfile->file, directive, buf); } /** %b: blocks */ @@ -202,12 +219,12 @@ static int bfs_printf_b(CFILE *cfile, const struct bfs_printf *directive, const uintmax_t blocks = ((uintmax_t)statbuf->blocks*BFS_STAT_BLKSIZE + 511)/512; BFS_PRINTF_BUF(buf, "%ju", blocks); - return fprintf(cfile->file, directive->str, buf); + return dyn_fprintf(cfile->file, directive, buf); } /** %d: depth */ static int bfs_printf_d(CFILE *cfile, const struct bfs_printf *directive, const struct BFTW *ftwbuf) { - return fprintf(cfile->file, directive->str, (intmax_t)ftwbuf->depth); + return dyn_fprintf(cfile->file, directive, (intmax_t)ftwbuf->depth); } /** %D: device */ @@ -218,7 +235,7 @@ static int bfs_printf_D(CFILE *cfile, const struct bfs_printf *directive, const } BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->dev); - return fprintf(cfile->file, directive->str, buf); + return dyn_fprintf(cfile->file, directive, buf); } /** %f: file name */ @@ -226,7 +243,7 @@ static int bfs_printf_f(CFILE *cfile, const struct bfs_printf *directive, const if (should_color(cfile, directive)) { return cfprintf(cfile, "%pF", ftwbuf); } else { - return fprintf(cfile->file, directive->str, ftwbuf->path + ftwbuf->nameoff); + return dyn_fprintf(cfile->file, directive, ftwbuf->path + ftwbuf->nameoff); } } @@ -238,7 +255,7 @@ static int bfs_printf_F(CFILE *cfile, const struct bfs_printf *directive, const } const char *type = bfs_fstype(directive->ptr, statbuf); - return fprintf(cfile->file, directive->str, type); + return dyn_fprintf(cfile->file, directive, type); } /** %G: gid */ @@ -249,7 +266,7 @@ static int bfs_printf_G(CFILE *cfile, const struct bfs_printf *directive, const } BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->gid); - return fprintf(cfile->file, directive->str, buf); + return dyn_fprintf(cfile->file, directive, buf); } /** %g: group name */ @@ -265,7 +282,7 @@ static int bfs_printf_g(CFILE *cfile, const struct bfs_printf *directive, const return bfs_printf_G(cfile, directive, ftwbuf); } - return fprintf(cfile->file, directive->str, grp->gr_name); + return dyn_fprintf(cfile->file, directive, grp->gr_name); } /** %h: leading directories */ @@ -294,7 +311,7 @@ static int bfs_printf_h(CFILE *cfile, const struct bfs_printf *directive, const if (should_color(cfile, directive)) { ret = cfprintf(cfile, "${di}%s${rs}", buf); } else { - ret = fprintf(cfile->file, directive->str, buf); + ret = dyn_fprintf(cfile->file, directive, buf); } free(copy); @@ -310,7 +327,7 @@ static int bfs_printf_H(CFILE *cfile, const struct bfs_printf *directive, const return cfprintf(cfile, "${di}%s${rs}", ftwbuf->root); } } else { - return fprintf(cfile->file, directive->str, ftwbuf->root); + return dyn_fprintf(cfile->file, directive, ftwbuf->root); } } @@ -322,7 +339,7 @@ static int bfs_printf_i(CFILE *cfile, const struct bfs_printf *directive, const } BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->ino); - return fprintf(cfile->file, directive->str, buf); + return dyn_fprintf(cfile->file, directive, buf); } /** %k: 1K blocks */ @@ -334,7 +351,7 @@ static int bfs_printf_k(CFILE *cfile, const struct bfs_printf *directive, const uintmax_t blocks = ((uintmax_t)statbuf->blocks*BFS_STAT_BLKSIZE + 1023)/1024; BFS_PRINTF_BUF(buf, "%ju", blocks); - return fprintf(cfile->file, directive->str, buf); + return dyn_fprintf(cfile->file, directive, buf); } /** %l: link target */ @@ -356,7 +373,7 @@ static int bfs_printf_l(CFILE *cfile, const struct bfs_printf *directive, const } } - int ret = fprintf(cfile->file, directive->str, target); + int ret = dyn_fprintf(cfile->file, directive, target); free(buf); return ret; } @@ -368,7 +385,7 @@ static int bfs_printf_m(CFILE *cfile, const struct bfs_printf *directive, const return -1; } - return fprintf(cfile->file, directive->str, (unsigned int)(statbuf->mode & 07777)); + return dyn_fprintf(cfile->file, directive, (unsigned int)(statbuf->mode & 07777)); } /** %M: symbolic mode */ @@ -380,7 +397,7 @@ static int bfs_printf_M(CFILE *cfile, const struct bfs_printf *directive, const char buf[11]; xstrmode(statbuf->mode, buf); - return fprintf(cfile->file, directive->str, buf); + return dyn_fprintf(cfile->file, directive, buf); } /** %n: link count */ @@ -391,7 +408,7 @@ static int bfs_printf_n(CFILE *cfile, const struct bfs_printf *directive, const } BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->nlink); - return fprintf(cfile->file, directive->str, buf); + return dyn_fprintf(cfile->file, directive, buf); } /** %p: full path */ @@ -399,7 +416,7 @@ static int bfs_printf_p(CFILE *cfile, const struct bfs_printf *directive, const if (should_color(cfile, directive)) { return cfprintf(cfile, "%pP", ftwbuf); } else { - return fprintf(cfile->file, directive->str, ftwbuf->path); + return dyn_fprintf(cfile->file, directive, ftwbuf->path); } } @@ -420,7 +437,7 @@ static int bfs_printf_P(CFILE *cfile, const struct bfs_printf *directive, const copybuf.nameoff -= offset; return cfprintf(cfile, "%pP", ©buf); } else { - return fprintf(cfile->file, directive->str, ftwbuf->path + offset); + return dyn_fprintf(cfile->file, directive, ftwbuf->path + offset); } } @@ -432,7 +449,7 @@ static int bfs_printf_s(CFILE *cfile, const struct bfs_printf *directive, const } BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->size); - return fprintf(cfile->file, directive->str, buf); + return dyn_fprintf(cfile->file, directive, buf); } /** %S: sparseness */ @@ -448,7 +465,7 @@ static int bfs_printf_S(CFILE *cfile, const struct bfs_printf *directive, const } else { sparsity = (double)BFS_STAT_BLKSIZE*statbuf->blocks/statbuf->size; } - return fprintf(cfile->file, directive->str, sparsity); + return dyn_fprintf(cfile->file, directive, sparsity); } /** %U: uid */ @@ -459,7 +476,7 @@ static int bfs_printf_U(CFILE *cfile, const struct bfs_printf *directive, const } BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->uid); - return fprintf(cfile->file, directive->str, buf); + return dyn_fprintf(cfile->file, directive, buf); } /** %u: user name */ @@ -475,7 +492,7 @@ static int bfs_printf_u(CFILE *cfile, const struct bfs_printf *directive, const return bfs_printf_U(cfile, directive, ftwbuf); } - return fprintf(cfile->file, directive->str, pwd->pw_name); + return dyn_fprintf(cfile->file, directive, pwd->pw_name); } static const char *bfs_printf_type(enum bfs_type type) { @@ -504,7 +521,7 @@ static const char *bfs_printf_type(enum bfs_type type) { /** %y: type */ static int bfs_printf_y(CFILE *cfile, const struct bfs_printf *directive, const struct BFTW *ftwbuf) { const char *type = bfs_printf_type(ftwbuf->type); - return fprintf(cfile->file, directive->str, type); + return dyn_fprintf(cfile->file, directive, type); } /** %Y: target type */ @@ -536,7 +553,7 @@ static int bfs_printf_Y(CFILE *cfile, const struct bfs_printf *directive, const } } - int ret = fprintf(cfile->file, directive->str, type); + int ret = dyn_fprintf(cfile->file, directive, type); if (error != 0) { ret = -1; errno = error; -- cgit v1.2.3 From e477e12ade9544c31779f007faee169aae22e145 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 9 Dec 2022 12:51:00 -0500 Subject: config: New BFS_UNINIT() macro for intentionally uninitialized variables --- src/config.h | 9 +++++++++ src/parse.c | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index 229f593..810f913 100644 --- a/src/config.h +++ b/src/config.h @@ -213,4 +213,13 @@ # define BFS_UNSUPPRESS() #endif +/** + * Initialize a variable, unless sanitizers would detect uninitialized uses. + */ +#if __has_feature(memory_sanitizer) +# define BFS_UNINIT(var, value) var = var +#else +# define BFS_UNINIT(var, value) var = value +#endif + #endif // BFS_CONFIG_H diff --git a/src/parse.c b/src/parse.c index 320e165..90e7e3b 100644 --- a/src/parse.c +++ b/src/parse.c @@ -2121,9 +2121,9 @@ static int parse_mode(const struct parser_state *state, const char *mode, struct MODE_EQUALS, } op; - mode_t who; - mode_t file_change; - mode_t dir_change; + mode_t BFS_UNINIT(who, 0); + mode_t BFS_UNINIT(file_change, 0); + mode_t BFS_UNINIT(dir_change, 0); const char *i = mode; while (true) { -- cgit v1.2.3 From 9463fdd30d392c98de7b5712d30dfbaeada40e99 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 25 Jan 2023 16:14:11 -0500 Subject: Replace license boilerplate with SPDX tags And while I'm at it, remove years from copyright declarations. Link: https://spdx.dev/about/ Link: https://daniel.haxx.se/blog/2023/01/08/copyright-without-years/ --- LICENSE | 33 +++++++++++++++++++++------------ Makefile | 17 ++--------------- completions/bfs.bash | 21 ++++----------------- src/bar.c | 17 ++--------------- src/bar.h | 17 ++--------------- src/bfstd.c | 17 ++--------------- src/bfstd.h | 17 ++--------------- src/bftw.c | 17 ++--------------- src/bftw.h | 17 ++--------------- src/color.c | 17 ++--------------- src/color.h | 17 ++--------------- src/config.h | 17 ++--------------- src/ctx.c | 17 ++--------------- src/ctx.h | 17 ++--------------- src/darray.c | 17 ++--------------- src/darray.h | 17 ++--------------- src/diag.c | 17 ++--------------- src/diag.h | 17 ++--------------- src/dir.c | 17 ++--------------- src/dir.h | 17 ++--------------- src/dstring.c | 17 ++--------------- src/dstring.h | 17 ++--------------- src/eval.c | 17 ++--------------- src/eval.h | 17 ++--------------- src/exec.c | 17 ++--------------- src/exec.h | 17 ++--------------- src/expr.h | 17 ++--------------- src/fsade.c | 17 ++--------------- src/fsade.h | 17 ++--------------- src/main.c | 17 ++--------------- src/mtab.c | 17 ++--------------- src/mtab.h | 17 ++--------------- src/opt.c | 17 ++--------------- src/opt.h | 17 ++--------------- src/parse.c | 17 ++--------------- src/parse.h | 17 ++--------------- src/printf.c | 17 ++--------------- src/printf.h | 17 ++--------------- src/pwcache.c | 17 ++--------------- src/pwcache.h | 17 ++--------------- src/stat.c | 17 ++--------------- src/stat.h | 17 ++--------------- src/trie.c | 17 ++--------------- src/trie.h | 17 ++--------------- src/typo.c | 17 ++--------------- src/typo.h | 17 ++--------------- src/xregex.c | 17 ++--------------- src/xregex.h | 18 ++---------------- src/xspawn.c | 17 ++--------------- src/xspawn.h | 17 ++--------------- src/xtime.c | 17 ++--------------- src/xtime.h | 17 ++--------------- tests/bfstd.c | 17 ++--------------- tests/find-color.sh | 17 ++--------------- tests/ls-color.sh | 17 ++--------------- tests/mksock.c | 17 ++--------------- tests/tests.sh | 17 ++--------------- tests/trie.c | 17 ++--------------- tests/xtimegm.c | 17 ++--------------- tests/xtouch.c | 17 ++--------------- 60 files changed, 141 insertions(+), 900 deletions(-) (limited to 'src/config.h') diff --git a/LICENSE b/LICENSE index 069b145..290e3d3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,12 +1,21 @@ -Copyright (C) 2015-2021 Tavian Barnes - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +Copyright © 2015-2023 Tavian Barnes and the bfs contributors + +Permission to use, copy, modify, and/or distribute this software for any purpose with or +without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT +SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE +USE OR PERFORMANCE OF THIS SOFTWARE. + +--- + +bfs is licensed under the Zero Clause BSD License. Individual files contain the following +tag instead of the full license text: + + SPDX-License-Identifier: 0BSD + +This enables machine processing of license information based on the SPDX License +Identifiers that are available here: https://spdx.org/licenses/ diff --git a/Makefile b/Makefile index b39a88a..0247b47 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,5 @@ -############################################################################ -# bfs # -# Copyright (C) 2015-2023 Tavian Barnes # -# # -# Permission to use, copy, modify, and/or distribute this software for any # -# purpose with or without fee is hereby granted. # -# # -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -############################################################################ +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD ifneq ($(wildcard .git),) VERSION := $(shell git describe --always 2>/dev/null) diff --git a/completions/bfs.bash b/completions/bfs.bash index f734ab1..2f52e8d 100644 --- a/completions/bfs.bash +++ b/completions/bfs.bash @@ -1,21 +1,8 @@ -# bash completion script for bfs +# Copyright © Benjamin Mundt +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD -############################################################################ -# bfs # -# Copyright (C) 2020 Benjamin Mundt # -# Copyright (C) 2021 Tavian Barnes # -# # -# Permission to use, copy, modify, and/or distribute this software for any # -# purpose with or without fee is hereby granted. # -# # -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -############################################################################ +# bash completion script for bfs _bfs() { local cur prev words cword diff --git a/src/bar.c b/src/bar.c index 37d33c8..bd5d381 100644 --- a/src/bar.c +++ b/src/bar.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2020-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "bar.h" #include "bfstd.h" diff --git a/src/bar.h b/src/bar.h index 3e509d6..20d92a9 100644 --- a/src/bar.h +++ b/src/bar.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2020 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * A terminal status bar. diff --git a/src/bfstd.c b/src/bfstd.c index 3a37250..437e9c9 100644 --- a/src/bfstd.c +++ b/src/bfstd.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2016-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "bfstd.h" #include "config.h" diff --git a/src/bfstd.h b/src/bfstd.h index 79307cc..0e11b66 100644 --- a/src/bfstd.h +++ b/src/bfstd.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2016-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * Standard library wrappers and polyfills. diff --git a/src/bftw.c b/src/bftw.c index 5f3ebde..9feca79 100644 --- a/src/bftw.c +++ b/src/bftw.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2015-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * The bftw() implementation consists of the following components: diff --git a/src/bftw.h b/src/bftw.h index c458e1b..77697ed 100644 --- a/src/bftw.h +++ b/src/bftw.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2015-2021 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * A file-walking API based on nftw(). diff --git a/src/color.c b/src/color.c index 7c16ec5..589e631 100644 --- a/src/color.c +++ b/src/color.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2015-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "color.h" #include "bfstd.h" diff --git a/src/color.h b/src/color.h index 5b350cc..737c34b 100644 --- a/src/color.h +++ b/src/color.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2015-2021 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * Utilities for colored output on ANSI terminals. diff --git a/src/config.h b/src/config.h index 810f913..5ae9c82 100644 --- a/src/config.h +++ b/src/config.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2015-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * Configuration and feature/platform detection. diff --git a/src/ctx.c b/src/ctx.c index 0403299..ff4a2a7 100644 --- a/src/ctx.c +++ b/src/ctx.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2015-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "ctx.h" #include "color.h" diff --git a/src/ctx.h b/src/ctx.h index 6755d02..4c748b7 100644 --- a/src/ctx.h +++ b/src/ctx.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2015-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * bfs execution context. diff --git a/src/darray.c b/src/darray.c index 6585d30..42b8397 100644 --- a/src/darray.c +++ b/src/darray.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2019-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "darray.h" #include diff --git a/src/darray.h b/src/darray.h index 4464381..cc6cc42 100644 --- a/src/darray.h +++ b/src/darray.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2019-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * A dynamic array library. diff --git a/src/diag.c b/src/diag.c index b02473a..53db98e 100644 --- a/src/diag.c +++ b/src/diag.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2019-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "diag.h" #include "bfstd.h" diff --git a/src/diag.h b/src/diag.h index 8d0b19f..2952e30 100644 --- a/src/diag.h +++ b/src/diag.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2019-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * Formatters for diagnostic messages. diff --git a/src/dir.c b/src/dir.c index 2081cc5..3d18eb2 100644 --- a/src/dir.c +++ b/src/dir.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2021-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "dir.h" #include "bfstd.h" diff --git a/src/dir.h b/src/dir.h index 69344c6..01eaaba 100644 --- a/src/dir.h +++ b/src/dir.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2021 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * Directories and their contents. diff --git a/src/dstring.c b/src/dstring.c index f344d09..9112e54 100644 --- a/src/dstring.c +++ b/src/dstring.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2016-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "dstring.h" #include diff --git a/src/dstring.h b/src/dstring.h index df20a04..ee3b345 100644 --- a/src/dstring.h +++ b/src/dstring.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2016-2020 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * A dynamic string library. diff --git a/src/eval.c b/src/eval.c index d297af1..53ce605 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2015-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * Implementation of all the primary expressions. diff --git a/src/eval.h b/src/eval.h index a50dc4e..3d70319 100644 --- a/src/eval.h +++ b/src/eval.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2015-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * The evaluation functions that implement primary expressions like -name, diff --git a/src/exec.c b/src/exec.c index 8630469..6bde1c1 100644 --- a/src/exec.c +++ b/src/exec.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2017-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "exec.h" #include "bfstd.h" diff --git a/src/exec.h b/src/exec.h index a3e3c71..9d4192d 100644 --- a/src/exec.h +++ b/src/exec.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2017-2020 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * Implementation of -exec/-execdir/-ok/-okdir. diff --git a/src/expr.h b/src/expr.h index a52007a..1628cac 100644 --- a/src/expr.h +++ b/src/expr.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2015-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * The expression tree representation. diff --git a/src/fsade.c b/src/fsade.c index 45969d1..a61a6b8 100644 --- a/src/fsade.c +++ b/src/fsade.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2019-2021 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "fsade.h" #include "config.h" diff --git a/src/fsade.h b/src/fsade.h index f45c6fd..9bef892 100644 --- a/src/fsade.h +++ b/src/fsade.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2019-2020 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * A facade over (file)system features that are (un)implemented differently diff --git a/src/main.c b/src/main.c index fbddbe5..4f99580 100644 --- a/src/main.c +++ b/src/main.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2015-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * - main(): the entry point for bfs(1), a breadth-first version of find(1) diff --git a/src/mtab.c b/src/mtab.c index 07d7a53..ae6dfd2 100644 --- a/src/mtab.c +++ b/src/mtab.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2017-2020 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "mtab.h" #include "bfstd.h" diff --git a/src/mtab.h b/src/mtab.h index 807539d..5dfdf6c 100644 --- a/src/mtab.h +++ b/src/mtab.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2017-2020 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * A facade over platform-specific APIs for enumerating mounted filesystems. diff --git a/src/opt.c b/src/opt.c index e76e216..5505b7b 100644 --- a/src/opt.c +++ b/src/opt.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2017-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * The expression optimizer. Different optimization levels are supported: diff --git a/src/opt.h b/src/opt.h index 5f8180d..28cadb9 100644 --- a/src/opt.h +++ b/src/opt.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2020 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * Optimization. diff --git a/src/parse.c b/src/parse.c index f2582e0..30bf56d 100644 --- a/src/parse.c +++ b/src/parse.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2015-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * The command line parser. Expressions are parsed by recursive descent, with a diff --git a/src/parse.h b/src/parse.h index 7e29a03..6895c9f 100644 --- a/src/parse.h +++ b/src/parse.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2020 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * bfs command line parsing. diff --git a/src/printf.c b/src/printf.c index 7c0c8db..1b4f2d4 100644 --- a/src/printf.c +++ b/src/printf.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2017-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "printf.h" #include "bfstd.h" diff --git a/src/printf.h b/src/printf.h index a8c5f2a..2bff087 100644 --- a/src/printf.h +++ b/src/printf.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2017-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * Implementation of -printf/-fprintf. diff --git a/src/pwcache.c b/src/pwcache.c index 868ec8f..5026dee 100644 --- a/src/pwcache.c +++ b/src/pwcache.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2020-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "pwcache.h" #include "darray.h" diff --git a/src/pwcache.h b/src/pwcache.h index f1ca0bf..b6c0b67 100644 --- a/src/pwcache.h +++ b/src/pwcache.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2020 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * A caching wrapper for /etc/{passwd,group}. diff --git a/src/stat.c b/src/stat.c index 94dedef..aaa5eac 100644 --- a/src/stat.c +++ b/src/stat.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2018-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "stat.h" #include "bfstd.h" diff --git a/src/stat.h b/src/stat.h index 44cbfad..7a70146 100644 --- a/src/stat.h +++ b/src/stat.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2018-2019 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * A facade over the stat() API that unifies some details that diverge between diff --git a/src/trie.c b/src/trie.c index 08a99b5..77c43cc 100644 --- a/src/trie.c +++ b/src/trie.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2019-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * This is an implementation of a "qp trie," as documented at diff --git a/src/trie.h b/src/trie.h index 2ede6ea..03ee64d 100644 --- a/src/trie.h +++ b/src/trie.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2019-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #ifndef BFS_TRIE_H #define BFS_TRIE_H diff --git a/src/typo.c b/src/typo.c index c16cab4..305711d 100644 --- a/src/typo.c +++ b/src/typo.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2016 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "typo.h" #include diff --git a/src/typo.h b/src/typo.h index 0347aae..13eaa67 100644 --- a/src/typo.h +++ b/src/typo.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2016 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #ifndef BFS_TYPO_H #define BFS_TYPO_H diff --git a/src/xregex.c b/src/xregex.c index 6f0e5a1..5f5480f 100644 --- a/src/xregex.c +++ b/src/xregex.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "xregex.h" #include "config.h" diff --git a/src/xregex.h b/src/xregex.h index b2f56a5..998a2b0 100644 --- a/src/xregex.h +++ b/src/xregex.h @@ -1,19 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2022 Tavian Barnes and bfs * - * contributors * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes and the bfs contributors +// SPDX-License-Identifier: 0BSD #ifndef BFS_XREGEX_H #define BFS_XREGEX_H diff --git a/src/xspawn.c b/src/xspawn.c index f76267b..a30c264 100644 --- a/src/xspawn.c +++ b/src/xspawn.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2018-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "xspawn.h" #include "bfstd.h" diff --git a/src/xspawn.h b/src/xspawn.h index cd6a42e..3dbf5d2 100644 --- a/src/xspawn.h +++ b/src/xspawn.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2018-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * A process-spawning library inspired by posix_spawn(). diff --git a/src/xtime.c b/src/xtime.c index 079d42a..82690d0 100644 --- a/src/xtime.c +++ b/src/xtime.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2020-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "xtime.h" #include diff --git a/src/xtime.h b/src/xtime.h index b49cd04..75d1f4e 100644 --- a/src/xtime.h +++ b/src/xtime.h @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2020-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * Date/time handling. diff --git a/tests/bfstd.c b/tests/bfstd.c index 4a8181b..8c61072 100644 --- a/tests/bfstd.c +++ b/tests/bfstd.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "../src/bfstd.h" #include diff --git a/tests/find-color.sh b/tests/find-color.sh index ecdd5af..47de2a2 100755 --- a/tests/find-color.sh +++ b/tests/find-color.sh @@ -1,20 +1,7 @@ #!/usr/bin/env bash -############################################################################ -# bfs # -# Copyright (C) 2019 Tavian Barnes # -# # -# Permission to use, copy, modify, and/or distribute this software for any # -# purpose with or without fee is hereby granted. # -# # -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -############################################################################ +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD set -e diff --git a/tests/ls-color.sh b/tests/ls-color.sh index c82a58d..6d33f53 100755 --- a/tests/ls-color.sh +++ b/tests/ls-color.sh @@ -1,20 +1,7 @@ #!/usr/bin/env bash -############################################################################ -# bfs # -# Copyright (C) 2019 Tavian Barnes # -# # -# Permission to use, copy, modify, and/or distribute this software for any # -# purpose with or without fee is hereby granted. # -# # -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -############################################################################ +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD # Prints the "ground truth" coloring of a path using ls diff --git a/tests/mksock.c b/tests/mksock.c index 5068bc8..05edbeb 100644 --- a/tests/mksock.c +++ b/tests/mksock.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2019 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD /** * There's no standard Unix utility that creates a socket file, so this small diff --git a/tests/tests.sh b/tests/tests.sh index e57db4e..98d332c 100755 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -1,20 +1,7 @@ #!/usr/bin/env bash -############################################################################ -# bfs # -# Copyright (C) 2015-2022 Tavian Barnes # -# # -# Permission to use, copy, modify, and/or distribute this software for any # -# purpose with or without fee is hereby granted. # -# # -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -############################################################################ +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD set -euP umask 022 diff --git a/tests/trie.c b/tests/trie.c index 88e92da..c2af18a 100644 --- a/tests/trie.c +++ b/tests/trie.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2020-2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #undef NDEBUG diff --git a/tests/xtimegm.c b/tests/xtimegm.c index d774b9e..bab64ba 100644 --- a/tests/xtimegm.c +++ b/tests/xtimegm.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2020 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "../src/xtime.h" #include diff --git a/tests/xtouch.c b/tests/xtouch.c index 9a91ec7..506c73d 100644 --- a/tests/xtouch.c +++ b/tests/xtouch.c @@ -1,18 +1,5 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2022 Tavian Barnes * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD #include "../src/bfstd.h" #include "../src/xtime.h" -- cgit v1.2.3 From a1bd70db67ddbe167caf15b7334b3588653d3b91 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 31 Jan 2023 11:26:41 -0500 Subject: Release 2.6.3 --- Makefile | 2 +- docs/CHANGELOG.md | 40 ++++++++++++++++++++++++++++++++++++++++ src/config.h | 2 +- 3 files changed, 42 insertions(+), 2 deletions(-) (limited to 'src/config.h') diff --git a/Makefile b/Makefile index 0247b47..b509065 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ VERSION := $(shell git describe --always 2>/dev/null) endif ifndef VERSION -VERSION := 2.6.2 +VERSION := 2.6.3 endif ifndef OS diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index ff1c1f7..f67e68a 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,46 @@ 2.* === +2.6.3 +----- + +**January 31, 2023** + +- Fixed running the tests as root on Linux [`8b24de3`] + +- Fixed some tests on Android [`2724dfb`] [`0a5a80c`] + +- Stopped relying on non-POSIX touch(1) features in the tests. + This should fix the tests on at least OpenBSD. + [`2d5edb3`] + +- User/group caches are now filled lazily instead of eagerly [`b41dca5`] + +- More caches and I/O streams are flushed before -exec/-ok [`f98a1c4`] + +- Fixed various memory safety issues found by fuzzing \ + [`712b137`] [`5ce883d`] [`da02def`] [`c55e855`] + +- Fixed a test failure on certain macOS versions [`8b24de3`] + +- Mitigated a race condition when determining filesystem types ([#97]) + +- Lots of refactoring and optimization + +[`8b24de3`]: https://github.com/tavianator/bfs/commit/8b24de3882ff5a3e33b82ab20bb4eadf134cf559 +[`2724dfb`]: https://github.com/tavianator/bfs/commit/2724dfbd17552f892a0d8b39b96cbe9e49d66fdb +[`0a5a80c`]: https://github.com/tavianator/bfs/commit/0a5a80c98cc7e5d8735b615fa197a6cff2bb08cc +[`2d5edb3`]: https://github.com/tavianator/bfs/commit/2d5edb37b924715b4fbee4d917ac334c773fca61 +[`b41dca5`]: https://github.com/tavianator/bfs/commit/b41dca52762c5188638236ae81b9f4597bb29ac9 +[`f98a1c4`]: https://github.com/tavianator/bfs/commit/f98a1c4a1cf61ff7d6483388ca1fac365fb0b31b +[`712b137`]: https://github.com/tavianator/bfs/commit/712b13756a09014ef730c8f9b96da4dc2f09b762 +[`5ce883d`]: https://github.com/tavianator/bfs/commit/5ce883daaafc69f83b01dac5db0647e9662a6e87 +[`da02def`]: https://github.com/tavianator/bfs/commit/da02defb91c3a1bda0ea7e653d81f997f1c8884a +[`c55e855`]: https://github.com/tavianator/bfs/commit/c55e85580df10c5afdc6fc0710e756a456aa8e93 +[`8b24de3`]: https://github.com/tavianator/bfs/commit/8b24de3882ff5a3e33b82ab20bb4eadf134cf559 +[#97]: https://github.com/tavianator/bfs/issues/97 + + 2.6.2 ----- diff --git a/src/config.h b/src/config.h index 5ae9c82..34ae11d 100644 --- a/src/config.h +++ b/src/config.h @@ -17,7 +17,7 @@ # define BFS_COMMAND "bfs" #endif #ifndef BFS_VERSION -# define BFS_VERSION "2.6.2" +# define BFS_VERSION "2.6.3" #endif #ifndef BFS_HOMEPAGE # define BFS_HOMEPAGE "https://tavianator.com/projects/bfs.html" -- cgit v1.2.3 From 135b98c26456adbfbc72fb12e4753ee0716b1f92 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 28 Mar 2023 14:18:08 -0400 Subject: list: New generic linked list API --- Makefile | 1 + src/config.h | 11 ++++ src/list.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/list.h | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 351 insertions(+) create mode 100644 src/list.c create mode 100644 src/list.h (limited to 'src/config.h') diff --git a/Makefile b/Makefile index b509065..428a0f7 100644 --- a/Makefile +++ b/Makefile @@ -223,6 +223,7 @@ LIBBFS := \ $(OBJ)/src/eval.o \ $(OBJ)/src/exec.o \ $(OBJ)/src/fsade.o \ + $(OBJ)/src/list.o \ $(OBJ)/src/mtab.o \ $(OBJ)/src/opt.o \ $(OBJ)/src/parse.o \ diff --git a/src/config.h b/src/config.h index 34ae11d..cee8511 100644 --- a/src/config.h +++ b/src/config.h @@ -147,6 +147,17 @@ */ #define BFS_COUNTOF(array) (sizeof(array) / sizeof(0[array])) +// BFS_CONTAINER_OF() helper +static inline char *bfs_container_offset(char *ptr, ptrdiff_t offset, size_t unused) { + return ptr ? ptr - offset : NULL; +} + +/** + * Move a pointer from a field to its outer struct. + */ +#define BFS_CONTAINER_OF(ptr, type, member) \ + ((type *)bfs_container_offset((char *)(ptr), offsetof(type, member), sizeof((ptr) - &((type *)NULL)->member))) + // Lower bound on BFS_FLEX_SIZEOF() #define BFS_FLEX_LB(type, member, length) (offsetof(type, member) + sizeof(((type *)NULL)->member[0]) * (length)) diff --git a/src/list.c b/src/list.c new file mode 100644 index 0000000..dffee19 --- /dev/null +++ b/src/list.c @@ -0,0 +1,169 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include "list.h" +#include +#include + +void slink_init(struct slink *link) { + link->next = NULL; +} + +void slist_init(struct slist *list) { + list->head = NULL; + list->tail = &list->head; +} + +bool slist_is_empty(const struct slist *list) { + return !list->head; +} + +void slist_append(struct slist *list, struct slink *link) { + assert(!link->next); + *list->tail = link; + list->tail = &link->next; +} + +void slist_prepend(struct slist *list, struct slink *link) { + assert(!link->next); + if (!list->head) { + list->tail = &link->next; + } + link->next = list->head; + list->head = link; +} + +void slist_extend(struct slist *dest, struct slist *src) { + if (src->head) { + *dest->tail = src->head; + dest->tail = src->tail; + slist_init(src); + } +} + +struct slink *slist_pop(struct slist *list) { + struct slink *head = list->head; + if (!head) { + return NULL; + } + + list->head = head->next; + if (!list->head) { + list->tail = &list->head; + } + + head->next = NULL; + return head; +} + +void slist_sort(struct slist *list, slist_cmp_fn *cmp_fn, const void *ptr) { + if (!list->head || !list->head->next) { + return; + } + + struct slist left, right; + slist_init(&left); + slist_init(&right); + + // Split + for (struct slink *hare = list->head; hare && (hare = hare->next); hare = hare->next) { + slist_append(&left, slist_pop(list)); + } + slist_extend(&right, list); + + // Recurse + slist_sort(&left, cmp_fn, ptr); + slist_sort(&right, cmp_fn, ptr); + + // Merge + while (left.head && right.head) { + if (cmp_fn(left.head, right.head, ptr)) { + slist_append(list, slist_pop(&left)); + } else { + slist_append(list, slist_pop(&right)); + } + } + slist_extend(list, &left); + slist_extend(list, &right); +} + +void link_init(struct link *link) { + link->prev = NULL; + link->next = NULL; +} + +void list_init(struct list *list) { + list->head = NULL; + list->tail = NULL; +} + +bool list_is_empty(const struct list *list) { + return !list->head; +} + +void list_append(struct list *list, struct link *link) { + list_insert_after(list, list->tail, link); +} + +void list_prepend(struct list *list, struct link *link) { + list_insert_after(list, NULL, link); +} + +void list_insert_after(struct list *list, struct link *target, struct link *link) { + assert(!list_attached(list, link)); + + if (target) { + link->prev = target; + link->next = target->next; + } else { + link->next = list->head; + } + + if (link->prev) { + link->prev->next = link; + } else { + list->head = link; + } + + if (link->next) { + link->next->prev = link; + } else { + list->tail = link; + } +} + +void list_remove(struct list *list, struct link *link) { + if (link->prev) { + assert(list->head != link); + link->prev->next = link->next; + } else { + assert(list->head == link); + list->head = link->next; + } + + if (link->next) { + assert(list->tail != link); + link->next->prev = link->prev; + } else { + assert(list->tail == link); + list->tail = link->prev; + } + + link->prev = NULL; + link->next = NULL; +} + +struct link *list_pop(struct list *list) { + struct link *head = list->head; + if (!head) { + return NULL; + } + + list_remove(list, head); + return head; +} + +bool list_attached(const struct list *list, const struct link *link) { + return link->prev || list->head == link + || link->next || list->tail == link; +} diff --git a/src/list.h b/src/list.h new file mode 100644 index 0000000..1985413 --- /dev/null +++ b/src/list.h @@ -0,0 +1,170 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +/** + * Intrusive linked lists. + */ + +#ifndef BFS_LIST_H +#define BFS_LIST_H + +#include "config.h" +#include + +/** + * A singly-linked list entry. + */ +struct slink { + struct slink *next; +}; + +/** Initialize a list entry. */ +void slink_init(struct slink *link); + +/** + * A singly-linked list. + */ +struct slist { + struct slink *head; + struct slink **tail; +}; + +/** Initialize an empty list. */ +void slist_init(struct slist *list); + +/** Check if a list is empty. */ +bool slist_is_empty(const struct slist *list); + +/** Add an entry at the tail of the list. */ +void slist_append(struct slist *list, struct slink *link); + +/** Add an entry at the head of the list. */ +void slist_prepend(struct slist *list, struct slink *link); + +/** Add an entire list at the tail of the list. */ +void slist_extend(struct slist *dest, struct slist *src); + +/** Remove the head of the list. */ +struct slink *slist_pop(struct slist *list); + +/** + * Comparison function type for slist_sort(). + * + * @param left + * The left-hand side of the comparison. + * @param right + * The right-hand side of the comparison. + * @param ptr + * An arbitrary pointer passed to slist_sort(). + * @return + * Whether left <= right. + */ +typedef bool slist_cmp_fn(struct slink *left, struct slink *right, const void *ptr); + +/** Sort a list. */ +void slist_sort(struct slist *list, slist_cmp_fn *cmp_fn, const void *ptr); + +/** + * A doubly-linked list entry. + */ +struct link { + struct link *prev; + struct link *next; +}; + +/** Initialize a list entry. */ +void link_init(struct link *link); + +/** + * A doubly-linked list. + */ +struct list { + struct link *head; + struct link *tail; +}; + +/** Initialize an empty list. */ +void list_init(struct list *list); + +/** Check if a list is empty. */ +bool list_is_empty(const struct list *list); + +/** Add an entry at the tail of the list. */ +void list_append(struct list *list, struct link *link); + +/** Add an entry at the head of the list. */ +void list_prepend(struct list *list, struct link *link); + +/** Insert an entry after the target entry. */ +void list_insert_after(struct list *list, struct link *target, struct link *link); + +/** Remove an entry from a list. */ +void list_remove(struct list *list, struct link *link); + +/** Remove the head of the list. */ +struct link *list_pop(struct list *list); + +/** Check if a link is attached to a list. */ +bool list_attached(const struct list *list, const struct link *link); + +// Helper for LIST_FOR_EACH_*() +#define LIST_FOR_EACH_IMPL(entry, type, i, member, ...) \ + for (type *_next, *i = BFS_CONTAINER_OF(entry, type, member); \ + i && (_next = BFS_CONTAINER_OF(i->member.next, type, member), true); \ + i = _next) + +/** + * Iterate over a list from the given entry. + * + * @param entry + * The entry to start from. + * @param type + * The type of the list entries. + * @param i + * The name of the loop variable, declared as type *i. + * @param member + * The name of the list link field (default: link). + */ +#define LIST_FOR_EACH_FROM(...) \ + LIST_FOR_EACH_IMPL(__VA_ARGS__, link,) + +/** + * Iterate over a list. + * + * @param list + * The list to iterate over. + * @param type + * The type of the list entries. + * @param i + * The name of the loop variable, declared as type *i. + * @param member + * The name of the list link field (default: link). + */ +#define LIST_FOR_EACH(list, ...) \ + LIST_FOR_EACH_FROM((list)->head, __VA_ARGS__) + +// Pop from a list or slist +#define LIST_POP(l) _Generic((l), \ + struct list *: list_pop((struct list *)l), \ + struct slist *: slist_pop((struct slist *)l)) + +// Helper for LIST_DRAIN() +#define LIST_DRAIN_IMPL(list, type, i, member, ...) \ + for (type *i; (i = BFS_CONTAINER_OF(LIST_POP(list), type, member));) + +/** + * Drain the entries from a list. + * + * @param list + * The list to drain. + * @param type + * The type of the list entries. + * @param i + * The name of the loop variable, declared as type *i. + * @param member + * The name of the list link field (default: link). + */ +#define LIST_DRAIN(...) \ + LIST_DRAIN_IMPL(__VA_ARGS__, link,) + +#endif // BFS_LIST_H -- cgit v1.2.3 From 86f4b4f7180bca73a734249e67dada708f8275ff Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 31 Mar 2023 16:19:45 -0400 Subject: list: Use macros instead of type-erased lists --- Makefile | 1 - src/bftw.c | 136 ++++++++++++------ src/config.h | 11 -- src/list.c | 169 ---------------------- src/list.h | 447 ++++++++++++++++++++++++++++++++++++++--------------------- src/trie.c | 8 +- src/trie.h | 9 +- src/xspawn.c | 15 +- src/xspawn.h | 4 +- tests/trie.c | 2 + 10 files changed, 403 insertions(+), 399 deletions(-) delete mode 100644 src/list.c (limited to 'src/config.h') diff --git a/Makefile b/Makefile index 428a0f7..b509065 100644 --- a/Makefile +++ b/Makefile @@ -223,7 +223,6 @@ LIBBFS := \ $(OBJ)/src/eval.o \ $(OBJ)/src/exec.o \ $(OBJ)/src/fsade.o \ - $(OBJ)/src/list.o \ $(OBJ)/src/mtab.o \ $(OBJ)/src/opt.o \ $(OBJ)/src/parse.o \ diff --git a/src/bftw.c b/src/bftw.c index aa36b87..7bc724a 100644 --- a/src/bftw.c +++ b/src/bftw.c @@ -7,6 +7,8 @@ * - struct bftw_file: A file that has been encountered during the traversal. * They have reference-counted links to their parents in the directory tree. * + * - struct bftw_list: A linked list of bftw_file's. + * * - struct bftw_cache: An LRU list of bftw_file's with open file descriptors, * used for openat() to minimize the amount of path re-traversals. * @@ -39,11 +41,14 @@ struct bftw_file { struct bftw_file *parent; /** The root under which this file was found. */ struct bftw_file *root; + /** The next file in the queue, if any. */ + struct bftw_file *next; - /** Queue link. */ - struct slink link; - /** LRU link. */ - struct link lru; + /** LRU list links. */ + struct { + struct bftw_file *prev; + struct bftw_file *next; + } lru; /** This file's depth in the walk. */ size_t depth; @@ -68,36 +73,42 @@ struct bftw_file { char name[]; }; -/** Move from a list entry to a bftw_file. */ -#define BFTW_FILE(...) \ - LIST_ITEM(struct bftw_file, __VA_ARGS__) +/** + * A linked list of bftw_file's. + */ +struct bftw_list { + struct bftw_file *head; + struct bftw_file **tail; +}; /** * A cache of open directories. */ struct bftw_cache { - /** The LRU list. */ - struct list list; + /** The head of the LRU list. */ + struct bftw_file *head; + /** The tail of the LRU list. */ + struct bftw_file *tail; /** The insertion target for the LRU list. */ - struct link *target; + struct bftw_file *target; /** The remaining capacity of the LRU list. */ size_t capacity; }; /** Initialize a cache. */ static void bftw_cache_init(struct bftw_cache *cache, size_t capacity) { - list_init(&cache->list); + LIST_INIT(cache); cache->target = NULL; cache->capacity = capacity; } /** Remove a bftw_file from the cache. */ static void bftw_cache_remove(struct bftw_cache *cache, struct bftw_file *file) { - if (cache->target == &file->lru) { - cache->target = cache->target->prev; + if (cache->target == file) { + cache->target = file->lru.prev; } - list_remove(&cache->list, &file->lru); + LIST_REMOVE(cache, file, lru); ++cache->capacity; } @@ -106,7 +117,7 @@ static void bftw_cache_remove(struct bftw_cache *cache, struct bftw_file *file) static void bftw_file_close(struct bftw_cache *cache, struct bftw_file *file) { assert(file->fd >= 0); - if (list_attached(&cache->list, &file->lru)) { + if (LIST_ATTACHED(cache, file, lru)) { bftw_cache_remove(cache, file); } @@ -116,11 +127,11 @@ static void bftw_file_close(struct bftw_cache *cache, struct bftw_file *file) { /** Pop the least recently used directory from the cache. */ static int bftw_cache_pop(struct bftw_cache *cache) { - if (list_is_empty(&cache->list)) { + struct bftw_file *file = cache->tail; + if (!file) { return -1; } - struct bftw_file *file = BFTW_FILE(cache->list.tail, lru); bftw_file_close(cache, file); return 0; } @@ -138,11 +149,11 @@ static int bftw_cache_add(struct bftw_cache *cache, struct bftw_file *file) { assert(cache->capacity > 0); --cache->capacity; - list_insert_after(&cache->list, cache->target, &file->lru); + LIST_INSERT(cache, cache->target, file, lru); // Prefer to keep the root paths open by keeping them at the head of the list if (file->depth == 0) { - cache->target = &file->lru; + cache->target = file; } return 0; @@ -159,8 +170,9 @@ static size_t bftw_child_nameoff(const struct bftw_file *parent) { /** Destroy a cache. */ static void bftw_cache_destroy(struct bftw_cache *cache) { + assert(!cache->head); + assert(!cache->tail); assert(!cache->target); - assert(list_is_empty(&cache->list)); } /** Create a new bftw_file. */ @@ -186,8 +198,8 @@ static struct bftw_file *bftw_file_new(struct bftw_file *parent, const char *nam file->nameoff = 0; } - slink_init(&file->link); - link_init(&file->lru); + file->next = NULL; + file->lru.prev = file->lru.next = NULL; file->refcount = 1; file->fd = -1; @@ -280,16 +292,19 @@ static int bftw_file_open(struct bftw_cache *cache, struct bftw_file *file, cons } // Handle ENAMETOOLONG by manually traversing the path component-by-component - struct slist parents; - slist_init(&parents); - for (struct bftw_file *cur = file; cur != base; cur = cur->parent) { - slist_prepend(&parents, &cur->link); + struct bftw_list parents; + SLIST_INIT(&parents); + + struct bftw_file *cur; + for (cur = file; cur != base; cur = cur->parent) { + SLIST_PREPEND(&parents, cur); } - LIST_DRAIN(&parents, struct bftw_file, cur) { + while ((cur = parents.head)) { if (!cur->parent || cur->parent->fd >= 0) { bftw_file_openat(cache, cur, cur->parent, cur->name); } + SLIST_POP(&parents); } return file->fd; @@ -348,9 +363,9 @@ struct bftw_state { /** The cache of open directories. */ struct bftw_cache cache; /** The queue of files left to explore. */ - struct slist queue; + struct bftw_list queue; /** A batch of files to enqueue. */ - struct slist batch; + struct bftw_list batch; /** The current path. */ char *path; @@ -396,8 +411,8 @@ static int bftw_state_init(struct bftw_state *state, const struct bftw_args *arg bftw_cache_init(&state->cache, args->nopenfd); - slist_init(&state->queue); - slist_init(&state->batch); + SLIST_INIT(&state->queue); + SLIST_INIT(&state->batch); state->file = NULL; state->previous = NULL; @@ -757,7 +772,7 @@ static int bftw_push(struct bftw_state *state, const char *name, bool fill_id) { bftw_fill_id(file, &state->ftwbuf); } - slist_append(&state->batch, &file->link); + SLIST_APPEND(&state->batch, file); return 0; } @@ -800,11 +815,12 @@ static int bftw_build_path(struct bftw_state *state) { * Pop the next file from the queue. */ static int bftw_pop(struct bftw_state *state) { - if (!state->queue.head) { + state->file = state->queue.head; + if (!state->file) { return 0; } - state->file = BFTW_FILE(slist_pop(&state->queue)); + SLIST_POP(&state->queue); if (bftw_build_path(state) != 0) { return -1; @@ -940,8 +956,10 @@ static enum bftw_action bftw_gc_file(struct bftw_state *state, enum bftw_gc_flag * Drain all the files from the queue. */ static void bftw_drain_queue(struct bftw_state *state) { - LIST_DRAIN(&state->queue, struct bftw_file, file) { - state->file = file; + while (state->queue.head) { + state->file = state->queue.head; + SLIST_POP(&state->queue); + bftw_gc_file(state, BFTW_VISIT_NONE); } } @@ -966,21 +984,55 @@ static int bftw_state_destroy(struct bftw_state *state) { return state->error ? -1 : 0; } -/** Comparison function for BFTW_SORT. */ -static bool bftw_file_cmp(struct slink *left, struct slink *right, const void *ptr) { - return strcoll(BFTW_FILE(left)->name, BFTW_FILE(right)->name) <= 0; +/** Sort a bftw_list by filename. */ +static void bftw_list_sort(struct bftw_list *queue) { + if (!queue->head || !queue->head->next) { + return; + } + + struct bftw_list left, right; + SLIST_INIT(&left); + SLIST_INIT(&right); + + // Split + for (struct bftw_file *hare = queue->head; hare && (hare = hare->next); hare = hare->next) { + struct bftw_file *tortoise = queue->head; + SLIST_POP(queue); + SLIST_APPEND(&left, tortoise); + } + SLIST_EXTEND(&right, queue); + + // Recurse + bftw_list_sort(&left); + bftw_list_sort(&right); + + // Merge + while (left.head && right.head) { + struct bftw_file *lf = left.head; + struct bftw_file *rf = right.head; + + if (strcoll(lf->name, rf->name) <= 0) { + SLIST_POP(&left); + SLIST_APPEND(queue, lf); + } else { + SLIST_POP(&right); + SLIST_APPEND(queue, rf); + } + } + SLIST_EXTEND(queue, &left); + SLIST_EXTEND(queue, &right); } /** Finish adding a batch of files. */ static void bftw_batch_finish(struct bftw_state *state) { if (state->flags & BFTW_SORT) { - slist_sort(&state->batch, bftw_file_cmp, NULL); + bftw_list_sort(&state->batch); } if (state->strategy == BFTW_DFS) { - slist_extend(&state->batch, &state->queue); + SLIST_EXTEND(&state->batch, &state->queue); } - slist_extend(&state->queue, &state->batch); + SLIST_EXTEND(&state->queue, &state->batch); } /** diff --git a/src/config.h b/src/config.h index cee8511..34ae11d 100644 --- a/src/config.h +++ b/src/config.h @@ -147,17 +147,6 @@ */ #define BFS_COUNTOF(array) (sizeof(array) / sizeof(0[array])) -// BFS_CONTAINER_OF() helper -static inline char *bfs_container_offset(char *ptr, ptrdiff_t offset, size_t unused) { - return ptr ? ptr - offset : NULL; -} - -/** - * Move a pointer from a field to its outer struct. - */ -#define BFS_CONTAINER_OF(ptr, type, member) \ - ((type *)bfs_container_offset((char *)(ptr), offsetof(type, member), sizeof((ptr) - &((type *)NULL)->member))) - // Lower bound on BFS_FLEX_SIZEOF() #define BFS_FLEX_LB(type, member, length) (offsetof(type, member) + sizeof(((type *)NULL)->member[0]) * (length)) diff --git a/src/list.c b/src/list.c deleted file mode 100644 index dffee19..0000000 --- a/src/list.c +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include "list.h" -#include -#include - -void slink_init(struct slink *link) { - link->next = NULL; -} - -void slist_init(struct slist *list) { - list->head = NULL; - list->tail = &list->head; -} - -bool slist_is_empty(const struct slist *list) { - return !list->head; -} - -void slist_append(struct slist *list, struct slink *link) { - assert(!link->next); - *list->tail = link; - list->tail = &link->next; -} - -void slist_prepend(struct slist *list, struct slink *link) { - assert(!link->next); - if (!list->head) { - list->tail = &link->next; - } - link->next = list->head; - list->head = link; -} - -void slist_extend(struct slist *dest, struct slist *src) { - if (src->head) { - *dest->tail = src->head; - dest->tail = src->tail; - slist_init(src); - } -} - -struct slink *slist_pop(struct slist *list) { - struct slink *head = list->head; - if (!head) { - return NULL; - } - - list->head = head->next; - if (!list->head) { - list->tail = &list->head; - } - - head->next = NULL; - return head; -} - -void slist_sort(struct slist *list, slist_cmp_fn *cmp_fn, const void *ptr) { - if (!list->head || !list->head->next) { - return; - } - - struct slist left, right; - slist_init(&left); - slist_init(&right); - - // Split - for (struct slink *hare = list->head; hare && (hare = hare->next); hare = hare->next) { - slist_append(&left, slist_pop(list)); - } - slist_extend(&right, list); - - // Recurse - slist_sort(&left, cmp_fn, ptr); - slist_sort(&right, cmp_fn, ptr); - - // Merge - while (left.head && right.head) { - if (cmp_fn(left.head, right.head, ptr)) { - slist_append(list, slist_pop(&left)); - } else { - slist_append(list, slist_pop(&right)); - } - } - slist_extend(list, &left); - slist_extend(list, &right); -} - -void link_init(struct link *link) { - link->prev = NULL; - link->next = NULL; -} - -void list_init(struct list *list) { - list->head = NULL; - list->tail = NULL; -} - -bool list_is_empty(const struct list *list) { - return !list->head; -} - -void list_append(struct list *list, struct link *link) { - list_insert_after(list, list->tail, link); -} - -void list_prepend(struct list *list, struct link *link) { - list_insert_after(list, NULL, link); -} - -void list_insert_after(struct list *list, struct link *target, struct link *link) { - assert(!list_attached(list, link)); - - if (target) { - link->prev = target; - link->next = target->next; - } else { - link->next = list->head; - } - - if (link->prev) { - link->prev->next = link; - } else { - list->head = link; - } - - if (link->next) { - link->next->prev = link; - } else { - list->tail = link; - } -} - -void list_remove(struct list *list, struct link *link) { - if (link->prev) { - assert(list->head != link); - link->prev->next = link->next; - } else { - assert(list->head == link); - list->head = link->next; - } - - if (link->next) { - assert(list->tail != link); - link->next->prev = link->prev; - } else { - assert(list->tail == link); - list->tail = link->prev; - } - - link->prev = NULL; - link->next = NULL; -} - -struct link *list_pop(struct list *list) { - struct link *head = list->head; - if (!head) { - return NULL; - } - - list_remove(list, head); - return head; -} - -bool list_attached(const struct list *list, const struct link *link) { - return link->prev || list->head == link - || link->next || list->tail == link; -} diff --git a/src/list.h b/src/list.h index b47bed7..c43be68 100644 --- a/src/list.h +++ b/src/list.h @@ -3,225 +3,354 @@ /** * Intrusive linked lists. + * + * Singly-linked lists are declared like this: + * + * struct item { + * struct item *next; + * }; + * + * struct list { + * struct item *head; + * struct item **tail; + * }; + * + * The SLIST_*() macros manipulate singly-linked lists. + * + * struct list list; + * SLIST_INIT(&list); + * + * struct item item; + * SLIST_APPEND(&list, &item); + * + * Doubly linked lists are similar: + * + * struct item { + * struct item *next; + * struct item *prev; + * }; + * + * struct list { + * struct item *head; + * struct item *tail; + * }; + * + * struct list list; + * LIST_INIT(&list); + * + * struct item item; + * LIST_APPEND(&list, &item); + * + * Items can be on multiple lists at once: + * + * struct item { + * struct { + * struct item *next; + * } chain; + * + * struct { + * struct item *next; + * struct item *prev; + * } lru; + * }; + * + * struct items { + * struct { + * struct item *head; + * struct item **tail; + * } queue; + * + * struct { + * struct item *head; + * struct item *tail; + * } cache; + * }; + * + * struct items items; + * SLIST_INIT(&items.queue); + * LIST_INIT(&items.cache); + * + * struct item item; + * SLIST_APPEND(&items.queue, &item, chain); + * LIST_APPEND(&items.cache, &item, lru); */ #ifndef BFS_LIST_H #define BFS_LIST_H -#include "config.h" -#include +#include /** - * A singly-linked list entry. + * Initialize a singly-linked list. + * + * @param list + * The list to initialize. + * + * --- + * + * Like many macros in this file, this macro delegates the bulk of its work to + * some helper macros. We explicitly parenthesize (list) here so the helpers + * don't have to. */ -struct slink { - struct slink *next; -}; +#define SLIST_INIT(list) \ + LIST_BLOCK_(SLIST_INIT_((list))) -/** Initialize a list entry. */ -void slink_init(struct slink *link); +#define SLIST_INIT_(list) \ + (list)->head = NULL; \ + (list)->tail = &(list)->head; /** - * A singly-linked list. + * Wraps a group of statements in a block. */ -struct slist { - struct slink *head; - struct slink **tail; -}; - -/** Initialize an empty list. */ -void slist_init(struct slist *list); - -/** Check if a list is empty. */ -bool slist_is_empty(const struct slist *list); - -/** Add an entry at the tail of the list. */ -void slist_append(struct slist *list, struct slink *link); - -/** Add an entry at the head of the list. */ -void slist_prepend(struct slist *list, struct slink *link); - -/** Add an entire list at the tail of the list. */ -void slist_extend(struct slist *dest, struct slist *src); - -/** Remove the head of the list. */ -struct slink *slist_pop(struct slist *list); +#define LIST_BLOCK_(block) do { block } while (0) /** - * Comparison function type for slist_sort(). + * Add an item to the tail of a singly-linked list. * - * @param left - * The left-hand side of the comparison. - * @param right - * The right-hand side of the comparison. - * @param ptr - * An arbitrary pointer passed to slist_sort(). - * @return - * Whether left <= right. + * @param list + * The list to modify. + * @param item + * The item to append. + * @param link (optional) + * If specified, use item->link.next rather than item->next. + * + * --- + * + * We play some tricks with variadic macros to handle the optional parameter: + * + * SLIST_APPEND(list, item) => { + * *list->tail = item; + * list->tail = &item->next; + * } + * + * SLIST_APPEND(list, item, link) => { + * *list->tail = item; + * list->tail = &item->link.next; + * } + * + * The first trick is that + * + * #define SLIST_APPEND(list, item, ...) + * + * won't work because both commas are required (until C23; see N3033). As a + * workaround, we dispatch to another macro and add a trailing comma. + * + * SLIST_APPEND(list, item) => SLIST_APPEND_(list, item, ) + * SLIST_APPEND(list, item, link) => SLIST_APPEND_(list, item, link, ) */ -typedef bool slist_cmp_fn(struct slink *left, struct slink *right, const void *ptr); +#define SLIST_APPEND(list, ...) SLIST_APPEND_(list, __VA_ARGS__, ) -/** Sort a list. */ -void slist_sort(struct slist *list, slist_cmp_fn *cmp_fn, const void *ptr); +/** + * Now we need a way to generate either ->next or ->link.next depending on + * whether the link parameter was passed. The approach is based on + * + * #define FOO(...) BAR(__VA_ARGS__, 1, 2, ) + * #define BAR(x, y, z, ...) z + * + * FOO(a) => 2 + * FOO(a, b) => 1 + * + * The LIST_NEXT_() macro uses this technique: + * + * LIST_NEXT_() => LIST_LINK_(next, ) + * LIST_NEXT_(link, ) => LIST_LINK_(next, link, ) + */ +#define LIST_NEXT_(...) LIST_LINK_(next, __VA_ARGS__) /** - * A doubly-linked list entry. + * LIST_LINK_() dispatches to yet another macro: + * + * LIST_LINK_(next, ) => LIST_LINK__(next, , , . , , ) + * LIST_LINK_(next, link, ) => LIST_LINK__(next, link, , , . , , ) */ -struct link { - struct link *prev; - struct link *next; -}; +#define LIST_LINK_(dir, ...) LIST_LINK__(dir, __VA_ARGS__, , . , , ) -/** Initialize a list entry. */ -void link_init(struct link *link); +/** + * And finally, LIST_LINK__() adds the link and the dot if necessary. + * + * dir link blank ignored dot + * v v v v v + * LIST_LINK__(next, , , . , , ) => next + * LIST_LINK__(next, link, , , . , , ) => link . next + * ^ ^ ^ ^ ^ + * dir link blank ignored dot + */ +#define LIST_LINK__(dir, link, blank, ignored, dot, ...) link dot dir /** - * A doubly-linked list. + * SLIST_APPEND_() uses LIST_NEXT_() to generate the right name for the list + * link, and finally delegates to the actual implementation. + * + * SLIST_APPEND_(list, item, ) => SLIST_APPEND__((list), (item), next) + * SLIST_APPEND_(list, item, link, ) => SLIST_APPEND__((list), (item), link.next) */ -struct list { - struct link *head; - struct link *tail; -}; +#define SLIST_APPEND_(list, item, ...) \ + LIST_BLOCK_(SLIST_APPEND__((list), (item), LIST_NEXT_(__VA_ARGS__))) -/** Initialize an empty list. */ -void list_init(struct list *list); +#define SLIST_APPEND__(list, item, next) \ + *list->tail = item; \ + list->tail = &item->next; -/** Check if a list is empty. */ -bool list_is_empty(const struct list *list); +/** + * Add an item to the head of a singly-linked list. + * + * @param list + * The list to modify. + * @param item + * The item to prepend. + * @param link (optional) + * If specified, use item->link.next rather than item->next. + */ +#define SLIST_PREPEND(list, ...) SLIST_PREPEND_(list, __VA_ARGS__, ) -/** Add an entry at the tail of the list. */ -void list_append(struct list *list, struct link *link); +#define SLIST_PREPEND_(list, item, ...) \ + LIST_BLOCK_(SLIST_PREPEND__((list), (item), LIST_NEXT_(__VA_ARGS__))) -/** Add an entry at the head of the list. */ -void list_prepend(struct list *list, struct link *link); +#define SLIST_PREPEND__(list, item, next) \ + list->tail = list->head ? list->tail : &item->next; \ + item->next = list->head; \ + list->head = item; -/** Insert an entry after the target entry. */ -void list_insert_after(struct list *list, struct link *target, struct link *link); +/** + * Add an entire singly-linked list to the tail of another. + * + * @param dest + * The destination list. + * @param src + * The source list. + */ +#define SLIST_EXTEND(dest, src) \ + LIST_BLOCK_(SLIST_EXTEND_((dest), (src))) -/** Remove an entry from a list. */ -void list_remove(struct list *list, struct link *link); +#define SLIST_EXTEND_(dest, src) \ + if (src->head) { \ + *dest->tail = src->head; \ + dest->tail = src->tail; \ + SLIST_INIT(src); \ + } -/** Remove the head of the list. */ -struct link *list_pop(struct list *list); +/** + * Pop the head off a singly-linked list. + * + * @param list + * The list to pop from. + * @param link (optional) + * If specified, use head->link.next rather than head->next. + */ +#define SLIST_POP(...) SLIST_POP_(__VA_ARGS__, ) -/** Check if a link is attached to a list. */ -bool list_attached(const struct list *list, const struct link *link); +#define SLIST_POP_(list, ...) \ + LIST_BLOCK_(SLIST_POP__((list), LIST_NEXT_(__VA_ARGS__))) -// LIST_ITEM() helper -#define LIST_ITEM_IMPL(type, entry, member, ...) \ - BFS_CONTAINER_OF(entry, type, member) +#define SLIST_POP__(list, next) \ + void *_next = (void *)list->head->next; \ + list->head->next = NULL; \ + list->head = _next; \ + list->tail = list->head ? list->tail : &list->head; /** - * Convert a list entry to its container. + * Initialize a doubly-linked list. * - * @param type - * The type of the list entries. - * @param entry - * The list entry to convert. - * @param member - * The name of the list link field (default: link). - * @return - * The item that contains the given entry. + * @param list + * The list to initialize. */ -#define LIST_ITEM(...) \ - LIST_ITEM_IMPL(__VA_ARGS__, link,) +#define LIST_INIT(list) \ + LIST_BLOCK_(LIST_INIT_((list))) -// LIST_NEXT() helper -#define LIST_NEXT_IMPL(type, entry, member, ...) \ - LIST_ITEM(type, (entry)->member.next, member) +#define LIST_INIT_(list) \ + list->head = list->tail = NULL; /** - * Get the next item in a list. - * - * @param type - * The type of the list entries. - * @param entry - * The current entry. - * @param member - * The name of the list link field (default: link). - * @return - * The next item in the list. + * LIST_PREV_() => prev + * LIST_PREV_(link, ) => link.prev */ -#define LIST_NEXT(...) \ - LIST_NEXT_IMPL(__VA_ARGS__, link,) - -// LIST_PREV() helper -#define LIST_PREV_IMPL(type, entry, member, ...) \ - LIST_ITEM(type, (entry)->member.prev, member) +#define LIST_PREV_(...) LIST_LINK_(prev, __VA_ARGS__) /** - * Get the previous entry in a list. + * Add an item to the tail of a doubly-linked list. * - * @param type - * The type of the list entries. - * @param entry - * The current entry. - * @param member - * The name of the list link field (default: link). - * @return - * The previous item in the list. + * @param list + * The list to modify. + * @param item + * The item to append. + * @param link (optional) + * If specified, use item->link.{prev,next} rather than item->{prev,next}. */ -#define LIST_PREV(...) \ - LIST_PREV_IMPL(__VA_ARGS__, link,) +#define LIST_APPEND(list, ...) LIST_INSERT(list, (list)->tail, __VA_ARGS__) -// Helper for LIST_FOR_EACH_*() -#define LIST_FOR_EACH_IMPL(entry, type, i, member, ...) \ - for (type *_next, *i = LIST_ITEM(type, entry, member); \ - i && (_next = LIST_NEXT(type, i, member), true); \ - i = _next) +/** + * Add an item to the head of a doubly-linked list. + * + * @param list + * The list to modify. + * @param item + * The item to prepend. + * @param link (optional) + * If specified, use item->link.{prev,next} rather than item->{prev,next}. + */ +#define LIST_PREPEND(list, ...) LIST_INSERT(list, NULL, __VA_ARGS__) /** - * Iterate over a list from the given entry. + * Insert into a doubly-linked list after the given cursor. * - * @param entry - * The entry to start from. - * @param type - * The type of the list entries. - * @param i - * The name of the loop variable, declared as type *i. - * @param member - * The name of the list link field (default: link). + * @param list + * The list to initialize. + * @param cursor + * Insert after this element. + * @param item + * The item to insert. + * @param link (optional) + * If specified, use item->link.{prev,next} rather than item->{prev,next}. */ -#define LIST_FOR_EACH_FROM(...) \ - LIST_FOR_EACH_IMPL(__VA_ARGS__, link,) +#define LIST_INSERT(list, cursor, ...) LIST_INSERT_(list, cursor, __VA_ARGS__, ) + +#define LIST_INSERT_(list, cursor, item, ...) \ + LIST_BLOCK_(LIST_INSERT__((list), (cursor), (item), LIST_PREV_(__VA_ARGS__), LIST_NEXT_(__VA_ARGS__))) + +#define LIST_INSERT__(list, cursor, item, prev, next) \ + item->prev = cursor; \ + item->next = cursor ? cursor->next : list->head; \ + *(item->prev ? &item->prev->next : &list->head) = item; \ + *(item->next ? &item->next->prev : &list->tail) = item; /** - * Iterate over a list. + * Remove an item from a doubly-linked list. * * @param list - * The list to iterate over. - * @param type - * The type of the list entries. - * @param i - * The name of the loop variable, declared as type *i. - * @param member - * The name of the list link field (default: link). + * The list to modify. + * @param item + * The item to remove. + * @param link (optional) + * If specified, use item->link.{prev,next} rather than item->{prev,next}. */ -#define LIST_FOR_EACH(list, ...) \ - LIST_FOR_EACH_FROM((list)->head, __VA_ARGS__) +#define LIST_REMOVE(list, ...) LIST_REMOVE_(list, __VA_ARGS__, ) -// Pop from a list or slist -#define LIST_POP(l) _Generic((l), \ - struct list *: list_pop((struct list *)l), \ - struct slist *: slist_pop((struct slist *)l)) +#define LIST_REMOVE_(list, item, ...) \ + LIST_BLOCK_(LIST_REMOVE__((list), (item), LIST_PREV_(__VA_ARGS__), LIST_NEXT_(__VA_ARGS__))) -// Helper for LIST_DRAIN() -#define LIST_DRAIN_IMPL(list, type, i, member, ...) \ - for (type *i; (i = LIST_ITEM(type, LIST_POP(list), member));) +#define LIST_REMOVE__(list, item, prev, next) \ + *(item->prev ? &item->prev->next : &list->head) = item->next; \ + *(item->next ? &item->next->prev : &list->tail) = item->prev; \ + item->prev = item->next = NULL; /** - * Drain the entries from a list. + * Check if an item is attached to a doubly-linked list. * * @param list - * The list to drain. - * @param type - * The type of the list entries. - * @param i - * The name of the loop variable, declared as type *i. - * @param member - * The name of the list link field (default: link). - */ -#define LIST_DRAIN(...) \ - LIST_DRAIN_IMPL(__VA_ARGS__, link,) + * The list to check. + * @param item + * The item to check. + * @param link (optional) + * If specified, use item->link.{prev,next} rather than item->{prev,next}. + * @return + * Whether the item is attached to the list. + */ +#define LIST_ATTACHED(list, ...) LIST_ATTACHED_(list, __VA_ARGS__, ) + +#define LIST_ATTACHED_(list, item, ...) \ + LIST_ATTACHED__((list), (item), LIST_PREV_(__VA_ARGS__), LIST_NEXT_(__VA_ARGS__)) + +#define LIST_ATTACHED__(list, item, prev, next) \ + (item->prev || item->next || list->head == item || list->tail == item) #endif // BFS_LIST_H diff --git a/src/trie.c b/src/trie.c index 7b00f4b..43df9dc 100644 --- a/src/trie.c +++ b/src/trie.c @@ -83,6 +83,7 @@ #include "trie.h" #include "config.h" +#include "list.h" #include #include #include @@ -163,7 +164,7 @@ static uintptr_t trie_encode_node(const struct trie_node *node) { void trie_init(struct trie *trie) { trie->root = 0; - list_init(&trie->leaves); + LIST_INIT(trie); } /** Check if a number is a power of two. */ @@ -340,8 +341,7 @@ static struct trie_leaf *trie_leaf_alloc(struct trie *trie, const void *key, siz return NULL; } - link_init(&leaf->link); - list_append(&trie->leaves, &leaf->link); + LIST_APPEND(trie, leaf); leaf->value = NULL; leaf->length = length; @@ -352,7 +352,7 @@ static struct trie_leaf *trie_leaf_alloc(struct trie *trie, const void *key, siz /** Free a leaf. */ static void trie_leaf_free(struct trie *trie, struct trie_leaf *leaf) { - list_remove(&trie->leaves, &leaf->link); + LIST_REMOVE(trie, leaf); free(leaf); } diff --git a/src/trie.h b/src/trie.h index 6e1e875..58974aa 100644 --- a/src/trie.h +++ b/src/trie.h @@ -5,7 +5,6 @@ #define BFS_TRIE_H #include "config.h" -#include "list.h" #include #include #include @@ -15,7 +14,7 @@ */ struct trie_leaf { /** Linked list of leaves, in insertion order. */ - struct link link; + struct trie_leaf *prev, *next; /** An arbitrary value associated with this leaf. */ void *value; /** The length of the key in bytes. */ @@ -31,7 +30,7 @@ struct trie { /** Pointer to the root node/leaf. */ uintptr_t root; /** Linked list of leaves. */ - struct list leaves; + struct trie_leaf *head, *tail; }; /** @@ -134,6 +133,8 @@ void trie_destroy(struct trie *trie); * Iterate over the leaves of a trie. */ #define TRIE_FOR_EACH(trie, leaf) \ - LIST_FOR_EACH(&(trie)->leaves, struct trie_leaf, leaf) + for (struct trie_leaf *leaf = (trie)->head, *_next; \ + leaf && (_next = leaf->next, true); \ + leaf = _next) #endif // BFS_TRIE_H diff --git a/src/xspawn.c b/src/xspawn.c index e6ce0de..a185200 100644 --- a/src/xspawn.c +++ b/src/xspawn.c @@ -33,7 +33,7 @@ enum bfs_spawn_op { * A spawn action. */ struct bfs_spawn_action { - struct slink link; + struct bfs_spawn_action *next; enum bfs_spawn_op op; int in_fd; @@ -44,12 +44,14 @@ struct bfs_spawn_action { int bfs_spawn_init(struct bfs_spawn *ctx) { ctx->flags = 0; - slist_init(&ctx->actions); + SLIST_INIT(ctx); return 0; } int bfs_spawn_destroy(struct bfs_spawn *ctx) { - LIST_DRAIN(&ctx->actions, struct bfs_spawn_action, action) { + while (ctx->head) { + struct bfs_spawn_action *action = ctx->head; + SLIST_POP(ctx); free(action); } @@ -68,12 +70,12 @@ static struct bfs_spawn_action *bfs_spawn_add(struct bfs_spawn *ctx, enum bfs_sp return NULL; } - slink_init(&action->link); + action->next = NULL; action->op = op; action->in_fd = -1; action->out_fd = -1; - slist_append(&ctx->actions, &action->link); + SLIST_APPEND(ctx, action); return action; } @@ -138,8 +140,7 @@ int bfs_spawn_addsetrlimit(struct bfs_spawn *ctx, int resource, const struct rli static void bfs_spawn_exec(const char *exe, const struct bfs_spawn *ctx, char **argv, char **envp, int pipefd[2]) { xclose(pipefd[0]); - const struct slink *head = ctx ? ctx->actions.head : NULL; - LIST_FOR_EACH_FROM(head, struct bfs_spawn_action, action) { + for (const struct bfs_spawn_action *action = ctx ? ctx->head : NULL; action; action = action->next) { // Move the error-reporting pipe out of the way if necessary... if (action->out_fd == pipefd[1]) { int fd = dup_cloexec(pipefd[1]); diff --git a/src/xspawn.h b/src/xspawn.h index 7e673f1..d9b4a2e 100644 --- a/src/xspawn.h +++ b/src/xspawn.h @@ -8,7 +8,6 @@ #ifndef BFS_XSPAWN_H #define BFS_XSPAWN_H -#include "list.h" #include #include @@ -25,7 +24,8 @@ enum bfs_spawn_flags { */ struct bfs_spawn { enum bfs_spawn_flags flags; - struct slist actions; + struct bfs_spawn_action *head; + struct bfs_spawn_action **tail; }; /** diff --git a/tests/trie.c b/tests/trie.c index 65660a9..c2af18a 100644 --- a/tests/trie.c +++ b/tests/trie.c @@ -74,6 +74,8 @@ int main(void) { size_t i = 0; TRIE_FOR_EACH(&trie, leaf) { assert(leaf == trie_find_str(&trie, keys[i])); + assert(!leaf->prev || leaf->prev->next == leaf); + assert(!leaf->next || leaf->next->prev == leaf); ++i; } assert(i == nkeys); -- cgit v1.2.3 From 7e5357a1cf40ebaa7ffaeebfd3a88c3ba93eb1a7 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 3 May 2023 09:29:19 -0400 Subject: style: Don't use tabs to indent preprocessor directives --- src/bfstd.c | 6 ++--- src/bfstd.h | 32 +++++++++++------------ src/config.h | 84 ++++++++++++++++++++++++++++++------------------------------ src/dir.c | 20 +++++++-------- src/eval.c | 22 ++++++++-------- src/fsade.c | 8 +++--- src/fsade.h | 8 +++--- src/mtab.c | 20 +++++++-------- src/printf.c | 8 +++--- src/stat.c | 10 ++++---- src/stat.h | 8 +++--- src/trie.c | 30 +++++++++++----------- src/xregex.c | 28 ++++++++++---------- src/xspawn.c | 2 +- 14 files changed, 143 insertions(+), 143 deletions(-) (limited to 'src/config.h') diff --git a/src/bfstd.c b/src/bfstd.c index bc31288..1dc322b 100644 --- a/src/bfstd.c +++ b/src/bfstd.c @@ -19,13 +19,13 @@ #include #if BFS_USE_SYS_SYSMACROS_H -# include +# include #elif BFS_USE_SYS_MKDEV_H -# include +# include #endif #if BFS_USE_UTIL_H -# include +# include #endif bool is_nonexistence_error(int error) { diff --git a/src/bfstd.h b/src/bfstd.h index f85b74f..028e4e6 100644 --- a/src/bfstd.h +++ b/src/bfstd.h @@ -21,29 +21,29 @@ bool is_nonexistence_error(int error); #include #ifndef O_EXEC -# ifdef O_PATH -# define O_EXEC O_PATH -# else -# define O_EXEC O_RDONLY -# endif +# ifdef O_PATH +# define O_EXEC O_PATH +# else +# define O_EXEC O_RDONLY +# endif #endif #ifndef O_SEARCH -# ifdef O_PATH -# define O_SEARCH O_PATH -# else -# define O_SEARCH O_RDONLY -# endif +# ifdef O_PATH +# define O_SEARCH O_PATH +# else +# define O_SEARCH O_RDONLY +# endif #endif #ifndef O_DIRECTORY -# define O_DIRECTORY 0 +# define O_DIRECTORY 0 #endif #include #if !defined(FNM_CASEFOLD) && defined(FNM_IGNORECASE) -# define FNM_CASEFOLD FNM_IGNORECASE +# define FNM_CASEFOLD FNM_IGNORECASE #endif // #include @@ -144,10 +144,10 @@ int xminor(dev_t dev); // #include #if __APPLE__ -# define st_atim st_atimespec -# define st_ctim st_ctimespec -# define st_mtim st_mtimespec -# define st_birthtim st_birthtimespec +# define st_atim st_atimespec +# define st_ctim st_ctimespec +# define st_mtim st_mtimespec +# define st_birthtim st_birthtimespec #endif // #include diff --git a/src/config.h b/src/config.h index 34ae11d..5f54250 100644 --- a/src/config.h +++ b/src/config.h @@ -14,13 +14,13 @@ // bfs packaging configuration #ifndef BFS_COMMAND -# define BFS_COMMAND "bfs" +# define BFS_COMMAND "bfs" #endif #ifndef BFS_VERSION -# define BFS_VERSION "2.6.3" +# define BFS_VERSION "2.6.3" #endif #ifndef BFS_HOMEPAGE -# define BFS_HOMEPAGE "https://tavianator.com/projects/bfs.html" +# define BFS_HOMEPAGE "https://tavianator.com/projects/bfs.html" #endif // Check for system headers @@ -28,34 +28,34 @@ #ifdef __has_include #if __has_include() -# define BFS_HAS_MNTENT_H true +# define BFS_HAS_MNTENT_H true #endif #if __has_include() -# define BFS_HAS_PATHS_H true +# define BFS_HAS_PATHS_H true #endif #if __has_include() -# define BFS_HAS_SYS_ACL_H true +# define BFS_HAS_SYS_ACL_H true #endif #if __has_include() -# define BFS_HAS_SYS_CAPABILITY_H true +# define BFS_HAS_SYS_CAPABILITY_H true #endif #if __has_include() -# define BFS_HAS_SYS_EXTATTR_H true +# define BFS_HAS_SYS_EXTATTR_H true #endif #if __has_include() -# define BFS_HAS_SYS_MKDEV_H true +# define BFS_HAS_SYS_MKDEV_H true #endif #if __has_include() -# define BFS_HAS_SYS_PARAM_H true +# define BFS_HAS_SYS_PARAM_H true #endif #if __has_include() -# define BFS_HAS_SYS_SYSMACROS_H true +# define BFS_HAS_SYS_SYSMACROS_H true #endif #if __has_include() -# define BFS_HAS_SYS_XATTR_H true +# define BFS_HAS_SYS_XATTR_H true #endif #if __has_include() -# define BFS_HAS_UTIL_H true +# define BFS_HAS_UTIL_H true #endif #else // !__has_include @@ -74,59 +74,59 @@ #endif // !__has_include #ifndef BFS_USE_MNTENT_H -# define BFS_USE_MNTENT_H BFS_HAS_MNTENT_H +# define BFS_USE_MNTENT_H BFS_HAS_MNTENT_H #endif #ifndef BFS_USE_PATHS_H -# define BFS_USE_PATHS_H BFS_HAS_PATHS_H +# define BFS_USE_PATHS_H BFS_HAS_PATHS_H #endif #ifndef BFS_USE_SYS_ACL_H -# define BFS_USE_SYS_ACL_H BFS_HAS_SYS_ACL_H +# define BFS_USE_SYS_ACL_H BFS_HAS_SYS_ACL_H #endif #ifndef BFS_USE_SYS_CAPABILITY_H -# define BFS_USE_SYS_CAPABILITY_H BFS_HAS_SYS_CAPABILITY_H +# define BFS_USE_SYS_CAPABILITY_H BFS_HAS_SYS_CAPABILITY_H #endif #ifndef BFS_USE_SYS_EXTATTR_H -# define BFS_USE_SYS_EXTATTR_H BFS_HAS_SYS_EXTATTR_H +# define BFS_USE_SYS_EXTATTR_H BFS_HAS_SYS_EXTATTR_H #endif #ifndef BFS_USE_SYS_MKDEV_H -# define BFS_USE_SYS_MKDEV_H BFS_HAS_SYS_MKDEV_H +# define BFS_USE_SYS_MKDEV_H BFS_HAS_SYS_MKDEV_H #endif #ifndef BFS_USE_SYS_PARAM_H -# define BFS_USE_SYS_PARAM_H BFS_HAS_SYS_PARAM_H +# define BFS_USE_SYS_PARAM_H BFS_HAS_SYS_PARAM_H #endif #ifndef BFS_USE_SYS_SYSMACROS_H -# define BFS_USE_SYS_SYSMACROS_H BFS_HAS_SYS_SYSMACROS_H +# define BFS_USE_SYS_SYSMACROS_H BFS_HAS_SYS_SYSMACROS_H #endif #ifndef BFS_USE_SYS_XATTR_H -# define BFS_USE_SYS_XATTR_H BFS_HAS_SYS_XATTR_H +# define BFS_USE_SYS_XATTR_H BFS_HAS_SYS_XATTR_H #endif #ifndef BFS_USE_UTIL_H -# define BFS_USE_UTIL_H BFS_HAS_UTIL_H +# define BFS_USE_UTIL_H BFS_HAS_UTIL_H #endif // Stub out feature detection on old/incompatible compilers #ifndef __has_feature -# define __has_feature(feat) false +# define __has_feature(feat) false #endif #ifndef __has_c_attribute -# define __has_c_attribute(attr) false +# define __has_c_attribute(attr) false #endif #ifndef __has_attribute -# define __has_attribute(attr) false +# define __has_attribute(attr) false #endif // Platform detection // Get the definition of BSD if available #if BFS_USE_SYS_PARAM_H -# include +# include #endif #ifndef __GLIBC_PREREQ -# define __GLIBC_PREREQ(maj, min) false +# define __GLIBC_PREREQ(maj, min) false #endif // Wrappers for fundamental language features/extensions @@ -135,11 +135,11 @@ * Silence compiler warnings about switch/case fall-throughs. */ #if __has_c_attribute(fallthrough) -# define BFS_FALLTHROUGH [[fallthrough]] +# define BFS_FALLTHROUGH [[fallthrough]] #elif __has_attribute(fallthrough) -# define BFS_FALLTHROUGH __attribute__((fallthrough)) +# define BFS_FALLTHROUGH __attribute__((fallthrough)) #else -# define BFS_FALLTHROUGH ((void)0) +# define BFS_FALLTHROUGH ((void)0) #endif /** @@ -173,40 +173,40 @@ * Adds compiler warnings for bad printf()-style function calls, if supported. */ #if __has_attribute(format) -# define BFS_FORMATTER(fmt, args) __attribute__((format(printf, fmt, args))) +# define BFS_FORMATTER(fmt, args) __attribute__((format(printf, fmt, args))) #else -# define BFS_FORMATTER(fmt, args) +# define BFS_FORMATTER(fmt, args) #endif /** * Check if function multiversioning via GNU indirect functions (ifunc) is supported. */ #if !defined(BFS_TARGET_CLONES) && __has_attribute(target_clones) && (__GLIBC__ || __FreeBSD__ || __NetBSD__) -# define BFS_TARGET_CLONES true +# define BFS_TARGET_CLONES true #endif /** * Ignore a particular GCC warning for a region of code. */ #if __GNUC__ -# define BFS_PRAGMA_STRINGIFY(...) _Pragma(#__VA_ARGS__) -# define BFS_SUPPRESS(warning) \ - _Pragma("GCC diagnostic push"); \ +# define BFS_PRAGMA_STRINGIFY(...) _Pragma(#__VA_ARGS__) +# define BFS_SUPPRESS(warning) \ + _Pragma("GCC diagnostic push"); \ BFS_PRAGMA_STRINGIFY(GCC diagnostic ignored warning) -# define BFS_UNSUPPRESS() \ +# define BFS_UNSUPPRESS() \ _Pragma("GCC diagnostic pop") #else -# define BFS_SUPPRESS(warning) -# define BFS_UNSUPPRESS() +# define BFS_SUPPRESS(warning) +# define BFS_UNSUPPRESS() #endif /** * Initialize a variable, unless sanitizers would detect uninitialized uses. */ #if __has_feature(memory_sanitizer) -# define BFS_UNINIT(var, value) var = var +# define BFS_UNINIT(var, value) var = var #else -# define BFS_UNINIT(var, value) var = value +# define BFS_UNINIT(var, value) var = value #endif #endif // BFS_CONFIG_H diff --git a/src/dir.c b/src/dir.c index 2719c15..eb6e3e0 100644 --- a/src/dir.c +++ b/src/dir.c @@ -16,16 +16,16 @@ #include #ifndef BFS_GETDENTS -# define BFS_GETDENTS (__linux__ || __FreeBSD__) +# define BFS_GETDENTS (__linux__ || __FreeBSD__) #endif #if BFS_GETDENTS -# if __has_feature(memory_sanitizer) -# include -# endif -# if __linux__ -# include -# endif +# if __has_feature(memory_sanitizer) +# include +# endif +# if __linux__ +# include +# endif /** getdents() syscall wrapper. */ static ssize_t bfs_getdents(int fd, void *buf, size_t size) { @@ -119,10 +119,10 @@ struct bfs_dir { }; #if BFS_GETDENTS -# define DIR_SIZE (64 << 10) -# define BUF_SIZE (DIR_SIZE - sizeof(struct bfs_dir)) +# define DIR_SIZE (64 << 10) +# define BUF_SIZE (DIR_SIZE - sizeof(struct bfs_dir)) #else -# define DIR_SIZE sizeof(struct bfs_dir) +# define DIR_SIZE sizeof(struct bfs_dir) #endif struct bfs_dir *bfs_opendir(int at_fd, const char *at_path) { diff --git a/src/eval.c b/src/eval.c index 53ce605..687ba32 100644 --- a/src/eval.c +++ b/src/eval.c @@ -943,9 +943,9 @@ bool eval_xtype(const struct bfs_expr *expr, struct bfs_eval *state) { } #if _POSIX_MONOTONIC_CLOCK > 0 -# define BFS_CLOCK CLOCK_MONOTONIC +# define BFS_CLOCK CLOCK_MONOTONIC #elif _POSIX_TIMERS > 0 -# define BFS_CLOCK CLOCK_REALTIME +# define BFS_CLOCK CLOCK_REALTIME #endif /** @@ -1194,15 +1194,15 @@ static bool eval_file_unique(struct bfs_eval *state, struct trie *seen) { } } -#define DEBUG_FLAG(flags, flag) \ - do { \ - if ((flags & flag) || flags == flag) { \ - fputs(#flag, stderr); \ - flags ^= flag; \ - if (flags) { \ - fputs(" | ", stderr); \ - } \ - } \ +#define DEBUG_FLAG(flags, flag) \ + do { \ + if ((flags & flag) || flags == flag) { \ + fputs(#flag, stderr); \ + flags ^= flag; \ + if (flags) { \ + fputs(" | ", stderr); \ + } \ + } \ } while (0) /** diff --git a/src/fsade.c b/src/fsade.c index a61a6b8..aefbb75 100644 --- a/src/fsade.c +++ b/src/fsade.c @@ -13,17 +13,17 @@ #include #if BFS_CAN_CHECK_ACL -# include +# include #endif #if BFS_CAN_CHECK_CAPABILITIES -# include +# include #endif #if BFS_USE_SYS_EXTATTR_H -# include +# include #elif BFS_USE_SYS_XATTR_H -# include +# include #endif #if BFS_CAN_CHECK_ACL || BFS_CAN_CHECK_CAPABILITIES || BFS_CAN_CHECK_XATTRS diff --git a/src/fsade.h b/src/fsade.h index 9bef892..557da26 100644 --- a/src/fsade.h +++ b/src/fsade.h @@ -15,10 +15,10 @@ #define BFS_CAN_CHECK_ACL BFS_USE_SYS_ACL_H #if !defined(BFS_CAN_CHECK_CAPABILITIES) && BFS_USE_SYS_CAPABILITY_H && !__FreeBSD__ -# include -# ifdef CAP_CHOWN -# define BFS_CAN_CHECK_CAPABILITIES true -# endif +# include +# ifdef CAP_CHOWN +# define BFS_CAN_CHECK_CAPABILITIES true +# endif #endif #define BFS_CAN_CHECK_XATTRS (BFS_USE_SYS_EXTATTR_H || BFS_USE_SYS_XATTR_H) diff --git a/src/mtab.c b/src/mtab.c index 0e377a1..27f1743 100644 --- a/src/mtab.c +++ b/src/mtab.c @@ -15,23 +15,23 @@ #include #if BFS_USE_MNTENT_H -# define BFS_MNTENT 1 +# define BFS_MNTENT 1 #elif BSD -# define BFS_MNTINFO 1 +# define BFS_MNTINFO 1 #elif __SVR4 -# define BFS_MNTTAB 1 +# define BFS_MNTTAB 1 #endif #if BFS_MNTENT -# include -# include -# include +# include +# include +# include #elif BFS_MNTINFO -# include -# include +# include +# include #elif BFS_MNTTAB -# include -# include +# include +# include #endif /** diff --git a/src/printf.c b/src/printf.c index 1b4f2d4..726d54d 100644 --- a/src/printf.c +++ b/src/printf.c @@ -72,10 +72,10 @@ static bool should_color(CFILE *cfile, const struct bfs_printf *directive) { /** * Print a value to a temporary buffer before formatting it. */ -#define BFS_PRINTF_BUF(buf, format, ...) \ - char buf[256]; \ - int ret = snprintf(buf, sizeof(buf), format, __VA_ARGS__); \ - assert(ret >= 0 && (size_t)ret < sizeof(buf)); \ +#define BFS_PRINTF_BUF(buf, format, ...) \ + char buf[256]; \ + int ret = snprintf(buf, sizeof(buf), format, __VA_ARGS__); \ + assert(ret >= 0 && (size_t)ret < sizeof(buf)); \ (void)ret /** diff --git a/src/stat.c b/src/stat.c index aaa5eac..f3d9046 100644 --- a/src/stat.c +++ b/src/stat.c @@ -13,15 +13,15 @@ #include #if defined(STATX_BASIC_STATS) && (!__ANDROID__ || __ANDROID_API__ >= 30) -# define BFS_LIBC_STATX true +# define BFS_LIBC_STATX true #elif __linux__ -# include -# include -# include +# include +# include +# include #endif #if BFS_LIBC_STATX || defined(__NR_statx) -# define BFS_STATX true +# define BFS_STATX true #endif const char *bfs_stat_field_name(enum bfs_stat_field field) { diff --git a/src/stat.h b/src/stat.h index 7a70146..e08dd4d 100644 --- a/src/stat.h +++ b/src/stat.h @@ -17,7 +17,7 @@ #include #if BFS_USE_SYS_PARAM_H -# include +# include #endif /** @@ -61,11 +61,11 @@ enum bfs_stat_flags { }; #ifdef DEV_BSIZE -# define BFS_STAT_BLKSIZE DEV_BSIZE +# define BFS_STAT_BLKSIZE DEV_BSIZE #elif defined(S_BLKSIZE) -# define BFS_STAT_BLKSIZE S_BLKSIZE +# define BFS_STAT_BLKSIZE S_BLKSIZE #else -# define BFS_STAT_BLKSIZE 512 +# define BFS_STAT_BLKSIZE 512 #endif /** diff --git a/src/trie.c b/src/trie.c index 43df9dc..9f2e45f 100644 --- a/src/trie.c +++ b/src/trie.c @@ -94,9 +94,9 @@ static_assert(CHAR_BIT == 8, "This trie implementation assumes 8-bit bytes."); #if BFS_TARGET_CLONES && (__i386__ || __x86_64__) -# define TARGET_CLONES_POPCNT __attribute__((target_clones("popcnt", "default"))) +# define TARGET_CLONES_POPCNT __attribute__((target_clones("popcnt", "default"))) #else -# define TARGET_CLONES_POPCNT +# define TARGET_CLONES_POPCNT #endif /** Number of bits for the sparse array bitmap, aka the range of a nibble. */ @@ -367,23 +367,23 @@ static size_t trie_node_size(unsigned int size) { } #if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define TRIE_BSWAP(n) (n) +# define TRIE_BSWAP(n) (n) #elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -# if __SIZEOF_SIZE_T__ == 8 -# define TRIE_BSWAP(n) __builtin_bswap64(n) -# elif __SIZEOF_SIZE_T__ == 4 -# define TRIE_BSWAP(n) __builtin_bswap32(n) -# endif +# if __SIZEOF_SIZE_T__ == 8 +# define TRIE_BSWAP(n) __builtin_bswap64(n) +# elif __SIZEOF_SIZE_T__ == 4 +# define TRIE_BSWAP(n) __builtin_bswap32(n) +# endif #endif #ifdef TRIE_BSWAP -# if __SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__ -# define TRIE_CTZ(n) __builtin_ctzll(n) -# elif __SIZEOF_SIZE_T__ == __SIZEOF_LONG__ -# define TRIE_CTZ(n) __builtin_ctzl(n) -# elif __SIZEOF_SIZE_T__ == __SIZEOF_INT__ -# define TRIE_CTZ(n) __builtin_ctz(n) -# endif +# if __SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__ +# define TRIE_CTZ(n) __builtin_ctzll(n) +# elif __SIZEOF_SIZE_T__ == __SIZEOF_LONG__ +# define TRIE_CTZ(n) __builtin_ctzl(n) +# elif __SIZEOF_SIZE_T__ == __SIZEOF_INT__ +# define TRIE_CTZ(n) __builtin_ctz(n) +# endif #endif /** Find the offset of the first nibble that differs between two keys. */ diff --git a/src/xregex.c b/src/xregex.c index 5f5480f..a7153b7 100644 --- a/src/xregex.c +++ b/src/xregex.c @@ -9,10 +9,10 @@ #include #if BFS_WITH_ONIGURUMA -# include -# include +# include +# include #else -# include +# include #endif struct bfs_regex { @@ -43,20 +43,20 @@ static int bfs_onig_encoding(OnigEncoding *penc) { // from the current locale. const char *charmap = nl_langinfo(CODESET); if (charmap) { -#define BFS_MAP_ENCODING(name, value) \ - do { \ - if (strcmp(charmap, name) == 0) { \ - enc = value; \ - } \ +#define BFS_MAP_ENCODING(name, value) \ + do { \ + if (strcmp(charmap, name) == 0) { \ + enc = value; \ + } \ } while (0) -#define BFS_MAP_ENCODING2(name1, name2, value) \ - do { \ - BFS_MAP_ENCODING(name1, value); \ - BFS_MAP_ENCODING(name2, value); \ +#define BFS_MAP_ENCODING2(name1, name2, value) \ + do { \ + BFS_MAP_ENCODING(name1, value); \ + BFS_MAP_ENCODING(name2, value); \ } while (0) // These names were found with locale -m on Linux and FreeBSD -#define BFS_MAP_ISO_8859(n) \ +#define BFS_MAP_ISO_8859(n) \ BFS_MAP_ENCODING2("ISO-8859-" #n, "ISO8859-" #n, ONIG_ENCODING_ISO_8859_ ## n) BFS_MAP_ISO_8859(1); @@ -78,7 +78,7 @@ static int bfs_onig_encoding(OnigEncoding *penc) { BFS_MAP_ENCODING("UTF-8", ONIG_ENCODING_UTF8); -#define BFS_MAP_EUC(name) \ +#define BFS_MAP_EUC(name) \ BFS_MAP_ENCODING2("EUC-" #name, "euc" #name, ONIG_ENCODING_EUC_ ## name) BFS_MAP_EUC(JP); diff --git a/src/xspawn.c b/src/xspawn.c index a185200..a6d18a3 100644 --- a/src/xspawn.c +++ b/src/xspawn.c @@ -16,7 +16,7 @@ #include #if BFS_USE_PATHS_H -# include +# include #endif /** -- cgit v1.2.3 From 3f1822caed3dca731997c8739c19ee32e5caadc1 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 8 May 2023 14:18:37 -0400 Subject: config: Hoist the assignment outside of BFS_UNINIT() --- src/config.h | 4 ++-- src/parse.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index 5f54250..ed3f6ab 100644 --- a/src/config.h +++ b/src/config.h @@ -204,9 +204,9 @@ * Initialize a variable, unless sanitizers would detect uninitialized uses. */ #if __has_feature(memory_sanitizer) -# define BFS_UNINIT(var, value) var = var +# define BFS_UNINIT(var, value) var #else -# define BFS_UNINIT(var, value) var = value +# define BFS_UNINIT(var, value) value #endif #endif // BFS_CONFIG_H diff --git a/src/parse.c b/src/parse.c index 30bf56d..9540e83 100644 --- a/src/parse.c +++ b/src/parse.c @@ -1962,11 +1962,11 @@ static int parse_mode(const struct parser_state *state, const char *mode, struct MODE_PLUS, MODE_MINUS, MODE_EQUALS, - } BFS_UNINIT(op, MODE_EQUALS); + } op = BFS_UNINIT(op, MODE_EQUALS); - mode_t BFS_UNINIT(who, 0); - mode_t BFS_UNINIT(file_change, 0); - mode_t BFS_UNINIT(dir_change, 0); + mode_t who = BFS_UNINIT(who, 0); + mode_t file_change = BFS_UNINIT(file_change, 0); + mode_t dir_change = BFS_UNINIT(dir_change, 0); const char *i = mode; while (true) { -- cgit v1.2.3 From f3ecfc1ee49e1c3ddd3d19ca6166424d72a08a5c Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 10 May 2023 15:42:09 -0400 Subject: config: Group attribute wrappers together --- src/config.h | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index ed3f6ab..e17f90b 100644 --- a/src/config.h +++ b/src/config.h @@ -129,18 +129,7 @@ # define __GLIBC_PREREQ(maj, min) false #endif -// Wrappers for fundamental language features/extensions - -/** - * Silence compiler warnings about switch/case fall-throughs. - */ -#if __has_c_attribute(fallthrough) -# define BFS_FALLTHROUGH [[fallthrough]] -#elif __has_attribute(fallthrough) -# define BFS_FALLTHROUGH __attribute__((fallthrough)) -#else -# define BFS_FALLTHROUGH ((void)0) -#endif +// Fundamental utilities /** * Get the length of an array. @@ -169,6 +158,28 @@ ? BFS_FLEX_LB(type, member, length) \ : BFS_FLEX_MAX(sizeof(type), BFS_FLEX_LB(type, member, length))) +/** + * Initialize a variable, unless sanitizers would detect uninitialized uses. + */ +#if __has_feature(memory_sanitizer) +# define BFS_UNINIT(var, value) var +#else +# define BFS_UNINIT(var, value) value +#endif + +// Wrappers for attributes + +/** + * Silence compiler warnings about switch/case fall-throughs. + */ +#if __has_c_attribute(fallthrough) +# define BFS_FALLTHROUGH [[fallthrough]] +#elif __has_attribute(fallthrough) +# define BFS_FALLTHROUGH __attribute__((fallthrough)) +#else +# define BFS_FALLTHROUGH ((void)0) +#endif + /** * Adds compiler warnings for bad printf()-style function calls, if supported. */ @@ -200,13 +211,4 @@ # define BFS_UNSUPPRESS() #endif -/** - * Initialize a variable, unless sanitizers would detect uninitialized uses. - */ -#if __has_feature(memory_sanitizer) -# define BFS_UNINIT(var, value) var -#else -# define BFS_UNINIT(var, value) value -#endif - #endif // BFS_CONFIG_H -- cgit v1.2.3 From 8368e139c176dcde3b125f4a180ff868729b1862 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 10 May 2023 15:42:54 -0400 Subject: config: s/BFS_COUNTOF/countof/ --- src/config.h | 2 +- src/fsade.c | 2 +- src/opt.c | 16 ++++++++-------- tests/trie.c | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index e17f90b..60bc930 100644 --- a/src/config.h +++ b/src/config.h @@ -134,7 +134,7 @@ /** * Get the length of an array. */ -#define BFS_COUNTOF(array) (sizeof(array) / sizeof(0[array])) +#define countof(array) (sizeof(array) / sizeof(0[array])) // Lower bound on BFS_FLEX_SIZEOF() #define BFS_FLEX_LB(type, member, length) (offsetof(type, member) + sizeof(((type *)NULL)->member[0]) * (length)) diff --git a/src/fsade.c b/src/fsade.c index aefbb75..4d67940 100644 --- a/src/fsade.c +++ b/src/fsade.c @@ -201,7 +201,7 @@ int bfs_check_acl(const struct BFTW *ftwbuf) { const char *path = fake_at(ftwbuf); int ret = -1, error = 0; - for (size_t i = 0; i < BFS_COUNTOF(acl_types) && ret <= 0; ++i) { + for (size_t i = 0; i < countof(acl_types) && ret <= 0; ++i) { acl_type_t type = acl_types[i]; if (type == ACL_TYPE_DEFAULT && ftwbuf->type != BFS_DIR) { diff --git a/src/opt.c b/src/opt.c index 5505b7b..731dd10 100644 --- a/src/opt.c +++ b/src/opt.c @@ -1154,21 +1154,21 @@ static const struct { * Look up the appropriate optimizer for an expression and call it. */ static struct bfs_expr *optimize_expr_lookup(struct opt_state *state, struct bfs_expr *expr) { - for (size_t i = 0; i < BFS_COUNTOF(opt_pure); ++i) { + for (size_t i = 0; i < countof(opt_pure); ++i) { if (opt_pure[i] == expr->eval_fn) { expr->pure = true; break; } } - for (size_t i = 0; i < BFS_COUNTOF(opt_always_true); ++i) { + for (size_t i = 0; i < countof(opt_always_true); ++i) { if (opt_always_true[i] == expr->eval_fn) { expr->always_true = true; break; } } - for (size_t i = 0; i < BFS_COUNTOF(opt_always_false); ++i) { + for (size_t i = 0; i < countof(opt_always_false); ++i) { if (opt_always_false[i] == expr->eval_fn) { expr->always_false = true; break; @@ -1176,35 +1176,35 @@ static struct bfs_expr *optimize_expr_lookup(struct opt_state *state, struct bfs } expr->cost = FAST_COST; - for (size_t i = 0; i < BFS_COUNTOF(opt_costs); ++i) { + for (size_t i = 0; i < countof(opt_costs); ++i) { if (opt_costs[i].eval_fn == expr->eval_fn) { expr->cost = opt_costs[i].cost; break; } } - for (size_t i = 0; i < BFS_COUNTOF(opt_probs); ++i) { + for (size_t i = 0; i < countof(opt_probs); ++i) { if (opt_probs[i].eval_fn == expr->eval_fn) { expr->probability = opt_probs[i].probability; break; } } - for (size_t i = 0; i < BFS_COUNTOF(opt_preds); ++i) { + for (size_t i = 0; i < countof(opt_preds); ++i) { if (opt_preds[i].eval_fn == expr->eval_fn) { infer_pred_facts(state, opt_preds[i].pred); break; } } - for (size_t i = 0; i < BFS_COUNTOF(opt_ranges); ++i) { + for (size_t i = 0; i < countof(opt_ranges); ++i) { if (opt_ranges[i].eval_fn == expr->eval_fn) { infer_icmp_facts(state, expr, opt_ranges[i].range); break; } } - for (size_t i = 0; i < BFS_COUNTOF(opt_fns); ++i) { + for (size_t i = 0; i < countof(opt_fns); ++i) { if (opt_fns[i].eval_fn == expr->eval_fn) { return opt_fns[i].opt_fn(state, expr); } diff --git a/tests/trie.c b/tests/trie.c index c2af18a..ced14d4 100644 --- a/tests/trie.c +++ b/tests/trie.c @@ -38,7 +38,7 @@ const char *keys[] = { ">>>", }; -const size_t nkeys = BFS_COUNTOF(keys); +const size_t nkeys = countof(keys); int main(void) { struct trie trie; -- cgit v1.2.3 From 3929ddedca049ac6f9dcbe88f85233b6ec1a415a Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 10 May 2023 15:43:31 -0400 Subject: config: s/BFS_FLEX_SIZEOF/flex_sizeof/ --- src/bftw.c | 2 +- src/config.h | 4 ++-- src/dstring.c | 2 +- src/trie.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/config.h') diff --git a/src/bftw.c b/src/bftw.c index e4dc411..d2f1e36 100644 --- a/src/bftw.c +++ b/src/bftw.c @@ -178,7 +178,7 @@ static void bftw_cache_destroy(struct bftw_cache *cache) { /** Create a new bftw_file. */ static struct bftw_file *bftw_file_new(struct bftw_file *parent, const char *name) { size_t namelen = strlen(name); - size_t size = BFS_FLEX_SIZEOF(struct bftw_file, name, namelen + 1); + size_t size = flex_sizeof(struct bftw_file, name, namelen + 1); struct bftw_file *file = malloc(size); if (!file) { diff --git a/src/config.h b/src/config.h index 60bc930..aa54491 100644 --- a/src/config.h +++ b/src/config.h @@ -136,7 +136,7 @@ */ #define countof(array) (sizeof(array) / sizeof(0[array])) -// Lower bound on BFS_FLEX_SIZEOF() +// Lower bound on flex_sizeof() #define BFS_FLEX_LB(type, member, length) (offsetof(type, member) + sizeof(((type *)NULL)->member[0]) * (length)) // Maximum macro for BFS_FLEX_SIZE() @@ -153,7 +153,7 @@ * @param length * The length of the flexible array. */ -#define BFS_FLEX_SIZEOF(type, member, length) \ +#define flex_sizeof(type, member, length) \ (sizeof(type) <= BFS_FLEX_LB(type, member, 0) \ ? BFS_FLEX_LB(type, member, length) \ : BFS_FLEX_MAX(sizeof(type), BFS_FLEX_LB(type, member, length))) diff --git a/src/dstring.c b/src/dstring.c index 9112e54..05efb10 100644 --- a/src/dstring.c +++ b/src/dstring.c @@ -24,7 +24,7 @@ static struct dstring *dstrheader(const char *dstr) { /** Get the correct size for a dstring with the given capacity. */ static size_t dstrsize(size_t capacity) { - return BFS_FLEX_SIZEOF(struct dstring, data, capacity + 1); + return flex_sizeof(struct dstring, data, capacity + 1); } /** Allocate a dstring with the given contents. */ diff --git a/src/trie.c b/src/trie.c index 9f2e45f..bfe97e6 100644 --- a/src/trie.c +++ b/src/trie.c @@ -336,7 +336,7 @@ struct trie_leaf *trie_find_prefix(const struct trie *trie, const char *key) { /** Create a new leaf, holding a copy of the given key. */ static struct trie_leaf *trie_leaf_alloc(struct trie *trie, const void *key, size_t length) { - struct trie_leaf *leaf = malloc(BFS_FLEX_SIZEOF(struct trie_leaf, key, length)); + struct trie_leaf *leaf = malloc(flex_sizeof(struct trie_leaf, key, length)); if (!leaf) { return NULL; } @@ -363,7 +363,7 @@ static size_t trie_node_size(unsigned int size) { // Node size must be a power of two assert(is_power_of_two(size)); - return BFS_FLEX_SIZEOF(struct trie_node, children, size); + return flex_sizeof(struct trie_node, children, size); } #if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -- cgit v1.2.3 From 2d6d2f2cf838dc459bc1ef27476a26af5d82a53f Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 10 May 2023 15:43:57 -0400 Subject: config: s/BFS_UNINIT/uninit/ --- src/config.h | 4 ++-- src/parse.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index aa54491..b9f2638 100644 --- a/src/config.h +++ b/src/config.h @@ -162,9 +162,9 @@ * Initialize a variable, unless sanitizers would detect uninitialized uses. */ #if __has_feature(memory_sanitizer) -# define BFS_UNINIT(var, value) var +# define uninit(var, value) var #else -# define BFS_UNINIT(var, value) value +# define uninit(var, value) value #endif // Wrappers for attributes diff --git a/src/parse.c b/src/parse.c index 9540e83..7dd851a 100644 --- a/src/parse.c +++ b/src/parse.c @@ -1962,11 +1962,11 @@ static int parse_mode(const struct parser_state *state, const char *mode, struct MODE_PLUS, MODE_MINUS, MODE_EQUALS, - } op = BFS_UNINIT(op, MODE_EQUALS); + } op = uninit(op, MODE_EQUALS); - mode_t who = BFS_UNINIT(who, 0); - mode_t file_change = BFS_UNINIT(file_change, 0); - mode_t dir_change = BFS_UNINIT(dir_change, 0); + mode_t who = uninit(who, 0); + mode_t file_change = uninit(file_change, 0); + mode_t dir_change = uninit(dir_change, 0); const char *i = mode; while (true) { -- cgit v1.2.3 From 87d8d5928325f951f40b5f87292a17586b85943b Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 10 May 2023 15:44:59 -0400 Subject: config: s/BFS_FALLTHROUGH/fallthru/ --- src/bftw.c | 2 +- src/config.h | 6 +++--- src/eval.c | 4 ++-- src/parse.c | 18 +++++++++--------- src/printf.c | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src/config.h') diff --git a/src/bftw.c b/src/bftw.c index d2f1e36..56701a7 100644 --- a/src/bftw.c +++ b/src/bftw.c @@ -758,7 +758,7 @@ static enum bftw_action bftw_call_back(struct bftw_state *state, const char *nam if ((state->flags & BFTW_PRUNE_MOUNTS) && bftw_is_mount(state, name)) { return BFTW_PRUNE; } - BFS_FALLTHROUGH; + fallthru; case BFTW_PRUNE: case BFTW_STOP: return ret; diff --git a/src/config.h b/src/config.h index b9f2638..229bafb 100644 --- a/src/config.h +++ b/src/config.h @@ -173,11 +173,11 @@ * Silence compiler warnings about switch/case fall-throughs. */ #if __has_c_attribute(fallthrough) -# define BFS_FALLTHROUGH [[fallthrough]] +# define fallthru [[fallthrough]] #elif __has_attribute(fallthrough) -# define BFS_FALLTHROUGH __attribute__((fallthrough)) +# define fallthru __attribute__((fallthrough)) #else -# define BFS_FALLTHROUGH ((void)0) +# define fallthru ((void)0) #endif /** diff --git a/src/eval.c b/src/eval.c index 687ba32..7444ec9 100644 --- a/src/eval.c +++ b/src/eval.c @@ -241,10 +241,10 @@ bool eval_time(const struct bfs_expr *expr, struct bfs_eval *state) { switch (expr->time_unit) { case BFS_DAYS: diff /= 60*24; - BFS_FALLTHROUGH; + fallthru; case BFS_MINUTES: diff /= 60; - BFS_FALLTHROUGH; + fallthru; case BFS_SECONDS: break; } diff --git a/src/parse.c b/src/parse.c index 7dd851a..15f38a4 100644 --- a/src/parse.c +++ b/src/parse.c @@ -1082,16 +1082,16 @@ static struct bfs_expr *parse_time(struct parser_state *state, int field, int ar switch (*tail) { case 'w': time *= 7; - BFS_FALLTHROUGH; + fallthru; case 'd': time *= 24; - BFS_FALLTHROUGH; + fallthru; case 'h': time *= 60; - BFS_FALLTHROUGH; + fallthru; case 'm': time *= 60; - BFS_FALLTHROUGH; + fallthru; case 's': break; default: @@ -1974,7 +1974,7 @@ static int parse_mode(const struct parser_state *state, const char *mode, struct case MODE_CLAUSE: who = 0; mstate = MODE_WHO; - BFS_FALLTHROUGH; + fallthru; case MODE_WHO: switch (*i) { @@ -2001,7 +2001,7 @@ static int parse_mode(const struct parser_state *state, const char *mode, struct case MODE_EQUALS: expr->file_mode &= ~who; expr->dir_mode &= ~who; - BFS_FALLTHROUGH; + fallthru; case MODE_PLUS: expr->file_mode |= file_change; expr->dir_mode |= dir_change; @@ -2011,7 +2011,7 @@ static int parse_mode(const struct parser_state *state, const char *mode, struct expr->dir_mode &= ~dir_change; break; } - BFS_FALLTHROUGH; + fallthru; case MODE_ACTION: if (who == 0) { @@ -2093,7 +2093,7 @@ static int parse_mode(const struct parser_state *state, const char *mode, struct break; case 'x': file_change |= who & 0111; - BFS_FALLTHROUGH; + fallthru; case 'X': dir_change |= who & 0111; break; @@ -2156,7 +2156,7 @@ static struct bfs_expr *parse_perm(struct parser_state *state, int field, int ar ++mode; break; } - BFS_FALLTHROUGH; + fallthru; default: expr->mode_cmp = BFS_MODE_EQUAL; break; diff --git a/src/printf.c b/src/printf.c index 726d54d..454fbee 100644 --- a/src/printf.c +++ b/src/printf.c @@ -680,7 +680,7 @@ int bfs_printf_parse(const struct bfs_ctx *ctx, struct bfs_expr *expr, const cha case '0': case '+': must_be_numeric = true; - BFS_FALLTHROUGH; + fallthru; case ' ': case '-': if (strchr(directive.str, c)) { -- cgit v1.2.3 From 59f87eed2b930af2f31fd1d1fb2589f80f426ee0 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 11 May 2023 10:12:35 -0400 Subject: config: Provide and In anticipation of C23, since those headers won't be necessary any more. --- src/bfstd.c | 1 - src/bfstd.h | 2 +- src/bftw.c | 1 - src/color.c | 1 - src/color.h | 1 - src/config.h | 6 +++++- src/ctx.h | 2 +- src/diag.h | 1 - src/dir.c | 2 -- src/eval.h | 2 +- src/exec.c | 1 - src/expr.h | 2 +- src/fsade.h | 1 - src/main.c | 2 +- src/mtab.c | 1 - src/mtab.h | 2 +- src/opt.c | 1 - src/parse.c | 1 - src/printf.c | 1 - src/pwcache.c | 2 +- src/stat.c | 1 - src/trie.c | 1 - src/trie.h | 1 - src/xspawn.c | 1 - src/xtime.c | 2 +- tests/xtimegm.c | 2 +- tests/xtouch.c | 2 +- 27 files changed, 15 insertions(+), 28 deletions(-) (limited to 'src/config.h') diff --git a/src/bfstd.c b/src/bfstd.c index 1dc322b..932f2c4 100644 --- a/src/bfstd.c +++ b/src/bfstd.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include diff --git a/src/bfstd.h b/src/bfstd.h index 028e4e6..e4fd1f1 100644 --- a/src/bfstd.h +++ b/src/bfstd.h @@ -8,7 +8,7 @@ #ifndef BFS_BFSTD_H #define BFS_BFSTD_H -#include +#include "config.h" #include // #include diff --git a/src/bftw.c b/src/bftw.c index 56701a7..14805de 100644 --- a/src/bftw.c +++ b/src/bftw.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/src/color.c b/src/color.c index 589e631..eeadf98 100644 --- a/src/color.c +++ b/src/color.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/src/color.h b/src/color.h index 737c34b..3db2b07 100644 --- a/src/color.h +++ b/src/color.h @@ -10,7 +10,6 @@ #include "config.h" #include -#include #include /** diff --git a/src/config.h b/src/config.h index 229bafb..4408feb 100644 --- a/src/config.h +++ b/src/config.h @@ -8,9 +8,13 @@ #ifndef BFS_CONFIG_H #define BFS_CONFIG_H -#include #include +#if __STDC_VERSION__ < 202311L +# include +# include +#endif + // bfs packaging configuration #ifndef BFS_COMMAND diff --git a/src/ctx.h b/src/ctx.h index 4c748b7..0dc9f08 100644 --- a/src/ctx.h +++ b/src/ctx.h @@ -9,8 +9,8 @@ #define BFS_CTX_H #include "bftw.h" +#include "config.h" #include "trie.h" -#include #include #include #include diff --git a/src/diag.h b/src/diag.h index 2952e30..987d4b4 100644 --- a/src/diag.h +++ b/src/diag.h @@ -11,7 +11,6 @@ #include "ctx.h" #include "config.h" #include -#include struct bfs_expr; diff --git a/src/dir.c b/src/dir.c index eb6e3e0..30db5df 100644 --- a/src/dir.c +++ b/src/dir.c @@ -8,8 +8,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/src/eval.h b/src/eval.h index 3d70319..bdb9440 100644 --- a/src/eval.h +++ b/src/eval.h @@ -9,7 +9,7 @@ #ifndef BFS_EVAL_H #define BFS_EVAL_H -#include +#include "config.h" struct bfs_ctx; struct bfs_expr; diff --git a/src/exec.c b/src/exec.c index 6bde1c1..7f22d36 100644 --- a/src/exec.c +++ b/src/exec.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/src/expr.h b/src/expr.h index 1628cac..356689d 100644 --- a/src/expr.h +++ b/src/expr.h @@ -9,9 +9,9 @@ #define BFS_EXPR_H #include "color.h" +#include "config.h" #include "eval.h" #include "stat.h" -#include #include #include #include diff --git a/src/fsade.h b/src/fsade.h index 557da26..0d9ecaf 100644 --- a/src/fsade.h +++ b/src/fsade.h @@ -10,7 +10,6 @@ #define BFS_FSADE_H #include "config.h" -#include #define BFS_CAN_CHECK_ACL BFS_USE_SYS_ACL_H diff --git a/src/main.c b/src/main.c index 4f99580..24a5035 100644 --- a/src/main.c +++ b/src/main.c @@ -40,13 +40,13 @@ */ #include "bfstd.h" +#include "config.h" #include "ctx.h" #include "eval.h" #include "parse.h" #include #include #include -#include #include #include #include diff --git a/src/mtab.c b/src/mtab.c index 27f1743..1d1ad94 100644 --- a/src/mtab.c +++ b/src/mtab.c @@ -9,7 +9,6 @@ #include "trie.h" #include #include -#include #include #include #include diff --git a/src/mtab.h b/src/mtab.h index 5dfdf6c..ca4372c 100644 --- a/src/mtab.h +++ b/src/mtab.h @@ -8,7 +8,7 @@ #ifndef BFS_MTAB_H #define BFS_MTAB_H -#include +#include "config.h" struct bfs_stat; diff --git a/src/opt.c b/src/opt.c index 731dd10..4ce9425 100644 --- a/src/opt.c +++ b/src/opt.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include diff --git a/src/parse.c b/src/parse.c index 15f38a4..55f1e74 100644 --- a/src/parse.c +++ b/src/parse.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/src/printf.c b/src/printf.c index 454fbee..9ccc216 100644 --- a/src/printf.c +++ b/src/printf.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/src/pwcache.c b/src/pwcache.c index 5026dee..f52e4e1 100644 --- a/src/pwcache.c +++ b/src/pwcache.c @@ -2,12 +2,12 @@ // SPDX-License-Identifier: 0BSD #include "pwcache.h" +#include "config.h" #include "darray.h" #include "trie.h" #include #include #include -#include #include #include #include diff --git a/src/stat.c b/src/stat.c index f3d9046..7973d71 100644 --- a/src/stat.c +++ b/src/stat.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include diff --git a/src/trie.c b/src/trie.c index bfe97e6..e0e00ff 100644 --- a/src/trie.c +++ b/src/trie.c @@ -86,7 +86,6 @@ #include "list.h" #include #include -#include #include #include #include diff --git a/src/trie.h b/src/trie.h index 58974aa..6bd211e 100644 --- a/src/trie.h +++ b/src/trie.h @@ -5,7 +5,6 @@ #define BFS_TRIE_H #include "config.h" -#include #include #include diff --git a/src/xspawn.c b/src/xspawn.c index a6d18a3..00fb76e 100644 --- a/src/xspawn.c +++ b/src/xspawn.c @@ -7,7 +7,6 @@ #include "list.h" #include #include -#include #include #include #include diff --git a/src/xtime.c b/src/xtime.c index 82690d0..406d694 100644 --- a/src/xtime.c +++ b/src/xtime.c @@ -2,9 +2,9 @@ // SPDX-License-Identifier: 0BSD #include "xtime.h" +#include "config.h" #include #include -#include #include #include #include diff --git a/tests/xtimegm.c b/tests/xtimegm.c index bab64ba..b2479b7 100644 --- a/tests/xtimegm.c +++ b/tests/xtimegm.c @@ -2,7 +2,7 @@ // SPDX-License-Identifier: 0BSD #include "../src/xtime.h" -#include +#include "../src/config.h" #include #include #include diff --git a/tests/xtouch.c b/tests/xtouch.c index 7e29547..50416ba 100644 --- a/tests/xtouch.c +++ b/tests/xtouch.c @@ -2,10 +2,10 @@ // SPDX-License-Identifier: 0BSD #include "../src/bfstd.h" +#include "../src/config.h" #include "../src/xtime.h" #include #include -#include #include #include #include -- cgit v1.2.3 From 7e26443627926bb3bcc88bd790190d5e4e0eda98 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 11 May 2023 10:38:23 -0400 Subject: config: Properly align flex_sizeof() --- src/config.h | 31 +++++++++++++++++++++---------- tests/bfstd.c | 13 +++++++++++++ 2 files changed, 34 insertions(+), 10 deletions(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index 4408feb..c6dcc1e 100644 --- a/src/config.h +++ b/src/config.h @@ -140,11 +140,12 @@ */ #define countof(array) (sizeof(array) / sizeof(0[array])) -// Lower bound on flex_sizeof() -#define BFS_FLEX_LB(type, member, length) (offsetof(type, member) + sizeof(((type *)NULL)->member[0]) * (length)) - -// Maximum macro for BFS_FLEX_SIZE() -#define BFS_FLEX_MAX(a, b) ((a) > (b) ? (a) : (b)) +/** + * Round up to a multiple of an alignment. + */ +static inline size_t align_ceil(size_t align, size_t size) { + return (size + align - 1) & ~(align - 1); +} /** * Computes the size of a struct containing a flexible array member of the given @@ -154,13 +155,23 @@ * The type of the struct containing the flexible array. * @param member * The name of the flexible array member. - * @param length + * @param count * The length of the flexible array. */ -#define flex_sizeof(type, member, length) \ - (sizeof(type) <= BFS_FLEX_LB(type, member, 0) \ - ? BFS_FLEX_LB(type, member, length) \ - : BFS_FLEX_MAX(sizeof(type), BFS_FLEX_LB(type, member, length))) +#define flex_sizeof(type, member, count) \ + flex_sizeof_impl(alignof(type), sizeof(type), offsetof(type, member), sizeof(((type *)NULL)->member[0]), count) + +static inline size_t flex_sizeof_impl(size_t align, size_t min, size_t offset, size_t size, size_t count) { + size_t ret = align_ceil(align, offset + size * count); + + // Make sure flex_sizeof(type, member, 0) >= sizeof(type), even if the + // type has more padding than necessary for alignment + if (min > align_ceil(align, offset) && ret < min) { + ret = min; + } + + return ret; +} /** * Initialize a variable, unless sanitizers would detect uninitialized uses. diff --git a/tests/bfstd.c b/tests/bfstd.c index 8c61072..c6a9e9f 100644 --- a/tests/bfstd.c +++ b/tests/bfstd.c @@ -1,8 +1,12 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#undef NDEBUG #include "../src/bfstd.h" +#include "../src/config.h" +#include #include +#include #include #include @@ -30,6 +34,15 @@ static void check_base_dir(const char *path, const char *dir, const char *base) } int main(void) { + // Check flex_sizeof() + struct flexible { + alignas(64) int foo; + int bar[]; + }; + assert(flex_sizeof(struct flexible, bar, 0) >= sizeof(struct flexible)); + assert(flex_sizeof(struct flexible, bar, 16) % alignof(struct flexible) == 0); + assert(flex_sizeof_impl(8, 16, 4, 4, 1) == 16); + // From man 3p basename check_base_dir("usr", ".", "usr"); check_base_dir("usr/", ".", "usr"); -- cgit v1.2.3 From a7932050f65844fb1f1145fee87c72aadaf4f995 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 11 May 2023 13:08:43 -0400 Subject: config: Saturate on overflow in flex_sizeof() --- src/config.h | 12 +++++++++++- tests/bfstd.c | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index c6dcc1e..b2c58be 100644 --- a/src/config.h +++ b/src/config.h @@ -162,7 +162,17 @@ static inline size_t align_ceil(size_t align, size_t size) { flex_sizeof_impl(alignof(type), sizeof(type), offsetof(type, member), sizeof(((type *)NULL)->member[0]), count) static inline size_t flex_sizeof_impl(size_t align, size_t min, size_t offset, size_t size, size_t count) { - size_t ret = align_ceil(align, offset + size * count); + size_t ret = size * count; + size_t overflow = ret / size != count; + + ret += offset; + overflow |= ret < offset; + + size_t mask = align - 1; + ret += mask; + overflow |= ret < mask; + ret &= ~mask; + ret |= -overflow; // Make sure flex_sizeof(type, member, 0) >= sizeof(type), even if the // type has more padding than necessary for alignment diff --git a/tests/bfstd.c b/tests/bfstd.c index c6a9e9f..1917a53 100644 --- a/tests/bfstd.c +++ b/tests/bfstd.c @@ -41,6 +41,7 @@ int main(void) { }; assert(flex_sizeof(struct flexible, bar, 0) >= sizeof(struct flexible)); assert(flex_sizeof(struct flexible, bar, 16) % alignof(struct flexible) == 0); + assert(flex_sizeof(struct flexible, bar, SIZE_MAX / sizeof(int) + 1) == SIZE_MAX); assert(flex_sizeof_impl(8, 16, 4, 4, 1) == 16); // From man 3p basename -- cgit v1.2.3 From 8706515d905038ee7d869ab5ace0471c781d2624 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 16 May 2023 11:37:53 -0400 Subject: config: Align after saturating in flex_sizeof() This ensures that it's legal to call aligned_alloc() with the result, which requires a multiple of the alignment. --- src/config.h | 11 +++++++++-- tests/bfstd.c | 3 ++- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index b2c58be..47aa529 100644 --- a/src/config.h +++ b/src/config.h @@ -140,11 +140,18 @@ */ #define countof(array) (sizeof(array) / sizeof(0[array])) +/** + * Round down to a multiple of an alignment. + */ +static inline size_t align_floor(size_t align, size_t size) { + return size & ~(align - 1); +} + /** * Round up to a multiple of an alignment. */ static inline size_t align_ceil(size_t align, size_t size) { - return (size + align - 1) & ~(align - 1); + return align_floor(align, size + align - 1); } /** @@ -171,8 +178,8 @@ static inline size_t flex_sizeof_impl(size_t align, size_t min, size_t offset, s size_t mask = align - 1; ret += mask; overflow |= ret < mask; - ret &= ~mask; ret |= -overflow; + ret &= ~mask; // Make sure flex_sizeof(type, member, 0) >= sizeof(type), even if the // type has more padding than necessary for alignment diff --git a/tests/bfstd.c b/tests/bfstd.c index 1917a53..a986a23 100644 --- a/tests/bfstd.c +++ b/tests/bfstd.c @@ -41,7 +41,8 @@ int main(void) { }; assert(flex_sizeof(struct flexible, bar, 0) >= sizeof(struct flexible)); assert(flex_sizeof(struct flexible, bar, 16) % alignof(struct flexible) == 0); - assert(flex_sizeof(struct flexible, bar, SIZE_MAX / sizeof(int) + 1) == SIZE_MAX); + assert(flex_sizeof(struct flexible, bar, SIZE_MAX / sizeof(int) + 1) + == align_floor(alignof(struct flexible), SIZE_MAX)); assert(flex_sizeof_impl(8, 16, 4, 4, 1) == 16); // From man 3p basename -- cgit v1.2.3 From 873e6bf836b2dd2d7dedc905c0386b7cd66c0d85 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 18 May 2023 11:50:38 -0400 Subject: config: Include --- src/config.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index 47aa529..f06300e 100644 --- a/src/config.h +++ b/src/config.h @@ -13,6 +13,7 @@ #if __STDC_VERSION__ < 202311L # include # include +# include #endif // bfs packaging configuration -- cgit v1.2.3 From 24a67ef8265e5873c0967ded296a9e57ed9f2914 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 25 May 2023 14:19:21 -0400 Subject: sanity: Add wrappers for sanitizer interfaces --- src/config.h | 9 ------ src/dir.c | 12 ++------ src/fsade.c | 9 +++--- src/parse.c | 1 + src/sanity.h | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/stat.c | 18 ++++++------ src/xregex.c | 8 ++---- 7 files changed, 110 insertions(+), 36 deletions(-) create mode 100644 src/sanity.h (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index f06300e..dbe3c74 100644 --- a/src/config.h +++ b/src/config.h @@ -191,15 +191,6 @@ static inline size_t flex_sizeof_impl(size_t align, size_t min, size_t offset, s return ret; } -/** - * Initialize a variable, unless sanitizers would detect uninitialized uses. - */ -#if __has_feature(memory_sanitizer) -# define uninit(var, value) var -#else -# define uninit(var, value) value -#endif - // Wrappers for attributes /** diff --git a/src/dir.c b/src/dir.c index d9ee63b..01d26db 100644 --- a/src/dir.c +++ b/src/dir.c @@ -5,6 +5,7 @@ #include "bfstd.h" #include "config.h" #include "diag.h" +#include "sanity.h" #include #include #include @@ -18,18 +19,13 @@ #endif #if BFS_GETDENTS -# if __has_feature(memory_sanitizer) -# include -# endif # if __linux__ # include # endif /** getdents() syscall wrapper. */ static ssize_t bfs_getdents(int fd, void *buf, size_t size) { -#if __has_feature(memory_sanitizer) - __msan_allocated_memory(buf, size); -#endif + sanitize_uninit(buf, size); #if __linux__ && __GLIBC__ && !__GLIBC_PREREQ(2, 30) ssize_t ret = syscall(SYS_getdents64, fd, buf, size); @@ -39,11 +35,9 @@ static ssize_t bfs_getdents(int fd, void *buf, size_t size) { ssize_t ret = getdents(fd, buf, size); #endif -#if __has_feature(memory_sanitizer) if (ret > 0) { - __msan_unpoison(buf, ret); + sanitize_init(buf, ret); } -#endif return ret; } diff --git a/src/fsade.c b/src/fsade.c index 4d67940..ba89b60 100644 --- a/src/fsade.c +++ b/src/fsade.c @@ -159,13 +159,12 @@ static int bfs_check_acl_type(acl_t acl, acl_type_t type) { #if __FreeBSD__ int trivial; + int ret = acl_is_trivial_np(acl, &trivial); -#if __has_feature(memory_sanitizer) - // msan seems to be missing an interceptor for acl_is_trivial_np() - trivial = 0; -#endif + // msan seems to be missing an interceptor for acl_is_trivial_np() + sanitize_init(&trivial); - if (acl_is_trivial_np(acl, &trivial) < 0) { + if (ret < 0) { return -1; } else if (trivial) { return 0; diff --git a/src/parse.c b/src/parse.c index 1a04e68..59a1e7d 100644 --- a/src/parse.c +++ b/src/parse.c @@ -24,6 +24,7 @@ #include "opt.h" #include "printf.h" #include "pwcache.h" +#include "sanity.h" #include "stat.h" #include "typo.h" #include "xregex.h" diff --git a/src/sanity.h b/src/sanity.h new file mode 100644 index 0000000..5696036 --- /dev/null +++ b/src/sanity.h @@ -0,0 +1,89 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +/** + * Sanitizer interface. + */ + +#ifndef BFS_SANITY_H +#define BFS_SANITY_H + +#include "config.h" +#include + +#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) +# define SANITIZE_ADDRESS true +#endif + +#if __has_feature(memory_sanitizer) || defined(__SANITIZE_MEMORY__) +# define SANITIZE_MEMORY true +#endif + +#if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__) +# define SANITIZE_THREAD true +#endif + +// Call macro(ptr, size) or macro(ptr, sizeof(*ptr)) +#define SANITIZE_CALL(...) \ + SANITIZE_CALL_(__VA_ARGS__, ) + +#define SANITIZE_CALL_(macro, ptr, ...) \ + SANITIZE_CALL__(macro, ptr, __VA_ARGS__ sizeof(*(ptr)), ) + +#define SANITIZE_CALL__(macro, ptr, size, ...) \ + macro(ptr, size) + +#if SANITIZE_ADDRESS +# include + +/** + * sanitize_alloc(ptr, size = sizeof(*ptr)) + * + * Mark a memory region as allocated. + */ +#define sanitize_alloc(...) SANITIZE_CALL(__asan_unpoison_memory_region, __VA_ARGS__) + +/** + * sanitize_free(ptr, size = sizeof(*ptr)) + * + * Mark a memory region as free. + */ +#define sanitize_free(...) SANITIZE_CALL(__asan_poison_memory_region, __VA_ARGS__) + +#else +# define sanitize_alloc sanitize_uninit +# define sanitize_free sanitize_uninit +#endif + +#if SANITIZE_MEMORY +# include + +/** + * sanitize_init(ptr, size = sizeof(*ptr)) + * + * Mark a memory region as initialized. + */ +#define sanitize_init(...) SANITIZE_CALL(__msan_unpoison, __VA_ARGS__) + +/** + * sanitize_uninit(ptr, size = sizeof(*ptr)) + * + * Mark a memory region as uninitialized. + */ +#define sanitize_uninit(...) SANITIZE_CALL(__msan_allocated_memory, __VA_ARGS__) + +#else +# define sanitize_init(...) +# define sanitize_uninit(...) +#endif + +/** + * Initialize a variable, unless sanitizers would detect uninitialized uses. + */ +#if SANITIZE_MEMORY +# define uninit(var, value) var +#else +# define uninit(var, value) value +#endif + +#endif // BFS_SANITY_H diff --git a/src/stat.c b/src/stat.c index 590a1d6..3f70e6c 100644 --- a/src/stat.c +++ b/src/stat.c @@ -5,6 +5,7 @@ #include "bfstd.h" #include "config.h" #include "diag.h" +#include "sanity.h" #include #include #include @@ -132,17 +133,18 @@ static int bfs_stat_impl(int at_fd, const char *at_path, int at_flags, struct bf * Wrapper for the statx() system call, which had no glibc wrapper prior to 2.28. */ static int bfs_statx(int at_fd, const char *at_path, int at_flags, unsigned int mask, struct statx *buf) { -#if __has_feature(memory_sanitizer) - // -fsanitize=memory doesn't know about statx(), so tell it the memory - // got initialized - memset(buf, 0, sizeof(*buf)); -#endif - #if BFS_LIBC_STATX - return statx(at_fd, at_path, at_flags, mask, buf); + int ret = statx(at_fd, at_path, at_flags, mask, buf); #else - return syscall(SYS_statx, at_fd, at_path, at_flags, mask, buf); + int ret = syscall(SYS_statx, at_fd, at_path, at_flags, mask, buf); #endif + + if (ret == 0) { + // -fsanitize=memory doesn't know about statx() + sanitize_init(buf); + } + + return ret; } /** diff --git a/src/xregex.c b/src/xregex.c index 1143f23..ce59ff5 100644 --- a/src/xregex.c +++ b/src/xregex.c @@ -4,6 +4,7 @@ #include "xregex.h" #include "config.h" #include "diag.h" +#include "sanity.h" #include #include #include @@ -175,13 +176,10 @@ int bfs_regcomp(struct bfs_regex **preg, const char *pattern, enum bfs_regex_typ cflags |= REG_ICASE; } -#if __has_feature(memory_sanitizer) - // https://github.com/google/sanitizers/issues/1496 - memset(®ex->impl, 0, sizeof(regex->impl)); -#endif - regex->err = regcomp(®ex->impl, pattern, cflags); if (regex->err != 0) { + // https://github.com/google/sanitizers/issues/1496 + sanitize_init(®ex->impl); return -1; } #endif -- cgit v1.2.3 From 29719ace5192ff5c2d81c29d1947e32d7889f62b Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 14 Jun 2023 10:35:24 -0400 Subject: config: Add macros for false/true sharing sizes --- src/config.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index dbe3c74..73348ac 100644 --- a/src/config.h +++ b/src/config.h @@ -191,6 +191,29 @@ static inline size_t flex_sizeof_impl(size_t align, size_t min, size_t offset, s return ret; } +/** + * False sharing/destructive interference/largest cache line size. + */ +#ifdef __GCC_DESTRUCTIVE_SIZE +# define FALSE_SHARING_SIZE __GCC_DESTRUCTIVE_SIZE +#else +# define FALSE_SHARING_SIZE 64 +#endif + +/** + * True sharing/constructive interference/smallest cache line size. + */ +#ifdef __GCC_CONSTRUCTIVE_SIZE +# define TRUE_SHARING_SIZE __GCC_CONSTRUCTIVE_SIZE +#else +# define TRUE_SHARING_SIZE 64 +#endif + +/** + * Alignment specifier that avoids false sharing. + */ +#define cache_align alignas(FALSE_SHARING_SIZE) + // Wrappers for attributes /** -- cgit v1.2.3 From 90ded13e589b0089167ef25ca3d26be599dfec9b Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 19 Jun 2023 12:11:36 -0400 Subject: alloc: New header for memory allocation utilities --- Makefile | 3 +- src/alloc.c | 50 ++++++++++++++++++++ src/alloc.h | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/bfstd.c | 13 ----- src/bfstd.h | 12 ----- src/bftw.c | 5 +- src/color.c | 5 +- src/config.h | 50 -------------------- src/ctx.c | 31 ++---------- src/dstring.c | 3 +- src/exec.c | 26 ++++------ src/ioq.c | 26 ++++------ src/ioq.h | 4 +- src/main.c | 1 + src/mtab.c | 5 +- src/parse.c | 28 ++--------- src/pwcache.c | 5 +- src/trie.c | 7 ++- src/xregex.c | 3 +- src/xspawn.c | 3 +- tests/alloc.c | 24 ++++++++++ tests/bfstd.c | 13 +---- 22 files changed, 271 insertions(+), 195 deletions(-) create mode 100644 src/alloc.c create mode 100644 src/alloc.h create mode 100644 tests/alloc.c (limited to 'src/config.h') diff --git a/Makefile b/Makefile index fb28e29..d38f581 100644 --- a/Makefile +++ b/Makefile @@ -217,6 +217,7 @@ $(OBJ)/FLAGS: $(OBJ)/FLAGS.new # All object files except the entry point LIBBFS := \ + $(OBJ)/src/alloc.o \ $(OBJ)/src/bar.o \ $(OBJ)/src/bfstd.o \ $(OBJ)/src/bftw.o \ @@ -246,7 +247,7 @@ LIBBFS := \ $(BIN)/bfs: $(OBJ)/src/main.o $(LIBBFS) # Standalone unit tests -UNITS := bfstd bit trie xtimegm +UNITS := alloc bfstd bit trie xtimegm UNIT_TESTS := $(UNITS:%=$(BIN)/tests/%) UNIT_CHECKS := $(UNITS:%=check-%) diff --git a/src/alloc.c b/src/alloc.c new file mode 100644 index 0000000..0003108 --- /dev/null +++ b/src/alloc.c @@ -0,0 +1,50 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include "alloc.h" +#include "bit.h" +#include "diag.h" +#include +#include +#include + +/** Portable aligned_alloc()/posix_memalign(). */ +static void *xmemalign(size_t align, size_t size) { + bfs_assert(has_single_bit(align)); + bfs_assert(align >= sizeof(void *)); + bfs_assert((size & (align - 1)) == 0); + +#if __APPLE__ + void *ptr = NULL; + errno = posix_memalign(&ptr, align, size); + return ptr; +#else + return aligned_alloc(align, size); +#endif +} + +void *alloc(size_t align, size_t size) { + bfs_assert(has_single_bit(align)); + bfs_assert((size & (align - 1)) == 0); + + if (align <= alignof(max_align_t)) { + return malloc(size); + } else { + return xmemalign(align, size); + } +} + +void *zalloc(size_t align, size_t size) { + bfs_assert(has_single_bit(align)); + bfs_assert((size & (align - 1)) == 0); + + if (align <= alignof(max_align_t)) { + return calloc(1, size); + } + + void *ret = xmemalign(align, size); + if (ret) { + memset(ret, 0, size); + } + return ret; +} diff --git a/src/alloc.h b/src/alloc.h new file mode 100644 index 0000000..899a4ec --- /dev/null +++ b/src/alloc.h @@ -0,0 +1,149 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +/** + * Memory allocation. + */ + +#ifndef BFS_ALLOC_H +#define BFS_ALLOC_H + +#include "config.h" +#include + +/** Round down to a multiple of an alignment. */ +static inline size_t align_floor(size_t align, size_t size) { + return size & ~(align - 1); +} + +/** Round up to a multiple of an alignment. */ +static inline size_t align_ceil(size_t align, size_t size) { + return align_floor(align, size + align - 1); +} + +/** + * Saturating array size. + * + * @param align + * Array element alignment. + * @param size + * Array element size. + * @param count + * Array element count. + * @return + * size * count, saturating to the maximum aligned value on overflow. + */ +static inline size_t array_size(size_t align, size_t size, size_t count) { + size_t ret = size * count; + return ret / size == count ? ret : ~(align - 1); +} + +/** Saturating array sizeof. */ +#define sizeof_array(type, count) \ + array_size(alignof(type), sizeof(type), count) + +/** Size of a struct/union field. */ +#define sizeof_member(type, member) \ + sizeof(((type *)NULL)->member) + +/** + * Saturating flexible struct size. + * + * @param align + * Struct alignment. + * @param min + * Minimum struct size. + * @param offset + * Flexible array member offset. + * @param size + * Flexible array element size. + * @param count + * Flexible array element count. + * @return + * The size of the struct with count flexible array elements. Saturates + * to the maximum aligned value on overflow. + */ +static inline size_t flex_size(size_t align, size_t min, size_t offset, size_t size, size_t count) { + size_t ret = size * count; + size_t overflow = ret / size != count; + + size_t extra = offset + align - 1; + ret += extra; + overflow |= ret < extra; + ret |= -overflow; + ret = align_floor(align, ret); + + // Make sure flex_sizeof(type, member, 0) >= sizeof(type), even if the + // type has more padding than necessary for alignment + if (min > align_ceil(align, offset)) { + ret = ret < min ? min : ret; + } + + return ret; +} + +/** + * Computes the size of a flexible struct. + * + * @param type + * The type of the struct containing the flexible array. + * @param member + * The name of the flexible array member. + * @param count + * The length of the flexible array. + * @return + * The size of the struct with count flexible array elements. Saturates + * to the maximum aligned value on overflow. + */ +#define sizeof_flex(type, member, count) \ + flex_size(alignof(type), sizeof(type), offsetof(type, member), sizeof_member(type, member[0]), count) + +/** + * General memory allocator. + * + * @param align + * The required alignment. + * @param size + * The size of the allocation. + * @return + * The allocated memory, or NULL on failure. + */ +void *alloc(size_t align, size_t size); + +/** + * Zero-initialized memory allocator. + * + * @param align + * The required alignment. + * @param size + * The size of the allocation. + * @return + * The allocated memory, or NULL on failure. + */ +void *zalloc(size_t align, size_t size); + +/** Allocate memory for the given type. */ +#define ALLOC(type) \ + (type *)alloc(alignof(type), sizeof(type)) + +/** Allocate zeroed memory for the given type. */ +#define ZALLOC(type) \ + (type *)zalloc(alignof(type), sizeof(type)) + +/** Allocate memory for an array. */ +#define ALLOC_ARRAY(type, count) \ + (type *)alloc(alignof(type), sizeof_array(type, count)); + +/** Allocate zeroed memory for an array. */ +#define ZALLOC_ARRAY(type, count) \ + (type *)zalloc(alignof(type), sizeof_array(type, count)); + +/** Allocate memory for a flexible struct. */ +#define ALLOC_FLEX(type, member, count) \ + (type *)alloc(alignof(type), sizeof_flex(type, member, count)) + +/** Allocate zeroed memory for a flexible struct. */ +#define ZALLOC_FLEX(type, member, count) \ + (type *)zalloc(alignof(type), sizeof_flex(type, member, count)) + +#endif // BFS_ALLOC_H diff --git a/src/bfstd.c b/src/bfstd.c index 856c76c..0e8ba5f 100644 --- a/src/bfstd.c +++ b/src/bfstd.c @@ -143,19 +143,6 @@ char *xgetdelim(FILE *file, char delim) { } } -void *xmemalign(size_t align, size_t size) { - bfs_assert(has_single_bit(align)); - bfs_assert((size & (align - 1)) == 0); - -#if __APPLE__ - void *ptr = NULL; - errno = posix_memalign(&ptr, align, size); - return ptr; -#else - return aligned_alloc(align, size); -#endif -} - /** Compile and execute a regular expression for xrpmatch(). */ static int xrpregex(nl_item item, const char *response) { const char *pattern = nl_langinfo(item); diff --git a/src/bfstd.h b/src/bfstd.h index 6f2e21e..cafe28f 100644 --- a/src/bfstd.h +++ b/src/bfstd.h @@ -105,18 +105,6 @@ char *xgetdelim(FILE *file, char delim); // #include -/** - * Portable version of aligned_alloc()/posix_memalign(). - * - * @param align - * The allocation's alignment. - * @param size - * The allocation's size. - * @return - * The allocation, or NULL on failure. - */ -void *xmemalign(size_t align, size_t size); - /** * Process a yes/no prompt. * diff --git a/src/bftw.c b/src/bftw.c index e711963..7ab14c7 100644 --- a/src/bftw.c +++ b/src/bftw.c @@ -17,6 +17,7 @@ */ #include "bftw.h" +#include "alloc.h" #include "bfstd.h" #include "config.h" #include "diag.h" @@ -241,9 +242,7 @@ static void bftw_cache_destroy(struct bftw_cache *cache) { /** Create a new bftw_file. */ static struct bftw_file *bftw_file_new(struct bftw_file *parent, const char *name) { size_t namelen = strlen(name); - size_t size = flex_sizeof(struct bftw_file, name, namelen + 1); - - struct bftw_file *file = malloc(size); + struct bftw_file *file = ALLOC_FLEX(struct bftw_file, name, namelen + 1); if (!file) { return NULL; } diff --git a/src/color.c b/src/color.c index 1edd8b5..b54ad53 100644 --- a/src/color.c +++ b/src/color.c @@ -2,6 +2,7 @@ // SPDX-License-Identifier: 0BSD #include "color.h" +#include "alloc.h" #include "bfstd.h" #include "bftw.h" #include "config.h" @@ -404,7 +405,7 @@ static void parse_gnu_ls_colors(struct colors *colors, const char *ls_colors) { } struct colors *parse_colors(void) { - struct colors *colors = malloc(sizeof(struct colors)); + struct colors *colors = ALLOC(struct colors); if (!colors) { return NULL; } @@ -497,7 +498,7 @@ void free_colors(struct colors *colors) { } CFILE *cfwrap(FILE *file, const struct colors *colors, bool close) { - CFILE *cfile = malloc(sizeof(*cfile)); + CFILE *cfile = ALLOC(CFILE); if (!cfile) { return NULL; } diff --git a/src/config.h b/src/config.h index 73348ac..1671a0d 100644 --- a/src/config.h +++ b/src/config.h @@ -141,56 +141,6 @@ */ #define countof(array) (sizeof(array) / sizeof(0[array])) -/** - * Round down to a multiple of an alignment. - */ -static inline size_t align_floor(size_t align, size_t size) { - return size & ~(align - 1); -} - -/** - * Round up to a multiple of an alignment. - */ -static inline size_t align_ceil(size_t align, size_t size) { - return align_floor(align, size + align - 1); -} - -/** - * Computes the size of a struct containing a flexible array member of the given - * length. - * - * @param type - * The type of the struct containing the flexible array. - * @param member - * The name of the flexible array member. - * @param count - * The length of the flexible array. - */ -#define flex_sizeof(type, member, count) \ - flex_sizeof_impl(alignof(type), sizeof(type), offsetof(type, member), sizeof(((type *)NULL)->member[0]), count) - -static inline size_t flex_sizeof_impl(size_t align, size_t min, size_t offset, size_t size, size_t count) { - size_t ret = size * count; - size_t overflow = ret / size != count; - - ret += offset; - overflow |= ret < offset; - - size_t mask = align - 1; - ret += mask; - overflow |= ret < mask; - ret |= -overflow; - ret &= ~mask; - - // Make sure flex_sizeof(type, member, 0) >= sizeof(type), even if the - // type has more padding than necessary for alignment - if (min > align_ceil(align, offset) && ret < min) { - ret = min; - } - - return ret; -} - /** * False sharing/destructive interference/largest cache line size. */ diff --git a/src/ctx.c b/src/ctx.c index e8ce0e8..a940bed 100644 --- a/src/ctx.c +++ b/src/ctx.c @@ -2,6 +2,7 @@ // SPDX-License-Identifier: 0BSD #include "ctx.h" +#include "alloc.h" #include "color.h" #include "darray.h" #include "diag.h" @@ -42,43 +43,17 @@ const char *debug_flag_name(enum debug_flags flag) { } struct bfs_ctx *bfs_ctx_new(void) { - struct bfs_ctx *ctx = malloc(sizeof(*ctx)); + struct bfs_ctx *ctx = ZALLOC(struct bfs_ctx); if (!ctx) { return NULL; } - ctx->argv = NULL; - ctx->paths = NULL; - ctx->expr = NULL; - ctx->exclude = NULL; - - ctx->mindepth = 0; ctx->maxdepth = INT_MAX; ctx->flags = BFTW_RECOVER; ctx->strategy = BFTW_BFS; - ctx->threads = 0; ctx->optlevel = 3; - ctx->debug = 0; - ctx->ignore_races = false; - ctx->posixly_correct = false; - ctx->status = false; - ctx->unique = false; - ctx->warn = false; - ctx->xargs_safe = false; - - ctx->colors = NULL; - ctx->colors_error = 0; - ctx->cout = NULL; - ctx->cerr = NULL; - - ctx->users = NULL; - ctx->groups = NULL; - - ctx->mtab = NULL; - ctx->mtab_error = 0; trie_init(&ctx->files); - ctx->nfiles = 0; struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) != 0) { @@ -155,7 +130,7 @@ CFILE *bfs_ctx_dedup(struct bfs_ctx *ctx, CFILE *cfile, const char *path) { return ctx_file->cfile; } - leaf->value = ctx_file = malloc(sizeof(*ctx_file)); + leaf->value = ctx_file = ALLOC(struct bfs_ctx_file); if (!ctx_file) { trie_remove(&ctx->files, leaf); return NULL; diff --git a/src/dstring.c b/src/dstring.c index 2c9869d..7ca74d0 100644 --- a/src/dstring.c +++ b/src/dstring.c @@ -2,6 +2,7 @@ // SPDX-License-Identifier: 0BSD #include "dstring.h" +#include "alloc.h" #include "diag.h" #include #include @@ -24,7 +25,7 @@ static struct dstring *dstrheader(const char *dstr) { /** Get the correct size for a dstring with the given capacity. */ static size_t dstrsize(size_t capacity) { - return flex_sizeof(struct dstring, data, capacity + 1); + return sizeof_flex(struct dstring, data, capacity + 1); } /** Allocate a dstring with the given contents. */ diff --git a/src/exec.c b/src/exec.c index 5912ad6..ea7f897 100644 --- a/src/exec.c +++ b/src/exec.c @@ -2,6 +2,7 @@ // SPDX-License-Identifier: 0BSD #include "exec.h" +#include "alloc.h" #include "bfstd.h" #include "bftw.h" #include "ctx.h" @@ -124,26 +125,16 @@ static void bfs_exec_parse_error(const struct bfs_ctx *ctx, const struct bfs_exe } struct bfs_exec *bfs_exec_parse(const struct bfs_ctx *ctx, char **argv, enum bfs_exec_flags flags) { - struct bfs_exec *execbuf = malloc(sizeof(*execbuf)); + struct bfs_exec *execbuf = ZALLOC(struct bfs_exec); if (!execbuf) { - bfs_perror(ctx, "malloc()"); + bfs_perror(ctx, "zalloc()"); goto fail; } execbuf->flags = flags; execbuf->ctx = ctx; execbuf->tmpl_argv = argv + 1; - execbuf->tmpl_argc = 0; - execbuf->argv = NULL; - execbuf->argc = 0; - execbuf->argv_cap = 0; - execbuf->arg_size = 0; - execbuf->arg_max = 0; - execbuf->arg_min = 0; execbuf->wd_fd = -1; - execbuf->wd_path = NULL; - execbuf->wd_len = 0; - execbuf->ret = 0; while (true) { const char *arg = execbuf->tmpl_argv[execbuf->tmpl_argc]; @@ -176,9 +167,9 @@ struct bfs_exec *bfs_exec_parse(const struct bfs_ctx *ctx, char **argv, enum bfs } execbuf->argv_cap = execbuf->tmpl_argc + 1; - execbuf->argv = malloc(execbuf->argv_cap*sizeof(*execbuf->argv)); + execbuf->argv = ALLOC_ARRAY(char *, execbuf->argv_cap); if (!execbuf->argv) { - bfs_perror(ctx, "malloc()"); + bfs_perror(ctx, "alloc()"); goto fail; } @@ -224,9 +215,8 @@ static char *bfs_exec_format_path(const struct bfs_exec *execbuf, const struct B return NULL; } - strcpy(path, "./"); - strcpy(path + 2, name); - + char *cur = stpcpy(path, "./"); + cur = stpcpy(cur, name); return path; } @@ -612,7 +602,7 @@ static int bfs_exec_push(struct bfs_exec *execbuf, char *arg) { if (execbuf->argc + 1 >= execbuf->argv_cap) { size_t cap = 2*execbuf->argv_cap; - char **argv = realloc(execbuf->argv, cap*sizeof(*argv)); + char **argv = realloc(execbuf->argv, sizeof_array(char *, cap)); if (!argv) { return -1; } diff --git a/src/ioq.c b/src/ioq.c index 5550c91..3e304ce 100644 --- a/src/ioq.c +++ b/src/ioq.c @@ -2,6 +2,7 @@ // SPDX-License-Identifier: 0BSD #include "ioq.h" +#include "alloc.h" #include "atomic.h" #include "bfstd.h" #include "bit.h" @@ -114,7 +115,7 @@ static struct ioqq *ioqq_create(size_t size) { // Circular buffer size must be a power of two size = bit_ceil(size); - struct ioqq *ioqq = xmemalign(alignof(struct ioqq), flex_sizeof(struct ioqq, slots, size)); + struct ioqq *ioqq = ALLOC_FLEX(struct ioqq, slots, size); if (!ioqq) { return NULL; } @@ -124,7 +125,7 @@ static struct ioqq *ioqq_create(size_t size) { // Use a pool of monitors size_t nmonitors = size < 64 ? size : 64; - ioqq->monitors = xmemalign(alignof(struct ioq_monitor), nmonitors * sizeof(struct ioq_monitor)); + ioqq->monitors = ALLOC_ARRAY(struct ioq_monitor, nmonitors); if (!ioqq->monitors) { ioqq_destroy(ioqq); return NULL; @@ -273,7 +274,7 @@ struct ioq { /** The number of background threads. */ size_t nthreads; /** The background threads themselves. */ - pthread_t *threads; + pthread_t threads[]; }; /** Background thread entry point. */ @@ -303,18 +304,13 @@ static void *ioq_work(void *ptr) { return NULL; } -struct ioq *ioq_create(size_t depth, size_t threads) { - struct ioq *ioq = malloc(sizeof(*ioq)); +struct ioq *ioq_create(size_t depth, size_t nthreads) { + struct ioq *ioq = ZALLOC_FLEX(struct ioq, threads, nthreads); if (!ioq) { goto fail; } ioq->depth = depth; - ioq->size = 0; - - ioq->pending = NULL; - ioq->ready = NULL; - ioq->nthreads = 0; ioq->pending = ioqq_create(depth); if (!ioq->pending) { @@ -326,12 +322,7 @@ struct ioq *ioq_create(size_t depth, size_t threads) { goto fail; } - ioq->threads = malloc(threads * sizeof(ioq->threads[0])); - if (!ioq->threads) { - goto fail; - } - - for (size_t i = 0; i < threads; ++i) { + for (size_t i = 0; i < nthreads; ++i) { errno = pthread_create(&ioq->threads[i], NULL, ioq_work, ioq); if (errno != 0) { goto fail; @@ -354,7 +345,7 @@ int ioq_opendir(struct ioq *ioq, int dfd, const char *path, void *ptr) { return -1; } - union ioq_cmd *cmd = malloc(sizeof(*cmd)); + union ioq_cmd *cmd = ALLOC(union ioq_cmd); if (!cmd) { return -1; } @@ -412,7 +403,6 @@ void ioq_destroy(struct ioq *ioq) { abort(); } } - free(ioq->threads); ioqq_destroy(ioq->ready); ioqq_destroy(ioq->pending); diff --git a/src/ioq.h b/src/ioq.h index 9492034..0af5779 100644 --- a/src/ioq.h +++ b/src/ioq.h @@ -33,12 +33,12 @@ struct ioq_res { * * @param depth * The maximum depth of the queue. - * @param threads + * @param nthreads * The maximum number of background threads. * @return * The new I/O queue, or NULL on failure. */ -struct ioq *ioq_create(size_t depth, size_t threads); +struct ioq *ioq_create(size_t depth, size_t nthreads); /** * Asynchronous bfs_opendir(). diff --git a/src/main.c b/src/main.c index 76dde86..b7a08c1 100644 --- a/src/main.c +++ b/src/main.c @@ -20,6 +20,7 @@ * - bftw.[ch] (an extended version of nftw(3)) * * - Utilities: + * - alloc.[ch] (memory allocation) * - atomic.h (atomic operations) * - bar.[ch] (a terminal status bar) * - bit.h (bit manipulation) diff --git a/src/mtab.c b/src/mtab.c index 1d1ad94..e5c25ba 100644 --- a/src/mtab.c +++ b/src/mtab.c @@ -2,6 +2,7 @@ // SPDX-License-Identifier: 0BSD #include "mtab.h" +#include "alloc.h" #include "bfstd.h" #include "config.h" #include "darray.h" @@ -87,15 +88,13 @@ fail: } struct bfs_mtab *bfs_mtab_parse(void) { - struct bfs_mtab *mtab = malloc(sizeof(*mtab)); + struct bfs_mtab *mtab = ZALLOC(struct bfs_mtab); if (!mtab) { return NULL; } - mtab->entries = NULL; trie_init(&mtab->names); trie_init(&mtab->types); - mtab->types_filled = false; int error = 0; diff --git a/src/parse.c b/src/parse.c index 64e08cd..cf4f696 100644 --- a/src/parse.c +++ b/src/parse.c @@ -9,6 +9,7 @@ */ #include "parse.h" +#include "alloc.h" #include "bfstd.h" #include "bftw.h" #include "color.h" @@ -55,39 +56,16 @@ static char *fake_print_arg = "-print"; static char *fake_true_arg = "-true"; struct bfs_expr *bfs_expr_new(bfs_eval_fn *eval_fn, size_t argc, char **argv) { - struct bfs_expr *expr = malloc(sizeof(*expr)); + struct bfs_expr *expr = ZALLOC(struct bfs_expr); if (!expr) { - perror("malloc()"); + perror("zalloc()"); return NULL; } expr->eval_fn = eval_fn; expr->argc = argc; expr->argv = argv; - expr->persistent_fds = 0; - expr->ephemeral_fds = 0; - expr->pure = false; - expr->always_true = false; - expr->always_false = false; - expr->cost = 0.0; expr->probability = 0.5; - expr->evaluations = 0; - expr->successes = 0; - expr->elapsed.tv_sec = 0; - expr->elapsed.tv_nsec = 0; - - // Prevent bfs_expr_free() from freeing uninitialized pointers on error paths - if (bfs_expr_is_parent(expr)) { - expr->lhs = NULL; - expr->rhs = NULL; - } else if (eval_fn == eval_exec) { - expr->exec = NULL; - } else if (eval_fn == eval_fprintf) { - expr->printf = NULL; - } else if (eval_fn == eval_regex) { - expr->regex = NULL; - } - return expr; } diff --git a/src/pwcache.c b/src/pwcache.c index f52e4e1..9f32eb0 100644 --- a/src/pwcache.c +++ b/src/pwcache.c @@ -2,6 +2,7 @@ // SPDX-License-Identifier: 0BSD #include "pwcache.h" +#include "alloc.h" #include "config.h" #include "darray.h" #include "trie.h" @@ -71,7 +72,7 @@ struct bfs_users { }; struct bfs_users *bfs_users_new(void) { - struct bfs_users *users = malloc(sizeof(*users)); + struct bfs_users *users = ALLOC(struct bfs_users); if (!users) { return NULL; } @@ -144,7 +145,7 @@ struct bfs_groups { }; struct bfs_groups *bfs_groups_new(void) { - struct bfs_groups *groups = malloc(sizeof(*groups)); + struct bfs_groups *groups = ALLOC(struct bfs_groups); if (!groups) { return NULL; } diff --git a/src/trie.c b/src/trie.c index 8543eb1..19423cf 100644 --- a/src/trie.c +++ b/src/trie.c @@ -82,6 +82,7 @@ */ #include "trie.h" +#include "alloc.h" #include "bit.h" #include "config.h" #include "diag.h" @@ -317,7 +318,7 @@ struct trie_leaf *trie_find_prefix(const struct trie *trie, const char *key) { /** Create a new leaf, holding a copy of the given key. */ static struct trie_leaf *trie_leaf_alloc(struct trie *trie, const void *key, size_t length) { - struct trie_leaf *leaf = malloc(flex_sizeof(struct trie_leaf, key, length)); + struct trie_leaf *leaf = ALLOC_FLEX(struct trie_leaf, key, length); if (!leaf) { return NULL; } @@ -339,12 +340,10 @@ static void trie_leaf_free(struct trie *trie, struct trie_leaf *leaf) { /** Compute the size of a trie node with a certain number of children. */ static size_t trie_node_size(unsigned int size) { - // Empty nodes aren't supported - bfs_assert(size > 0); // Node size must be a power of two bfs_assert(has_single_bit(size)); - return flex_sizeof(struct trie_node, children, size); + return sizeof_flex(struct trie_node, children, size); } #if ENDIAN_NATIVE == ENDIAN_LITTLE diff --git a/src/xregex.c b/src/xregex.c index 89c2e90..ab5f793 100644 --- a/src/xregex.c +++ b/src/xregex.c @@ -2,6 +2,7 @@ // SPDX-License-Identifier: 0BSD #include "xregex.h" +#include "alloc.h" #include "config.h" #include "diag.h" #include "sanity.h" @@ -115,7 +116,7 @@ static int bfs_onig_initialize(OnigEncoding *enc) { #endif int bfs_regcomp(struct bfs_regex **preg, const char *pattern, enum bfs_regex_type type, enum bfs_regcomp_flags flags) { - struct bfs_regex *regex = *preg = malloc(sizeof(*regex)); + struct bfs_regex *regex = *preg = ALLOC(struct bfs_regex); if (!regex) { return -1; } diff --git a/src/xspawn.c b/src/xspawn.c index 740e38e..2cabdcc 100644 --- a/src/xspawn.c +++ b/src/xspawn.c @@ -2,6 +2,7 @@ // SPDX-License-Identifier: 0BSD #include "xspawn.h" +#include "alloc.h" #include "bfstd.h" #include "config.h" #include "list.h" @@ -62,7 +63,7 @@ int bfs_spawn_setflags(struct bfs_spawn *ctx, enum bfs_spawn_flags flags) { /** Add a spawn action to the chain. */ static struct bfs_spawn_action *bfs_spawn_add(struct bfs_spawn *ctx, enum bfs_spawn_op op) { - struct bfs_spawn_action *action = malloc(sizeof(*action)); + struct bfs_spawn_action *action = ALLOC(struct bfs_spawn_action); if (!action) { return NULL; } diff --git a/tests/alloc.c b/tests/alloc.c new file mode 100644 index 0000000..91b1b43 --- /dev/null +++ b/tests/alloc.c @@ -0,0 +1,24 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include "../src/alloc.h" +#include "../src/diag.h" +#include + +int main(void) { + // Check sizeof_flex() + struct flexible { + alignas(64) int foo; + int bar[]; + }; + bfs_verify(sizeof_flex(struct flexible, bar, 0) >= sizeof(struct flexible)); + bfs_verify(sizeof_flex(struct flexible, bar, 16) % alignof(struct flexible) == 0); + bfs_verify(sizeof_flex(struct flexible, bar, SIZE_MAX / sizeof(int) + 1) + == align_floor(alignof(struct flexible), SIZE_MAX)); + + // Corner case: sizeof(type) > align_ceil(alignof(type), offsetof(type, member)) + // Doesn't happen in typical ABIs + bfs_verify(flex_size(8, 16, 4, 4, 1) == 16); + + return EXIT_SUCCESS; +} diff --git a/tests/bfstd.c b/tests/bfstd.c index 7fea9b5..fa854a8 100644 --- a/tests/bfstd.c +++ b/tests/bfstd.c @@ -24,17 +24,6 @@ static void check_base_dir(const char *path, const char *dir, const char *base) } int main(void) { - // Check flex_sizeof() - struct flexible { - alignas(64) int foo; - int bar[]; - }; - bfs_verify(flex_sizeof(struct flexible, bar, 0) >= sizeof(struct flexible)); - bfs_verify(flex_sizeof(struct flexible, bar, 16) % alignof(struct flexible) == 0); - bfs_verify(flex_sizeof(struct flexible, bar, SIZE_MAX / sizeof(int) + 1) - == align_floor(alignof(struct flexible), SIZE_MAX)); - bfs_verify(flex_sizeof_impl(8, 16, 4, 4, 1) == 16); - // From man 3p basename check_base_dir("usr", ".", "usr"); check_base_dir("usr/", ".", "usr"); @@ -46,4 +35,6 @@ int main(void) { check_base_dir("/usr/lib", "/usr", "lib"); check_base_dir("//usr//lib//", "//usr", "lib"); check_base_dir("/home//dwc//test", "/home//dwc", "test"); + + return EXIT_SUCCESS; } -- cgit v1.2.3 From 5c3572dc323527a5c168cc12a31b730e0749002d Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sat, 24 Jun 2023 12:00:22 -0400 Subject: Unify macro naming conventions In particular, macros that decide whether to use a particular API/ dependency should be spelled BFS_USE_*, and should be configurable. --- Makefile | 20 ++++++++++---------- docs/BUILDING.md | 18 +++++++++--------- src/config.h | 6 ++++-- src/diag.h | 6 ++---- src/dir.c | 28 ++++++++++++++-------------- src/mtab.c | 28 ++++++++++++++-------------- src/parse.c | 4 ++-- src/stat.c | 16 +++++++++------- src/trie.c | 2 +- src/xregex.c | 14 +++++++------- 10 files changed, 72 insertions(+), 70 deletions(-) (limited to 'src/config.h') diff --git a/Makefile b/Makefile index d38f581..f7af9cc 100644 --- a/Makefile +++ b/Makefile @@ -104,11 +104,11 @@ LOCAL_CFLAGS += -fno-sanitize-recover=all endif ifndef NOLIBS -WITH_ONIGURUMA := y +USE_ONIGURUMA := y endif -ifdef WITH_ONIGURUMA -LOCAL_CPPFLAGS += -DBFS_WITH_ONIGURUMA=1 +ifdef USE_ONIGURUMA +LOCAL_CPPFLAGS += -DBFS_USE_ONIGURUMA=1 ONIG_CONFIG := $(shell command -v onig-config 2>/dev/null) ifdef ONIG_CONFIG @@ -120,28 +120,28 @@ endif LOCAL_CFLAGS += $(ONIG_CFLAGS) LOCAL_LDLIBS += $(ONIG_LDLIBS) -endif # WITH_ONIGURUMA +endif # USE_ONIGURUMA ifeq ($(OS),Linux) ifndef NOLIBS -WITH_ACL := y -WITH_ATTR := y -WITH_LIBCAP := y +USE_ACL := y +USE_ATTR := y +USE_LIBCAP := y endif -ifdef WITH_ACL +ifdef USE_ACL LOCAL_LDLIBS += -lacl else LOCAL_CPPFLAGS += -DBFS_USE_SYS_ACL_H=0 endif -ifdef WITH_ATTR +ifdef USE_ATTR LOCAL_LDLIBS += -lattr else LOCAL_CPPFLAGS += -DBFS_USE_SYS_XATTR_H=0 endif -ifdef WITH_LIBCAP +ifdef USE_LIBCAP LOCAL_LDLIBS += -lcap else LOCAL_CPPFLAGS += -DBFS_USE_SYS_CAPABILITY_H=0 diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 5219160..d0cb1fc 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -56,7 +56,7 @@ Here are some of the common ones; check the [`Makefile`](/Makefile) for more. | `CC` | The C compiler to use, e.g. `make CC=clang` | | `CFLAGS`
`EXTRA_CFLAGS` | Override/add to the default compiler flags | | `LDFLAGS`
`EXTRA_LDFLAGS` | Override/add to the linker flags | -| `WITH_ACL`
`WITH_ATTR`
... | Enable/disable [optional dependencies] | +| `USE_ACL`
`USE_ATTR`
... | Enable/disable [optional dependencies] | | `TEST_FLAGS` | `tests.sh` flags for `make check` | | `BUILDDIR` | The build output directory (default: `.`) | | `DESTDIR` | The root directory for `make install` | @@ -68,14 +68,14 @@ Here are some of the common ones; check the [`Makefile`](/Makefile) for more. ### Dependencies `bfs` depends on some system libraries for some of its features. -These dependencies are optional, and can be turned off at build time if necessary by setting the appropriate variable to the empty string (e.g. `make WITH_ONIGURUMA=`). - -| Dependency | Platforms | `make` flag | -|-------------|------------|------------------| -| [acl] | Linux only | `WITH_ACL` | -| [attr] | Linux only | `WITH_ATTR` | -| [libcap] | Linux only | `WITH_LIBCAP` | -| [Oniguruma] | All | `WITH_ONIGURUMA` | +These dependencies are optional, and can be turned off at build time if necessary by setting the appropriate variable to the empty string (e.g. `make USE_ONIGURUMA=`). + +| Dependency | Platforms | `make` flag | +|-------------|------------|-----------------| +| [acl] | Linux only | `USE_ACL` | +| [attr] | Linux only | `USE_ATTR` | +| [libcap] | Linux only | `USE_LIBCAP` | +| [Oniguruma] | All | `USE_ONIGURUMA` | [acl]: https://savannah.nongnu.org/projects/acl [attr]: https://savannah.nongnu.org/projects/attr diff --git a/src/config.h b/src/config.h index 1671a0d..79bd931 100644 --- a/src/config.h +++ b/src/config.h @@ -189,8 +189,10 @@ /** * Check if function multiversioning via GNU indirect functions (ifunc) is supported. */ -#if !defined(BFS_TARGET_CLONES) && __has_attribute(target_clones) && (__GLIBC__ || __FreeBSD__ || __NetBSD__) -# define BFS_TARGET_CLONES true +#ifndef BFS_USE_TARGET_CLONES +# if __has_attribute(target_clones) && (__GLIBC__ || __FreeBSD__ || __NetBSD__) +# define BFS_USE_TARGET_CLONES true +# endif #endif /** diff --git a/src/diag.h b/src/diag.h index 8d02da6..c909da5 100644 --- a/src/diag.h +++ b/src/diag.h @@ -18,8 +18,8 @@ #if __STDC_VERSION__ >= 202311L # define bfs_static_assert static_assert #else -# define bfs_static_assert(...) BFS_STATIC_ASSERT(__VA_ARGS__, #__VA_ARGS__, ) -# define BFS_STATIC_ASSERT(expr, msg, ...) _Static_assert(expr, msg) +# define bfs_static_assert(...) bfs_static_assert_(__VA_ARGS__, #__VA_ARGS__, ) +# define bfs_static_assert_(expr, msg, ...) _Static_assert(expr, msg) #endif /** @@ -62,8 +62,6 @@ noreturn void bfs_abortf(const struct bfs_loc *loc, const char *format, ...); # define bfs_bug bfs_abort #endif - - /** * Unconditional assert. */ diff --git a/src/dir.c b/src/dir.c index a24b572..685bac5 100644 --- a/src/dir.c +++ b/src/dir.c @@ -15,11 +15,11 @@ #include #include -#ifndef BFS_GETDENTS -# define BFS_GETDENTS (__linux__ || __FreeBSD__) +#ifndef BFS_USE_GETDENTS +# define BFS_USE_GETDENTS (__linux__ || __FreeBSD__) #endif -#if BFS_GETDENTS +#if BFS_USE_GETDENTS # if __linux__ # include # endif @@ -43,9 +43,9 @@ static ssize_t bfs_getdents(int fd, void *buf, size_t size) { return ret; } -#endif // BFS_GETDENTS +#endif // BFS_USE_GETDENTS -#if BFS_GETDENTS && __linux__ +#if BFS_USE_GETDENTS && __linux__ /** Directory entry type for bfs_getdents() */ typedef struct dirent64 sys_dirent; #else @@ -101,7 +101,7 @@ enum bfs_type bfs_mode_to_type(mode_t mode) { } struct bfs_dir { -#if BFS_GETDENTS +#if BFS_USE_GETDENTS alignas(sys_dirent) int fd; unsigned short pos; unsigned short size; @@ -114,7 +114,7 @@ struct bfs_dir { bool eof; }; -#if BFS_GETDENTS +#if BFS_USE_GETDENTS # define DIR_SIZE (64 << 10) # define BUF_SIZE (DIR_SIZE - sizeof(struct bfs_dir)) #else @@ -143,7 +143,7 @@ int bfs_opendir(struct bfs_dir *dir, int at_fd, const char *at_path) { return -1; } -#if BFS_GETDENTS +#if BFS_USE_GETDENTS dir->fd = fd; dir->pos = 0; dir->size = 0; @@ -163,7 +163,7 @@ int bfs_opendir(struct bfs_dir *dir, int at_fd, const char *at_path) { } int bfs_dirfd(const struct bfs_dir *dir) { -#if BFS_GETDENTS +#if BFS_USE_GETDENTS return dir->fd; #else return dirfd(dir->dir); @@ -171,7 +171,7 @@ int bfs_dirfd(const struct bfs_dir *dir) { } int bfs_polldir(struct bfs_dir *dir) { -#if BFS_GETDENTS +#if BFS_USE_GETDENTS if (dir->pos < dir->size) { return 1; } else if (dir->eof) { @@ -203,7 +203,7 @@ int bfs_polldir(struct bfs_dir *dir) { } return 1; -#else // !BFS_GETDENTS +#else // !BFS_USE_GETDENTS if (dir->de) { return 1; } else if (dir->eof) { @@ -227,7 +227,7 @@ int bfs_polldir(struct bfs_dir *dir) { static int bfs_getdent(struct bfs_dir *dir, const sys_dirent **de) { int ret = bfs_polldir(dir); if (ret > 0) { -#if BFS_GETDENTS +#if BFS_USE_GETDENTS char *buf = (char *)(dir + 1); *de = (const sys_dirent *)(buf + dir->pos); dir->pos += (*de)->d_reclen; @@ -283,7 +283,7 @@ int bfs_readdir(struct bfs_dir *dir, struct bfs_dirent *de) { } int bfs_closedir(struct bfs_dir *dir) { -#if BFS_GETDENTS +#if BFS_USE_GETDENTS int ret = xclose(dir->fd); #else int ret = closedir(dir->dir); @@ -297,7 +297,7 @@ int bfs_closedir(struct bfs_dir *dir) { } int bfs_fdclosedir(struct bfs_dir *dir, bool same_fd) { -#if BFS_GETDENTS +#if BFS_USE_GETDENTS int ret = dir->fd; #elif __FreeBSD__ int ret = fdclosedir(dir->dir); diff --git a/src/mtab.c b/src/mtab.c index e5c25ba..384fdfc 100644 --- a/src/mtab.c +++ b/src/mtab.c @@ -14,22 +14,22 @@ #include #include -#if BFS_USE_MNTENT_H -# define BFS_MNTENT 1 -#elif BSD -# define BFS_MNTINFO 1 -#elif __SVR4 -# define BFS_MNTTAB 1 +#if !defined(BFS_USE_MNTENT) && BFS_USE_MNTENT_H +# define BFS_USE_MNTENT true +#elif !defined(BFS_USE_MNTINFO) && BSD +# define BFS_USE_MNTINFO true +#elif !defined(BFS_USE_MNTTAB) && __SVR4 +# define BFS_USE_MNTTAB true #endif -#if BFS_MNTENT +#if BFS_USE_MNTENT # include # include # include -#elif BFS_MNTINFO +#elif BFS_USE_MNTINFO # include # include -#elif BFS_MNTTAB +#elif BFS_USE_MNTTAB # include # include #endif @@ -45,7 +45,7 @@ struct bfs_mtab_entry { }; struct bfs_mtab { - /** The list of mount points. */ + /** The array of mount points. */ struct bfs_mtab_entry *entries; /** The basenames of every mount point. */ struct trie names; @@ -59,7 +59,7 @@ struct bfs_mtab { /** * Add an entry to the mount table. */ -static int bfs_mtab_add(struct bfs_mtab *mtab, const char *path, const char *type) { +static inline int bfs_mtab_add(struct bfs_mtab *mtab, const char *path, const char *type) { struct bfs_mtab_entry entry = { .path = strdup(path), .type = strdup(type), @@ -98,7 +98,7 @@ struct bfs_mtab *bfs_mtab_parse(void) { int error = 0; -#if BFS_MNTENT +#if BFS_USE_MNTENT FILE *file = setmntent(_PATH_MOUNTED, "r"); if (!file) { @@ -121,7 +121,7 @@ struct bfs_mtab *bfs_mtab_parse(void) { endmntent(file); -#elif BFS_MNTINFO +#elif BFS_USE_MNTINFO #if __NetBSD__ typedef struct statvfs bfs_statfs; @@ -143,7 +143,7 @@ struct bfs_mtab *bfs_mtab_parse(void) { } } -#elif BFS_MNTTAB +#elif BFS_USE_MNTTAB FILE *file = xfopen(MNTTAB, O_RDONLY | O_CLOEXEC); if (!file) { diff --git a/src/parse.c b/src/parse.c index cf4f696..1321270 100644 --- a/src/parse.c +++ b/src/parse.c @@ -2296,7 +2296,7 @@ static struct bfs_expr *parse_regextype(struct parser_state *state, int arg1, in state->regex_type = BFS_REGEX_POSIX_BASIC; } else if (strcmp(type, "posix-extended") == 0) { state->regex_type = BFS_REGEX_POSIX_EXTENDED; -#if BFS_WITH_ONIGURUMA +#if BFS_USE_ONIGURUMA } else if (strcmp(type, "emacs") == 0) { state->regex_type = BFS_REGEX_EMACS; } else if (strcmp(type, "grep") == 0) { @@ -2318,7 +2318,7 @@ list_types: cfprintf(cfile, " ${bld}posix-basic${rs}: POSIX basic regular expressions (BRE)\n"); cfprintf(cfile, " ${bld}posix-extended${rs}: POSIX extended regular expressions (ERE)\n"); cfprintf(cfile, " ${bld}ed${rs}: Like ${grn}ed${rs} (same as ${bld}posix-basic${rs})\n"); -#if BFS_WITH_ONIGURUMA +#if BFS_USE_ONIGURUMA cfprintf(cfile, " ${bld}emacs${rs}: Like ${grn}emacs${rs}\n"); cfprintf(cfile, " ${bld}grep${rs}: Like ${grn}grep${rs}\n"); #endif diff --git a/src/stat.c b/src/stat.c index e3e5aaa..7a413cd 100644 --- a/src/stat.c +++ b/src/stat.c @@ -14,15 +14,17 @@ #include #if defined(STATX_BASIC_STATS) && (!__ANDROID__ || __ANDROID_API__ >= 30) -# define BFS_LIBC_STATX true +# define BFS_HAS_LIBC_STATX true #elif __linux__ # include # include # include #endif -#if BFS_LIBC_STATX || defined(SYS_statx) -# define BFS_STATX true +#ifndef BFS_USE_STATX +# if BFS_HAS_LIBC_STATX || defined(SYS_statx) +# define BFS_USE_STATX true +# endif #endif const char *bfs_stat_field_name(enum bfs_stat_field field) { @@ -128,13 +130,13 @@ static int bfs_stat_impl(int at_fd, const char *at_path, int at_flags, struct bf return ret; } -#if BFS_STATX +#if BFS_USE_STATX /** * Wrapper for the statx() system call, which had no glibc wrapper prior to 2.28. */ static int bfs_statx(int at_fd, const char *at_path, int at_flags, unsigned int mask, struct statx *buf) { -#if BFS_LIBC_STATX +#if BFS_HAS_LIBC_STATX int ret = statx(at_fd, at_path, at_flags, mask, buf); #else int ret = syscall(SYS_statx, at_fd, at_path, at_flags, mask, buf); @@ -242,13 +244,13 @@ static int bfs_statx_impl(int at_fd, const char *at_path, int at_flags, struct b return ret; } -#endif // BFS_STATX +#endif // BFS_USE_STATX /** * Calls the stat() implementation with explicit flags. */ static int bfs_stat_explicit(int at_fd, const char *at_path, int at_flags, int x_flags, struct bfs_stat *buf) { -#if BFS_STATX +#if BFS_USE_STATX static atomic bool has_statx = true; if (load(&has_statx, relaxed)) { diff --git a/src/trie.c b/src/trie.c index 992d42b..0206509 100644 --- a/src/trie.c +++ b/src/trie.c @@ -94,7 +94,7 @@ bfs_static_assert(CHAR_WIDTH == 8); -#if BFS_TARGET_CLONES && (__i386__ || __x86_64__) +#if BFS_USE_TARGET_CLONES && (__i386__ || __x86_64__) # define TARGET_CLONES_POPCNT __attribute__((target_clones("popcnt", "default"))) #else # define TARGET_CLONES_POPCNT diff --git a/src/xregex.c b/src/xregex.c index ab5f793..88df082 100644 --- a/src/xregex.c +++ b/src/xregex.c @@ -11,7 +11,7 @@ #include #include -#if BFS_WITH_ONIGURUMA +#if BFS_USE_ONIGURUMA # include # include #else @@ -19,7 +19,7 @@ #endif struct bfs_regex { -#if BFS_WITH_ONIGURUMA +#if BFS_USE_ONIGURUMA unsigned char *pattern; OnigRegex impl; int err; @@ -30,7 +30,7 @@ struct bfs_regex { #endif }; -#if BFS_WITH_ONIGURUMA +#if BFS_USE_ONIGURUMA static int bfs_onig_status; static OnigEncoding bfs_onig_enc; @@ -121,7 +121,7 @@ int bfs_regcomp(struct bfs_regex **preg, const char *pattern, enum bfs_regex_typ return -1; } -#if BFS_WITH_ONIGURUMA +#if BFS_USE_ONIGURUMA // onig_error_code_to_str() says // // don't call this after the pattern argument of onig_new() is freed @@ -204,7 +204,7 @@ fail: int bfs_regexec(struct bfs_regex *regex, const char *str, enum bfs_regexec_flags flags) { size_t len = strlen(str); -#if BFS_WITH_ONIGURUMA +#if BFS_USE_ONIGURUMA const unsigned char *ustr = (const unsigned char *)str; const unsigned char *end = ustr + len; @@ -263,7 +263,7 @@ int bfs_regexec(struct bfs_regex *regex, const char *str, enum bfs_regexec_flags void bfs_regfree(struct bfs_regex *regex) { if (regex) { -#if BFS_WITH_ONIGURUMA +#if BFS_USE_ONIGURUMA onig_free(regex->impl); free(regex->pattern); #else @@ -278,7 +278,7 @@ char *bfs_regerror(const struct bfs_regex *regex) { return strdup(strerror(ENOMEM)); } -#if BFS_WITH_ONIGURUMA +#if BFS_USE_ONIGURUMA unsigned char *str = malloc(ONIG_MAX_ERROR_MESSAGE_LEN); if (str) { onig_error_code_to_str(str, regex->err, ®ex->einfo); -- cgit v1.2.3 From 75b6e1b49e37c6eecd2225c9602ac7aa266c4023 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 30 Jun 2023 11:20:43 -0400 Subject: docs: Start preparing for the 3.0 release --- Makefile | 2 +- docs/CHANGELOG.md | 39 +++++++++++++++++++++++++++++++++++++++ src/config.h | 2 +- 3 files changed, 41 insertions(+), 2 deletions(-) (limited to 'src/config.h') diff --git a/Makefile b/Makefile index 5d7461e..beaf59d 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ VERSION := $(shell git describe --always 2>/dev/null) endif ifndef VERSION -VERSION := 2.6.3 +VERSION := 3.0 endif ifndef OS diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index f67e68a..933ddc3 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,3 +1,42 @@ +3.* +=== + +3.0 +--- + +**Coming soon** + +### New features + +- `bfs` now reads directories asynchronously and in parallel ([#101]). + Performance is significantly improved as a result. + Parallelism is controlled by the new `-j` flag, e.g. `-j1`, `-j2`, etc. + +[#101]: https://github.com/tavianator/bfs/issues/101 + +### Changes + +- `bfs` now uses the [C17] standard version, up from C11 + +- Due to [#101], `bfs` now requires some additional C and POSIX features: + - [Standard C atomics] (``) + - [POSIX threads] (``) + +- `$LS_COLORS` extensions written in different cases (e.g. `*.jpg=35:*.JPG=01;35`) are now matched case-sensitively, to match the new behaviour of GNU ls since coreutils version 9.2 + +- Added a warning/error if `$LS_COLORS` can't be parsed, depending on whether `-color` is requested explicitly + +- Build flags like `WITH_ONIGURUMA` have been renamed to `USE_ONIGURUMA` + +[C17]: https://en.cppreference.com/w/c/17 +[Standard C atomics]: https://en.cppreference.com/w/c/atomic +[POSIX threads]: https://pubs.opengroup.org/onlinepubs/9699919799/idx/threads.html + +### Bug fixes + +- Fixed handling of the "normal text" color (`no` in `$LS_COLORS`) to match GNU ls + + 2.* === diff --git a/src/config.h b/src/config.h index 79bd931..59d2671 100644 --- a/src/config.h +++ b/src/config.h @@ -22,7 +22,7 @@ # define BFS_COMMAND "bfs" #endif #ifndef BFS_VERSION -# define BFS_VERSION "2.6.3" +# define BFS_VERSION "3.0" #endif #ifndef BFS_HOMEPAGE # define BFS_HOMEPAGE "https://tavianator.com/projects/bfs.html" -- cgit v1.2.3 From fb023fdeea088fa66b0df6cbf4e7becf8edeebbb Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 18 Jul 2023 12:23:21 -0400 Subject: Release 3.0.1 --- Makefile | 2 +- docs/CHANGELOG.md | 18 ++++++++++++++++++ src/config.h | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src/config.h') diff --git a/Makefile b/Makefile index db955b5..406506b 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ VERSION := $(shell git describe --always 2>/dev/null) endif ifndef VERSION -VERSION := 3.0 +VERSION := 3.0.1 endif ifndef OS diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index a1b0049..1cc95e9 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,24 @@ 3.* === +3.0.1 +----- + +**July 18, 2023** + +### Bug fixes + +- Traversal fixes that mostly affect large directory trees ([#107]) + + - `bfs` could encounter `EMFILE`, close a file, and retry many times, particularly with `-j1` + + - Breadth-first search could become highly unbalanced, negating many of the benefits of `bfs` + + - On non-{Linux,FreeBSD} plaforms, directories could stay open longer than necessary, consuming extra memory + +[#107]: https://github.com/tavianator/bfs/pull/107 + + 3.0 --- diff --git a/src/config.h b/src/config.h index 59d2671..fd4961f 100644 --- a/src/config.h +++ b/src/config.h @@ -22,7 +22,7 @@ # define BFS_COMMAND "bfs" #endif #ifndef BFS_VERSION -# define BFS_VERSION "3.0" +# define BFS_VERSION "3.0.1" #endif #ifndef BFS_HOMEPAGE # define BFS_HOMEPAGE "https://tavianator.com/projects/bfs.html" -- cgit v1.2.3 From 0015b79936a58a325e80cf036c10cb1010122703 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 6 Sep 2023 21:15:50 -0400 Subject: Release 3.0.2 --- GNUmakefile | 2 +- docs/CHANGELOG.md | 18 ++++++++++++++++++ src/config.h | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src/config.h') diff --git a/GNUmakefile b/GNUmakefile index 069c548..6902979 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -6,7 +6,7 @@ VERSION := $(shell git describe --always 2>/dev/null) endif ifndef VERSION -VERSION := 3.0.1 +VERSION := 3.0.2 endif ifndef OS diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 1cc95e9..3dca97c 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,24 @@ 3.* === +3.0.2 +----- + +**September 6, 2023** + +### Changes + +- `-files0-from` now allows an empty set of paths to be given, matching GNU findutils 4.9.0 + +- Reduced memory consumption in multi-threaded searches + +- Many man page updates + +### Bug fixes + +- Fixed an out-of-bounds memory read that could occur when escaping a string containing an incomplete multi-byte character + + 3.0.1 ----- diff --git a/src/config.h b/src/config.h index fd4961f..14c9305 100644 --- a/src/config.h +++ b/src/config.h @@ -22,7 +22,7 @@ # define BFS_COMMAND "bfs" #endif #ifndef BFS_VERSION -# define BFS_VERSION "3.0.1" +# define BFS_VERSION "3.0.2" #endif #ifndef BFS_HOMEPAGE # define BFS_HOMEPAGE "https://tavianator.com/projects/bfs.html" -- cgit v1.2.3 From 14f790c80acf0f9f005ce9e7a94246954533163b Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 5 Oct 2023 12:47:31 -0400 Subject: config: Fold !__FreeBSD__ into BFS_USE_SYS_CAPABILITY_H --- src/config.h | 2 +- src/fsade.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index 14c9305..e3048c4 100644 --- a/src/config.h +++ b/src/config.h @@ -88,7 +88,7 @@ # define BFS_USE_SYS_ACL_H BFS_HAS_SYS_ACL_H #endif #ifndef BFS_USE_SYS_CAPABILITY_H -# define BFS_USE_SYS_CAPABILITY_H BFS_HAS_SYS_CAPABILITY_H +# define BFS_USE_SYS_CAPABILITY_H (BFS_HAS_SYS_CAPABILITY_H && !__FreeBSD__) #endif #ifndef BFS_USE_SYS_EXTATTR_H # define BFS_USE_SYS_EXTATTR_H BFS_HAS_SYS_EXTATTR_H diff --git a/src/fsade.h b/src/fsade.h index 0d9ecaf..413938d 100644 --- a/src/fsade.h +++ b/src/fsade.h @@ -13,7 +13,7 @@ #define BFS_CAN_CHECK_ACL BFS_USE_SYS_ACL_H -#if !defined(BFS_CAN_CHECK_CAPABILITIES) && BFS_USE_SYS_CAPABILITY_H && !__FreeBSD__ +#if !defined(BFS_CAN_CHECK_CAPABILITIES) && BFS_USE_SYS_CAPABILITY_H # include # ifdef CAP_CHOWN # define BFS_CAN_CHECK_CAPABILITIES true -- cgit v1.2.3 From 634359bb169311646f6369b21f0c90a9819fe2ce Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 5 Oct 2023 12:55:56 -0400 Subject: thread: Define thread_local --- src/config.h | 7 +++++++ src/thread.h | 9 +++++++++ 2 files changed, 16 insertions(+) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index e3048c4..862a839 100644 --- a/src/config.h +++ b/src/config.h @@ -59,6 +59,9 @@ #if __has_include() # define BFS_HAS_SYS_XATTR_H true #endif +#if __has_include() +# define BFS_HAS_THREADS_H true +#endif #if __has_include() # define BFS_HAS_UTIL_H true #endif @@ -74,6 +77,7 @@ #define BFS_HAS_SYS_PARAM_H true #define BFS_HAS_SYS_SYSMACROS_H __GLIBC__ #define BFS_HAS_SYS_XATTR_H __linux__ +#define BFS_HAS_THREADS_H (!__STDC_NO_THREADS__) #define BFS_HAS_UTIL_H __NetBSD__ #endif // !__has_include @@ -105,6 +109,9 @@ #ifndef BFS_USE_SYS_XATTR_H # define BFS_USE_SYS_XATTR_H BFS_HAS_SYS_XATTR_H #endif +#ifndef BFS_USE_THREADS_H +# define BFS_USE_THREADS_H BFS_HAS_THREADS_H +#endif #ifndef BFS_USE_UTIL_H # define BFS_USE_UTIL_H BFS_HAS_UTIL_H #endif diff --git a/src/thread.h b/src/thread.h index 45b5e1f..ab95a79 100644 --- a/src/thread.h +++ b/src/thread.h @@ -8,11 +8,20 @@ #ifndef BFS_THREAD_H #define BFS_THREAD_H +#include "config.h" #include "diag.h" #include #include #include +#if __STDC_VERSION__ < 202311L && !defined(thread_local) +# if BFS_USE_THREADS_H +# include +# else +# define thread_local _Thread_local +# endif +#endif + #define thread_verify(expr, cond) \ bfs_verify((errno = (expr), (cond)), "%s: %s", #expr, strerror(errno)) -- cgit v1.2.3 From 2acd897857fe301dfc6f5a8648e0124cd8515b4e Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 12 Oct 2023 22:13:49 -0400 Subject: Release 3.0.3 --- GNUmakefile | 2 +- docs/CHANGELOG.md | 14 +++----------- src/config.h | 2 +- 3 files changed, 5 insertions(+), 13 deletions(-) (limited to 'src/config.h') diff --git a/GNUmakefile b/GNUmakefile index 69cfe3d..27d6674 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -6,7 +6,7 @@ VERSION := $(shell git describe --always 2>/dev/null) endif ifndef VERSION -VERSION := 3.0.2 +VERSION := 3.0.3 endif ifndef OS diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 8e10caa..253dd46 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,16 +1,10 @@ 3.* === -3.1 ---- - -**Coming soon** - -### New features - -- `bfs` now uses `io_uring` on Linux ([#106]) +3.0.3 +----- -- `bfs` now comes with an official benchmark suite ([#126]) +**October 12, 2023** ### Changes @@ -26,8 +20,6 @@ - Fixed a linked-list corruption that could lead to an infinite loop on macOS and other non-Linux, non-FreeBSD platforms ([`773f4a4`]) -[#106]: https://github.com/tavianator/bfs/pull/106 -[#126]: https://github.com/tavianator/bfs/pull/126 [`5f16169`]: https://github.com/tavianator/bfs/commit/5f1616912ba3a7a23ce6bce02df3791b73da38ab [`2572273`]: https://github.com/tavianator/bfs/commit/257227326fe60fe70e80433fd34d1ebcb2f9f623 [`a029d95`]: https://github.com/tavianator/bfs/commit/a029d95b5736a74879f32089514a5a6b63d6efbc diff --git a/src/config.h b/src/config.h index 862a839..980980a 100644 --- a/src/config.h +++ b/src/config.h @@ -22,7 +22,7 @@ # define BFS_COMMAND "bfs" #endif #ifndef BFS_VERSION -# define BFS_VERSION "3.0.2" +# define BFS_VERSION "3.0.3" #endif #ifndef BFS_HOMEPAGE # define BFS_HOMEPAGE "https://tavianator.com/projects/bfs.html" -- cgit v1.2.3 From c25fa4fb5e58e20ce97c3747c05d26307a70baaa Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 12 Oct 2023 23:50:16 -0400 Subject: Release 3.0.4 --- GNUmakefile | 2 +- docs/CHANGELOG.md | 12 ++++++++++++ src/config.h | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src/config.h') diff --git a/GNUmakefile b/GNUmakefile index 27d6674..011e397 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -6,7 +6,7 @@ VERSION := $(shell git describe --always 2>/dev/null) endif ifndef VERSION -VERSION := 3.0.3 +VERSION := 3.0.4 endif ifndef OS diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 253dd46..3b07f01 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,18 @@ 3.* === +3.0.4 +----- + +**October 12, 2023** + +### Bug Fixes + +- Fixed a segfault when reporting errors under musl ([`d40eb87`]) + +[`d40eb87`]: https://github.com/tavianator/bfs/commit/d40eb87cc00f50a5debb8899eacb7fcf1065badf + + 3.0.3 ----- diff --git a/src/config.h b/src/config.h index 980980a..38ca69b 100644 --- a/src/config.h +++ b/src/config.h @@ -22,7 +22,7 @@ # define BFS_COMMAND "bfs" #endif #ifndef BFS_VERSION -# define BFS_VERSION "3.0.3" +# define BFS_VERSION "3.0.4" #endif #ifndef BFS_HOMEPAGE # define BFS_HOMEPAGE "https://tavianator.com/projects/bfs.html" -- cgit v1.2.3 From b5b1e98a66aef5b64409e3d02149733bf3f475fb Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 9 Nov 2023 15:29:04 -0500 Subject: config: Remove BFS_SUPPRESS() --- src/config.h | 15 --------------- src/printf.c | 18 ++++++++++++++---- 2 files changed, 14 insertions(+), 19 deletions(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index 38ca69b..e11941a 100644 --- a/src/config.h +++ b/src/config.h @@ -202,19 +202,4 @@ # endif #endif -/** - * Ignore a particular GCC warning for a region of code. - */ -#if __GNUC__ -# define BFS_PRAGMA_STRINGIFY(...) _Pragma(#__VA_ARGS__) -# define BFS_SUPPRESS(warning) \ - _Pragma("GCC diagnostic push"); \ - BFS_PRAGMA_STRINGIFY(GCC diagnostic ignored warning) -# define BFS_UNSUPPRESS() \ - _Pragma("GCC diagnostic pop") -#else -# define BFS_SUPPRESS(warning) -# define BFS_UNSUPPRESS() -#endif - #endif // BFS_CONFIG_H diff --git a/src/printf.c b/src/printf.c index 704e26d..02ca586 100644 --- a/src/printf.c +++ b/src/printf.c @@ -83,9 +83,14 @@ static int dyn_fprintf(FILE *file, const struct bfs_printf *directive, ...) { va_list args; va_start(args, directive); - BFS_SUPPRESS("-Wformat-nonliteral"); +#if __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif int ret = vfprintf(file, directive->str, args); - BFS_UNSUPPRESS(); +#if __GNUC__ +# pragma GCC diagnostic pop +#endif va_end(args); return ret; @@ -183,9 +188,14 @@ static int bfs_printf_strftime(CFILE *cfile, const struct bfs_printf *directive, // POSIX strftime() features default: format[1] = directive->c; - BFS_SUPPRESS("-Wformat-nonliteral"); +#if __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif ret = strftime(buf, sizeof(buf), format, &tm); - BFS_UNSUPPRESS(); +#if __GNUC__ +# pragma GCC diagnostic pop +#endif break; } -- cgit v1.2.3 From 026e8fbd248561396752552efa3cc04e0ac832b7 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 9 Nov 2023 12:59:20 -0500 Subject: config: s/BFS_FORMATTER/attr_format/ --- src/bar.c | 2 +- src/color.c | 4 ++-- src/color.h | 4 ++-- src/config.h | 4 ++-- src/diag.h | 14 +++++++------- src/dstring.h | 8 ++++---- src/eval.c | 2 +- src/exec.c | 2 +- src/opt.c | 4 ++-- src/parse.c | 14 +++++++------- 10 files changed, 29 insertions(+), 29 deletions(-) (limited to 'src/config.h') diff --git a/src/bar.c b/src/bar.c index 57cc4dd..2e50dbe 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(). */ -BFS_FORMATTER(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 fbb5edf..7644ca3 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. */ -BFS_FORMATTER(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; } -BFS_FORMATTER(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 b118f77..8a81573 100644 --- a/src/color.h +++ b/src/color.h @@ -100,13 +100,13 @@ int cfclose(CFILE *cfile); * @return * 0 on success, -1 on failure. */ -BFS_FORMATTER(2, 3) +attr_format(2, 3) int cfprintf(CFILE *cfile, const char *format, ...); /** * cfprintf() variant that takes a va_list. */ -BFS_FORMATTER(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 e11941a..f19677c 100644 --- a/src/config.h +++ b/src/config.h @@ -188,9 +188,9 @@ * Adds compiler warnings for bad printf()-style function calls, if supported. */ #if __has_attribute(format) -# define BFS_FORMATTER(fmt, args) __attribute__((format(printf, fmt, args))) +# define attr_format(fmt, args) __attribute__((format(printf, fmt, args))) #else -# define BFS_FORMATTER(fmt, args) +# define attr_format(fmt, args) #endif /** diff --git a/src/diag.h b/src/diag.h index 838a794..8c7ed57 100644 --- a/src/diag.h +++ b/src/diag.h @@ -44,7 +44,7 @@ struct bfs_loc { /** * Print a message to standard error and abort. */ -BFS_FORMATTER(2, 3) +attr_format(2, 3) noreturn void bfs_abortf(const struct bfs_loc *loc, const char *format, ...); /** @@ -121,7 +121,7 @@ void bfs_perror(const struct bfs_ctx *ctx, const char *str); /** * Shorthand for printing error messages. */ -BFS_FORMATTER(2, 3) +attr_format(2, 3) void bfs_error(const struct bfs_ctx *ctx, const char *format, ...); /** @@ -129,7 +129,7 @@ void bfs_error(const struct bfs_ctx *ctx, const char *format, ...); * * @return Whether a warning was printed. */ -BFS_FORMATTER(2, 3) +attr_format(2, 3) bool bfs_warning(const struct bfs_ctx *ctx, const char *format, ...); /** @@ -137,25 +137,25 @@ bool bfs_warning(const struct bfs_ctx *ctx, const char *format, ...); * * @return Whether a debug message was printed. */ -BFS_FORMATTER(3, 4) +attr_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. */ -BFS_FORMATTER(2, 0) +attr_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. */ -BFS_FORMATTER(2, 0) +attr_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. */ -BFS_FORMATTER(3, 0) +attr_format(3, 0) bool bfs_vdebug(const struct bfs_ctx *ctx, enum debug_flags flag, const char *format, va_list args); /** diff --git a/src/dstring.h b/src/dstring.h index 6496a4f..fd98df8 100644 --- a/src/dstring.h +++ b/src/dstring.h @@ -230,7 +230,7 @@ int dstrxcpy(dchar **dest, const char *str, size_t len); * @return * The created string, or NULL on failure. */ -BFS_FORMATTER(1, 2) +attr_format(1, 2) char *dstrprintf(const char *format, ...); /** @@ -243,7 +243,7 @@ char *dstrprintf(const char *format, ...); * @return * The created string, or NULL on failure. */ -BFS_FORMATTER(1, 0) +attr_format(1, 0) char *dstrvprintf(const char *format, va_list args); /** @@ -258,7 +258,7 @@ char *dstrvprintf(const char *format, va_list args); * @return * 0 on success, -1 on failure. */ -BFS_FORMATTER(2, 3) +attr_format(2, 3) int dstrcatf(dchar **str, const char *format, ...); /** @@ -273,7 +273,7 @@ int dstrcatf(dchar **str, const char *format, ...); * @return * 0 on success, -1 on failure. */ -BFS_FORMATTER(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 b511eba..eb4a0ca 100644 --- a/src/eval.c +++ b/src/eval.c @@ -58,7 +58,7 @@ struct bfs_eval { /** * Print an error message. */ -BFS_FORMATTER(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 f0730d2..ba82439 100644 --- a/src/exec.c +++ b/src/exec.c @@ -22,7 +22,7 @@ #include /** Print some debugging info. */ -BFS_FORMATTER(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/opt.c b/src/opt.c index 77c2798..5da73d8 100644 --- a/src/opt.c +++ b/src/opt.c @@ -305,7 +305,7 @@ struct opt_state { }; /** Log an optimization. */ -BFS_FORMATTER(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. */ -BFS_FORMATTER(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 d21ab40..d3938fc 100644 --- a/src/parse.c +++ b/src/parse.c @@ -247,7 +247,7 @@ static void highlight_args(const struct bfs_ctx *ctx, char **argv, size_t argc, /** * Print an error message during parsing. */ -BFS_FORMATTER(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; @@ -267,7 +267,7 @@ static void parse_error(const struct parser_state *state, const char *format, .. /** * Print an error about some command line arguments. */ -BFS_FORMATTER(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; @@ -287,7 +287,7 @@ static void parse_argv_error(const struct parser_state *state, char **argv, size /** * Print an error about conflicting command line arguments. */ -BFS_FORMATTER(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; @@ -308,7 +308,7 @@ static void parse_conflict_error(const struct parser_state *state, char **argv1, /** * Print an error about an expression. */ -BFS_FORMATTER(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; @@ -325,7 +325,7 @@ static void parse_expr_error(const struct parser_state *state, const struct bfs_ /** * Print a warning message during parsing. */ -BFS_FORMATTER(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; @@ -348,7 +348,7 @@ static bool parse_warning(const struct parser_state *state, const char *format, /** * Print a warning about conflicting command line arguments. */ -BFS_FORMATTER(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; @@ -372,7 +372,7 @@ static bool parse_conflict_warning(const struct parser_state *state, char **argv /** * Print a warning about an expression. */ -BFS_FORMATTER(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; -- cgit v1.2.3 From 0a5091a9005b485fccad689a4cbf081802860a5a Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 9 Nov 2023 13:02:59 -0500 Subject: config: New attr_target_clones() macro --- src/config.h | 9 +++++++++ src/trie.c | 16 ++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index f19677c..3100cec 100644 --- a/src/config.h +++ b/src/config.h @@ -202,4 +202,13 @@ # endif #endif +/** + * Apply the target_clones attribute, if available. + */ +#if BFS_USE_TARGET_CLONES +# define attr_target_clones(...) __attribute__((target_clones(__VA_ARGS__))) +#else +# define attr_target_clones(...) +#endif + #endif // BFS_CONFIG_H diff --git a/src/trie.c b/src/trie.c index 23b70ff..cf55cee 100644 --- a/src/trie.c +++ b/src/trie.c @@ -94,10 +94,10 @@ bfs_static_assert(CHAR_WIDTH == 8); -#if BFS_USE_TARGET_CLONES && (__i386__ || __x86_64__) -# define TARGET_CLONES_POPCNT __attribute__((target_clones("popcnt", "default"))) +#if __i386__ || __x86_64__ +# define trie_clones attr_target_clones("popcnt", "default") #else -# define TARGET_CLONES_POPCNT +# define trie_clones #endif /** Number of bits for the sparse array bitmap, aka the range of a nibble. */ @@ -192,7 +192,7 @@ static unsigned char trie_key_nibble(const void *key, size_t offset) { * that case, the first mismatch between the key and the representative will be * the depth at which to make a new branch to insert the key. */ -TARGET_CLONES_POPCNT +trie_clones static struct trie_leaf *trie_representative(const struct trie *trie, const void *key, size_t length) { uintptr_t ptr = trie->root; if (!ptr) { @@ -271,7 +271,7 @@ static bool trie_check_prefix(struct trie_leaf *leaf, size_t skip, const char *k } } -TARGET_CLONES_POPCNT +trie_clones static struct trie_leaf *trie_find_prefix_impl(const struct trie *trie, const char *key) { uintptr_t ptr = trie->root; if (!ptr) { @@ -429,7 +429,7 @@ static size_t trie_mismatch(const struct trie_leaf *rep, const void *key, size_t * | Z * +--->... */ -TARGET_CLONES_POPCNT +trie_clones static struct trie_leaf *trie_node_insert(struct trie *trie, uintptr_t *ptr, struct trie_leaf *leaf, unsigned char nibble) { struct trie_node *node = trie_decode_node(*ptr); unsigned int size = count_ones(node->bitmap); @@ -552,7 +552,7 @@ struct trie_leaf *trie_insert_str(struct trie *trie, const char *key) { return trie_insert_mem(trie, key, strlen(key) + 1); } -TARGET_CLONES_POPCNT +trie_clones static struct trie_leaf *trie_insert_mem_impl(struct trie *trie, const void *key, size_t length) { struct trie_leaf *rep = trie_representative(trie, key, length); size_t mismatch = trie_mismatch(rep, key, length); @@ -654,7 +654,7 @@ static int trie_collapse_node(struct trie *trie, uintptr_t *parent, struct trie_ return 0; } -TARGET_CLONES_POPCNT +trie_clones static void trie_remove_impl(struct trie *trie, struct trie_leaf *leaf) { uintptr_t *child = &trie->root; uintptr_t *parent = NULL; -- cgit v1.2.3 From c745df94a182b8a569cb833ecfbe8da33bf01f98 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 9 Nov 2023 14:34:21 -0500 Subject: config: New attr_noinline and attr_cold macros --- src/alloc.c | 1 + src/config.h | 18 ++++++++++++++++++ src/diag.h | 15 +++++++++++++++ src/ioq.c | 2 ++ 4 files changed, 36 insertions(+) (limited to 'src/config.h') diff --git a/src/alloc.c b/src/alloc.c index 0b978ba..3b9972f 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -107,6 +107,7 @@ void arena_init(struct arena *arena, size_t align, size_t size) { } /** Allocate a new slab. */ +attr_cold static int slab_alloc(struct arena *arena) { void **slabs = realloc(arena->slabs, sizeof_array(void *, arena->nslabs + 1)); if (!slabs) { diff --git a/src/config.h b/src/config.h index 3100cec..b95abaa 100644 --- a/src/config.h +++ b/src/config.h @@ -184,6 +184,24 @@ # define fallthru ((void)0) #endif +/** + * Hint to avoid inlining a function. + */ +#if __has_attribute(noinline) +# define attr_noinline __attribute__((noinline)) +#else +# define attr_noinline +#endif + +/** + * Hint that a function is unlikely to be called. + */ +#if __has_attribute(cold) +# define attr_cold attr_noinline __attribute__((cold)) +#else +# define attr_cold attr_noinline +#endif + /** * Adds compiler warnings for bad printf()-style function calls, if supported. */ diff --git a/src/diag.h b/src/diag.h index 8c7ed57..870264e 100644 --- a/src/diag.h +++ b/src/diag.h @@ -44,6 +44,7 @@ struct bfs_loc { /** * Print a message to standard error and abort. */ +attr_cold attr_format(2, 3) noreturn void bfs_abortf(const struct bfs_loc *loc, const char *format, ...); @@ -116,11 +117,13 @@ const char *debug_flag_name(enum debug_flags flag); /** * Like perror(), but decorated like bfs_error(). */ +attr_cold void bfs_perror(const struct bfs_ctx *ctx, const char *str); /** * Shorthand for printing error messages. */ +attr_cold attr_format(2, 3) void bfs_error(const struct bfs_ctx *ctx, const char *format, ...); @@ -129,6 +132,7 @@ void bfs_error(const struct bfs_ctx *ctx, const char *format, ...); * * @return Whether a warning was printed. */ +attr_cold attr_format(2, 3) bool bfs_warning(const struct bfs_ctx *ctx, const char *format, ...); @@ -137,60 +141,71 @@ bool bfs_warning(const struct bfs_ctx *ctx, const char *format, ...); * * @return Whether a debug message was printed. */ +attr_cold attr_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) 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) 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) 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 void bfs_error_prefix(const struct bfs_ctx *ctx); /** * Print the warning message prefix. */ +attr_cold bool bfs_warning_prefix(const struct bfs_ctx *ctx); /** * Print the debug message prefix. */ +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 void bfs_argv_error(const struct bfs_ctx *ctx, const bool args[]); /** * Highlight parts of an expression in an error message. */ +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 bool bfs_argv_warning(const struct bfs_ctx *ctx, const bool args[]); /** * Highlight parts of an expression in a warning message. */ +attr_cold bool bfs_expr_warning(const struct bfs_ctx *ctx, const struct bfs_expr *expr); #endif // BFS_DIAG_H diff --git a/src/ioq.c b/src/ioq.c index 244b2cc..ef89fa8 100644 --- a/src/ioq.c +++ b/src/ioq.c @@ -269,6 +269,7 @@ static struct ioq_monitor *ioq_slot_monitor(struct ioqq *ioqq, ioq_slot *slot) { } /** Atomically wait for a slot to change. */ +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); @@ -298,6 +299,7 @@ done: } /** Wake up any threads waiting on a slot. */ +attr_noinline static void ioq_slot_wake(struct ioqq *ioqq, ioq_slot *slot) { struct ioq_monitor *monitor = ioq_slot_monitor(ioqq, slot); -- cgit v1.2.3 From e25261a90222de75781726a93ab809c660208afd Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 9 Nov 2023 15:16:04 -0500 Subject: config: Add (de)allocator attributes --- src/alloc.h | 40 +++++++++++++++++++++++----------------- src/config.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ src/dstring.h | 21 +++++++++++++-------- tests/alloc.c | 4 ++++ 4 files changed, 89 insertions(+), 25 deletions(-) (limited to 'src/config.h') diff --git a/src/alloc.h b/src/alloc.h index fd3e5f0..34f6949 100644 --- a/src/alloc.h +++ b/src/alloc.h @@ -9,7 +9,7 @@ #define BFS_ALLOC_H #include "config.h" -#include +#include /** Round down to a multiple of an alignment. */ static inline size_t align_floor(size_t align, size_t size) { @@ -108,6 +108,8 @@ 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) void *alloc(size_t align, size_t size); /** @@ -120,6 +122,8 @@ 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) void *zalloc(size_t align, size_t size); /** Allocate memory for the given type. */ @@ -176,14 +180,15 @@ void arena_init(struct arena *arena, size_t align, size_t size); arena_init((arena), alignof(type), sizeof(type)) /** - * Allocate an object out of the arena. + * Free an object from the arena. */ -void *arena_alloc(struct arena *arena); +void arena_free(struct arena *arena, void *ptr); /** - * Free an object from the arena. + * Allocate an object out of the arena. */ -void arena_free(struct arena *arena, void *ptr); +attr_malloc(arena_free, 2) +void *arena_alloc(struct arena *arena); /** * Free all allocations from an arena. @@ -242,6 +247,18 @@ void varena_init(struct varena *varena, size_t align, size_t min, size_t offset, #define VARENA_INIT(varena, type, member) \ varena_init(varena, alignof(type), sizeof(type), offsetof(type, member), sizeof_member(type, member[0])) +/** + * Free an arena-allocated flexible struct. + * + * @param varena + * The that allocated the object. + * @param ptr + * The object to free. + * @param count + * The length of the flexible array. + */ +void varena_free(struct varena *varena, void *ptr, size_t count); + /** * Arena-allocate a flexible struct. * @@ -252,6 +269,7 @@ void varena_init(struct varena *varena, size_t align, size_t min, size_t offset, * @return * The allocated struct, or NULL on failure. */ +attr_malloc(varena_free, 2) void *varena_alloc(struct varena *varena, size_t count); /** @@ -284,18 +302,6 @@ void *varena_realloc(struct varena *varena, void *ptr, size_t old_count, size_t */ void *varena_grow(struct varena *varena, void *ptr, size_t *count); -/** - * Free an arena-allocated flexible struct. - * - * @param varena - * The that allocated the object. - * @param ptr - * The object to free. - * @param count - * The length of the flexible array. - */ -void varena_free(struct varena *varena, void *ptr, size_t count); - /** * Free all allocations from a varena. */ diff --git a/src/config.h b/src/config.h index b95abaa..db62ef8 100644 --- a/src/config.h +++ b/src/config.h @@ -184,6 +184,17 @@ # define fallthru ((void)0) #endif +/** + * Warn if a value is unused. + */ +#if __has_c_attribute(nodiscard) +# define attr_nodiscard [[nodiscard]] +#elif __has_attribute(nodiscard) +# define attr_nodiscard __attribute__((nodiscard)) +#else +# define attr_nodiscard +#endif + /** * Hint to avoid inlining a function. */ @@ -211,6 +222,44 @@ # define attr_format(fmt, args) #endif +/** + * Annotates allocator-like functions. + */ +#if __has_attribute(malloc) +# if __clang__ +# define attr_malloc(...) attr_nodiscard __attribute__((malloc)) +# else +# define attr_malloc(...) attr_nodiscard __attribute__((malloc(__VA_ARGS__))) +# endif +#else +# define attr_malloc(...) attr_nodiscard +#endif + +/** + * Specifies that a function returns allocations with a given alignment. + */ +#if __has_attribute(alloc_align) +# define attr_alloc_align(param) __attribute__((alloc_align(param))) +#else +# define attr_alloc_align(param) +#endif + +/** + * Specifies that a function returns allocations with a given size. + */ +#if __has_attribute(alloc_size) +# define attr_alloc_size(...) __attribute__((alloc_size(__VA_ARGS__))) +#else +# define attr_alloc_size(...) +#endif + +/** + * Shorthand for attr_alloc_align() and attr_alloc_size(). + */ +#define attr_aligned_alloc(align, ...) \ + attr_alloc_align(align) \ + attr_alloc_size(__VA_ARGS__) + /** * Check if function multiversioning via GNU indirect functions (ifunc) is supported. */ diff --git a/src/dstring.h b/src/dstring.h index fd98df8..07b4ee9 100644 --- a/src/dstring.h +++ b/src/dstring.h @@ -27,12 +27,21 @@ typedef __attribute__((aligned(alignof(size_t)))) char dchar; typedef char dchar; #endif +/** + * Free a dynamic string. + * + * @param dstr + * The string to free. + */ +void dstrfree(dchar *dstr); + /** * Allocate a dynamic string. * * @param capacity * The initial capacity of the string. */ +attr_malloc(dstrfree, 1) dchar *dstralloc(size_t capacity); /** @@ -41,6 +50,7 @@ dchar *dstralloc(size_t capacity); * @param str * The NUL-terminated string to copy. */ +attr_malloc(dstrfree, 1) dchar *dstrdup(const char *str); /** @@ -51,6 +61,7 @@ dchar *dstrdup(const char *str); * @param n * The maximum number of characters to copy from str. */ +attr_malloc(dstrfree, 1) dchar *dstrndup(const char *str, size_t n); /** @@ -59,6 +70,7 @@ dchar *dstrndup(const char *str, size_t n); * @param dstr * The dynamic string to copy. */ +attr_malloc(dstrfree, 1) dchar *dstrddup(const dchar *dstr); /** @@ -69,6 +81,7 @@ dchar *dstrddup(const dchar *dstr); * @param len * The length of the string, which may include internal NUL bytes. */ +attr_malloc(dstrfree, 1) dchar *dstrxdup(const char *str, size_t len); /** @@ -306,12 +319,4 @@ int dstrescat(dchar **dest, const char *str, enum wesc_flags flags); */ int dstrnescat(dchar **dest, const char *str, size_t n, enum wesc_flags flags); -/** - * Free a dynamic string. - * - * @param dstr - * The string to free. - */ -void dstrfree(dchar *dstr); - #endif // BFS_DSTRING_H diff --git a/tests/alloc.c b/tests/alloc.c index 2334241..37b70bf 100644 --- a/tests/alloc.c +++ b/tests/alloc.c @@ -24,6 +24,10 @@ int main(void) { bfs_verify(flex_size(8, 16, 4, 4, 1) == 16); // Make sure we detect allocation size overflows +#if __GNUC__ && !__clang__ +# pragma GCC diagnostic ignored "-Walloc-size-larger-than=" +#endif + bfs_verify(ALLOC_ARRAY(int, too_many) == NULL && errno == EOVERFLOW); bfs_verify(ZALLOC_ARRAY(int, too_many) == NULL && errno == EOVERFLOW); bfs_verify(ALLOC_FLEX(struct flexible, bar, too_many) == NULL && errno == EOVERFLOW); -- cgit v1.2.3 From 4efbe8eca395c90fc0053c7ba1038ccb7bf69e61 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 10 Nov 2023 09:58:57 -0500 Subject: config: Add constants for C standard versions --- src/bit.h | 8 ++++---- src/config.h | 10 +++++++++- src/diag.h | 4 ++-- src/thread.h | 2 +- 4 files changed, 16 insertions(+), 8 deletions(-) (limited to 'src/config.h') diff --git a/src/bit.h b/src/bit.h index 3f756f6..21a8076 100644 --- a/src/bit.h +++ b/src/bit.h @@ -12,7 +12,7 @@ #include #include -#if __STDC_VERSION__ >= 202311L +#if __STDC_VERSION__ >= C23 # include #endif @@ -173,7 +173,7 @@ # define ENDIAN_NATIVE 0 #endif -#if __STDC_VERSION__ >= 202311L +#if __STDC_VERSION__ >= C23 # define bswap16 stdc_memreverse8u16 # define bswap32 stdc_memreverse8u32 # define bswap64 stdc_memreverse8u64 @@ -236,7 +236,7 @@ static inline uint8_t bswap8(uint8_t n) { // C23 polyfill: bit utilities -#if __STDC_VERSION__ >= 202311L +#if __STDC_VERSION__ >= C23 # define count_ones stdc_count_ones # define count_zeros stdc_count_zeros # define rotate_left stdc_rotate_left @@ -395,6 +395,6 @@ UINT_OVERLOADS(BIT_CEIL) #define bit_floor(n) UINT_SELECT(n, bit_floor)(n) #define bit_ceil(n) UINT_SELECT(n, bit_ceil)(n) -#endif // __STDC_VERSION__ < 202311L +#endif // __STDC_VERSION__ < C23 #endif // BFS_BIT_H diff --git a/src/config.h b/src/config.h index db62ef8..821e4a9 100644 --- a/src/config.h +++ b/src/config.h @@ -8,9 +8,17 @@ #ifndef BFS_CONFIG_H #define BFS_CONFIG_H +// Possible __STDC_VERSION__ values + +#define C95 199409L +#define C99 199901L +#define C11 201112L +#define C17 201710L +#define C23 202311L + #include -#if __STDC_VERSION__ < 202311L +#if __STDC_VERSION__ < C23 # include # include # include diff --git a/src/diag.h b/src/diag.h index 870264e..981419e 100644 --- a/src/diag.h +++ b/src/diag.h @@ -14,7 +14,7 @@ /** * static_assert() with an optional second argument. */ -#if __STDC_VERSION__ >= 202311L +#if __STDC_VERSION__ >= C23 # define bfs_static_assert static_assert #else # define bfs_static_assert(...) bfs_static_assert_(__VA_ARGS__, #__VA_ARGS__, ) @@ -35,7 +35,7 @@ struct bfs_loc { /** * Get the current source code location. */ -#if __STDC_VERSION__ >= 202311L +#if __STDC_VERSION__ >= C23 # define bfs_location() (&(static const struct bfs_loc)BFS_LOC_INIT) #else # define bfs_location() (&(const struct bfs_loc)BFS_LOC_INIT) diff --git a/src/thread.h b/src/thread.h index b37d45f..8174fe4 100644 --- a/src/thread.h +++ b/src/thread.h @@ -11,7 +11,7 @@ #include "config.h" #include -#if __STDC_VERSION__ < 202311L && !defined(thread_local) +#if __STDC_VERSION__ < C23 && !defined(thread_local) # if BFS_USE_THREADS_H # include # else -- cgit v1.2.3 From 640fa83406bb8c08d971be68b32b7e222e92e286 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 10 Nov 2023 22:22:01 -0500 Subject: Initial support for Cosmopolitan Libc --- src/alloc.c | 1 + src/bfstd.c | 2 +- src/config.h | 4 ++++ src/eval.c | 4 +++- src/xspawn.c | 25 ++++++++++++++++++++++++- 5 files changed, 33 insertions(+), 3 deletions(-) (limited to 'src/config.h') diff --git a/src/alloc.c b/src/alloc.c index 3b9972f..ff3ec6d 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -3,6 +3,7 @@ #include "alloc.h" #include "bit.h" +#include "config.h" #include "diag.h" #include "sanity.h" #include diff --git a/src/bfstd.c b/src/bfstd.c index 985a268..16cd82e 100644 --- a/src/bfstd.c +++ b/src/bfstd.c @@ -284,7 +284,7 @@ const char *xstrerror(int errnum) { const char *ret = NULL; static thread_local char buf[256]; -#if __APPLE__ +#if __APPLE__ || __COSMOPOLITAN__ // No strerror_l() on macOS if (strerror_r(errnum, buf, sizeof(buf)) == 0) { ret = buf; diff --git a/src/config.h b/src/config.h index 821e4a9..a474fb3 100644 --- a/src/config.h +++ b/src/config.h @@ -179,6 +179,10 @@ */ #define cache_align alignas(FALSE_SHARING_SIZE) +#if __COSMOPOLITAN__ +typedef long double max_align_t; +#endif + // Wrappers for attributes /** diff --git a/src/eval.c b/src/eval.c index eb4a0ca..6aa5104 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1558,7 +1558,9 @@ static const char *dump_bftw_strategy(enum bftw_strategy strategy) { /** Check if we need to enable BFTW_BUFFER. */ static bool eval_must_buffer(const struct bfs_expr *expr) { -#if __FreeBSD__ +#if __COSMOPOLITAN__ + return true; +#elif __FreeBSD__ // FreeBSD doesn't properly handle adding/removing directory entries // during readdir() on NFS mounts. Work around it by passing BFTW_BUFFER // whenever we could be mutating the directory ourselves through -delete diff --git a/src/xspawn.c b/src/xspawn.c index 01f21e9..6a2ebba 100644 --- a/src/xspawn.c +++ b/src/xspawn.c @@ -174,15 +174,38 @@ int bfs_spawn_addfchdir(struct bfs_spawn *ctx, int fd) { int bfs_spawn_addsetrlimit(struct bfs_spawn *ctx, int resource, const struct rlimit *rl) { struct bfs_spawn_action *action = bfs_spawn_action(BFS_SPAWN_SETRLIMIT); if (!action) { - return -1; + goto fail; + } + +#ifdef POSIX_SPAWN_SETRLIMIT + short flags; + errno = posix_spawnattr_getflags(&ctx->attr, &flags); + if (errno != 0) { + goto fail; + } + + flags |= POSIX_SPAWN_SETRLIMIT; + errno = posix_spawnattr_setflags(&ctx->attr, flags); + if (errno != 0) { + goto fail; } + errno = posix_spawnattr_setrlimit(&ctx->attr, resource, rl); + if (errno != 0) { + goto fail; + } +#else ctx->flags &= ~BFS_SPAWN_USE_POSIX; +#endif action->resource = resource; action->rlimit = *rl; SLIST_APPEND(ctx, action); return 0; + +fail: + free(action); + return -1; } /** bfs_spawn() implementation using posix_spawn(). */ -- cgit v1.2.3 From f4e8084414e07a8e03cb279090bbcf9eea76ed1e Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 15 Nov 2023 10:04:57 -0500 Subject: config: New attr_maybe_unused macro --- src/config.h | 13 ++++++++++++- src/fsade.c | 7 +++---- src/mtab.c | 3 ++- src/xspawn.c | 3 ++- 4 files changed, 19 insertions(+), 7 deletions(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index a474fb3..9f95674 100644 --- a/src/config.h +++ b/src/config.h @@ -186,7 +186,7 @@ typedef long double max_align_t; // Wrappers for attributes /** - * Silence compiler warnings about switch/case fall-throughs. + * Silence warnings about switch/case fall-throughs. */ #if __has_c_attribute(fallthrough) # define fallthru [[fallthrough]] @@ -196,6 +196,17 @@ typedef long double max_align_t; # define fallthru ((void)0) #endif +/** + * Silence warnings about unused declarations. + */ +#if __has_c_attribute(maybe_unused) +# define attr_maybe_unused [[maybe_unused]] +#elif __has_attribute(unused) +# define attr_maybe_unused __attribute__((unused)) +#else +# define attr_maybe_unused +#endif + /** * Warn if a value is unused. */ diff --git a/src/fsade.c b/src/fsade.c index cbff47b..4d22d99 100644 --- a/src/fsade.c +++ b/src/fsade.c @@ -28,12 +28,11 @@ # include #endif -#if BFS_CAN_CHECK_ACL || BFS_CAN_CHECK_CAPABILITIES || BFS_CAN_CHECK_XATTRS - /** * 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 static const char *fake_at(const struct BFTW *ftwbuf) { static atomic int proc_works = -1; @@ -67,6 +66,7 @@ fail: return ftwbuf->path; } +attr_maybe_unused static void free_fake_at(const struct BFTW *ftwbuf, const char *path) { if (path != ftwbuf->path) { dstrfree((dchar *)path); @@ -76,6 +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 static bool is_absence_error(int error) { // If the OS doesn't support the feature, it's obviously not enabled for // any files @@ -114,8 +115,6 @@ static bool is_absence_error(int error) { return false; } -#endif // BFS_CAN_CHECK_ACL || BFS_CAN_CHECK_CAPABILITIES || BFS_CAN_CHECK_XATTRS - #if BFS_CAN_CHECK_ACL /** Check if a POSIX.1e ACL is non-trivial. */ diff --git a/src/mtab.c b/src/mtab.c index 384fdfc..6b6f9d1 100644 --- a/src/mtab.c +++ b/src/mtab.c @@ -59,7 +59,8 @@ struct bfs_mtab { /** * Add an entry to the mount table. */ -static inline int bfs_mtab_add(struct bfs_mtab *mtab, const char *path, const char *type) { +attr_maybe_unused +static int bfs_mtab_add(struct bfs_mtab *mtab, const char *path, const char *type) { struct bfs_mtab_entry entry = { .path = strdup(path), .type = strdup(type), diff --git a/src/xspawn.c b/src/xspawn.c index 3974768..51432dd 100644 --- a/src/xspawn.c +++ b/src/xspawn.c @@ -73,7 +73,8 @@ int bfs_spawn_destroy(struct bfs_spawn *ctx) { } /** Set some posix_spawnattr flags. */ -static inline int bfs_spawn_addflags(struct bfs_spawn *ctx, short flags) { +attr_maybe_unused +static int bfs_spawn_addflags(struct bfs_spawn *ctx, short flags) { short prev; errno = posix_spawnattr_getflags(&ctx->attr, &prev); if (errno != 0) { -- cgit v1.2.3 From 5b38f658ee42bef05cecb6cadec65b25d9e94993 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 16 Nov 2023 12:25:09 -0500 Subject: config: New variadic attr(...) macro --- src/alloc.c | 2 +- src/alloc.h | 10 ++++---- src/bar.c | 2 +- src/color.c | 4 ++-- src/color.h | 4 ++-- src/config.h | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/diag.h | 37 ++++++++++++------------------ src/dstring.h | 18 +++++++-------- src/eval.c | 2 +- src/exec.c | 2 +- src/fsade.c | 6 ++--- src/ioq.c | 4 ++-- src/mtab.c | 2 +- src/opt.c | 4 ++-- src/parse.c | 14 +++++------ src/trie.c | 2 +- src/xspawn.c | 2 +- 17 files changed, 127 insertions(+), 62 deletions(-) (limited to 'src/config.h') 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 /** 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); -- cgit v1.2.3 From a85fc263a89fb89bc8b2a8166747660a177b1773 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 22 Nov 2023 09:33:49 -0500 Subject: config: s/attr_format/attr_printf/ --- src/bar.c | 2 +- src/color.c | 4 ++-- src/color.h | 4 ++-- src/config.h | 4 ++-- src/diag.h | 14 +++++++------- src/dstring.h | 8 ++++---- src/eval.c | 2 +- src/exec.c | 2 +- src/opt.c | 4 ++-- src/parse.c | 14 +++++++------- 10 files changed, 29 insertions(+), 29 deletions(-) (limited to 'src/config.h') diff --git a/src/bar.c b/src/bar.c index babadc3..8ab4112 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(printf(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 4c2c8ca..5247cbf 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(printf(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(printf(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 81f0e2a..760aa9d 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(printf(2, 3)) int cfprintf(CFILE *cfile, const char *format, ...); /** * cfprintf() variant that takes a va_list. */ -attr(format(2, 0)) +attr(printf(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 aa03552..46f1efe 100644 --- a/src/config.h +++ b/src/config.h @@ -240,9 +240,9 @@ typedef long double max_align_t; * Adds compiler warnings for bad printf()-style function calls, if supported. */ #if __has_attribute(format) -# define attr_format(fmt, args) __attribute__((format(printf, fmt, args))) +# define attr_printf(fmt, args) __attribute__((format(printf, fmt, args))) #else -# define attr_format(fmt, args) +# define attr_printf(fmt, args) #endif /** diff --git a/src/diag.h b/src/diag.h index aa6a44f..791c065 100644 --- a/src/diag.h +++ b/src/diag.h @@ -44,7 +44,7 @@ struct bfs_loc { /** * Print a message to standard error and abort. */ -attr(cold, format(2, 3)) +attr(cold, printf(2, 3)) noreturn void bfs_abortf(const struct bfs_loc *loc, const char *format, ...); /** @@ -122,7 +122,7 @@ void bfs_perror(const struct bfs_ctx *ctx, const char *str); /** * Shorthand for printing error messages. */ -attr(cold, format(2, 3)) +attr(cold, printf(2, 3)) void bfs_error(const struct bfs_ctx *ctx, const char *format, ...); /** @@ -130,7 +130,7 @@ void bfs_error(const struct bfs_ctx *ctx, const char *format, ...); * * @return Whether a warning was printed. */ -attr(cold, format(2, 3)) +attr(cold, printf(2, 3)) bool bfs_warning(const struct bfs_ctx *ctx, const char *format, ...); /** @@ -138,25 +138,25 @@ bool bfs_warning(const struct bfs_ctx *ctx, const char *format, ...); * * @return Whether a debug message was printed. */ -attr(cold, format(3, 4)) +attr(cold, printf(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, format(2, 0)) +attr(cold, printf(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, format(2, 0)) +attr(cold, printf(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, format(3, 0)) +attr(cold, printf(3, 0)) bool bfs_vdebug(const struct bfs_ctx *ctx, enum debug_flags flag, const char *format, va_list args); /** diff --git a/src/dstring.h b/src/dstring.h index 1be1185..6006199 100644 --- a/src/dstring.h +++ b/src/dstring.h @@ -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(printf(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(printf(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(printf(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(printf(2, 0)) int dstrvcatf(dchar **str, const char *format, va_list args); /** diff --git a/src/eval.c b/src/eval.c index 859ad7e..372fcf5 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(printf(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 ba2fec8..60bfd28 100644 --- a/src/exec.c +++ b/src/exec.c @@ -22,7 +22,7 @@ #include /** Print some debugging info. */ -attr(format(2, 3)) +attr(printf(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/opt.c b/src/opt.c index 3ee5e81..ddcd1ab 100644 --- a/src/opt.c +++ b/src/opt.c @@ -305,7 +305,7 @@ struct opt_state { }; /** Log an optimization. */ -attr(format(3, 4)) +attr(printf(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(printf(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 35d22fb..8d9c3f0 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(printf(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(printf(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(printf(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(printf(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(printf(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(printf(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(printf(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; -- cgit v1.2.3 From 2f3653bf522ce079501254bfd34abbf884dc528e Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 20 Dec 2023 18:34:49 -0500 Subject: config: Fix attr_nodiscard to use warn_unused_result --- src/config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index 46f1efe..91cef71 100644 --- a/src/config.h +++ b/src/config.h @@ -212,8 +212,8 @@ typedef long double max_align_t; */ #if __has_c_attribute(nodiscard) # define attr_nodiscard [[nodiscard]] -#elif __has_attribute(nodiscard) -# define attr_nodiscard __attribute__((nodiscard)) +#elif __has_attribute(warn_unused_result) +# define attr_nodiscard __attribute__((warn_unused_result)) #else # define attr_nodiscard #endif -- cgit v1.2.3 From f0d4c378f07195c2313b20c6b7072c1735359814 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 2 Jan 2024 19:31:48 -0500 Subject: config: Don't use target_clones on NetBSD --- src/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index 91cef71..7080fb6 100644 --- a/src/config.h +++ b/src/config.h @@ -287,7 +287,7 @@ typedef long double max_align_t; * Check if function multiversioning via GNU indirect functions (ifunc) is supported. */ #ifndef BFS_USE_TARGET_CLONES -# if __has_attribute(target_clones) && (__GLIBC__ || __FreeBSD__ || __NetBSD__) +# if __has_attribute(target_clones) && (__GLIBC__ || __FreeBSD__) # define BFS_USE_TARGET_CLONES true # endif #endif -- cgit v1.2.3 From 3b2c1067c56f234580145244530237071a1af46d Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 2 Jan 2024 18:32:41 -0500 Subject: config: Polyfill __NetBSD_Prereq__ --- src/config.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index 7080fb6..7dd9dc2 100644 --- a/src/config.h +++ b/src/config.h @@ -149,6 +149,10 @@ # define __GLIBC_PREREQ(maj, min) false #endif +#ifndef __NetBSD_Prereq__ +# define __NetBSD_Prereq__(maj, min, patch) false +#endif + // Fundamental utilities /** -- cgit v1.2.3 From 08867473e75e8e20ca76c7fb181204839e28b271 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 3 Jan 2024 15:00:00 -0500 Subject: config: Check for GCC >= 11 before using malloc attribute args --- src/config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index 7dd9dc2..ed9a869 100644 --- a/src/config.h +++ b/src/config.h @@ -253,10 +253,10 @@ typedef long double max_align_t; * Annotates allocator-like functions. */ #if __has_attribute(malloc) -# if __clang__ -# define attr_malloc(...) attr_nodiscard __attribute__((malloc)) -# else +# if __GNUC__ >= 11 # define attr_malloc(...) attr_nodiscard __attribute__((malloc(__VA_ARGS__))) +# else +# define attr_malloc(...) attr_nodiscard __attribute__((malloc)) # endif #else # define attr_malloc(...) attr_nodiscard -- cgit v1.2.3 From 976514edfb6063170049f561f5edbf330bbe4132 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 3 Jan 2024 16:42:07 -0500 Subject: config: Disable xattrs on DragonFly BSD DragonFly is missing extattr_get_link() and extattr_list_{file,link}(). --- src/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index ed9a869..24c6258 100644 --- a/src/config.h +++ b/src/config.h @@ -103,7 +103,7 @@ # define BFS_USE_SYS_CAPABILITY_H (BFS_HAS_SYS_CAPABILITY_H && !__FreeBSD__) #endif #ifndef BFS_USE_SYS_EXTATTR_H -# define BFS_USE_SYS_EXTATTR_H BFS_HAS_SYS_EXTATTR_H +# define BFS_USE_SYS_EXTATTR_H (BFS_HAS_SYS_EXTATTR_H && !__DragonFly__) #endif #ifndef BFS_USE_SYS_MKDEV_H # define BFS_USE_SYS_MKDEV_H BFS_HAS_SYS_MKDEV_H -- cgit v1.2.3 From d39d6999a78747f8048fd57e2ca3143c81c53537 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 9 Jan 2024 13:17:24 -0500 Subject: config: Disable sys/acl.h on illumos Their ACL API is quite a bit different from most. Link: https://illumos.org/man/2/acl --- src/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index 24c6258..85ad57e 100644 --- a/src/config.h +++ b/src/config.h @@ -97,7 +97,7 @@ # define BFS_USE_PATHS_H BFS_HAS_PATHS_H #endif #ifndef BFS_USE_SYS_ACL_H -# define BFS_USE_SYS_ACL_H BFS_HAS_SYS_ACL_H +# define BFS_USE_SYS_ACL_H (BFS_HAS_SYS_ACL_H && !__illumos__) #endif #ifndef BFS_USE_SYS_CAPABILITY_H # define BFS_USE_SYS_CAPABILITY_H (BFS_HAS_SYS_CAPABILITY_H && !__FreeBSD__) -- cgit v1.2.3 From 66468fd13ce70d0f6f6388cd31d7f75196ccac31 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 6 Feb 2024 16:06:27 -0500 Subject: Release 3.1 --- GNUmakefile | 2 +- docs/CHANGELOG.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/config.h | 2 +- 3 files changed, 46 insertions(+), 2 deletions(-) (limited to 'src/config.h') diff --git a/GNUmakefile b/GNUmakefile index 637a63e..8b1f848 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -6,7 +6,7 @@ VERSION := $(shell git describe --always 2>/dev/null) endif ifndef VERSION -VERSION := 3.0.4 +VERSION := 3.1 endif ifndef OS diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 3b07f01..b70ed32 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,50 @@ 3.* === +3.1 +--- + +**February 6, 2024** + +### New features + +- On Linux, `bfs` now uses [io_uring](https://en.wikipedia.org/wiki/Io_uring) for async I/O + +- On all platforms, `bfs` can now perform `stat()` calls in parallel, accelerating queries like `-links`, `-newer`, and `-size`, as well as colorized output + +- On FreeBSD, `-type w` now works to find whiteouts like the system `find` + +### Changes + +- Improved `bfs -j2` performance ([`b2ab7a1`](https://github.com/tavianator/bfs/commit/b2ab7a151fca517f4879e76e626ec85ad3de97c7)) + +- Optimized `-exec` by using `posix_spawn()` when possible, which can avoid the overhead of `fork()` ([`95fbde1`](https://github.com/tavianator/bfs/commit/95fbde17a66377b6fbe7ff1f014301dbbf09270d)) + +- `-execdir` and `-okdir` are now rejected if `$PATH` contains a relative path, matching the behaviour of GNU find ([`163baf1`](https://github.com/tavianator/bfs/commit/163baf1c9af13be0ce705b133e41e0c3d6427398)) + +- Leading whitespace is no longer accepted in integer command line arguments like `-links ' 1'` ([`e0d7dc5`](https://github.com/tavianator/bfs/commit/e0d7dc5dfd7bdaa62b6bc18e9c1cce00bbe08577)) + +### Bug Fixes + +- `-quit` and `-exit` could be ignored in the iterative deepening modes (`-S {ids,eds}`). + This is now fixed ([`670ebd9`](https://github.com/tavianator/bfs/commit/670ebd97fb431e830b1500b2e7e8013b121fb2c5)). + The bug was introduced in version 3.0.3 (commit [`5f16169`]). + +- Fixed two possible errors in sort mode (`-s`): + - Too many open files ([`710c083`](https://github.com/tavianator/bfs/commit/710c083ff02eb1cc5b8daa6778784f3d1cd3c08d)) + - Out of memory ([`76ffc8d`](https://github.com/tavianator/bfs/commit/76ffc8d30cb1160d55d855d8ac630a2b9075fbcf)) + +- Fixed handling of FreeBSD union mounts ([`3ac3bee`](https://github.com/tavianator/bfs/commit/3ac3bee7b0d9c9be693415206efa664bf4a7d4a7)) + +- Fixed `NO_COLOR` handling when it's set to the empty string ([`79aee58`](https://github.com/tavianator/bfs/commit/79aee58a4621d01c4b1e98c332775f3b87213ddb)) + +- Fixed some portability issues: + - [OpenBSD](https://github.com/tavianator/bfs/compare/ee200c07643801c8b53e5b80df704ecbf77a884e...79f1521b0e628be72bed3a648f0ae90b62fc69b8) + - [NetBSD](https://github.com/tavianator/bfs/compare/683f2c41c72efcb82ce866e3dcc311ac9bd8b66d...6435684a7d515e18247ae1b3dd9ec8681fee22d0) + - [DragonFly BSD](https://github.com/tavianator/bfs/compare/08867473e75e8e20ca76c7fb181204839e28b271...45fb1d952c3b262278a3b22e9c7d60cca19a5407) + - [Illumos](https://github.com/tavianator/bfs/compare/4010140cb748cc4f7f57b0a3d514485796c665ce...ae94cdc00136685abe61d55e1e357caaa636d785) + + 3.0.4 ----- diff --git a/src/config.h b/src/config.h index 85ad57e..519a454 100644 --- a/src/config.h +++ b/src/config.h @@ -30,7 +30,7 @@ # define BFS_COMMAND "bfs" #endif #ifndef BFS_VERSION -# define BFS_VERSION "3.0.4" +# define BFS_VERSION "3.1" #endif #ifndef BFS_HOMEPAGE # define BFS_HOMEPAGE "https://tavianator.com/projects/bfs.html" -- cgit v1.2.3 From 60fb65a75147a0d703842b412effdf8ca6ae2169 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 16 Feb 2024 08:43:44 -0500 Subject: Release 3.1.1 --- GNUmakefile | 2 +- docs/CHANGELOG.md | 12 ++++++++++++ src/config.h | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src/config.h') diff --git a/GNUmakefile b/GNUmakefile index 8b1f848..b0314d8 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -6,7 +6,7 @@ VERSION := $(shell git describe --always 2>/dev/null) endif ifndef VERSION -VERSION := 3.1 +VERSION := 3.1.1 endif ifndef OS diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index b70ed32..3255495 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,18 @@ 3.* === +3.1.1 +----- + +**February 16, 2024** + +### Changes + +- Performance and scalability improvements + +- The file count in `bfs -status` now has a thousands separator + + 3.1 --- diff --git a/src/config.h b/src/config.h index 519a454..41a8d5f 100644 --- a/src/config.h +++ b/src/config.h @@ -30,7 +30,7 @@ # define BFS_COMMAND "bfs" #endif #ifndef BFS_VERSION -# define BFS_VERSION "3.1" +# define BFS_VERSION "3.1.1" #endif #ifndef BFS_HOMEPAGE # define BFS_HOMEPAGE "https://tavianator.com/projects/bfs.html" -- cgit v1.2.3 From abcac506d025ebf6f0d003635ee5b156f549d93f Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 29 Feb 2024 11:30:54 -0500 Subject: Release 3.1.2 --- GNUmakefile | 2 +- docs/CHANGELOG.md | 22 +++++++++++++++++++--- src/config.h | 2 +- 3 files changed, 21 insertions(+), 5 deletions(-) (limited to 'src/config.h') diff --git a/GNUmakefile b/GNUmakefile index 852621e..91baf5c 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -6,7 +6,7 @@ VERSION := $(shell git describe --always 2>/dev/null) endif ifndef VERSION -VERSION := 3.1.1 +VERSION := 3.1.2 endif ifndef OS diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 3255495..9d03705 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,22 @@ 3.* === +3.1.2 +----- + +**February 29, 2024** + +### Bug fixes + +- On Linux, we now check for supported `io_uring` operations before using them, which should fix `bfs` on 5.X series kernels that support `io_uring` but not all of `openat()`/`close()`/`statx()` ([`8bc72d6`](https://github.com/tavianator/bfs/commit/8bc72d6c20c5e38783c4956c4d9fde9b3ee9140c)) + +- Fixed a test failure triggered by certain filesystem types for `/tmp` ([#131](https://github.com/tavianator/bfs/issues/131)) + +- Fixed parsing and interpretation of timezone offsets for explicit reference times used in `-*since` and `-newerXt` ([`a9f3cde`](https://github.com/tavianator/bfs/commit/a9f3cde30426b546ba6e3172e1a7951213a72049)) + +- Fixed the build on m68k ([`c749c11`](https://github.com/tavianator/bfs/commit/c749c11b04444ca40941dd2ddc5802faed148f6a)) + + 3.1.1 ----- @@ -36,7 +52,7 @@ - Leading whitespace is no longer accepted in integer command line arguments like `-links ' 1'` ([`e0d7dc5`](https://github.com/tavianator/bfs/commit/e0d7dc5dfd7bdaa62b6bc18e9c1cce00bbe08577)) -### Bug Fixes +### Bug fixes - `-quit` and `-exit` could be ignored in the iterative deepening modes (`-S {ids,eds}`). This is now fixed ([`670ebd9`](https://github.com/tavianator/bfs/commit/670ebd97fb431e830b1500b2e7e8013b121fb2c5)). @@ -62,7 +78,7 @@ **October 12, 2023** -### Bug Fixes +### Bug fixes - Fixed a segfault when reporting errors under musl ([`d40eb87`]) @@ -80,7 +96,7 @@ - Parallel depth-first search (`-S dfs`) was optimized to avoid enqueueing every file separately ([`2572273`]) -### Bug Fixes +### Bug fixes - Iterative deepening modes (`-S {ids,eds}`) were performing iterative *breadth*-first searches since `bfs` 3.0, negating any advantages they may have had over normal breadth-first search. They now do iterative *depth*-first searches as expected. diff --git a/src/config.h b/src/config.h index 41a8d5f..4697083 100644 --- a/src/config.h +++ b/src/config.h @@ -30,7 +30,7 @@ # define BFS_COMMAND "bfs" #endif #ifndef BFS_VERSION -# define BFS_VERSION "3.1.1" +# define BFS_VERSION "3.1.2" #endif #ifndef BFS_HOMEPAGE # define BFS_HOMEPAGE "https://tavianator.com/projects/bfs.html" -- cgit v1.2.3 From a1e288cb6a2482b7acc1edb92eea9d676da0729f Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 6 Mar 2024 18:55:16 -0500 Subject: Release 3.1.3 --- GNUmakefile | 2 +- docs/CHANGELOG.md | 12 ++++++++++++ src/config.h | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src/config.h') diff --git a/GNUmakefile b/GNUmakefile index 91baf5c..7dcd76f 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -6,7 +6,7 @@ VERSION := $(shell git describe --always 2>/dev/null) endif ifndef VERSION -VERSION := 3.1.2 +VERSION := 3.1.3 endif ifndef OS diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 9d03705..672c2b4 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,18 @@ 3.* === +3.1.3 +----- + +**March 6, 2024** + +### Bug fixes + +- On Linux, the `io_uring` feature probing introduced in `bfs` 3.1.2 only applied to one thread, causing all other threads to avoid using io_uring entirely. + The probe results are now copied to all threads correctly. + ([`f64f76b`](https://github.com/tavianator/bfs/commit/f64f76b55400b71e8576ed7e4a377eb5ef9576aa)) + + 3.1.2 ----- diff --git a/src/config.h b/src/config.h index 4697083..ad2e481 100644 --- a/src/config.h +++ b/src/config.h @@ -30,7 +30,7 @@ # define BFS_COMMAND "bfs" #endif #ifndef BFS_VERSION -# define BFS_VERSION "3.1.2" +# define BFS_VERSION "3.1.3" #endif #ifndef BFS_HOMEPAGE # define BFS_HOMEPAGE "https://tavianator.com/projects/bfs.html" -- cgit v1.2.3 From 10b2c56677c1708289779e4ce37a958a8cf37533 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sun, 17 Mar 2024 12:32:40 -0400 Subject: config: Don't mix [[attr]] and __attribute__((attr)) GCC and Clang don't support combining the two attribute syntaxes in arbitrary order. For now, just use the GNU style. --- src/config.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index ad2e481..45422a2 100644 --- a/src/config.h +++ b/src/config.h @@ -203,9 +203,7 @@ typedef long double max_align_t; /** * Silence warnings about unused declarations. */ -#if __has_c_attribute(maybe_unused) -# define attr_maybe_unused [[maybe_unused]] -#elif __has_attribute(unused) +#if __has_attribute(unused) # define attr_maybe_unused __attribute__((unused)) #else # define attr_maybe_unused @@ -214,9 +212,7 @@ typedef long double max_align_t; /** * Warn if a value is unused. */ -#if __has_c_attribute(nodiscard) -# define attr_nodiscard [[nodiscard]] -#elif __has_attribute(warn_unused_result) +#if __has_attribute(warn_unused_result) # define attr_nodiscard __attribute__((warn_unused_result)) #else # define attr_nodiscard -- cgit v1.2.3 From c643e1dd27e633c67589b622a06582bbb6fb5cf6 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 22 Mar 2024 14:06:04 -0400 Subject: Fix some -Wpedantic warnings --- src/config.h | 6 ++---- src/opt.c | 12 ++++++------ 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index 45422a2..892f24c 100644 --- a/src/config.h +++ b/src/config.h @@ -192,9 +192,7 @@ typedef long double max_align_t; /** * Silence warnings about switch/case fall-throughs. */ -#if __has_c_attribute(fallthrough) -# define fallthru [[fallthrough]] -#elif __has_attribute(fallthrough) +#if __has_attribute(fallthrough) # define fallthru __attribute__((fallthrough)) #else # define fallthru ((void)0) @@ -309,7 +307,7 @@ typedef long double max_align_t; * attr_d */ #define attr(...) \ - attr__(attr_##__VA_ARGS__, none, none, none, none, none, none, none, none, none) + 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. diff --git a/src/opt.c b/src/opt.c index a470d25..b74b4e1 100644 --- a/src/opt.c +++ b/src/opt.c @@ -724,7 +724,7 @@ struct visitor { visit_fn *leave; /** A visitor lookup table. */ - struct visitor_table table[]; + const struct visitor_table *table; }; /** Recursive visitor implementation. */ @@ -1331,7 +1331,7 @@ static struct bfs_expr *annotate_visit(struct bfs_opt *opt, struct bfs_expr *exp static const struct visitor annotate = { .name = "annotate", .visit = annotate_visit, - .table = { + .table = (const struct visitor_table[]) { {eval_access, annotate_access}, {eval_empty, annotate_empty}, {eval_exec, annotate_exec}, @@ -1516,7 +1516,7 @@ static struct bfs_expr *canonicalize_assoc(struct bfs_opt *opt, struct bfs_expr */ static const struct visitor canonicalize = { .name = "canonicalize", - .table = { + .table = (const struct visitor_table[]) { {eval_not, canonicalize_not}, {eval_and, canonicalize_assoc}, {eval_or, canonicalize_assoc}, @@ -1609,7 +1609,7 @@ static struct bfs_expr *reorder_andor(struct bfs_opt *opt, struct bfs_expr *expr */ static const struct visitor reorder = { .name = "reorder", - .table = { + .table = (const struct visitor_table[]) { {eval_and, reorder_andor}, {eval_or, reorder_andor}, {NULL, NULL}, @@ -1887,7 +1887,7 @@ static const struct visitor data_flow = { .enter = data_flow_enter, .visit = data_flow_visit, .leave = data_flow_leave, - .table = { + .table = (const struct visitor_table[]) { {eval_access, data_flow_access}, {eval_gid, data_flow_gid}, {eval_inum, data_flow_inum}, @@ -2103,7 +2103,7 @@ static struct bfs_expr *simplify_comma(struct bfs_opt *opt, struct bfs_expr *exp */ static const struct visitor simplify = { .name = "simplify", - .table = { + .table = (const struct visitor_table[]) { {eval_not, simplify_not}, {eval_and, simplify_and}, {eval_or, simplify_or}, -- cgit v1.2.3 From 0219441e5911b35035e927846cd8a0af77324f07 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 28 Mar 2024 15:13:04 -0400 Subject: config: Allow inlining allocator functions GCC disables inlining on custom allocator/deallocator pairs, so that they can be matched up accurately in stack traces. --- src/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/config.h') diff --git a/src/config.h b/src/config.h index 892f24c..506ad3e 100644 --- a/src/config.h +++ b/src/config.h @@ -247,7 +247,7 @@ typedef long double max_align_t; * Annotates allocator-like functions. */ #if __has_attribute(malloc) -# if __GNUC__ >= 11 +# if __GNUC__ >= 11 && !__OPTIMIZE__ // malloc(deallocator) disables inlining on GCC # define attr_malloc(...) attr_nodiscard __attribute__((malloc(__VA_ARGS__))) # else # define attr_malloc(...) attr_nodiscard __attribute__((malloc)) -- cgit v1.2.3 From c31577d102d87455f3f12086be4c0e2159fa5d35 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 8 Apr 2024 11:27:11 -0400 Subject: build: Add a separate configuration step --- .github/workflows/ci.yml | 23 +- .github/workflows/codecov.yml | 3 +- .github/workflows/codeql.yml | 1 + .gitignore | 2 + GNUmakefile | 372 ------------------------------ Makefile | 517 ++++++++++++++++++++++++++++++++++++++++++ README.md | 4 +- config/cc.sh | 12 + config/empty.c | 6 + config/libacl.c | 6 + config/libcap.c | 6 + config/liburing.c | 6 + config/oniguruma.c | 6 + config/pkg.sh | 44 ++++ config/pkgconf.sh | 64 ++++++ docs/BUILDING.md | 83 +++---- docs/USAGE.md | 2 +- src/config.h | 11 +- src/main.c | 1 + src/parse.c | 2 +- src/version.c | 6 + tests/run.sh | 2 +- tests/tests.mk | 10 +- 23 files changed, 757 insertions(+), 432 deletions(-) delete mode 100644 GNUmakefile create mode 100644 Makefile create mode 100755 config/cc.sh create mode 100644 config/empty.c create mode 100644 config/libacl.c create mode 100644 config/libcap.c create mode 100644 config/liburing.c create mode 100644 config/oniguruma.c create mode 100755 config/pkg.sh create mode 100755 config/pkgconf.sh create mode 100644 src/version.c (limited to 'src/config.h') diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 51d06fb..78aa196 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,12 +53,13 @@ jobs: run: | brew install \ bash \ - expect + expect \ + make - name: Run tests run: | jobs=$(sysctl -n hw.ncpu) - make -j$jobs distcheck + gmake -j$jobs distcheck freebsd: name: FreeBSD @@ -79,8 +80,8 @@ jobs: pkg install -y \ bash \ expect \ - gmake \ oniguruma \ + pkgconf \ sudo \ tcl-wrapper pw useradd -n action -m -G wheel -s /usr/local/bin/bash @@ -89,7 +90,7 @@ jobs: run: | chown -R action:action . - sudo -u action gmake -j$(nproc) distcheck + sudo -u action make -j$(nproc) distcheck openbsd: name: OpenBSD @@ -119,6 +120,7 @@ jobs: run: | chown -R action:action . jobs=$(sysctl -n hw.ncpu) + doas -u action gmake config doas -u action gmake -j$jobs check TEST_FLAGS="--sudo=doas --verbose=skipped" netbsd: @@ -141,8 +143,8 @@ jobs: pkg_add \ bash \ clang \ - gmake \ oniguruma \ + pkgconf \ sudo \ tcl-expect useradd -m -G wheel -g =uid action @@ -152,7 +154,8 @@ jobs: PATH="/sbin:/usr/sbin:$PATH" chown -R action:action . jobs=$(sysctl -n hw.ncpu) - sudo -u action gmake -j$jobs check CC=clang LDFLAGS="-rpath /usr/pkg/lib" TEST_FLAGS="--sudo --verbose=skipped" + sudo -u action make config CC=clang + sudo -u action make -j$jobs check TEST_FLAGS="--sudo --verbose=skipped" dragonflybsd: name: DragonFly BSD @@ -173,8 +176,8 @@ jobs: pkg install -y \ bash \ expect \ - gmake \ oniguruma \ + pkgconf \ sudo \ tcl-wrapper pw useradd -n action -m -G wheel -s /usr/local/bin/bash @@ -183,7 +186,8 @@ jobs: run: | chown -R action:action . jobs=$(sysctl -n hw.ncpu) - sudo -u action gmake -j$jobs check TEST_FLAGS="--sudo --verbose=skipped" + sudo -u action make config + sudo -u action make -j$jobs check TEST_FLAGS="--sudo --verbose=skipped" omnios: name: OmniOS @@ -215,4 +219,5 @@ jobs: PATH="/usr/xpg4/bin:$PATH" chown -R action:staff . jobs=$(getconf NPROCESSORS_ONLN) - sudo -u action gmake -j$jobs check LDFLAGS="-Wl,-rpath,/opt/ooce/lib/amd64" TEST_FLAGS="--sudo --verbose=skipped" + sudo -u action gmake config + sudo -u action gmake -j$jobs check TEST_FLAGS="--sudo --verbose=skipped" diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index d1dc351..2abe531 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -25,7 +25,8 @@ jobs: - name: Generate coverage run: | - make -j$(nproc) gcov check TEST_FLAGS="--sudo" + make config GCOV=y + make -j$(nproc) check TEST_FLAGS="--sudo" gcov -abcfpu obj/*/*.o - uses: codecov/codecov-action@v3 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index c50b266..a2c224a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -47,6 +47,7 @@ jobs: - name: Build run: | + make config make -j$(nproc) all - name: Perform CodeQL Analysis diff --git a/.gitignore b/.gitignore index 4ded7c4..84e47fc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /bin/ +/gen/ /obj/ +/distcheck-*/ diff --git a/GNUmakefile b/GNUmakefile deleted file mode 100644 index 8685ca3..0000000 --- a/GNUmakefile +++ /dev/null @@ -1,372 +0,0 @@ -# Copyright © Tavian Barnes -# SPDX-License-Identifier: 0BSD - -ifneq ($(wildcard .git),) -VERSION := $(shell git describe --always 2>/dev/null) -endif - -ifndef VERSION -VERSION := 3.1.3 -endif - -ifndef OS -OS := $(shell uname) -endif - -ifndef ARCH -ARCH := $(shell uname -m) -endif - -CC ?= gcc -INSTALL ?= install -MKDIR ?= mkdir -p -RM ?= rm -f - -export BUILDDIR ?= . -DESTDIR ?= -PREFIX ?= /usr -MANDIR ?= $(PREFIX)/share/man - -BIN := $(BUILDDIR)/bin -OBJ := $(BUILDDIR)/obj - -DEFAULT_CFLAGS := \ - -g \ - -Wall \ - -Wformat=2 \ - -Werror=implicit \ - -Wimplicit-fallthrough \ - -Wmissing-declarations \ - -Wshadow \ - -Wsign-compare \ - -Wstrict-prototypes - -CFLAGS ?= $(DEFAULT_CFLAGS) -LDFLAGS ?= -DEPFLAGS ?= -MD -MP -MF $(@:.o=.d) - -LOCAL_CPPFLAGS := \ - -D__EXTENSIONS__ \ - -D_ATFILE_SOURCE \ - -D_BSD_SOURCE \ - -D_DARWIN_C_SOURCE \ - -D_DEFAULT_SOURCE \ - -D_GNU_SOURCE \ - -D_LARGEFILE64_SOURCE \ - -D_POSIX_PTHREAD_SEMANTICS \ - -D_FILE_OFFSET_BITS=64 \ - -D_TIME_BITS=64 \ - -DBFS_VERSION=\"$(VERSION)\" - -LOCAL_CFLAGS := -std=c17 -pthread -LOCAL_LDFLAGS := -LOCAL_LDLIBS := - -ASAN := $(filter asan,$(MAKECMDGOALS)) -LSAN := $(filter lsan,$(MAKECMDGOALS)) -MSAN := $(filter msan,$(MAKECMDGOALS)) -TSAN := $(filter tsan,$(MAKECMDGOALS)) -UBSAN := $(filter ubsan,$(MAKECMDGOALS)) - -ifdef ASAN -LOCAL_CFLAGS += -fsanitize=address -SANITIZE := y -endif - -ifdef LSAN -LOCAL_CFLAGS += -fsanitize=leak -SANITIZE := y -endif - -ifdef MSAN -# msan needs all code instrumented -NOLIBS := y -LOCAL_CFLAGS += -fsanitize=memory -fsanitize-memory-track-origins -SANITIZE := y -endif - -ifdef TSAN -# tsan needs all code instrumented -NOLIBS := y -# https://github.com/google/sanitizers/issues/342 -LOCAL_CPPFLAGS += -DBFS_USE_TARGET_CLONES=0 -LOCAL_CFLAGS += -fsanitize=thread -SANITIZE := y -endif - -ifdef UBSAN -LOCAL_CFLAGS += -fsanitize=undefined -SANITIZE := y -endif - -ifdef SANITIZE -LOCAL_CFLAGS += -fno-sanitize-recover=all -endif - -ifndef NOLIBS -USE_ONIGURUMA := y -endif - -ifdef USE_ONIGURUMA -LOCAL_CPPFLAGS += -DBFS_USE_ONIGURUMA=1 - -ONIG_CONFIG := $(shell command -v onig-config 2>/dev/null) -ifdef ONIG_CONFIG -ONIG_CFLAGS := $(shell $(ONIG_CONFIG) --cflags) -ONIG_LDLIBS := $(shell $(ONIG_CONFIG) --libs) -else -ONIG_LDLIBS := -lonig -endif - -LOCAL_CFLAGS += $(ONIG_CFLAGS) -LOCAL_LDLIBS += $(ONIG_LDLIBS) -endif # USE_ONIGURUMA - -ifeq ($(OS),Linux) -ifndef NOLIBS -USE_ACL := y -USE_LIBCAP := y -USE_LIBURING := y -endif - -ifdef USE_ACL -LOCAL_LDLIBS += -lacl -else -LOCAL_CPPFLAGS += -DBFS_USE_SYS_ACL_H=0 -endif - -ifdef USE_LIBCAP -LOCAL_LDLIBS += -lcap -else -LOCAL_CPPFLAGS += -DBFS_USE_SYS_CAPABILITY_H=0 -endif - -ifdef USE_LIBURING -LOCAL_CPPFLAGS += -DBFS_USE_LIBURING=1 -LOCAL_LDLIBS += -luring -endif - -LOCAL_LDFLAGS += -Wl,--as-needed -LOCAL_LDLIBS += -lrt -endif # Linux - -ifeq ($(OS),NetBSD) -LOCAL_LDLIBS += -lutil -endif - -ifeq ($(OS),DragonFly) -LOCAL_LDLIBS += -lposix1e -endif - -ifeq ($(OS),SunOS) -LOCAL_LDLIBS += -lsocket -lnsl -endif - -ifneq ($(filter gcov,$(MAKECMDGOALS)),) -LOCAL_CFLAGS += --coverage -# gcov only intercepts fork()/exec() with -std=gnu* -LOCAL_CFLAGS := $(patsubst -std=c%,-std=gnu%,$(LOCAL_CFLAGS)) -endif - -ifneq ($(filter lint,$(MAKECMDGOALS)),) -LOCAL_CPPFLAGS += \ - -D_FORTIFY_SOURCE=3 \ - -DBFS_LINT -LOCAL_CFLAGS += -Werror -O2 -endif - -ifneq ($(filter release,$(MAKECMDGOALS)),) -LOCAL_CPPFLAGS += -DNDEBUG -CFLAGS := $(DEFAULT_CFLAGS) -O3 -flto=auto -endif - -ALL_CPPFLAGS = $(LOCAL_CPPFLAGS) $(CPPFLAGS) $(EXTRA_CPPFLAGS) -ALL_CFLAGS = $(ALL_CPPFLAGS) $(LOCAL_CFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) $(DEPFLAGS) -ALL_LDFLAGS = $(ALL_CFLAGS) $(LOCAL_LDFLAGS) $(LDFLAGS) $(EXTRA_LDFLAGS) -ALL_LDLIBS = $(LOCAL_LDLIBS) $(LDLIBS) $(EXTRA_LDLIBS) - -# Default make target -bfs: $(BIN)/bfs -.PHONY: bfs - -# Goals that are treated like flags by this makefile -FLAG_GOALS := asan lsan msan tsan ubsan gcov lint release - -# These are the remaining non-flag goals -GOALS := $(filter-out $(FLAG_GOALS),$(MAKECMDGOALS)) - -# Build the default goal if only flag goals are specified -FLAG_PREREQS := -ifndef GOALS -FLAG_PREREQS += bfs -endif - -# Make sure that "make release" builds everything, but "make release obj/src/main.o" doesn't -$(FLAG_GOALS): $(FLAG_PREREQS) - @: -.PHONY: $(FLAG_GOALS) - -all: bfs tests -.PHONY: all - -$(BIN)/%: - @$(MKDIR) $(@D) - +$(CC) $(ALL_LDFLAGS) $^ $(ALL_LDLIBS) -o $@ -ifeq ($(OS) $(SANITIZE),FreeBSD y) - elfctl -e +noaslr $@ -endif - -$(OBJ)/%.o: %.c $(OBJ)/FLAGS - @$(MKDIR) $(@D) - $(CC) $(ALL_CFLAGS) -c $< -o $@ - -# Save the full set of flags to rebuild everything when they change -$(OBJ)/FLAGS.new: - @$(MKDIR) $(@D) - @echo $(CC) : $(ALL_CFLAGS) : $(ALL_LDFLAGS) : $(ALL_LDLIBS) >$@ -.PHONY: $(OBJ)/FLAGS.new - -# Only update obj/FLAGS if obj/FLAGS.new is different -$(OBJ)/FLAGS: $(OBJ)/FLAGS.new - @test -e $@ && cmp -s $@ $< && rm $< || mv $< $@ - -# All object files except the entry point -LIBBFS := \ - $(OBJ)/src/alloc.o \ - $(OBJ)/src/bar.o \ - $(OBJ)/src/bfstd.o \ - $(OBJ)/src/bftw.o \ - $(OBJ)/src/color.o \ - $(OBJ)/src/ctx.o \ - $(OBJ)/src/diag.o \ - $(OBJ)/src/dir.o \ - $(OBJ)/src/dstring.o \ - $(OBJ)/src/eval.o \ - $(OBJ)/src/exec.o \ - $(OBJ)/src/expr.o \ - $(OBJ)/src/fsade.o \ - $(OBJ)/src/ioq.o \ - $(OBJ)/src/mtab.o \ - $(OBJ)/src/opt.o \ - $(OBJ)/src/parse.o \ - $(OBJ)/src/printf.o \ - $(OBJ)/src/pwcache.o \ - $(OBJ)/src/stat.o \ - $(OBJ)/src/thread.o \ - $(OBJ)/src/trie.o \ - $(OBJ)/src/typo.o \ - $(OBJ)/src/xregex.o \ - $(OBJ)/src/xspawn.o \ - $(OBJ)/src/xtime.o - -# The main executable -$(BIN)/bfs: $(OBJ)/src/main.o $(LIBBFS) - -# Testing utilities -TEST_UTILS := \ - $(BIN)/tests/mksock \ - $(BIN)/tests/xspawnee \ - $(BIN)/tests/xtouch - -$(BIN)/tests/mksock: $(OBJ)/tests/mksock.o $(LIBBFS) - -$(BIN)/tests/xspawnee: $(OBJ)/tests/xspawnee.o - -$(BIN)/tests/xtouch: $(OBJ)/tests/xtouch.o $(LIBBFS) - -# All test binaries -TESTS := $(BIN)/tests/units $(TEST_UTILS) - -$(BIN)/tests/units: \ - $(OBJ)/tests/alloc.o \ - $(OBJ)/tests/bfstd.o \ - $(OBJ)/tests/bit.o \ - $(OBJ)/tests/ioq.o \ - $(OBJ)/tests/main.o \ - $(OBJ)/tests/trie.o \ - $(OBJ)/tests/xspawn.o \ - $(OBJ)/tests/xtime.o \ - $(LIBBFS) - -# Build all the test binaries -tests: $(TESTS) -.PHONY: tests - -# Run the unit tests -unit-tests: $(BIN)/tests/units $(BIN)/tests/xspawnee - $< -.PHONY: unit-tests - -# The different flag combinations we check -INTEGRATIONS := default dfs ids eds j1 j2 j3 s -INTEGRATION_TESTS := $(INTEGRATIONS:%=check-%) - -check-default: $(BIN)/bfs $(TEST_UTILS) - +./tests/tests.sh --make="$(MAKE)" --bfs="$<" $(TEST_FLAGS) - -check-dfs check-ids check-eds: check-%: $(BIN)/bfs $(TEST_UTILS) - +./tests/tests.sh --make="$(MAKE)" --bfs="$< -S $*" $(TEST_FLAGS) - -check-j1 check-j2 check-j3 check-s: check-%: $(BIN)/bfs $(TEST_UTILS) - +./tests/tests.sh --make="$(MAKE)" --bfs="$< -$*" $(TEST_FLAGS) - -# Run the integration tests -integration-tests: $(INTEGRATION_TESTS) -.PHONY: integration-tests - -# Run all the tests -check: unit-tests integration-tests -.PHONY: check - -# Custom test flags for distcheck -DISTCHECK_FLAGS := -s TEST_FLAGS="--sudo --verbose=skipped" - -distcheck: - +$(MAKE) -B asan ubsan check $(DISTCHECK_FLAGS) -ifneq ($(OS),Darwin) - +$(MAKE) -B msan ubsan check CC=clang $(DISTCHECK_FLAGS) -endif - +$(MAKE) -B tsan ubsan check CC=clang $(DISTCHECK_FLAGS) -ifeq ($(OS) $(ARCH),Linux x86_64) - +$(MAKE) -B check EXTRA_CFLAGS="-m32" ONIG_CONFIG= USE_LIBURING= $(DISTCHECK_FLAGS) -endif - +$(MAKE) -B release check $(DISTCHECK_FLAGS) - +$(MAKE) -B check $(DISTCHECK_FLAGS) - +$(MAKE) check-install $(DISTCHECK_FLAGS) -.PHONY: distcheck - -clean: - $(RM) -r $(BIN) $(OBJ) -.PHONY: clean - -install: - $(MKDIR) $(DESTDIR)$(PREFIX)/bin - $(INSTALL) -m755 $(BIN)/bfs $(DESTDIR)$(PREFIX)/bin/bfs - $(MKDIR) $(DESTDIR)$(MANDIR)/man1 - $(INSTALL) -m644 docs/bfs.1 $(DESTDIR)$(MANDIR)/man1/bfs.1 - $(MKDIR) $(DESTDIR)$(PREFIX)/share/bash-completion/completions - $(INSTALL) -m644 completions/bfs.bash $(DESTDIR)$(PREFIX)/share/bash-completion/completions/bfs - $(MKDIR) $(DESTDIR)$(PREFIX)/share/zsh/site-functions - $(INSTALL) -m644 completions/bfs.zsh $(DESTDIR)$(PREFIX)/share/zsh/site-functions/_bfs - $(MKDIR) $(DESTDIR)$(PREFIX)/share/fish/vendor_completions.d - $(INSTALL) -m644 completions/bfs.fish $(DESTDIR)$(PREFIX)/share/fish/vendor_completions.d/bfs.fish -.PHONY: install - -uninstall: - $(RM) $(DESTDIR)$(PREFIX)/share/bash-completion/completions/bfs - $(RM) $(DESTDIR)$(PREFIX)/share/zsh/site-functions/_bfs - $(RM) $(DESTDIR)$(PREFIX)/share/fish/vendor_completions.d/bfs.fish - $(RM) $(DESTDIR)$(MANDIR)/man1/bfs.1 - $(RM) $(DESTDIR)$(PREFIX)/bin/bfs -.PHONY: uninstall - -check-install: - +$(MAKE) install DESTDIR=$(BUILDDIR)/pkg - +$(MAKE) uninstall DESTDIR=$(BUILDDIR)/pkg - $(BIN)/bfs $(BUILDDIR)/pkg -not -type d -print -exit 1 - $(RM) -r $(BUILDDIR)/pkg -.PHONY: check-install - -.SUFFIXES: - --include $(wildcard $(OBJ)/*/*.d) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..326ee87 --- /dev/null +++ b/Makefile @@ -0,0 +1,517 @@ +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD + +# This Makefile implements the configuration and build steps for bfs. It is +# portable to both GNU make and the BSD make implementations (how that works +# is documented below). To build bfs, run +# +# $ make config +# $ make + +# The default build target +default: bfs +.PHONY: default + +# BSD make will chdir into ${.OBJDIR} by default, unless we tell it not to +.OBJDIR: . + +# We don't use any suffix rules +.SUFFIXES: + +# GNU make has $^ for the full list of targets, while BSD make has $> and the +# long-form ${.ALLSRC}. We could write $^ $> to get them both, but that would +# break if one of them implemented support for the other. So instead, bring +# BSD's ${.ALLSRC} to GNU. +.ALLSRC ?= $^ + +# Platform detection +OS != uname +ARCH != uname -m + +# For out-of-tree builds, e.g. +# +# $ make config BUILDDIR=/path/to/build/dir +# $ make BUILDDIR=/path/to/build/dir +BUILDDIR ?= . + +# Shorthand for build subdirectories +BIN := ${BUILDDIR}/bin +GEN := ${BUILDDIR}/gen +OBJ := ${BUILDDIR}/obj + +# GNU make strips a leading ./ from target names, so do the same for BSD make +BIN := ${BIN:./%=%} +GEN := ${GEN:./%=%} +OBJ := ${OBJ:./%=%} + +# Installation paths +DESTDIR ?= +PREFIX ?= /usr +MANDIR ?= ${PREFIX}/share/man + +# Configurable executables; can be overridden with +# +# $ make config CC=clang +CC ?= cc +INSTALL ?= install +MKDIR ?= mkdir -p +PKG_CONFIG ?= pkg-config +RM ?= rm -f + +# Configurable flags + +CPPFLAGS ?= +CFLAGS ?= \ + -g \ + -Wall \ + -Wformat=2 \ + -Werror=implicit \ + -Wimplicit-fallthrough \ + -Wmissing-declarations \ + -Wshadow \ + -Wsign-compare \ + -Wstrict-prototypes +LDFLAGS ?= +LDLIBS ?= + +EXTRA_CPPFLAGS ?= +EXTRA_CFLAGS ?= +EXTRA_LDFLAGS ?= +EXTRA_LDLIBS ?= + +GIT_VERSION != test -d .git && command -v git >/dev/null 2>&1 && git describe --always --dirty || echo 3.1.3 +VERSION ?= ${GIT_VERSION} + +# Immutable flags +export BFS_CPPFLAGS= \ + -D__EXTENSIONS__ \ + -D_ATFILE_SOURCE \ + -D_BSD_SOURCE \ + -D_DARWIN_C_SOURCE \ + -D_DEFAULT_SOURCE \ + -D_GNU_SOURCE \ + -D_LARGEFILE64_SOURCE \ + -D_POSIX_PTHREAD_SEMANTICS \ + -D_FILE_OFFSET_BITS=64 \ + -D_TIME_BITS=64 +export BFS_CFLAGS= -std=c17 -pthread + +# Platform-specific system libraries +LDLIBS,DragonFly := -lposix1e +LDLIBS,Linux := -lrt +LDLIBS,NetBSD := -lutil +LDLIBS,SunOS := -lsocket -lnsl +_BFS_LDLIBS := ${LDLIBS,${OS}} +export BFS_LDLIBS=${_BFS_LDLIBS} + +# Build profiles +ASAN ?= n +LSAN ?= n +MSAN ?= n +TSAN ?= n +UBSAN ?= n +GCOV ?= n +LINT ?= n +RELEASE ?= n + +export ASAN_CFLAGS= -fsanitize=address +export LSAN_CFLAGS= -fsanitize=leak +export MSAN_CFLAGS= -fsanitize=memory -fsanitize-memory-track-origins +export UBSAN_CFLAGS= -fsanitize=undefined + +# https://github.com/google/sanitizers/issues/342 +export TSAN_CPPFLAGS= -DBFS_USE_TARGET_CLONES=0 +export TSAN_CFLAGS= -fsanitize=thread + +SAN := ${ASAN}${LSAN}${MSAN}${TSAN}${UBSAN} +export SAN_CFLAGS= -fno-sanitize-recover=all + +# MSAN and TSAN both need all code to be instrumented +export NOLIBS= ${MSAN}${TSAN} + +# gcov only intercepts fork()/exec() with -std=gnu* +export GCOV_CFLAGS= --coverage -std=gnu17 + +export LINT_CPPFLAGS= -D_FORTIFY_SOURCE=3 -DBFS_LINT +export LINT_CFLAGS= -Werror -O2 + +export RELEASE_CPPFLAGS= -DNDEBUG +export RELEASE_CFLAGS= -O3 -flto=auto + +# Auto-detected library dependencies. Can be set manually with +# +# $ make config USE_LIBURING=n USE_ONIGURUMA=y +USE_LIBACL ?= +USE_LIBCAP ?= +USE_LIBURING ?= +USE_ONIGURUMA ?= + +# Save the new value of these variables, before they potentially get overridden +# by `-include ${CONFIG}` below + +_XPREFIX := ${PREFIX} +_XMANDIR := ${MANDIR} + +_XOS := ${OS} +_XARCH := ${ARCH} + +_XCC := ${CC} +_XINSTALL := ${INSTALL} +_XMKDIR := ${MKDIR} +_XRM := ${RM} + +_XCPPFLAGS := ${CPPFLAGS} +_XCFLAGS := ${CFLAGS} +_XLDFLAGS := ${LDFLAGS} +_XLDLIBS := ${LDLIBS} + +_XUSE_LIBACL := ${USE_LIBACL} +_XUSE_LIBCAP := ${USE_LIBCAP} +_XUSE_LIBURING := ${USE_LIBURING} +_XUSE_ONIGURUMA := ${USE_ONIGURUMA} + +# GNU make supports `export VAR`, but BSD make requires `export VAR=value`. +# Sadly, GNU make gives a recursion error on `export VAR=${VAR}`. + +_BUILDDIR := ${BUILDDIR} +_PKG_CONFIG := ${PKG_CONFIG} + +export BUILDDIR=${_BUILDDIR} +export PKG_CONFIG=${_PKG_CONFIG} + +export XPREFIX=${_XPREFIX} +export XMANDIR=${_XMANDIR} + +export XOS=${_XOS} +export XARCH=${_XARCH} + +export XCC=${_XCC} +export XINSTALL=${_XINSTALL} +export XMKDIR=${_XMKDIR} +export XRM=${_XRM} + +export XCPPFLAGS=${_XCPPFLAGS} +export XCFLAGS=${_XCFLAGS} +export XLDFLAGS=${_XLDFLAGS} +export XLDLIBS=${_XLDLIBS} + +export XUSE_LIBACL=${_XUSE_LIBACL} +export XUSE_LIBCAP=${_XUSE_LIBCAP} +export XUSE_LIBURING=${_XUSE_LIBURING} +export XUSE_ONIGURUMA=${_XUSE_ONIGURUMA} + +# The configuration file generated by `make config` +CONFIG := ${GEN}/config.mk +-include ${CONFIG} + +## Configuration phase (`make config`) + +# External dependencies +PKGS := \ + ${GEN}/libacl.mk \ + ${GEN}/libcap.mk \ + ${GEN}/liburing.mk \ + ${GEN}/oniguruma.mk + +# Makefile fragments generated by `make config` +MKS := \ + ${GEN}/vars.mk \ + ${GEN}/deps.mk \ + ${GEN}/objs.mk \ + ${PKGS} + +# The configuration goal itself +config: ${MKS} + @printf 'include $${GEN}/%s\n' ${MKS:${GEN}/%=%} >${CONFIG} +.PHONY: config + +# Saves the configurable variables +${GEN}/vars.mk:: + @${XMKDIR} ${@D} + @printf 'PREFIX := %s\n' "$$XPREFIX" >$@ + @printf 'MANDIR := %s\n' "$$XMANDIR" >>$@ + @printf 'OS := %s\n' "$$XOS" >>$@ + @printf 'ARCH := %s\n' "$$XARCH" >>$@ + @printf 'CC := %s\n' "$$XCC" >>$@ + @printf 'INSTALL := %s\n' "$$XINSTALL" >>$@ + @printf 'MKDIR := %s\n' "$$XMKDIR" >>$@ + @printf 'RM := %s\n' "$$XRM" >>$@ + @printf 'CPPFLAGS := %s\n' "$$BFS_CPPFLAGS" >>$@ + @test "${TSAN}" != y || printf 'CPPFLAGS += %s\n' "$$TSAN_CPPFLAGS" >>$@ + @test "${LINT}" != y || printf 'CPPFLAGS += %s\n' "$$LINT_CPPFLAGS" >>$@ + @test "${RELEASE}" != y || printf 'CPPFLAGS += %s\n' "$$RELEASE_CPPFLAGS" >>$@ + @test -z "$$XCPPFLAGS" || printf 'CPPFLAGS += %s\n' "$$XCPPFLAGS" >>$@ + @test -z "$$EXTRA_CPPFLAGS" || printf 'CPPFLAGS += %s\n' "$$EXTRA_CPPFLAGS" >>$@ + @printf 'CFLAGS := %s\n' "$$BFS_CFLAGS" >>$@ + @test "${ASAN}" != y || printf 'CFLAGS += %s\n' "$$ASAN_CFLAGS" >>$@ + @test "${LSAN}" != y || printf 'CFLAGS += %s\n' "$$LSAN_CFLAGS" >>$@ + @test "${MSAN}" != y || printf 'CFLAGS += %s\n' "$$MSAN_CFLAGS" >>$@ + @test "${TSAN}" != y || printf 'CFLAGS += %s\n' "$$TSAN_CFLAGS" >>$@ + @test "${UBSAN}" != y || printf 'CFLAGS += %s\n' "$$UBSAN_CFLAGS" >>$@ + @case "${SAN}" in *y*) printf 'CFLAGS += %s\n' "$$SAN_CFLAGS" >>$@ ;; esac + @test "${GCOV}" != y || printf 'CFLAGS += %s\n' "$$GCOV_CFLAGS" >>$@ + @test "${LINT}" != y || printf 'CFLAGS += %s\n' "$$LINT_CFLAGS" >>$@ + @test "${RELEASE}" != y || printf 'CFLAGS += %s\n' "$$RELEASE_CFLAGS" >>$@ + @test -z "$$XCFLAGS" || printf 'CFLAGS += %s\n' "$$XCFLAGS" >>$@ + @test -z "$$EXTRA_CFLAGS" || printf 'CFLAGS += %s\n' "$$EXTRA_CFLAGS" >>$@ + @printf 'LDFLAGS := %s\n' "$$XLDFLAGS" >>$@ + @test -z "$$EXTRA_LDFLAGS" || printf 'LDFLAGS += %s\n' "$$EXTRA_LDFLAGS" >>$@ + @printf 'LDLIBS := %s\n' "$$XLDLIBS" >>$@ + @test -z "$$EXTRA_LDLIBS" || printf 'LDLIBS += %s\n' "$$EXTRA_LDLIBS" >>$@ + @test -z "$$BFS_LDLIBS" || printf 'LDLIBS += %s\n' "$$BFS_LDLIBS" >>$@ + @case "${OS}-${SAN}" in FreeBSD-*y*) printf 'POSTLINK = elfctl -e +noaslr $$@\n' >>$@ ;; esac + @cat $@ + +# Check for dependency generation support +${GEN}/deps.mk:: + @${MKDIR} ${@D} + @if config/cc.sh -MD -MP -MF /dev/null config/empty.c; then \ + echo 'DEPFLAGS = -MD -MP -MF $${@:.o=.d}'; \ + fi 2>$@.log | tee $@ + @printf -- '-include %s\n' ${OBJS:.o=.d} >>$@ + +# Lists file.o: file.c dependencies +${GEN}/objs.mk:: + @${MKDIR} ${@D} + @for obj in ${OBJS:${OBJ}/%.o=%}; do printf '$${OBJ}/%s.o: %s.c\n' "$$obj" "$$obj"; done >$@ + +# Auto-detect dependencies and their build flags +${PKGS}:: + @${MKDIR} ${@D} + @config/pkg.sh ${@:${GEN}/%.mk=%} >$@ 2>$@.log + @cat $@ + +# bfs used to have flag-like targets (`make release`, `make asan ubsan`, etc.). +# Direct users to the new configuration system. +asan lsan msan tsan ubsan gcov lint release:: + @printf 'error: `make %s` is no longer supported. ' $@ >&2 + @printf 'Use `make config %s=y` instead.\n' $$(echo $@ | tr '[a-z]' '[A-Z]') >&2 + @false + +## Build phase (`make`) + +# The main binary +bfs: ${BIN}/bfs +.PHONY: bfs + +# All binaries +BINS := \ + ${BIN}/bfs \ + ${BIN}/tests/mksock \ + ${BIN}/tests/units \ + ${BIN}/tests/xspawnee \ + ${BIN}/tests/xtouch + +all: ${BINS} +.PHONY: all + +# All object files except the entry point +LIBBFS := \ + ${OBJ}/src/alloc.o \ + ${OBJ}/src/bar.o \ + ${OBJ}/src/bfstd.o \ + ${OBJ}/src/bftw.o \ + ${OBJ}/src/color.o \ + ${OBJ}/src/ctx.o \ + ${OBJ}/src/diag.o \ + ${OBJ}/src/dir.o \ + ${OBJ}/src/dstring.o \ + ${OBJ}/src/eval.o \ + ${OBJ}/src/exec.o \ + ${OBJ}/src/expr.o \ + ${OBJ}/src/fsade.o \ + ${OBJ}/src/ioq.o \ + ${OBJ}/src/mtab.o \ + ${OBJ}/src/opt.o \ + ${OBJ}/src/parse.o \ + ${OBJ}/src/printf.o \ + ${OBJ}/src/pwcache.o \ + ${OBJ}/src/stat.o \ + ${OBJ}/src/thread.o \ + ${OBJ}/src/trie.o \ + ${OBJ}/src/typo.o \ + ${OBJ}/src/version.o \ + ${OBJ}/src/xregex.o \ + ${OBJ}/src/xspawn.o \ + ${OBJ}/src/xtime.o + +# Group relevant flags together +ALL_CFLAGS = ${CPPFLAGS} ${CFLAGS} ${DEPFLAGS} +ALL_LDFLAGS = ${CFLAGS} ${LDFLAGS} + +# The main binary +${BIN}/bfs: ${LIBBFS} ${OBJ}/src/main.o + +${BINS}: + @${MKDIR} ${@D} + +${CC} ${ALL_LDFLAGS} ${.ALLSRC} ${LDLIBS} -o $@ + ${POSTLINK} + +# All object files +OBJS := \ + ${OBJ}/src/main.o \ + ${OBJ}/tests/alloc.o \ + ${OBJ}/tests/bfstd.o \ + ${OBJ}/tests/bit.o \ + ${OBJ}/tests/ioq.o \ + ${OBJ}/tests/main.o \ + ${OBJ}/tests/mksock.o \ + ${OBJ}/tests/trie.o \ + ${OBJ}/tests/xspawn.o \ + ${OBJ}/tests/xspawnee.o \ + ${OBJ}/tests/xtime.o \ + ${OBJ}/tests/xtouch.o \ + ${LIBBFS} + +# Depend on ${CONFIG} to make sure `make config` runs first, and to rebuild when +# the configuration changes +${OBJS}: ${CONFIG} + @${MKDIR} ${@D} + ${CC} ${ALL_CFLAGS} -c ${@:${OBJ}/%.o=%.c} -o $@ + +# Save the version number to this file, but only update VERSION if it changes +${GEN}/NEWVERSION:: + @${MKDIR} ${@D} + @printf '%s\n' '${VERSION}' >$@ + +${GEN}/VERSION: ${GEN}/NEWVERSION + @test -e $@ && cmp -s $@ ${.ALLSRC} && rm ${.ALLSRC} || mv ${.ALLSRC} $@ + +# Rebuild version.c whenever the version number changes +${OBJ}/src/version.o: ${GEN}/VERSION +${OBJ}/src/version.o: CPPFLAGS := ${CPPFLAGS} -DBFS_VERSION='"${VERSION}"' + +# Clean all build products +clean:: + ${RM} -r ${BIN} ${OBJ} + +# Clean everything, including generated files +distclean: clean + ${RM} -r ${GEN} +.PHONY: distclean + +## Test phase (`make check`) + +# Unit test binaries +UTEST_BINS := \ + ${BIN}/tests/units \ + ${BIN}/tests/xspawnee + +# Integration test binaries +ITEST_BINS := \ + ${BIN}/tests/mksock \ + ${BIN}/tests/xtouch + +# Build (but don't run) test binaries +tests: ${UTEST_BINS} ${ITEST_BINS} +.PHONY: tests + +# Run all the tests +check: unit-tests integration-tests +.PHONY: check + +# Run the unit tests +unit-tests: ${UTEST_BINS} + ${BIN}/tests/units +.PHONY: unit-tests + +${BIN}/tests/units: \ + ${OBJ}/tests/alloc.o \ + ${OBJ}/tests/bfstd.o \ + ${OBJ}/tests/bit.o \ + ${OBJ}/tests/ioq.o \ + ${OBJ}/tests/main.o \ + ${OBJ}/tests/trie.o \ + ${OBJ}/tests/xspawn.o \ + ${OBJ}/tests/xtime.o \ + ${LIBBFS} + +${BIN}/tests/xspawnee: \ + ${OBJ}/tests/xspawnee.o + +# The different flag combinations we check +INTEGRATIONS := default dfs ids eds j1 j2 j3 s +INTEGRATION_TESTS := ${INTEGRATIONS:%=check-%} + +# Check just `bfs` +check-default: ${BIN}/bfs ${ITEST_BINS} + +./tests/tests.sh --make="${MAKE}" --bfs="${BIN}/bfs" ${TEST_FLAGS} + +# Check the different search strategies +check-dfs check-ids check-eds: ${BIN}/bfs ${ITEST_BINS} + +./tests/tests.sh --make="${MAKE}" --bfs="${BIN}/bfs -S ${@:check-%=%}" ${TEST_FLAGS} + +# Check various flags +check-j1 check-j2 check-j3 check-s: ${BIN}/bfs ${ITEST_BINS} + +./tests/tests.sh --make="${MAKE}" --bfs="${BIN}/bfs -${@:check-%=%}" ${TEST_FLAGS} + +# Run the integration tests +integration-tests: ${INTEGRATION_TESTS} +.PHONY: integration-tests + +${BIN}/tests/mksock: \ + ${OBJ}/tests/mksock.o \ + ${LIBBFS} + +${BIN}/tests/xtouch: \ + ${OBJ}/tests/xtouch.o \ + ${LIBBFS} + +# `make distcheck` configurations +DISTCHECKS := distcheck-asan distcheck-tsan distcheck-release + +# Don't use msan on macOS +IS_DARWIN,Darwin := y +IS_DARWIN := ${IS_DARWIN,${OS}} +DISTCHECK_MSAN, := distcheck-msan +DISTCHECKS += ${DISTCHECK_MSAN,${IS_DARWIN}} + +# Only add a 32-bit build on 64-bit Linux +DISTCHECK_M32,Linux,x86_64 := distcheck-m32 +DISTCHECKS += ${DISTCHECK_M32,${OS},${ARCH}} + +# Test multiple configurations +distcheck: ${DISTCHECKS} +.PHONY: distcheck + +# Per-distcheck configuration +DISTCHECK_CONFIG_asan := ASAN=y UBSAN=y +DISTCHECK_CONFIG_msan := MSAN=y UBSAN=y CC=clang +DISTCHECK_CONFIG_tsan := TSAN=y UBSAN=y CC=clang +DISTCHECK_CONFIG_m32 := EXTRA_CFLAGS="-m32" PKG_CONFIG_PATH=/usr/lib32/pkgconfig USE_LIBURING=n +DISTCHECK_CONFIG_release := RELEASE=y + +${DISTCHECKS}:: + +${MAKE} -rs BUILDDIR=${BUILDDIR}/$@ config ${DISTCHECK_CONFIG_${@:distcheck-%=%}} + +${MAKE} -s BUILDDIR=${BUILDDIR}/$@ check TEST_FLAGS="--sudo --verbose=skipped" + +## Packaging (`make install`) + +DEST_PREFIX := ${DESTDIR}${PREFIX} +DEST_MANDIR := ${DESTDIR}${MANDIR} + +install:: + ${MKDIR} ${DEST_PREFIX}/bin + ${INSTALL} -m755 ${BIN}/bfs ${DEST_PREFIX}/bin/bfs + ${MKDIR} ${DEST_MANDIR}/man1 + ${INSTALL} -m644 docs/bfs.1 ${DEST_MANDIR}/man1/bfs.1 + ${MKDIR} ${DEST_PREFIX}/share/bash-completion/completions + ${INSTALL} -m644 completions/bfs.bash ${DEST_PREFIX}/share/bash-completion/completions/bfs + ${MKDIR} ${DEST_PREFIX}/share/zsh/site-functions + ${INSTALL} -m644 completions/bfs.zsh ${DEST_PREFIX}/share/zsh/site-functions/_bfs + ${MKDIR} ${DEST_PREFIX}/share/fish/vendor_completions.d + ${INSTALL} -m644 completions/bfs.fish ${DEST_PREFIX}/share/fish/vendor_completions.d/bfs.fish + +uninstall:: + ${RM} ${DEST_PREFIX}/share/bash-completion/completions/bfs + ${RM} ${DEST_PREFIX}/share/zsh/site-functions/_bfs + ${RM} ${DEST_PREFIX}/share/fish/vendor_completions.d/bfs.fish + ${RM} ${DEST_MANDIR}/man1/bfs.1 + ${RM} ${DEST_PREFIX}/bin/bfs + +# Check that `make install` works and `make uninstall` removes everything +check-install:: + +${MAKE} install DESTDIR=${BUILDDIR}/pkg + +${MAKE} uninstall DESTDIR=${BUILDDIR}/pkg + ${BIN}/bfs ${BUILDDIR}/pkg -not -type d -print -exit 1 + ${RM} -r ${BUILDDIR}/pkg diff --git a/README.md b/README.md index 17226fd..b95c16b 100644 --- a/README.md +++ b/README.md @@ -333,6 +333,7 @@ Once you have the dependencies, you can build bfs. Download one of the [releases](https://github.com/tavianator/bfs/releases) or clone the [git repo](https://github.com/tavianator/bfs). Then run + $ make config $ make This will build the `./bin/bfs` binary. @@ -342,7 +343,8 @@ Run the test suite to make sure it works correctly: If you're interested in speed, you may want to build the release version instead: - $ make release + $ make config RELEASE=y + $ make Finally, if you want to install it globally, run diff --git a/config/cc.sh b/config/cc.sh new file mode 100755 index 0000000..04b142a --- /dev/null +++ b/config/cc.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD + +# Run the compiler and check if it succeeded + +printf '$ %s' "$XCC" >&2 +printf ' %q' "$@" >&2 +printf ' -o /dev/null\n' >&2 + +$XCC "$@" -o /dev/null diff --git a/config/empty.c b/config/empty.c new file mode 100644 index 0000000..4fa9a5b --- /dev/null +++ b/config/empty.c @@ -0,0 +1,6 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +int main(void) { + return 0; +} diff --git a/config/libacl.c b/config/libacl.c new file mode 100644 index 0000000..877cb69 --- /dev/null +++ b/config/libacl.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + acl_free(0); + return 0; +} diff --git a/config/libcap.c b/config/libcap.c new file mode 100644 index 0000000..64188ac --- /dev/null +++ b/config/libcap.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + cap_free(0); + return 0; +} diff --git a/config/liburing.c b/config/liburing.c new file mode 100644 index 0000000..456059c --- /dev/null +++ b/config/liburing.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + io_uring_free_probe(0); + return 0; +} diff --git a/config/oniguruma.c b/config/oniguruma.c new file mode 100644 index 0000000..b834fac --- /dev/null +++ b/config/oniguruma.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + onig_free(0); + return 0; +} diff --git a/config/pkg.sh b/config/pkg.sh new file mode 100755 index 0000000..6335b4b --- /dev/null +++ b/config/pkg.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD + +# pkg-config wrapper that outputs a makefile fragment + +set -eu + +NAME="${1^^}" +declare -n XUSE="XUSE_$NAME" + +if [ "$XUSE" ]; then + USE="$XUSE" +elif [[ "$NOLIBS" == *y* ]]; then + USE=n +elif config/pkgconf.sh "$1"; then + USE=y +else + USE=n +fi + +printf '%s := %s\n' "USE_$NAME" "$USE" + +if [ "$USE" = y ]; then + printf 'CPPFLAGS += -DBFS_USE_%s=1\n' "$NAME" + + CFLAGS=$(config/pkgconf.sh --cflags "$1") + if [ "$CFLAGS" ]; then + printf 'CFLAGS += %s\n' "$CFLAGS" + fi + + LDFLAGS=$(config/pkgconf.sh --ldflags "$1") + if [ "$LDFLAGS" ]; then + printf 'LDFLAGS += %s\n' "$LDFLAGS" + fi + + LDLIBS=$(config/pkgconf.sh --ldlibs "$1") + if [ "$LDLIBS" ]; then + printf 'LDLIBS += %s\n' "$LDLIBS" + fi +else + printf 'CPPFLAGS += -DBFS_USE_%s=0\n' "$NAME" +fi diff --git a/config/pkgconf.sh b/config/pkgconf.sh new file mode 100755 index 0000000..070fad6 --- /dev/null +++ b/config/pkgconf.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash + +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD + +# pkg-config wrapper with hardcoded fallbacks + +set -eu + +MODE= +if [[ "$1" == --* ]]; then + MODE="$1" + shift +fi + +if command -v "${PKG_CONFIG:-}" &>/dev/null; then + case "$MODE" in + --cflags) + "$PKG_CONFIG" --cflags "$@" + ;; + --ldflags) + "$PKG_CONFIG" --libs-only-L --libs-only-other "$@" + ;; + --ldlibs) + "$PKG_CONFIG" --libs-only-l "$@" + ;; + "") + "$PKG_CONFIG" "$@" + ;; + esac +else + for lib; do + case "$lib" in + libacl) + LDLIB=-lacl + ;; + libcap) + LDLIB=-lcap + ;; + liburing) + LDLIB=-luring + ;; + oniguruma) + LDLIB=-lonig + ;; + *) + printf 'error: Unknown package %s\n' "$lib" >&2 + exit 1 + esac + + case "$MODE" in + --ldlibs) + printf ' %s' "$LDLIB" + ;; + "") + config/cc.sh "config/$lib.c" "$LDLIB" || exit $? + ;; + esac + done + + if [ "$MODE" = "--ldlibs" ]; then + printf '\n' + fi +fi diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 7eb3a37..abf6185 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -7,9 +7,10 @@ Compiling `bfs` uses [GNU Make](https://www.gnu.org/software/make/) as its build system. A simple invocation of + $ make config $ make -should build `bfs` successfully, with no additional steps necessary. +should build `bfs` successfully. As usual with `make`, you can run a [parallel build](https://www.gnu.org/software/make/manual/html_node/Parallel.html) with `-j`. For example, to use all your cores, run `make -j$(nproc)`. @@ -17,25 +18,28 @@ For example, to use all your cores, run `make -j$(nproc)`. | Command | Description | |------------------|---------------------------------------------------------------| +| `make config` | Configures the build system | | `make` | Builds just the `bfs` binary | | `make all` | Builds everything, including the tests (but doesn't run them) | | `make check` | Builds everything, and runs the tests | | `make install` | Installs `bfs` (with man page, shell completions, etc.) | | `make uninstall` | Uninstalls `bfs` | +| `make clean` | Delete the build products | +| `make mrclean` | Delete all generated files, including the build configuration | -### Flag-like targets +### Build profiles -The build system provides a few shorthand targets for handy configurations: +The configuration system provides a few shorthand flags for handy configurations: -| Command | Description | -|----------------|-------------------------------------------------------------| -| `make release` | Build `bfs` with optimizations, LTO, and without assertions | -| `make asan` | Enable [AddressSanitizer] | -| `make lsan` | Enable [LeakSanitizer] | -| `make msan` | Enable [MemorySanitizer] | -| `make tsan` | Enable [ThreadSanitizer] | -| `make ubsan` | Enable [UndefinedBehaviorSanitizer] | -| `make gcov` | Enable [code coverage] | +| Command | Description | +|-------------------------|-------------------------------------------------------------| +| `make config RELEASE=y` | Build `bfs` with optimizations, LTO, and without assertions | +| `make config ASAN=y` | Enable [AddressSanitizer] | +| `make config LSAN=y` | Enable [LeakSanitizer] | +| `make config MSAN=y` | Enable [MemorySanitizer] | +| `make config TSAN=y` | Enable [ThreadSanitizer] | +| `make config UBSAN=y` | Enable [UndefinedBehaviorSanitizer] | +| `make config GCOV=y` | Enable [code coverage] | [AddressSanitizer]: https://github.com/google/sanitizers/wiki/AddressSanitizer [LeakSanitizer]: https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer#stand-alone-mode @@ -44,38 +48,38 @@ The build system provides a few shorthand targets for handy configurations: [UndefinedBehaviorSanitizer]: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html [code coverage]: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html -You can combine multiple flags and other targets (e.g. `make asan ubsan check`), but not all of them will work together. +You can combine multiple profiles (e.g. `make config ASAN=y UBSAN=y`), but not all of them will work together. ### Flags -Other flags are controlled with `make` variables and/or environment variables. -Here are some of the common ones; check the [`GNUmakefile`](/GNUmakefile) for more. - -| Flag | Description | -|----------------------------------|---------------------------------------------| -| `CC` | The C compiler to use, e.g. `make CC=clang` | -| `CFLAGS`
`EXTRA_CFLAGS` | Override/add to the default compiler flags | -| `LDFLAGS`
`EXTRA_LDFLAGS` | Override/add to the linker flags | -| `USE_ACL`
`USE_LIBCAP`
... | Enable/disable [optional dependencies] | -| `TEST_FLAGS` | `tests.sh` flags for `make check` | -| `BUILDDIR` | The build output directory (default: `.`) | -| `DESTDIR` | The root directory for `make install` | -| `PREFIX` | The installation prefix (default: `/usr`) | -| `MANDIR` | The man page installation directory | +Other flags can be specified on the `make config` command line or in the environment. +Here are some of the common ones; check the [`Makefile`](/Makefile) for more. + +| Flag | Description | +|----------------------------------|----------------------------------------------------| +| `CC` | The C compiler to use, e.g. `make config CC=clang` | +| `CFLAGS`
`EXTRA_CFLAGS` | Override/add to the default compiler flags | +| `LDFLAGS`
`EXTRA_LDFLAGS` | Override/add to the linker flags | +| `USE_ACL`
`USE_LIBCAP`
... | Enable/disable [optional dependencies] | +| `TEST_FLAGS` | `tests.sh` flags for `make check` | +| `BUILDDIR` | The build output directory (default: `.`) | +| `DESTDIR` | The root directory for `make install` | +| `PREFIX` | The installation prefix (default: `/usr`) | +| `MANDIR` | The man page installation directory | [optional dependencies]: #dependencies ### Dependencies `bfs` depends on some system libraries for some of its features. -These dependencies are optional, and can be turned off at build time if necessary by setting the appropriate variable to the empty string (e.g. `make USE_ONIGURUMA=`). +These dependencies are optional, and can be turned off in `make config` if necessary by setting the appropriate variable to `n` (e.g. `make config USE_ONIGURUMA=n`). -| Dependency | Platforms | `make` flag | -|-------------|------------|-----------------| -| [acl] | Linux only | `USE_ACL` | -| [libcap] | Linux only | `USE_LIBCAP` | -| [liburing] | Linux only | `USE_LIBURING` | -| [Oniguruma] | All | `USE_ONIGURUMA` | +| Dependency | Platforms | `make config` flag | +|-------------|------------|--------------------| +| [acl] | Linux only | `USE_ACL` | +| [libcap] | Linux only | `USE_LIBCAP` | +| [liburing] | Linux only | `USE_LIBURING` | +| [Oniguruma] | All | `USE_ONIGURUMA` | [acl]: https://savannah.nongnu.org/projects/acl [libcap]: https://sites.google.com/site/fullycapable/ @@ -84,21 +88,22 @@ These dependencies are optional, and can be turned off at build time if necessar ### Dependency tracking -The build system automatically tracks header dependencies with the `-M` family of compiler options (see `DEPFLAGS` in the [`GNUmakefile`](/GNUmakefile)). +The build system automatically tracks header dependencies with the `-M` family of compiler options (see `DEPFLAGS` in the [`Makefile`](/Makefile)). So if you edit a header file, `make` will rebuild the necessary object files ensuring they don't go out of sync. +We also add a dependency on the current configuration, so you can change configurations and rebuild without having to `make clean`. + We go one step further than most build systems by tracking the flags that were used for the previous compilation. That means you can change configurations without having to `make clean`. For example, + $ make config + $ make + $ make config RELEASE=y $ make - $ make release will build the project in debug mode and then rebuild it in release mode. -A side effect of this may be surprising: `make check` by itself will rebuild the project in the default configuration. -To test a different configuration, you'll have to repeat it (e.g. `make release check`). - Testing ------- diff --git a/docs/USAGE.md b/docs/USAGE.md index 071c95b..70f8475 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -7,8 +7,8 @@ When invoked with no arguments, `bfs` will list everything under the current dir ```console $ bfs . -./GNUmakefile ./LICENSE +./Makefile ./README.md ./completions ./docs diff --git a/src/config.h b/src/config.h index 506ad3e..2eff1fc 100644 --- a/src/config.h +++ b/src/config.h @@ -29,13 +29,14 @@ #ifndef BFS_COMMAND # define BFS_COMMAND "bfs" #endif -#ifndef BFS_VERSION -# define BFS_VERSION "3.1.3" -#endif #ifndef BFS_HOMEPAGE # define BFS_HOMEPAGE "https://tavianator.com/projects/bfs.html" #endif +// This is a symbol instead of a literal so we don't have to rebuild everything +// when the version number changes +extern const char bfs_version[]; + // Check for system headers #ifdef __has_include @@ -97,10 +98,10 @@ # define BFS_USE_PATHS_H BFS_HAS_PATHS_H #endif #ifndef BFS_USE_SYS_ACL_H -# define BFS_USE_SYS_ACL_H (BFS_HAS_SYS_ACL_H && !__illumos__) +# define BFS_USE_SYS_ACL_H (BFS_HAS_SYS_ACL_H && !__illumos__ && (!__linux__ || BFS_USE_LIBACL)) #endif #ifndef BFS_USE_SYS_CAPABILITY_H -# define BFS_USE_SYS_CAPABILITY_H (BFS_HAS_SYS_CAPABILITY_H && !__FreeBSD__) +# define BFS_USE_SYS_CAPABILITY_H (BFS_HAS_SYS_CAPABILITY_H && !__FreeBSD__ && (!__linux__ || BFS_USE_LIBCAP)) #endif #ifndef BFS_USE_SYS_EXTATTR_H # define BFS_USE_SYS_EXTATTR_H (BFS_HAS_SYS_EXTATTR_H && !__DragonFly__) diff --git a/src/main.c b/src/main.c index e120f03..b4d65ce 100644 --- a/src/main.c +++ b/src/main.c @@ -40,6 +40,7 @@ * - thread.h (multi-threading) * - trie.[ch] (a trie set/map implementation) * - typo.[ch] (fuzzy matching for typos) + * - version.c (defines the version number) * - xregex.[ch] (regular expression support) * - xspawn.[ch] (spawns processes) * - xtime.[ch] (date/time handling utilities) diff --git a/src/parse.c b/src/parse.c index 2dfcab2..38ebf3f 100644 --- a/src/parse.c +++ b/src/parse.c @@ -2909,7 +2909,7 @@ static struct bfs_expr *parse_help(struct bfs_parser *parser, int arg1, int arg2 * "Parse" -version. */ static struct bfs_expr *parse_version(struct bfs_parser *parser, int arg1, int arg2) { - cfprintf(parser->ctx->cout, "${ex}%s${rs} ${bld}%s${rs}\n\n", BFS_COMMAND, BFS_VERSION); + cfprintf(parser->ctx->cout, "${ex}%s${rs} ${bld}%s${rs}\n\n", BFS_COMMAND, bfs_version); printf("%s\n", BFS_HOMEPAGE); diff --git a/src/version.c b/src/version.c new file mode 100644 index 0000000..736f3d5 --- /dev/null +++ b/src/version.c @@ -0,0 +1,6 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include "config.h" + +const char bfs_version[] = BFS_VERSION; diff --git a/tests/run.sh b/tests/run.sh index 720515d..ab1ed6d 100644 --- a/tests/run.sh +++ b/tests/run.sh @@ -156,7 +156,7 @@ comake() { -f "$TESTS/tests.mk" \ DONE=$DONE_PIPE \ READY=$READY_PIPE \ - "${TEST_CASES[@]/#/tests/}" \ + "${!TEST_CASES[@]}" \ /dev/null } diff --git a/tests/tests.mk b/tests/tests.mk index 5bf4f6c..035ca79 100644 --- a/tests/tests.mk +++ b/tests/tests.mk @@ -1,7 +1,13 @@ # Copyright © Tavian Barnes # SPDX-License-Identifier: 0BSD -# GNU makefile that exposes make's job control to tests.sh +# Makefile that exposes make's job control to tests.sh -tests/%: +# BSD make will chdir into ${.OBJDIR} by default, unless we tell it not to +.OBJDIR: . + +# Turn off implicit rules +.SUFFIXES: + +.DEFAULT:: bash -c 'printf . >&$(READY) && read -r -N1 -u$(DONE)' -- cgit v1.2.3 From c66379749f423413913b406609dfe9311ba6e555 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 18 Apr 2024 14:53:56 -0400 Subject: Rename config.h to prelude.h --- src/alloc.c | 2 +- src/alloc.h | 2 +- src/bar.c | 2 +- src/bfstd.c | 2 +- src/bfstd.h | 2 +- src/bftw.c | 2 +- src/bit.h | 2 +- src/color.c | 2 +- src/color.h | 2 +- src/config.h | 377 --------------------------------------------------------- src/ctx.h | 2 +- src/diag.c | 2 +- src/diag.h | 2 +- src/dir.c | 2 +- src/dstring.c | 2 +- src/dstring.h | 2 +- src/eval.c | 2 +- src/eval.h | 2 +- src/exec.c | 2 +- src/expr.h | 2 +- src/fsade.c | 2 +- src/fsade.h | 2 +- src/ioq.c | 2 +- src/ioq.h | 2 +- src/main.c | 4 +- src/mtab.c | 2 +- src/mtab.h | 2 +- src/opt.c | 2 +- src/parse.c | 2 +- src/prelude.h | 377 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/printf.c | 2 +- src/pwcache.c | 2 +- src/sanity.h | 2 +- src/stat.c | 2 +- src/stat.h | 2 +- src/thread.c | 2 +- src/thread.h | 2 +- src/trie.c | 2 +- src/xregex.c | 2 +- src/xspawn.c | 2 +- src/xspawn.h | 2 +- src/xtime.c | 2 +- tests/alloc.c | 2 +- tests/bfstd.c | 2 +- tests/bit.c | 2 +- tests/ioq.c | 2 +- tests/main.c | 2 +- tests/tests.h | 2 +- tests/trie.c | 2 +- tests/xspawn.c | 2 +- tests/xtime.c | 2 +- tests/xtouch.c | 2 +- 52 files changed, 428 insertions(+), 428 deletions(-) delete mode 100644 src/config.h create mode 100644 src/prelude.h (limited to 'src/config.h') diff --git a/src/alloc.c b/src/alloc.c index b65d0c5..ec8608f 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -1,9 +1,9 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "alloc.h" #include "bit.h" -#include "config.h" #include "diag.h" #include "sanity.h" #include diff --git a/src/alloc.h b/src/alloc.h index ae055bc..095134a 100644 --- a/src/alloc.h +++ b/src/alloc.h @@ -8,7 +8,7 @@ #ifndef BFS_ALLOC_H #define BFS_ALLOC_H -#include "config.h" +#include "prelude.h" #include #include #include diff --git a/src/bar.c b/src/bar.c index 8ab4112..184d9a0 100644 --- a/src/bar.c +++ b/src/bar.c @@ -1,11 +1,11 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "bar.h" #include "atomic.h" #include "bfstd.h" #include "bit.h" -#include "config.h" #include "dstring.h" #include #include diff --git a/src/bfstd.c b/src/bfstd.c index 2499f00..e1b4804 100644 --- a/src/bfstd.c +++ b/src/bfstd.c @@ -1,9 +1,9 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "bfstd.h" #include "bit.h" -#include "config.h" #include "diag.h" #include "sanity.h" #include "thread.h" diff --git a/src/bfstd.h b/src/bfstd.h index fc22971..42f5d5b 100644 --- a/src/bfstd.h +++ b/src/bfstd.h @@ -8,7 +8,7 @@ #ifndef BFS_BFSTD_H #define BFS_BFSTD_H -#include "config.h" +#include "prelude.h" #include "sanity.h" #include diff --git a/src/bftw.c b/src/bftw.c index 6130c44..c4d3c17 100644 --- a/src/bftw.c +++ b/src/bftw.c @@ -18,10 +18,10 @@ * various helper functions to take fewer parameters. */ +#include "prelude.h" #include "bftw.h" #include "alloc.h" #include "bfstd.h" -#include "config.h" #include "diag.h" #include "dir.h" #include "dstring.h" diff --git a/src/bit.h b/src/bit.h index 69df21e..17cfbcf 100644 --- a/src/bit.h +++ b/src/bit.h @@ -8,7 +8,7 @@ #ifndef BFS_BIT_H #define BFS_BIT_H -#include "config.h" +#include "prelude.h" #include #include diff --git a/src/color.c b/src/color.c index 8c32a68..f004bf2 100644 --- a/src/color.c +++ b/src/color.c @@ -1,11 +1,11 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "color.h" #include "alloc.h" #include "bfstd.h" #include "bftw.h" -#include "config.h" #include "diag.h" #include "dir.h" #include "dstring.h" diff --git a/src/color.h b/src/color.h index e3e7973..3278cd6 100644 --- a/src/color.h +++ b/src/color.h @@ -8,7 +8,7 @@ #ifndef BFS_COLOR_H #define BFS_COLOR_H -#include "config.h" +#include "prelude.h" #include "dstring.h" #include diff --git a/src/config.h b/src/config.h deleted file mode 100644 index 2eff1fc..0000000 --- a/src/config.h +++ /dev/null @@ -1,377 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -/** - * Configuration and feature/platform detection. - */ - -#ifndef BFS_CONFIG_H -#define BFS_CONFIG_H - -// Possible __STDC_VERSION__ values - -#define C95 199409L -#define C99 199901L -#define C11 201112L -#define C17 201710L -#define C23 202311L - -#include - -#if __STDC_VERSION__ < C23 -# include -# include -# include -#endif - -// bfs packaging configuration - -#ifndef BFS_COMMAND -# define BFS_COMMAND "bfs" -#endif -#ifndef BFS_HOMEPAGE -# define BFS_HOMEPAGE "https://tavianator.com/projects/bfs.html" -#endif - -// This is a symbol instead of a literal so we don't have to rebuild everything -// when the version number changes -extern const char bfs_version[]; - -// Check for system headers - -#ifdef __has_include - -#if __has_include() -# define BFS_HAS_MNTENT_H true -#endif -#if __has_include() -# define BFS_HAS_PATHS_H true -#endif -#if __has_include() -# define BFS_HAS_SYS_ACL_H true -#endif -#if __has_include() -# define BFS_HAS_SYS_CAPABILITY_H true -#endif -#if __has_include() -# define BFS_HAS_SYS_EXTATTR_H true -#endif -#if __has_include() -# define BFS_HAS_SYS_MKDEV_H true -#endif -#if __has_include() -# define BFS_HAS_SYS_PARAM_H true -#endif -#if __has_include() -# define BFS_HAS_SYS_SYSMACROS_H true -#endif -#if __has_include() -# define BFS_HAS_SYS_XATTR_H true -#endif -#if __has_include() -# define BFS_HAS_THREADS_H true -#endif -#if __has_include() -# define BFS_HAS_UTIL_H true -#endif - -#else // !__has_include - -#define BFS_HAS_MNTENT_H __GLIBC__ -#define BFS_HAS_PATHS_H true -#define BFS_HAS_SYS_ACL_H true -#define BFS_HAS_SYS_CAPABILITY_H __linux__ -#define BFS_HAS_SYS_EXTATTR_H __FreeBSD__ -#define BFS_HAS_SYS_MKDEV_H false -#define BFS_HAS_SYS_PARAM_H true -#define BFS_HAS_SYS_SYSMACROS_H __GLIBC__ -#define BFS_HAS_SYS_XATTR_H __linux__ -#define BFS_HAS_THREADS_H (!__STDC_NO_THREADS__) -#define BFS_HAS_UTIL_H __NetBSD__ - -#endif // !__has_include - -#ifndef BFS_USE_MNTENT_H -# define BFS_USE_MNTENT_H BFS_HAS_MNTENT_H -#endif -#ifndef BFS_USE_PATHS_H -# define BFS_USE_PATHS_H BFS_HAS_PATHS_H -#endif -#ifndef BFS_USE_SYS_ACL_H -# define BFS_USE_SYS_ACL_H (BFS_HAS_SYS_ACL_H && !__illumos__ && (!__linux__ || BFS_USE_LIBACL)) -#endif -#ifndef BFS_USE_SYS_CAPABILITY_H -# define BFS_USE_SYS_CAPABILITY_H (BFS_HAS_SYS_CAPABILITY_H && !__FreeBSD__ && (!__linux__ || BFS_USE_LIBCAP)) -#endif -#ifndef BFS_USE_SYS_EXTATTR_H -# define BFS_USE_SYS_EXTATTR_H (BFS_HAS_SYS_EXTATTR_H && !__DragonFly__) -#endif -#ifndef BFS_USE_SYS_MKDEV_H -# define BFS_USE_SYS_MKDEV_H BFS_HAS_SYS_MKDEV_H -#endif -#ifndef BFS_USE_SYS_PARAM_H -# define BFS_USE_SYS_PARAM_H BFS_HAS_SYS_PARAM_H -#endif -#ifndef BFS_USE_SYS_SYSMACROS_H -# define BFS_USE_SYS_SYSMACROS_H BFS_HAS_SYS_SYSMACROS_H -#endif -#ifndef BFS_USE_SYS_XATTR_H -# define BFS_USE_SYS_XATTR_H BFS_HAS_SYS_XATTR_H -#endif -#ifndef BFS_USE_THREADS_H -# define BFS_USE_THREADS_H BFS_HAS_THREADS_H -#endif -#ifndef BFS_USE_UTIL_H -# define BFS_USE_UTIL_H BFS_HAS_UTIL_H -#endif - -// Stub out feature detection on old/incompatible compilers - -#ifndef __has_feature -# define __has_feature(feat) false -#endif - -#ifndef __has_c_attribute -# define __has_c_attribute(attr) false -#endif - -#ifndef __has_attribute -# define __has_attribute(attr) false -#endif - -// Platform detection - -// Get the definition of BSD if available -#if BFS_USE_SYS_PARAM_H -# include -#endif - -#ifndef __GLIBC_PREREQ -# define __GLIBC_PREREQ(maj, min) false -#endif - -#ifndef __NetBSD_Prereq__ -# define __NetBSD_Prereq__(maj, min, patch) false -#endif - -// Fundamental utilities - -/** - * Get the length of an array. - */ -#define countof(array) (sizeof(array) / sizeof(0[array])) - -/** - * False sharing/destructive interference/largest cache line size. - */ -#ifdef __GCC_DESTRUCTIVE_SIZE -# define FALSE_SHARING_SIZE __GCC_DESTRUCTIVE_SIZE -#else -# define FALSE_SHARING_SIZE 64 -#endif - -/** - * True sharing/constructive interference/smallest cache line size. - */ -#ifdef __GCC_CONSTRUCTIVE_SIZE -# define TRUE_SHARING_SIZE __GCC_CONSTRUCTIVE_SIZE -#else -# define TRUE_SHARING_SIZE 64 -#endif - -/** - * Alignment specifier that avoids false sharing. - */ -#define cache_align alignas(FALSE_SHARING_SIZE) - -#if __COSMOPOLITAN__ -typedef long double max_align_t; -#endif - -// Wrappers for attributes - -/** - * Silence warnings about switch/case fall-throughs. - */ -#if __has_attribute(fallthrough) -# define fallthru __attribute__((fallthrough)) -#else -# define fallthru ((void)0) -#endif - -/** - * Silence warnings about unused declarations. - */ -#if __has_attribute(unused) -# define attr_maybe_unused __attribute__((unused)) -#else -# define attr_maybe_unused -#endif - -/** - * Warn if a value is unused. - */ -#if __has_attribute(warn_unused_result) -# define attr_nodiscard __attribute__((warn_unused_result)) -#else -# define attr_nodiscard -#endif - -/** - * Hint to avoid inlining a function. - */ -#if __has_attribute(noinline) -# define attr_noinline __attribute__((noinline)) -#else -# define attr_noinline -#endif - -/** - * Hint that a function is unlikely to be called. - */ -#if __has_attribute(cold) -# define attr_cold attr_noinline __attribute__((cold)) -#else -# define attr_cold attr_noinline -#endif - -/** - * Adds compiler warnings for bad printf()-style function calls, if supported. - */ -#if __has_attribute(format) -# define attr_printf(fmt, args) __attribute__((format(printf, fmt, args))) -#else -# define attr_printf(fmt, args) -#endif - -/** - * Annotates allocator-like functions. - */ -#if __has_attribute(malloc) -# if __GNUC__ >= 11 && !__OPTIMIZE__ // malloc(deallocator) disables inlining on GCC -# define attr_malloc(...) attr_nodiscard __attribute__((malloc(__VA_ARGS__))) -# else -# define attr_malloc(...) attr_nodiscard __attribute__((malloc)) -# endif -#else -# define attr_malloc(...) attr_nodiscard -#endif - -/** - * Specifies that a function returns allocations with a given alignment. - */ -#if __has_attribute(alloc_align) -# define attr_alloc_align(param) __attribute__((alloc_align(param))) -#else -# define attr_alloc_align(param) -#endif - -/** - * Specifies that a function returns allocations with a given size. - */ -#if __has_attribute(alloc_size) -# define attr_alloc_size(...) __attribute__((alloc_size(__VA_ARGS__))) -#else -# define attr_alloc_size(...) -#endif - -/** - * Shorthand for attr_alloc_align() and attr_alloc_size(). - */ -#define attr_aligned_alloc(align, ...) \ - attr_alloc_align(align) \ - attr_alloc_size(__VA_ARGS__) - -/** - * Check if function multiversioning via GNU indirect functions (ifunc) is supported. - */ -#ifndef BFS_USE_TARGET_CLONES -# if __has_attribute(target_clones) && (__GLIBC__ || __FreeBSD__) -# define BFS_USE_TARGET_CLONES true -# endif -#endif - -/** - * Apply the target_clones attribute, if available. - */ -#if BFS_USE_TARGET_CLONES -# define attr_target_clones(...) __attribute__((target_clones(__VA_ARGS__))) -#else -# 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/ctx.h b/src/ctx.h index e14db21..fc3020c 100644 --- a/src/ctx.h +++ b/src/ctx.h @@ -8,9 +8,9 @@ #ifndef BFS_CTX_H #define BFS_CTX_H +#include "prelude.h" #include "alloc.h" #include "bftw.h" -#include "config.h" #include "diag.h" #include "expr.h" #include "trie.h" diff --git a/src/diag.c b/src/diag.c index cb27b92..deb6f26 100644 --- a/src/diag.c +++ b/src/diag.c @@ -1,11 +1,11 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "diag.h" #include "alloc.h" #include "bfstd.h" #include "color.h" -#include "config.h" #include "ctx.h" #include "dstring.h" #include "expr.h" diff --git a/src/diag.h b/src/diag.h index 4054c48..2b13609 100644 --- a/src/diag.h +++ b/src/diag.h @@ -8,7 +8,7 @@ #ifndef BFS_DIAG_H #define BFS_DIAG_H -#include "config.h" +#include "prelude.h" #include /** diff --git a/src/dir.c b/src/dir.c index 98518f2..53c9be3 100644 --- a/src/dir.c +++ b/src/dir.c @@ -1,10 +1,10 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "dir.h" #include "alloc.h" #include "bfstd.h" -#include "config.h" #include "diag.h" #include "sanity.h" #include "trie.h" diff --git a/src/dstring.c b/src/dstring.c index 10b0fad..913dda8 100644 --- a/src/dstring.c +++ b/src/dstring.c @@ -1,10 +1,10 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "dstring.h" #include "alloc.h" #include "bit.h" -#include "config.h" #include "diag.h" #include #include diff --git a/src/dstring.h b/src/dstring.h index 6006199..9ea7eb9 100644 --- a/src/dstring.h +++ b/src/dstring.h @@ -8,8 +8,8 @@ #ifndef BFS_DSTRING_H #define BFS_DSTRING_H +#include "prelude.h" #include "bfstd.h" -#include "config.h" #include #include diff --git a/src/eval.c b/src/eval.c index d0112c2..b103912 100644 --- a/src/eval.c +++ b/src/eval.c @@ -5,12 +5,12 @@ * Implementation of all the primary expressions. */ +#include "prelude.h" #include "eval.h" #include "bar.h" #include "bfstd.h" #include "bftw.h" #include "color.h" -#include "config.h" #include "ctx.h" #include "diag.h" #include "dir.h" diff --git a/src/eval.h b/src/eval.h index ae43628..4dd7996 100644 --- a/src/eval.h +++ b/src/eval.h @@ -9,7 +9,7 @@ #ifndef BFS_EVAL_H #define BFS_EVAL_H -#include "config.h" +#include "prelude.h" struct bfs_ctx; struct bfs_expr; diff --git a/src/exec.c b/src/exec.c index 60bfd28..e782d49 100644 --- a/src/exec.c +++ b/src/exec.c @@ -1,12 +1,12 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "exec.h" #include "alloc.h" #include "bfstd.h" #include "bftw.h" #include "color.h" -#include "config.h" #include "ctx.h" #include "diag.h" #include "dstring.h" diff --git a/src/expr.h b/src/expr.h index 75cb5fd..7bcace7 100644 --- a/src/expr.h +++ b/src/expr.h @@ -8,8 +8,8 @@ #ifndef BFS_EXPR_H #define BFS_EXPR_H +#include "prelude.h" #include "color.h" -#include "config.h" #include "eval.h" #include "stat.h" #include diff --git a/src/fsade.c b/src/fsade.c index 0810c7f..34a4d57 100644 --- a/src/fsade.c +++ b/src/fsade.c @@ -1,11 +1,11 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "fsade.h" #include "atomic.h" #include "bfstd.h" #include "bftw.h" -#include "config.h" #include "dir.h" #include "dstring.h" #include "sanity.h" diff --git a/src/fsade.h b/src/fsade.h index 1f1dbfc..6300852 100644 --- a/src/fsade.h +++ b/src/fsade.h @@ -9,7 +9,7 @@ #ifndef BFS_FSADE_H #define BFS_FSADE_H -#include "config.h" +#include "prelude.h" #define BFS_CAN_CHECK_ACL BFS_USE_SYS_ACL_H diff --git a/src/ioq.c b/src/ioq.c index b936681..189bdac 100644 --- a/src/ioq.c +++ b/src/ioq.c @@ -118,12 +118,12 @@ * [1]: https://arxiv.org/abs/2201.02179 */ +#include "prelude.h" #include "ioq.h" #include "alloc.h" #include "atomic.h" #include "bfstd.h" #include "bit.h" -#include "config.h" #include "diag.h" #include "dir.h" #include "stat.h" diff --git a/src/ioq.h b/src/ioq.h index 818eea6..d8e1573 100644 --- a/src/ioq.h +++ b/src/ioq.h @@ -8,7 +8,7 @@ #ifndef BFS_IOQ_H #define BFS_IOQ_H -#include "config.h" +#include "prelude.h" #include "dir.h" #include "stat.h" #include diff --git a/src/main.c b/src/main.c index e120f03..9d8b206 100644 --- a/src/main.c +++ b/src/main.c @@ -26,7 +26,7 @@ * - bit.h (bit manipulation) * - bfstd.[ch] (standard library wrappers/polyfills) * - color.[ch] (for pretty terminal colors) - * - config.h (configuration and feature/platform detection) + * - prelude.h (configuration and feature/platform detection) * - diag.[ch] (formats diagnostic messages) * - dir.[ch] (a directory API facade) * - dstring.[ch] (a dynamic string library) @@ -45,8 +45,8 @@ * - xtime.[ch] (date/time handling utilities) */ +#include "prelude.h" #include "bfstd.h" -#include "config.h" #include "ctx.h" #include "diag.h" #include "eval.h" diff --git a/src/mtab.c b/src/mtab.c index 86ae151..7905d14 100644 --- a/src/mtab.c +++ b/src/mtab.c @@ -1,10 +1,10 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "mtab.h" #include "alloc.h" #include "bfstd.h" -#include "config.h" #include "stat.h" #include "trie.h" #include diff --git a/src/mtab.h b/src/mtab.h index d99d78f..67290c2 100644 --- a/src/mtab.h +++ b/src/mtab.h @@ -8,7 +8,7 @@ #ifndef BFS_MTAB_H #define BFS_MTAB_H -#include "config.h" +#include "prelude.h" struct bfs_stat; diff --git a/src/opt.c b/src/opt.c index b74b4e1..ffc795b 100644 --- a/src/opt.c +++ b/src/opt.c @@ -25,11 +25,11 @@ * effects are reachable at all, skipping the traversal if not. */ +#include "prelude.h" #include "opt.h" #include "bftw.h" #include "bit.h" #include "color.h" -#include "config.h" #include "ctx.h" #include "diag.h" #include "dir.h" diff --git a/src/parse.c b/src/parse.c index a3e32fe..c2ae58f 100644 --- a/src/parse.c +++ b/src/parse.c @@ -8,12 +8,12 @@ * flags like always-true options, and skipping over paths wherever they appear. */ +#include "prelude.h" #include "parse.h" #include "alloc.h" #include "bfstd.h" #include "bftw.h" #include "color.h" -#include "config.h" #include "ctx.h" #include "diag.h" #include "dir.h" diff --git a/src/prelude.h b/src/prelude.h new file mode 100644 index 0000000..c3a0752 --- /dev/null +++ b/src/prelude.h @@ -0,0 +1,377 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +/** + * Configuration and feature/platform detection. + */ + +#ifndef BFS_PRELUDE_H +#define BFS_PRELUDE_H + +// Possible __STDC_VERSION__ values + +#define C95 199409L +#define C99 199901L +#define C11 201112L +#define C17 201710L +#define C23 202311L + +#include + +#if __STDC_VERSION__ < C23 +# include +# include +# include +#endif + +// bfs packaging configuration + +#ifndef BFS_COMMAND +# define BFS_COMMAND "bfs" +#endif +#ifndef BFS_HOMEPAGE +# define BFS_HOMEPAGE "https://tavianator.com/projects/bfs.html" +#endif + +// This is a symbol instead of a literal so we don't have to rebuild everything +// when the version number changes +extern const char bfs_version[]; + +// Check for system headers + +#ifdef __has_include + +#if __has_include() +# define BFS_HAS_MNTENT_H true +#endif +#if __has_include() +# define BFS_HAS_PATHS_H true +#endif +#if __has_include() +# define BFS_HAS_SYS_ACL_H true +#endif +#if __has_include() +# define BFS_HAS_SYS_CAPABILITY_H true +#endif +#if __has_include() +# define BFS_HAS_SYS_EXTATTR_H true +#endif +#if __has_include() +# define BFS_HAS_SYS_MKDEV_H true +#endif +#if __has_include() +# define BFS_HAS_SYS_PARAM_H true +#endif +#if __has_include() +# define BFS_HAS_SYS_SYSMACROS_H true +#endif +#if __has_include() +# define BFS_HAS_SYS_XATTR_H true +#endif +#if __has_include() +# define BFS_HAS_THREADS_H true +#endif +#if __has_include() +# define BFS_HAS_UTIL_H true +#endif + +#else // !__has_include + +#define BFS_HAS_MNTENT_H __GLIBC__ +#define BFS_HAS_PATHS_H true +#define BFS_HAS_SYS_ACL_H true +#define BFS_HAS_SYS_CAPABILITY_H __linux__ +#define BFS_HAS_SYS_EXTATTR_H __FreeBSD__ +#define BFS_HAS_SYS_MKDEV_H false +#define BFS_HAS_SYS_PARAM_H true +#define BFS_HAS_SYS_SYSMACROS_H __GLIBC__ +#define BFS_HAS_SYS_XATTR_H __linux__ +#define BFS_HAS_THREADS_H (!__STDC_NO_THREADS__) +#define BFS_HAS_UTIL_H __NetBSD__ + +#endif // !__has_include + +#ifndef BFS_USE_MNTENT_H +# define BFS_USE_MNTENT_H BFS_HAS_MNTENT_H +#endif +#ifndef BFS_USE_PATHS_H +# define BFS_USE_PATHS_H BFS_HAS_PATHS_H +#endif +#ifndef BFS_USE_SYS_ACL_H +# define BFS_USE_SYS_ACL_H (BFS_HAS_SYS_ACL_H && !__illumos__ && (!__linux__ || BFS_USE_LIBACL)) +#endif +#ifndef BFS_USE_SYS_CAPABILITY_H +# define BFS_USE_SYS_CAPABILITY_H (BFS_HAS_SYS_CAPABILITY_H && !__FreeBSD__ && (!__linux__ || BFS_USE_LIBCAP)) +#endif +#ifndef BFS_USE_SYS_EXTATTR_H +# define BFS_USE_SYS_EXTATTR_H (BFS_HAS_SYS_EXTATTR_H && !__DragonFly__) +#endif +#ifndef BFS_USE_SYS_MKDEV_H +# define BFS_USE_SYS_MKDEV_H BFS_HAS_SYS_MKDEV_H +#endif +#ifndef BFS_USE_SYS_PARAM_H +# define BFS_USE_SYS_PARAM_H BFS_HAS_SYS_PARAM_H +#endif +#ifndef BFS_USE_SYS_SYSMACROS_H +# define BFS_USE_SYS_SYSMACROS_H BFS_HAS_SYS_SYSMACROS_H +#endif +#ifndef BFS_USE_SYS_XATTR_H +# define BFS_USE_SYS_XATTR_H BFS_HAS_SYS_XATTR_H +#endif +#ifndef BFS_USE_THREADS_H +# define BFS_USE_THREADS_H BFS_HAS_THREADS_H +#endif +#ifndef BFS_USE_UTIL_H +# define BFS_USE_UTIL_H BFS_HAS_UTIL_H +#endif + +// Stub out feature detection on old/incompatible compilers + +#ifndef __has_feature +# define __has_feature(feat) false +#endif + +#ifndef __has_c_attribute +# define __has_c_attribute(attr) false +#endif + +#ifndef __has_attribute +# define __has_attribute(attr) false +#endif + +// Platform detection + +// Get the definition of BSD if available +#if BFS_USE_SYS_PARAM_H +# include +#endif + +#ifndef __GLIBC_PREREQ +# define __GLIBC_PREREQ(maj, min) false +#endif + +#ifndef __NetBSD_Prereq__ +# define __NetBSD_Prereq__(maj, min, patch) false +#endif + +// Fundamental utilities + +/** + * Get the length of an array. + */ +#define countof(array) (sizeof(array) / sizeof(0[array])) + +/** + * False sharing/destructive interference/largest cache line size. + */ +#ifdef __GCC_DESTRUCTIVE_SIZE +# define FALSE_SHARING_SIZE __GCC_DESTRUCTIVE_SIZE +#else +# define FALSE_SHARING_SIZE 64 +#endif + +/** + * True sharing/constructive interference/smallest cache line size. + */ +#ifdef __GCC_CONSTRUCTIVE_SIZE +# define TRUE_SHARING_SIZE __GCC_CONSTRUCTIVE_SIZE +#else +# define TRUE_SHARING_SIZE 64 +#endif + +/** + * Alignment specifier that avoids false sharing. + */ +#define cache_align alignas(FALSE_SHARING_SIZE) + +#if __COSMOPOLITAN__ +typedef long double max_align_t; +#endif + +// Wrappers for attributes + +/** + * Silence warnings about switch/case fall-throughs. + */ +#if __has_attribute(fallthrough) +# define fallthru __attribute__((fallthrough)) +#else +# define fallthru ((void)0) +#endif + +/** + * Silence warnings about unused declarations. + */ +#if __has_attribute(unused) +# define attr_maybe_unused __attribute__((unused)) +#else +# define attr_maybe_unused +#endif + +/** + * Warn if a value is unused. + */ +#if __has_attribute(warn_unused_result) +# define attr_nodiscard __attribute__((warn_unused_result)) +#else +# define attr_nodiscard +#endif + +/** + * Hint to avoid inlining a function. + */ +#if __has_attribute(noinline) +# define attr_noinline __attribute__((noinline)) +#else +# define attr_noinline +#endif + +/** + * Hint that a function is unlikely to be called. + */ +#if __has_attribute(cold) +# define attr_cold attr_noinline __attribute__((cold)) +#else +# define attr_cold attr_noinline +#endif + +/** + * Adds compiler warnings for bad printf()-style function calls, if supported. + */ +#if __has_attribute(format) +# define attr_printf(fmt, args) __attribute__((format(printf, fmt, args))) +#else +# define attr_printf(fmt, args) +#endif + +/** + * Annotates allocator-like functions. + */ +#if __has_attribute(malloc) +# if __GNUC__ >= 11 && !__OPTIMIZE__ // malloc(deallocator) disables inlining on GCC +# define attr_malloc(...) attr_nodiscard __attribute__((malloc(__VA_ARGS__))) +# else +# define attr_malloc(...) attr_nodiscard __attribute__((malloc)) +# endif +#else +# define attr_malloc(...) attr_nodiscard +#endif + +/** + * Specifies that a function returns allocations with a given alignment. + */ +#if __has_attribute(alloc_align) +# define attr_alloc_align(param) __attribute__((alloc_align(param))) +#else +# define attr_alloc_align(param) +#endif + +/** + * Specifies that a function returns allocations with a given size. + */ +#if __has_attribute(alloc_size) +# define attr_alloc_size(...) __attribute__((alloc_size(__VA_ARGS__))) +#else +# define attr_alloc_size(...) +#endif + +/** + * Shorthand for attr_alloc_align() and attr_alloc_size(). + */ +#define attr_aligned_alloc(align, ...) \ + attr_alloc_align(align) \ + attr_alloc_size(__VA_ARGS__) + +/** + * Check if function multiversioning via GNU indirect functions (ifunc) is supported. + */ +#ifndef BFS_USE_TARGET_CLONES +# if __has_attribute(target_clones) && (__GLIBC__ || __FreeBSD__) +# define BFS_USE_TARGET_CLONES true +# endif +#endif + +/** + * Apply the target_clones attribute, if available. + */ +#if BFS_USE_TARGET_CLONES +# define attr_target_clones(...) __attribute__((target_clones(__VA_ARGS__))) +#else +# 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_PRELUDE_H diff --git a/src/printf.c b/src/printf.c index 3b8269e..4df399b 100644 --- a/src/printf.c +++ b/src/printf.c @@ -1,12 +1,12 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "printf.h" #include "alloc.h" #include "bfstd.h" #include "bftw.h" #include "color.h" -#include "config.h" #include "ctx.h" #include "diag.h" #include "dir.h" diff --git a/src/pwcache.c b/src/pwcache.c index 79437d8..af8c237 100644 --- a/src/pwcache.c +++ b/src/pwcache.c @@ -1,9 +1,9 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "pwcache.h" #include "alloc.h" -#include "config.h" #include "trie.h" #include #include diff --git a/src/sanity.h b/src/sanity.h index 423e6ff..e168b8f 100644 --- a/src/sanity.h +++ b/src/sanity.h @@ -8,7 +8,7 @@ #ifndef BFS_SANITY_H #define BFS_SANITY_H -#include "config.h" +#include "prelude.h" #include #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) diff --git a/src/stat.c b/src/stat.c index 2f2743b..eca5bab 100644 --- a/src/stat.c +++ b/src/stat.c @@ -1,10 +1,10 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "stat.h" #include "atomic.h" #include "bfstd.h" -#include "config.h" #include "diag.h" #include "sanity.h" #include diff --git a/src/stat.h b/src/stat.h index 856a2ca..1fdd263 100644 --- a/src/stat.h +++ b/src/stat.h @@ -12,7 +12,7 @@ #ifndef BFS_STAT_H #define BFS_STAT_H -#include "config.h" +#include "prelude.h" #include #include #include diff --git a/src/thread.c b/src/thread.c index 200d8c3..3793896 100644 --- a/src/thread.c +++ b/src/thread.c @@ -1,9 +1,9 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "thread.h" #include "bfstd.h" -#include "config.h" #include "diag.h" #include #include diff --git a/src/thread.h b/src/thread.h index 8174fe4..db11bd8 100644 --- a/src/thread.h +++ b/src/thread.h @@ -8,7 +8,7 @@ #ifndef BFS_THREAD_H #define BFS_THREAD_H -#include "config.h" +#include "prelude.h" #include #if __STDC_VERSION__ < C23 && !defined(thread_local) diff --git a/src/trie.c b/src/trie.c index f275064..808953e 100644 --- a/src/trie.c +++ b/src/trie.c @@ -81,10 +81,10 @@ * and insert intermediate singleton "jump" nodes when necessary. */ +#include "prelude.h" #include "trie.h" #include "alloc.h" #include "bit.h" -#include "config.h" #include "diag.h" #include "list.h" #include diff --git a/src/xregex.c b/src/xregex.c index 3df27f0..c2711bc 100644 --- a/src/xregex.c +++ b/src/xregex.c @@ -1,10 +1,10 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "xregex.h" #include "alloc.h" #include "bfstd.h" -#include "config.h" #include "diag.h" #include "sanity.h" #include "thread.h" diff --git a/src/xspawn.c b/src/xspawn.c index 347625d..113d7ec 100644 --- a/src/xspawn.c +++ b/src/xspawn.c @@ -1,10 +1,10 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "xspawn.h" #include "alloc.h" #include "bfstd.h" -#include "config.h" #include "list.h" #include #include diff --git a/src/xspawn.h b/src/xspawn.h index a20cbd0..6a8f54a 100644 --- a/src/xspawn.h +++ b/src/xspawn.h @@ -8,7 +8,7 @@ #ifndef BFS_XSPAWN_H #define BFS_XSPAWN_H -#include "config.h" +#include "prelude.h" #include #include #include diff --git a/src/xtime.c b/src/xtime.c index bcf6dd3..91ed915 100644 --- a/src/xtime.c +++ b/src/xtime.c @@ -1,9 +1,9 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "xtime.h" #include "bfstd.h" -#include "config.h" #include "diag.h" #include #include diff --git a/tests/alloc.c b/tests/alloc.c index 54b84ba..6c0defd 100644 --- a/tests/alloc.c +++ b/tests/alloc.c @@ -1,9 +1,9 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "tests.h" #include "alloc.h" -#include "config.h" #include "diag.h" #include #include diff --git a/tests/bfstd.c b/tests/bfstd.c index 5e408ca..07b68b0 100644 --- a/tests/bfstd.c +++ b/tests/bfstd.c @@ -1,9 +1,9 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "tests.h" #include "bfstd.h" -#include "config.h" #include "diag.h" #include #include diff --git a/tests/bit.c b/tests/bit.c index b444e50..674d1b2 100644 --- a/tests/bit.c +++ b/tests/bit.c @@ -1,9 +1,9 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "tests.h" #include "bit.h" -#include "config.h" #include "diag.h" #include #include diff --git a/tests/ioq.c b/tests/ioq.c index a69f2bf..ef5ee3b 100644 --- a/tests/ioq.c +++ b/tests/ioq.c @@ -1,10 +1,10 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "tests.h" #include "ioq.h" #include "bfstd.h" -#include "config.h" #include "diag.h" #include "dir.h" #include diff --git a/tests/main.c b/tests/main.c index 281c417..429772b 100644 --- a/tests/main.c +++ b/tests/main.c @@ -5,10 +5,10 @@ * Entry point for unit tests. */ +#include "prelude.h" #include "tests.h" #include "bfstd.h" #include "color.h" -#include "config.h" #include #include #include diff --git a/tests/tests.h b/tests/tests.h index d61ffd7..9078938 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -8,7 +8,7 @@ #ifndef BFS_TESTS_H #define BFS_TESTS_H -#include "config.h" +#include "prelude.h" #include "diag.h" /** Unit test function type. */ diff --git a/tests/trie.c b/tests/trie.c index 2a6eb48..4667322 100644 --- a/tests/trie.c +++ b/tests/trie.c @@ -1,9 +1,9 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "tests.h" #include "trie.h" -#include "config.h" #include "diag.h" #include #include diff --git a/tests/xspawn.c b/tests/xspawn.c index fd8362e..7362aa5 100644 --- a/tests/xspawn.c +++ b/tests/xspawn.c @@ -1,10 +1,10 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "tests.h" #include "alloc.h" #include "bfstd.h" -#include "config.h" #include "dstring.h" #include "xspawn.h" #include diff --git a/tests/xtime.c b/tests/xtime.c index fd7aa0f..a7c63d2 100644 --- a/tests/xtime.c +++ b/tests/xtime.c @@ -1,10 +1,10 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "tests.h" #include "xtime.h" #include "bfstd.h" -#include "config.h" #include "diag.h" #include #include diff --git a/tests/xtouch.c b/tests/xtouch.c index b1daec7..82d749d 100644 --- a/tests/xtouch.c +++ b/tests/xtouch.c @@ -1,8 +1,8 @@ // Copyright © Tavian Barnes // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "bfstd.h" -#include "config.h" #include "sanity.h" #include "xtime.h" #include -- cgit v1.2.3