Skip to content
Browse files

Import of our changes to grep developed in othersrc. A very

brief summary:

* Add NetBSD RCS Ids. Change to use a date based version number.
* Remove unused variables and functions.
* Move towards NetBSD code style.
* Add missing GNU options (except for --include, --exclude and
	--line-buffered)
* Bug fixes
* Bug fixes and changes from OpenBSD's src/usr.bin/grep

A full list of changes can be viewed in the NetBSD CVS repository at
othersrc/usr.bin/grep. A ChangeLog is also available at:
	ftp://ftp.NetBSD.org/pub/NetBSD/misc/cjep/grep-ChangeLog.txt

If you want to help out, please let me (cjep@) know so that we can
organise our efforts efficiently.
  • Loading branch information...
1 parent a8e134c commit 271df26e3fb6b23a7123a20498e43acde994c9fc cjep committed
Showing with 726 additions and 333 deletions.
  1. +15 −9 usr.bin/grep/Makefile
  2. +24 −16 usr.bin/grep/binary.c
  3. +65 −43 usr.bin/grep/file.c
  4. +42 −22 usr.bin/grep/grep.1
  5. +313 −114 usr.bin/grep/grep.c
  6. +76 −43 usr.bin/grep/grep.h
  7. +13 −13 usr.bin/grep/mmfile.c
  8. +15 −15 usr.bin/grep/queue.c
  9. +163 −58 usr.bin/grep/util.c
