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