
/*
 * $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
 *
 */

/*	Copyright (c) 1984 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/

#ident	"$Header: sub2.c 1.5 90/03/13 $@(#)lex:sub2.c	1.4"
/* sub2.c */
# include "ldefs.c"
static int marray[512];
static int mcount;
static int mstatus = 0;
cfoll(v)
	int v;
	{
	register int i,j,k;
	unsigned char *p;
	i = name[v];
	if(i < NCH) i = 1;	/* character */
	switch(i){
		case 1: case RSTR: case RCCL: case RNCCL: case RNULLS:
			for(j=0;j<tptr;j++)
				tmpstat[j] = FALSE;
			count = 0;
			follow(v);
# ifdef PP
			padd(foll,v);  	/* packing version */
# endif
# ifndef PP
			add(foll,v);		/* no packing version */
# endif
			if(i == RSTR) cfoll(left[v]);
			else if(i == RCCL || i == RNCCL){	/* compress ccl list */
				for(j=1; j<NCH;j++)
					symbol[j] = (i==RNCCL);
				p = (unsigned char *)left[v];
				while(*p)
					symbol[*p++] = (i == RCCL);
				p = pcptr;
				for(j=1;j<NCH;j++)
					if(symbol[j]){
						for(k=0;p+k < pcptr; k++)
							if(cindex[j] == *(p+k))
								break;
						if(p+k >= pcptr)*pcptr++ = cindex[j];
						}
				*pcptr++ = 0;
				if(pcptr > pchar + pchlen)
					error("Too many packed character classes");
				left[v] = (int)p;
				name[v] = RCCL;	/* RNCCL eliminated */
# ifdef DEBUG
				if(debug && *p){
					printf("ccl %d: %d",v,*p++);
					while(*p)
						printf(", %d",*p++);
					putchar('\n');
					}
# endif
				}
			break;
		case CARAT:
			cfoll(left[v]);
			break;
		case STAR: case PLUS: case QUEST: case RSCON: 
			cfoll(left[v]);
			break;
		case BAR: case RCAT: case DIV: case RNEWE:
			cfoll(left[v]);
			cfoll(right[v]);
			break;
# ifdef DEBUG
		case FINAL:
		case S1FINAL:
		case S2FINAL:
			break;
		default:
			warning("bad switch cfoll %d",v);
# endif
		}
	return;
	}
# ifdef DEBUG
pfoll()
	{
	register int i,k,*p;
	int j;
	/* print sets of chars which may follow positions */
	printf("pos\tchars\n");
	for(i=0;i<tptr;i++)
		if(p=foll[i]){
			j = *p++;
			if(j >= 1){
				printf("%d:\t%d",i,*p++);
				for(k=2;k<=j;k++)
					printf(", %d",*p++);
				putchar('\n');
				}
			}
	return;
	}
# endif
add(array,n)
  int **array;
  int n; {
	register int i, *temp;
	register unsigned char *ctemp;
	temp = nxtpos;
	ctemp = tmpstat;
	array[n] = nxtpos;		/* note no packing is done in positions */
	*temp++ = count;
	for(i=0;i<tptr;i++)
		if(ctemp[i] == TRUE)
			*temp++ = i;
	nxtpos = temp;
	if(nxtpos >= positions+maxpos)
		error("Too many positions %s",(maxpos== MAXPOS?"\nTry using %p num":""));
	return;
	}
follow(v)
  int v;
	{
	register int p;
	if(v >= tptr-1)return;
	p = parent[v];
	if(p == 0) return;
	switch(name[p]){
			/* will not be CHAR RNULLS FINAL S1FINAL S2FINAL RCCL RNCCL */
		case RSTR:
			if(tmpstat[p] == FALSE){
				count++;
				tmpstat[p] = TRUE;
				}
			break;
		case STAR: case PLUS:
			first(v);
			follow(p);
			break;
		case BAR: case QUEST: case RNEWE:
			follow(p);
			break;
		case RCAT: case DIV: 
			if(v == left[p]){
				if(nullstr[right[p]])
					follow(p);
				first(right[p]);
				}
			else follow(p);
			break;
		case RSCON: case CARAT: 
			follow(p);
			break;
# ifdef DEBUG
		default:
			warning("bad switch follow %d",p);
# endif
		}
	return;
	}
