sbase

suckless unix tools
git clone git://git.suckless.org/sbase
Log | Files | Refs | README | LICENSE

commit a1844fae70993122005e138f68937255da0f091c
parent 5ba4f37ec3c4dc0d47bc39662d99e8ce005639ba
Author: sin <sin@2f30.org>
Date:   Thu, 20 Nov 2014 16:57:49 +0000

Implement grep -f

Diffstat:
Mgrep.1 | 8++++++++
Mgrep.c | 40+++++++++++++++++++++++++++++-----------
2 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/grep.1 b/grep.1 @@ -6,6 +6,8 @@ grep \- search files for a pattern .RB [ \-EFHchilnqsvx ] .RB [ \-e .I pattern ] +.RB [ \-f +.I file ] .I pattern .RI [ file ...] .SH DESCRIPTION @@ -40,6 +42,12 @@ Specify a pattern used during the search of the input: an input line is selected if it matches any of the specified patterns. This option is most useful when multiple -e options are used to specify multiple patterns, or when a pattern begins with a dash +.TP +.B \-f file +Read one or more patterns from the file named by the pathname file. +Patterns in file shall be terminated by a <newline>. A null pattern can be +specified by an empty line in pattern_file. Unless the -E or -F option is +also specified, each pattern shall be treated as a BRE. (`-'). .TP .B \-h diff --git a/grep.c b/grep.c @@ -12,11 +12,13 @@ enum { Match = 0, NoMatch = 1, Error = 2 }; static void addpattern(const char *); +static void addpatternfile(const char *); static int grep(FILE *, const char *); static int Fflag; static int Hflag; static int eflag; +static int fflag; static int hflag; static int sflag; static int vflag; @@ -35,7 +37,7 @@ static SLIST_HEAD(phead, pattern) phead; static void usage(void) { - enprintf(Error, "usage: %s [-EFHcilnqsvx] [-e pattern] pattern [files...]\n", argv0); + enprintf(Error, "usage: %s [-EFHcilnqsvx] [-e pattern] [-f file] pattern [files...]\n", argv0); } int @@ -61,6 +63,10 @@ main(int argc, char *argv[]) addpattern(EARGF(usage())); eflag = 1; break; + case 'f': + addpatternfile(EARGF(usage())); + fflag = 1; + break; case 'h': hflag = 1; break; @@ -86,11 +92,11 @@ main(int argc, char *argv[]) usage(); } ARGEND; - if (argc == 0 && !eflag) + if (argc == 0 && !eflag && !fflag) usage(); /* no pattern */ - /* If -e is not specified treat it as if it were */ - if (!eflag) { + /* just add literal pattern to list */ + if (!eflag && !fflag) { addpattern(argv[0]); argc--; argv++; @@ -149,18 +155,30 @@ addpattern(const char *pattern) tmp = estrdup(pattern); } - SLIST_FOREACH(pnode, &phead, entry) { - if (!strcmp(pnode->pattern, tmp)) { - free(tmp); - return; - } - } - pnode = emalloc(sizeof(*pnode)); pnode->pattern = tmp; SLIST_INSERT_HEAD(&phead, pnode, entry); } +static void +addpatternfile(const char *file) +{ + FILE *fp; + char *buf = NULL; + size_t len = 0, size = 0; + + fp = fopen(file, "r"); + if (!fp) + enprintf(Error, "fopen %s:", file); + while ((len = getline(&buf, &size, fp)) != -1) { + if (len && buf[len - 1] == '\n') + buf[len - 1] = '\0'; + addpattern(buf); + } + free(buf); + fclose(fp); +} + static int grep(FILE *fp, const char *str) {