commit a1844fae70993122005e138f68937255da0f091c
Author: sin <[email protected]>
Date:   Thu Nov 20 16:57:49 2014 +0000

    Implement grep -f

diff --git a/grep.1 b/grep.1
index b939f7c..9f0fa19 100644
--- 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
index fa3e3bd..1da705e 100644
--- 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)
 {


Reply via email to