diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bftw.c | 41 | ||||
-rw-r--r-- | src/color.c | 186 | ||||
-rw-r--r-- | src/exec.c | 2 | ||||
-rw-r--r-- | src/ioq.c | 22 | ||||
-rw-r--r-- | src/parse.c | 12 | ||||
-rw-r--r-- | src/prelude.h | 2 | ||||
-rw-r--r-- | src/version.c | 4 |
7 files changed, 133 insertions, 136 deletions
@@ -1529,11 +1529,28 @@ static bool bftw_pop_file(struct bftw_state *state) { return bftw_pop(state, &state->fileq); } +/** Add a path component to the path. */ +static void bftw_prepend_path(char *path, size_t nameoff, size_t namelen, const char *name) { + if (nameoff > 0) { + path[nameoff - 1] = '/'; + } + memcpy(path + nameoff, name, namelen); +} + /** Build the path to the current file. */ static int bftw_build_path(struct bftw_state *state, const char *name) { const struct bftw_file *file = state->file; - size_t pathlen = file ? file->nameoff + file->namelen : 0; + size_t nameoff, namelen; + if (name) { + nameoff = file ? bftw_child_nameoff(file) : 0; + namelen = strlen(name); + } else { + nameoff = file->nameoff; + namelen = file->namelen; + } + + size_t pathlen = nameoff + namelen; if (dstresize(&state->path, pathlen) != 0) { state->error = errno; return -1; @@ -1546,11 +1563,11 @@ static int bftw_build_path(struct bftw_state *state, const char *name) { } // Build the path backwards + if (name) { + bftw_prepend_path(state->path, nameoff, namelen, name); + } while (file && file != ancestor) { - if (file->nameoff > 0) { - state->path[file->nameoff - 1] = '/'; - } - memcpy(state->path + file->nameoff, file->name, file->namelen); + bftw_prepend_path(state->path, file->nameoff, file->namelen, file->name); if (ancestor && ancestor->depth == file->depth) { ancestor = ancestor->parent; @@ -1559,20 +1576,6 @@ static int bftw_build_path(struct bftw_state *state, const char *name) { } state->previous = state->file; - - if (name) { - if (pathlen > 0 && state->path[pathlen - 1] != '/') { - if (dstrapp(&state->path, '/') != 0) { - state->error = errno; - return -1; - } - } - if (dstrcat(&state->path, name) != 0) { - state->error = errno; - return -1; - } - } - return 0; } diff --git a/src/color.c b/src/color.c index 81f28bb..13a4e08 100644 --- a/src/color.c +++ b/src/color.c @@ -214,57 +214,26 @@ static void ext_tolower(char *ext, size_t len) { } } -/** - * The "smart case" algorithm. - * - * @param ext - * The current extension being added. - * @param prev - * The previous case-sensitive match, if any, for the same extension. - * @param iprev - * The previous case-insensitive match, if any, for the same extension. - * @return - * Whether this extension should become case-sensitive. - */ -static bool ext_case_sensitive(struct ext_color *ext, struct ext_color *prev, struct ext_color *iprev) { - // This is the first case-insensitive occurrence of this extension, e.g. - // - // *.gz=01;31:*.tar.gz=01;33 - if (!iprev) { - bfs_assert(!prev); - return false; - } - - // If the last version of this extension is already case-sensitive, - // this one should be too, e.g. - // - // *.tar.gz=01;31:*.TAR.GZ=01;32:*.TAR.GZ=01;33 - if (iprev->case_sensitive) { - return true; - } - - // The case matches the last occurrence exactly, e.g. - // - // *.tar.gz=01;31:*.tar.gz=01;33 - if (iprev == prev) { - return false; +/** Insert an extension into a trie. */ +static int insert_ext(struct trie *trie, struct ext_color *ext) { + // A later *.x should override any earlier *.x, *.y.x, etc. + struct trie_leaf *leaf; + while ((leaf = trie_find_postfix(trie, ext->ext))) { + trie_remove(trie, leaf); } - // Different case, but same value, e.g. - // - // *.tar.gz=01;31:*.TAR.GZ=01;31 - if (esc_eq(iprev->esc, ext->esc->seq, ext->esc->len)) { - return false; + size_t len = ext->len + 1; + leaf = trie_insert_mem(trie, ext->ext, len); + if (!leaf) { + return -1; } - // Different case, different value, e.g. - // - // *.tar.gz=01;31:*.TAR.GZ=01;33 - return true; + leaf->value = ext; + return 0; } /** Set the color for an extension. */ -static int set_ext(struct colors *colors, char *key, char *value) { +static int set_ext(struct colors *colors, dchar *key, dchar *value) { size_t len = dstrlen(key); struct ext_color *ext = varena_alloc(&colors->ext_arena, len + 1); if (!ext) { @@ -279,45 +248,19 @@ static int set_ext(struct colors *colors, char *key, char *value) { goto fail; } - key = memcpy(ext->ext, key, len + 1); + memcpy(ext->ext, key, len + 1); // Reverse the extension (`*.y.x` -> `x.y.*`) so we can use trie_find_prefix() - ext_reverse(key, len); - - // Find any pre-existing exact match - struct ext_color *prev = NULL; - struct trie_leaf *leaf = trie_find_str(&colors->ext_trie, key); - if (leaf) { - prev = leaf->value; - trie_remove(&colors->ext_trie, leaf); - } - - // A later *.x should override any earlier *.x, *.y.x, etc. - while ((leaf = trie_find_postfix(&colors->ext_trie, key))) { - trie_remove(&colors->ext_trie, leaf); - } + ext_reverse(ext->ext, len); // Insert the extension into the case-sensitive trie - leaf = trie_insert_str(&colors->ext_trie, key); - if (!leaf) { - goto fail; - } - leaf->value = ext; - - // "Smart case": if the same extension is given with two different - // capitalizations (e.g. `*.y.x=31:*.Y.Z=32:`), make it case-sensitive - ext_tolower(key, len); - leaf = trie_insert_str(&colors->iext_trie, key); - if (!leaf) { + if (insert_ext(&colors->ext_trie, ext) != 0) { goto fail; } - struct ext_color *iprev = leaf->value; - if (ext_case_sensitive(ext, prev, iprev)) { - iprev->case_sensitive = true; - ext->case_sensitive = true; + if (colors->ext_len < len) { + colors->ext_len = len; } - leaf->value = ext; return 0; @@ -329,32 +272,83 @@ fail: return -1; } -/** Rebuild the case-insensitive trie after all extensions have been parsed. */ -static int build_iext_trie(struct colors *colors) { - trie_clear(&colors->iext_trie); +/** + * The "smart case" algorithm. + * + * @param ext + * The current extension being added. + * @param iext + * The previous case-insensitive match, if any, for the same extension. + * @return + * Whether this extension should become case-sensitive. + */ +static bool ext_case_sensitive(struct ext_color *ext, struct ext_color *iext) { + // This is the first case-insensitive occurrence of this extension, e.g. + // + // *.gz=01;31:*.tar.gz=01;33 + if (!iext) { + return false; + } + // If the last version of this extension is already case-sensitive, + // this one should be too, e.g. + // + // *.tar.gz=01;31:*.TAR.GZ=01;32:*.TAR.GZ=01;33 + if (iext->case_sensitive) { + return true; + } + + // Different case, but same value, e.g. + // + // *.tar.gz=01;31:*.TAR.GZ=01;31 + if (esc_eq(iext->esc, ext->esc->seq, ext->esc->len)) { + return false; + } + + // Different case, different value, e.g. + // + // *.tar.gz=01;31:*.TAR.GZ=01;33 + return true; +} + +/** Build the case-insensitive trie, after all extensions have been parsed. */ +static int build_iext_trie(struct colors *colors) { + // Find which extensions should be case-sensitive for_trie (leaf, &colors->ext_trie) { - size_t len = leaf->length - 1; - if (colors->ext_len < len) { - colors->ext_len = len; + struct ext_color *ext = leaf->value; + + // "Smart case": if the same extension is given with two different + // capitalizations (e.g. `*.y.x=31:*.Y.Z=32:`), make it case-sensitive + ext_tolower(ext->ext, ext->len); + + size_t len = ext->len + 1; + struct trie_leaf *ileaf = trie_insert_mem(&colors->iext_trie, ext->ext, len); + if (!ileaf) { + return -1; } + struct ext_color *iext = ileaf->value; + if (ext_case_sensitive(ext, iext)) { + ext->case_sensitive = true; + iext->case_sensitive = true; + } + + ileaf->value = ext; + } + + // Rebuild the trie with only the case-insensitive ones + trie_clear(&colors->iext_trie); + + for_trie (leaf, &colors->ext_trie) { struct ext_color *ext = leaf->value; if (ext->case_sensitive) { continue; } - // set_ext() already reversed and lowercased the extension - struct trie_leaf *ileaf; - while ((ileaf = trie_find_postfix(&colors->iext_trie, ext->ext))) { - trie_remove(&colors->iext_trie, ileaf); - } - - ileaf = trie_insert_str(&colors->iext_trie, ext->ext); - if (!ileaf) { + // We already lowercased the extension above + if (insert_ext(&colors->iext_trie, ext) != 0) { return -1; } - ileaf->value = ext; } return 0; @@ -583,7 +577,7 @@ static int parse_gnu_ls_colors(struct colors *colors, const char *ls_colors) { break; } - if (dstrncpy(&key, chunk, equals - chunk) != 0) { + if (dstrxcpy(&key, chunk, equals - chunk) != 0) { goto fail; } if (unescape(&value, equals + 1, ':', &next) != 0) { @@ -968,7 +962,7 @@ static ssize_t first_broken_offset(const char *path, const struct BFTW *ftwbuf, if (path == ftwbuf->path) { if (ftwbuf->depth == 0) { at_fd = AT_FDCWD; - at_path = dstrndup(path, max); + at_path = dstrxdup(path, max); } else { // The parent must have existed to get here goto out; @@ -977,13 +971,13 @@ static ssize_t first_broken_offset(const char *path, const struct BFTW *ftwbuf, // We're in print_link_target(), so resolve relative to the link's parent directory at_fd = ftwbuf->at_fd; if (at_fd == (int)AT_FDCWD && path[0] != '/') { - at_path = dstrndup(ftwbuf->path, ftwbuf->nameoff); - if (at_path && dstrncat(&at_path, path, max) != 0) { + at_path = dstrxdup(ftwbuf->path, ftwbuf->nameoff); + if (at_path && dstrxcat(&at_path, path, max) != 0) { ret = -1; goto out_path; } } else { - at_path = dstrndup(path, max); + at_path = dstrxdup(path, max); } } @@ -1206,7 +1200,7 @@ static int cvbuff(CFILE *cfile, const char *format, va_list args) { for (const char *i = format; *i; ++i) { size_t verbatim = strcspn(i, "%$"); - if (dstrncat(&cfile->buffer, i, verbatim) != 0) { + if (dstrxcat(&cfile->buffer, i, verbatim) != 0) { return -1; } i += verbatim; @@ -234,7 +234,7 @@ static char *bfs_exec_format_arg(char *arg, const char *path) { char *last = arg; do { - if (dstrncat(&ret, last, match - last) != 0) { + if (dstrxcat(&ret, last, match - last) != 0) { goto err; } if (dstrcat(&ret, path) != 0) { @@ -313,9 +313,11 @@ static void ioq_slot_wake(struct ioqq *ioqq, ioq_slot *slot) { cond_broadcast(&monitor->cond); } -/** Branch-free (slot & IOQ_SKIP) ? ~IOQ_BLOCKED : 0 */ -static uintptr_t ioq_skip_mask(uintptr_t slot) { - return -(slot >> IOQ_SKIP_BIT) << 1; +/** Branch-free ((slot & IOQ_SKIP) ? skip : full) & ~IOQ_BLOCKED */ +static uintptr_t ioq_slot_blend(uintptr_t slot, uintptr_t skip, uintptr_t full) { + uintptr_t mask = -(slot >> IOQ_SKIP_BIT); + uintptr_t ret = (skip & mask) | (full & ~mask); + return ret & ~IOQ_BLOCKED; } /** Push an entry into a slot. */ @@ -323,19 +325,18 @@ static bool ioq_slot_push(struct ioqq *ioqq, ioq_slot *slot, struct ioq_ent *ent uintptr_t prev = load(slot, relaxed); while (true) { - size_t skip_mask = ioq_skip_mask(prev); - size_t full_mask = ~skip_mask & ~IOQ_BLOCKED; - if (prev & full_mask) { + uintptr_t full = ioq_slot_blend(prev, 0, prev); + if (full) { // full(ptr) → wait prev = ioq_slot_wait(ioqq, slot, prev); continue; } // empty → full(ptr) - uintptr_t next = ((uintptr_t)ent >> 1) & full_mask; + uintptr_t next = (uintptr_t)ent >> 1; // skip(1) → empty // skip(n) → skip(n - 1) - next |= (prev - IOQ_SKIP_ONE) & skip_mask; + next = ioq_slot_blend(prev, prev - IOQ_SKIP_ONE, next); if (compare_exchange_weak(slot, &prev, next, release, relaxed)) { break; @@ -357,9 +358,8 @@ static struct ioq_ent *ioq_slot_pop(struct ioqq *ioqq, ioq_slot *slot, bool bloc // skip(n) → skip(n + 1) // full(ptr) → full(ptr - 1) uintptr_t next = prev + IOQ_SKIP_ONE; - // skip(n) → ~IOQ_BLOCKED // full(ptr) → 0 - next &= ioq_skip_mask(next); + next = ioq_slot_blend(next, next, 0); if (block && next) { prev = ioq_slot_wait(ioqq, slot, prev); @@ -378,7 +378,7 @@ static struct ioq_ent *ioq_slot_pop(struct ioqq *ioqq, ioq_slot *slot, bool bloc // empty → 0 // skip(n) → 0 // full(ptr) → ptr - prev &= ioq_skip_mask(~prev); + prev = ioq_slot_blend(prev, 0, prev); return (struct ioq_ent *)(prev << 1); } diff --git a/src/parse.c b/src/parse.c index 9035344..86ce72c 100644 --- a/src/parse.c +++ b/src/parse.c @@ -2961,12 +2961,12 @@ static struct bfs_expr *parse_version(struct bfs_parser *parser, int arg1, int a printf("Copyright © Tavian Barnes and the bfs contributors\n"); printf("No rights reserved (https://opensource.org/license/0BSD)\n\n"); - printf("CONFIG := %s\n", bfs_config); - printf("CC := %s\n", bfs_cc); - printf("CPPFLAGS := %s\n", bfs_cppflags); - printf("CFLAGS := %s\n", bfs_cflags); - printf("LDFLAGS := %s\n", bfs_ldflags); - printf("LDLIBS := %s\n", bfs_ldlibs); + printf("CONFFLAGS := %s\n", bfs_confflags); + printf("CC := %s\n", bfs_cc); + printf("CPPFLAGS := %s\n", bfs_cppflags); + printf("CFLAGS := %s\n", bfs_cflags); + printf("LDFLAGS := %s\n", bfs_ldflags); + printf("LDLIBS := %s\n", bfs_ldlibs); printf("\n%s\n", BFS_HOMEPAGE); diff --git a/src/prelude.h b/src/prelude.h index bca16b2..34ce803 100644 --- a/src/prelude.h +++ b/src/prelude.h @@ -40,7 +40,7 @@ // when the version number changes extern const char bfs_version[]; -extern const char bfs_config[]; +extern const char bfs_confflags[]; extern const char bfs_cc[]; extern const char bfs_cppflags[]; extern const char bfs_cflags[]; diff --git a/src/version.c b/src/version.c index 9e5c82f..8383350 100644 --- a/src/version.c +++ b/src/version.c @@ -7,8 +7,8 @@ const char bfs_version[] = { #include "version.i" }; -const char bfs_config[] = { -#include "config.i" +const char bfs_confflags[] = { +#include "confflags.i" }; const char bfs_cc[] = { |