/*
 * $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
 *
 */
/*	Copyright (c) 1984 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/

%{
#ident	"$Header: egrep.y 1.5 89/11/10 $@(#)egrep:egrep.y	1.10.1.2"
%}
/*
 * egrep -- print lines containing (or not containing) a regular expression
 *
 *	status returns:
 *		0 - ok, and some matches
 *		1 - ok, but no matches
 *		2 - some error
 */
%token CHAR MCHAR DOT CCL NCCL OR CAT STAR PLUS QUEST
%left OR
%left CHAR MCHAR DOT CCL NCCL '('
%left CAT
%left STAR PLUS QUEST

%{
#include <stdio.h>
#include <ctype.h>

#define MAXLIN 350
#define MAXPOS 4000
#define NCHARS 256
#define NSTATES 128
#define FINAL -1
unsigned char gotofn[NSTATES][NCHARS];
int state[NSTATES];
#define MCHARS	128	/* # of 8th bit on codes */
#define MAXEUC 4	/* max # of bytes in EUC excluding ss2 and ss3 */
unsigned char multigoto[NSTATES], mstate[NSTATES];
int spos[NSTATES][MAXLIN];	/* for cgotofn(), mcgotofn() */
unsigned char out[NSTATES];
int line = 1;
int name[MAXLIN];
int left[MAXLIN];
int right[MAXLIN];
int parent[MAXLIN];
int foll[MAXLIN];
int positions[MAXPOS];
unsigned char chars[MAXLIN];
int nxtpos;
int nxtchar = 0;
unsigned char bytes[MAXLIN];
int nxtbyte = 0;
int tmpstat[MAXLIN];
int initstat[MAXLIN];
int xstate;
int count;
int icount;
unsigned char *input = NULL;

extern int getopt();
int access();
void exit();

#include	<euc.h>
#include	<getwidth.h>
#define	Wgetwidth()	{getwidth(&WW); WW._eucw2++; WW._eucw3++;}
eucwidth_t WW;
#define WIDTH1	WW._eucw1
#define WIDTH2	WW._eucw2
#define WIDTH3	WW._eucw3
#define MULTI_BYTE	WW._multibyte
#define WIDTH(c)	(ISASCII((c)) ? 1 : \
			(ISSET2((c)) ? WIDTH2 : (ISSET3((c)) ? WIDTH3 : WIDTH1)))
#define CODESET(c)	(ISASCII(c) ? 0 : (ISSET2(c) ? 2 : (ISSET3(c) ? 3 : 1 )))

long	lnum;
int	bflag;
int	cflag;
int	iflag;
int	fflag;
int	lflag;
int	nflag;
int	vflag;
int	eflag;
int	nfile;
extern 	char *optarg;
extern	int optind;
FILE	*expfile;
FILE	*fptr;
int	blkno;
long	tln;
int	nsucc;

%}

%%
s:	t
		={ (void) unary(FINAL, $1);
		  line--;
		}
	;
t:	b r
		={ $$ = node(CAT, $1, $2); }
	| OR b r OR
		={ $$ = node(CAT, $2, $3); }
	| OR b r
		={ $$ = node(CAT, $2, $3); }
	| b r OR
		={ $$ = node(CAT, $1, $2); }
	;
b:
		={ $$ = enter(DOT);
		   $$ = unary(STAR, $$); }
	;
r:	CHAR
		={ $$ = enter($1); }
	| MCHAR
		={ $$ = menter($1); }
	| DOT
		={ $$ = enter(DOT); }
	| CCL
		={ $$ = cclenter(CCL); }
	| NCCL
		={ $$ = cclenter(NCCL); }
	;

r:	r OR r
		={ $$ = node(OR, $1, $3); }
	| r r %prec CAT
		={ $$ = node(CAT, $1, $2); }
	| r STAR
		={ $$ = unary(STAR, $1); }
	| r PLUS
		={ $$ = unary(PLUS, $1); }
	| r QUEST
		={ $$ = unary(QUEST, $1); }
	| '(' r ')'
		={ $$ = $2; }
	| error 
	;

%%
void
yyerror(s) 
char *s;
{
	(void) fprintf(stderr, gettxt("colon:9","egrep: %s\n"), s);
	exit(2);
}

