17dd7cddfSDavid du Colombier #define EXTERN
27dd7cddfSDavid du Colombier #include "grep.h"
37dd7cddfSDavid du Colombier
4*a7529a1dSDavid du Colombier char *validflags = "bchiLlnsv";
57dd7cddfSDavid du Colombier void
usage(void)67dd7cddfSDavid du Colombier usage(void)
77dd7cddfSDavid du Colombier {
8*a7529a1dSDavid du Colombier fprint(2, "usage: grep [-%s] [-e pattern] [-f patternfile] [file ...]\n", validflags);
97dd7cddfSDavid du Colombier exits("usage");
107dd7cddfSDavid du Colombier }
117dd7cddfSDavid du Colombier
127dd7cddfSDavid du Colombier void
main(int argc,char * argv[])137dd7cddfSDavid du Colombier main(int argc, char *argv[])
147dd7cddfSDavid du Colombier {
157dd7cddfSDavid du Colombier int i, status;
167dd7cddfSDavid du Colombier
177dd7cddfSDavid du Colombier ARGBEGIN {
187dd7cddfSDavid du Colombier default:
197dd7cddfSDavid du Colombier if(utfrune(validflags, ARGC()) == nil)
207dd7cddfSDavid du Colombier usage();
217dd7cddfSDavid du Colombier flags[ARGC()]++;
227dd7cddfSDavid du Colombier break;
237dd7cddfSDavid du Colombier
247dd7cddfSDavid du Colombier case 'e':
257dd7cddfSDavid du Colombier flags['e']++;
267dd7cddfSDavid du Colombier lineno = 0;
2712fd1c83SDavid du Colombier str2top(EARGF(usage()));
287dd7cddfSDavid du Colombier break;
297dd7cddfSDavid du Colombier
307dd7cddfSDavid du Colombier case 'f':
317dd7cddfSDavid du Colombier flags['f']++;
3212fd1c83SDavid du Colombier filename = EARGF(usage());
337dd7cddfSDavid du Colombier rein = Bopen(filename, OREAD);
347dd7cddfSDavid du Colombier if(rein == 0) {
357dd7cddfSDavid du Colombier fprint(2, "grep: can't open %s: %r\n", filename);
367dd7cddfSDavid du Colombier exits("open");
377dd7cddfSDavid du Colombier }
387dd7cddfSDavid du Colombier lineno = 1;
397dd7cddfSDavid du Colombier str2top(filename);
407dd7cddfSDavid du Colombier break;
417dd7cddfSDavid du Colombier } ARGEND
427dd7cddfSDavid du Colombier
437dd7cddfSDavid du Colombier if(flags['f'] == 0 && flags['e'] == 0) {
447dd7cddfSDavid du Colombier if(argc <= 0)
457dd7cddfSDavid du Colombier usage();
467dd7cddfSDavid du Colombier str2top(argv[0]);
477dd7cddfSDavid du Colombier argc--;
487dd7cddfSDavid du Colombier argv++;
497dd7cddfSDavid du Colombier }
507dd7cddfSDavid du Colombier
517dd7cddfSDavid du Colombier follow = mal(maxfollow*sizeof(*follow));
527dd7cddfSDavid du Colombier state0 = initstate(topre.beg);
537dd7cddfSDavid du Colombier
547dd7cddfSDavid du Colombier Binit(&bout, 1, OWRITE);
557dd7cddfSDavid du Colombier switch(argc) {
567dd7cddfSDavid du Colombier case 0:
577dd7cddfSDavid du Colombier status = search(0, 0);
587dd7cddfSDavid du Colombier break;
597dd7cddfSDavid du Colombier case 1:
607dd7cddfSDavid du Colombier status = search(argv[0], 0);
617dd7cddfSDavid du Colombier break;
627dd7cddfSDavid du Colombier default:
637dd7cddfSDavid du Colombier status = 0;
647dd7cddfSDavid du Colombier for(i=0; i<argc; i++)
657dd7cddfSDavid du Colombier status |= search(argv[i], Hflag);
667dd7cddfSDavid du Colombier break;
677dd7cddfSDavid du Colombier }
687dd7cddfSDavid du Colombier if(status)
697dd7cddfSDavid du Colombier exits(0);
707dd7cddfSDavid du Colombier exits("no matches");
717dd7cddfSDavid du Colombier }
727dd7cddfSDavid du Colombier
737dd7cddfSDavid du Colombier int
search(char * file,int flag)747dd7cddfSDavid du Colombier search(char *file, int flag)
757dd7cddfSDavid du Colombier {
767dd7cddfSDavid du Colombier State *s, *ns;
779a747e4fSDavid du Colombier int c, fid, eof, nl, empty;
787dd7cddfSDavid du Colombier long count, lineno, n;
797dd7cddfSDavid du Colombier uchar *elp, *lp, *bol;
807dd7cddfSDavid du Colombier
817dd7cddfSDavid du Colombier if(file == 0) {
827dd7cddfSDavid du Colombier file = "stdin";
837dd7cddfSDavid du Colombier fid = 0;
8459cc4ca5SDavid du Colombier flag |= Bflag;
857dd7cddfSDavid du Colombier } else
867dd7cddfSDavid du Colombier fid = open(file, OREAD);
877dd7cddfSDavid du Colombier
887dd7cddfSDavid du Colombier if(fid < 0) {
897dd7cddfSDavid du Colombier fprint(2, "grep: can't open %s: %r\n", file);
907dd7cddfSDavid du Colombier return 0;
917dd7cddfSDavid du Colombier }
927dd7cddfSDavid du Colombier
9359cc4ca5SDavid du Colombier if(flags['b'])
9459cc4ca5SDavid du Colombier flag ^= Bflag; /* dont buffer output */
957dd7cddfSDavid du Colombier if(flags['c'])
967dd7cddfSDavid du Colombier flag |= Cflag; /* count */
977dd7cddfSDavid du Colombier if(flags['h'])
987dd7cddfSDavid du Colombier flag &= ~Hflag; /* do not print file name in output */
997dd7cddfSDavid du Colombier if(flags['i'])
1007dd7cddfSDavid du Colombier flag |= Iflag; /* fold upper-lower */
1017dd7cddfSDavid du Colombier if(flags['l'])
1027dd7cddfSDavid du Colombier flag |= Llflag; /* print only name of file if any match */
1037dd7cddfSDavid du Colombier if(flags['L'])
1047dd7cddfSDavid du Colombier flag |= LLflag; /* print only name of file if any non match */
1057dd7cddfSDavid du Colombier if(flags['n'])
1067dd7cddfSDavid du Colombier flag |= Nflag; /* count only */
1077dd7cddfSDavid du Colombier if(flags['s'])
1087dd7cddfSDavid du Colombier flag |= Sflag; /* status only */
1097dd7cddfSDavid du Colombier if(flags['v'])
1107dd7cddfSDavid du Colombier flag |= Vflag; /* inverse match */
1117dd7cddfSDavid du Colombier
1127dd7cddfSDavid du Colombier s = state0;
1137dd7cddfSDavid du Colombier lineno = 0;
1147dd7cddfSDavid du Colombier count = 0;
1159a747e4fSDavid du Colombier eof = 0;
1169a747e4fSDavid du Colombier empty = 1;
1179a747e4fSDavid du Colombier nl = 0;
1187dd7cddfSDavid du Colombier lp = u.buf;
1197dd7cddfSDavid du Colombier bol = lp;
1207dd7cddfSDavid du Colombier
1217dd7cddfSDavid du Colombier loop0:
1227dd7cddfSDavid du Colombier n = lp-bol;
1237dd7cddfSDavid du Colombier if(n > sizeof(u.pre))
1247dd7cddfSDavid du Colombier n = sizeof(u.pre);
1257dd7cddfSDavid du Colombier memmove(u.buf-n, bol, n);
1267dd7cddfSDavid du Colombier bol = u.buf-n;
1277dd7cddfSDavid du Colombier n = read(fid, u.buf, sizeof(u.buf));
1289a747e4fSDavid du Colombier /* if file has no final newline, simulate one to emit matches to last line */
1299a747e4fSDavid du Colombier if(n > 0) {
1309a747e4fSDavid du Colombier empty = 0;
1319a747e4fSDavid du Colombier nl = u.buf[n-1]=='\n';
1329a747e4fSDavid du Colombier } else {
1339a747e4fSDavid du Colombier if(n < 0){
1349a747e4fSDavid du Colombier fprint(2, "grep: read error on %s: %r\n", file);
1359a747e4fSDavid du Colombier return count != 0;
1369a747e4fSDavid du Colombier }
1379a747e4fSDavid du Colombier if(!eof && !nl && !empty) {
1389a747e4fSDavid du Colombier u.buf[0] = '\n';
1399a747e4fSDavid du Colombier n = 1;
1409a747e4fSDavid du Colombier eof = 1;
1419a747e4fSDavid du Colombier }
1429a747e4fSDavid du Colombier }
1437dd7cddfSDavid du Colombier if(n <= 0) {
1447dd7cddfSDavid du Colombier close(fid);
1457dd7cddfSDavid du Colombier if(flag & Cflag) {
1467dd7cddfSDavid du Colombier if(flag & Hflag)
1477dd7cddfSDavid du Colombier Bprint(&bout, "%s:", file);
1487dd7cddfSDavid du Colombier Bprint(&bout, "%ld\n", count);
1497dd7cddfSDavid du Colombier }
1507dd7cddfSDavid du Colombier if(((flag&Llflag) && count != 0) || ((flag&LLflag) && count == 0))
1517dd7cddfSDavid du Colombier Bprint(&bout, "%s\n", file);
1527dd7cddfSDavid du Colombier Bflush(&bout);
1537dd7cddfSDavid du Colombier return count != 0;
1547dd7cddfSDavid du Colombier }
1557dd7cddfSDavid du Colombier lp = u.buf;
1567dd7cddfSDavid du Colombier elp = lp+n;
1577dd7cddfSDavid du Colombier if(flag & Iflag)
1587dd7cddfSDavid du Colombier goto loopi;
1597dd7cddfSDavid du Colombier
1607dd7cddfSDavid du Colombier /*
1617dd7cddfSDavid du Colombier * normal character loop
1627dd7cddfSDavid du Colombier */
1637dd7cddfSDavid du Colombier loop:
1647dd7cddfSDavid du Colombier c = *lp;
1657dd7cddfSDavid du Colombier ns = s->next[c];
1667dd7cddfSDavid du Colombier if(ns == 0) {
1677dd7cddfSDavid du Colombier increment(s, c);
1687dd7cddfSDavid du Colombier goto loop;
1697dd7cddfSDavid du Colombier }
1707dd7cddfSDavid du Colombier // if(flags['2'])
1717dd7cddfSDavid du Colombier // if(s->match)
1727dd7cddfSDavid du Colombier // print("%d: %.2x**\n", s, c);
1737dd7cddfSDavid du Colombier // else
1747dd7cddfSDavid du Colombier // print("%d: %.2x\n", s, c);
1757dd7cddfSDavid du Colombier lp++;
1767dd7cddfSDavid du Colombier s = ns;
1777dd7cddfSDavid du Colombier if(c == '\n') {
1787dd7cddfSDavid du Colombier lineno++;
1797dd7cddfSDavid du Colombier if(!!s->match == !(flag&Vflag)) {
1807dd7cddfSDavid du Colombier count++;
1817dd7cddfSDavid du Colombier if(flag & (Cflag|Sflag|Llflag|LLflag))
1827dd7cddfSDavid du Colombier goto cont;
1837dd7cddfSDavid du Colombier if(flag & Hflag)
1847dd7cddfSDavid du Colombier Bprint(&bout, "%s:", file);
1857dd7cddfSDavid du Colombier if(flag & Nflag)
1867dd7cddfSDavid du Colombier Bprint(&bout, "%ld: ", lineno);
1879a747e4fSDavid du Colombier /* suppress extra newline at EOF unless we are labeling matches with file name */
1889a747e4fSDavid du Colombier Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));
18959cc4ca5SDavid du Colombier if(flag & Bflag)
1907dd7cddfSDavid du Colombier Bflush(&bout);
1917dd7cddfSDavid du Colombier }
19259cc4ca5SDavid du Colombier if((lineno & Flshcnt) == 0)
19359cc4ca5SDavid du Colombier Bflush(&bout);
1947dd7cddfSDavid du Colombier cont:
1957dd7cddfSDavid du Colombier bol = lp;
1967dd7cddfSDavid du Colombier }
1977dd7cddfSDavid du Colombier if(lp != elp)
1987dd7cddfSDavid du Colombier goto loop;
1997dd7cddfSDavid du Colombier goto loop0;
2007dd7cddfSDavid du Colombier
2017dd7cddfSDavid du Colombier /*
2027dd7cddfSDavid du Colombier * character loop for -i flag
2037dd7cddfSDavid du Colombier * for speed
2047dd7cddfSDavid du Colombier */
2057dd7cddfSDavid du Colombier loopi:
2067dd7cddfSDavid du Colombier c = *lp;
2077dd7cddfSDavid du Colombier if(c >= 'A' && c <= 'Z')
2087dd7cddfSDavid du Colombier c += 'a'-'A';
2097dd7cddfSDavid du Colombier ns = s->next[c];
2107dd7cddfSDavid du Colombier if(ns == 0) {
2117dd7cddfSDavid du Colombier increment(s, c);
2127dd7cddfSDavid du Colombier goto loopi;
2137dd7cddfSDavid du Colombier }
2147dd7cddfSDavid du Colombier lp++;
2157dd7cddfSDavid du Colombier s = ns;
2167dd7cddfSDavid du Colombier if(c == '\n') {
2177dd7cddfSDavid du Colombier lineno++;
2187dd7cddfSDavid du Colombier if(!!s->match == !(flag&Vflag)) {
2197dd7cddfSDavid du Colombier count++;
2207dd7cddfSDavid du Colombier if(flag & (Cflag|Sflag|Llflag|LLflag))
2217dd7cddfSDavid du Colombier goto conti;
2227dd7cddfSDavid du Colombier if(flag & Hflag)
2237dd7cddfSDavid du Colombier Bprint(&bout, "%s:", file);
2247dd7cddfSDavid du Colombier if(flag & Nflag)
2257dd7cddfSDavid du Colombier Bprint(&bout, "%ld: ", lineno);
2269a747e4fSDavid du Colombier /* suppress extra newline at EOF unless we are labeling matches with file name */
2279a747e4fSDavid du Colombier Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));
22859cc4ca5SDavid du Colombier if(flag & Bflag)
2297dd7cddfSDavid du Colombier Bflush(&bout);
2307dd7cddfSDavid du Colombier }
23159cc4ca5SDavid du Colombier if((lineno & Flshcnt) == 0)
23259cc4ca5SDavid du Colombier Bflush(&bout);
2337dd7cddfSDavid du Colombier conti:
2347dd7cddfSDavid du Colombier bol = lp;
2357dd7cddfSDavid du Colombier }
2367dd7cddfSDavid du Colombier if(lp != elp)
2377dd7cddfSDavid du Colombier goto loopi;
2387dd7cddfSDavid du Colombier goto loop0;
2397dd7cddfSDavid du Colombier }
2407dd7cddfSDavid du Colombier
2417dd7cddfSDavid du Colombier State*
initstate(Re * r)2427dd7cddfSDavid du Colombier initstate(Re *r)
2437dd7cddfSDavid du Colombier {
2447dd7cddfSDavid du Colombier State *s;
2457dd7cddfSDavid du Colombier int i;
2467dd7cddfSDavid du Colombier
2477dd7cddfSDavid du Colombier addcase(r);
2487dd7cddfSDavid du Colombier if(flags['1'])
2497dd7cddfSDavid du Colombier reprint("r", r);
2507dd7cddfSDavid du Colombier nfollow = 0;
2517dd7cddfSDavid du Colombier gen++;
2527dd7cddfSDavid du Colombier fol1(r, Cbegin);
2537dd7cddfSDavid du Colombier follow[nfollow++] = r;
2547dd7cddfSDavid du Colombier qsort(follow, nfollow, sizeof(*follow), fcmp);
2557dd7cddfSDavid du Colombier
2567dd7cddfSDavid du Colombier s = sal(nfollow);
2577dd7cddfSDavid du Colombier for(i=0; i<nfollow; i++)
2587dd7cddfSDavid du Colombier s->re[i] = follow[i];
2597dd7cddfSDavid du Colombier return s;
2607dd7cddfSDavid du Colombier }
261