967 lines
21 KiB
C
967 lines
21 KiB
C
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
|
|
/* Copyright (c) 1988 AT&T */
|
|
/* All Rights Reserved */
|
|
|
|
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
|
|
/* UNIX System Laboratories, Inc. */
|
|
/* The copyright notice above does not evidence any */
|
|
/* actual or intended publication of such source code. */
|
|
|
|
#ident "@(#)lex:sub2.c 1.10"
|
|
/* sub2.c */
|
|
# include "ldefs.c"
|
|
void
|
|
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){
|
|
(void)printf("ccl %d: %d",v,*p++);
|
|
while(*p)
|
|
(void)printf(", %d",*p++);
|
|
(void) 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 */
|
|
(void)printf("pos\tchars\n");
|
|
for(i=0;i<tptr;i++)
|
|
if(p=foll[i]){
|
|
j = *p++;
|
|
if(j >= 1){
|
|
(void)printf("%d:\t%d",i,*p++);
|
|
for(k=2;k<=j;k++)
|
|
(void)printf(", %d",*p++);
|
|
(void) putchar('\n');
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
# endif
|
|
add(array,n)
|
|
int **array;
|
|
int n; {
|
|
register int i, *temp;
|
|
register 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;
|
|
}
|
|
void
|
|
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){
|
|
(void)fprintf(fout,"blockdata\n");
|
|
(void)fprintf(fout,"common /Lvstop/ vstop\n");
|
|
(void)fprintf(fout,"define Svstop %d\n",nstates+1);
|
|
(void)fprintf(fout,"integer vstop(Svstop)\n");
|
|
}
|
|
else (void)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)
|
|
(void)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){
|
|
(void)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;
|
|
(void)printf("\n\t");
|
|
}
|
|
}
|
|
(void) 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 char *temp, *tz;
|
|
int *pos, i, *f, num, curpos, number;
|
|
/* state to goto from state s on 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 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 */
|
|
/* nchar 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 += (long) 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 char */
|
|
# ifdef DEBUG
|
|
if(debug) (void)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 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)(void)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;
|
|
(void)printf("State %d:\n",s);
|
|
p = state[s];
|
|
i = *p++;
|
|
if(i == 0) return;
|
|
(void)printf("%4d",*p++);
|
|
for(j = 1; j<i; j++){
|
|
(void)printf(", %4d",*p++);
|
|
if(j%30 == 0)(void) putchar('\n');
|
|
}
|
|
(void) putchar('\n');
|
|
return;
|
|
}
|
|
# endif
|
|
member(d,t)
|
|
int d;
|
|
char *t; {
|
|
register int c;
|
|
register 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;
|
|
(void)printf("State %d:",i);
|
|
/* print actions, if any */
|
|
t = atable[i];
|
|
if(t != -1)(void)printf(" final");
|
|
(void) putchar('\n');
|
|
if(cpackflg[i] == TRUE)(void)printf("backup char in use\n");
|
|
if(sfall[i] != -1)(void)printf("fall back state %d\n",sfall[i]);
|
|
p = gotof[i];
|
|
if(p == -1) return;
|
|
(void)printf("(%d transitions)\n",nexts[p]);
|
|
while(nchar[p]){
|
|
charc = 0;
|
|
if(nexts[p+1] >= 0)
|
|
(void)printf("%d\t",nexts[p+1]);
|
|
else (void)printf("err\t");
|
|
allprint(nchar[p++]);
|
|
while(nexts[p] == nexts[p+1] && nchar[p]){
|
|
if(charc > LINESIZE){
|
|
charc = 0;
|
|
(void)printf("\n\t");
|
|
}
|
|
allprint(nchar[p++]);
|
|
}
|
|
(void) putchar('\n');
|
|
}
|
|
(void) 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[300], k, neg[300], n;
|
|
k = 0;
|
|
n = 0;
|
|
p = state[s];
|
|
cnt = *p++;
|
|
if(cnt > 300)
|
|
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) (void)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)(void)fprintf(fout,"/* actions for state %d */",s);
|
|
# endif
|
|
(void) 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)
|
|
(void)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)(void)printf("%d ",neg[i]);
|
|
# endif
|
|
}
|
|
# ifdef DEBUG
|
|
if(debug)(void) 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;
|
|
(void)printf("char class intersection\n");
|
|
for(i=0; i< ccount; i++){
|
|
charc = 0;
|
|
(void)printf("class %d:\n\t",i);
|
|
for(j=1;j<NCH;j++)
|
|
if(cindex[j] == i){
|
|
allprint(j);
|
|
if(charc > LINESIZE){
|
|
(void)printf("\n\t");
|
|
charc = 0;
|
|
}
|
|
}
|
|
(void) putchar('\n');
|
|
}
|
|
charc = 0;
|
|
(void)printf("match:\n");
|
|
for(i=0;i<NCH;i++){
|
|
allprint(match[i]);
|
|
if(charc > LINESIZE){
|
|
(void) putchar('\n');
|
|
charc = 0;
|
|
}
|
|
}
|
|
(void) putchar('\n');
|
|
return;
|
|
}
|
|
# endif
|
|
void
|
|
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 char for new ccl i */
|
|
for(i = 1; i<NCH; i++)
|
|
match[i] = tab[cindex[i]];
|
|
return;
|
|
}
|
|
void
|
|
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;
|
|
# if DEBUG
|
|
if (debug)
|
|
{
|
|
(void)printf("State %d: (layout)\n", i);
|
|
for(j=bot; j<=top;j++)
|
|
{
|
|
(void)printf(" %o", nchar[j]);
|
|
if (j%10==0) (void) putchar('\n');
|
|
}
|
|
(void) putchar('\n');
|
|
}
|
|
# endif
|
|
while(verify[omin+ZCH]) omin++;
|
|
startup = omin;
|
|
# if DEBUG
|
|
if (debug) (void)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);
|
|
# if DEBUG
|
|
if (debug) (void)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)
|
|
(void)printf("j %d nchar %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 */
|
|
# if DEBUG
|
|
if (debug) (void)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){
|
|
(void)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;
|
|
}
|
|
(void)fprintf(fout,"# define YYTYPE %s\n",stnum+1 > NCH ? "int" : "unsigned char");
|
|
(void)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])
|
|
(void)fprintf(fout,"%d,%d,\t",verify[k],advance[k]);
|
|
else
|
|
(void)fprintf(fout,"0,0,\t");
|
|
}
|
|
(void) putc('\n',fout);
|
|
}
|
|
(void)fprintf(fout,"0,0};\n");
|
|
|
|
/* put out yysvec */
|
|
|
|
(void)fprintf(fout,"struct yysvf yysvec[] = {\n");
|
|
(void)fprintf(fout,"0,\t0,\t0,\n");
|
|
for(i=0;i<=stnum;i++){ /* for each state */
|
|
if(cpackflg[i])stoff[i] = -stoff[i];
|
|
(void)fprintf(fout,"yycrank+%d,\t",stoff[i]);
|
|
if(sfall[i] != -1)
|
|
(void)fprintf(fout,"yysvec+%d,\t", sfall[i]+1); /* state + 1 */
|
|
else (void)fprintf(fout,"0,\t\t");
|
|
if(atable[i] != -1)
|
|
(void)fprintf(fout,"yyvstop+%d,",atable[i]);
|
|
else (void)fprintf(fout,"0,\t");
|
|
# ifdef DEBUG
|
|
(void)fprintf(fout,"\t\t/* state %d */",i);
|
|
# endif
|
|
(void) putc('\n',fout);
|
|
}
|
|
(void)fprintf(fout,"0,\t0,\t0};\n");
|
|
|
|
/* put out yymatch */
|
|
|
|
(void)fprintf(fout,"struct yywork *yytop = yycrank+%d;\n",yytop);
|
|
(void)fprintf(fout,"struct yysvf *yybgin = yysvec+1;\n");
|
|
if(optim){
|
|
(void)fprintf(fout,"unsigned char 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 != '\\')
|
|
(void)fprintf(fout,"'%c' ,",fbch);
|
|
else (void)fprintf(fout,"0%-3o,",fbch);
|
|
}
|
|
(void) putc('\n',fout);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int *fbarr;
|
|
fbarr = (int *)myalloc(2*NCH, sizeof(*fbarr));
|
|
if (fbarr==0)
|
|
error("No space for 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++)
|
|
(void)fprintf(fout, "0%-3o,",fbarr[i+j]);
|
|
(void) putc('\n',fout);
|
|
}
|
|
cfree((char *)fbarr, 2*NCH, 1);
|
|
}
|
|
(void)fprintf(fout,"0};\n");
|
|
}
|
|
/* put out yyextra */
|
|
(void)fprintf(fout,"char yyextra[] = {\n");
|
|
for(i=0;i<casecount;i+=8){
|
|
for(j=0;j<8;j++)
|
|
(void)fprintf(fout, "%d,", i+j<NACTIONS ?
|
|
extra[i+j] : 0);
|
|
(void) putc('\n',fout);
|
|
}
|
|
(void)fprintf(fout,"0};\n");
|
|
return;
|
|
}
|
|
rprint(a,s,n)
|
|
char *s;
|
|
int *a, n; {
|
|
register int i;
|
|
(void)fprintf(fout,"block data\n");
|
|
(void)fprintf(fout,"common /L%s/ %s\n",s,s);
|
|
(void)fprintf(fout,"define S%s %d\n",s,n);
|
|
(void)fprintf(fout,"integer %s (S%s)\n",s,s);
|
|
for(i=1; i<=n; i++)
|
|
{
|
|
if (i%8==1) (void)fprintf(fout, "data ");
|
|
(void)fprintf(fout, "%s (%d)/%d/",s,i,a[i]);
|
|
(void)fprintf(fout, (i%8 && i<n) ? ", " : "\n");
|
|
}
|
|
(void)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)
|
|
char *s, *a;
|
|
int n; {
|
|
register int i, j, k;
|
|
(void)fprintf(fout,"block data\n");
|
|
(void)fprintf(fout,"common /L%s/ %s\n",s,s);
|
|
(void)fprintf(fout,"define S%s %d\n",s,n);
|
|
(void)fprintf(fout,"integer %s (S%s)\n",s,s);
|
|
for(i=1;i<n;i+=8){
|
|
(void)fprintf(fout,"data %s (%d)/%d/",s,i,a[i]);
|
|
for(j=1;j<8;j++){
|
|
k = i+j;
|
|
if(k < n)(void)fprintf(fout,", %s (%d)/%d/",s,k,a[k]);
|
|
}
|
|
(void) putc('\n',fout);
|
|
}
|
|
(void)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
|