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:
parent
46f48ee519
commit
5ee1ea02fd
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user