ref: 68f15d65942da7e30cf9cbae7362f778fe5da1d2
dir: /sys/src/cmd/grep/main.c/
#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; }