first(v)	/* calculate set of positions with v as root which can be active initially */
  int v; {
	register int i;
	register unsigned char *p;
	i = name[v];
	if(i < NCH)i = 1;
	switch(i){
		case 1: case RCCL: case RNCCL: case RNULLS: case FINAL: case S1FINAL: case S2FINAL:
			if(tmpstat[v] == FALSE){
				count++;
				tmpstat[v] = TRUE;
				}
			break;
		case BAR: case RNEWE:
			first(left[v]);
			first(right[v]);
			break;
		case CARAT:
			if(stnum % 2 == 1)
				first(left[v]);
			break;
		case RSCON:
			i = stnum/2 +1;
			p = (unsigned char *)right[v];
			while(*p)
				if(*p++ == i){
					first(left[v]);
					break;
					}
			break;
		case STAR: case QUEST: case PLUS:  case RSTR:
			first(left[v]);
			break;
		case RCAT: case DIV:
			first(left[v]);
			if(nullstr[left[v]])
				first(right[v]);
			break;
# ifdef DEBUG
		default:
			warning("bad switch first %d",v);
# endif
		}
	return;
	}
cgoto(){
	register int i, j, s;
	int npos, curpos, n;
	int tryit;
	unsigned char tch[NCH];
	int tst[NCH];
	unsigned char *q;
	/* generate initial state, for each start condition */
	if(ratfor){
		fprintf(fout,"blockdata\n");
		fprintf(fout,"common /Lvstop/ vstop\n");
		fprintf(fout,"define Svstop %d\n",nstates+1);
		fprintf(fout,"integer vstop(Svstop)\n");
		}
	else fprintf(fout,"int yyvstop[] = {\n0,\n");
	while(stnum < 2 || stnum/2 < sptr){
		for(i = 0; i<tptr; i++) tmpstat[i] = 0;
		count = 0;
		if(tptr > 0)first(tptr-1);
		add(state,stnum);
# ifdef DEBUG
		if(debug){
			if(stnum > 1)
				printf("%s:\n",sname[stnum/2]);
			pstate(stnum);
			}
# endif
		stnum++;
		}
	stnum--;
	/* even stnum = might not be at line begin */
	/* odd stnum  = must be at line begin */
	/* even states can occur anywhere, odd states only at line begin */
	for(s = 0; s <= stnum; s++){
		tryit = FALSE;
		cpackflg[s] = FALSE;
		sfall[s] = -1;
		acompute(s);
		for(i=0;i<NCH;i++) symbol[i] = 0;
		npos = *state[s];
		for(i = 1; i<=npos; i++){
			curpos = *(state[s]+i);
			if(name[curpos] < NCH) symbol[name[curpos]] = TRUE;
			else switch(name[curpos]){
			case RCCL:
				tryit = TRUE;
				q = (unsigned char *)left[curpos];
				while(*q){
					for(j=1;j<NCH;j++)
						if(cindex[j] == *q)
							symbol[j] = TRUE;
					q++;
					}
				break;
			case RSTR:
				symbol[right[curpos]] = TRUE;
				break;
# ifdef DEBUG
			case RNULLS:
			case FINAL:
			case S1FINAL:
			case S2FINAL:
				break;
			default:
				warning("bad switch cgoto %d state %d",curpos,s);
				break;
# endif
			}
		}
# ifdef DEBUG
		if(debug){
			printf("State %d transitions on:\n\t",s);
			charc = 0;
			for(i = 1; i<NCH; i++){
				if(symbol[i]) allprint(i);
				if(charc > LINESIZE){
					charc = 0;
					printf("\n\t");
					}
				}
			putchar('\n');
			}
# endif
		/* for each char, calculate next state */
		n = 0;
		for(i = 1; i<NCH; i++){
			if(symbol[i]){
				nextstate(s,i);		/* executed for each state, transition pair */
				xstate = notin(stnum);
				if(xstate == -2) warning("bad state  %d %o",s,i);
				else if(xstate == -1){
					if(stnum >= nstates)
						error("Too many states %s",(nstates == NSTATES ? "\nTry using %n num":""));
					add(state,++stnum);
# ifdef DEBUG
					if(debug)pstate(stnum);
# endif
					tch[n] = i;
					tst[n++] = stnum;
					}
				else {		/* xstate >= 0 ==> state exists */
					tch[n] = i;
					tst[n++] = xstate;
					}
				}
			}
		tch[n] = 0;
		tst[n] = -1;
		/* pack transitions into permanent array */
		if(n > 0) packtrans(s,tch,tst,n,tryit);
		else gotof[s] = -1;
		}
	ratfor ? fprintf(fout,"end\n") : fprintf(fout,"0};\n");
	return;
	}
	/*	Beware -- 70% of total CPU time is spent in this subroutine -
		if you don't believe me - try it yourself ! */
