|  | # include "ldefs.h" | 
|  | void | 
|  | cfoll(int v) | 
|  | { | 
|  | int i,j,k; | 
|  | uchar *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 = ptr[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"); | 
|  | ptr[v] = p; | 
|  | name[v] = RCCL;	/* RNCCL eliminated */ | 
|  | # ifdef DEBUG | 
|  | if(debug && *p){ | 
|  | print("ccl %d: %d",v,*p++); | 
|  | while(*p) | 
|  | print(", %d",*p++); | 
|  | print("\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 | 
|  | } | 
|  | } | 
|  |  | 
|  | # ifdef DEBUG | 
|  | void | 
|  | pfoll(void) | 
|  | { | 
|  | int i,k,*p; | 
|  | int j; | 
|  | /* print sets of chars which may follow positions */ | 
|  | print("pos\tchars\n"); | 
|  | for(i=0;i<tptr;i++) | 
|  | if(p=foll[i]){ | 
|  | j = *p++; | 
|  | if(j >= 1){ | 
|  | print("%d:\t%d",i,*p++); | 
|  | for(k=2;k<=j;k++) | 
|  | print(", %d",*p++); | 
|  | print("\n"); | 
|  | } | 
|  | } | 
|  | } | 
|  | # endif | 
|  |  | 
|  | void | 
|  | add(int **array, int n) | 
|  | { | 
|  | int i, *temp; | 
|  | uchar *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; | 
|  | } | 
|  |  | 
|  | void | 
|  | follow(int v) | 
|  | { | 
|  | 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 | 
|  | } | 
|  | } | 
|  |  | 
|  | void | 
|  | first(int v)	/* calculate set of positions with v as root which can be active initially */ | 
|  | { | 
|  | int i; | 
|  | uchar *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 = (uchar*)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 | 
|  | } | 
|  | } | 
|  |  | 
|  | void | 
|  | cgoto(void) | 
|  | { | 
|  | int i, j, s; | 
|  | int npos, curpos, n; | 
|  | int tryit; | 
|  | uchar tch[NCH]; | 
|  | int tst[NCH]; | 
|  | uchar *q; | 
|  |  | 
|  | /* generate initial state, for each start condition */ | 
|  | Bprint(&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) | 
|  | print("%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 = ptr[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){ | 
|  | print("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; | 
|  | print("\n\t"); | 
|  | } | 
|  | } | 
|  | print("\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; | 
|  | } | 
|  | Bprint(&fout,"0};\n"); | 
|  | } | 
|  |  | 
|  | /*	Beware -- 70% of total CPU time is spent in this subroutine - | 
|  | if you don't believe me - try it yourself ! */ | 
|  | void | 
|  | nextstate(int s, int c) | 
|  | { | 
|  | int j, *newpos; | 
|  | uchar *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, ptr[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; | 
|  | } | 
|  |  | 
|  | int | 
|  | notin(int n) | 
|  | {	/* see if tmpstat occurs previously */ | 
|  | int *j,k; | 
|  | uchar *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); | 
|  | } | 
|  |  | 
|  | void | 
|  | packtrans(int st, uchar *tch, int *tst, int cnt, int tryit) | 
|  | { | 
|  | /* 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 i,j,k; | 
|  | int cmin, cval, tcnt, diff, p, *ast; | 
|  | uchar *ach; | 
|  | int go[NCH], temp[NCH], c; | 
|  | int swork[NCH]; | 
|  | uchar cwork[NCH]; | 
|  | int upper; | 
|  |  | 
|  | rcount += cnt; | 
|  | cmin = -1; | 
|  | cval = NCH; | 
|  | ast = tst; | 
|  | ach = tch; | 
|  | /* try to pack transitions using ccl's */ | 
|  | 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) print("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; | 
|  | 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)print("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":"")); | 
|  | } | 
|  |  | 
|  | # ifdef DEBUG | 
|  | void | 
|  | pstate(int s) | 
|  | { | 
|  | int *p,i,j; | 
|  | print("State %d:\n",s); | 
|  | p = state[s]; | 
|  | i = *p++; | 
|  | if(i == 0) return; | 
|  | print("%4d",*p++); | 
|  | for(j = 1; j<i; j++){ | 
|  | print(", %4d",*p++); | 
|  | if(j%30 == 0)print("\n"); | 
|  | } | 
|  | print("\n"); | 
|  | return; | 
|  | } | 
|  | # endif | 
|  |  | 
|  | int | 
|  | member(int d, uchar *t) | 
|  | { | 
|  | int c; | 
|  | uchar *s; | 
|  |  | 
|  | c = d; | 
|  | s = t; | 
|  | c = cindex[c]; | 
|  | while(*s) | 
|  | if(*s++ == c) return(1); | 
|  | return(0); | 
|  | } | 
|  |  | 
|  | # ifdef DEBUG | 
|  | void | 
|  | stprt(int i) | 
|  | { | 
|  | int p, t; | 
|  |  | 
|  | print("State %d:",i); | 
|  | /* print actions, if any */ | 
|  | t = atable[i]; | 
|  | if(t != -1)print(" final"); | 
|  | print("\n"); | 
|  | if(cpackflg[i] == TRUE)print("backup char in use\n"); | 
|  | if(sfall[i] != -1)print("fall back state %d\n",sfall[i]); | 
|  | p = gotof[i]; | 
|  | if(p == -1) return; | 
|  | print("(%d transitions)\n",nexts[p]); | 
|  | while(nchar[p]){ | 
|  | charc = 0; | 
|  | if(nexts[p+1] >= 0) | 
|  | print("%d\t",nexts[p+1]); | 
|  | else print("err\t"); | 
|  | allprint(nchar[p++]); | 
|  | while(nexts[p] == nexts[p+1] && nchar[p]){ | 
|  | if(charc > LINESIZE){ | 
|  | charc = 0; | 
|  | print("\n\t"); | 
|  | } | 
|  | allprint(nchar[p++]); | 
|  | } | 
|  | print("\n"); | 
|  | } | 
|  | print("\n"); | 
|  | } | 
|  | # endif | 
|  |  | 
|  | void | 
|  | acompute(int s)	/* compute action list = set of poss. actions */ | 
|  | { | 
|  | 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) print("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 | 
|  | Bprint(&fout,"/* actions for state %d */",s); | 
|  | # endif | 
|  | Bputc(&fout, '\n'); | 
|  | for(i=0;i<k;i++) | 
|  | if(temp[i] != 0){ | 
|  | Bprint(&fout,"%d,\n",temp[i]); | 
|  | # ifdef DEBUG | 
|  | if(debug) | 
|  | print("%d ",temp[i]); | 
|  | # endif | 
|  | aptr++; | 
|  | } | 
|  | for(i=0;i<n;i++){		/* copy fall back actions - all neg */ | 
|  | Bprint(&fout,"%d,\n",neg[i]); | 
|  | aptr++; | 
|  | # ifdef DEBUG | 
|  | if(debug)print("%d ",neg[i]); | 
|  | # endif | 
|  | } | 
|  | # ifdef DEBUG | 
|  | if(debug)print("\n"); | 
|  | # endif | 
|  | Bprint(&fout,"0,\n"); | 
|  | aptr++; | 
|  | return; | 
|  | } | 
|  |  | 
|  | # ifdef DEBUG | 
|  | void | 
|  | pccl(void) { | 
|  | /* print character class sets */ | 
|  | int i, j; | 
|  |  | 
|  | print("char class intersection\n"); | 
|  | for(i=0; i< ccount; i++){ | 
|  | charc = 0; | 
|  | print("class %d:\n\t",i); | 
|  | for(j=1;j<NCH;j++) | 
|  | if(cindex[j] == i){ | 
|  | allprint(j); | 
|  | if(charc > LINESIZE){ | 
|  | print("\n\t"); | 
|  | charc = 0; | 
|  | } | 
|  | } | 
|  | print("\n"); | 
|  | } | 
|  | charc = 0; | 
|  | print("match:\n"); | 
|  | for(i=0;i<NCH;i++){ | 
|  | allprint(match[i]); | 
|  | if(charc > LINESIZE){ | 
|  | print("\n"); | 
|  | charc = 0; | 
|  | } | 
|  | } | 
|  | print("\n"); | 
|  | return; | 
|  | } | 
|  | # endif | 
|  |  | 
|  | void | 
|  | mkmatch(void) | 
|  | { | 
|  | int i; | 
|  | uchar 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(void) | 
|  | { | 
|  | /* format and output final program's tables */ | 
|  | int i, j, k; | 
|  | int  top, bot, startup, omin; | 
|  |  | 
|  | 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) { | 
|  | print("State %d: (layout)\n", i); | 
|  | for(j=bot; j<=top;j++) { | 
|  | print("  %o", nchar[j]); | 
|  | if (j%10==0) print("\n"); | 
|  | } | 
|  | print("\n"); | 
|  | } | 
|  | # endif | 
|  | while(verify[omin+NCH]) omin++; | 
|  | startup = omin; | 
|  | # ifdef DEBUG | 
|  | if (debug) print("bot,top %d, %d startup begins %d\n",bot,top,startup); | 
|  | # endif | 
|  | do { | 
|  | startup += 1; | 
|  | if(startup > outsize - NCH) | 
|  | 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) print(" 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 */ | 
|  | Bprint(&fout,"# define YYTYPE %s\n",stnum+1 >= NCH ? "int" : "Uchar"); | 
|  | Bprint(&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]) | 
|  | Bprint(&fout,"%d,%d,\t",verify[k],advance[k]); | 
|  | else | 
|  | Bprint(&fout,"0,0,\t"); | 
|  | } | 
|  | Bputc(&fout, '\n'); | 
|  | } | 
|  | Bprint(&fout,"0,0};\n"); | 
|  |  | 
|  | /* put out yysvec */ | 
|  |  | 
|  | Bprint(&fout,"struct yysvf yysvec[] = {\n"); | 
|  | Bprint(&fout,"0,\t0,\t0,\n"); | 
|  | for(i=0;i<=stnum;i++){	/* for each state */ | 
|  | if(cpackflg[i])stoff[i] = -stoff[i]; | 
|  | Bprint(&fout,"yycrank+%d,\t",stoff[i]); | 
|  | if(sfall[i] != -1) | 
|  | Bprint(&fout,"yysvec+%d,\t", sfall[i]+1);	/* state + 1 */ | 
|  | else Bprint(&fout,"0,\t\t"); | 
|  | if(atable[i] != -1) | 
|  | Bprint(&fout,"yyvstop+%d,",atable[i]); | 
|  | else Bprint(&fout,"0,\t"); | 
|  | # ifdef DEBUG | 
|  | Bprint(&fout,"\t\t/* state %d */",i); | 
|  | # endif | 
|  | Bputc(&fout, '\n'); | 
|  | } | 
|  | Bprint(&fout,"0,\t0,\t0};\n"); | 
|  |  | 
|  | /* put out yymatch */ | 
|  |  | 
|  | Bprint(&fout,"struct yywork *yytop = yycrank+%d;\n",yytop); | 
|  | Bprint(&fout,"struct yysvf *yybgin = yysvec+1;\n"); | 
|  | Bprint(&fout,"Uchar yymatch[] = {\n"); | 
|  | for(i=0; i<NCH; i+=8){ | 
|  | for(j=0; j<8; j++){ | 
|  | int fbch; | 
|  | fbch = match[i+j]; | 
|  | if(isprint(fbch) && fbch != '\'' && fbch != '\\') | 
|  | Bprint(&fout,"'%c' ,",fbch); | 
|  | else Bprint(&fout,"0%-3o,",fbch); | 
|  | } | 
|  | Bputc(&fout, '\n'); | 
|  | } | 
|  | Bprint(&fout,"0};\n"); | 
|  | /* put out yyextra */ | 
|  | Bprint(&fout,"Uchar yyextra[] = {\n"); | 
|  | for(i=0;i<casecount;i+=8){ | 
|  | for(j=0;j<8;j++) | 
|  | Bprint(&fout, "%d,", i+j<NACTIONS ? | 
|  | extra[i+j] : 0); | 
|  | Bputc(&fout, '\n'); | 
|  | } | 
|  | Bprint(&fout,"0};\n"); | 
|  | } | 
|  |  | 
|  | # ifdef PP | 
|  | void | 
|  | padd(int **array, int n) | 
|  | { | 
|  | 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); | 
|  | } | 
|  | # endif |