bsdgrep: add -z/--null-data support

-z treats input and output data as sequences of lines terminated by a
zero byte instead of a newline. This brings it more in line with GNU grep
and brings us closer to passing the current tests with BSD grep.

Submitted by:	Kyle Evans <kevans91 at ksu.edu>
Reviewed by:	cem
Relnotes:	Yes
Differential Revision:	https://reviews.freebsd.org/D10101
This commit is contained in:
Ed Maste 2017-04-17 13:14:18 +00:00
parent 46f48ee519
commit 5ee1ea02fd
5 changed files with 21 additions and 10 deletions

View File

@ -197,7 +197,7 @@ grep_fgetln(struct file *f, size_t *lenp)
}
/* Look for a newline in the remaining part of the buffer */
if ((p = memchr(bufpos, '\n', bufrem)) != NULL) {
if ((p = memchr(bufpos, fileeol, bufrem)) != NULL) {
++p; /* advance over newline */
ret = bufpos;
len = p - bufpos;
@ -219,7 +219,7 @@ grep_fgetln(struct file *f, size_t *lenp)
if (bufrem == 0)
/* EOF: return partial line */
break;
if ((p = memchr(bufpos, '\n', bufrem)) == NULL &&
if ((p = memchr(bufpos, fileeol, bufrem)) == NULL &&
filebehave != FILE_MMAP)
continue;
if (p == NULL) {
@ -322,7 +322,8 @@ grep_open(const char *path)
goto error2;
/* Check for binary stuff, if necessary */
if (binbehave != BINFILE_TEXT && memchr(bufpos, '\0', bufrem) != NULL)
if (binbehave != BINFILE_TEXT && fileeol != '\0' &&
memchr(bufpos, '\0', bufrem) != NULL)
f->binary = true;
return (f);

View File

@ -30,7 +30,7 @@
.\"
.\" @(#)grep.1 8.3 (Berkeley) 4/18/94
.\"
.Dd July 28, 2010
.Dd April 17, 2017
.Dt GREP 1
.Os
.Sh NAME
@ -40,7 +40,7 @@
.Sh SYNOPSIS
.Nm grep
.Bk -words
.Op Fl abcdDEFGHhIiJLlmnOopqRSsUVvwxZ
.Op Fl abcdDEFGHhIiJLlmnOopqRSsUVvwxZz
.Op Fl A Ar num
.Op Fl B Ar num
.Op Fl C Ns Op Ar num
@ -378,7 +378,10 @@ expression are considered to be matching lines.
Equivalent to
.Fl i .
Obsoleted.
.It Fl Z , Fl z , Fl Fl decompress
.It Fl z , Fl Fl null-data
Treat input and output data as sequences of lines terminated by a
zero-byte instead of a newline.
.It Fl Z , Fl Fl decompress
Force
.Nm grep
to behave as

View File

@ -66,7 +66,7 @@ const char *errstr[] = {
/* 1*/ "(standard input)",
/* 2*/ "cannot read bzip2 compressed file",
/* 3*/ "unknown %s option",
/* 4*/ "usage: %s [-abcDEFGHhIiJLlmnOoPqRSsUVvwxZ] [-A num] [-B num] [-C[num]]\n",
/* 4*/ "usage: %s [-abcDEFGHhIiJLlmnOoPqRSsUVvwxZz] [-A num] [-B num] [-C[num]]\n",
/* 5*/ "\t[-e pattern] [-f file] [--binary-files=value] [--color=when]\n",
/* 6*/ "\t[--context[=num]] [--directories=action] [--label] [--line-buffered]\n",
/* 7*/ "\t[--null] [pattern] [file ...]\n",
@ -109,6 +109,7 @@ bool lflag; /* -l: only show names of files with matches */
bool mflag; /* -m x: stop reading the files after x matches */
long long mcount; /* count for -m */
long long mlimit; /* requested value for -m */
char fileeol; /* indicator for eol */
bool nflag; /* -n: show line numbers in front of matching lines */
bool oflag; /* -o: print only matching part */
bool qflag; /* -q: quiet mode (don't output anything) */
@ -165,7 +166,7 @@ usage(void)
exit(2);
}
static const char *optstr = "0123456789A:B:C:D:EFGHIJMLOPSRUVZabcd:e:f:hilm:nopqrsuvwxXy";
static const char *optstr = "0123456789A:B:C:D:EFGHIJMLOPSRUVZabcd:e:f:hilm:nopqrsuvwxXyz";
static const struct option long_options[] =
{
@ -215,6 +216,7 @@ static const struct option long_options[] =
{"word-regexp", no_argument, NULL, 'w'},
{"line-regexp", no_argument, NULL, 'x'},
{"xz", no_argument, NULL, 'X'},
{"null-data", no_argument, NULL, 'z'},
{"decompress", no_argument, NULL, 'Z'},
{NULL, no_argument, NULL, 0}
};
@ -384,6 +386,7 @@ main(int argc, char *argv[])
newarg = 1;
prevoptind = 1;
needpattern = 1;
fileeol = '\n';
eopts = getenv("GREP_OPTIONS");
@ -605,6 +608,9 @@ main(int argc, char *argv[])
case 'X':
filebehave = FILE_XZ;
break;
case 'z':
fileeol = '\0';
break;
case 'Z':
filebehave = FILE_GZIP;
break;

View File

@ -116,6 +116,7 @@ extern bool dexclude, dinclude, fexclude, finclude, lbflag, nullflag;
extern unsigned long long Aflag, Bflag;
extern long long mcount;
extern long long mlimit;
extern char fileeol;
extern char *label;
extern const char *color;
extern int binbehave, devbehave, dirbehave, filebehave, grepbehave, linkbehave;

View File

@ -221,7 +221,7 @@ procfile(const char *fn)
else
break;
}
if (ln.len > 0 && ln.dat[ln.len - 1] == '\n')
if (ln.len > 0 && ln.dat[ln.len - 1] == fileeol)
--ln.len;
ln.line_no++;
@ -530,6 +530,6 @@ printline(struct str *line, int sep, regmatch_t *matches, int m)
}
} else {
fwrite(line->dat, line->len, 1, stdout);
putchar('\n');
putchar(fileeol);
}
}