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