View
24 usr.bin/grep/Makefile
@@ -1,16 +1,22 @@
-# $Id: Makefile,v 1.1.1.1 2004/01/02 14:58:45 cjep Exp $
+# $NetBSD: Makefile,v 1.1.1.2 2004/01/02 15:00:25 cjep Exp $
PROG= grep
SRCS= binary.c file.c grep.c mmfile.c queue.c util.c
-LINKS= ${BINDIR}/grep ${BINDIR}/egrep \
- ${BINDIR}/grep ${BINDIR}/fgrep \
- ${BINDIR}/grep ${BINDIR}/zgrep
-MLINKS= grep.1 egrep.1 \
- grep.1 fgrep.1 \
- grep.1 zgrep.1
-CFLAGS+= -I/usr/local/include -Wall -pedantic
+LINKS= ${BINDIR}/grep ${BINDIR}/egrep \
+ ${BINDIR}/grep ${BINDIR}/fgrep \
+ ${BINDIR}/grep ${BINDIR}/zgrep \
+ ${BINDIR}/grep ${BINDIR}/zegrep \
+ ${BINDIR}/grep ${BINDIR}/zfgrep
-LDADD= -lz -L/usr/local/lib/ -liberty
+MLINKS= grep.1 egrep.1 \
+ grep.1 fgrep.1 \
+ grep.1 zgrep.1 \
+ grep.1 zegrep.1 \
+ grep.1 zfgrep.1
+
+LDADD= -lz
+
+WARNS=2
.include <bsd.prog.mk>
View
40 usr.bin/grep/binary.c
@@ -1,3 +1,5 @@
+/* $NetBSD: binary.c,v 1.1.1.2 2004/01/02 15:00:27 cjep Exp $ */
+
/*-
* Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
* All rights reserved.
@@ -23,33 +25,38 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: binary.c,v 1.1.1.1 2004/01/02 14:58:45 cjep Exp $
*/
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: binary.c,v 1.1.1.2 2004/01/02 15:00:27 cjep Exp $");
+#endif /* not lint */
+
#include <ctype.h>
#include <stdio.h>
#include <zlib.h>
#include "grep.h"
-#define BUFFER_SIZE 32
+#define BUFFER_SIZE 128
int
bin_file(FILE *f)
{
- char buf[BUFFER_SIZE];
- int i, m;
+ char buf[BUFFER_SIZE];
+ int i, m;
- if (fseek(f, SEEK_SET, 0) == -1)
+ if (fseek(f, 0L, SEEK_SET) == -1)
return 0;
if ((m = (int)fread(buf, 1, BUFFER_SIZE, f)) == 0)
return 0;
for (i = 0; i < m; i++)
- if (!isprint(buf[i]) && !isspace(buf[i]))
- return 1;
-
+ if (!isprint(buf[i]) && !isspace(buf[i]) &&
+ buf[i] != line_endchar)
+ return 1;
+
rewind(f);
return 0;
}
@@ -57,17 +64,18 @@ bin_file(FILE *f)
int
gzbin_file(gzFile *f)
{
- char buf[BUFFER_SIZE];
- int i, m;
+ char buf[BUFFER_SIZE];
+ int i, m;
- if (gzseek(f, SEEK_SET, 0) == -1)
+ if (gzseek(f, 0L, SEEK_SET) == -1)
return 0;
- if ((m = (int)gzread(f, buf, BUFFER_SIZE)) == 0)
+ if ((m = gzread(f, buf, BUFFER_SIZE)) == 0)
return 0;
for (i = 0; i < m; i++)
- if (!isprint(buf[i]))
+ if (!isprint(buf[i]) && !isspace(buf[i]) &&
+ buf[i] != line_endchar)
return 1;
gzrewind(f);
@@ -78,10 +86,10 @@ int
mmbin_file(mmf_t *f)
{
int i;
-
/* XXX knows too much about mmf internals */
- for (i = 0; i < BUFFER_SIZE && i < f->len; i++)
- if (!isprint(f->base[i]))
+ for (i = 0; i < BUFFER_SIZE && i < f->len - 1; i++)
+ if (!isprint(f->base[i]) && !isspace(f->base[i]) &&
+ f->base[i] != line_endchar)
return 1;
mmrewind(f);
return 0;
View
108 usr.bin/grep/file.c
@@ -1,3 +1,5 @@
+/* $NetBSD: file.c,v 1.1.1.2 2004/01/02 15:00:27 cjep Exp $ */
+
/*-
* Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
* All rights reserved.
@@ -23,9 +25,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: file.c,v 1.1.1.1 2004/01/02 14:58:45 cjep Exp $
*/
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: file.c,v 1.1.1.2 2004/01/02 15:00:27 cjep Exp $");
+#endif /* not lint */
+
#include <sys/param.h>
#include <err.h>
@@ -35,26 +41,55 @@
#include "grep.h"
-static char fname[MAXPATHLEN];
-static char *lnbuf;
-static int lnbuflen;
+static char fname[MAXPATHLEN];
+static char *lnbuf;
+static int lnbuflen;
#define FILE_STDIO 0
#define FILE_MMAP 1
#define FILE_GZIP 2
struct file {
- int type;
- FILE *f;
- mmf_t *mmf;
- gzFile *gzf;
+ int type;
+ FILE *f;
+ mmf_t *mmf;
+ gzFile *gzf;
};
static char *
+grepfgetln(FILE *f, size_t *len)
+{
+ size_t n;
+ int c;
+
+ for (n = 0; ; ++n) {
+ c = getc(f);
+ if (c == EOF) {
+ if (feof(f))
+ break;
+ err(2, "%s", fname);
+ /* ERROR */
+
+ }
+ if (c == line_endchar)
+ break;
+ if (n >= lnbuflen) {
+ lnbuflen *= 2;
+ lnbuf = grep_realloc(lnbuf, ++lnbuflen);
+ }
+ lnbuf[n] = c;
+ }
+ if (feof(f) && n == 0)
+ return NULL;
+ *len = n;
+ return lnbuf;
+}
+
+static char *
gzfgetln(gzFile *f, size_t *len)
{
- size_t n;
- int c;
+ size_t n;
+ int c;
for (n = 0; ; ++n) {
c = gzgetc(f);
@@ -64,14 +99,14 @@ gzfgetln(gzFile *f, size_t *len)
if (gzeof(f))
break;
-
+
gzerrstr = gzerror(f, &gzerr);
if (gzerr == Z_ERRNO)
- err(1, "%s", fname);
+ err(2, "%s", fname);
else
- errx(1, "%s: %s", fname, gzerrstr);
+ errx(2, "%s: %s", fname, gzerrstr);
}
- if (c == '\n')
+ if (c == line_endchar)
break;
if (n >= lnbuflen) {
lnbuflen *= 2;
@@ -95,10 +130,10 @@ grep_fdopen(int fd, char *mode)
sprintf(fname, "(standard input)");
else
sprintf(fname, "(fd %d)", fd);
-
+
f = grep_malloc(sizeof *f);
-
- if (Zflag) {
+
+ if (zgrep) {
f->type = FILE_GZIP;
if ((f->gzf = gzdopen(fd, mode)) != NULL)
return f;
@@ -107,7 +142,7 @@ grep_fdopen(int fd, char *mode)
if ((f->f = fdopen(fd, mode)) != NULL)
return f;
}
-
+
free(f);
return NULL;
}
@@ -118,10 +153,10 @@ grep_open(char *path, char *mode)
file_t *f;
snprintf(fname, MAXPATHLEN, "%s", path);
-
+
f = grep_malloc(sizeof *f);
-
- if (Zflag) {
+
+ if (zgrep) {
f->type = FILE_GZIP;
if ((f->gzf = gzopen(fname, mode)) != NULL)
return f;
@@ -135,7 +170,7 @@ grep_open(char *path, char *mode)
if ((f->f = fopen(path, mode)) != NULL)
return f;
}
-
+
free(f);
return NULL;
}
@@ -147,28 +182,12 @@ grep_bin_file(file_t *f)
case FILE_STDIO:
return bin_file(f->f);
case FILE_MMAP:
- return mmbin_file(f->mmf);
+ return mmbin_file(f->mmf);
case FILE_GZIP:
return gzbin_file(f->gzf);
default:
/* can't happen */
- errx(1, "invalid file type");
- }
-}
-
-long
-grep_tell(file_t *f)
-{
- switch (f->type) {
- case FILE_STDIO:
- return ftell(f->f);
- case FILE_MMAP:
- return mmtell(f->mmf);
- case FILE_GZIP:
- return gztell(f->gzf);
- default:
- /* can't happen */
- errx(1, "invalid file type");
+ errx(2, "invalid file type");
}
}
@@ -177,14 +196,17 @@ grep_fgetln(file_t *f, size_t *l)
{
switch (f->type) {
case FILE_STDIO:
- return fgetln(f->f, l);
+ if (line_endchar == '\n')
+ return fgetln(f->f, l);
+ else
+ return grepfgetln(f->f, l);
case FILE_MMAP:
return mmfgetln(f->mmf, l);
case FILE_GZIP:
return gzfgetln(f->gzf, l);
default:
/* can't happen */
- errx(1, "invalid file type");
+ errx(2, "invalid file type");
}
}
@@ -203,6 +225,6 @@ grep_close(file_t *f)
break;
default:
/* can't happen */
- errx(1, "invalid file type");
+ errx(2, "invalid file type");
}
}
View
64 usr.bin/grep/grep.1
@@ -1,3 +1,5 @@
+.\" $NetBSD: grep.1,v 1.1.1.2 2004/01/02 15:00:27 cjep Exp $
+.\"
.\" Copyright (c) 1980, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
@@ -35,12 +37,13 @@
.Dt GREP 1
.Os
.Sh NAME
-.Nm grep, egrep, fgrep. zgrep
+.Nm grep, egrep, fgrep, zgrep
.Nd file pattern searcher
.Sh SYNOPSIS
.Nm grep
-.Op Fl AB Ar num
-.Op Fl CEFGHLPRSVZabchilnoqsvwx
+.Op Fl ABC Ar num
+.Op Fl EFGHILPSVZabchilnqrsvwxz
+.Op Fl d Ar action
.Op Fl e Ar pattern
.Op Fl f Ar file
.Op Ar
@@ -91,12 +94,19 @@ lines of trailing context after each match.
Print
.Ar num
lines of leading context before each match.
-.It Fl C
-Equivalent to
-.Fl A
-.Ar 2
-.Fl B
-.Ar 2 .
+.It Fl C Ar num
+Print
+.Ar num
+lines of leading and trailing context before and after each match
+respectively.
+.It Fl D Ar action
+Use the specified action when processing input files that are devices, FIFOs
+or sockets.
+The default action is
+.Nm read ,
+which means that that devices are treated as ordinary files. If the action is
+.Nm skip
+then devices will not be processed at all.
.It Fl E
Force
.Nm grep
@@ -113,10 +123,10 @@ Force
to behave as
.Nm grep.
.It Fl H
-If
-.Fl R
-is specified, follow symbolic links only if they were explictly listed
-on the command line.
+Always print filename headers with output lines.
+.It Fl I
+If the file being processed is binary, assume that it does not contain
+matching data.
.It Fl L
Only the names of files not containing selected lines are written to
standard output.
@@ -128,8 +138,6 @@ is written.
If
.Fl R
is specified, no symbolic links are followed.
-.It Fl R
-Recursively search subdirectories listed.
.It Fl S
If
.Fl R
@@ -137,17 +145,26 @@ is specified, all symbolic links are followed.
.It Fl V
Display version information.
.It Fl Z
-Force
-.Nm grep
-to behave as
-.Nm zgrep .
+When printing filenames, output a null character after the filename instead of
+a newline character.
.It Fl a
-Do not search in binary files.
+Treat all files as text.
.It Fl b
The block number on the disk in which a matched pattern is located is
displayed in front of the respective matched line.
.It Fl c
Only a count of selected lines is written to standard output.
+.It Fl d Ar action
+Use the specified action when processing input files that are directories.
+The default action is
+.Nm read ,
+which means that directories are treated as ordinary files. If the action is
+.Nm skip
+then directories will not be processed at all. If the action is
+.Nm recurse
+then
+.Nm grep
+will read all files under each directory recursively.
.It Fl e Ar expression
Specify a pattern used during the search of the input. Multiple
.Fl e
@@ -181,10 +198,10 @@ or
.Fl s
is
specified.
-.It Fl o
-Always print filename headers with output lines.
.It Fl q
Suppress normal output.
+.It Fl r
+Recursively search subdirectories listed.
.It Fl s
Silent mode. Nonexistent and unreadable files are ignored.
.It Fl v
@@ -199,6 +216,9 @@ and `\e>', see
.It Fl x
Only input lines selected against an entire fixed string or regular
expression are considered to be matching lines.
+.It Fl z
+When printing matched lines, output a null character after the line instead of
+a newline character.
.Pp
.El
If no file arguments are specified, the standard input is used.
View
427 usr.bin/grep/grep.c
@@ -1,3 +1,5 @@
+/* $NetBSD: grep.c,v 1.1.1.2 2004/01/02 15:00:29 cjep Exp $ */
+
/*-
* Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
* All rights reserved.
@@ -23,8 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: grep.c,v 1.1.1.1 2004/01/02 14:58:44 cjep Exp $
*/
+
+
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: grep.c,v 1.1.1.2 2004/01/02 15:00:29 cjep Exp $");
+#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
@@ -32,6 +40,7 @@
#include <err.h>
#include <errno.h>
#include <getopt.h>
+#include <limits.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
@@ -40,98 +49,141 @@
#include "grep.h"
+/*
+ * Upper bound of number of digits to represent an int in decimal
+ * 2^8n <= 10^3n. Allow a terminator.
+ */
+#define MAX_BUF_DIGITS (sizeof(int) * 3) + 1
+
/* Flags passed to regcomp() and regexec() */
-int cflags;
-int eflags = REG_STARTEND;
+int cflags = REG_BASIC;
+int eflags = REG_STARTEND;
-int matchall; /* shortcut */
-int patterns, pattern_sz;
-char **pattern;
+int matchall; /* shortcut */
+int patterns, pattern_sz;
+char **pattern;
regex_t *r_pattern;
/* For regex errors */
-char re_error[RE_ERROR_BUF + 1];
+char re_error[RE_ERROR_BUF + 1];
/* Command-line flags */
-int Aflag; /* -A x: print x lines trailing each match */
-int Bflag; /* -B x: print x lines leading each match */
-int Eflag; /* -E: interpret pattern as extended regexp */
-int Fflag; /* -F: interpret pattern as list of fixed strings */
-int Gflag; /* -G: interpret pattern as basic regexp */
-int Hflag; /* -H: if -R, follow explicitly listed symlinks */
-int Lflag; /* -L: only show names of files with no matches */
-int Pflag; /* -P: if -R, no symlinks are followed */
-int Rflag; /* -R: recursively search directory trees */
-int Sflag; /* -S: if -R, follow all symlinks */
-int Vflag; /* -V: display version information */
-int Zflag; /* -Z: decompress input before processing */
-int aflag; /* -a: only search ascii files */
-int bflag; /* -b: show block numbers for each match */
-int cflag; /* -c: only show a count of matching lines */
-int hflag; /* -h: don't print filename headers */
-int iflag; /* -i: ignore case */
-int lflag; /* -l: only show names of files with matches */
-int nflag; /* -n: show line numbers in front of matching lines */
-int oflag; /* -o: always print file name */
-int qflag; /* -q: quiet mode (don't output anything) */
-int sflag; /* -s: silent mode (ignore errors) */
-int vflag; /* -v: only show non-matching lines */
-int wflag; /* -w: pattern must start and end on word boundaries */
-int xflag; /* -x: pattern must match entire line */
+int Aflag; /* -A x: print x lines trailing each match */
+int Bflag; /* -B x: print x lines leading each match */
+int Eflag; /* -E: interpret pattern as extended regexp */
+int Fflag; /* -F: interpret pattern as list of fixed strings */
+int Gflag; /* -G: interpret pattern as basic regexp */
+int Hflag; /* -H: Always print filenames */
+int Lflag; /* -L: only show names of files with no matches */
+/*int Pflag; *//* -P: if -r, no symlinks are followed */
+/*int Sflag; *//* -S: if -r, follow all symlinks */
+int bflag; /* -b: show block numbers for each match */
+int cflag; /* -c: only show a count of matching lines */
+int hflag; /* -h: Never print filenames. -H overrides */
+int lflag; /* -l: only show names of files with matches */
+int mflag; /* -m: specify maximum line matches (per file) */
+int nflag; /* -n: show line numbers in front of matching lines */
+int oflag; /* -o: only print out matches */
+int qflag; /* -q: quiet mode (don't output anything) */
+int sflag; /* -s: silent mode (ignore errors) */
+int vflag; /* -v: only show non-matching lines */
+int wflag; /* -w: pattern must start and end on word boundaries */
+int xflag; /* -x: pattern must match entire line */
-/* Housekeeping */
-int first; /* flag whether or not this is our fist match */
-int tail; /* lines left to print */
-int lead; /* number of lines in leading context queue */
+int colours = 0; /* Attempt to use terminal colours */
+const char *grep_colour = "01;32"; /* Default colour string, green */
+char *uc;
+
+/* Characters to print after filenames */
+char fn_endchar = '\n';
+char fn_colonchar = ':';
+char fn_dashchar = '-';
+char line_endchar = '\n'; /* End of line character */
-char *progname;
+int maxcount = 0; /* Maximum line matches per file */
+int output_filenames = 0;
+
+/* Argv[0] flags */
+int zgrep; /* If we are invoked as zgrep */
+
+int binbehave = BIN_FILE_BIN;
+int dirbehave = GREP_READ;
+int devbehave = GREP_READ;
+/*int linkbehave = LINK_FOLLOW;*/
+char *stdin_label;
+
+enum {
+ BIN_OPT = CHAR_MAX + 1,
+ HELP_OPT,
+ LABEL_OPT,
+ MMAP_OPT,
+ LINK_OPT,
+ COLOUR_OPT
+};
+
+/* Housekeeping */
+int first; /* flag whether or not this is our first match */
+int tail; /* lines left to print */
static void
usage(void)
{
fprintf(stderr, "usage: %s %s %s\n",
- progname,
- "[-[AB] num] [-CEFGHLPRSVZabchilnoqsvwx]",
- "[-e patttern] [-f file]");
+ getprogname(),
+ "[-[ABC] num] [-EFGHILVZabcdhilnoqrsvwxz]",
+ "[-D action] [-d action] [-e pattern] [-f file]");
exit(2);
}
-static char *optstr = "0123456789A:B:CEFGHLPSRUVZabce:f:hilnoqrsuvwxy";
+static char *optstr = "0123456789A:B:C:D:EFGHILUVZabcd:e:f:hilm:noqrsuvwxyz";
-struct option long_options[] =
+struct option long_options[] =
{
- {"basic-regexp", no_argument, NULL, 'G'},
- {"extended-regexp", no_argument, NULL, 'E'},
- {"fixed-strings", no_argument, NULL, 'F'},
+ {"binary-files", required_argument, NULL, BIN_OPT},
+ {"help", no_argument, NULL, HELP_OPT},
+ {"label", required_argument, NULL, LABEL_OPT},
+ {"mmap", no_argument, NULL, MMAP_OPT},
+/* {"links", required_argument, NULL, LINK_OPT},*/
{"after-context", required_argument, NULL, 'A'},
{"before-context", required_argument, NULL, 'B'},
+ {"color", optional_argument, NULL, COLOUR_OPT},
+ {"colour", optional_argument, NULL, COLOUR_OPT},
{"context", optional_argument, NULL, 'C'},
+ {"devices", required_argument, NULL, 'D'},
+ {"extended-regexp", no_argument, NULL, 'E'},
+ {"fixed-strings", no_argument, NULL, 'F'},
+ {"fixed-regexp", no_argument, NULL, 'F'},
+ {"basic-regexp", no_argument, NULL, 'G'},
+ {"with-filename", no_argument, NULL, 'H'},
+ {"files-without-match", no_argument, NULL, 'L'},
+ {"binary", no_argument, NULL, 'U'},
{"version", no_argument, NULL, 'V'},
+ {"null", no_argument, NULL, 'Z'},
+ {"text", no_argument, NULL, 'a'},
{"byte-offset", no_argument, NULL, 'b'},
{"count", no_argument, NULL, 'c'},
+ {"directories", required_argument, NULL, 'd'},
{"regexp", required_argument, NULL, 'e'},
{"file", required_argument, NULL, 'f'},
{"no-filename", no_argument, NULL, 'h'},
{"ignore-case", no_argument, NULL, 'i'},
- {"files-without-match", no_argument, NULL, 'L'},
{"files-with-matches", no_argument, NULL, 'l'},
+ {"max-count", required_argument, NULL, 'm'},
{"line-number", no_argument, NULL, 'n'},
+ {"only-matching", no_argument, NULL, 'o'},
{"quiet", no_argument, NULL, 'q'},
{"silent", no_argument, NULL, 'q'},
{"recursive", no_argument, NULL, 'r'},
{"no-messages", no_argument, NULL, 's'},
- {"text", no_argument, NULL, 'a'},
- {"revert-match", no_argument, NULL, 'v'},
+ {"unix-byte-offsets", no_argument, NULL, 'u'},
+ {"invert-match", no_argument, NULL, 'v'},
{"word-regexp", no_argument, NULL, 'w'},
{"line-regexp", no_argument, NULL, 'x'},
- {"binary", no_argument, NULL, 'U'},
- {"unix-byte-offsets", no_argument, NULL, 'u'},
- {"decompress", no_argument, NULL, 'Z'},
-
+ {"null-data", no_argument, NULL, 'z'},
+
{NULL, no_argument, NULL, 0}
};
-
static void
add_pattern(char *pat, size_t len)
{
@@ -141,11 +193,11 @@ add_pattern(char *pat, size_t len)
}
if (patterns == pattern_sz) {
pattern_sz *= 2;
- pattern = grep_realloc(pattern, ++pattern_sz);
+ pattern = grep_realloc(pattern, ++pattern_sz * sizeof(*pattern));
}
- if (pat[len-1] == '\n')
+ if (pat[len - 1] == '\n')
--len;
- pattern[patterns] = grep_malloc(len+1);
+ pattern[patterns] = grep_malloc(len + 1);
strncpy(pattern[patterns], pat, len);
pattern[patterns][len] = '\0';
++patterns;
@@ -160,7 +212,7 @@ read_patterns(char *fn)
int nl;
if ((f = fopen(fn, "r")) == NULL)
- err(1, "%s", fn);
+ err(2, "%s", fn);
nl = 0;
while ((line = fgetln(f, &len)) != NULL) {
if (*line == '\n') {
@@ -175,85 +227,163 @@ read_patterns(char *fn)
add_pattern(line, len);
}
if (ferror(f))
- err(1, "%s", fn);
+ err(2, "%s", fn);
fclose(f);
}
+static int
+check_context_arg(char const *str) {
+ char *ep;
+ long lval;
+
+ errno = 0;
+ lval = strtol(str, &ep, 10);
+
+ if (str[0] == '\0' || *ep != '\0')
+ errx(2, "Invalid context argument");
+
+ if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) ||
+ (lval > INT_MAX || lval < INT_MIN))
+ errx(2, "Context argument out of range");
+
+ return lval;
+
+}
+
+static int
+grep_getopt(int argc, char *const *argv)
+{
+ int c, ptr;
+ char buffer[MAX_BUF_DIGITS];
+
+ ptr = 0;
+ while (c = getopt_long(argc, argv, optstr, long_options,
+ (int *)NULL), '0' <= c &&
+ c <= '9' && ptr < MAX_BUF_DIGITS) {
+
+ /* Avoid leading zeros */
+ if (ptr != 0 || (ptr == 0 && c != '0'))
+ buffer[ptr++] = c;
+ }
+
+ if (ptr >= MAX_BUF_DIGITS)
+ errx(2, "Context argument out of range");
+
+ if (ptr) {
+ buffer[ptr] = '\0'; /* We now have a string of digits */
+ Aflag = Bflag = check_context_arg(buffer);
+ }
+
+ return c;
+}
+
int
main(int argc, char *argv[])
{
- char *tmp;
+ const char *progname;
int c, i;
+ struct stat sb;
+
+ stdin_label = "(standard input)";
- if ((progname = strrchr(*argv, '/')) != NULL)
- ++progname;
- else
- progname = *argv;
+ progname = getprogname();
+ switch (progname[0]) {
+ case 'e':
+ Eflag++;
+ break;
+ case 'f':
+ Fflag++;
+ break;
+ case 'g':
+ Gflag++;
+ break;
+ case 'z':
+ zgrep++;
+ switch (progname[1]) {
+ case 'e':
+ Eflag++;
+ break;
+ case 'f':
+ Fflag++;
+ break;
+ case 'g':
+ Gflag++;
+ break;
+ }
+ break;
+ }
+
+ while ((c = grep_getopt(argc, argv)) != -1) {
- while ((c = getopt_long(argc, argv, optstr,
- long_options, (int *)NULL)) != -1) {
switch (c) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- tmp = argv[optind - 1];
- if (tmp[0] == '-' && tmp[1] == c && !tmp[2])
- Aflag = Bflag = strtol(++tmp, (char **)NULL, 10);
- else
- Aflag = Bflag = strtol(argv[optind] + 1, (char **)NULL, 10);
- break;
+
case 'A':
- Aflag = strtol(optarg, (char **)NULL, 10);
+ Aflag = check_context_arg(optarg);
break;
case 'B':
- Bflag = strtol(optarg, (char **)NULL, 10);
+ Bflag = check_context_arg(optarg);
break;
case 'C':
if (optarg == NULL)
Aflag = Bflag = 2;
else
- Aflag = Bflag = strtol(optarg, (char **)NULL, 10);
+ Aflag = Bflag = check_context_arg(optarg);
break;
+ case 'D':
+ if (strcmp("read", optarg) == 0)
+ devbehave = GREP_READ;
+ else if (strcmp("skip", optarg) == 0)
+ devbehave = GREP_SKIP;
+ else {
+ errx(2, "Unknown device option");
+ }
+ break;
+
case 'E':
+ Fflag = Gflag = 0;
Eflag++;
break;
case 'F':
+ Eflag = Gflag = 0;
Fflag++;
break;
case 'G':
+ Eflag = Fflag = 0;
Gflag++;
break;
case 'H':
- Hflag++;
+ Hflag = 1;
+ break;
+ case 'I':
+ binbehave = BIN_FILE_SKIP;
break;
case 'L':
lflag = 0;
Lflag = qflag = 1;
break;
- case 'P':
- Pflag++;
+/* case 'P':
+ linkbehave = LINK_SKIP;
break;
case 'S':
- Sflag++;
- break;
+ linkbehave = LINK_FOLLOW;
+ break;*/
case 'R':
case 'r':
- Rflag++;
- oflag++;
+ dirbehave = GREP_RECURSE;
break;
case 'U':
case 'u':
/* these are here for compatability */
break;
case 'V':
- fprintf(stderr, "grep version %u.%u\n", VER_MAJ, VER_MIN);
- fprintf(stderr, argv[0]);
- usage();
+ fprintf(stdout, "grep version %s\n", VERSION);
+ exit(0);
break;
case 'Z':
- Zflag++;
+ fn_colonchar = fn_endchar = fn_dashchar = 0;
break;
case 'a':
- aflag = 1;
+ binbehave = BIN_FILE_TEXT;
break;
case 'b':
bflag = 1;
@@ -261,6 +391,18 @@ main(int argc, char *argv[])
case 'c':
cflag = 1;
break;
+ case 'd':
+ if (strcmp("read", optarg) == 0)
+ dirbehave = GREP_READ;
+ else if (strcmp("skip", optarg) == 0)
+ dirbehave = GREP_SKIP;
+ else if (strcmp("recurse", optarg) == 0)
+ dirbehave = GREP_RECURSE;
+ else {
+ errx(2, "Unknown directory option\n");
+ }
+ break;
+
case 'e':
add_pattern(optarg, strlen(optarg));
break;
@@ -268,7 +410,6 @@ main(int argc, char *argv[])
read_patterns(optarg);
break;
case 'h':
- oflag = 0;
hflag = 1;
break;
case 'i':
@@ -279,11 +420,14 @@ main(int argc, char *argv[])
Lflag = 0;
lflag = qflag = 1;
break;
+ case 'm':
+ mflag = 1;
+ maxcount = strtol(optarg, (char **)NULL, 10);
+ break;
case 'n':
nflag = 1;
break;
case 'o':
- hflag = 0;
oflag = 1;
break;
case 'q':
@@ -301,54 +445,109 @@ main(int argc, char *argv[])
case 'x':
xflag = 1;
break;
+ case 'z':
+ line_endchar = 0;
+ break;
+ case BIN_OPT:
+ if (strcmp("binary", optarg) == 0)
+ binbehave = BIN_FILE_BIN;
+ else if (strcmp("without-match", optarg) == 0)
+ binbehave = BIN_FILE_SKIP;
+ else if (strcmp("text", optarg) == 0)
+ binbehave = BIN_FILE_TEXT;
+ else {
+ errx(2, "Unknown binary-files option\n");
+ }
+ break;
+
+ case COLOUR_OPT:
+ if (optarg == NULL || strcmp("auto", optarg) == 0 ||
+ strcmp("tty", optarg) == 0 ||
+ strcmp("if-tty", optarg) == 0) {
+
+ /* Check that stdout is a terminal */
+ if (isatty(STDOUT_FILENO) &&
+ getenv("TERM") &&
+ strcmp(getenv("TERM"), "dumb") != 0)
+ colours = 1;
+ else
+ colours = 0;
+
+ } else if (strcmp("always", optarg) == 0 ||
+ strcmp("yes", optarg) == 0 ||
+ strcmp("force", optarg) == 0)
+ colours = 1;
+ else if (strcmp("never", optarg) == 0 ||
+ strcmp("no", optarg) == 0 ||
+ strcmp("none", optarg) == 0)
+ colours = 0;
+ else
+ errx(2, "Unknown color option\n");
+
+ uc = getenv("GREP_COLOR");
+ if (colours == 1 && uc != NULL && *uc != '\0')
+ grep_colour = uc;
+ break;
+ case LABEL_OPT:
+ stdin_label = optarg;
+ break;
+ case MMAP_OPT:
+ break;
+/*
+ * case LINK_OPT:
+ * if (strcmp("explicit", optarg) == 0)
+ * linkbehave = LINK_EXPLICIT;
+ * else if (strcmp("follow", optarg) == 0)
+ * linkbehave = LINK_FOLLOW;
+ * else if (strcmp("skip", optarg) == 0)
+ * linkbehave = LINK_SKIP;
+ * else {
+ * errx(2, "Unknown links option\n");
+ * }
+ * break;
+ */
+
+ case HELP_OPT:
default:
usage();
}
+
}
-
+
argc -= optind;
argv += optind;
if (argc == 0 && patterns == 0)
usage();
-
if (patterns == 0) {
add_pattern(*argv, strlen(*argv));
--argc;
++argv;
}
-
- switch (*progname) {
- case 'e':
- Eflag++;
- break;
- case 'f':
- Fflag++;
- break;
- case 'g':
- Gflag++;
- break;
- case 'z':
- Zflag++;
- break;
- }
- cflags |= Eflag ? REG_EXTENDED : REG_BASIC;
- r_pattern = grep_malloc(patterns * sizeof(regex_t));
+ if (Eflag)
+ cflags |= REG_EXTENDED;
+ else if (Fflag)
+ cflags |= REG_NOSPEC;
+ r_pattern = grep_malloc(patterns * sizeof(*r_pattern));
for (i = 0; i < patterns; ++i) {
if ((c = regcomp(&r_pattern[i], pattern[i], cflags))) {
regerror(c, &r_pattern[i], re_error, RE_ERROR_BUF);
- errx(1, "%s", re_error);
+ errx(2, "%s", re_error);
}
}
- if ((argc == 0 || argc == 1) && !oflag)
- hflag = 1;
+ if ((argc > 1 && !hflag) || Hflag)
+ output_filenames = 1;
+ if (argc == 1 && !hflag && dirbehave == GREP_RECURSE)
+ if (!stat(*argv, &sb) && (sb.st_mode & S_IFMT) == S_IFDIR)
+ output_filenames = 1;
+
if (argc == 0)
exit(!procfile(NULL));
-
- if (Rflag)
+
+ if (dirbehave == GREP_RECURSE)
c = grep_tree(argv);
else
for (c = 0; argc--; ++argv)
View
119 usr.bin/grep/grep.h
@@ -1,3 +1,5 @@
+/* $NetBSD: grep.h,v 1.1.1.2 2004/01/02 15:00:34 cjep Exp $ */
+
/*-
* Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
* All rights reserved.
@@ -30,72 +32,103 @@
#include <stdio.h>
#include <zlib.h>
-#define VER_MAJ 0
-#define VER_MIN 9
+#define VERSION "20031230"
+
+#define GREP_READ 0
+#define GREP_SKIP 1
+#define GREP_RECURSE 2
+
+#define BIN_FILE_BIN 0
+#define BIN_FILE_SKIP 1
+#define BIN_FILE_TEXT 2
+
+#define LINK_EXPLICIT 0
+#define LINK_FOLLOW 1
+#define LINK_SKIP 2
+
+#define MAX_LINE_MATCHES 30
typedef struct {
- size_t len;
- int line_no;
- int off;
- char *file;
- char *dat;
+ size_t len;
+ int line_no;
+ int off;
+ char *file;
+ char *dat;
} str_t;
/* Flags passed to regcomp() and regexec() */
-extern int cflags, eflags;
+extern int cflags, eflags;
/* Command line flags */
-extern int Aflag, Bflag, Hflag, Lflag, Pflag, Sflag, Rflag, Zflag,
- aflag, bflag, cflag, hflag, lflag, nflag, qflag, sflag,
- vflag, wflag, xflag;
+extern int Aflag, Bflag, Fflag, Lflag, bflag, cflag, lflag, mflag,
+ nflag, oflag, qflag, sflag, vflag, wflag, xflag;
+
+extern int colours;
+extern const char *grep_colour;
+extern char fn_endchar, fn_colonchar, fn_dashchar;
+extern char line_endchar;
+
+extern int output_filenames;
-extern int first, lead, matchall, patterns, tail;
-extern char **pattern;
-extern regex_t *r_pattern;
+extern int maxcount;
-/* For regex errors */
-#define RE_ERROR_BUF 512
-extern char re_error[RE_ERROR_BUF + 1]; /* Seems big enough */
+/* Argv[0] flags */
+extern int zgrep;
+
+extern int binbehave, dirbehave, devbehave;
+/* extern int linkbehave; */
+extern char *stdin_label;
+
+extern int first, matchall, patterns, tail;
+extern char **pattern;
+extern regex_t *r_pattern;
+
+/*
+ * For regex errors, 512 seems to be big enough
+ */
+#define RE_ERROR_BUF 512
+
+extern char re_error[RE_ERROR_BUF + 1];
/* util.c */
-int procfile(char *fn);
-int grep_tree(char **argv);
-void *grep_malloc(size_t size);
-void *grep_realloc(void *ptr, size_t size);
-void printline(str_t *line, int sep);
+int procfile(char *fn);
+int grep_tree(char **argv);
+
+void *grep_malloc(size_t size);
+void *grep_realloc(void *ptr, size_t size);
+void printline(str_t *line, int sep, regmatch_t *matches, int m);
/* queue.c */
-void initqueue();
-void enqueue(str_t *x);
-void printqueue();
-void clearqueue();
+void initqueue(void);
+void enqueue(str_t *x);
+void printqueue(void);
+void clearqueue(void);
/* mmfile.c */
typedef struct mmfile {
- int fd;
- size_t len;
- char *base, *end, *ptr;
+ int fd;
+ size_t len;
+ char *base, *end, *ptr;
} mmf_t;
-mmf_t *mmopen(char *fn, char *mode);
-void mmclose(mmf_t *mmf);
-char *mmfgetln(mmf_t *mmf, size_t *l);
-long mmtell(mmf_t *mmf);
-void mmrewind(mmf_t *mmf);
+mmf_t *mmopen(char *fn, char *mode);
+void mmclose(mmf_t *mmf);
+char *mmfgetln(mmf_t *mmf, size_t *l);
+void mmrewind(mmf_t *mmf);
/* file.c */
struct file;
typedef struct file file_t;
-file_t *grep_fdopen(int fd, char *mode);
-file_t *grep_open(char *path, char *mode);
-int grep_bin_file(file_t *f);
-long grep_tell(file_t *f);
-char *grep_fgetln(file_t *f, size_t *l);
-void grep_close(file_t *f);
+file_t *grep_fdopen(int fd, char *mode);
+file_t *grep_open(char *path, char *mode);
+
+int grep_bin_file(file_t *f);
+char *grep_fgetln(file_t *f, size_t *l);
+void grep_close(file_t *f);
/* binary.c */
-int bin_file(FILE * f);
-int gzbin_file(gzFile * f);
-int mmbin_file(mmf_t *f);
+int bin_file(FILE * f);
+int gzbin_file(gzFile * f);
+int mmbin_file(mmf_t *f);
View
26 usr.bin/grep/mmfile.c
@@ -1,3 +1,5 @@
+/* $NetBSD: mmfile.c,v 1.1.1.2 2004/01/02 15:00:34 cjep Exp $ */
+
/*-
* Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
* All rights reserved.
@@ -23,9 +25,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: mmfile.c,v 1.1.1.1 2004/01/02 14:58:44 cjep Exp $
*/
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: mmfile.c,v 1.1.1.2 2004/01/02 15:00:34 cjep Exp $");
+#endif /* not lint */
+
#include <sys/param.h>
#include <sys/mman.h>
#include <sys/stat.h>
@@ -47,19 +53,19 @@ mmopen(char *fn, char *mode)
/* XXX ignore mode for now */
mode = mode;
-
+
mmf = grep_malloc(sizeof *mmf);
if ((mmf->fd = open(fn, O_RDONLY)) == -1)
goto ouch1;
if (fstat(mmf->fd, &st) == -1)
goto ouch2;
- if (st.st_size > SIZE_T_MAX) /* too big to mmap */
+ if (st.st_size > SIZE_T_MAX) /* too big to mmap */
goto ouch2;
- if ((st.st_mode & S_IFREG) == 0) /* only mmap regular files */
+ if ((st.st_mode & S_IFREG) == 0) /* only mmap regular files */
goto ouch2;
mmf->len = (size_t)st.st_size;
mmf->base = mmap(NULL, mmf->len, PROT_READ, MAP_PRIVATE, mmf->fd, 0);
- if (mmf->base == NULL)
+ if (mmf->base == MAP_FAILED)
goto ouch2;
mmf->ptr = mmf->base;
mmf->end = mmf->base + mmf->len;
@@ -89,21 +95,15 @@ mmfgetln(mmf_t *mmf, size_t *l)
if (mmf->ptr >= mmf->end)
return NULL;
for (p = mmf->ptr; mmf->ptr < mmf->end; ++mmf->ptr)
- if (*mmf->ptr == '\n')
+ if (*mmf->ptr == line_endchar)
break;
*l = mmf->ptr - p;
++mmf->ptr;
return p;
}
-long
-mmtell(mmf_t *mmf)
-{
- return mmf->ptr - mmf->base;
-}
-
void
mmrewind(mmf_t *mmf)
{
- mmf->ptr = mmf->base;
+ mmf->ptr = mmf->base;
}
View
30 usr.bin/grep/queue.c
@@ -1,3 +1,5 @@
+/* $NetBSD: queue.c,v 1.1.1.2 2004/01/02 15:00:34 cjep Exp $ */
+
/*-
* Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
* All rights reserved.
@@ -23,9 +25,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: queue.c,v 1.1.1.1 2004/01/02 14:58:43 cjep Exp $
*/
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: queue.c,v 1.1.1.2 2004/01/02 15:00:34 cjep Exp $");
+#endif /* not lint */
+
/*
* A really poor man's queue. It does only what it has to and gets out of
* Dodge.
@@ -39,14 +45,14 @@
#include "grep.h"
typedef struct queue {
- struct queue *next;
- str_t data;
+ struct queue *next;
+ str_t data;
} queue_t;
-static queue_t *q_head, *q_tail;
-static int count;
+static queue_t *q_head, *q_tail;
+static int count;
-static queue_t *dequeue(void);
+static queue_t *dequeue(void);
void
initqueue(void)
@@ -63,7 +69,7 @@ free_item(queue_t *item)
void
enqueue(str_t *x)
{
- queue_t *item;
+ queue_t *item;
item = grep_malloc(sizeof *item + x->len);
item->data.len = x->len;
@@ -88,7 +94,7 @@ enqueue(str_t *x)
static queue_t *
dequeue(void)
{
- queue_t *item;
+ queue_t *item;
if (q_head == NULL)
return NULL;
@@ -107,7 +113,7 @@ printqueue(void)
queue_t *item;
while ((item = dequeue()) != NULL) {
- printline(&item->data, '-');
+ printline(&item->data, fn_dashchar, (regmatch_t *)NULL, 0);
free_item(item);
}
}
@@ -120,9 +126,3 @@ clearqueue(void)
while ((item = dequeue()) != NULL)
free_item(item);
}
-
-int
-countqueue(void)
-{
- return count;
-}
View
221 usr.bin/grep/util.c
@@ -1,3 +1,5 @@
+/* $NetBSD: util.c,v 1.1.1.2 2004/01/02 15:00:34 cjep Exp $ */
+
/*-
* Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
* All rights reserved.
@@ -23,9 +25,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: util.c,v 1.1.1.1 2004/01/02 14:58:43 cjep Exp $
*/
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: util.c,v 1.1.1.2 2004/01/02 15:00:34 cjep Exp $");
+#endif /* not lint */
+
#include <sys/types.h>
#include <sys/stat.h>
@@ -46,37 +52,42 @@
* Process a file line by line...
*/
-static int linesqueued;
-static int procline(str_t *l);
+static int linesqueued, newfile;
+static int procline(str_t *l, int nottext);
int
grep_tree(char **argv)
{
- FTS *fts;
- FTSENT *p;
- int c, fts_flags;
+ FTS *fts;
+ FTSENT *p;
+ int c, fts_flags;
c = fts_flags = 0;
- if (Hflag)
+/* if (linkbehave == LINK_EXPLICIT)
fts_flags = FTS_COMFOLLOW;
- if (Pflag)
+ if (linkbehave == LINK_SKIP)
fts_flags = FTS_PHYSICAL;
- if (Sflag)
- fts_flags = FTS_LOGICAL;
+ if (linkbehave == LINK_FOLLOW)
+ fts_flags = FTS_LOGICAL;*/
- fts_flags |= FTS_NOSTAT | FTS_NOCHDIR;
+ fts_flags |= FTS_NOSTAT | FTS_NOCHDIR | FTS_LOGICAL;
- if (!(fts = fts_open(argv, fts_flags, (int (*) ()) NULL)))
- err(1, NULL);
+ if ((fts = fts_open(argv, fts_flags, NULL)) == NULL)
+ err(2, NULL);
while ((p = fts_read(fts)) != NULL) {
switch (p->fts_info) {
case FTS_DNR:
break;
case FTS_ERR:
- errx(1, "%s: %s", p->fts_path, strerror(p->fts_errno));
+ errx(2, "%s: %s", p->fts_path, strerror(p->fts_errno));
break;
case FTS_DP:
+ case FTS_D:
+ break;
+ case FTS_DC:
+ warnx("warning: %s: recursive directory loop\n",
+ p->fts_path);
break;
default:
c += procfile(p->fts_path);
@@ -92,12 +103,36 @@ procfile(char *fn)
{
str_t ln;
file_t *f;
- int c, t, z;
+ struct stat sb;
+ mode_t s;
+ int c, t, z, nottext, skip;
+
+ tail = 0;
+ newfile = 1;
if (fn == NULL) {
- fn = "(standard input)";
+ fn = stdin_label;
f = grep_fdopen(STDIN_FILENO, "r");
} else {
+ skip = 1;
+ if (dirbehave == GREP_SKIP || devbehave == GREP_SKIP) {
+ if (stat(fn, &sb)) {
+ fprintf(stderr, "Cannot stat %s %d\n",
+ fn, errno);
+ /* XXX record error variable */
+ } else {
+ s = sb.st_mode & S_IFMT;
+ if (s == S_IFDIR && dirbehave == GREP_SKIP)
+ skip = 0;
+ if ( (s == S_IFIFO || s == S_IFCHR ||
+ s == S_IFBLK || s == S_IFSOCK)
+ && devbehave == GREP_SKIP)
+ skip = 0;
+ }
+ }
+ if (skip == 0)
+ return 0;
+
f = grep_open(fn, "r");
}
if (f == NULL) {
@@ -105,7 +140,11 @@ procfile(char *fn)
warn("%s", fn);
return 0;
}
- if (aflag && grep_bin_file(f)) {
+
+ nottext = grep_bin_file(f);
+
+ if (nottext && binbehave == BIN_FILE_SKIP) {
+ /* Skip this file as it is binary */
grep_close(f);
return 0;
}
@@ -121,31 +160,40 @@ procfile(char *fn)
ln.off += ln.len + 1;
if ((ln.dat = grep_fgetln(f, &ln.len)) == NULL)
break;
- if (ln.len > 0 && ln.dat[ln.len - 1] == '\n')
+ if (ln.len > 0 && ln.dat[ln.len - 1] == line_endchar)
--ln.len;
ln.line_no++;
z = tail;
- if ((t = procline(&ln)) == 0 && Bflag > 0 && z == 0) {
+ if ((t = procline(&ln, nottext)) == 0 && Bflag > 0 && z == 0) {
enqueue(&ln);
linesqueued++;
}
c += t;
+
+ /* If we have a maximum number of matches, stop processing */
+ if (mflag && c >= maxcount)
+ break;
}
if (Bflag > 0)
clearqueue();
grep_close(f);
if (cflag) {
- if (!hflag)
- printf("%s:", ln.file);
+ if (output_filenames)
+ printf("%s%c", ln.file, fn_colonchar);
printf("%u\n", c);
- }
+ }
+
if (lflag && c != 0)
- printf("%s\n", fn);
+ printf("%s%c", fn, fn_endchar);
if (Lflag && c == 0)
- printf("%s\n", fn);
+ printf("%s%c", fn, fn_endchar);
+ if (c && !cflag && !lflag && !Lflag &&
+ binbehave == BIN_FILE_BIN && nottext && !qflag)
+ printf("Binary file %s matches\n", fn);
+
return c;
}
@@ -157,10 +205,12 @@ procfile(char *fn)
#define isword(x) (isalnum(x) || (x) == '_')
static int
-procline(str_t *l)
+procline(str_t *l, int nottext)
{
- regmatch_t pmatch;
- int c, i, r, t;
+ regmatch_t pmatch;
+ regmatch_t matches[MAX_LINE_MATCHES];
+ int c = 0, i, r, t, m = 0;
+ regoff_t st = 0;
if (matchall) {
c = !vflag;
@@ -168,44 +218,70 @@ procline(str_t *l)
}
t = vflag ? REG_NOMATCH : 0;
- pmatch.rm_so = 0;
- pmatch.rm_eo = l->len;
- for (c = i = 0; i < patterns; i++) {
- r = regexec(&r_pattern[i], l->dat, 0, &pmatch, eflags);
- if (r == REG_NOMATCH && t == 0)
- continue;
- if (r == 0) {
- if (wflag) {
- if ((pmatch.rm_so != 0 && isword(l->dat[pmatch.rm_so - 1]))
- || (pmatch.rm_eo != l->len && isword(l->dat[pmatch.rm_eo])))
- r = REG_NOMATCH;
+
+ while (st <= l->len) {
+ pmatch.rm_so = st;
+ pmatch.rm_eo = l->len;
+ for (i = 0; i < patterns; i++) {
+ r = regexec(&r_pattern[i], l->dat, 1, &pmatch, eflags);
+ if (r == REG_NOMATCH && t == 0)
+ continue;
+ if (r == 0) {
+ if (wflag) {
+ if ((pmatch.rm_so != 0 && isword(l->dat[pmatch.rm_so - 1]))
+ || (pmatch.rm_eo != l->len && isword(l->dat[pmatch.rm_eo])))
+ r = REG_NOMATCH;
+ }
+ if (xflag) {
+ if (pmatch.rm_so != 0 || pmatch.rm_eo != l->len)
+ r = REG_NOMATCH;
+ }
}
- if (xflag) {
- if (pmatch.rm_so != 0 || pmatch.rm_eo != l->len)
- r = REG_NOMATCH;
+ if (r == t) {
+ if (m == 0)
+ c++;
+ if (m < MAX_LINE_MATCHES) {
+ matches[m] = pmatch;
+ m++;
+ }
+ st = pmatch.rm_eo;
+ break;
}
}
- if (r == t) {
- c++;
+
+ /* One pass if we are not recording matches */
+ if (!oflag && !colours)
break;
- }
+
+ if (st == pmatch.rm_so)
+ break; /* No matches */
+
}
print:
+
+ if (c && binbehave == BIN_FILE_BIN && nottext)
+ return c; /* Binary file */
+
if ((tail > 0 || c) && !cflag && !qflag) {
if (c) {
- if (first > 0 && tail == 0 && (Bflag < linesqueued) && (Aflag || Bflag))
- printf("--\n");
+
+ if ( (Aflag || Bflag) && first > 0 &&
+ ( (Bflag <= linesqueued && tail == 0) || newfile) )
+ printf("--\n");
+
first = 1;
+ newfile = 0;
tail = Aflag;
if (Bflag > 0)
printqueue();
linesqueued = 0;
- printline(l, ':');
+ printline(l, fn_colonchar, matches, m);
} else {
- printline(l, '-');
+ printline(l, fn_dashchar, matches, m);
tail--;
}
+
}
return c;
}
@@ -213,10 +289,10 @@ procline(str_t *l)
void *
grep_malloc(size_t size)
{
- void *ptr;
+ void *ptr;
if ((ptr = malloc(size)) == NULL)
- err(1, "malloc");
+ err(2, "malloc");
return ptr;
}
@@ -224,17 +300,17 @@ void *
grep_realloc(void *ptr, size_t size)
{
if ((ptr = realloc(ptr, size)) == NULL)
- err(1, "realloc");
+ err(2, "realloc");
return ptr;
}
void
-printline(str_t *line, int sep)
+printline(str_t *line, int sep, regmatch_t *matches, int m)
{
- int n;
-
- n = 0;
- if (!hflag) {
+ int i, n = 0;
+ size_t a = 0;
+
+ if (output_filenames) {
fputs(line->file, stdout);
++n;
}
@@ -251,6 +327,35 @@ printline(str_t *line, int sep)
}
if (n)
putchar(sep);
- fwrite(line->dat, line->len, 1, stdout);
- putchar('\n');
+
+ if ((oflag || colours) && m > 0) {
+
+ for (i = 0; i < m; i++) {
+
+ if (!oflag)
+ fwrite(line->dat + a, matches[i].rm_so - a, 1, stdout);
+
+ if (colours)
+ fprintf(stdout, "\33[%sm", grep_colour);
+ fwrite(line->dat + matches[i].rm_so,
+ matches[i].rm_eo - matches[i].rm_so, 1, stdout);
+
+ if (colours)
+ fprintf(stdout, "\33[00m");
+ a = matches[i].rm_eo;
+ if (oflag)
+ putchar('\n');
+ }
+ if (!oflag) {
+ if (line->len - a > 0)
+ fwrite(line->dat + a, line->len - a, 1, stdout);
+ putchar('\n');
+ }
+
+
+ } else {
+ fwrite(line->dat, line->len, 1, stdout);
+ putchar(line_endchar);
+ }
+
}

0 comments on commit 271df26

Please sign in to comment.
Something went wrong with that request. Please try again.