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 'E': /* ignore, turns gnu grep into egrep */
25 break;
27 case 'e':
28 flags['e']++;
29 lineno = 0;
30 str2top(ARGF());
31 break;
33 case 'f':
34 flags['f']++;
35 filename = ARGF();
36 rein = Bopen(filename, OREAD);
37 if(rein == 0) {
38 fprint(2, "grep: can't open %s: %r\n", filename);
39 exits("open");
40 }
41 lineno = 1;
42 str2top(filename);
43 break;
44 } ARGEND
46 if(flags['f'] == 0 && flags['e'] == 0) {
47 if(argc <= 0)
48 usage();
49 str2top(argv[0]);
50 argc--;
51 argv++;
52 }
54 follow = mal(maxfollow*sizeof(*follow));
55 state0 = initstate(topre.beg);
57 Binit(&bout, 1, OWRITE);
58 switch(argc) {
59 case 0:
60 status = search(0, 0);
61 break;
62 case 1:
63 status = search(argv[0], 0);
64 break;
65 default:
66 status = 0;
67 for(i=0; i<argc; i++)
68 status |= search(argv[i], Hflag);
69 break;
70 }
71 if(status)
72 exits(0);
73 exits("no matches");
74 }
76 int
77 search(char *file, int flag)
78 {
79 State *s, *ns;
80 int c, fid, eof, nl, empty;
81 long count, lineno, n;
82 uchar *elp, *lp, *bol;
84 if(file == 0) {
85 file = "stdin";
86 fid = 0;
87 flag |= Bflag;
88 } else
89 fid = open(file, OREAD);
91 if(fid < 0) {
92 fprint(2, "grep: can't open %s: %r\n", file);
93 return 0;
94 }
96 if(flags['b'])
97 flag ^= Bflag; /* dont buffer output */
98 if(flags['c'])
99 flag |= Cflag; /* count */
100 if(flags['h'])
101 flag &= ~Hflag; /* do not print file name in output */
102 if(flags['i'])
103 flag |= Iflag; /* fold upper-lower */
104 if(flags['l'])
105 flag |= Llflag; /* print only name of file if any match */
106 if(flags['L'])
107 flag |= LLflag; /* print only name of file if any non match */
108 if(flags['n'])
109 flag |= Nflag; /* count only */
110 if(flags['s'])
111 flag |= Sflag; /* status only */
112 if(flags['v'])
113 flag |= Vflag; /* inverse match */
115 s = state0;
116 lineno = 0;
117 count = 0;
118 eof = 0;
119 empty = 1;
120 nl = 0;
121 lp = u.u.buf;
122 bol = lp;
124 loop0:
125 n = lp-bol;
126 if(n > sizeof(u.u.pre))
127 n = sizeof(u.u.pre);
128 memmove(u.u.buf-n, bol, n);
129 bol = u.u.buf-n;
130 n = read(fid, u.u.buf, sizeof(u.u.buf));
131 /* if file has no final newline, simulate one to emit matches to last line */
132 if(n > 0) {
133 empty = 0;
134 nl = u.u.buf[n-1]=='\n';
135 } else {
136 if(n < 0){
137 fprint(2, "grep: read error on %s: %r\n", file);
138 return count != 0;
140 if(!eof && !nl && !empty) {
141 u.u.buf[0] = '\n';
142 n = 1;
143 eof = 1;
146 if(n <= 0) {
147 close(fid);
148 if(flag & Cflag) {
149 if(flag & Hflag)
150 Bprint(&bout, "%s:", file);
151 Bprint(&bout, "%ld\n", count);
153 if(((flag&Llflag) && count != 0) || ((flag&LLflag) && count == 0))
154 Bprint(&bout, "%s\n", file);
155 Bflush(&bout);
156 return count != 0;
158 lp = u.u.buf;
159 elp = lp+n;
160 if(flag & Iflag)
161 goto loopi;
163 /*
164 * normal character loop
165 */
166 loop:
167 c = *lp;
168 ns = s->next[c];
169 if(ns == 0) {
170 increment(s, c);
171 goto loop;
173 /* if(flags['2']) */
174 /* if(s->match) */
175 /* print("%d: %.2x**\n", s, c); */
176 /* else */
177 /* print("%d: %.2x\n", s, c); */
178 lp++;
179 s = ns;
180 if(c == '\n') {
181 lineno++;
182 if(!!s->match == !(flag&Vflag)) {
183 count++;
184 if(flag & (Cflag|Sflag|Llflag|LLflag))
185 goto cont;
186 if(flag & Hflag)
187 Bprint(&bout, "%s:", file);
188 if(flag & Nflag)
189 Bprint(&bout, "%ld: ", lineno);
190 /* suppress extra newline at EOF unless we are labeling matches with file name */
191 Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));
192 if(flag & Bflag)
193 Bflush(&bout);
195 if((lineno & Flshcnt) == 0)
196 Bflush(&bout);
197 cont:
198 bol = lp;
200 if(lp != elp)
201 goto loop;
202 goto loop0;
204 /*
205 * character loop for -i flag
206 * for speed
207 */
208 loopi:
209 c = *lp;
210 if(c >= 'A' && c <= 'Z')
211 c += 'a'-'A';
212 ns = s->next[c];
213 if(ns == 0) {
214 increment(s, c);
215 goto loopi;
217 lp++;
218 s = ns;
219 if(c == '\n') {
220 lineno++;
221 if(!!s->match == !(flag&Vflag)) {
222 count++;
223 if(flag & (Cflag|Sflag|Llflag|LLflag))
224 goto conti;
225 if(flag & Hflag)
226 Bprint(&bout, "%s:", file);
227 if(flag & Nflag)
228 Bprint(&bout, "%ld: ", lineno);
229 /* suppress extra newline at EOF unless we are labeling matches with file name */
230 Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));
231 if(flag & Bflag)
232 Bflush(&bout);
234 if((lineno & Flshcnt) == 0)
235 Bflush(&bout);
236 conti:
237 bol = lp;
239 if(lp != elp)
240 goto loopi;
241 goto loop0;
244 State*
245 initstate(Re *r)
247 State *s;
248 int i;
250 addcase(r);
251 if(flags['1'])
252 reprint("r", r);
253 nfollow = 0;
254 gen++;
255 fol1(r, Cbegin);
256 follow[nfollow++] = r;
257 qsort(follow, nfollow, sizeof(*follow), fcmp);
259 s = sal(nfollow);
260 for(i=0; i<nfollow; i++)
261 s->re[i] = follow[i];
262 return s;