yylex() {
	extern int yylval;
	int cclcnt, x;
	register int w, j;
	unsigned char *q;
#define LEFTEDGEP(p)	(ISASCII(p[-1]) ? 1 :		\
			(ISSET2(p[-WIDTH2]) ? WIDTH2 :	\
			(ISSET3(p[-WIDTH3]) ? WIDTH3 : WIDTH1 )))
	register unsigned char c, d;
	switch(c = nextch()) {
		case '$':
		case '^': c = '\n';
			goto defchar;
		case '|': return (OR);
		case '*': return (STAR);
		case '+': return (PLUS);
		case '?': return (QUEST);
		case '(': return (c);
		case ')': return (c);
		case '.': return (DOT);
		case '\0': return (0);
		case '\n': return (OR);
		case '[': 
			x = CCL;
			cclcnt = 0;
			count = nxtchar++;
			if ((c = nextch()) == '^') {
				x = NCCL;
				c = nextch();
			}
			do {
				if (c == '\0') synerror();
				if (c == '-' && cclcnt > 0 && chars[nxtchar-1] != 0) {
					if ((c = nextch()) != 0) {
						q = &chars[nxtchar];
						q -= LEFTEDGEP(q);
						if(CODESET(*q) != CODESET(c))
							;/* '-' is discarded */
						else if((w=WIDTH(c)) <= 1) {
							d = chars[nxtchar-1];
							while (++d < c) {
								if (nxtchar >= MAXLIN) overflo();
								chars[nxtchar++] = d;
								cclcnt++;
							}
						} else {
							if (nxtchar >= MAXLIN) overflo();
							chars[nxtchar++] = '-';
							cclcnt++;
							for(j=0; j<w && q[j]==c; j++) {
								if (nxtchar >= MAXLIN) overflo();
								chars[nxtchar++] = c;
								cclcnt++;
								c = nextch();
							}
							if(j >= w) {
								/* remove '-' and 'y' */
								cclcnt -= (w+1);
								nxtchar -= (w+1);
							} else if(q[j] > c) {
								/* remove '-' */
								cclcnt--;
								nxtchar--;
								if(j>0) strncpy(&chars[nxtchar-j], &chars[nxtchar-j+1], j);
							}
						}
					}
				}
				if (nxtchar >= MAXLIN) overflo();
				chars[nxtchar++] = c;
				cclcnt++;
			} while ((c = nextch()) != ']');
			chars[count] = cclcnt;
			return (x);
		case '\\':
			if ((c = nextch()) == '\0') synerror();
		defchar:
		default: yylval = c;
			if((w=WIDTH(c)) <= 1) return (CHAR);
			count = nxtbyte; /* menter() refers count. */
			while(--w) bytes[nxtbyte++] = nextch();
			return (MCHAR);
	}
}

int
nextch() {
	register int c;
	if (fflag) {
		if ((c = getc(expfile)) == EOF) return(0);
	}
	else c = *input++;
	return(c);
}

int
synerror() {
	(void) fprintf(stderr, gettxt("egrep:1","egrep: syntax error\n"));
	exit(2);
}

int
enter(x) int x; {
	if(line >= MAXLIN) overflo();
	name[line] = x;
	left[line] = 0;
	right[line] = 0;
	return(line++);
}

int
menter(x) int x; {
	if(line >= MAXLIN) overflo();
	name[line] = x;
	left[line] = 0;
	right[line] = count;
	return(line++);
}

int
cclenter(x) int x; {
	register linno;
	linno = enter(x);
	right[linno] = count;
	return (linno);
}

int
node(x, l, r) int x, l, r; {
	if(line >= MAXLIN) overflo();
	name[line] = x;
	left[line] = l;
	right[line] = r;
	parent[l] = line;
	parent[r] = line;
	return(line++);
}

int
unary(x, d) int x, d; {
	if(line >= MAXLIN) overflo();
	name[line] = x;
	left[line] = d;
	right[line] = 0;
	parent[d] = line;
	return(line++);
}

int
overflo() {
	(void) fprintf(stderr, gettxt("egrep:2","egrep: regular expression too long\n"));
	exit(2);
}

