2004-03-25 23:03:57 +00:00
|
|
|
#define EXTERN
|
|
|
|
#include "grep.h"
|
|
|
|
|
|
|
|
char *validflags = "bchiLlnsv";
|
|
|
|
void
|
|
|
|
usage(void)
|
|
|
|
{
|
|
|
|
fprint(2, "usage: grep [-%s] [-f file] [-e expr] [file ...]\n", validflags);
|
|
|
|
exits("usage");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
int i, status;
|
|
|
|
|
|
|
|
ARGBEGIN {
|
|
|
|
default:
|
|
|
|
if(utfrune(validflags, ARGC()) == nil)
|
|
|
|
usage();
|
|
|
|
flags[ARGC()]++;
|
|
|
|
break;
|
|
|
|
|
2005-01-13 04:49:19 +00:00
|
|
|
case 'E': /* ignore, turns gnu grep into egrep */
|
|
|
|
break;
|
|
|
|
|
2004-03-25 23:03:57 +00:00
|
|
|
case 'e':
|
|
|
|
flags['e']++;
|
|
|
|
lineno = 0;
|
|
|
|
str2top(ARGF());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'f':
|
|
|
|
flags['f']++;
|
|
|
|
filename = ARGF();
|
|
|
|
rein = Bopen(filename, OREAD);
|
|
|
|
if(rein == 0) {
|
|
|
|
fprint(2, "grep: can't open %s: %r\n", filename);
|
|
|
|
exits("open");
|
|
|
|
}
|
|
|
|
lineno = 1;
|
|
|
|
str2top(filename);
|
|
|
|
break;
|
|
|
|
} ARGEND
|
|
|
|
|
|
|
|
if(flags['f'] == 0 && flags['e'] == 0) {
|
|
|
|
if(argc <= 0)
|
|
|
|
usage();
|
|
|
|
str2top(argv[0]);
|
|
|
|
argc--;
|
|
|
|
argv++;
|
|
|
|
}
|
|
|
|
|
|
|
|
follow = mal(maxfollow*sizeof(*follow));
|
|
|
|
state0 = initstate(topre.beg);
|
|
|
|
|
|
|
|
Binit(&bout, 1, OWRITE);
|
|
|
|
switch(argc) {
|
|
|
|
case 0:
|
|
|
|
status = search(0, 0);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
status = search(argv[0], 0);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
status = 0;
|
|
|
|
for(i=0; i<argc; i++)
|
|
|
|
status |= search(argv[i], Hflag);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(status)
|
|
|
|
exits(0);
|
|
|
|
exits("no matches");
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
search(char *file, int flag)
|
|
|
|
{
|
|
|
|
State *s, *ns;
|
|
|
|
int c, fid, eof, nl, empty;
|
|
|
|
long count, lineno, n;
|
|
|
|
uchar *elp, *lp, *bol;
|
|
|
|
|
|
|
|
if(file == 0) {
|
|
|
|
file = "stdin";
|
|
|
|
fid = 0;
|
|
|
|
flag |= Bflag;
|
|
|
|
} else
|
|
|
|
fid = open(file, OREAD);
|
|
|
|
|
|
|
|
if(fid < 0) {
|
|
|
|
fprint(2, "grep: can't open %s: %r\n", file);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(flags['b'])
|
|
|
|
flag ^= Bflag; /* dont buffer output */
|
|
|
|
if(flags['c'])
|
|
|
|
flag |= Cflag; /* count */
|
|
|
|
if(flags['h'])
|
|
|
|
flag &= ~Hflag; /* do not print file name in output */
|
|
|
|
if(flags['i'])
|
|
|
|
flag |= Iflag; /* fold upper-lower */
|
|
|
|
if(flags['l'])
|
|
|
|
flag |= Llflag; /* print only name of file if any match */
|
|
|
|
if(flags['L'])
|
|
|
|
flag |= LLflag; /* print only name of file if any non match */
|
|
|
|
if(flags['n'])
|
|
|
|
flag |= Nflag; /* count only */
|
|
|
|
if(flags['s'])
|
|
|
|
flag |= Sflag; /* status only */
|
|
|
|
if(flags['v'])
|
|
|
|
flag |= Vflag; /* inverse match */
|
|
|
|
|
|
|
|
s = state0;
|
|
|
|
lineno = 0;
|
|
|
|
count = 0;
|
|
|
|
eof = 0;
|
|
|
|
empty = 1;
|
|
|
|
nl = 0;
|
2004-03-25 23:25:45 +00:00
|
|
|
lp = u.u.buf;
|
2004-03-25 23:03:57 +00:00
|
|
|
bol = lp;
|
|
|
|
|
|
|
|
loop0:
|
|
|
|
n = lp-bol;
|
2004-03-25 23:25:45 +00:00
|
|
|
if(n > sizeof(u.u.pre))
|
|
|
|
n = sizeof(u.u.pre);
|
|
|
|
memmove(u.u.buf-n, bol, n);
|
|
|
|
bol = u.u.buf-n;
|
|
|
|
n = read(fid, u.u.buf, sizeof(u.u.buf));
|
2004-03-25 23:03:57 +00:00
|
|
|
/* if file has no final newline, simulate one to emit matches to last line */
|
|
|
|
if(n > 0) {
|
|
|
|
empty = 0;
|
2004-03-25 23:25:45 +00:00
|
|
|
nl = u.u.buf[n-1]=='\n';
|
2004-03-25 23:03:57 +00:00
|
|
|
} else {
|
|
|
|
if(n < 0){
|
|
|
|
fprint(2, "grep: read error on %s: %r\n", file);
|
|
|
|
return count != 0;
|
|
|
|
}
|
|
|
|
if(!eof && !nl && !empty) {
|
2004-03-25 23:25:45 +00:00
|
|
|
u.u.buf[0] = '\n';
|
2004-03-25 23:03:57 +00:00
|
|
|
n = 1;
|
|
|
|
eof = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(n <= 0) {
|
|
|
|
close(fid);
|
|
|
|
if(flag & Cflag) {
|
|
|
|
if(flag & Hflag)
|
|
|
|
Bprint(&bout, "%s:", file);
|
|
|
|
Bprint(&bout, "%ld\n", count);
|
|
|
|
}
|
|
|
|
if(((flag&Llflag) && count != 0) || ((flag&LLflag) && count == 0))
|
|
|
|
Bprint(&bout, "%s\n", file);
|
|
|
|
Bflush(&bout);
|
|
|
|
return count != 0;
|
|
|
|
}
|
2004-03-25 23:25:45 +00:00
|
|
|
lp = u.u.buf;
|
2004-03-25 23:03:57 +00:00
|
|
|
elp = lp+n;
|
|
|
|
if(flag & Iflag)
|
|
|
|
goto loopi;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* normal character loop
|
|
|
|
*/
|
|
|
|
loop:
|
|
|
|
c = *lp;
|
|
|
|
ns = s->next[c];
|
|
|
|
if(ns == 0) {
|
|
|
|
increment(s, c);
|
|
|
|
goto loop;
|
|
|
|
}
|
|
|
|
// if(flags['2'])
|
|
|
|
// if(s->match)
|
|
|
|
// print("%d: %.2x**\n", s, c);
|
|
|
|
// else
|
|
|
|
// print("%d: %.2x\n", s, c);
|
|
|
|
lp++;
|
|
|
|
s = ns;
|
|
|
|
if(c == '\n') {
|
|
|
|
lineno++;
|
|
|
|
if(!!s->match == !(flag&Vflag)) {
|
|
|
|
count++;
|
|
|
|
if(flag & (Cflag|Sflag|Llflag|LLflag))
|
|
|
|
goto cont;
|
|
|
|
if(flag & Hflag)
|
|
|
|
Bprint(&bout, "%s:", file);
|
|
|
|
if(flag & Nflag)
|
|
|
|
Bprint(&bout, "%ld: ", lineno);
|
|
|
|
/* suppress extra newline at EOF unless we are labeling matches with file name */
|
|
|
|
Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));
|
|
|
|
if(flag & Bflag)
|
|
|
|
Bflush(&bout);
|
|
|
|
}
|
|
|
|
if((lineno & Flshcnt) == 0)
|
|
|
|
Bflush(&bout);
|
|
|
|
cont:
|
|
|
|
bol = lp;
|
|
|
|
}
|
|
|
|
if(lp != elp)
|
|
|
|
goto loop;
|
|
|
|
goto loop0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* character loop for -i flag
|
|
|
|
* for speed
|
|
|
|
*/
|
|
|
|
loopi:
|
|
|
|
c = *lp;
|
|
|
|
if(c >= 'A' && c <= 'Z')
|
|
|
|
c += 'a'-'A';
|
|
|
|
ns = s->next[c];
|
|
|
|
if(ns == 0) {
|
|
|
|
increment(s, c);
|
|
|
|
goto loopi;
|
|
|
|
}
|
|
|
|
lp++;
|
|
|
|
s = ns;
|
|
|
|
if(c == '\n') {
|
|
|
|
lineno++;
|
|
|
|
if(!!s->match == !(flag&Vflag)) {
|
|
|
|
count++;
|
|
|
|
if(flag & (Cflag|Sflag|Llflag|LLflag))
|
|
|
|
goto conti;
|
|
|
|
if(flag & Hflag)
|
|
|
|
Bprint(&bout, "%s:", file);
|
|
|
|
if(flag & Nflag)
|
|
|
|
Bprint(&bout, "%ld: ", lineno);
|
|
|
|
/* suppress extra newline at EOF unless we are labeling matches with file name */
|
|
|
|
Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));
|
|
|
|
if(flag & Bflag)
|
|
|
|
Bflush(&bout);
|
|
|
|
}
|
|
|
|
if((lineno & Flshcnt) == 0)
|
|
|
|
Bflush(&bout);
|
|
|
|
conti:
|
|
|
|
bol = lp;
|
|
|
|
}
|
|
|
|
if(lp != elp)
|
|
|
|
goto loopi;
|
|
|
|
goto loop0;
|
|
|
|
}
|
|
|
|
|
|
|
|
State*
|
|
|
|
initstate(Re *r)
|
|
|
|
{
|
|
|
|
State *s;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
addcase(r);
|
|
|
|
if(flags['1'])
|
|
|
|
reprint("r", r);
|
|
|
|
nfollow = 0;
|
|
|
|
gen++;
|
|
|
|
fol1(r, Cbegin);
|
|
|
|
follow[nfollow++] = r;
|
|
|
|
qsort(follow, nfollow, sizeof(*follow), fcmp);
|
|
|
|
|
|
|
|
s = sal(nfollow);
|
|
|
|
for(i=0; i<nfollow; i++)
|
|
|
|
s->re[i] = follow[i];
|
|
|
|
return s;
|
|
|
|
}
|