nextstate(s,c)
  int s,c; {
	register int j, *newpos;
	register unsigned char *temp, *tz;
	int *pos, i, *f, num, curpos, number;
	/* state to goto from state s on unsigned char c */
	num = *state[s];
	temp = tmpstat;
	pos = state[s] + 1;
	for(i = 0; i<num; i++){
		curpos = *pos++;
		j = name[curpos];
		if(j < NCH && j == c
		|| j == RSTR && c == right[curpos]
		|| j == RCCL && member(c,left[curpos])){
			f = foll[curpos];
			number = *f;
			newpos = f+1;
			for(j=0;j<number;j++)
				temp[*newpos++] = 2;
			}
		}
	j = 0;
	tz = temp + tptr;
	while(temp < tz){
		if(*temp == 2){
			j++;
			*temp++ = 1;
			}
		else *temp++ = 0;
		}
	count = j;
	return;
	}
notin(n)
  int n;	{	/* see if tmpstat occurs previously */
	register int *j,k;
	register unsigned char *temp;
	int i;
	if(count == 0)
		return(-2);
	temp = tmpstat;
	for(i=n;i>=0;i--){	/* for each state */
		j = state[i];
		if(count == *j++){
			for(k=0;k<count;k++)
				if(!temp[*j++])break;
			if(k >= count)
				return(i);
			}
		}
	return(-1);
	}