void
cfoll(v) int v;{
	register i;
	if (left[v] == 0) {
		count = 0;
		for (i=1; i<=line; i++) tmpstat[i] = 0;
		follow(v);
		add(foll, v);
	}
	else if (right[v] == 0) cfoll(left[v]);
	else {
		cfoll(left[v]);
		cfoll(right[v]);
	}
}

void
cgotofn() {
	register c, i, k;
	int n, s;
	unsigned char symbol[NCHARS];
	int j, nc, pc, pos;
	int curpos, num;
	int number, newpos;
	int nstate, dotstate, substate;
	unsigned char mc[MAXEUC+1];
	count = 0;
	for (n=3; n<=line; n++) tmpstat[n] = 0;
	if (cstate(line-1)==0) {
		tmpstat[line] = 1;
		count++;
		out[0] = 1;
	}
	for (n=3; n<=line; n++) initstat[n] = tmpstat[n];
	count--;		/*leave out position 1 */
	icount = count;
	tmpstat[1] = 0;
	add(state, 0);
	n = 0;
	multigoto[0] = mstate[0] = 0;
	for (s=0; s<=n; s++)  {
		if (multigoto[s]) continue;
		if (out[s] == 1) continue;
		for (i=0; i<NCHARS; i++) symbol[i] = 0;
		num = positions[state[s]];
		count = icount;
		for (i=3; i<=line; i++) tmpstat[i] = initstat[i];
		pos = state[s] + 1;
		for (i=0; i<num; i++) {
			curpos = positions[pos];
			if ((c = name[curpos]) >= 0) {
				if (c < NCHARS) symbol[c] = 1;
				else if (c == DOT) {
					for (k=0; k<NCHARS; k++)
						if (k!='\n') symbol[k] = 1;
				}
				else if (c == CCL) {
					pc = right[curpos] + 1;
					nc = pc + chars[right[curpos]];
					for( ; pc < nc; pc += WIDTH(chars[pc])) 
					{
					if(chars[pc]=='-' && c!=CCL && pc+1<nc)
						for(pc++; c++ < chars[pc];)
							symbol[c] = 1;
					symbol[(c = chars[pc])] = 1;
					}
				}
				else if (c == NCCL) {
						nc=right[curpos]+1+chars[right[curpos]];
					for(j=0; j< MCHARS; j++) {
						pc = right[curpos] + 1;
						for (k = 0; k < nc; k++)
							if (j==chars[pc++]) goto cont;
						if (j!='\n') symbol[j] = 1;
						cont:;
					}
					for (j = MCHARS; j < NCHARS; j++) {
						if(WIDTH(j) <= 1) {
							pc = right[curpos] + 1;
							for( ; pc<nc; pc += WIDTH(chars[pc]))
								if (j==chars[pc]) goto contm;
						}
						symbol[j] = 1;
						contm:;
					}
				}
				else (void) printf(gettxt("egrep:3", "something's funny\n"));
			}
			pos++;
		}
		for (c=0; c<NCHARS; c++) {
			if (symbol[c] == 1) { /* nextstate(s,c) */
				count = icount;
				for (i=3; i <= line; i++) tmpstat[i] = initstat[i];
				pos = state[s] + 1;
				nstate = dotstate = substate = 0;
				for (i=0; i<num; i++) {
					curpos = positions[pos];
					if ((k = name[curpos]) >= 0)
						if (
							(k == c)
							|| (k == DOT)
							|| (k == CCL && member(c, right[curpos], 1))
							|| (k == NCCL && (WIDTH(c ) > 1 || member(c, right[curpos], 0)))
						) {
							if(WIDTH(c)>1) {
								spos[n+1][++nstate] = curpos;
								if(k==DOT) dotstate++;
								else if(k!=NCCL || member(c, right[curpos], 1))
									substate++;
							}
							number = positions[foll[curpos]];
							newpos = foll[curpos] + 1;
							for (k=0; k<number; k++) {
								if (tmpstat[positions[newpos]] != 1) {
									tmpstat[positions[newpos]] = 1;
									count++;
								}
								newpos++;
							}
						}
					pos++;
				} /* end nextstate */
				spos[n+1][0] = nstate;
				if(substate < nstate-dotstate) {
					for(i = 1; i <= n; i++)
						if((k = spos[i][0]) == nstate) {
							for( ; k>0 && spos[n+1][k]==spos[i][k]; k--);
							if(k <= 0) {
								gotofn[s][c] = i;
								goto cont_c;
							}
						}
				}
				if (notin(n, 0, nstate!=dotstate)) {
				newin:
					if (n >= NSTATES) overflo();
					add(state, ++n);
					if (tmpstat[line] == 1) out[n] = 1;
					gotofn[s][c] = n;
					mstate[n] = 0;
					if(nstate == dotstate)
						multigoto[n] = 0;
					else {
						multigoto[n] = 1;
						mc[0] = c;
						n = mcgotofn(mc, 1, spos[n], n);
					}
				}
				else {
					if(nstate-dotstate>0 || multigoto[xstate] && WIDTH(c)<=1)
						goto newin;
					gotofn[s][c] = xstate;
				}
				cont_c:;
			}
		}
	}
}

