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