packtrans(st,tch,tst,cnt,tryit)
  int st, *tst, cnt,tryit;
  unsigned char *tch; {
	/* pack transitions into nchar, nexts */
	/* nunsigned char is terminated by '\0', nexts uses cnt, followed by elements */
	/* gotof[st] = index into nchr, nexts for state st */

	/* sfall[st] =  t implies t is fall back state for st */
	/*	        == -1 implies no fall back */

	int cmin, cval, tcnt, diff, p, *ast;
	register int i,j,k;
	unsigned char *ach;
	int go[NCH], temp[NCH], c;
	int swork[NCH];
	unsigned char cwork[NCH];
	int upper;

	rcount += cnt;
	cmin = -1;
	cval = NCH;
	ast = tst;
	ach = tch;
	/* try to pack transitions using ccl's */
	if(!optim)goto nopack;		/* skip all compaction */
	if(tryit){	/* ccl's used */
		for(i=1;i<NCH;i++){
			go[i] = temp[i] = -1;
			symbol[i] = 1;
			}
		for(i=0;i<cnt;i++){
			go[tch[i]] = tst[i];
			symbol[tch[i]] = 0;
			}
		for(i=0; i<cnt;i++){
			c = match[tch[i]];
			if(go[c] != tst[i] || c == tch[i])
				temp[tch[i]] = tst[i];
			}
		/* fill in error entries */
		for(i=1;i<NCH;i++)
			if(symbol[i]) temp[i] = -2;	/* error trans */
		/* count them */
		k = 0;
		for(i=1;i<NCH;i++)
			if(temp[i] != -1)k++;
		if(k <cnt){	/* compress by unsigned char */
# ifdef DEBUG
			if(debug) printf("use compression  %d,  %d vs %d\n",st,k,cnt);
# endif
			k = 0;
			for(i=1;i<NCH;i++)
				if(temp[i] != -1){
					cwork[k] = i;
					swork[k++] = (temp[i] == -2 ? -1 : temp[i]);
					}
			cwork[k] = 0;
# ifdef PC
			ach = cwork;
			ast = swork;
			cnt = k;
			cpackflg[st] = TRUE;
# endif
			}
		}
	for(i=0; i<st; i++){	/* get most similar state */
				/* reject state with more transitions, state already represented by a third state,
					and state which is compressed by unsigned char if ours is not to be */
		if(sfall[i] != -1) continue;
		if(cpackflg[st] == 1) if(!(cpackflg[i] == 1)) continue;
		p = gotof[i];
		if(p == -1) /* no transitions */ continue;
		tcnt = nexts[p];
		if(tcnt > cnt) continue;
		diff = 0;
		k = 0;
		j = 0;
		upper = p + tcnt;
		while(ach[j] && p < upper){
			while(ach[j] < nchar[p] && ach[j]){diff++; j++; }
			if(ach[j] == 0)break;
			if(ach[j] > nchar[p]){diff=NCH;break;}
			/* ach[j] == nchar[p] */
			if(ast[j] != nexts[++p] || ast[j] == -1 || (cpackflg[st] && ach[j] != match[ach[j]]))diff++;
			j++;
			}
		while(ach[j]){
			diff++;
			j++;
			}
		if(p < upper)diff = NCH;
		if(diff < cval && diff < tcnt){
			cval = diff;
			cmin = i;
			if(cval == 0)break;
			}
		}
	/* cmin = state "most like" state st */
# ifdef DEBUG
	if(debug)printf("select st %d for st %d diff %d\n",cmin,st,cval);
# endif
# ifdef PS
	if(cmin != -1){ /* if we can use st cmin */
		gotof[st] = nptr;
		k = 0;
		sfall[st] = cmin;
		p = gotof[cmin]+1;
		j = 0;
		while(ach[j]){
			/* if cmin has a transition on c, then so will st */
			/* st may be "larger" than cmin, however */
			while(ach[j] < nchar[p-1] && ach[j]){
				k++;
				nchar[nptr] = ach[j];
				nexts[++nptr] = ast[j];
				j++;
				}
			if(nchar[p-1] == 0)break;
			if(ach[j] > nchar[p-1]){
				warning("bad transition %d %d",st,cmin);
				goto nopack;
				}
			/* ach[j] == nchar[p-1] */
			if(ast[j] != nexts[p] || ast[j] == -1 || (cpackflg[st] && ach[j] != match[ach[j]])){
				k++;
				nchar[nptr] = ach[j];
				nexts[++nptr] = ast[j];
				}
			p++;
			j++;
			}
		while(ach[j]){
			nchar[nptr] = ach[j];
			nexts[++nptr] = ast[j++];
			k++;
			}
		nexts[gotof[st]] = cnt = k;
		nchar[nptr++] = 0;
		}
	else {
# endif
nopack:
	/* stick it in */
		gotof[st] = nptr;
		nexts[nptr] = cnt;
		for(i=0;i<cnt;i++){
			nchar[nptr] = ach[i];
			nexts[++nptr] = ast[i];
			}
		nchar[nptr++] = 0;
# ifdef PS
		}
# endif
	if(cnt < 1){
		gotof[st] = -1;
		nptr--;
		}
	else
		if(nptr > ntrans)
			error("Too many transitions %s",(ntrans==NTRANS?"\nTry using %a num":""));
	return;
	}
# ifdef DEBUG
pstate(s)
  int s; {
	register int *p,i,j;
	printf("State %d:\n",s);
	p = state[s];
	i = *p++;
	if(i == 0) return;
	printf("%4d",*p++);
	for(j = 1; j<i; j++){
		printf(", %4d",*p++);
		if(j%30 == 0)putchar('\n');
		}
	putchar('\n');
	return;
	}
# endif
member(d,t)
  int d;
  unsigned char *t;	{
	register int c;
	register unsigned char *s;
	c = d;
	s = t;
	c = cindex[c];
	while(*s)
		if(*s++ == c) return(1);
	return(0);
	}
# ifdef DEBUG
stprt(i)
  int i; {
	register int p, t;
	printf("State %d:",i);
	/* print actions, if any */
	t = atable[i];
	if(t != -1)printf(" final");
	putchar('\n');
	if(cpackflg[i] == TRUE)printf("backup unsigned char in use\n");
	if(sfall[i] != -1)printf("fall back state %d\n",sfall[i]);
	p = gotof[i];
	if(p == -1) return;
	printf("(%d transitions)\n",nexts[p]);
	while(nchar[p]){
		charc = 0;
		if(nexts[p+1] >= 0)
			printf("%d\t",nexts[p+1]);
		else printf("err\t");
		allprint(nchar[p++]);
		while(nexts[p] == nexts[p+1] && nchar[p]){
			if(charc > LINESIZE){
				charc = 0;
				printf("\n\t");
				}
			allprint(nchar[p++]);
			}
		putchar('\n');
		}
	putchar('\n');
	return;
	}
