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