| # 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 |