# endif
acompute(s)	/* compute action list = set of poss. actions */
  int s; {
	register int *p, i, j;
	int cnt, m;
 	int temp[POSMEM], k, neg[POSMEM], n;
	k = 0;
	n = 0;
	p = state[s];
	cnt = *p++;
	if(cnt > POSMEM){
                printf("%d %d\n",cnt,POSMEM);
		error("Too many positions for one state - acompute");
                }
	for(i=0;i<cnt;i++){
		if(name[*p] == FINAL)temp[k++] = left[*p];
		else if(name[*p] == S1FINAL){temp[k++] = left[*p];
			if (left[*p] >NACTIONS) error("Too many right contexts");
			extra[left[*p]] = 1;
			}
		else if(name[*p] == S2FINAL)neg[n++] = left[*p];
		p++;
		}
	atable[s] = -1;
	if(k < 1 && n < 1) return;
# ifdef DEBUG
	if(debug) printf("final %d actions:",s);
# endif
	/* sort action list */
	for(i=0; i<k; i++)
		for(j=i+1;j<k;j++)
			if(temp[j] < temp[i]){
				m = temp[j];
				temp[j] = temp[i];
				temp[i] = m;
				}
	/* remove dups */
	for(i=0;i<k-1;i++)
		if(temp[i] == temp[i+1]) temp[i] = 0;
	/* copy to permanent quarters */
	atable[s] = aptr;
# ifdef DEBUG
	if(!ratfor)fprintf(fout,"/* actions for state %d */",s);
# endif
	putc('\n',fout);
	for(i=0;i<k;i++)
		if(temp[i] != 0){
			ratfor ? fprintf(fout,"data vstop(%d)/%d/\n",aptr,temp[i]) : fprintf(fout,"%d,\n",temp[i]);
# ifdef DEBUG
			if(debug)
				printf("%d ",temp[i]);
# endif
			aptr++;
			}
	for(i=0;i<n;i++){		/* copy fall back actions - all neg */
		ratfor ? fprintf(fout,"data vstop(%d)/%d/\n",aptr,neg[i]) : fprintf(fout,"%d,\n",neg[i]);
		aptr++;
# ifdef DEBUG
		if(debug)printf("%d ",neg[i]);
# endif
		}
# ifdef DEBUG
	if(debug)putchar('\n');
# endif
	ratfor ? fprintf(fout,"data vstop (%d)/0/\n",aptr) : fprintf(fout,"0,\n");
	aptr++;
	return;
	}
# ifdef DEBUG
pccl() {
	/* print character class sets */
	register int i, j;
	printf("unsigned char class intersection\n");
	for(i=0; i< ccount; i++){
		charc = 0;
		printf("class %d:\n\t",i);
		for(j=1;j<NCH;j++)
			if(cindex[j] == i){
				allprint(j);
				if(charc > LINESIZE){
					printf("\n\t");
					charc = 0;
					}
				}
		putchar('\n');
		}
	charc = 0;
	printf("match:\n");
	for(i=0;i<NCH;i++){
		allprint(match[i]);
		if(charc > LINESIZE){
			putchar('\n');
			charc = 0;
			}
		}
	putchar('\n');
	return;
	}
# endif
mkmatch(){
	register int i;
	unsigned char tab[NCH];
	for(i=0; i<ccount; i++)
		tab[i] = 0;
	for(i=1;i<NCH;i++)
		if(tab[cindex[i]] == 0)
			tab[cindex[i]] = i;
	/* tab[i] = principal unsigned char for new ccl i */
	for(i = 1; i<NCH; i++)
		match[i] = tab[cindex[i]];
	return;
	}
