Blob
1 #define EXTERN2 #include "grep.h"4 char *validflags = "bchiLlnsv";5 void6 usage(void)7 {8 fprint(2, "usage: grep [-%s] [-f file] [-e expr] [file ...]\n", validflags);9 exits("usage");10 }12 void13 main(int argc, char *argv[])14 {15 int i, status;17 ARGBEGIN {18 default:19 if(utfrune(validflags, ARGC()) == nil)20 usage();21 flags[ARGC()]++;22 break;24 case 'q': /* gnu grep -q means plan 9 grep -s */25 flags['s']++;26 break;28 case 'E': /* ignore, turns gnu grep into egrep */29 break;31 case 'e':32 flags['e']++;33 lineno = 0;34 str2top(ARGF());35 break;37 case 'f':38 flags['f']++;39 filename = ARGF();40 rein = Bopen(filename, OREAD);41 if(rein == 0) {42 fprint(2, "grep: can't open %s: %r\n", filename);43 exits("open");44 }45 lineno = 1;46 str2top(filename);47 break;48 } ARGEND50 if(flags['f'] == 0 && flags['e'] == 0) {51 if(argc <= 0)52 usage();53 str2top(argv[0]);54 argc--;55 argv++;56 }58 follow = mal(maxfollow*sizeof(*follow));59 state0 = initstate(topre.beg);61 Binit(&bout, 1, OWRITE);62 switch(argc) {63 case 0:64 status = search(0, 0);65 break;66 case 1:67 status = search(argv[0], 0);68 break;69 default:70 status = 0;71 for(i=0; i<argc; i++)72 status |= search(argv[i], Hflag);73 break;74 }75 if(status)76 exits(0);77 exits("no matches");78 }80 int81 search(char *file, int flag)82 {83 State *s, *ns;84 int c, fid, eof, nl, empty;85 long count, lineno, n;86 uchar *elp, *lp, *bol;88 if(file == 0) {89 file = "stdin";90 fid = 0;91 flag |= Bflag;92 } else93 fid = open(file, OREAD);95 if(fid < 0) {96 fprint(2, "grep: can't open %s: %r\n", file);97 return 0;98 }100 if(flags['b'])101 flag ^= Bflag; /* dont buffer output */102 if(flags['c'])103 flag |= Cflag; /* count */104 if(flags['h'])105 flag &= ~Hflag; /* do not print file name in output */106 if(flags['i'])107 flag |= Iflag; /* fold upper-lower */108 if(flags['l'])109 flag |= Llflag; /* print only name of file if any match */110 if(flags['L'])111 flag |= LLflag; /* print only name of file if any non match */112 if(flags['n'])113 flag |= Nflag; /* count only */114 if(flags['s'])115 flag |= Sflag; /* status only */116 if(flags['v'])117 flag |= Vflag; /* inverse match */119 s = state0;120 lineno = 0;121 count = 0;122 eof = 0;123 empty = 1;124 nl = 0;125 lp = u.u.buf;126 bol = lp;128 loop0:129 n = lp-bol;130 if(n > sizeof(u.u.pre))131 n = sizeof(u.u.pre);132 memmove(u.u.buf-n, bol, n);133 bol = u.u.buf-n;134 n = read(fid, u.u.buf, sizeof(u.u.buf));135 /* if file has no final newline, simulate one to emit matches to last line */136 if(n > 0) {137 empty = 0;138 nl = u.u.buf[n-1]=='\n';139 } else {140 if(n < 0){141 fprint(2, "grep: read error on %s: %r\n", file);142 return count != 0;143 }144 if(!eof && !nl && !empty) {145 u.u.buf[0] = '\n';146 n = 1;147 eof = 1;148 }149 }150 if(n <= 0) {151 close(fid);152 if(flag & Cflag) {153 if(flag & Hflag)154 Bprint(&bout, "%s:", file);155 Bprint(&bout, "%ld\n", count);156 }157 if(((flag&Llflag) && count != 0) || ((flag&LLflag) && count == 0))158 Bprint(&bout, "%s\n", file);159 Bflush(&bout);160 return count != 0;161 }162 lp = u.u.buf;163 elp = lp+n;164 if(flag & Iflag)165 goto loopi;167 /*168 * normal character loop169 */170 loop:171 c = *lp;172 ns = s->next[c];173 if(ns == 0) {174 increment(s, c);175 goto loop;176 }177 /* if(flags['2']) */178 /* if(s->match) */179 /* print("%d: %.2x**\n", s, c); */180 /* else */181 /* print("%d: %.2x\n", s, c); */182 lp++;183 s = ns;184 if(c == '\n') {185 lineno++;186 if(!!s->match == !(flag&Vflag)) {187 count++;188 if(flag & (Cflag|Sflag|Llflag|LLflag))189 goto cont;190 if(flag & Hflag)191 Bprint(&bout, "%s:", file);192 if(flag & Nflag)193 Bprint(&bout, "%ld: ", lineno);194 /* suppress extra newline at EOF unless we are labeling matches with file name */195 Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));196 if(flag & Bflag)197 Bflush(&bout);198 }199 if((lineno & Flshcnt) == 0)200 Bflush(&bout);201 cont:202 bol = lp;203 }204 if(lp != elp)205 goto loop;206 goto loop0;208 /*209 * character loop for -i flag210 * for speed211 */212 loopi:213 c = *lp;214 if(c >= 'A' && c <= 'Z')215 c += 'a'-'A';216 ns = s->next[c];217 if(ns == 0) {218 increment(s, c);219 goto loopi;220 }221 lp++;222 s = ns;223 if(c == '\n') {224 lineno++;225 if(!!s->match == !(flag&Vflag)) {226 count++;227 if(flag & (Cflag|Sflag|Llflag|LLflag))228 goto conti;229 if(flag & Hflag)230 Bprint(&bout, "%s:", file);231 if(flag & Nflag)232 Bprint(&bout, "%ld: ", lineno);233 /* suppress extra newline at EOF unless we are labeling matches with file name */234 Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));235 if(flag & Bflag)236 Bflush(&bout);237 }238 if((lineno & Flshcnt) == 0)239 Bflush(&bout);240 conti:241 bol = lp;242 }243 if(lp != elp)244 goto loopi;245 goto loop0;246 }248 State*249 initstate(Re *r)250 {251 State *s;252 int i;254 addcase(r);255 if(flags['1'])256 reprint("r", r);257 nfollow = 0;258 gen++;259 fol1(r, Cbegin);260 follow[nfollow++] = r;261 qsort(follow, nfollow, sizeof(*follow), fcmp);263 s = sal(nfollow);264 for(i=0; i<nfollow; i++)265 s->re[i] = follow[i];266 return s;267 }