123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- /*
- * 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 = 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;
- }
|