layout(){
	/* format and output final program's tables */
	register int i, j, k;
	int  top, bot, startup, omin;
	startup = 0;
	for(i=0; i<outsize;i++)
		verify[i] = advance[i] = 0;
	omin = 0;
	yytop = 0;
	for(i=0; i<= stnum; i++){	/* for each state */
		j = gotof[i];
		if(j == -1){
			stoff[i] = 0;
			continue;
			}
		bot = j;
		while(nchar[j])j++;
		top = j - 1;
# ifdef DEBUG
                if (debug)
			{ 
			printf("State %d: (layout)\n", i);
			for(j=bot; j<=top;j++)
				{
				printf("  %o", nchar[j]);
				if (j%10==0) putchar('\n');
				}
			putchar('\n');
                        } 
# endif
		while(verify[omin+ZCH]) omin++;
		startup = omin;
# ifdef DEBUG
		if (debug)  printf("bot,top %d, %d startup begins %d\n",bot,top,startup);
# endif
		if(chset){
			do {
				startup += 1;
				if(startup > outsize - ZCH)
					error("output table overflow");
				for(j = bot; j<= top; j++){
					k=startup+ctable[nchar[j]];
					if(verify[k])break;
					}
				} while (j <= top);
# ifdef DEBUG
		if (debug)  printf(" startup will be %d\n",startup);
# endif
			/* have found place */
			for(j = bot; j<= top; j++){
				k = startup + ctable[nchar[j]];
				if (ctable[nchar[j]]<=0)
				 printf("j %d nunsigned char %d ctable.nch %d\n",j,nchar[j],ctable[nchar[k]]);
				verify[k] = i+1;			/* state number + 1*/
				advance[k] = nexts[j+1]+1;		/* state number + 1*/
				if(yytop < k) yytop = k;
				}
			}
		else {
			do {
				startup += 1;
				if(startup > outsize - ZCH)
					error("output table overflow");
				for(j = bot; j<= top; j++){
					k = startup + nchar[j];
					if(verify[k])break;
					}
				} while (j <= top);
			/* have found place */
# ifdef DEBUG
		if (debug)  printf(" startup going to be %d\n", startup);
# endif
			for(j = bot; j<= top; j++){
				k = startup + nchar[j];
				verify[k] = i+1;			/* state number + 1*/
				advance[k] = nexts[j+1]+1;		/* state number + 1*/
				if(yytop < k) yytop = k;
				}
			}
		stoff[i] = startup;
		}

	/* stoff[i] = offset into verify, advance for trans for state i */
	/* put out yywork */
	if(ratfor){
		fprintf(fout, "define YYTOPVAL %d\n", yytop);
		rprint(verify,"verif",yytop+1);
		rprint(advance,"advan",yytop+1);
 		shiftr(stoff, stnum); 
		rprint(stoff,"stoff",stnum+1);
 		shiftr(sfall, stnum); upone(sfall, stnum+1);
		rprint(sfall,"sfall",stnum+1);
		bprint(extra,"extra",casecount+1);
		bprint(match,"match",NCH);
 		shiftr(atable, stnum);
		rprint(atable,"atable",stnum+1);
		return;
		}
	/*
	 * Note: this will only work correctly if NCH happens to be one
	 * greater than the max value held by an unsigned char.
	 */
	fprintf(fout,"# define YYTYPE %s\n",stnum+1 >= NCH ? "int" : "unsigned char");
	fprintf(fout,"struct yywork { YYTYPE verify, advance; } yycrank[] = {\n");
	for(i=0;i<=yytop;i+=4){
		for(j=0;j<4;j++){
			k = i+j;
			if(verify[k])
				fprintf(fout,"%d,%d,\t",verify[k],advance[k]);
			else
				fprintf(fout,"0,0,\t");
			}
		putc('\n',fout);
		}
	fprintf(fout,"0,0};\n");

	/* put out yysvec */

	fprintf(fout,"struct yysvf yysvec[] = {\n");
	fprintf(fout,"0,\t0,\t0,\n");
	for(i=0;i<=stnum;i++){	/* for each state */
		if(cpackflg[i])stoff[i] = -stoff[i];
		fprintf(fout,"yycrank+%d,\t",stoff[i]);
		if(sfall[i] != -1)
			fprintf(fout,"yysvec+%d,\t", sfall[i]+1);	/* state + 1 */
		else fprintf(fout,"0,\t\t");
		if(atable[i] != -1)
			fprintf(fout,"yyvstop+%d,",atable[i]);
		else fprintf(fout,"0,\t");
# ifdef DEBUG
		fprintf(fout,"\t\t/* state %d */",i);
# endif
		putc('\n',fout);
		}
	fprintf(fout,"0,\t0,\t0};\n");

	/* put out yymatch */
	
	fprintf(fout,"struct yywork *yytop = yycrank+%d;\n",yytop);
	fprintf(fout,"struct yysvf *yybgin = yysvec+1;\n");
	if(optim){
		fprintf(fout,"int  yymatch[] = {\n");
		if (chset==0) /* no chset, put out in normal order */
			{
			for(i=0; i<NCH; i+=8){
				for(j=0; j<8; j++){
					int fbch;
					fbch = match[i+j];
					if(printable(fbch) && fbch != '\'' && fbch != '\\')
						fprintf(fout,"'%c' ,",fbch);
					else fprintf(fout,"0%-3o,",fbch);
					}
				putc('\n',fout);
				}
			}
		else
			{
			int *fbarr;
			fbarr = (int *)myalloc(2*NCH, sizeof(*fbarr));
			if (fbarr==0)
				error("No space for unsigned char table reverse",0);
			for(i=0; i<ZCH; i++)
				fbarr[i]=0;
			for(i=0; i<NCH; i++)
				fbarr[ctable[i]] = ctable[match[i]];
			for(i=0; i<ZCH; i+=8)
				{
				for(j=0; j<8; j++)
					fprintf(fout, "0%-3o,",fbarr[i+j]);
				putc('\n',fout);
				}
			cfree((unsigned char *)fbarr, 2*NCH, 1);
			}
		fprintf(fout,"0};\n");
		}
	/* put out yyextra */
	fprintf(fout,"unsigned char yyextra[] = {\n");
	for(i=0;i<casecount;i+=8){
		for(j=0;j<8;j++)
			fprintf(fout, "%d,", i+j<NACTIONS ?
				extra[i+j] : 0);
		putc('\n',fout);
		}
	fprintf(fout,"0};\n");
	return;
	}
