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