Bell 32V development
[unix-history] / usr / src / cmd / grep.c
CommitLineData
d2dd26a1
TL
1/*
2 * grep -- print lines matching (or not matching) a pattern
3 *
4 * status returns:
5 * 0 - ok, and some matches
6 * 1 - ok, but no matches
7 * 2 - some error
8 */
9
10#include <stdio.h>
11#include <ctype.h>
12
13#define CBRA 1
14#define CCHR 2
15#define CDOT 4
16#define CCL 6
17#define NCCL 8
18#define CDOL 10
19#define CEOF 11
20#define CKET 12
21#define CBACK 18
22
23#define STAR 01
24
25#define LBSIZE 512
26#define ESIZE 256
27#define NBRA 9
28
29char expbuf[ESIZE];
30long lnum;
31char linebuf[LBSIZE+1];
32char ybuf[ESIZE];
33int bflag;
34int lflag;
35int nflag;
36int cflag;
37int vflag;
38int nfile;
39int hflag = 1;
40int sflag;
41int yflag;
42int circf;
43int blkno;
44long tln;
45int nsucc;
46char *braslist[NBRA];
47char *braelist[NBRA];
48char bittab[] = {
49 1,
50 2,
51 4,
52 8,
53 16,
54 32,
55 64,
56 128
57};
58
59main(argc, argv)
60char **argv;
61{
62 while (--argc > 0 && (++argv)[0][0]=='-')
63 switch (argv[0][1]) {
64
65 case 'y':
66 yflag++;
67 continue;
68
69 case 'h':
70 hflag = 0;
71 continue;
72
73 case 's':
74 sflag++;
75 continue;
76
77 case 'v':
78 vflag++;
79 continue;
80
81 case 'b':
82 bflag++;
83 continue;
84
85 case 'l':
86 lflag++;
87 continue;
88
89 case 'c':
90 cflag++;
91 continue;
92
93 case 'n':
94 nflag++;
95 continue;
96
97 case 'e':
98 --argc;
99 ++argv;
100 goto out;
101
102 default:
103 errexit("grep: unknown flag\n", (char *)NULL);
104 continue;
105 }
106out:
107 if (argc<=0)
108 exit(2);
109 if (yflag) {
110 register char *p, *s;
111 for (s = ybuf, p = *argv; *p; ) {
112 if (*p == '\\') {
113 *s++ = *p++;
114 if (*p)
115 *s++ = *p++;
116 } else if (*p == '[') {
117 while (*p != '\0' && *p != ']')
118 *s++ = *p++;
119 } else if (islower(*p)) {
120 *s++ = '[';
121 *s++ = toupper(*p);
122 *s++ = *p++;
123 *s++ = ']';
124 } else
125 *s++ = *p++;
126 if (s >= ybuf+ESIZE-5)
127 errexit("grep: argument too long\n", (char *)NULL);
128 }
129 *s = '\0';
130 *argv = ybuf;
131 }
132 compile(*argv);
133 nfile = --argc;
134 if (argc<=0) {
135 if (lflag)
136 exit(1);
137 execute((char *)NULL);
138 } else while (--argc >= 0) {
139 argv++;
140 execute(*argv);
141 }
142 exit(nsucc == 0);
143}
144
145compile(astr)
146char *astr;
147{
148 register c;
149 register char *ep, *sp;
150 char *cstart;
151 char *lastep;
152 int cclcnt;
153 char bracket[NBRA], *bracketp;
154 int closed;
155 char numbra;
156 char neg;
157
158 ep = expbuf;
159 sp = astr;
160 lastep = 0;
161 bracketp = bracket;
162 closed = numbra = 0;
163 if (*sp == '^') {
164 circf++;
165 sp++;
166 }
167 for (;;) {
168 if (ep >= &expbuf[ESIZE])
169 goto cerror;
170 if ((c = *sp++) != '*')
171 lastep = ep;
172 switch (c) {
173
174 case '\0':
175 *ep++ = CEOF;
176 return;
177
178 case '.':
179 *ep++ = CDOT;
180 continue;
181
182 case '*':
183 if (lastep==0 || *lastep==CBRA || *lastep==CKET)
184 goto defchar;
185 *lastep |= STAR;
186 continue;
187
188 case '$':
189 if (*sp != '\0')
190 goto defchar;
191 *ep++ = CDOL;
192 continue;
193
194 case '[':
195 if(&ep[17] >= &expbuf[ESIZE])
196 goto cerror;
197 *ep++ = CCL;
198 neg = 0;
199 if((c = *sp++) == '^') {
200 neg = 1;
201 c = *sp++;
202 }
203 cstart = sp;
204 do {
205 if (c=='\0')
206 goto cerror;
207 if (c=='-' && sp>cstart && *sp!=']') {
208 for (c = sp[-2]; c<*sp; c++)
209 ep[c>>3] |= bittab[c&07];
210 sp++;
211 }
212 ep[c>>3] |= bittab[c&07];
213 } while((c = *sp++) != ']');
214 if(neg) {
215 for(cclcnt = 0; cclcnt < 16; cclcnt++)
216 ep[cclcnt] ^= -1;
217 ep[0] &= 0376;
218 }
219
220 ep += 16;
221
222 continue;
223
224 case '\\':
225 if((c = *sp++) == '(') {
226 if(numbra >= NBRA) {
227 goto cerror;
228 }
229 *bracketp++ = numbra;
230 *ep++ = CBRA;
231 *ep++ = numbra++;
232 continue;
233 }
234 if(c == ')') {
235 if(bracketp <= bracket) {
236 goto cerror;
237 }
238 *ep++ = CKET;
239 *ep++ = *--bracketp;
240 closed++;
241 continue;
242 }
243
244 if(c >= '1' && c <= '9') {
245 if((c -= '1') >= closed)
246 goto cerror;
247 *ep++ = CBACK;
248 *ep++ = c;
249 continue;
250 }
251
252 defchar:
253 default:
254 *ep++ = CCHR;
255 *ep++ = c;
256 }
257 }
258 cerror:
259 errexit("grep: RE error\n", (char *)NULL);
260}
261
262execute(file)
263char *file;
264{
265 register char *p1, *p2;
266 register c;
267
268 if (file) {
269 if (freopen(file, "r", stdin) == NULL)
270 errexit("grep: can't open %s\n", file);
271 }
272 lnum = 0;
273 tln = 0;
274 for (;;) {
275 lnum++;
276 p1 = linebuf;
277 while ((c = getchar()) != '\n') {
278 if (c == EOF) {
279 if (cflag) {
280 if (nfile>1)
281 printf("%s:", file);
282 printf("%D\n", tln);
283 }
284 return;
285 }
286 *p1++ = c;
287 if (p1 >= &linebuf[LBSIZE-1])
288 break;
289 }
290 *p1++ = '\0';
291 p1 = linebuf;
292 p2 = expbuf;
293 if (circf) {
294 if (advance(p1, p2))
295 goto found;
296 goto nfound;
297 }
298 /* fast check for first character */
299 if (*p2==CCHR) {
300 c = p2[1];
301 do {
302 if (*p1!=c)
303 continue;
304 if (advance(p1, p2))
305 goto found;
306 } while (*p1++);
307 goto nfound;
308 }
309 /* regular algorithm */
310 do {
311 if (advance(p1, p2))
312 goto found;
313 } while (*p1++);
314 nfound:
315 if (vflag)
316 succeed(file);
317 continue;
318 found:
319 if (vflag==0)
320 succeed(file);
321 }
322}
323
324advance(lp, ep)
325register char *lp, *ep;
326{
327 register char *curlp;
328 char c;
329 char *bbeg;
330 int ct;
331
332 for (;;) switch (*ep++) {
333
334 case CCHR:
335 if (*ep++ == *lp++)
336 continue;
337 return(0);
338
339 case CDOT:
340 if (*lp++)
341 continue;
342 return(0);
343
344 case CDOL:
345 if (*lp==0)
346 continue;
347 return(0);
348
349 case CEOF:
350 return(1);
351
352 case CCL:
353 c = *lp++ & 0177;
354 if(ep[c>>3] & bittab[c & 07]) {
355 ep += 16;
356 continue;
357 }
358 return(0);
359 case CBRA:
360 braslist[*ep++] = lp;
361 continue;
362
363 case CKET:
364 braelist[*ep++] = lp;
365 continue;
366
367 case CBACK:
368 bbeg = braslist[*ep];
369 if (braelist[*ep]==0)
370 return(0);
371 ct = braelist[*ep++] - bbeg;
372 if(ecmp(bbeg, lp, ct)) {
373 lp += ct;
374 continue;
375 }
376 return(0);
377
378 case CBACK|STAR:
379 bbeg = braslist[*ep];
380 if (braelist[*ep]==0)
381 return(0);
382 ct = braelist[*ep++] - bbeg;
383 curlp = lp;
384 while(ecmp(bbeg, lp, ct))
385 lp += ct;
386 while(lp >= curlp) {
387 if(advance(lp, ep)) return(1);
388 lp -= ct;
389 }
390 return(0);
391
392
393 case CDOT|STAR:
394 curlp = lp;
395 while (*lp++);
396 goto star;
397
398 case CCHR|STAR:
399 curlp = lp;
400 while (*lp++ == *ep);
401 ep++;
402 goto star;
403
404 case CCL|STAR:
405 curlp = lp;
406 do {
407 c = *lp++ & 0177;
408 } while(ep[c>>3] & bittab[c & 07]);
409 ep += 16;
410 goto star;
411
412 star:
413 if(--lp == curlp) {
414 continue;
415 }
416
417 if(*ep == CCHR) {
418 c = ep[1];
419 do {
420 if(*lp != c)
421 continue;
422 if(advance(lp, ep))
423 return(1);
424 } while(lp-- > curlp);
425 return(0);
426 }
427
428 do {
429 if (advance(lp, ep))
430 return(1);
431 } while (lp-- > curlp);
432 return(0);
433
434 default:
435 errexit("grep RE botch\n", (char *)NULL);
436 }
437}
438
439succeed(f)
440char *f;
441{
442 nsucc = 1;
443 if (sflag)
444 return;
445 if (cflag) {
446 tln++;
447 return;
448 }
449 if (lflag) {
450 printf("%s\n", f);
451 fseek(stdin, 0l, 2);
452 return;
453 }
454 if (nfile > 1 && hflag)
455 printf("%s:", f);
456 if (bflag)
457 printf("%u:", blkno);
458 if (nflag)
459 printf("%ld:", lnum);
460 printf("%s\n", linebuf);
461}
462
463ecmp(a, b, count)
464char *a, *b;
465{
466 register cc = count;
467 while(cc--)
468 if(*a++ != *b++) return(0);
469 return(1);
470}
471
472errexit(s, f)
473char *s, *f;
474{
475 fprintf(stderr, s, f);
476 exit(2);
477}