xref: /csrg-svn/old/awk/b.c (revision 48236)
1*48236Sbostic /*-
2*48236Sbostic  * Copyright (c) 1991 The Regents of the University of California.
3*48236Sbostic  * All rights reserved.
4*48236Sbostic  *
5*48236Sbostic  * %sccs.include.proprietary.c%
6*48236Sbostic  */
7*48236Sbostic 
814472Ssam #ifndef lint
9*48236Sbostic static char sccsid[] = "@(#)b.c	4.4 (Berkeley) 04/17/91";
10*48236Sbostic #endif /* not lint */
116669Smckusick 
126669Smckusick #include "awk.def"
136669Smckusick #include "stdio.h"
146669Smckusick #include "awk.h"
156669Smckusick 
166669Smckusick extern node *op2();
176669Smckusick extern struct fa *cgotofn();
186669Smckusick #define MAXLIN 256
196669Smckusick #define NCHARS 128
206669Smckusick #define NSTATES 256
216669Smckusick 
226669Smckusick #define type(v)	v->nobj
236669Smckusick #define left(v)	v->narg[0]
246669Smckusick #define right(v)	v->narg[1]
256669Smckusick #define parent(v)	v->nnext
266669Smckusick 
276669Smckusick #define LEAF	case CCL: case NCCL: case CHAR: case DOT:
286669Smckusick #define UNARY	case FINAL: case STAR: case PLUS: case QUEST:
296669Smckusick 
306669Smckusick /* encoding in tree nodes:
316669Smckusick 	leaf (CCL, NCCL, CHAR, DOT): left is index, right contains value or pointer to value
326669Smckusick 	unary (FINAL, STAR, PLUS, QUEST): left is child, right is null
336669Smckusick 	binary (CAT, OR): left and right are children
346669Smckusick 	parent contains pointer to parent
356669Smckusick */
366669Smckusick 
376669Smckusick struct fa {
386669Smckusick 	int cch;
396669Smckusick 	struct fa *st;
406669Smckusick };
416669Smckusick 
426669Smckusick int	*state[NSTATES];
436669Smckusick int	*foll[MAXLIN];
446669Smckusick char	chars[MAXLIN];
456669Smckusick int	setvec[MAXLIN];
466669Smckusick node	*point[MAXLIN];
476669Smckusick 
486669Smckusick int	setcnt;
496669Smckusick int	line;
5029543Smckusick int	maxfoll;  /* index of highest foll[] entry set by cfoll() */
516669Smckusick 
526669Smckusick 
makedfa(p)536669Smckusick struct fa *makedfa(p)	/* returns dfa for tree pointed to by p */
546669Smckusick node *p;
556669Smckusick {
566669Smckusick 	node *p1;
576669Smckusick 	struct fa *fap;
586669Smckusick 	p1 = op2(CAT, op2(STAR, op2(DOT, (node *) 0, (node *) 0), (node *) 0), p);
596669Smckusick 		/* put DOT STAR in front of reg. exp. */
606669Smckusick 	p1 = op2(FINAL, p1, (node *) 0);		/* install FINAL node */
616669Smckusick 
626669Smckusick 	line = 0;
636669Smckusick 	penter(p1);	/* enter parent pointers and leaf indices */
646669Smckusick 	point[line] = p1;	/* FINAL node */
656669Smckusick 	setvec[0] = 1;		/* for initial DOT STAR */
666669Smckusick 	cfoll(p1);	/* set up follow sets */
676669Smckusick 	fap = cgotofn();
686669Smckusick 	freetr(p1);	/* add this when alloc works */
696669Smckusick 	return(fap);
706669Smckusick }
716669Smckusick 
penter(p)726669Smckusick penter(p)	/* set up parent pointers and leaf indices */
736669Smckusick node *p;
746669Smckusick {
756669Smckusick 	switch(type(p)) {
766669Smckusick 		LEAF
776669Smckusick 			left(p) = (node *) line;
786669Smckusick 			point[line++] = p;
796669Smckusick 			break;
806669Smckusick 		UNARY
816669Smckusick 			penter(left(p));
826669Smckusick 			parent(left(p)) = p;
836669Smckusick 			break;
846669Smckusick 		case CAT:
856669Smckusick 		case OR:
866669Smckusick 			penter(left(p));
876669Smckusick 			penter(right(p));
886669Smckusick 			parent(left(p)) = p;
896669Smckusick 			parent(right(p)) = p;
906669Smckusick 			break;
916669Smckusick 		default:
926669Smckusick 			error(FATAL, "unknown type %d in penter\n", type(p));
936669Smckusick 			break;
946669Smckusick 	}
956669Smckusick }
966669Smckusick 
freetr(p)976669Smckusick freetr(p)	/* free parse tree and follow sets */
986669Smckusick node *p;
996669Smckusick {
1006669Smckusick 	switch(type(p)) {
1016669Smckusick 		LEAF
10229543Smckusick 			foll_free((int) left(p));
1036669Smckusick 			xfree(p);
1046669Smckusick 			break;
1056669Smckusick 		UNARY
1066669Smckusick 			freetr(left(p));
1076669Smckusick 			xfree(p);
1086669Smckusick 			break;
1096669Smckusick 		case CAT:
1106669Smckusick 		case OR:
1116669Smckusick 			freetr(left(p));
1126669Smckusick 			freetr(right(p));
1136669Smckusick 			xfree(p);
1146669Smckusick 			break;
1156669Smckusick 		default:
1166669Smckusick 			error(FATAL, "unknown type %d in freetr", type(p));
1176669Smckusick 			break;
1186669Smckusick 	}
1196669Smckusick }
cclenter(p)1206669Smckusick char *cclenter(p)
1216669Smckusick register char *p;
1226669Smckusick {
1236669Smckusick 	register i, c;
1246669Smckusick 	char *op;
1256669Smckusick 
1266669Smckusick 	op = p;
1276669Smckusick 	i = 0;
1286669Smckusick 	while ((c = *p++) != 0) {
1296669Smckusick 		if (c == '-' && i > 0 && chars[i-1] != 0) {
1306669Smckusick 			if (*p != 0) {
1316669Smckusick 				c = chars[i-1];
1326669Smckusick 				while (c < *p) {
1336669Smckusick 					if (i >= MAXLIN)
1346669Smckusick 						overflo();
1356669Smckusick 					chars[i++] = ++c;
1366669Smckusick 				}
1376669Smckusick 				p++;
1386669Smckusick 				continue;
1396669Smckusick 			}
1406669Smckusick 		}
1416669Smckusick 		if (i >= MAXLIN)
1426669Smckusick 			overflo();
1436669Smckusick 		chars[i++] = c;
1446669Smckusick 	}
1456669Smckusick 	chars[i++] = '\0';
1466669Smckusick 	dprintf("cclenter: in = |%s|, out = |%s|\n", op, chars, NULL);
1476669Smckusick 	xfree(op);
1486669Smckusick 	return(tostring(chars));
1496669Smckusick }
1506669Smckusick 
overflo()1516669Smckusick overflo()
1526669Smckusick {
1536669Smckusick 	error(FATAL, "regular expression too long\n");
1546669Smckusick }
1556669Smckusick 
cfoll(v)1566669Smckusick cfoll(v)		/* enter follow set of each leaf of vertex v into foll[leaf] */
1576669Smckusick register node *v;
1586669Smckusick {
1596669Smckusick 	register i;
1606669Smckusick 	int prev;
1616669Smckusick 	int *add();
1626669Smckusick 
16329543Smckusick 	maxfoll = -1;
1646669Smckusick 	switch(type(v)) {
1656669Smckusick 		LEAF
1666669Smckusick 			setcnt = 0;
1676669Smckusick 			for (i=1; i<=line; i++)
1686669Smckusick 				setvec[i] = 0;
1696669Smckusick 			follow(v);
1706669Smckusick 			if (notin(foll, ( (int) left(v))-1, &prev)) {
1716669Smckusick 				foll[(int) left(v)] = add(setcnt);
1726669Smckusick 			}
1736669Smckusick 			else
1746669Smckusick 				foll[ (int) left(v)] = foll[prev];
17529543Smckusick 			if ((int)left(v) > maxfoll)
17629543Smckusick 				maxfoll = (int)left(v);
1776669Smckusick 			break;
1786669Smckusick 		UNARY
1796669Smckusick 			cfoll(left(v));
1806669Smckusick 			break;
1816669Smckusick 		case CAT:
1826669Smckusick 		case OR:
1836669Smckusick 			cfoll(left(v));
1846669Smckusick 			cfoll(right(v));
1856669Smckusick 			break;
1866669Smckusick 		default:
1876669Smckusick 			error(FATAL, "unknown type %d in cfoll", type(v));
1886669Smckusick 	}
1896669Smckusick }
1906669Smckusick 
first(p)1916669Smckusick first(p)			/* collects initially active leaves of p into setvec */
1926669Smckusick register node *p;		/* returns 0 or 1 depending on whether p matches empty string */
1936669Smckusick {
1946669Smckusick 	register b;
1956669Smckusick 
1966669Smckusick 	switch(type(p)) {
1976669Smckusick 		LEAF
1986669Smckusick 			if (setvec[(int) left(p)] != 1) {
1996669Smckusick 				setvec[(int) left(p)] = 1;
2006669Smckusick 				setcnt++;
2016669Smckusick 			}
2026669Smckusick 			if (type(p) == CCL && (*(char *) right(p)) == '\0')
2036669Smckusick 				return(0);		/* empty CCL */
2046669Smckusick 			else return(1);
2056669Smckusick 		case FINAL:
2066669Smckusick 		case PLUS:
2076669Smckusick 			if (first(left(p)) == 0) return(0);
2086669Smckusick 			return(1);
2096669Smckusick 		case STAR:
2106669Smckusick 		case QUEST:
2116669Smckusick 			first(left(p));
2126669Smckusick 			return(0);
2136669Smckusick 		case CAT:
2146669Smckusick 			if (first(left(p)) == 0 && first(right(p)) == 0) return(0);
2156669Smckusick 			return(1);
2166669Smckusick 		case OR:
2176669Smckusick 			b = first(right(p));
2186669Smckusick 			if (first(left(p)) == 0 || b == 0) return(0);
2196669Smckusick 			return(1);
2206669Smckusick 	}
2216669Smckusick 	error(FATAL, "unknown type %d in first\n", type(p));
2226669Smckusick 	return(-1);
2236669Smckusick }
2246669Smckusick 
follow(v)2256669Smckusick follow(v)
2266669Smckusick node *v;		/* collects leaves that can follow v into setvec */
2276669Smckusick {
2286669Smckusick 	node *p;
2296669Smckusick 
2306669Smckusick 	if (type(v) == FINAL)
2316669Smckusick 		return;
2326669Smckusick 	p = parent(v);
2336669Smckusick 	switch (type(p)) {
2346669Smckusick 		case STAR:
2356669Smckusick 		case PLUS:	first(v);
2366669Smckusick 				follow(p);
2376669Smckusick 				return;
2386669Smckusick 
2396669Smckusick 		case OR:
2406669Smckusick 		case QUEST:	follow(p);
2416669Smckusick 				return;
2426669Smckusick 
2436669Smckusick 		case CAT:	if (v == left(p)) {	/* v is left child of p */
2446669Smckusick 					if (first(right(p)) == 0) {
2456669Smckusick 						follow(p);
2466669Smckusick 						return;
2476669Smckusick 					}
2486669Smckusick 				}
2496669Smckusick 				else		/* v is right child */
2506669Smckusick 					follow(p);
2516669Smckusick 				return;
2526669Smckusick 		case FINAL:	if (setvec[line] != 1) {
2536669Smckusick 					setvec[line] = 1;
2546669Smckusick 					setcnt++;
2556669Smckusick 				}
2566669Smckusick 				return;
2576669Smckusick 	}
2586669Smckusick }
2596669Smckusick 
member(c,s)2606669Smckusick member(c, s)	/* is c in s? */
2616669Smckusick register char c, *s;
2626669Smckusick {
2636669Smckusick 	while (*s)
2646669Smckusick 		if (c == *s++)
2656669Smckusick 			return(1);
2666669Smckusick 	return(0);
2676669Smckusick }
2686669Smckusick 
notin(array,n,prev)2696669Smckusick notin(array, n, prev)		/* is setvec in array[0] thru array[n]? */
2706669Smckusick int **array;
2716669Smckusick int *prev; {
2726669Smckusick 	register i, j;
2736669Smckusick 	int *ptr;
2746669Smckusick 	for (i=0; i<=n; i++) {
2756669Smckusick 		ptr = array[i];
2766669Smckusick 		if (*ptr == setcnt) {
2776669Smckusick 			for (j=0; j < setcnt; j++)
2786669Smckusick 				if (setvec[*(++ptr)] != 1) goto nxt;
2796669Smckusick 			*prev = i;
2806669Smckusick 			return(0);
2816669Smckusick 		}
2826669Smckusick 		nxt: ;
2836669Smckusick 	}
2846669Smckusick 	return(1);
2856669Smckusick }
2866669Smckusick 
add(n)2876669Smckusick int *add(n) {		/* remember setvec */
2886669Smckusick 	int *ptr, *p;
2896669Smckusick 	register i;
2906669Smckusick 	if ((p = ptr = (int *) malloc((n+1)*sizeof(int))) == NULL)
2916669Smckusick 		overflo();
2926669Smckusick 	*ptr = n;
2936669Smckusick 	dprintf("add(%d)\n", n, NULL, NULL);
2946669Smckusick 	for (i=1; i <= line; i++)
2956669Smckusick 		if (setvec[i] == 1) {
2966669Smckusick 			*(++ptr) = i;
2976669Smckusick 			dprintf("  ptr = %o, *ptr = %d, i = %d\n", ptr, *ptr, i);
2986669Smckusick 		}
2996669Smckusick 	dprintf("\n", NULL, NULL, NULL);
3006669Smckusick 	return(p);
3016669Smckusick }
3026669Smckusick 
cgotofn()3036669Smckusick struct fa *cgotofn()
3046669Smckusick {
3056669Smckusick 	register i, k;
3066669Smckusick 	register int *ptr;
3076669Smckusick 	char c;
3086669Smckusick 	char *p;
3096669Smckusick 	node *cp;
3106669Smckusick 	int j, n, s, ind, numtrans;
3116669Smckusick 	int finflg;
3126669Smckusick 	int curpos, num, prev;
3136669Smckusick 	struct fa *where[NSTATES];
3146669Smckusick 
3156669Smckusick 	int fatab[257];
3166669Smckusick 	struct fa *pfa;
3176669Smckusick 
3186669Smckusick 	char index[MAXLIN];
3196669Smckusick 	char iposns[MAXLIN];
3206669Smckusick 	int sposns[MAXLIN];
3216669Smckusick 	int spmax, spinit;
3226669Smckusick 
3236669Smckusick 	char symbol[NCHARS];
3246669Smckusick 	char isyms[NCHARS];
3256669Smckusick 	char ssyms[NCHARS];
3266669Smckusick 	int ssmax, ssinit;
3276669Smckusick 
3286669Smckusick 	for (i=0; i<=line; i++) index[i] = iposns[i] = setvec[i] = 0;
3296669Smckusick 	for (i=0; i<NCHARS; i++)  isyms[i] = symbol[i] = 0;
3306669Smckusick 	setcnt = 0;
3316669Smckusick 	/* compute initial positions and symbols of state 0 */
3326669Smckusick 	ssmax = 0;
3336669Smckusick 	ptr = state[0] = foll[0];
3346669Smckusick 	spinit = *ptr;
3356669Smckusick 	for (i=0; i<spinit; i++) {
3366669Smckusick 		curpos = *(++ptr);
3376669Smckusick 		sposns[i] = curpos;
3386669Smckusick 		iposns[curpos] = 1;
3396669Smckusick 		cp = point[curpos];
3406669Smckusick 		dprintf("i = %d, spinit = %d, curpos = %d\n", i, spinit, curpos);
3416669Smckusick 		switch (type(cp)) {
3426669Smckusick 			case CHAR:
3436669Smckusick 				k = (int) right(cp);
3446669Smckusick 				if (isyms[k] != 1) {
3456669Smckusick 					isyms[k] = 1;
3466669Smckusick 					ssyms[ssmax++] = k;
3476669Smckusick 				}
3486669Smckusick 				break;
3496669Smckusick 			case DOT:
3506669Smckusick 				for (k=1; k<NCHARS; k++) {
3516669Smckusick 					if (k != HAT) {
3526669Smckusick 						if (isyms[k] != 1) {
3536669Smckusick 							isyms[k] = 1;
3546669Smckusick 							ssyms[ssmax++] = k;
3556669Smckusick 						}
3566669Smckusick 					}
3576669Smckusick 				}
3586669Smckusick 				break;
3596669Smckusick 			case CCL:
3606669Smckusick 				for (p = (char *) right(cp); *p; p++) {
3616669Smckusick 					if (*p != HAT) {
3626669Smckusick 						if (isyms[*p] != 1) {
3636669Smckusick 							isyms[*p] = 1;
3646669Smckusick 							ssyms[ssmax++] = *p;
3656669Smckusick 						}
3666669Smckusick 					}
3676669Smckusick 				}
3686669Smckusick 				break;
3696669Smckusick 			case NCCL:
3706669Smckusick 				for (k=1; k<NCHARS; k++) {
3716669Smckusick 					if (k != HAT && !member(k, (char *) right(cp))) {
3726669Smckusick 						if (isyms[k] != 1) {
3736669Smckusick 							isyms[k] = 1;
3746669Smckusick 							ssyms[ssmax++] = k;
3756669Smckusick 						}
3766669Smckusick 					}
3776669Smckusick 				}
3786669Smckusick 		}
3796669Smckusick 	}
3806669Smckusick 	ssinit = ssmax;
3816669Smckusick 	n = 0;
3826669Smckusick 	for (s=0; s<=n; s++)  {
3836669Smckusick 	dprintf("s = %d\n", s, NULL, NULL);
3846669Smckusick 		ind = 0;
3856669Smckusick 		numtrans = 0;
3866669Smckusick 		finflg = 0;
3876669Smckusick 		if (*(state[s] + *state[s]) == line) {		/* s final? */
3886669Smckusick 			finflg = 1;
3896669Smckusick 			goto tenter;
3906669Smckusick 		}
3916669Smckusick 		spmax = spinit;
3926669Smckusick 		ssmax = ssinit;
3936669Smckusick 		ptr = state[s];
3946669Smckusick 		num = *ptr;
3956669Smckusick 		for (i=0; i<num; i++) {
3966669Smckusick 			curpos = *(++ptr);
3976669Smckusick 			if (iposns[curpos] != 1 && index[curpos] != 1) {
3986669Smckusick 				index[curpos] = 1;
3996669Smckusick 				sposns[spmax++] = curpos;
4006669Smckusick 			}
4016669Smckusick 			cp = point[curpos];
4026669Smckusick 			switch (type(cp)) {
4036669Smckusick 				case CHAR:
4046669Smckusick 					k = (int) right(cp);
4056669Smckusick 					if (isyms[k] == 0 && symbol[k] == 0) {
4066669Smckusick 						symbol[k] = 1;
4076669Smckusick 						ssyms[ssmax++] = k;
4086669Smckusick 					}
4096669Smckusick 					break;
4106669Smckusick 				case DOT:
4116669Smckusick 					for (k=1; k<NCHARS; k++) {
4126669Smckusick 						if (k != HAT) {
4136669Smckusick 							if (isyms[k] == 0 && symbol[k] == 0) {
4146669Smckusick 								symbol[k] = 1;
4156669Smckusick 								ssyms[ssmax++] = k;
4166669Smckusick 							}
4176669Smckusick 						}
4186669Smckusick 					}
4196669Smckusick 					break;
4206669Smckusick 				case CCL:
4216669Smckusick 					for (p = (char *) right(cp); *p; p++) {
4226669Smckusick 						if (*p != HAT) {
4236669Smckusick 							if (isyms[*p] == 0 && symbol[*p] == 0) {
4246669Smckusick 								symbol[*p] = 1;
4256669Smckusick 								ssyms[ssmax++] = *p;
4266669Smckusick 							}
4276669Smckusick 						}
4286669Smckusick 					}
4296669Smckusick 					break;
4306669Smckusick 				case NCCL:
4316669Smckusick 					for (k=1; k<NCHARS; k++) {
4326669Smckusick 						if (k != HAT && !member(k, (char *) right(cp))) {
4336669Smckusick 							if (isyms[k] == 0 && symbol[k] == 0) {
4346669Smckusick 								symbol[k] = 1;
4356669Smckusick 								ssyms[ssmax++] = k;
4366669Smckusick 							}
4376669Smckusick 						}
4386669Smckusick 					}
4396669Smckusick 			}
4406669Smckusick 		}
4416669Smckusick 		for (j=0; j<ssmax; j++) {	/* nextstate(s, ssyms[j]) */
4426669Smckusick 			c = ssyms[j];
4436669Smckusick 			symbol[c] = 0;
4446669Smckusick 			setcnt = 0;
4456669Smckusick 			for (k=0; k<=line; k++) setvec[k] = 0;
4466669Smckusick 			for (i=0; i<spmax; i++) {
4476669Smckusick 				index[sposns[i]] = 0;
4486669Smckusick 				cp = point[sposns[i]];
4496669Smckusick 				if ((k = type(cp)) != FINAL)
4506669Smckusick 					if (k == CHAR && c == (int) right(cp)
4516669Smckusick 					 || k == DOT
4526669Smckusick 					 || k == CCL && member(c, (char *) right(cp))
4536669Smckusick 					 || k == NCCL && !member(c, (char *) right(cp))) {
4546669Smckusick 						ptr = foll[sposns[i]];
4556669Smckusick 						num = *ptr;
4566669Smckusick 						for (k=0; k<num; k++) {
4576669Smckusick 							if (setvec[*(++ptr)] != 1
4586669Smckusick 								&& iposns[*ptr] != 1) {
4596669Smckusick 								setvec[*ptr] = 1;
4606669Smckusick 								setcnt++;
4616669Smckusick 							}
4626669Smckusick 						}
4636669Smckusick 					}
4646669Smckusick 			} /* end nextstate */
4656669Smckusick 			if (notin(state, n, &prev)) {
4666669Smckusick 				if (n >= NSTATES) {
4676669Smckusick 					dprintf("cgotofn: notin; state = %d, n = %d\n", state, n, NULL);
4686669Smckusick 					overflo();
4696669Smckusick 				}
4706669Smckusick 				state[++n] = add(setcnt);
4716669Smckusick 				dprintf("	delta(%d,%o) = %d", s,c,n);
4726669Smckusick 				dprintf(", ind = %d\n", ind+1, NULL, NULL);
4736669Smckusick 				fatab[++ind] = c;
4746669Smckusick 				fatab[++ind] = n;
4756669Smckusick 				numtrans++;
4766669Smckusick 			}
4776669Smckusick 			else {
4786669Smckusick 				if (prev != 0) {
4796669Smckusick 					dprintf("	delta(%d,%o) = %d", s,c,prev);
4806669Smckusick 					dprintf(", ind = %d\n", ind+1, NULL, NULL);
4816669Smckusick 					fatab[++ind] = c;
4826669Smckusick 					fatab[++ind] = prev;
4836669Smckusick 					numtrans++;
4846669Smckusick 				}
4856669Smckusick 			}
4866669Smckusick 		}
4876669Smckusick 	tenter:
4886669Smckusick 		if ((pfa = (struct fa *) malloc((numtrans + 1) * sizeof(struct fa))) == NULL)
4896669Smckusick 			overflo();
4906669Smckusick 		where[s] = pfa;
4916669Smckusick 		if (finflg)
4926669Smckusick 			pfa->cch = -1;		/* s is a final state */
4936669Smckusick 		else
4946669Smckusick 			pfa->cch = numtrans;
4956669Smckusick 		pfa->st = 0;
4966669Smckusick 		for (i=1, pfa += 1; i<=numtrans; i++, pfa++) {
4976669Smckusick 			pfa->cch = fatab[2*i-1];
4986669Smckusick 			pfa->st = (struct fa *) fatab[2*i];
4996669Smckusick 		}
5006669Smckusick 	}
5016669Smckusick 	for (i=0; i<=n; i++) {
50229543Smckusick 		/* N.b. state[0] == foll[0], not separately allocated */
50329543Smckusick 		if (i>0)
50429543Smckusick 			xfree(state[i]);       /* free state[i] */
5056669Smckusick 		pfa = where[i];
5066669Smckusick 		pfa->st = where[0];
5076669Smckusick 		dprintf("state %d: (%o)\n", i, pfa, NULL);
5086669Smckusick 		dprintf("	numtrans = %d,	default = %o\n", pfa->cch, pfa->st, NULL);
5096669Smckusick 		for (k=1; k<=pfa->cch; k++) {
5106669Smckusick 			(pfa+k)->st = where[ (int) (pfa+k)->st];
5116669Smckusick 			dprintf("	char = %o,	nextstate = %o\n",(pfa+k)->cch, (pfa+k)->st, NULL);
5126669Smckusick 		}
5136669Smckusick 	}
5146669Smckusick 	pfa = where[0];
5156669Smckusick 	if ((num = pfa->cch) < 0)
5166669Smckusick 		return(where[0]);
5176669Smckusick 	for (pfa += num; num; num--, pfa--)
5186669Smckusick 		if (pfa->cch == HAT) {
5196669Smckusick 			return(pfa->st);
5206669Smckusick 		}
5216669Smckusick 	return(where[0]);
5226669Smckusick }
5236669Smckusick 
match(pfa,p)5246669Smckusick match(pfa, p)
5256669Smckusick register struct fa *pfa;
5266669Smckusick register char *p;
5276669Smckusick {
5286669Smckusick 	register count;
5296669Smckusick 	char c;
5306669Smckusick 	if (p == 0) return(0);
5316669Smckusick 	if (pfa->cch == 1) {		/* fast test for first character, if possible */
5326669Smckusick 		c = (++pfa)->cch;
5336669Smckusick 		do
5346669Smckusick 			if (c == *p) {
5356669Smckusick 				p++;
5366669Smckusick 				pfa = pfa->st;
5376669Smckusick 				goto adv;
5386669Smckusick 			}
5396669Smckusick 		while (*p++ != 0);
5406669Smckusick 		return(0);
5416669Smckusick 	}
5426669Smckusick    adv: if ((count = pfa->cch) < 0) return(1);
5436669Smckusick 	do {
5446669Smckusick 		for (pfa += count; count; count--, pfa--)
5456669Smckusick 			if (pfa->cch == *p) {
5466669Smckusick 				break;
5476669Smckusick 			}
5486669Smckusick 		pfa = pfa->st;
5496669Smckusick 		if ((count = pfa->cch) < 0) return(1);
5506669Smckusick 	} while(*p++ != 0);
5516669Smckusick 	return(0);
5526669Smckusick }
55329543Smckusick 
55429543Smckusick /*
55529543Smckusick  * Free foll[i], taking into account identical foll[] entries.
55629543Smckusick  * This is necessary because cfoll() uses the same physical follow set for
55729543Smckusick  * several foll[] entries when the set is identical.  Called by freetr().
55829543Smckusick  */
foll_free(i)55929543Smckusick foll_free(i)
56029543Smckusick int i;
56129543Smckusick {
56229543Smckusick 	register int j;
56329543Smckusick 	int *p = foll[i];
56429543Smckusick 	if (p==NULL) return;
56529543Smckusick 	for (j=0; j<=maxfoll; j++)
56629543Smckusick 		if (foll[j]==p) foll[j]=NULL;
56729543Smckusick 	xfree(p);
56829543Smckusick }
569