From b7b37e986c7e4ca819f9cbbf683033f149f74e4b Mon Sep 17 00:00:00 2001 From: Jakob Kaivo Date: Thu, 28 Apr 2022 11:36:53 -0400 Subject: implement -Fi --- grep.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/grep.c b/grep.c index 73d9220..56e7769 100644 --- a/grep.c +++ b/grep.c @@ -31,11 +31,13 @@ #include #include #include +#include #include struct grep_list { struct grep_list *next; char *string; + size_t len; regex_t re; }; @@ -46,27 +48,55 @@ static int grep_inverse = 0; static int grep_silent = 0; static int grep_exact = 0; -static int grep_match(struct grep_list *head, const char *buf) +static int grep_match_re(struct grep_list *head, const char *buf) { for (struct grep_list *c = head; c != NULL; c = c->next) { - if (c->string) { - if (grep_exact && strcmp(buf, c->string) == 0) { - return !grep_inverse; - } - if (!grep_exact && strstr(buf, c->string)) { - return !grep_inverse; - } - continue; + if (regexec(&(c->re), buf, 0, NULL, 0) == 0) { + return !grep_inverse; } + } - if (regexec(&(c->re), buf, 0, NULL, 0) == 0) { + return grep_inverse; +} + +static int grep_match_fixed(struct grep_list *head, const char *buf) +{ + for (struct grep_list *c = head; c != NULL; c = c->next) { + if (grep_exact && strcmp(buf, c->string) == 0) { + return !grep_inverse; + } + if (!grep_exact && strstr(buf, c->string)) { return !grep_inverse; } } + return grep_inverse; +} +static int grep_match_fixedcase(struct grep_list *head, const char *buf) +{ + size_t blen = strlen(buf); + for (struct grep_list *c = head; c != NULL; c = c->next) { + if (grep_exact && strcasecmp(buf, c->string) == 0) { + return !grep_inverse; + } + if (grep_exact) { + continue; + } + if (blen <= c->len) { + continue; + } + + for (size_t i = 0; i < (blen - c->len); i++) { + if (strncasecmp(buf + i, c->string, c->len) == 0) { + return !grep_inverse; + } + } + } return grep_inverse; } +static int (*grep_match)(struct grep_list *head, const char *buf) = grep_match_re; + static uintmax_t grep(struct grep_list *head, const char *path) { FILE *f = stdin; @@ -144,6 +174,7 @@ static struct grep_list * grep_add_list(struct grep_list *head, char *s) } node->string = strdup(pattern); + node->len = strlen(node->string); pattern = strtok(NULL, "\n"); } @@ -176,7 +207,7 @@ int main(int argc, char *argv[]) int flags = REG_NOSUB; struct grep_list *head = NULL; - enum {REGEX, FIXED } type = REGEX; + enum { REGEX, FIXED } type = REGEX; int c; while ((c = getopt(argc, argv, "EFce:f:ilnqsvx")) != -1) { @@ -187,6 +218,7 @@ int main(int argc, char *argv[]) case 'F': type = FIXED; + grep_match = grep_match_fixed; break; case 'c': @@ -242,6 +274,10 @@ int main(int argc, char *argv[]) head = grep_add_list(head, argv[optind++]); } + if (type == FIXED && (flags & REG_ICASE)) { + grep_match = grep_match_fixedcase; + } + if (type != FIXED) { for (struct grep_list *c = head; c != NULL; c = c->next) { int e = regcomp(&(c->re), c->string, flags); -- cgit v1.2.1