summaryrefslogtreecommitdiff
path: root/grep.c
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2022-04-28 11:36:53 -0400
committerJakob Kaivo <jkk@ung.org>2022-04-28 11:36:53 -0400
commitb7b37e986c7e4ca819f9cbbf683033f149f74e4b (patch)
treecc905de6977ef2941725c37454b7066b8fe0c72a /grep.c
parent7e965cba479cd560600bbb68bd1be0c619da9541 (diff)
implement -Fi
Diffstat (limited to 'grep.c')
-rw-r--r--grep.c58
1 files 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <unistd.h>
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);