Blob


1 #define EXTERN
2 #include "grep.h"
4 char *validflags = "bchiLlnsv";
5 void
6 usage(void)
7 {
8 fprint(2, "usage: grep [-%s] [-f file] [-e expr] [file ...]\n", validflags);
9 exits("usage");
10 }
12 void
13 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 } ARGEND
50 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 int
81 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 } else
93 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;
144 if(!eof && !nl && !empty) {
145 u.u.buf[0] = '\n';
146 n = 1;
147 eof = 1;
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);
157 if(((flag&Llflag) && count != 0) || ((flag&LLflag) && count == 0))
158 Bprint(&bout, "%s\n", file);
159 Bflush(&bout);
160 return count != 0;
162 lp = u.u.buf;
163 elp = lp+n;
164 if(flag & Iflag)
165 goto loopi;
167 /*
168 * normal character loop
169 */
170 loop:
171 c = *lp;
172 ns = s->next[c];
173 if(ns == 0) {
174 increment(s, c);
175 goto loop;
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);
199 if((lineno & Flshcnt) == 0)
200 Bflush(&bout);
201 cont:
202 bol = lp;
204 if(lp != elp)
205 goto loop;
206 goto loop0;
208 /*
209 * character loop for -i flag
210 * for speed
211 */
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;
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);
238 if((lineno & Flshcnt) == 0)
239 Bflush(&bout);
240 conti:
241 bol = lp;
243 if(lp != elp)
244 goto loopi;
245 goto loop0;
248 State*
249 initstate(Re *r)
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;