xref: /original-bsd/old/awk/b.c (revision 894d3702)
1*894d3702Sbostic /*-
2*894d3702Sbostic  * Copyright (c) 1991 The Regents of the University of California.
3*894d3702Sbostic  * All rights reserved.
4*894d3702Sbostic  *
5*894d3702Sbostic  * %sccs.include.proprietary.c%
6*894d3702Sbostic  */
7*894d3702Sbostic 
8ba723b2cSsam #ifndef lint
9*894d3702Sbostic static char sccsid[] = "@(#)b.c	4.4 (Berkeley) 04/17/91";
10*894d3702Sbostic #endif /* not lint */
11e78391dbSmckusick 
12e78391dbSmckusick #include "awk.def"
13e78391dbSmckusick #include "stdio.h"
14e78391dbSmckusick #include "awk.h"
15e78391dbSmckusick 
16e78391dbSmckusick extern node *op2();
17e78391dbSmckusick extern struct fa *cgotofn();
18e78391dbSmckusick #define MAXLIN 256
19e78391dbSmckusick #define NCHARS 128
20e78391dbSmckusick #define NSTATES 256
21e78391dbSmckusick 
22e78391dbSmckusick #define type(v)	v->nobj
23e78391dbSmckusick #define left(v)	v->narg[0]
24e78391dbSmckusick #define right(v)	v->narg[1]
25e78391dbSmckusick #define parent(v)	v->nnext
26e78391dbSmckusick 
27e78391dbSmckusick #define LEAF	case CCL: case NCCL: case CHAR: case DOT:
28e78391dbSmckusick #define UNARY	case FINAL: case STAR: case PLUS: case QUEST:
29e78391dbSmckusick 
30e78391dbSmckusick /* encoding in tree nodes:
31e78391dbSmckusick 	leaf (CCL, NCCL, CHAR, DOT): left is index, right contains value or pointer to value
32e78391dbSmckusick 	unary (FINAL, STAR, PLUS, QUEST): left is child, right is null
33e78391dbSmckusick 	binary (CAT, OR): left and right are children
34e78391dbSmckusick 	parent contains pointer to parent
35e78391dbSmckusick */
36e78391dbSmckusick 
37e78391dbSmckusick struct fa {
38e78391dbSmckusick 	int cch;
39e78391dbSmckusick 	struct fa *st;
40e78391dbSmckusick };
41e78391dbSmckusick 
42e78391dbSmckusick int	*state[NSTATES];
43e78391dbSmckusick int	*foll[MAXLIN];
44e78391dbSmckusick char	chars[MAXLIN];
45e78391dbSmckusick int	setvec[MAXLIN];
46e78391dbSmckusick node	*point[MAXLIN];
47e78391dbSmckusick 
48e78391dbSmckusick int	setcnt;
49e78391dbSmckusick int	line;
5027759187Smckusick int	maxfoll;  /* index of highest foll[] entry set by cfoll() */
51e78391dbSmckusick 
52e78391dbSmckusick 
makedfa(p)53e78391dbSmckusick struct fa *makedfa(p)	/* returns dfa for tree pointed to by p */
54e78391dbSmckusick node *p;
55e78391dbSmckusick {
56e78391dbSmckusick 	node *p1;
57e78391dbSmckusick 	struct fa *fap;
58e78391dbSmckusick 	p1 = op2(CAT, op2(STAR, op2(DOT, (node *) 0, (node *) 0), (node *) 0), p);
59e78391dbSmckusick 		/* put DOT STAR in front of reg. exp. */
60e78391dbSmckusick 	p1 = op2(FINAL, p1, (node *) 0);		/* install FINAL node */
61e78391dbSmckusick 
62e78391dbSmckusick 	line = 0;
63e78391dbSmckusick 	penter(p1);	/* enter parent pointers and leaf indices */
64e78391dbSmckusick 	point[line] = p1;	/* FINAL node */
65e78391dbSmckusick 	setvec[0] = 1;		/* for initial DOT STAR */
66e78391dbSmckusick 	cfoll(p1);	/* set up follow sets */
67e78391dbSmckusick 	fap = cgotofn();
68e78391dbSmckusick 	freetr(p1);	/* add this when alloc works */
69e78391dbSmckusick 	return(fap);
70e78391dbSmckusick }
71e78391dbSmckusick 
penter(p)72e78391dbSmckusick penter(p)	/* set up parent pointers and leaf indices */
73e78391dbSmckusick node *p;
74e78391dbSmckusick {
75e78391dbSmckusick 	switch(type(p)) {
76e78391dbSmckusick 		LEAF
77e78391dbSmckusick 			left(p) = (node *) line;
78e78391dbSmckusick 			point[line++] = p;
79e78391dbSmckusick 			break;
80e78391dbSmckusick 		UNARY
81e78391dbSmckusick 			penter(left(p));
82e78391dbSmckusick 			parent(left(p)) = p;
83e78391dbSmckusick 			break;
84e78391dbSmckusick 		case CAT:
85e78391dbSmckusick 		case OR:
86e78391dbSmckusick 			penter(left(p));
87e78391dbSmckusick 			penter(right(p));
88e78391dbSmckusick 			parent(left(p)) = p;
89e78391dbSmckusick 			parent(right(p)) = p;
90e78391dbSmckusick 			break;
91e78391dbSmckusick 		default:
92e78391dbSmckusick 			error(FATAL, "unknown type %d in penter\n", type(p));
93e78391dbSmckusick 			break;
94e78391dbSmckusick 	}
95e78391dbSmckusick }
96e78391dbSmckusick 
freetr(p)97e78391dbSmckusick freetr(p)	/* free parse tree and follow sets */
98e78391dbSmckusick node *p;
99e78391dbSmckusick {
100e78391dbSmckusick 	switch(type(p)) {
101e78391dbSmckusick 		LEAF
10227759187Smckusick 			foll_free((int) left(p));
103e78391dbSmckusick 			xfree(p);
104e78391dbSmckusick 			break;
105e78391dbSmckusick 		UNARY
106e78391dbSmckusick 			freetr(left(p));
107e78391dbSmckusick 			xfree(p);
108e78391dbSmckusick 			break;
109e78391dbSmckusick 		case CAT:
110e78391dbSmckusick 		case OR:
111e78391dbSmckusick 			freetr(left(p));
112e78391dbSmckusick 			freetr(right(p));
113e78391dbSmckusick 			xfree(p);
114e78391dbSmckusick 			break;
115e78391dbSmckusick 		default:
116e78391dbSmckusick 			error(FATAL, "unknown type %d in freetr", type(p));
117e78391dbSmckusick 			break;
118e78391dbSmckusick 	}
119e78391dbSmckusick }
cclenter(p)120e78391dbSmckusick char *cclenter(p)
121e78391dbSmckusick register char *p;
122e78391dbSmckusick {
123e78391dbSmckusick 	register i, c;
124e78391dbSmckusick 	char *op;
125e78391dbSmckusick 
126e78391dbSmckusick 	op = p;
127e78391dbSmckusick 	i = 0;
128e78391dbSmckusick 	while ((c = *p++) != 0) {
129e78391dbSmckusick 		if (c == '-' && i > 0 && chars[i-1] != 0) {
130e78391dbSmckusick 			if (*p != 0) {
131e78391dbSmckusick 				c = chars[i-1];
132e78391dbSmckusick 				while (c < *p) {
133e78391dbSmckusick 					if (i >= MAXLIN)
134e78391dbSmckusick 						overflo();
135e78391dbSmckusick 					chars[i++] = ++c;
136e78391dbSmckusick 				}
137e78391dbSmckusick 				p++;
138e78391dbSmckusick 				continue;
139e78391dbSmckusick 			}
140e78391dbSmckusick 		}
141e78391dbSmckusick 		if (i >= MAXLIN)
142e78391dbSmckusick 			overflo();
143e78391dbSmckusick 		chars[i++] = c;
144e78391dbSmckusick 	}
145e78391dbSmckusick 	chars[i++] = '\0';
146e78391dbSmckusick 	dprintf("cclenter: in = |%s|, out = |%s|\n", op, chars, NULL);
147e78391dbSmckusick 	xfree(op);
148e78391dbSmckusick 	return(tostring(chars));
149e78391dbSmckusick }
150e78391dbSmckusick 
overflo()151e78391dbSmckusick overflo()
152e78391dbSmckusick {
153e78391dbSmckusick 	error(FATAL, "regular expression too long\n");
154e78391dbSmckusick }
155e78391dbSmckusick 
cfoll(v)156e78391dbSmckusick cfoll(v)		/* enter follow set of each leaf of vertex v into foll[leaf] */
157e78391dbSmckusick register node *v;
158e78391dbSmckusick {
159e78391dbSmckusick 	register i;
160e78391dbSmckusick 	int prev;
161e78391dbSmckusick 	int *add();
162e78391dbSmckusick 
16327759187Smckusick 	maxfoll = -1;
164e78391dbSmckusick 	switch(type(v)) {
165e78391dbSmckusick 		LEAF
166e78391dbSmckusick 			setcnt = 0;
167e78391dbSmckusick 			for (i=1; i<=line; i++)
168e78391dbSmckusick 				setvec[i] = 0;
169e78391dbSmckusick 			follow(v);
170e78391dbSmckusick 			if (notin(foll, ( (int) left(v))-1, &prev)) {
171e78391dbSmckusick 				foll[(int) left(v)] = add(setcnt);
172e78391dbSmckusick 			}
173e78391dbSmckusick 			else
174e78391dbSmckusick 				foll[ (int) left(v)] = foll[prev];
17527759187Smckusick 			if ((int)left(v) > maxfoll)
17627759187Smckusick 				maxfoll = (int)left(v);
177e78391dbSmckusick 			break;
178e78391dbSmckusick 		UNARY
179e78391dbSmckusick 			cfoll(left(v));
180e78391dbSmckusick 			break;
181e78391dbSmckusick 		case CAT:
182e78391dbSmckusick 		case OR:
183e78391dbSmckusick 			cfoll(left(v));
184e78391dbSmckusick 			cfoll(right(v));
185e78391dbSmckusick 			break;
186e78391dbSmckusick 		default:
187e78391dbSmckusick 			error(FATAL, "unknown type %d in cfoll", type(v));
188e78391dbSmckusick 	}
189e78391dbSmckusick }
190e78391dbSmckusick 
first(p)191e78391dbSmckusick first(p)			/* collects initially active leaves of p into setvec */
192e78391dbSmckusick register node *p;		/* returns 0 or 1 depending on whether p matches empty string */
193e78391dbSmckusick {
194e78391dbSmckusick 	register b;
195e78391dbSmckusick 
196e78391dbSmckusick 	switch(type(p)) {
197e78391dbSmckusick 		LEAF
198e78391dbSmckusick 			if (setvec[(int) left(p)] != 1) {
199e78391dbSmckusick 				setvec[(int) left(p)] = 1;
200e78391dbSmckusick 				setcnt++;
201e78391dbSmckusick 			}
202e78391dbSmckusick 			if (type(p) == CCL && (*(char *) right(p)) == '\0')
203e78391dbSmckusick 				return(0);		/* empty CCL */
204e78391dbSmckusick 			else return(1);
205e78391dbSmckusick 		case FINAL:
206e78391dbSmckusick 		case PLUS:
207e78391dbSmckusick 			if (first(left(p)) == 0) return(0);
208e78391dbSmckusick 			return(1);
209e78391dbSmckusick 		case STAR:
210e78391dbSmckusick 		case QUEST:
211e78391dbSmckusick 			first(left(p));
212e78391dbSmckusick 			return(0);
213e78391dbSmckusick 		case CAT:
214e78391dbSmckusick 			if (first(left(p)) == 0 && first(right(p)) == 0) return(0);
215e78391dbSmckusick 			return(1);
216e78391dbSmckusick 		case OR:
217e78391dbSmckusick 			b = first(right(p));
218e78391dbSmckusick 			if (first(left(p)) == 0 || b == 0) return(0);
219e78391dbSmckusick 			return(1);
220e78391dbSmckusick 	}
221e78391dbSmckusick 	error(FATAL, "unknown type %d in first\n", type(p));
222e78391dbSmckusick 	return(-1);
223e78391dbSmckusick }
224e78391dbSmckusick 
follow(v)225e78391dbSmckusick follow(v)
226e78391dbSmckusick node *v;		/* collects leaves that can follow v into setvec */
227e78391dbSmckusick {
228e78391dbSmckusick 	node *p;
229e78391dbSmckusick 
230e78391dbSmckusick 	if (type(v) == FINAL)
231e78391dbSmckusick 		return;
232e78391dbSmckusick 	p = parent(v);
233e78391dbSmckusick 	switch (type(p)) {
234e78391dbSmckusick 		case STAR:
235e78391dbSmckusick 		case PLUS:	first(v);
236e78391dbSmckusick 				follow(p);
237e78391dbSmckusick 				return;
238e78391dbSmckusick 
239e78391dbSmckusick 		case OR:
240e78391dbSmckusick 		case QUEST:	follow(p);
241e78391dbSmckusick 				return;
242e78391dbSmckusick 
243e78391dbSmckusick 		case CAT:	if (v == left(p)) {	/* v is left child of p */
244e78391dbSmckusick 					if (first(right(p)) == 0) {
245e78391dbSmckusick 						follow(p);
246e78391dbSmckusick 						return;
247e78391dbSmckusick 					}
248e78391dbSmckusick 				}
249e78391dbSmckusick 				else		/* v is right child */
250e78391dbSmckusick 					follow(p);
251e78391dbSmckusick 				return;
252e78391dbSmckusick 		case FINAL:	if (setvec[line] != 1) {
253e78391dbSmckusick 					setvec[line] = 1;
254e78391dbSmckusick 					setcnt++;
255e78391dbSmckusick 				}
256e78391dbSmckusick 				return;
257e78391dbSmckusick 	}
258e78391dbSmckusick }
259e78391dbSmckusick 
member(c,s)260e78391dbSmckusick member(c, s)	/* is c in s? */
261e78391dbSmckusick register char c, *s;
262e78391dbSmckusick {
263e78391dbSmckusick 	while (*s)
264e78391dbSmckusick 		if (c == *s++)
265e78391dbSmckusick 			return(1);
266e78391dbSmckusick 	return(0);
267e78391dbSmckusick }
268e78391dbSmckusick 
notin(array,n,prev)269e78391dbSmckusick notin(array, n, prev)		/* is setvec in array[0] thru array[n]? */
270e78391dbSmckusick int **array;
271e78391dbSmckusick int *prev; {
272e78391dbSmckusick 	register i, j;
273e78391dbSmckusick 	int *ptr;
274e78391dbSmckusick 	for (i=0; i<=n; i++) {
275e78391dbSmckusick 		ptr = array[i];
276e78391dbSmckusick 		if (*ptr == setcnt) {
277e78391dbSmckusick 			for (j=0; j < setcnt; j++)
278e78391dbSmckusick 				if (setvec[*(++ptr)] != 1) goto nxt;
279e78391dbSmckusick 			*prev = i;
280e78391dbSmckusick 			return(0);
281e78391dbSmckusick 		}
282e78391dbSmckusick 		nxt: ;
283e78391dbSmckusick 	}
284e78391dbSmckusick 	return(1);
285e78391dbSmckusick }
286e78391dbSmckusick 
add(n)287e78391dbSmckusick int *add(n) {		/* remember setvec */
288e78391dbSmckusick 	int *ptr, *p;
289e78391dbSmckusick 	register i;
290e78391dbSmckusick 	if ((p = ptr = (int *) malloc((n+1)*sizeof(int))) == NULL)
291e78391dbSmckusick 		overflo();
292e78391dbSmckusick 	*ptr = n;
293e78391dbSmckusick 	dprintf("add(%d)\n", n, NULL, NULL);
294e78391dbSmckusick 	for (i=1; i <= line; i++)
295e78391dbSmckusick 		if (setvec[i] == 1) {
296e78391dbSmckusick 			*(++ptr) = i;
297e78391dbSmckusick 			dprintf("  ptr = %o, *ptr = %d, i = %d\n", ptr, *ptr, i);
298e78391dbSmckusick 		}
299e78391dbSmckusick 	dprintf("\n", NULL, NULL, NULL);
300e78391dbSmckusick 	return(p);
301e78391dbSmckusick }
302e78391dbSmckusick 
cgotofn()303e78391dbSmckusick struct fa *cgotofn()
304e78391dbSmckusick {
305e78391dbSmckusick 	register i, k;
306e78391dbSmckusick 	register int *ptr;
307e78391dbSmckusick 	char c;
308e78391dbSmckusick 	char *p;
309e78391dbSmckusick 	node *cp;
310e78391dbSmckusick 	int j, n, s, ind, numtrans;
311e78391dbSmckusick 	int finflg;
312e78391dbSmckusick 	int curpos, num, prev;
313e78391dbSmckusick 	struct fa *where[NSTATES];
314e78391dbSmckusick 
315e78391dbSmckusick 	int fatab[257];
316e78391dbSmckusick 	struct fa *pfa;
317e78391dbSmckusick 
318e78391dbSmckusick 	char index[MAXLIN];
319e78391dbSmckusick 	char iposns[MAXLIN];
320e78391dbSmckusick 	int sposns[MAXLIN];
321e78391dbSmckusick 	int spmax, spinit;
322e78391dbSmckusick 
323e78391dbSmckusick 	char symbol[NCHARS];
324e78391dbSmckusick 	char isyms[NCHARS];
325e78391dbSmckusick 	char ssyms[NCHARS];
326e78391dbSmckusick 	int ssmax, ssinit;
327e78391dbSmckusick 
328e78391dbSmckusick 	for (i=0; i<=line; i++) index[i] = iposns[i] = setvec[i] = 0;
329e78391dbSmckusick 	for (i=0; i<NCHARS; i++)  isyms[i] = symbol[i] = 0;
330e78391dbSmckusick 	setcnt = 0;
331e78391dbSmckusick 	/* compute initial positions and symbols of state 0 */
332e78391dbSmckusick 	ssmax = 0;
333e78391dbSmckusick 	ptr = state[0] = foll[0];
334e78391dbSmckusick 	spinit = *ptr;
335e78391dbSmckusick 	for (i=0; i<spinit; i++) {
336e78391dbSmckusick 		curpos = *(++ptr);
337e78391dbSmckusick 		sposns[i] = curpos;
338e78391dbSmckusick 		iposns[curpos] = 1;
339e78391dbSmckusick 		cp = point[curpos];
340e78391dbSmckusick 		dprintf("i = %d, spinit = %d, curpos = %d\n", i, spinit, curpos);
341e78391dbSmckusick 		switch (type(cp)) {
342e78391dbSmckusick 			case CHAR:
343e78391dbSmckusick 				k = (int) right(cp);
344e78391dbSmckusick 				if (isyms[k] != 1) {
345e78391dbSmckusick 					isyms[k] = 1;
346e78391dbSmckusick 					ssyms[ssmax++] = k;
347e78391dbSmckusick 				}
348e78391dbSmckusick 				break;
349e78391dbSmckusick 			case DOT:
350e78391dbSmckusick 				for (k=1; k<NCHARS; k++) {
351e78391dbSmckusick 					if (k != HAT) {
352e78391dbSmckusick 						if (isyms[k] != 1) {
353e78391dbSmckusick 							isyms[k] = 1;
354e78391dbSmckusick 							ssyms[ssmax++] = k;
355e78391dbSmckusick 						}
356e78391dbSmckusick 					}
357e78391dbSmckusick 				}
358e78391dbSmckusick 				break;
359e78391dbSmckusick 			case CCL:
360e78391dbSmckusick 				for (p = (char *) right(cp); *p; p++) {
361e78391dbSmckusick 					if (*p != HAT) {
362e78391dbSmckusick 						if (isyms[*p] != 1) {
363e78391dbSmckusick 							isyms[*p] = 1;
364e78391dbSmckusick 							ssyms[ssmax++] = *p;
365e78391dbSmckusick 						}
366e78391dbSmckusick 					}
367e78391dbSmckusick 				}
368e78391dbSmckusick 				break;
369e78391dbSmckusick 			case NCCL:
370e78391dbSmckusick 				for (k=1; k<NCHARS; k++) {
371e78391dbSmckusick 					if (k != HAT && !member(k, (char *) right(cp))) {
372e78391dbSmckusick 						if (isyms[k] != 1) {
373e78391dbSmckusick 							isyms[k] = 1;
374e78391dbSmckusick 							ssyms[ssmax++] = k;
375e78391dbSmckusick 						}
376e78391dbSmckusick 					}
377e78391dbSmckusick 				}
378e78391dbSmckusick 		}
379e78391dbSmckusick 	}
380e78391dbSmckusick 	ssinit = ssmax;
381e78391dbSmckusick 	n = 0;
382e78391dbSmckusick 	for (s=0; s<=n; s++)  {
383e78391dbSmckusick 	dprintf("s = %d\n", s, NULL, NULL);
384e78391dbSmckusick 		ind = 0;
385e78391dbSmckusick 		numtrans = 0;
386e78391dbSmckusick 		finflg = 0;
387e78391dbSmckusick 		if (*(state[s] + *state[s]) == line) {		/* s final? */
388e78391dbSmckusick 			finflg = 1;
389e78391dbSmckusick 			goto tenter;
390e78391dbSmckusick 		}
391e78391dbSmckusick 		spmax = spinit;
392e78391dbSmckusick 		ssmax = ssinit;
393e78391dbSmckusick 		ptr = state[s];
394e78391dbSmckusick 		num = *ptr;
395e78391dbSmckusick 		for (i=0; i<num; i++) {
396e78391dbSmckusick 			curpos = *(++ptr);
397e78391dbSmckusick 			if (iposns[curpos] != 1 && index[curpos] != 1) {
398e78391dbSmckusick 				index[curpos] = 1;
399e78391dbSmckusick 				sposns[spmax++] = curpos;
400e78391dbSmckusick 			}
401e78391dbSmckusick 			cp = point[curpos];
402e78391dbSmckusick 			switch (type(cp)) {
403e78391dbSmckusick 				case CHAR:
404e78391dbSmckusick 					k = (int) right(cp);
405e78391dbSmckusick 					if (isyms[k] == 0 && symbol[k] == 0) {
406e78391dbSmckusick 						symbol[k] = 1;
407e78391dbSmckusick 						ssyms[ssmax++] = k;
408e78391dbSmckusick 					}
409e78391dbSmckusick 					break;
410e78391dbSmckusick 				case DOT:
411e78391dbSmckusick 					for (k=1; k<NCHARS; k++) {
412e78391dbSmckusick 						if (k != HAT) {
413e78391dbSmckusick 							if (isyms[k] == 0 && symbol[k] == 0) {
414e78391dbSmckusick 								symbol[k] = 1;
415e78391dbSmckusick 								ssyms[ssmax++] = k;
416e78391dbSmckusick 							}
417e78391dbSmckusick 						}
418e78391dbSmckusick 					}
419e78391dbSmckusick 					break;
420e78391dbSmckusick 				case CCL:
421e78391dbSmckusick 					for (p = (char *) right(cp); *p; p++) {
422e78391dbSmckusick 						if (*p != HAT) {
423e78391dbSmckusick 							if (isyms[*p] == 0 && symbol[*p] == 0) {
424e78391dbSmckusick 								symbol[*p] = 1;
425e78391dbSmckusick 								ssyms[ssmax++] = *p;
426e78391dbSmckusick 							}
427e78391dbSmckusick 						}
428e78391dbSmckusick 					}
429e78391dbSmckusick 					break;
430e78391dbSmckusick 				case NCCL:
431e78391dbSmckusick 					for (k=1; k<NCHARS; k++) {
432e78391dbSmckusick 						if (k != HAT && !member(k, (char *) right(cp))) {
433e78391dbSmckusick 							if (isyms[k] == 0 && symbol[k] == 0) {
434e78391dbSmckusick 								symbol[k] = 1;
435e78391dbSmckusick 								ssyms[ssmax++] = k;
436e78391dbSmckusick 							}
437e78391dbSmckusick 						}
438e78391dbSmckusick 					}
439e78391dbSmckusick 			}
440e78391dbSmckusick 		}
441e78391dbSmckusick 		for (j=0; j<ssmax; j++) {	/* nextstate(s, ssyms[j]) */
442e78391dbSmckusick 			c = ssyms[j];
443e78391dbSmckusick 			symbol[c] = 0;
444e78391dbSmckusick 			setcnt = 0;
445e78391dbSmckusick 			for (k=0; k<=line; k++) setvec[k] = 0;
446e78391dbSmckusick 			for (i=0; i<spmax; i++) {
447e78391dbSmckusick 				index[sposns[i]] = 0;
448e78391dbSmckusick 				cp = point[sposns[i]];
449e78391dbSmckusick 				if ((k = type(cp)) != FINAL)
450e78391dbSmckusick 					if (k == CHAR && c == (int) right(cp)
451e78391dbSmckusick 					 || k == DOT
452e78391dbSmckusick 					 || k == CCL && member(c, (char *) right(cp))
453e78391dbSmckusick 					 || k == NCCL && !member(c, (char *) right(cp))) {
454e78391dbSmckusick 						ptr = foll[sposns[i]];
455e78391dbSmckusick 						num = *ptr;
456e78391dbSmckusick 						for (k=0; k<num; k++) {
457e78391dbSmckusick 							if (setvec[*(++ptr)] != 1
458e78391dbSmckusick 								&& iposns[*ptr] != 1) {
459e78391dbSmckusick 								setvec[*ptr] = 1;
460e78391dbSmckusick 								setcnt++;
461e78391dbSmckusick 							}
462e78391dbSmckusick 						}
463e78391dbSmckusick 					}
464e78391dbSmckusick 			} /* end nextstate */
465e78391dbSmckusick 			if (notin(state, n, &prev)) {
466e78391dbSmckusick 				if (n >= NSTATES) {
467e78391dbSmckusick 					dprintf("cgotofn: notin; state = %d, n = %d\n", state, n, NULL);
468e78391dbSmckusick 					overflo();
469e78391dbSmckusick 				}
470e78391dbSmckusick 				state[++n] = add(setcnt);
471e78391dbSmckusick 				dprintf("	delta(%d,%o) = %d", s,c,n);
472e78391dbSmckusick 				dprintf(", ind = %d\n", ind+1, NULL, NULL);
473e78391dbSmckusick 				fatab[++ind] = c;
474e78391dbSmckusick 				fatab[++ind] = n;
475e78391dbSmckusick 				numtrans++;
476e78391dbSmckusick 			}
477e78391dbSmckusick 			else {
478e78391dbSmckusick 				if (prev != 0) {
479e78391dbSmckusick 					dprintf("	delta(%d,%o) = %d", s,c,prev);
480e78391dbSmckusick 					dprintf(", ind = %d\n", ind+1, NULL, NULL);
481e78391dbSmckusick 					fatab[++ind] = c;
482e78391dbSmckusick 					fatab[++ind] = prev;
483e78391dbSmckusick 					numtrans++;
484e78391dbSmckusick 				}
485e78391dbSmckusick 			}
486e78391dbSmckusick 		}
487e78391dbSmckusick 	tenter:
488e78391dbSmckusick 		if ((pfa = (struct fa *) malloc((numtrans + 1) * sizeof(struct fa))) == NULL)
489e78391dbSmckusick 			overflo();
490e78391dbSmckusick 		where[s] = pfa;
491e78391dbSmckusick 		if (finflg)
492e78391dbSmckusick 			pfa->cch = -1;		/* s is a final state */
493e78391dbSmckusick 		else
494e78391dbSmckusick 			pfa->cch = numtrans;
495e78391dbSmckusick 		pfa->st = 0;
496e78391dbSmckusick 		for (i=1, pfa += 1; i<=numtrans; i++, pfa++) {
497e78391dbSmckusick 			pfa->cch = fatab[2*i-1];
498e78391dbSmckusick 			pfa->st = (struct fa *) fatab[2*i];
499e78391dbSmckusick 		}
500e78391dbSmckusick 	}
501e78391dbSmckusick 	for (i=0; i<=n; i++) {
50227759187Smckusick 		/* N.b. state[0] == foll[0], not separately allocated */
50327759187Smckusick 		if (i>0)
504e78391dbSmckusick 			xfree(state[i]);       /* free state[i] */
505e78391dbSmckusick 		pfa = where[i];
506e78391dbSmckusick 		pfa->st = where[0];
507e78391dbSmckusick 		dprintf("state %d: (%o)\n", i, pfa, NULL);
508e78391dbSmckusick 		dprintf("	numtrans = %d,	default = %o\n", pfa->cch, pfa->st, NULL);
509e78391dbSmckusick 		for (k=1; k<=pfa->cch; k++) {
510e78391dbSmckusick 			(pfa+k)->st = where[ (int) (pfa+k)->st];
511e78391dbSmckusick 			dprintf("	char = %o,	nextstate = %o\n",(pfa+k)->cch, (pfa+k)->st, NULL);
512e78391dbSmckusick 		}
513e78391dbSmckusick 	}
514e78391dbSmckusick 	pfa = where[0];
515e78391dbSmckusick 	if ((num = pfa->cch) < 0)
516e78391dbSmckusick 		return(where[0]);
517e78391dbSmckusick 	for (pfa += num; num; num--, pfa--)
518e78391dbSmckusick 		if (pfa->cch == HAT) {
519e78391dbSmckusick 			return(pfa->st);
520e78391dbSmckusick 		}
521e78391dbSmckusick 	return(where[0]);
522e78391dbSmckusick }
523e78391dbSmckusick 
match(pfa,p)524e78391dbSmckusick match(pfa, p)
525e78391dbSmckusick register struct fa *pfa;
526e78391dbSmckusick register char *p;
527e78391dbSmckusick {
528e78391dbSmckusick 	register count;
529e78391dbSmckusick 	char c;
530e78391dbSmckusick 	if (p == 0) return(0);
531e78391dbSmckusick 	if (pfa->cch == 1) {		/* fast test for first character, if possible */
532e78391dbSmckusick 		c = (++pfa)->cch;
533e78391dbSmckusick 		do
534e78391dbSmckusick 			if (c == *p) {
535e78391dbSmckusick 				p++;
536e78391dbSmckusick 				pfa = pfa->st;
537e78391dbSmckusick 				goto adv;
538e78391dbSmckusick 			}
539e78391dbSmckusick 		while (*p++ != 0);
540e78391dbSmckusick 		return(0);
541e78391dbSmckusick 	}
542e78391dbSmckusick    adv: if ((count = pfa->cch) < 0) return(1);
543e78391dbSmckusick 	do {
544e78391dbSmckusick 		for (pfa += count; count; count--, pfa--)
545e78391dbSmckusick 			if (pfa->cch == *p) {
546e78391dbSmckusick 				break;
547e78391dbSmckusick 			}
548e78391dbSmckusick 		pfa = pfa->st;
549e78391dbSmckusick 		if ((count = pfa->cch) < 0) return(1);
550e78391dbSmckusick 	} while(*p++ != 0);
551e78391dbSmckusick 	return(0);
552e78391dbSmckusick }
55327759187Smckusick 
55427759187Smckusick /*
55527759187Smckusick  * Free foll[i], taking into account identical foll[] entries.
55627759187Smckusick  * This is necessary because cfoll() uses the same physical follow set for
55727759187Smckusick  * several foll[] entries when the set is identical.  Called by freetr().
55827759187Smckusick  */
foll_free(i)55927759187Smckusick foll_free(i)
56027759187Smckusick int i;
56127759187Smckusick {
56227759187Smckusick 	register int j;
56327759187Smckusick 	int *p = foll[i];
56427759187Smckusick 	if (p==NULL) return;
56527759187Smckusick 	for (j=0; j<=maxfoll; j++)
56627759187Smckusick 		if (foll[j]==p) foll[j]=NULL;
56727759187Smckusick 	xfree(p);
56827759187Smckusick }
569