From a215ab6de0ae34db7311136404d0f9feab34ef04 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 5 Jul 2023 10:45:56 -0400 Subject: Use strcmp() instead of fnmatch() if possible --- src/parse.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src/parse.c') diff --git a/src/parse.c b/src/parse.c index 623a528..c225a5b 100644 --- a/src/parse.c +++ b/src/parse.c @@ -1676,16 +1676,18 @@ static struct bfs_expr *parse_fnmatch(const struct parser_state *state, struct b return NULL; } + expr->pattern = expr->argv[1]; + if (casefold) { #ifdef FNM_CASEFOLD - expr->num = FNM_CASEFOLD; + expr->fnm_flags = FNM_CASEFOLD; #else parse_expr_error(state, expr, "Missing platform support.\n"); bfs_expr_free(expr); return NULL; #endif } else { - expr->num = 0; + expr->fnm_flags = 0; } // POSIX says, about fnmatch(): @@ -1694,10 +1696,9 @@ static struct bfs_expr *parse_fnmatch(const struct parser_state *state, struct b // return a non-zero value (indicating either no match or an error). // // But not all implementations obey this, so check for it ourselves. - const char *pattern = expr->argv[1]; - size_t i, len = strlen(pattern); + size_t i, len = strlen(expr->pattern); for (i = 0; i < len; ++i) { - if (pattern[len - i - 1] != '\\') { + if (expr->pattern[len - i - 1] != '\\') { break; } } @@ -1707,6 +1708,12 @@ static struct bfs_expr *parse_fnmatch(const struct parser_state *state, struct b return expr; } + // strcmp() can be much faster than fnmatch() since it doesn't have to + // parse the pattern, so special-case patterns with no wildcards. + // + // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13_01 + expr->literal = strcspn(expr->pattern, "?*\\[") == len; + return expr; } -- cgit v1.2.3