xref: /csrg-svn/old/lex/sub2.c (revision 33343)
114494Ssam #ifndef lint
2*33343Sbostic static char sccsid[] = "@(#)sub2.c	4.2 (Berkeley) 01/12/88";
314494Ssam #endif
414494Ssam 
514494Ssam # include "ldefs.c"
614494Ssam cfoll(v)
714494Ssam 	int v;
814494Ssam 	{
914494Ssam 	register int i,j,k;
1014494Ssam 	char *p;
1114494Ssam 	i = name[v];
1214494Ssam 	if(i < NCH) i = 1;	/* character */
1314494Ssam 	switch(i){
1414494Ssam 		case 1: case RSTR: case RCCL: case RNCCL: case RNULLS:
1514494Ssam 			for(j=0;j<tptr;j++)
1614494Ssam 				tmpstat[j] = FALSE;
1714494Ssam 			count = 0;
1814494Ssam 			follow(v);
1914494Ssam # ifdef PP
2014494Ssam 			padd(foll,v);		/* packing version */
2114494Ssam # endif
2214494Ssam # ifndef PP
2314494Ssam 			add(foll,v);		/* no packing version */
2414494Ssam # endif
2514494Ssam 			if(i == RSTR) cfoll(left[v]);
2614494Ssam 			else if(i == RCCL || i == RNCCL){	/* compress ccl list */
2714494Ssam 				for(j=1; j<NCH;j++)
2814494Ssam 					symbol[j] = (i==RNCCL);
29*33343Sbostic 				p = (char *)left[v];
3014494Ssam 				while(*p)
3114494Ssam 					symbol[*p++] = (i == RCCL);
3214494Ssam 				p = pcptr;
3314494Ssam 				for(j=1;j<NCH;j++)
3414494Ssam 					if(symbol[j]){
3514494Ssam 						for(k=0;p+k < pcptr; k++)
3614494Ssam 							if(cindex[j] == *(p+k))
3714494Ssam 								break;
3814494Ssam 						if(p+k >= pcptr)*pcptr++ = cindex[j];
3914494Ssam 						}
4014494Ssam 				*pcptr++ = 0;
4114494Ssam 				if(pcptr > pchar + pchlen)
4214494Ssam 					error("Too many packed character classes");
43*33343Sbostic 				left[v] = (int)p;
4414494Ssam 				name[v] = RCCL;	/* RNCCL eliminated */
4514494Ssam # ifdef DEBUG
4614494Ssam 				if(debug && *p){
4714494Ssam 					printf("ccl %d: %d",v,*p++);
4814494Ssam 					while(*p)
4914494Ssam 						printf(", %d",*p++);
5014494Ssam 					putchar('\n');
5114494Ssam 					}
5214494Ssam # endif
5314494Ssam 				}
5414494Ssam 			break;
5514494Ssam 		case CARAT:
5614494Ssam 			cfoll(left[v]);
5714494Ssam 			break;
5814494Ssam 		case STAR: case PLUS: case QUEST: case RSCON:
5914494Ssam 			cfoll(left[v]);
6014494Ssam 			break;
6114494Ssam 		case BAR: case RCAT: case DIV: case RNEWE:
6214494Ssam 			cfoll(left[v]);
6314494Ssam 			cfoll(right[v]);
6414494Ssam 			break;
6514494Ssam # ifdef DEBUG
6614494Ssam 		case FINAL:
6714494Ssam 		case S1FINAL:
6814494Ssam 		case S2FINAL:
6914494Ssam 			break;
7014494Ssam 		default:
7114494Ssam 			warning("bad switch cfoll %d",v);
7214494Ssam # endif
7314494Ssam 		}
7414494Ssam 	return;
7514494Ssam 	}
7614494Ssam # ifdef DEBUG
7714494Ssam pfoll()
7814494Ssam 	{
7914494Ssam 	register int i,k,*p;
8014494Ssam 	int j;
8114494Ssam 	/* print sets of chars which may follow positions */
8214494Ssam 	printf("pos\tchars\n");
8314494Ssam 	for(i=0;i<tptr;i++)
8414494Ssam 		if(p=foll[i]){
8514494Ssam 			j = *p++;
8614494Ssam 			if(j >= 1){
8714494Ssam 				printf("%d:\t%d",i,*p++);
8814494Ssam 				for(k=2;k<=j;k++)
8914494Ssam 					printf(", %d",*p++);
9014494Ssam 				putchar('\n');
9114494Ssam 				}
9214494Ssam 			}
9314494Ssam 	return;
9414494Ssam 	}
9514494Ssam # endif
9614494Ssam add(array,n)
9714494Ssam   int **array;
9814494Ssam   int n; {
9914494Ssam 	register int i, *temp;
10014494Ssam 	register char *ctemp;
10114494Ssam 	temp = nxtpos;
10214494Ssam 	ctemp = tmpstat;
10314494Ssam 	array[n] = nxtpos;		/* note no packing is done in positions */
10414494Ssam 	*temp++ = count;
10514494Ssam 	for(i=0;i<tptr;i++)
10614494Ssam 		if(ctemp[i] == TRUE)
10714494Ssam 			*temp++ = i;
10814494Ssam 	nxtpos = temp;
10914494Ssam 	if(nxtpos >= positions+maxpos)
11014494Ssam 		error("Too many positions %s",(maxpos== MAXPOS?"\nTry using %p num":""));
11114494Ssam 	return;
11214494Ssam 	}
11314494Ssam follow(v)
11414494Ssam   int v;
11514494Ssam 	{
11614494Ssam 	register int p;
11714494Ssam 	if(v >= tptr-1)return;
11814494Ssam 	p = parent[v];
11914494Ssam 	if(p == 0) return;
12014494Ssam 	switch(name[p]){
12114494Ssam 			/* will not be CHAR RNULLS FINAL S1FINAL S2FINAL RCCL RNCCL */
12214494Ssam 		case RSTR:
12314494Ssam 			if(tmpstat[p] == FALSE){
12414494Ssam 				count++;
12514494Ssam 				tmpstat[p] = TRUE;
12614494Ssam 				}
12714494Ssam 			break;
12814494Ssam 		case STAR: case PLUS:
12914494Ssam 			first(v);
13014494Ssam 			follow(p);
13114494Ssam 			break;
13214494Ssam 		case BAR: case QUEST: case RNEWE:
13314494Ssam 			follow(p);
13414494Ssam 			break;
13514494Ssam 		case RCAT: case DIV:
13614494Ssam 			if(v == left[p]){
13714494Ssam 				if(nullstr[right[p]])
13814494Ssam 					follow(p);
13914494Ssam 				first(right[p]);
14014494Ssam 				}
14114494Ssam 			else follow(p);
14214494Ssam 			break;
14314494Ssam 		case RSCON: case CARAT:
14414494Ssam 			follow(p);
14514494Ssam 			break;
14614494Ssam # ifdef DEBUG
14714494Ssam 		default:
14814494Ssam 			warning("bad switch follow %d",p);
14914494Ssam # endif
15014494Ssam 		}
15114494Ssam 	return;
15214494Ssam 	}
15314494Ssam first(v)	/* calculate set of positions with v as root which can be active initially */
15414494Ssam   int v; {
15514494Ssam 	register int i;
15614494Ssam 	register char *p;
15714494Ssam 	i = name[v];
15814494Ssam 	if(i < NCH)i = 1;
15914494Ssam 	switch(i){
16014494Ssam 		case 1: case RCCL: case RNCCL: case RNULLS: case FINAL: case S1FINAL: case S2FINAL:
16114494Ssam 			if(tmpstat[v] == FALSE){
16214494Ssam 				count++;
16314494Ssam 				tmpstat[v] = TRUE;
16414494Ssam 				}
16514494Ssam 			break;
16614494Ssam 		case BAR: case RNEWE:
16714494Ssam 			first(left[v]);
16814494Ssam 			first(right[v]);
16914494Ssam 			break;
17014494Ssam 		case CARAT:
17114494Ssam 			if(stnum % 2 == 1)
17214494Ssam 				first(left[v]);
17314494Ssam 			break;
17414494Ssam 		case RSCON:
17514494Ssam 			i = stnum/2 +1;
176*33343Sbostic 			p = (char *)right[v];
17714494Ssam 			while(*p)
17814494Ssam 				if(*p++ == i){
17914494Ssam 					first(left[v]);
18014494Ssam 					break;
18114494Ssam 					}
18214494Ssam 			break;
18314494Ssam 		case STAR: case QUEST: case PLUS:  case RSTR:
18414494Ssam 			first(left[v]);
18514494Ssam 			break;
18614494Ssam 		case RCAT: case DIV:
18714494Ssam 			first(left[v]);
18814494Ssam 			if(nullstr[left[v]])
18914494Ssam 				first(right[v]);
19014494Ssam 			break;
19114494Ssam # ifdef DEBUG
19214494Ssam 		default:
19314494Ssam 			warning("bad switch first %d",v);
19414494Ssam # endif
19514494Ssam 		}
19614494Ssam 	return;
19714494Ssam 	}
19814494Ssam cgoto(){
19914494Ssam 	register int i, j, s;
20014494Ssam 	int npos, curpos, n;
20114494Ssam 	int tryit;
20214494Ssam 	char tch[NCH];
20314494Ssam 	int tst[NCH];
20414494Ssam 	char *q;
20514494Ssam 	/* generate initial state, for each start condition */
20614494Ssam 	if(ratfor){
20714494Ssam 		fprintf(fout,"blockdata\n");
20814494Ssam 		fprintf(fout,"common /Lvstop/ vstop\n");
20914494Ssam 		fprintf(fout,"define Svstop %d\n",nstates+1);
21014494Ssam 		fprintf(fout,"integer vstop(Svstop)\n");
21114494Ssam 		}
21214494Ssam 	else fprintf(fout,"int yyvstop[] ={\n0,\n");
21314494Ssam 	while(stnum < 2 || stnum/2 < sptr){
21414494Ssam 		for(i = 0; i<tptr; i++) tmpstat[i] = 0;
21514494Ssam 		count = 0;
21614494Ssam 		if(tptr > 0)first(tptr-1);
21714494Ssam 		add(state,stnum);
21814494Ssam # ifdef DEBUG
21914494Ssam 		if(debug){
22014494Ssam 			if(stnum > 1)
22114494Ssam 				printf("%s:\n",sname[stnum/2]);
22214494Ssam 			pstate(stnum);
22314494Ssam 			}
22414494Ssam # endif
22514494Ssam 		stnum++;
22614494Ssam 		}
22714494Ssam 	stnum--;
22814494Ssam 	/* even stnum = might not be at line begin */
22914494Ssam 	/* odd stnum  = must be at line begin */
23014494Ssam 	/* even states can occur anywhere, odd states only at line begin */
23114494Ssam 	for(s = 0; s <= stnum; s++){
23214494Ssam 		tryit = FALSE;
23314494Ssam 		cpackflg[s] = FALSE;
23414494Ssam 		sfall[s] = -1;
23514494Ssam 		acompute(s);
23614494Ssam 		for(i=0;i<NCH;i++) symbol[i] = 0;
23714494Ssam 		npos = *state[s];
23814494Ssam 		for(i = 1; i<=npos; i++){
23914494Ssam 			curpos = *(state[s]+i);
24014494Ssam 			if(name[curpos] < NCH) symbol[name[curpos]] = TRUE;
24114494Ssam 			else switch(name[curpos]){
24214494Ssam 			case RCCL:
24314494Ssam 				tryit = TRUE;
244*33343Sbostic 				q = (char *)left[curpos];
24514494Ssam 				while(*q){
24614494Ssam 					for(j=1;j<NCH;j++)
24714494Ssam 						if(cindex[j] == *q)
24814494Ssam 							symbol[j] = TRUE;
24914494Ssam 					q++;
25014494Ssam 					}
25114494Ssam 				break;
25214494Ssam 			case RSTR:
25314494Ssam 				symbol[right[curpos]] = TRUE;
25414494Ssam 				break;
25514494Ssam # ifdef DEBUG
25614494Ssam 			case RNULLS:
25714494Ssam 			case FINAL:
25814494Ssam 			case S1FINAL:
25914494Ssam 			case S2FINAL:
26014494Ssam 				break;
26114494Ssam 			default:
26214494Ssam 				warning("bad switch cgoto %d state %d",curpos,s);
26314494Ssam 				break;
26414494Ssam # endif
26514494Ssam 			}
26614494Ssam 		}
26714494Ssam # ifdef DEBUG
26814494Ssam 		if(debug){
26914494Ssam 			printf("State %d transitions on:\n\t",s);
27014494Ssam 			charc = 0;
27114494Ssam 			for(i = 1; i<NCH; i++){
27214494Ssam 				if(symbol[i]) allprint(i);
27314494Ssam 				if(charc > LINESIZE){
27414494Ssam 					charc = 0;
27514494Ssam 					printf("\n\t");
27614494Ssam 					}
27714494Ssam 				}
27814494Ssam 			putchar('\n');
27914494Ssam 			}
28014494Ssam # endif
28114494Ssam 		/* for each char, calculate next state */
28214494Ssam 		n = 0;
28314494Ssam 		for(i = 1; i<NCH; i++){
28414494Ssam 			if(symbol[i]){
28514494Ssam 				nextstate(s,i);		/* executed for each state, transition pair */
28614494Ssam 				xstate = notin(stnum);
28714494Ssam 				if(xstate == -2) warning("bad state  %d %o",s,i);
28814494Ssam 				else if(xstate == -1){
28914494Ssam 					if(stnum >= nstates)
29014494Ssam 						error("Too many states %s",(nstates == NSTATES ? "\nTry using %n num":""));
29114494Ssam 					add(state,++stnum);
29214494Ssam # ifdef DEBUG
29314494Ssam 					if(debug)pstate(stnum);
29414494Ssam # endif
29514494Ssam 					tch[n] = i;
29614494Ssam 					tst[n++] = stnum;
29714494Ssam 					}
29814494Ssam 				else {		/* xstate >= 0 ==> state exists */
29914494Ssam 					tch[n] = i;
30014494Ssam 					tst[n++] = xstate;
30114494Ssam 					}
30214494Ssam 				}
30314494Ssam 			}
30414494Ssam 		tch[n] = 0;
30514494Ssam 		tst[n] = -1;
30614494Ssam 		/* pack transitions into permanent array */
30714494Ssam 		if(n > 0) packtrans(s,tch,tst,n,tryit);
30814494Ssam 		else gotof[s] = -1;
30914494Ssam 		}
31014494Ssam 	ratfor ? fprintf(fout,"end\n") : fprintf(fout,"0};\n");
31114494Ssam 	return;
31214494Ssam 	}
31314494Ssam 	/*	Beware -- 70% of total CPU time is spent in this subroutine -
31414494Ssam 		if you don't believe me - try it yourself ! */
31514494Ssam nextstate(s,c)
31614494Ssam   int s,c; {
31714494Ssam 	register int j, *newpos;
31814494Ssam 	register char *temp, *tz;
31914494Ssam 	int *pos, i, *f, num, curpos, number;
32014494Ssam 	/* state to goto from state s on char c */
32114494Ssam 	num = *state[s];
32214494Ssam 	temp = tmpstat;
32314494Ssam 	pos = state[s] + 1;
32414494Ssam 	for(i = 0; i<num; i++){
32514494Ssam 		curpos = *pos++;
32614494Ssam 		j = name[curpos];
32714494Ssam 		if(j < NCH && j == c
32814494Ssam 		|| j == RSTR && c == right[curpos]
32914494Ssam 		|| j == RCCL && member(c,left[curpos])){
33014494Ssam 			f = foll[curpos];
33114494Ssam 			number = *f;
33214494Ssam 			newpos = f+1;
33314494Ssam 			for(j=0;j<number;j++)
33414494Ssam 				temp[*newpos++] = 2;
33514494Ssam 			}
33614494Ssam 		}
33714494Ssam 	j = 0;
33814494Ssam 	tz = temp + tptr;
33914494Ssam 	while(temp < tz){
34014494Ssam 		if(*temp == 2){
34114494Ssam 			j++;
34214494Ssam 			*temp++ = 1;
34314494Ssam 			}
34414494Ssam 		else *temp++ = 0;
34514494Ssam 		}
34614494Ssam 	count = j;
34714494Ssam 	return;
34814494Ssam 	}
34914494Ssam notin(n)
35014494Ssam   int n;	{	/* see if tmpstat occurs previously */
35114494Ssam 	register int *j,k;
35214494Ssam 	register char *temp;
35314494Ssam 	int i;
35414494Ssam 	if(count == 0)
35514494Ssam 		return(-2);
35614494Ssam 	temp = tmpstat;
35714494Ssam 	for(i=n;i>=0;i--){	/* for each state */
35814494Ssam 		j = state[i];
35914494Ssam 		if(count == *j++){
36014494Ssam 			for(k=0;k<count;k++)
36114494Ssam 				if(!temp[*j++])break;
36214494Ssam 			if(k >= count)
36314494Ssam 				return(i);
36414494Ssam 			}
36514494Ssam 		}
36614494Ssam 	return(-1);
36714494Ssam 	}
36814494Ssam packtrans(st,tch,tst,cnt,tryit)
36914494Ssam   int st, *tst, cnt,tryit;
37014494Ssam   char *tch; {
37114494Ssam 	/* pack transitions into nchar, nexts */
37214494Ssam 	/* nchar is terminated by '\0', nexts uses cnt, followed by elements */
37314494Ssam 	/* gotof[st] = index into nchr, nexts for state st */
37414494Ssam 
37514494Ssam 	/* sfall[st] =  t implies t is fall back state for st */
37614494Ssam 	/*	        == -1 implies no fall back */
37714494Ssam 
37814494Ssam 	int cmin, cval, tcnt, diff, p, *ast;
37914494Ssam 	register int i,j,k;
38014494Ssam 	char *ach;
38114494Ssam 	int go[NCH], temp[NCH], c;
38214494Ssam 	int swork[NCH];
38314494Ssam 	char cwork[NCH];
38414494Ssam 	int upper;
38514494Ssam 
38614494Ssam 	rcount += cnt;
38714494Ssam 	cmin = -1;
38814494Ssam 	cval = NCH;
38914494Ssam 	ast = tst;
39014494Ssam 	ach = tch;
39114494Ssam 	/* try to pack transitions using ccl's */
39214494Ssam 	if(!optim)goto nopack;		/* skip all compaction */
39314494Ssam 	if(tryit){	/* ccl's used */
39414494Ssam 		for(i=1;i<NCH;i++){
39514494Ssam 			go[i] = temp[i] = -1;
39614494Ssam 			symbol[i] = 1;
39714494Ssam 			}
39814494Ssam 		for(i=0;i<cnt;i++){
39914494Ssam 			go[tch[i]] = tst[i];
40014494Ssam 			symbol[tch[i]] = 0;
40114494Ssam 			}
40214494Ssam 		for(i=0; i<cnt;i++){
40314494Ssam 			c = match[tch[i]];
40414494Ssam 			if(go[c] != tst[i] || c == tch[i])
40514494Ssam 				temp[tch[i]] = tst[i];
40614494Ssam 			}
40714494Ssam 		/* fill in error entries */
40814494Ssam 		for(i=1;i<NCH;i++)
40914494Ssam 			if(symbol[i]) temp[i] = -2;	/* error trans */
41014494Ssam 		/* count them */
41114494Ssam 		k = 0;
41214494Ssam 		for(i=1;i<NCH;i++)
41314494Ssam 			if(temp[i] != -1)k++;
41414494Ssam 		if(k <cnt){	/* compress by char */
41514494Ssam # ifdef DEBUG
41614494Ssam 			if(debug) printf("use compression  %d,  %d vs %d\n",st,k,cnt);
41714494Ssam # endif
41814494Ssam 			k = 0;
41914494Ssam 			for(i=1;i<NCH;i++)
42014494Ssam 				if(temp[i] != -1){
42114494Ssam 					cwork[k] = i;
42214494Ssam 					swork[k++] = (temp[i] == -2 ? -1 : temp[i]);
42314494Ssam 					}
42414494Ssam 			cwork[k] = 0;
42514494Ssam # ifdef PC
42614494Ssam 			ach = cwork;
42714494Ssam 			ast = swork;
42814494Ssam 			cnt = k;
42914494Ssam 			cpackflg[st] = TRUE;
43014494Ssam # endif
43114494Ssam 			}
43214494Ssam 		}
43314494Ssam 	for(i=0; i<st; i++){	/* get most similar state */
43414494Ssam 				/* reject state with more transitions, state already represented by a third state,
43514494Ssam 					and state which is compressed by char if ours is not to be */
43614494Ssam 		if(sfall[i] != -1) continue;
43714494Ssam 		if(cpackflg[st] == 1) if(!(cpackflg[i] == 1)) continue;
43814494Ssam 		p = gotof[i];
43914494Ssam 		if(p == -1) /* no transitions */ continue;
44014494Ssam 		tcnt = nexts[p];
44114494Ssam 		if(tcnt > cnt) continue;
44214494Ssam 		diff = 0;
44314494Ssam 		k = 0;
44414494Ssam 		j = 0;
44514494Ssam 		upper = p + tcnt;
44614494Ssam 		while(ach[j] && p < upper){
44714494Ssam 			while(ach[j] < nchar[p] && ach[j]){diff++; j++; }
44814494Ssam 			if(ach[j] == 0)break;
44914494Ssam 			if(ach[j] > nchar[p]){diff=NCH;break;}
45014494Ssam 			/* ach[j] == nchar[p] */
45114494Ssam 			if(ast[j] != nexts[++p] || ast[j] == -1 || (cpackflg[st] && ach[j] != match[ach[j]]))diff++;
45214494Ssam 			j++;
45314494Ssam 			}
45414494Ssam 		while(ach[j]){
45514494Ssam 			diff++;
45614494Ssam 			j++;
45714494Ssam 			}
45814494Ssam 		if(p < upper)diff = NCH;
45914494Ssam 		if(diff < cval && diff < tcnt){
46014494Ssam 			cval = diff;
46114494Ssam 			cmin = i;
46214494Ssam 			if(cval == 0)break;
46314494Ssam 			}
46414494Ssam 		}
46514494Ssam 	/* cmin = state "most like" state st */
46614494Ssam # ifdef DEBUG
46714494Ssam 	if(debug)printf("select st %d for st %d diff %d\n",cmin,st,cval);
46814494Ssam # endif
46914494Ssam # ifdef PS
47014494Ssam 	if(cmin != -1){ /* if we can use st cmin */
47114494Ssam 		gotof[st] = nptr;
47214494Ssam 		k = 0;
47314494Ssam 		sfall[st] = cmin;
47414494Ssam 		p = gotof[cmin]+1;
47514494Ssam 		j = 0;
47614494Ssam 		while(ach[j]){
47714494Ssam 			/* if cmin has a transition on c, then so will st */
47814494Ssam 			/* st may be "larger" than cmin, however */
47914494Ssam 			while(ach[j] < nchar[p-1] && ach[j]){
48014494Ssam 				k++;
48114494Ssam 				nchar[nptr] = ach[j];
48214494Ssam 				nexts[++nptr] = ast[j];
48314494Ssam 				j++;
48414494Ssam 				}
48514494Ssam 			if(nchar[p-1] == 0)break;
48614494Ssam 			if(ach[j] > nchar[p-1]){
48714494Ssam 				warning("bad transition %d %d",st,cmin);
48814494Ssam 				goto nopack;
48914494Ssam 				}
49014494Ssam 			/* ach[j] == nchar[p-1] */
49114494Ssam 			if(ast[j] != nexts[p] || ast[j] == -1 || (cpackflg[st] && ach[j] != match[ach[j]])){
49214494Ssam 				k++;
49314494Ssam 				nchar[nptr] = ach[j];
49414494Ssam 				nexts[++nptr] = ast[j];
49514494Ssam 				}
49614494Ssam 			p++;
49714494Ssam 			j++;
49814494Ssam 			}
49914494Ssam 		while(ach[j]){
50014494Ssam 			nchar[nptr] = ach[j];
50114494Ssam 			nexts[++nptr] = ast[j++];
50214494Ssam 			k++;
50314494Ssam 			}
50414494Ssam 		nexts[gotof[st]] = cnt = k;
50514494Ssam 		nchar[nptr++] = 0;
50614494Ssam 		}
50714494Ssam 	else {
50814494Ssam # endif
50914494Ssam nopack:
51014494Ssam 	/* stick it in */
51114494Ssam 		gotof[st] = nptr;
51214494Ssam 		nexts[nptr] = cnt;
51314494Ssam 		for(i=0;i<cnt;i++){
51414494Ssam 			nchar[nptr] = ach[i];
51514494Ssam 			nexts[++nptr] = ast[i];
51614494Ssam 			}
51714494Ssam 		nchar[nptr++] = 0;
51814494Ssam # ifdef PS
51914494Ssam 		}
52014494Ssam # endif
52114494Ssam 	if(cnt < 1){
52214494Ssam 		gotof[st] = -1;
52314494Ssam 		nptr--;
52414494Ssam 		}
52514494Ssam 	else
52614494Ssam 		if(nptr > ntrans)
52714494Ssam 			error("Too many transitions %s",(ntrans==NTRANS?"\nTry using %a num":""));
52814494Ssam 	return;
52914494Ssam 	}
53014494Ssam # ifdef DEBUG
53114494Ssam pstate(s)
53214494Ssam   int s; {
53314494Ssam 	register int *p,i,j;
53414494Ssam 	printf("State %d:\n",s);
53514494Ssam 	p = state[s];
53614494Ssam 	i = *p++;
53714494Ssam 	if(i == 0) return;
53814494Ssam 	printf("%4d",*p++);
53914494Ssam 	for(j = 1; j<i; j++){
54014494Ssam 		printf(", %4d",*p++);
54114494Ssam 		if(j%30 == 0)putchar('\n');
54214494Ssam 		}
54314494Ssam 	putchar('\n');
54414494Ssam 	return;
54514494Ssam 	}
54614494Ssam # endif
54714494Ssam member(d,t)
54814494Ssam   int d;
54914494Ssam   char *t;	{
55014494Ssam 	register int c;
55114494Ssam 	register char *s;
55214494Ssam 	c = d;
55314494Ssam 	s = t;
55414494Ssam 	c = cindex[c];
55514494Ssam 	while(*s)
55614494Ssam 		if(*s++ == c) return(1);
55714494Ssam 	return(0);
55814494Ssam 	}
55914494Ssam # ifdef DEBUG
56014494Ssam stprt(i)
56114494Ssam   int i; {
56214494Ssam 	register int p, t;
56314494Ssam 	printf("State %d:",i);
56414494Ssam 	/* print actions, if any */
56514494Ssam 	t = atable[i];
56614494Ssam 	if(t != -1)printf(" final");
56714494Ssam 	putchar('\n');
56814494Ssam 	if(cpackflg[i] == TRUE)printf("backup char in use\n");
56914494Ssam 	if(sfall[i] != -1)printf("fall back state %d\n",sfall[i]);
57014494Ssam 	p = gotof[i];
57114494Ssam 	if(p == -1) return;
57214494Ssam 	printf("(%d transitions)\n",nexts[p]);
57314494Ssam 	while(nchar[p]){
57414494Ssam 		charc = 0;
57514494Ssam 		if(nexts[p+1] >= 0)
57614494Ssam 			printf("%d\t",nexts[p+1]);
57714494Ssam 		else printf("err\t");
57814494Ssam 		allprint(nchar[p++]);
57914494Ssam 		while(nexts[p] == nexts[p+1] && nchar[p]){
58014494Ssam 			if(charc > LINESIZE){
58114494Ssam 				charc = 0;
58214494Ssam 				printf("\n\t");
58314494Ssam 				}
58414494Ssam 			allprint(nchar[p++]);
58514494Ssam 			}
58614494Ssam 		putchar('\n');
58714494Ssam 		}
58814494Ssam 	putchar('\n');
58914494Ssam 	return;
59014494Ssam 	}
59114494Ssam # endif
59214494Ssam acompute(s)	/* compute action list = set of poss. actions */
59314494Ssam   int s; {
59414494Ssam 	register int *p, i, j;
59514494Ssam 	int cnt, m;
59614494Ssam 	int temp[300], k, neg[300], n;
59714494Ssam 	k = 0;
59814494Ssam 	n = 0;
59914494Ssam 	p = state[s];
60014494Ssam 	cnt = *p++;
60114494Ssam 	if(cnt > 300)
60214494Ssam 		error("Too many positions for one state - acompute");
60314494Ssam 	for(i=0;i<cnt;i++){
60414494Ssam 		if(name[*p] == FINAL)temp[k++] = left[*p];
60514494Ssam 		else if(name[*p] == S1FINAL){temp[k++] = left[*p];
60614494Ssam 			if (left[*p] >NACTIONS) error("Too many right contexts");
60714494Ssam 			extra[left[*p]] = 1;
60814494Ssam 			}
60914494Ssam 		else if(name[*p] == S2FINAL)neg[n++] = left[*p];
61014494Ssam 		p++;
61114494Ssam 		}
61214494Ssam 	atable[s] = -1;
61314494Ssam 	if(k < 1 && n < 1) return;
61414494Ssam # ifdef DEBUG
61514494Ssam 	if(debug) printf("final %d actions:",s);
61614494Ssam # endif
61714494Ssam 	/* sort action list */
61814494Ssam 	for(i=0; i<k; i++)
61914494Ssam 		for(j=i+1;j<k;j++)
62014494Ssam 			if(temp[j] < temp[i]){
62114494Ssam 				m = temp[j];
62214494Ssam 				temp[j] = temp[i];
62314494Ssam 				temp[i] = m;
62414494Ssam 				}
62514494Ssam 	/* remove dups */
62614494Ssam 	for(i=0;i<k-1;i++)
62714494Ssam 		if(temp[i] == temp[i+1]) temp[i] = 0;
62814494Ssam 	/* copy to permanent quarters */
62914494Ssam 	atable[s] = aptr;
63014494Ssam # ifdef DEBUG
63114494Ssam 	if(!ratfor)fprintf(fout,"/* actions for state %d */",s);
63214494Ssam # endif
63314494Ssam 	putc('\n',fout);
63414494Ssam 	for(i=0;i<k;i++)
63514494Ssam 		if(temp[i] != 0){
63614494Ssam 			ratfor ? fprintf(fout,"data vstop(%d)/%d/\n",aptr,temp[i]) : fprintf(fout,"%d,\n",temp[i]);
63714494Ssam # ifdef DEBUG
63814494Ssam 			if(debug)
63914494Ssam 				printf("%d ",temp[i]);
64014494Ssam # endif
64114494Ssam 			aptr++;
64214494Ssam 			}
64314494Ssam 	for(i=0;i<n;i++){		/* copy fall back actions - all neg */
64414494Ssam 		ratfor ? fprintf(fout,"data vstop(%d)/%d/\n",aptr,neg[i]) : fprintf(fout,"%d,\n",neg[i]);
64514494Ssam 		aptr++;
64614494Ssam # ifdef DEBUG
64714494Ssam 		if(debug)printf("%d ",neg[i]);
64814494Ssam # endif
64914494Ssam 		}
65014494Ssam # ifdef DEBUG
65114494Ssam 	if(debug)putchar('\n');
65214494Ssam # endif
65314494Ssam 	ratfor ? fprintf(fout,"data vstop (%d)/0/\n",aptr) : fprintf(fout,"0,\n");
65414494Ssam 	aptr++;
65514494Ssam 	return;
65614494Ssam 	}
65714494Ssam # ifdef DEBUG
65814494Ssam pccl() {
65914494Ssam 	/* print character class sets */
66014494Ssam 	register int i, j;
66114494Ssam 	printf("char class intersection\n");
66214494Ssam 	for(i=0; i< ccount; i++){
66314494Ssam 		charc = 0;
66414494Ssam 		printf("class %d:\n\t",i);
66514494Ssam 		for(j=1;j<NCH;j++)
66614494Ssam 			if(cindex[j] == i){
66714494Ssam 				allprint(j);
66814494Ssam 				if(charc > LINESIZE){
66914494Ssam 					printf("\n\t");
67014494Ssam 					charc = 0;
67114494Ssam 					}
67214494Ssam 				}
67314494Ssam 		putchar('\n');
67414494Ssam 		}
67514494Ssam 	charc = 0;
67614494Ssam 	printf("match:\n");
67714494Ssam 	for(i=0;i<NCH;i++){
67814494Ssam 		allprint(match[i]);
67914494Ssam 		if(charc > LINESIZE){
68014494Ssam 			putchar('\n');
68114494Ssam 			charc = 0;
68214494Ssam 			}
68314494Ssam 		}
68414494Ssam 	putchar('\n');
68514494Ssam 	return;
68614494Ssam 	}
68714494Ssam # endif
68814494Ssam mkmatch(){
68914494Ssam 	register int i;
69014494Ssam 	char tab[NCH];
69114494Ssam 	for(i=0; i<ccount; i++)
69214494Ssam 		tab[i] = 0;
69314494Ssam 	for(i=1;i<NCH;i++)
69414494Ssam 		if(tab[cindex[i]] == 0)
69514494Ssam 			tab[cindex[i]] = i;
69614494Ssam 	/* tab[i] = principal char for new ccl i */
69714494Ssam 	for(i = 1; i<NCH; i++)
69814494Ssam 		match[i] = tab[cindex[i]];
69914494Ssam 	return;
70014494Ssam 	}
70114494Ssam layout(){
70214494Ssam 	/* format and output final program's tables */
70314494Ssam 	register int i, j, k;
70414494Ssam 	int  top, bot, startup, omin;
70514494Ssam 	startup = 0;
70614494Ssam 	for(i=0; i<outsize;i++)
70714494Ssam 		verify[i] = advance[i] = 0;
70814494Ssam 	omin = 0;
70914494Ssam 	yytop = 0;
71014494Ssam 	for(i=0; i<= stnum; i++){	/* for each state */
71114494Ssam 		j = gotof[i];
71214494Ssam 		if(j == -1){
71314494Ssam 			stoff[i] = 0;
71414494Ssam 			continue;
71514494Ssam 			}
71614494Ssam 		bot = j;
71714494Ssam 		while(nchar[j])j++;
71814494Ssam 		top = j - 1;
71914494Ssam # if DEBUG
72014494Ssam 		if (debug)
72114494Ssam 			{
72214494Ssam 			printf("State %d: (layout)\n", i);
72314494Ssam 			for(j=bot; j<=top;j++)
72414494Ssam 				{
72514494Ssam 				printf("  %o", nchar[j]);
72614494Ssam 				if (j%10==0) putchar('\n');
72714494Ssam 				}
72814494Ssam 			putchar('\n');
72914494Ssam 			}
73014494Ssam # endif
73114494Ssam 		while(verify[omin+ZCH]) omin++;
73214494Ssam 		startup = omin;
73314494Ssam # if DEBUG
73414494Ssam 		if (debug) printf("bot,top %d, %d startup begins %d\n",bot,top,startup);
73514494Ssam # endif
73614494Ssam 		if(chset){
73714494Ssam 			do {
73814494Ssam 				++startup;
73914494Ssam 				if(startup > outsize - ZCH)
74014494Ssam 					error("output table overflow");
74114494Ssam 				for(j = bot; j<= top; j++){
74214494Ssam 					k=startup+ctable[nchar[j]];
74314494Ssam 					if(verify[k])break;
74414494Ssam 					}
74514494Ssam 				} while (j <= top);
74614494Ssam # if DEBUG
74714494Ssam 			if (debug) printf(" startup will be %d\n",startup);
74814494Ssam # endif
74914494Ssam 			/* have found place */
75014494Ssam 			for(j = bot; j<= top; j++){
75114494Ssam 				k = startup + ctable[nchar[j]];
75214494Ssam 				if (ctable[nchar[j]]<=0)
75314494Ssam 				 printf("j %d nchar %d ctable.nch %d\n",j,nchar[j],ctable[nchar[k]]);
75414494Ssam 				verify[k] = i+1;			/* state number + 1*/
75514494Ssam 				advance[k] = nexts[j+1]+1;		/* state number + 1*/
75614494Ssam 				if(yytop < k) yytop = k;
75714494Ssam 				}
75814494Ssam 			}
75914494Ssam 		else {
76014494Ssam 			do {
76114494Ssam 				++startup;
76214494Ssam 				if(startup > outsize - ZCH)
76314494Ssam 					error("output table overflow");
76414494Ssam 				for(j = bot; j<= top; j++){
76514494Ssam 					k = startup + nchar[j];
76614494Ssam 					if(verify[k])break;
76714494Ssam 					}
76814494Ssam 				} while (j <= top);
76914494Ssam 			/* have found place */
77014494Ssam # if DEBUG
77114494Ssam 	if (debug) printf(" startup going to be %d\n", startup);
77214494Ssam # endif
77314494Ssam 			for(j = bot; j<= top; j++){
77414494Ssam 				k = startup + nchar[j];
77514494Ssam 				verify[k] = i+1;			/* state number + 1*/
77614494Ssam 				advance[k] = nexts[j+1]+1;		/* state number + 1*/
77714494Ssam 				if(yytop < k) yytop = k;
77814494Ssam 				}
77914494Ssam 			}
78014494Ssam 		stoff[i] = startup;
78114494Ssam 		}
78214494Ssam 
78314494Ssam 	/* stoff[i] = offset into verify, advance for trans for state i */
78414494Ssam 	/* put out yywork */
78514494Ssam 	if(ratfor){
78614494Ssam 		fprintf(fout, "define YYTOPVAL %d\n", yytop);
78714494Ssam 		rprint(verify,"verif",yytop+1);
78814494Ssam 		rprint(advance,"advan",yytop+1);
78914494Ssam  		shiftr(stoff, stnum);
79014494Ssam 		rprint(stoff,"stoff",stnum+1);
79114494Ssam  		shiftr(sfall, stnum); upone(sfall, stnum+1);
79214494Ssam 		rprint(sfall,"sfall",stnum+1);
79314494Ssam 		bprint(extra,"extra",casecount+1);
79414494Ssam 		bprint(match,"match",NCH);
79514494Ssam  		shiftr(atable, stnum);
79614494Ssam 		rprint(atable,"atable",stnum+1);
79714494Ssam 		return;
79814494Ssam 		}
79914494Ssam 	fprintf(fout,"# define YYTYPE %s\n",stnum+1 > NCH ? "int" : "char");
80014494Ssam 	fprintf(fout,"struct yywork { YYTYPE verify, advance; } yycrank[] ={\n");
80114494Ssam 	for(i=0;i<=yytop;i+=4){
80214494Ssam 		for(j=0;j<4;j++){
80314494Ssam 			k = i+j;
80414494Ssam 			if(verify[k])
80514494Ssam 				fprintf(fout,"%d,%d,\t",verify[k],advance[k]);
80614494Ssam 			else
80714494Ssam 				fprintf(fout,"0,0,\t");
80814494Ssam 			}
80914494Ssam 		putc('\n',fout);
81014494Ssam 		}
81114494Ssam 	fprintf(fout,"0,0};\n");
81214494Ssam 
81314494Ssam 	/* put out yysvec */
81414494Ssam 
81514494Ssam 	fprintf(fout,"struct yysvf yysvec[] ={\n");
81614494Ssam 	fprintf(fout,"0,\t0,\t0,\n");
81714494Ssam 	for(i=0;i<=stnum;i++){	/* for each state */
81814494Ssam 		if(cpackflg[i])stoff[i] = -stoff[i];
81914494Ssam 		fprintf(fout,"yycrank+%d,\t",stoff[i]);
82014494Ssam 		if(sfall[i] != -1)
82114494Ssam 			fprintf(fout,"yysvec+%d,\t", sfall[i]+1);	/* state + 1 */
82214494Ssam 		else fprintf(fout,"0,\t\t");
82314494Ssam 		if(atable[i] != -1)
82414494Ssam 			fprintf(fout,"yyvstop+%d,",atable[i]);
82514494Ssam 		else fprintf(fout,"0,\t");
82614494Ssam # ifdef DEBUG
82714494Ssam 		fprintf(fout,"\t\t/* state %d */",i);
82814494Ssam # endif
82914494Ssam 		putc('\n',fout);
83014494Ssam 		}
83114494Ssam 	fprintf(fout,"0,\t0,\t0};\n");
83214494Ssam 
83314494Ssam 	/* put out yymatch */
83414494Ssam 
83514494Ssam 	fprintf(fout,"struct yywork *yytop = yycrank+%d;\n",yytop);
83614494Ssam 	fprintf(fout,"struct yysvf *yybgin = yysvec+1;\n");
83714494Ssam 	if(optim){
83814494Ssam 		fprintf(fout,"char yymatch[] ={\n");
83914494Ssam 		if (chset==0) /* no chset, put out in normal order */
84014494Ssam 			{
84114494Ssam 			for(i=0; i<NCH; i+=8){
84214494Ssam 				for(j=0; j<8; j++){
84314494Ssam 					int fbch;
84414494Ssam 					fbch = match[i+j];
84514494Ssam 					if(printable(fbch) && fbch != '\'' && fbch != '\\')
84614494Ssam 						fprintf(fout,"'%c' ,",fbch);
84714494Ssam 					else fprintf(fout,"0%-3o,",fbch);
84814494Ssam 					}
84914494Ssam 				putc('\n',fout);
85014494Ssam 				}
85114494Ssam 			}
85214494Ssam 		else
85314494Ssam 			{
85414494Ssam 			int *fbarr;
855*33343Sbostic 			fbarr = (int *)myalloc(2*NCH, sizeof(*fbarr));
85614494Ssam 			if (fbarr==0)
85714494Ssam 				error("No space for char table reverse",0);
85814494Ssam 			for(i=0; i<ZCH; i++)
85914494Ssam 				fbarr[i]=0;
86014494Ssam 			for(i=0; i<NCH; i++)
86114494Ssam 				fbarr[ctable[i]] = ctable[match[i]];
86214494Ssam 			for(i=0; i<ZCH; i+=8)
86314494Ssam 				{
86414494Ssam 				for(j=0; j<8; j++)
86514494Ssam 					fprintf(fout, "0%-3o,",fbarr[i+j]);
86614494Ssam 				putc('\n',fout);
86714494Ssam 				}
86814494Ssam 			cfree(fbarr, 2*NCH, 1);
86914494Ssam 			}
87014494Ssam 		fprintf(fout,"0};\n");
87114494Ssam 		}
87214494Ssam 	/* put out yyextra */
87314494Ssam 	fprintf(fout,"char yyextra[] ={\n");
87414494Ssam 	for(i=0;i<casecount;i+=8){
87514494Ssam 		for(j=0;j<8;j++)
87614494Ssam 			fprintf(fout, "%d,", i+j<NACTIONS ?
87714494Ssam 				extra[i+j] : 0);
87814494Ssam 		putc('\n',fout);
87914494Ssam 		}
88014494Ssam 	fprintf(fout,"0};\n");
88114494Ssam 	return;
88214494Ssam 	}
88314494Ssam rprint(a,s,n)
88414494Ssam   char *s;
88514494Ssam   int *a, n; {
88614494Ssam 	register int i;
88714494Ssam 	fprintf(fout,"block data\n");
88814494Ssam 	fprintf(fout,"common /L%s/ %s\n",s,s);
88914494Ssam 	fprintf(fout,"define S%s %d\n",s,n);
89014494Ssam 	fprintf(fout,"integer %s (S%s)\n",s,s);
89114494Ssam 	for(i=1; i<=n; i++)
89214494Ssam 		{
89314494Ssam 		if (i%8==1) fprintf(fout, "data ");
89414494Ssam 		fprintf(fout, "%s (%d)/%d/",s,i,a[i]);
89514494Ssam 		fprintf(fout, (i%8 && i<n) ? ", " : "\n");
89614494Ssam 		}
89714494Ssam 	fprintf(fout,"end\n");
89814494Ssam 	}
89914494Ssam shiftr(a, n)
90014494Ssam 	int *a;
90114494Ssam {
90214494Ssam int i;
90314494Ssam for(i=n; i>=0; i--)
90414494Ssam 	a[i+1]=a[i];
90514494Ssam }
90614494Ssam upone(a,n)
90714494Ssam 	int *a;
90814494Ssam {
90914494Ssam int i;
91014494Ssam for(i=0; i<=n ; i++)
91114494Ssam 	a[i]++;
91214494Ssam }
91314494Ssam bprint(a,s,n)
91414494Ssam  char *s,  *a;
91514494Ssam  int  n; {
91614494Ssam 	register int i, j, k;
91714494Ssam 	fprintf(fout,"block data\n");
91814494Ssam 	fprintf(fout,"common /L%s/ %s\n",s,s);
91914494Ssam 	fprintf(fout,"define S%s %d\n",s,n);
92014494Ssam 	fprintf(fout,"integer %s (S%s)\n",s,s);
92114494Ssam 	for(i=1;i<n;i+=8){
92214494Ssam 		fprintf(fout,"data %s (%d)/%d/",s,i,a[i]);
92314494Ssam 		for(j=1;j<8;j++){
92414494Ssam 			k = i+j;
92514494Ssam 			if(k < n)fprintf(fout,", %s (%d)/%d/",s,k,a[k]);
92614494Ssam 			}
92714494Ssam 		putc('\n',fout);
92814494Ssam 		}
92914494Ssam 	fprintf(fout,"end\n");
93014494Ssam 	}
93114494Ssam # ifdef PP
93214494Ssam padd(array,n)
93314494Ssam   int **array;
93414494Ssam   int n; {
93514494Ssam 	register int i, *j, k;
93614494Ssam 	array[n] = nxtpos;
93714494Ssam 	if(count == 0){
93814494Ssam 		*nxtpos++ = 0;
93914494Ssam 		return;
94014494Ssam 		}
94114494Ssam 	for(i=tptr-1;i>=0;i--){
94214494Ssam 		j = array[i];
94314494Ssam 		if(j && *j++ == count){
94414494Ssam 			for(k=0;k<count;k++)
94514494Ssam 				if(!tmpstat[*j++])break;
94614494Ssam 			if(k >= count){
94714494Ssam 				array[n] = array[i];
94814494Ssam 				return;
94914494Ssam 				}
95014494Ssam 			}
95114494Ssam 		}
95214494Ssam 	add(array,n);
95314494Ssam 	return;
95414494Ssam 	}
95514494Ssam # endif
956