#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdarg.h>
#include <regex.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
#include <errno.h>
#include <unistd.h>
#include <wctype.h>
#include <ftw.h>
#include <sys/param.h>
#include <getopt.h>
#define STDIN_FILENAME gettext("(standard input)")
#define BSIZE 512
#define BUFSIZE 8192
#define MAX_DEPTH 1000
#define AFTER 1
#define BEFORE 2
#define CONTEXT (AFTER|BEFORE)
#define M_CSETSIZE 256
static int bmglen;
static char *bmgpat;
static int bmgtab[M_CSETSIZE];
typedef struct _PATTERN {
char *pattern;
struct _PATTERN *next;
regex_t re;
} PATTERN;
static PATTERN *patterns;
static char errstr[128];
static int regflags = 0;
static int matched = 0;
static int errors = 0;
static uchar_t fgrep = 0;
static uchar_t egrep = 0;
static boolean_t nvflag = B_TRUE;
static uchar_t cflag;
static uchar_t iflag;
static uchar_t Hflag;
static uchar_t hflag;
static uchar_t lflag;
static uchar_t Lflag;
static uchar_t nflag;
static uchar_t rflag;
static uchar_t bflag;
static uchar_t sflag;
static uchar_t qflag;
static uchar_t wflag;
static uchar_t xflag;
static uchar_t Eflag;
static uchar_t Fflag;
static uchar_t Rflag;
static uchar_t outfn;
static uchar_t conflag;
static uchar_t oflag;
static char *cmdname;
static char *stdin_label;
static int use_bmg, mblocale;
static size_t prntbuflen, conbuflen;
static unsigned long conalen, conblen, conmatches;
static char *prntbuf, *conbuf;
static void addfile(const char *fn);
static void addpattern(char *s);
static void fixpatterns(void);
static void usage(void);
static int grep(int, const char *);
static void bmgcomp(char *, int);
static char *bmgexec(char *, char *);
static int recursive(const char *, const struct stat *, int, struct FTW *);
static void process_path(const char *);
static void process_file(const char *, int);
enum grep_opts {
OPT_LABEL = SHRT_MAX + 1
};
static struct option grep_options[] = {
{ "label", required_argument, NULL, OPT_LABEL },
{ NULL }
};
int
main(int argc, char **argv)
{
char *ap, *test;
int c;
int fflag = 0;
int i, n_pattern = 0, n_file = 0;
char **pattern_list = NULL;
char **file_list = NULL;
(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
mblocale = (MB_CUR_MAX > 1);
cmdname = argv[0];
if (ap = strrchr(cmdname, '/'))
cmdname = ap + 1;
ap = cmdname;
if (*ap == 'e' || *ap == 'E') {
regflags |= REG_EXTENDED;
egrep++;
} else {
if (*ap == 'f' || *ap == 'F') {
fgrep++;
regflags |= REG_NOSPEC;
}
}
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "--") == 0)
break;
if ((argv[i][0] == '-') && isdigit(argv[i][1])) {
if (strlen(&argv[i][1]) !=
strspn(&argv[i][1], "0123456789")) {
(void) fprintf(stderr, gettext(
"%s: Bad number flag\n"), argv[0]);
usage();
}
errno = 0;
conalen = conblen = strtoul(&argv[i][1], (char **)NULL,
10);
if (errno != 0 || conalen >= ULONG_MAX) {
(void) fprintf(stderr, gettext(
"%s: Bad context argument\n"), argv[0]);
} else if (conalen)
conflag = CONTEXT;
while (i < argc) {
argv[i] = argv[i + 1];
i++;
}
argc--;
}
}
while ((c = getopt_long(argc, argv, "+vwchHilLnrbse:f:qxEFIRA:B:C:o",
grep_options, NULL)) != EOF) {
unsigned long tval;
switch (c) {
case 'v':
nvflag = B_FALSE;
break;
case 'c':
cflag++;
break;
case 'i':
iflag++;
regflags |= REG_ICASE;
break;
case 'l':
lflag++;
Lflag = 0;
break;
case 'L':
Lflag++;
lflag = 0;
break;
case 'n':
nflag++;
break;
case 'r':
rflag++;
break;
case 'b':
bflag++;
break;
case 's':
sflag++;
break;
case 'e':
n_pattern++;
pattern_list = realloc(pattern_list,
sizeof (char *) * n_pattern);
if (pattern_list == NULL) {
(void) fprintf(stderr,
gettext("%s: out of memory\n"),
cmdname);
exit(2);
}
*(pattern_list + n_pattern - 1) = optarg;
break;
case 'f':
fflag = 1;
n_file++;
file_list = realloc(file_list,
sizeof (char *) * n_file);
if (file_list == NULL) {
(void) fprintf(stderr,
gettext("%s: out of memory\n"),
cmdname);
exit(2);
}
*(file_list + n_file - 1) = optarg;
break;
case 'h':
hflag = 1;
Hflag = 0;
break;
case 'H':
Hflag = 1;
hflag = 0;
break;
case 'q':
qflag++;
break;
case 'w':
wflag++;
break;
case 'x':
xflag++;
break;
case 'E':
regflags |= REG_EXTENDED;
Eflag++;
break;
case 'F':
Fflag++;
regflags |= REG_NOSPEC;
break;
case 'R':
Rflag++;
rflag++;
break;
case 'A':
errno = 0;
conalen = strtoul(optarg, &test, 10);
if (errno != 0 || *test != '\0' ||
conalen >= ULONG_MAX) {
(void) fprintf(stderr, gettext(
"%s: Bad context argument: %s\n"),
argv[0], optarg);
exit(2);
}
if (conalen)
conflag |= AFTER;
else
conflag &= ~AFTER;
break;
case 'B':
errno = 0;
conblen = strtoul(optarg, &test, 10);
if (errno != 0 || *test != '\0' ||
conblen >= ULONG_MAX) {
(void) fprintf(stderr, gettext(
"%s: Bad context argument: %s\n"),
argv[0], optarg);
exit(2);
}
if (conblen)
conflag |= BEFORE;
else
conflag &= ~BEFORE;
break;
case 'C':
errno = 0;
tval = strtoul(optarg, &test, 10);
if (errno != 0 || *test != '\0' || tval >= ULONG_MAX) {
(void) fprintf(stderr, gettext(
"%s: Bad context argument: %s\n"),
argv[0], optarg);
exit(2);
}
if (tval) {
if ((conflag & BEFORE) == 0)
conblen = tval;
if ((conflag & AFTER) == 0)
conalen = tval;
conflag = CONTEXT;
}
break;
case OPT_LABEL:
stdin_label = optarg;
break;
case 'o':
oflag++;
break;
default:
usage();
}
}
if (egrep || fgrep) {
if (Eflag || Fflag)
usage();
if (wflag)
usage();
if (sflag)
qflag++;
if (egrep)
Eflag++;
else
Fflag++;
}
if (wflag && (Eflag || Fflag)) {
usage();
}
if (Eflag && Fflag)
usage();
if (lflag || Lflag) {
Hflag = 0;
oflag = 0;
}
if (cflag) {
lflag = 0;
Lflag = 0;
oflag = 0;
}
if (oflag) {
conflag = 0;
}
if (oflag && !nvflag) {
(void) fprintf(stderr, gettext("%s: the combination of -v and "
"-o is not supported currently\n"), argv[0]);
exit(2);
}
argv += optind - 1;
argc -= optind - 1;
if (pattern_list) {
for (i = 0; i < n_pattern; i++) {
addpattern(pattern_list[i]);
}
free(pattern_list);
}
if (file_list) {
for (i = 0; i < n_file; i++) {
addfile(file_list[i]);
}
free(file_list);
}
if (patterns == NULL && !fflag) {
if (argc < 2)
usage();
addpattern(argv[1]);
argc--;
argv++;
}
fixpatterns();
if (stdin_label == NULL) {
stdin_label = STDIN_FILENAME;
}
if (argc < 2) {
matched = grep(0, stdin_label);
} else {
if (Hflag || (argc > 2 && hflag == 0))
outfn = 1;
for (argv++; *argv != NULL; argv++) {
process_path(*argv);
}
}
(void) fflush(stdout);
if (errors)
return (2);
return (matched ? 0 : 1);
}
static void
process_path(const char *path)
{
struct stat st;
int walkflags = FTW_CHDIR;
char *buf = NULL;
if (rflag) {
if (stat(path, &st) != -1 &&
(st.st_mode & S_IFMT) == S_IFDIR) {
if (!hflag)
outfn = 1;
if (path[strlen(path) - 1] != '/') {
(void) asprintf(&buf, "%s/", path);
if (buf != NULL)
path = buf;
}
if (!Rflag)
walkflags |= FTW_PHYS;
if (nftw(path, recursive, MAX_DEPTH, walkflags) != 0) {
if (!sflag)
(void) fprintf(stderr,
gettext("%s: can't open \"%s\"\n"),
cmdname, path);
errors = 1;
}
return;
}
}
process_file(path, 0);
}
static int
recursive(const char *name, const struct stat *statp, int info, struct FTW *ftw)
{
if (info != FTW_F) {
if (!sflag &&
(info == FTW_SLN || info == FTW_DNR || info == FTW_NS)) {
(void) fprintf(stderr,
gettext("%s: can't open \"%s\"\n"), cmdname, name);
}
return (0);
}
if (!Rflag && !S_ISREG(statp->st_mode))
return (0);
process_file(name, ftw->base);
return (0);
}
static void
process_file(const char *name, int base)
{
int fd;
if ((fd = open(name + base, O_RDONLY)) == -1) {
errors = 1;
if (!sflag)
(void) fprintf(stderr, gettext(
"%s: can't open \"%s\"\n"),
cmdname, name);
return;
}
matched |= grep(fd, name);
(void) close(fd);
if (ferror(stdout)) {
(void) fprintf(stderr, gettext(
"%s: error writing to stdout\n"),
cmdname);
(void) fflush(stdout);
exit(2);
}
}
static void
addfile(const char *fn)
{
FILE *fp;
char *inbuf;
char *bufp;
size_t bufsiz, buflen, bufused;
if ((fp = fopen(fn, "r")) == NULL) {
(void) fprintf(stderr, gettext("%s: can't open \"%s\"\n"),
cmdname, fn);
exit(2);
}
bufsiz = BUFSIZE;
if ((inbuf = malloc(bufsiz)) == NULL) {
(void) fprintf(stderr,
gettext("%s: out of memory\n"), cmdname);
exit(2);
}
bufp = inbuf;
bufused = 0;
while (fgets(bufp, bufsiz - bufused, fp) != NULL) {
buflen = strlen(bufp);
bufused += buflen;
if (bufused + 1 == bufsiz && bufp[buflen - 1] != '\n') {
bufsiz += BUFSIZE;
if ((inbuf = realloc(inbuf, bufsiz)) == NULL) {
(void) fprintf(stderr,
gettext("%s: out of memory\n"),
cmdname);
exit(2);
}
bufp = inbuf + bufused;
continue;
}
if (bufp[buflen - 1] == '\n') {
bufp[--buflen] = '\0';
}
addpattern(inbuf);
bufp = inbuf;
bufused = 0;
}
free(inbuf);
free(prntbuf);
free(conbuf);
(void) fclose(fp);
}
static void
addpattern(char *s)
{
PATTERN *pp;
char *wordbuf;
char *np;
for (; ; ) {
np = strchr(s, '\n');
if (np != NULL)
*np = '\0';
if ((pp = malloc(sizeof (PATTERN))) == NULL) {
(void) fprintf(stderr, gettext(
"%s: out of memory\n"),
cmdname);
exit(2);
}
if (wflag) {
size_t slen, wordlen;
slen = strlen(s);
wordlen = slen + 5;
if ((wordbuf = malloc(wordlen)) == NULL) {
(void) fprintf(stderr,
gettext("%s: out of memory\n"),
cmdname);
exit(2);
}
(void) strcpy(wordbuf, "\\<");
(void) strcpy(wordbuf + 2, s);
(void) strcpy(wordbuf + 2 + slen, "\\>");
} else {
if ((wordbuf = strdup(s)) == NULL) {
(void) fprintf(stderr,
gettext("%s: out of memory\n"),
cmdname);
exit(2);
}
}
pp->pattern = wordbuf;
pp->next = patterns;
patterns = pp;
if (np == NULL)
break;
s = np + 1;
}
}
static boolean_t
simple_pattern(const char *str)
{
for (; *str != '\0'; str++) {
if (!isascii(*str)) {
return (B_FALSE);
}
if (isalnum(*str)) {
continue;
}
switch (*str) {
case '!':
case '@':
case '#':
case '/':
case '-':
case '_':
case '<':
case '>':
case '=':
continue;
default:
return (B_FALSE);
}
}
return (B_TRUE);
}
static void
fixpatterns(void)
{
PATTERN *pp;
int rv, fix_pattern;
use_bmg = !mblocale && !iflag && !nflag && nvflag && !oflag &&
(patterns != NULL && patterns->next == NULL) && !wflag &&
(strlen(patterns->pattern) != 0) && conflag == 0 &&
(Fflag || simple_pattern(patterns->pattern));
if (use_bmg) {
return;
}
fix_pattern = !Fflag && xflag;
for (pp = patterns; pp != NULL; pp = pp->next) {
if (fix_pattern) {
char *cp, *cq;
size_t plen, nplen;
plen = strlen(pp->pattern);
nplen = 1 + plen + 1 + 1;
if ((cp = malloc(nplen)) == NULL) {
(void) fprintf(stderr,
gettext("%s: out of memory\n"),
cmdname);
exit(2);
}
cq = cp;
*cq++ = '^';
cq = strcpy(cq, pp->pattern) + plen;
*cq++ = '$';
*cq = '\0';
free(pp->pattern);
pp->pattern = cp;
}
if ((rv = regcomp(&pp->re, pp->pattern, regflags)) != 0) {
(void) regerror(rv, &pp->re, errstr, sizeof (errstr));
(void) fprintf(stderr,
gettext("%s: RE error in %s: %s\n"),
cmdname, pp->pattern, errstr);
exit(2);
}
free(pp->pattern);
}
}
static char *
find_nl(const char *ptr, size_t len)
{
while (len-- != 0) {
if (*ptr++ == '\n') {
return ((char *)--ptr);
}
}
return (NULL);
}
static char *
rfind_nl(const char *ptr, size_t len)
{
const char *uptr = ptr + len;
while (len--) {
if (*--uptr == '\n') {
return ((char *)uptr);
}
}
return (NULL);
}
static int
grep(int fd, const char *fn)
{
PATTERN *pp;
off_t data_len;
off_t line_len;
off_t line_offset;
off_t blkoffset;
long long lineno, linenum;
long long matches = 0;
long long conacnt = 0, conbcnt = 0;
int newlinep;
char *ptr, *ptrend, *prntptr, *prntptrend;
char *nextptr = NULL, *nextend = NULL;
char *conptr = NULL, *conptrend = NULL;
char *matchptr = NULL;
int conaprnt = 0, conbprnt = 0, lastmatch = 0;
boolean_t nearmatch;
boolean_t havematch = B_FALSE;
boolean_t sameline = B_FALSE;
size_t prntlen;
if (patterns == NULL)
return (0);
pp = patterns;
if (use_bmg) {
bmgcomp(pp->pattern, strlen(pp->pattern));
}
if (prntbuf == NULL) {
prntbuflen = BUFSIZE;
if ((prntbuf = malloc(prntbuflen + 1)) == NULL) {
(void) fprintf(stderr, gettext("%s: out of memory\n"),
cmdname);
exit(2);
}
}
if (conflag != 0 && (conbuf == NULL)) {
conbuflen = BUFSIZE;
if ((conbuf = malloc(BUFSIZE+1)) == NULL) {
(void) fprintf(stderr, gettext("%s: out of memory\n"),
cmdname);
exit(2);
}
}
nearmatch = (conmatches != 0);
blkoffset = line_offset = 0;
lineno = 0;
linenum = 1;
newlinep = 1;
data_len = 0;
for (; ; ) {
long count;
off_t offset = 0;
char separate;
char *startmatch = NULL;
char *postmatch = NULL;
boolean_t last_ctx = B_FALSE, eof = B_FALSE;
if (data_len == 0) {
ptr = prntbuf;
if (conflag != 0 && conptr == NULL) {
conptr = conbuf;
conptrend = conptr - 1;
}
}
if (ptr == prntbuf) {
count = read(fd, ptr + data_len, prntbuflen - data_len);
if (count < 0) {
if (cflag) {
if (outfn && !rflag) {
(void) fprintf(stdout,
"%s:", fn);
}
if (!qflag && !rflag) {
(void) fprintf(stdout, "%lld\n",
matches);
}
}
return (0);
} else if (count == 0) {
eof = B_TRUE;
if (data_len == 0) {
if (conflag != 0) {
if (conptrend >= conptr)
*conptrend = '\n';
last_ctx = B_TRUE;
goto L_next_line;
} else {
goto out;
}
}
ptrend = ptr + data_len;
newlinep = 0;
goto L_start_process;
}
offset = data_len;
data_len += count;
}
ptrend = find_nl(ptr + offset, data_len - offset);
if (ptrend == NULL) {
if (ptr > prntbuf) {
(void) memmove(prntbuf, ptr, data_len);
}
if (data_len == prntbuflen) {
if (prntbuflen > SIZE_MAX - BUFSIZE) {
(void) fprintf(stderr,
gettext("%s: buflen would"
" overflow\n"),
cmdname);
exit(2);
}
prntbuflen += BUFSIZE;
prntbuf = realloc(prntbuf, prntbuflen + 1);
if (prntbuf == NULL) {
(void) fprintf(stderr,
gettext("%s: out of memory\n"),
cmdname);
exit(2);
}
}
ptr = prntbuf;
continue;
}
L_start_process:
if (use_bmg) {
char *bline;
bline = bmgexec(ptr, ptr + data_len);
if (bline == NULL) {
ptrend = rfind_nl(ptr, data_len);
line_len = ptrend - ptr;
goto L_skip_line;
}
if (bline > ptrend) {
line_len = ptrend - ptr;
goto L_skip_line;
}
*ptrend = '\0';
line_len = ptrend - ptr;
if (xflag && (line_len != bmglen ||
strcmp(bmgpat, ptr) != 0)) {
pp = NULL;
} else {
pp = patterns;
}
goto L_next_line;
}
if (!sameline) {
lineno++;
} else {
sameline = B_FALSE;
}
*ptrend = '\0';
line_len = ptrend - ptr;
for (pp = patterns; pp; pp = pp->next) {
int rv;
regmatch_t rm;
size_t nmatch = 0;
if (oflag || (Fflag && xflag))
nmatch = 1;
rv = regexec(&pp->re, ptr, nmatch, &rm, 0);
if (rv == REG_OK) {
if (Fflag && xflag &&
line_len != rm.rm_eo - rm.rm_so) {
continue;
}
if (oflag) {
startmatch = ptr + rm.rm_so;
postmatch = ptr + rm.rm_eo;
}
break;
}
switch (rv) {
case REG_NOMATCH:
break;
case REG_ECHAR:
(void) fprintf(stderr, gettext(
"%s: input file \"%s\": line %lld: invalid multibyte character\n"),
cmdname, fn, lineno);
break;
default:
(void) regerror(rv, &pp->re, errstr,
sizeof (errstr));
(void) fprintf(stderr, gettext(
"%s: input file \"%s\": line %lld: %s\n"),
cmdname, fn, lineno, errstr);
exit(2);
}
}
if (conflag == 0)
goto L_next_line;
while ((line_len + 1) > (conbuflen -
((conptrend >= conptr) ? conptrend - conbuf : 0))) {
char *oldconbuf = conbuf;
char *oldconptr = conptr;
long tmp = matchptr - conptr;
if (conbuflen > SIZE_MAX - BUFSIZE) {
(void) fprintf(stderr,
gettext("%s: buflen would overflow\n"),
cmdname);
exit(2);
}
conbuflen += BUFSIZE;
conbuf = realloc(conbuf, conbuflen + 1);
if (conbuf == NULL) {
(void) fprintf(stderr,
gettext("%s: out of memory\n"),
cmdname);
exit(2);
}
conptr = conbuf + (conptr - oldconbuf);
conptrend = conptr + (conptrend - oldconptr);
if (matchptr)
matchptr = conptr + tmp;
}
(void) memcpy(conptrend + 1, ptr, line_len);
conptrend += line_len + 1;
*conptrend = '\n';
if (nvflag == (pp != NULL)) {
if (havematch) {
if ((conflag & AFTER) != 0) {
conaprnt = 1;
nextend = conptrend;
conptrend = conptr + lastmatch;
nextptr = conptrend + 1;
*nextend = '\n';
}
} else {
if (conflag == AFTER) {
conptr = conptrend - (line_len);
linenum = lineno;
}
blkoffset = line_offset -
(conptrend - conptr - line_len);
}
if (conflag == BEFORE)
conbprnt = 1;
lastmatch = conptrend - conptr;
havematch = B_TRUE;
goto L_next_line;
}
if (!havematch) {
if ((conflag & BEFORE) != 0) {
if (conbcnt >= conblen) {
char *tmp = conptr;
conptr = find_nl(conptr,
conptrend - conptr) + 1;
if (bflag)
blkoffset += conptr - tmp;
linenum++;
nearmatch = B_TRUE;
} else {
conbcnt++;
}
}
if (conflag == AFTER)
nearmatch = B_TRUE;
} else {
if (++conacnt >= conalen && !conaprnt && conalen)
conaprnt = 1;
else
lastmatch = conptrend - conptr;
}
L_next_line:
if (!last_ctx && nvflag == (pp != NULL)) {
matches++;
if (!nextend) {
if (conflag != 0) {
matchptr = conptrend;
} else if (oflag) {
matchptr = postmatch - 1;
} else {
matchptr = ptrend;
}
}
}
if (pp != NULL && oflag && postmatch == NULL) {
(void) fprintf(stderr, gettext("%s: internal error, "
"-o set, but failed to find postmatch\n"), cmdname);
abort();
}
if (havematch && (eof || conaprnt || conbprnt)) {
if (eof && nextptr)
conptrend = nextend;
prntlen = conptrend - conptr + 1;
prntptr = conptr;
if (conmatches++ && nearmatch && !cflag)
(void) fwrite("--\n", 1, 3, stdout);
} else if (conflag == 0 && nvflag == (pp != NULL)) {
*ptrend = '\n';
if (oflag) {
prntptr = startmatch;
} else {
prntptr = ptr;
}
prntlen = line_len + 1;
linenum = lineno;
blkoffset = line_offset;
if (oflag) {
blkoffset += startmatch - ptr;
}
} else if (eof) {
goto out;
} else {
goto L_skip_line;
}
if (oflag) {
prntptrend = postmatch - 1;
} else {
prntptrend = prntptr - 1;
}
while (oflag || (prntptrend = find_nl(prntptrend + 1,
prntlen)) != NULL) {
if (prntptrend == matchptr) {
if (eof && nextptr) {
matchptr = nextend;
nextptr = NULL;
} else {
matchptr = NULL;
}
separate = ':';
} else {
separate = '-';
}
if (qflag) {
off_t pos;
pos = ptr + data_len - (ptrend + 1);
(void) lseek(fd, -pos, SEEK_CUR);
exit(0);
}
if (lflag) {
(void) printf("%s\n", fn);
goto out;
}
if (Lflag) {
goto out;
}
if (!cflag) {
if (Hflag || outfn) {
(void) printf("%s%c", fn, separate);
}
if (bflag) {
(void) printf("%lld%c", (offset_t)
(blkoffset / BSIZE), separate);
}
if (nflag) {
(void) printf("%lld%c", linenum,
separate);
}
(void) fwrite(prntptr, 1,
prntptrend - prntptr + 1, stdout);
if (oflag) {
(void) fputc('\n', stdout);
}
}
if (ferror(stdout)) {
return (0);
}
if (oflag) {
goto L_skip_line;
}
linenum++;
prntlen -= prntptrend - prntptr + 1;
blkoffset += prntptrend - prntptr + 1;
prntptr = prntptrend + 1;
}
if (eof)
goto out;
if (conflag != 0) {
conptr = conbuf;
conaprnt = conbprnt = 0;
nearmatch = B_FALSE;
conacnt = conbcnt = 0;
if (nextptr) {
(void) memmove(conbuf, nextptr,
nextend - nextptr + 1);
blkoffset += nextptr - conptrend - 1;
conptrend = conptr + (nextend - nextptr);
matchptr = conptrend;
linenum = lineno;
lastmatch = conptrend - conptr;
havematch = B_TRUE;
} else {
conptrend = conptr - 1;
conacnt = 0;
lastmatch = 0;
havematch = B_FALSE;
}
nextptr = nextend = NULL;
}
L_skip_line:
if (!newlinep)
break;
if (oflag && postmatch != NULL) {
line_len = postmatch - 1 - ptr;
ptr = postmatch;
sameline = B_TRUE;
} else {
ptr = ptrend + 1;
}
data_len -= line_len + 1;
line_offset += line_len + 1;
}
out:
if (cflag) {
if (Hflag || outfn) {
(void) printf("%s:", fn);
}
if (!qflag) {
(void) printf("%lld\n", matches);
}
}
if (Lflag) {
if (matches == 0) {
(void) printf("%s\n", fn);
matches = 1;
} else {
matches = 0;
}
}
return (matches != 0);
}
static void
usage(void)
{
(void) fprintf(stderr, gettext("usage: %5s"), cmdname);
if (!egrep && !fgrep)
(void) fprintf(stderr, gettext(" [-E|-F]"));
(void) fprintf(stderr, gettext(" [-bchHilLnoqrRsvx] [-A num] [-B num] "
"[-C num|-num]\n [--label=name] [-e pattern_list]... "
"[-f pattern_file]...\n [pattern_list] [file]...\n"));
exit(2);
}
static void
bmgcomp(char *pat, int len)
{
int i;
int tlen;
unsigned char *uc = (unsigned char *)pat;
bmglen = len;
bmgpat = pat;
for (i = 0; i < M_CSETSIZE; i++) {
bmgtab[i] = len;
}
len--;
for (tlen = len, i = 0; i <= len; i++, tlen--) {
bmgtab[*uc++] = tlen;
}
}
static char *
bmgexec(char *str, char *end)
{
int t;
char *k, *s, *p;
k = str + bmglen - 1;
if (bmglen == 1) {
return (memchr(str, bmgpat[0], end - str));
}
for (; ; ) {
while (k < end && (t = bmgtab[(unsigned char)*k]) != 0) {
k += t;
}
if (k >= end) {
return (NULL);
}
for (s = k, p = bmgpat + bmglen - 1; *--s == *--p; ) {
if (p == bmgpat) {
return (s);
}
}
k++;
}
}