int
mcgotofn(mc, m, pos, s)
unsigned char *mc;
register int m, *pos;
int s;
{
	register int c, i, k, num;
	unsigned char symbol[MCHARS];
	int n;
	int j, w, pcw, nc, pc;
	int number, newpos;
	int nstate, dotstate, substate, lastbyte;
	n = s;
	num = *pos++;
	w = WIDTH(*mc);
	lastbyte = w-m == 1 ? 1 : 0;
	for (i=0; i<MCHARS; i++) symbol[i] = 0;
	count = icount;
	for (i=3; i<=line; i++) tmpstat[i] = initstat[i];
	for (i=0; i<num; i++) {
		if ((c = name[pos[i]]) == *mc)
			symbol[(bytes[right[pos[i]]+m-1]) & 0177] = 1;
		else if (c == DOT) {
			for (k=0; k<MCHARS; k++) symbol[k] = 1;
		}
		else if (c == CCL) {
			pc = right[pos[i]] + 1;
			nc = pc + chars[right[pos[i]]];
			for( ; pc < nc; pc += WIDTH(chars[pc])) {
				for(j=0; j<m && chars[pc+j] == mc[j]; j++);
				if(j>=m) symbol[chars[pc+m]&0177] = 1;
			}
			pc = right[pos[i]] + 1;
			for( ; pc < nc; pc += pcw) {
				pcw = WIDTH(chars[pc]);
				if(chars[pc+pcw] == '-' && pc+pcw+1 < nc
					&& CODESET(chars[pc]) == CODESET(*mc)
				) {
					for(j=0; j<m && chars[pc+j]==mc[j]; j++);
					if(j>=m) c = chars[pc+m];
					else if(chars[pc+j]<mc[j]) c = MCHARS;
					else continue;
					pc += (pcw+1);
					for(j=0; j<m && chars[pc+j]==mc[j]; j++);
					if(j>=m) k = chars[pc+m];
					else if(chars[pc+j]>mc[j]) k = NCHARS;
					else continue;
					while(c < k) symbol[c++&0177] = 1;
				}
			}
		}
		else if (c == NCCL) {
			nc = right[pos[i]] + 1 + chars[right[pos[i]]];
			for (k = MCHARS; k < NCHARS; k++) {
				if(lastbyte) {
					pc = right[pos[i]]+1;
					for( ; pc<nc; pc += WIDTH(chars[pc])) {
						for(j=0; j<m && chars[pc+j] == mc[j]; j++);
						if(j>=m && k==chars[pc+m])
							goto cont;
					}
					pc = right[pos[i]] + 1;
					for( ; pc < nc; pc += pcw) {
						pcw = WIDTH(chars[pc]);
						if(chars[pc+pcw] == '-' && pc+pcw+1 < nc
						&& CODESET(chars[pc]) == CODESET(*mc)
						) {
							for(j=0; j<m && chars[pc+j]==mc[j]; j++);
							if(j>=m && k<chars[pc+m]
							|| j<m &&  mc[j]<chars[pc+j])
								continue;
							pc += (pcw+1);
							for(j=0; j<m && chars[pc+j]==mc[j]; j++);
							if(j>=m && k<chars[pc+m]
							|| j<m && mc[j]<chars[pc+j])
								goto cont;
						}
					}
				}
				symbol[k&0177] = 1;
				cont:;
			}
		}
		else (void) printf(gettxt("egrep:3", "something's funny\n"));
	}
	for (c=MCHARS; c<NCHARS; c++) {
		if (symbol[c&0177] == 1) { /* nextstate(s,c) */
			count = icount;
			for (i=3; i <= line; i++) tmpstat[i] = initstat[i];
			nstate = dotstate = substate = 0;
			mc[m] = c;
			for (i=0; i<num; i++) {
				if (
					(k=name[pos[i]]) == *mc && strncmp(mc+1, &bytes[right[pos[i]]], m) == 0
					|| k == DOT
					|| k == CCL && memberm(mc, m, &chars[right[pos[i]]], 1)
					|| k == NCCL && (!lastbyte || memberm(mc, m, &chars[right[pos[i]]], 0))
				) {
					if(!lastbyte) {
						spos[n+1][++nstate] = pos[i];
						if(k==DOT) dotstate++;
						else if(k!=NCCL || memberm(mc, m, &chars[right[pos[i]]], 1))
							substate++;
					}
					number = positions[foll[pos[i]]];
					newpos = foll[pos[i]] + 1;
					for (k=0; k<number; k++) {
						if (tmpstat[positions[newpos]] != 1) {
							tmpstat[positions[newpos]] = 1;
							count++;
						}
						newpos++;
					}
				}
			} /* end nextstate */
			spos[n+1][0] = nstate;
			if(substate < nstate-dotstate) {
				for(i=1; i<=m; i++)
					if((k = spos[i][0]) == nstate) {
						for( ; k>0 && spos[n+1][k]==spos[i][k]; k--);
						if(k <= 0) {
							gotofn[s][c] = i;
							goto cont_mc;
						}
					}
			}
			if (notin(n, m, nstate!=dotstate)) {
				if (n >= NSTATES) overflo();
				add(state, ++n);
				if (tmpstat[line] == 1) out[n] = 1;
				gotofn[s][c] = n;
				mstate[n] = m;
				if(nstate == dotstate)
					multigoto[n] = 0;
				else {
					multigoto[n] = 1;
					n = mcgotofn(mc, m+1, spos[n], n);
				}
			} else {
				gotofn[s][c] = xstate;
			}
			cont_mc:;
		}
	}
	return(n);
}

