text: /*-
   * Copyright (c) 1991, 1993
   *	The Regents of the University of California.  All rights reserved.
   *
   * %sccs.include.proprietary.c%
   */
  
  #ifndef lint
  static char copyright[] =
  "@(#) Copyright (c) 1991, 1993\n\
  	The Regents of the University of California.  All rights reserved.\n";
  #endif /* not lint */
  
  #ifndef lint
  static char sccsid[] = "@(#)old.bin.grep.c	8.1 (Berkeley) 06/06/93";
  #endif /* not lint */
  
  /*
   * grep -- print lines matching (or not matching) a pattern
   *
   *	status returns:
   *		0 - ok, and some matches
   *		1 - ok, but no matches
   *		2 - some error
   */
  
  #include <stdio.h>
  #include <ctype.h>
  
  #define	CBRA	1
  #define	CCHR	2
  #define	CDOT	4
  #define	CCL	6
  #define	NCCL	8
  #define	CDOL	10
  #define	CEOF	11
  #define	CKET	12
  #define	CBRC	14
  #define	CLET	15
  #define	CBACK	18
  
  #define	STAR	01
  
  #define	LBSIZE	BUFSIZ
  #define	ESIZE	256
  #define	NBRA	9
  
  char	expbuf[ESIZE];
  long	lnum;
  char	linebuf[LBSIZE+1];
  char	ybuf[ESIZE];
  int	bflag;
  int	lflag;
  int	nflag;
  int	cflag;
  int	vflag;
  int	nfile;
  int	hflag	= 1;
  int	oflag;
  int	sflag;
  int	yflag;
  int	wflag;
  int	retcode = 0;
  int	circf;
  int	blkno;
  long	tln;
  int	nsucc;
  char	*braslist[NBRA];
  char	*braelist[NBRA];
  char	bittab[] = {
  	1,
  	2,
  	4,
  	8,
  	16,
  	32,
  	64,
  	128
  };
  
  main(argc, argv)
  	int argc;
  	char **argv;
  {
  	extern char *optarg;
  	extern int optind;
  	int ch;
  
  	while ((ch = getopt(argc, argv, "iywohsvblcne:")) != EOF)
  		switch((char)ch) {
  		case 'i':
  		case 'y':
  			yflag++;
  			break;
  		case 'w':
  			wflag++;
  			break;
  		case 'o':
  			oflag++;
  			break;
  		case 'h':
  			hflag = 0;
  			break;
  		case 's':
  			sflag++;
  			break;
  		case 'v':
  			vflag++;
  			break;
  		case 'b':
  			bflag++;
  			break;
  		case 'l':
  			lflag++;
  			break;
  		case 'c':
  			cflag++;
  			break;
  		case 'n':
  			nflag++;
  			break;
  		case 'e':
  			argv += optind - 1;
  			argc -= optind - 1;
  			*argv = optarg;
  			goto out;
  		case '?':
  		default:
  			errexit("grep: unknown flag\n", (char *)NULL);
  		}
  	argv += optind;
  	argc -= optind;
  
  out:
  	if (argc<=0)
  		exit(2);
  	if (yflag) {
  		register char *p, *s;
  		for (s = ybuf, p = *argv; *p; ) {
  			if (*p == '\\') {
  				*s++ = *p++;
  				if (*p)
  					*s++ = *p++;
  			} else if (*p == '[') {
  				while (*p != '\0' && *p != ']')
  					*s++ = *p++;
  			} else if (islower(*p)) {
  				*s++ = '[';
  				*s++ = toupper(*p);
  				*s++ = *p++;
  				*s++ = ']';
  			} else
  				*s++ = *p++;
  			if (s >= ybuf+ESIZE-5)
  				errexit("grep: argument too long\n", (char *)NULL);
  		}
  		*s = '\0';
  		*argv = ybuf;
  	}
  	compile(*argv);
  	nfile = --argc;
  	if (argc<=0) {
  		if (lflag)
  			exit(1);
  		execute((char *)NULL);
  	} else while (--argc >= 0) {
  		argv++;
  		execute(*argv);
  	}
  	exit(retcode != 0 ? retcode : nsucc == 0);
  }
  
  compile(astr)
  char *astr;
  {
  	register c;
  	register char *ep, *sp;
  	char *cstart;
  	char *lastep;
  	int cclcnt;
  	char bracket[NBRA], *bracketp;
  	int closed;
  	char numbra;
  	char neg;
  
  	ep = expbuf;
  	sp = astr;
  	lastep = 0;
  	bracketp = bracket;
  	closed = numbra = 0;
  	if (*sp == '^') {
  		circf++;
  		sp++;
  	}
  	if (wflag)
  		*ep++ = CBRC;
  	for (;;) {
  		if (ep >= &expbuf[ESIZE])
  			goto cerror;
  		if ((c = *sp++) != '*')
  			lastep = ep;
  		switch (c) {
  
  		case '\0':
  			if (wflag)
  				*ep++ = CLET;
  			*ep++ = CEOF;
  			return;
  
  		case '.':
  			*ep++ = CDOT;
  			continue;
  
  		case '*':
  			if (lastep==0 || *lastep==CBRA || *lastep==CKET ||
  			    *lastep == CBRC || *lastep == CLET)
  				goto defchar;
  			*lastep |= STAR;
  			continue;
  
  		case '$':
  			if (*sp != '\0')
  				goto defchar;
  			*ep++ = CDOL;
  			continue;
  
  		case '[':
  			if(&ep[17] >= &expbuf[ESIZE])
  				goto cerror;
  			*ep++ = CCL;
  			neg = 0;
  			if((c = *sp++) == '^') {
  				neg = 1;
  				c = *sp++;
  			}
  			cstart = sp;
  			do {
  				if (c=='\0')
  					goto cerror;
  				if (c=='-' && sp>cstart && *sp!=']') {
  					for (c = sp[-2]; c<*sp; c++)
  						ep[c>>3] |= bittab[c&07];
  					sp++;
  				}
  				ep[c>>3] |= bittab[c&07];
  			} while((c = *sp++) != ']');
  			if(neg) {
  				for(cclcnt = 0; cclcnt < 16; cclcnt++)
  					ep[cclcnt] ^= -1;
  				ep[0] &= 0376;
  			}
  
  			ep += 16;
  
  			continue;
  
  		case '\\':
  			if((c = *sp++) == 0)
  				goto cerror;
  			if(c == '<') {
  				*ep++ = CBRC;
  				continue;
  			}
  			if(c == '>') {
  				*ep++ = CLET;
  				continue;
  			}
  			if(c == '(') {
  				if(numbra >= NBRA) {
  					goto cerror;
  				}
  				*bracketp++ = numbra;
  				*ep++ = CBRA;
  				*ep++ = numbra++;
  				continue;
  			}
  			if(c == ')') {
  				if(bracketp <= bracket) {
  					goto cerror;
  				}
  				*ep++ = CKET;
  				*ep++ = *--bracketp;
  				closed++;
  				continue;
  			}
  
  			if(c >= '1' && c <= '9') {
  				if((c -= '1') >= closed)
  					goto cerror;
  				*ep++ = CBACK;
  				*ep++ = c;
  				continue;
  			}
  
  		defchar:
  		default:
  			*ep++ = CCHR;
  			*ep++ = c;
  		}
  	}
      cerror:
  	errexit("grep: RE error\n", (char *)NULL);
  }
  
  execute(file)
  char *file;
  {
  	register char *p1, *p2;
  	register c;
  
  	if (file) {
  		if (freopen(file, "r", stdin) == NULL) {
  			perror(file);
  			retcode = 2;
  		}
  	}
  	lnum = 0;
  	tln = 0;
  	for (;;) {
  		lnum++;
  		p1 = linebuf;
  		while ((c = getchar()) != '\n') {
  			if (c == EOF) {
  				if (cflag) {
  					if (nfile>1)
  						printf("%s:", file);
  					printf("%D\n", tln);
  					fflush(stdout);
  				}
  				return;
  			}
  			*p1++ = c;
  			if (p1 >= &linebuf[LBSIZE-1])
  				break;
  		}
  		*p1++ = '\0';
  		p1 = linebuf;
  		p2 = expbuf;
  		if (circf) {
  			if (advance(p1, p2))
  				goto found;
  			goto nfound;
  		}
  		/* fast check for first character */
  		if (*p2==CCHR) {
  			c = p2[1];
  			do {
  				if (*p1!=c)
  					continue;
  				if (advance(p1, p2))
  					goto found;
  			} while (*p1++);
  			goto nfound;
  		}
  		/* regular algorithm */
  		do {
  			if (advance(p1, p2))
  				goto found;
  		} while (*p1++);
  	nfound:
  		if (vflag)
  			succeed(file);
  		continue;
  	found:
  		if (vflag==0)
  			succeed(file);
  	}
  }
  
  advance(lp, ep)
  register char *lp, *ep;
  {
  	register char *curlp;
  	char c;
  	char *bbeg;
  	int ct;
  
  	for (;;) switch (*ep++) {
  
  	case CCHR:
  		if (*ep++ == *lp++)
  			continue;
  		return(0);
  
  	case CDOT:
  		if (*lp++)
  			continue;
  		return(0);
  
  	case CDOL:
  		if (*lp==0)
  			continue;
  		return(0);
  
  	case CEOF:
  		return(1);
  
  	case CCL:
  		c = *lp++ & 0177;
  		if(ep[c>>3] & bittab[c & 07]) {
  			ep += 16;
  			continue;
  		}
  		return(0);
  	case CBRA:
  		braslist[*ep++] = lp;
  		continue;
  
  	case CKET:
  		braelist[*ep++] = lp;
  		continue;
  
  	case CBACK:
  		bbeg = braslist[*ep];
  		if (braelist[*ep]==0)
  			return(0);
  		ct = braelist[*ep++] - bbeg;
  		if(ecmp(bbeg, lp, ct)) {
  			lp += ct;
  			continue;
  		}
  		return(0);
  
  	case CBACK|STAR:
  		bbeg = braslist[*ep];
  		if (braelist[*ep]==0)
  			return(0);
  		ct = braelist[*ep++] - bbeg;
  		curlp = lp;
  		while(ecmp(bbeg, lp, ct))
  			lp += ct;
  		while(lp >= curlp) {
  			if(advance(lp, ep))	return(1);
  			lp -= ct;
  		}
  		return(0);
  
  
  	case CDOT|STAR:
  		curlp = lp;
  		while (*lp++);
  		goto star;
  
  	case CCHR|STAR:
  		curlp = lp;
  		while (*lp++ == *ep);
  		ep++;
  		goto star;
  
  	case CCL|STAR:
  		curlp = lp;
  		do {
  			c = *lp++ & 0177;
  		} while(ep[c>>3] & bittab[c & 07]);
  		ep += 16;
  		goto star;
  
  	star:
  		if(--lp == curlp) {
  			continue;
  		}
  
  		if(*ep == CCHR) {
  			c = ep[1];
  			do {
  				if(*lp != c)
  					continue;
  				if(advance(lp, ep))
  					return(1);
  			} while(lp-- > curlp);
  			return(0);
  		}
  
  		do {
  			if (advance(lp, ep))
  				return(1);
  		} while (lp-- > curlp);
  		return(0);
  
  	case CBRC:
  		if (lp == expbuf)
  			continue;
  #define	uletter(c)	(isalpha(c) || (c) == '_')
  		if (uletter(*lp) || isdigit(*lp))
  			if (!uletter(lp[-1]) && !isdigit(lp[-1]))
  				continue;
  		return (0);
  
  	case CLET:
  		if (!uletter(*lp) && !isdigit(*lp))
  			continue;
  		return (0);
  
  	default:
  		errexit("grep RE botch\n", (char *)NULL);
  	}
  }
  
  succeed(f)
  char *f;
  {
  	nsucc = 1;
  	if (sflag)
  		return;
  	if (cflag) {
  		tln++;
  		return;
  	}
  	if (lflag) {
  		printf("%s\n", f);
  		fflush(stdout);
  		fseek(stdin, 0l, 2);
  		return;
  	}
  	if (nfile > 1 && hflag || oflag)
  		printf("%s:", f);
  	if (bflag)
  		printf("%u:", blkno);
  	if (nflag)
  		printf("%ld:", lnum);
  	printf("%s\n", linebuf);
  	fflush(stdout);
  }
  
  ecmp(a, b, count)
  char	*a, *b;
  {
  	register cc = count;
  	while(cc--)
  		if(*a++ != *b++)	return(0);
  	return(1);
  }
  
  errexit(s, f)
  char *s, *f;
  {
  	fprintf(stderr, s, f);
  	exit(2);
  }
  