rprint(a,s,n)
  unsigned char *s;
  int *a, n; {
	register int i;
	fprintf(fout,"block data\n");
	fprintf(fout,"common /L%s/ %s\n",s,s);
	fprintf(fout,"define S%s %d\n",s,n);
	fprintf(fout,"integer %s (S%s)\n",s,s);
	for(i=1; i<=n; i++)
		{
		if (i%8==1) fprintf(fout, "data ");
		fprintf(fout, "%s (%d)/%d/",s,i,a[i]);
		fprintf(fout, (i%8 && i<n) ? ", " : "\n");
		}
	fprintf(fout,"end\n");
	}
shiftr(a, n)
	int *a;
{
int i;
for(i=n; i>=0; i--)
	a[i+1]=a[i];
}
upone(a,n)
	int *a;
{
int i;
for(i=0; i<=n ; i++)
	a[i]++;
}
bprint(a,s,n)
 unsigned char *s,  *a;
 int  n; {
	register int i, j, k;
	fprintf(fout,"block data\n");
	fprintf(fout,"common /L%s/ %s\n",s,s);
	fprintf(fout,"define S%s %d\n",s,n);
	fprintf(fout,"integer %s (S%s)\n",s,s);
	for(i=1;i<n;i+=8){
		fprintf(fout,"data %s (%d)/%d/",s,i,a[i]);
		for(j=1;j<8;j++){
			k = i+j;
			if(k < n)fprintf(fout,", %s (%d)/%d/",s,k,a[k]);
			}
		putc('\n',fout);
		}
	fprintf(fout,"end\n");
	}
# ifdef PP
padd(array,n)
  int **array;
  int n; {
	register int i, *j, k;
	array[n] = nxtpos;
	if(count == 0){
		*nxtpos++ = 0;
		return;
		}
	for(i=tptr-1;i>=0;i--){
		j = array[i];
		if(j && *j++ == count){
			for(k=0;k<count;k++)
				if(!tmpstat[*j++])break;
			if(k >= count){
				array[n] = array[i];
				return;
				}
			}
		}
	add(array,n);
	return;
	}
# endif