int
cstate(v) int v;{
	register b;
	if (left[v] == 0) {
		if (tmpstat[v] != 1) {
			tmpstat[v] = 1;
			count++;
		}
		return(1);
	}
	else if (right[v] == 0) {
		if (cstate(left[v]) == 0) return (0);
		else if (name[v] == PLUS) return (1);
		else return (0);
	}
	else if (name[v] == CAT) {
		if (cstate(left[v]) == 0 && cstate(right[v]) == 0) return (0);
		else return (1);
	}
	else { /* name[v] == OR */
		b = cstate(right[v]);
		if (cstate(left[v]) == 0 || b == 0) return (0);
		else return (1);
	}
}


int
member(symb, set, torf) int symb, set, torf;{
	register num, pos;
	pos = set + 1;
	num = pos + chars[set];
	if(symb == '-') {
		if(chars[pos] == '-' || chars[num-1] == '-')
			return(torf);
		return(!torf);
	}
	while(pos < num) {
		if (symb == chars[pos]) return (torf);
		if(WIDTH(chars[pos]) > 1 && symb > chars[pos]) {
			pos += WIDTH(chars[pos]);
			if(chars[pos] != '-' || pos++ >= num) continue;
			if(symb <= chars[pos]) return(torf);
		}
		pos += WIDTH(chars[pos]);
	}
	return (!torf);
}

memberm(p, m, set, torf)
	register unsigned char *p, *set;
	int m, torf;
{
	register int j, w, num, pos;
	for(pos=0, num = *set++; pos < num; pos += w) {
		w = WIDTH(set[pos]);
		for(j=0; j <= m && p[j] == set[pos+j]; j++);
		if(j > m) return(torf);
		if(set[pos+w]=='-' && pos+w+1<num && CODESET(*p)==CODESET(set[pos])) {
			if(p[j] < set[pos+j]) continue;
			pos += (w+1);
			for(j=0; j <= m && p[j] == set[pos+j]; j++);
			if(j > m || p[j] < set[pos+j]) return(torf);
		}
	}
	return(!torf);
}

