/* * 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; int32_t count, lineno, n; uint8_t *elp, *lp, *bol; if (file == 0) { file = "stdin"; fid = 0; flag |= Bflag; } else fid = sys_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 = jehanne_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) { sys_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; }