/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #define EXTERN#include "grep.h" char *validflags = "bchiLlnsv";voidusage(void){ fprint(2, "usage: grep [-%s] [-e pattern] [-f patternfile] [file ...]\n", validflags); exits("usage");} voidmain(int argc, char *argv[]){ int i, status; ARGBEGIN { default: if(utfrune(validflags, ARGC()) == nil) usage(); flags[ARGC()]++; break; case 'e': flags['e']++; lineno = 0; str2top(EARGF(usage())); break; case 'f': flags['f']++; filename = EARGF(usage()); 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");} intsearch(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; lp = u.buf; bol = lp; loop0: n = lp-bol; if(n > sizeof(u.pre)) n = sizeof(u.pre); memmove(u.buf-n, bol, n); bol = u.buf-n; n = read(fid, u.buf, sizeof(u.buf)); /* if file has no final newline, simulate one to emit matches to last line */ if(n > 0) { empty = 0; nl = u.buf[n-1]=='\n'; } else { if(n < 0){ fprint(2, "grep: read error on %s: %r\n", file); return count != 0; } if(!eof && !nl && !empty) { u.buf[0] = '\n'; 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; } lp = u.buf; 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;}
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#define EXTERN
#include "grep.h"
char *validflags = "bchiLlnsv";
void
usage(void)
{
fprint(2, "usage: grep [-%s] [-e pattern] [-f patternfile] [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;
case 'e':
flags['e']++;
lineno = 0;
str2top(EARGF(usage()));
break;
case 'f':
flags['f']++;
filename = EARGF(usage());
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;
lp = u.buf;
bol = lp;
loop0:
n = lp-bol;
if(n > sizeof(u.pre))
n = sizeof(u.pre);
memmove(u.buf-n, bol, n);
bol = u.buf-n;
n = read(fid, u.buf, sizeof(u.buf));
/* if file has no final newline, simulate one to emit matches to last line */
if(n > 0) {
empty = 0;
nl = u.buf[n-1]=='\n';
} else {
if(n < 0){
fprint(2, "grep: read error on %s: %r\n", file);
return count != 0;
}
if(!eof && !nl && !empty) {
u.buf[0] = '\n';
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;
}
lp = u.buf;
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;
}