int
notin(n,flag,multi) int n, flag, multi;{
	register i, j, pos;
	for (i=0; i<=n; i++) {
		if (mstate[i] != flag || multigoto[i] != multi) continue;
		if (positions[state[i]] == count) {
			pos = state[i] + 1;
			for (j=0; j < count; j++)
				if (tmpstat[positions[pos++]] != 1) goto nxt;
			xstate = i;
			return (0);
		}
		nxt: ;
	}
	return (1);
}

int
add(array, n) int *array; int n;{
	register i;
	if (nxtpos + count > MAXPOS) overflo();
	array[n] = nxtpos;
	positions[nxtpos++] = count;
	for (i=3; i <= line; i++) {
		if (tmpstat[i] == 1) {
			positions[nxtpos++] = i;
		}
	}
}

int
follow(v) int v; {
	int p;
	if (v == line) return;
	p = parent[v];
	switch(name[p]) {
		case STAR:
		case PLUS:	(void) cstate(v);
				follow(p);
				return;

		case OR:
		case QUEST:	follow(p);
				return;

		case CAT:	if (v == left[p]) {
					if (cstate(right[p]) == 0) {
						follow(p);
						return;
					}
				}
				else follow(p);
				return;
		case FINAL:	if (tmpstat[line] != 1) {
					tmpstat[line] = 1;
					count++;
				}
				return;
	}
}


void
main(argc, argv)
int argc;
char **argv;
{
	register c;
	char *usage;
	register unsigned char *arg;
	int errflg = 0;
	usage = "[ -bcilnv ] [ -e exp ] [ -f file ] [ strings ] [ file ] ...";

	while(( c = getopt(argc, argv, "bcie:f:lnv")) != EOF)
		switch(c) {

		case 'b':
			bflag++;
			continue;

		case 'c':
			cflag++;
			continue;

		case 'i':
			iflag++;
			continue;

		case 'e':
			eflag++;
			input = (unsigned char *)optarg;
			continue;

		case 'f':
			fflag++;
			expfile = fopen(optarg,"r");
			if (expfile == NULL) {
				(void) fprintf(stderr, gettxt("egrep:4","egrep: can't open %s\n"), optarg);
				exit(2);
			}
			continue;

		case 'l':
			lflag++;
			continue;

		case 'n':
			nflag++;
			continue;

		case 'v':
			vflag++;
			continue;

		case '?':
			errflg++;
	}

	argc -= optind;
	if (errflg || ((argc <= 0) && !fflag && !eflag)) {
		(void) printf(gettxt("egrep:5","usage: egrep %s\n"),usage);
		exit(2);
	}
	if ( !eflag  && !fflag ) {
		input = (unsigned char *)argv[optind];
		optind++;
		argc--;
	}

	if (iflag && !fflag) {
		for (arg = input; *arg != NULL; ++arg)
			*arg = (unsigned char)tolower((int)(*arg));
	}

	argv = &argv[optind];
	if(argc > 0)
		if (access(*argv, 0) != 0) {
			(void) fprintf(stderr, gettxt("egrep:6","egrep: %s does not exist\n"), *argv);
			exit(2);
		}
	Wgetwidth();
	(void) yyparse();

	cfoll(line-1);
	cgotofn();
	nfile = argc;
	if (argc<=0) {
		if (lflag) exit(1);
		execute((unsigned char *)NULL);
	}
	else
		while ( --argc >= 0 ) {
			execute(*(unsigned char **)argv);
			argv++;
		}
	exit((nsucc == 2) ? 2 : (nsucc == 0));
}

int
execute(file)
unsigned char *file;
{
	register unsigned char *p;
	register cstat;
	register ccount;
	register int w,i;
	unsigned char mc[MAXEUC+1];
	unsigned char buf[2*BUFSIZ];
	unsigned char *nlp;
	int istat;
	int in_line;
	if (file) {
		if ((fptr = fopen((char *)file, "r")) == NULL) {
			(void) fprintf(stderr, gettxt("egrep:4","egrep: can't open %s\n"), file);
			nsucc = 2;
			return;
		}
	}
	else
		fptr = stdin;
	ccount = 0;
	lnum = 1;
	tln = 0;
	in_line = 0;
	blkno = 0;
	p = buf;
	nlp = p;
	if ((ccount = fread((char *)p, sizeof(unsigned char), BUFSIZ, fptr)) <= 0) goto done;
	in_line = 1;
	istat = cstat = gotofn[0]['\n'];
	if (out[cstat]) goto found;
	for (;;) {
		w = WIDTH(*p);
		mc[0] = *p++;
		for(i=1; i<w; i++) {
			if (--ccount <= 0) {
				if (p <= &buf[BUFSIZ]) {
					ccount = fread((char *)p, sizeof(unsigned char), BUFSIZ, fptr);
				} else if (p == &buf[2*BUFSIZ]) {
					p = buf;
					ccount = fread((char *)p, sizeof(unsigned char), BUFSIZ, fptr);
				} else {
					ccount = fread((char *)p, sizeof(unsigned char), &buf[2*BUFSIZ] - p, fptr);
				}
				if (ccount <= 0) {
					if (in_line && vflag) {
						in_line = 0;
						goto succeed;
					}
					break;
				}
				blkno++;
			}
			in_line = 1;
			mc[i] = *p++;
		}
		p--;
		if (!iflag)
			cstat = gotofn[cstat][*mc];
		else
			cstat = gotofn[cstat][tolower(*mc)];
		if (w>1 && multigoto[cstat]) {
			for(i=1; i < w && multigoto[cstat]; i++) {
				if (!iflag)
					cstat = gotofn[cstat][mc[i]];
				else
					cstat = gotofn[cstat][tolower(mc[i])];
			}
		}
		if (out[cstat]) {
		found:	for(;;) {
				if (*p++ == '\n') {
					in_line = 0;
					if (vflag == 0) {
				succeed:	nsucc = (nsucc == 2) ? 2 : 1;
						if (cflag) tln++;
						else if (lflag) {
							(void) printf("%s\n", file);
							(void) fclose(fptr);
							return;
						}
						else {
							if (nfile > 1 ) (void) printf(gettxt("colon:10","%s:"), file);
							if (bflag) (void) printf(gettxt("colon:11","%d:"), blkno);
							if (nflag) (void) printf(gettxt("colon:12","%ld:"), lnum);
							if (p <= nlp) {
								while (nlp < &buf[2*BUFSIZ]) (void) putchar((char)*nlp++);
								nlp = buf;
							}
							while (nlp < p) (void) putchar((char)*nlp++);
						}
					}
					lnum++;
					nlp = p;
					if ((out[(cstat=istat)]) == 0) goto brk2;
				}
				cfound:
				if (--ccount <= 0) {
					if (p <= &buf[BUFSIZ]) {
						ccount = fread((char *)p, sizeof(unsigned char), BUFSIZ, fptr);
					}
					else if (p == &buf[2*BUFSIZ]) {
						p = buf;
						ccount = fread((char *)p, sizeof(unsigned char), BUFSIZ, fptr);
					}
					else {
						ccount = fread((char *)p, sizeof(unsigned char), &buf[2*BUFSIZ] - p, fptr);
					}
					if (ccount <= 0) {
						if (in_line && (vflag == 0)) {
							in_line = 0;
							goto succeed;
						}
						goto done;
					}
					blkno++;
				}
				in_line = 1;
			}
		}
		if (*p++ == '\n') {
			in_line = 0;
			if (vflag) goto succeed;
			else {
				lnum++;
				nlp = p;
				if (out[(cstat=istat)]) goto cfound;
			}
		}
		brk2:
		if (--ccount <= 0) {
			if (p <= &buf[BUFSIZ]) {
				ccount = fread((char *)p, sizeof(unsigned char), BUFSIZ, fptr);
			}
			else if (p == &buf[2*BUFSIZ]) {
				p = buf;
				ccount = fread((char *)p, sizeof(unsigned char), BUFSIZ, fptr);
			}
			else {
				ccount = fread((char *)p, sizeof(unsigned char), &buf[2*BUFSIZ] - p, fptr);
			}
			if (ccount <= 0) {
				if (in_line && vflag) {
					in_line = 0;
					goto succeed;
				}
				break;
			}
			blkno++;
		}
		in_line = 1;
	}
done:	(void) fclose(fptr);
	if (cflag) {
		if (nfile > 1 )
			(void) printf(gettxt("colon:10","%s:"), file);
		(void) printf("%ld\n", tln);
	}
}

