Blob


1 # include "ldefs.h"
2 void
3 cfoll(int v)
4 {
5 int i,j,k;
6 uchar *p;
7 i = name[v];
8 if(i < NCH) i = 1; /* character */
9 switch(i){
10 case 1: case RSTR: case RCCL: case RNCCL: case RNULLS:
11 for(j=0;j<tptr;j++)
12 tmpstat[j] = FALSE;
13 count = 0;
14 follow(v);
15 # ifdef PP
16 padd(foll,v); /* packing version */
17 # endif
18 # ifndef PP
19 add(foll,v); /* no packing version */
20 # endif
21 if(i == RSTR) cfoll(left[v]);
22 else if(i == RCCL || i == RNCCL){ /* compress ccl list */
23 for(j=1; j<NCH;j++)
24 symbol[j] = (i==RNCCL);
25 p = ptr[v];
26 while(*p)
27 symbol[*p++] = (i == RCCL);
28 p = pcptr;
29 for(j=1;j<NCH;j++)
30 if(symbol[j]){
31 for(k=0;p+k < pcptr; k++)
32 if(cindex[j] == *(p+k))
33 break;
34 if(p+k >= pcptr)*pcptr++ = cindex[j];
35 }
36 *pcptr++ = 0;
37 if(pcptr > pchar + pchlen)
38 error("Too many packed character classes");
39 ptr[v] = p;
40 name[v] = RCCL; /* RNCCL eliminated */
41 # ifdef DEBUG
42 if(debug && *p){
43 print("ccl %d: %d",v,*p++);
44 while(*p)
45 print(", %d",*p++);
46 print("\n");
47 }
48 # endif
49 }
50 break;
51 case CARAT:
52 cfoll(left[v]);
53 break;
54 case STAR: case PLUS: case QUEST: case RSCON:
55 cfoll(left[v]);
56 break;
57 case BAR: case RCAT: case DIV: case RNEWE:
58 cfoll(left[v]);
59 cfoll(right[v]);
60 break;
61 # ifdef DEBUG
62 case FINAL:
63 case S1FINAL:
64 case S2FINAL:
65 break;
66 default:
67 warning("bad switch cfoll %d",v);
68 # endif
69 }
70 }
72 # ifdef DEBUG
73 void
74 pfoll(void)
75 {
76 int i,k,*p;
77 int j;
78 /* print sets of chars which may follow positions */
79 print("pos\tchars\n");
80 for(i=0;i<tptr;i++)
81 if(p=foll[i]){
82 j = *p++;
83 if(j >= 1){
84 print("%d:\t%d",i,*p++);
85 for(k=2;k<=j;k++)
86 print(", %d",*p++);
87 print("\n");
88 }
89 }
90 }
91 # endif
93 void
94 add(int **array, int n)
95 {
96 int i, *temp;
97 uchar *ctemp;
99 temp = nxtpos;
100 ctemp = tmpstat;
101 array[n] = nxtpos; /* note no packing is done in positions */
102 *temp++ = count;
103 for(i=0;i<tptr;i++)
104 if(ctemp[i] == TRUE)
105 *temp++ = i;
106 nxtpos = temp;
107 if(nxtpos >= positions+maxpos)
108 error("Too many positions %s",(maxpos== MAXPOS?"\nTry using %p num":""));
109 return;
112 void
113 follow(int v)
115 int p;
116 if(v >= tptr-1)return;
117 p = parent[v];
118 if(p == 0) return;
119 switch(name[p]){
120 /* will not be CHAR RNULLS FINAL S1FINAL S2FINAL RCCL RNCCL */
121 case RSTR:
122 if(tmpstat[p] == FALSE){
123 count++;
124 tmpstat[p] = TRUE;
126 break;
127 case STAR: case PLUS:
128 first(v);
129 follow(p);
130 break;
131 case BAR: case QUEST: case RNEWE:
132 follow(p);
133 break;
134 case RCAT: case DIV:
135 if(v == left[p]){
136 if(nullstr[right[p]])
137 follow(p);
138 first(right[p]);
140 else follow(p);
141 break;
142 case RSCON: case CARAT:
143 follow(p);
144 break;
145 # ifdef DEBUG
146 default:
147 warning("bad switch follow %d",p);
148 # endif
152 void
153 first(int v) /* calculate set of positions with v as root which can be active initially */
155 int i;
156 uchar *p;
157 i = name[v];
158 if(i < NCH)i = 1;
159 switch(i){
160 case 1: case RCCL: case RNCCL: case RNULLS: case FINAL: case S1FINAL: case S2FINAL:
161 if(tmpstat[v] == FALSE){
162 count++;
163 tmpstat[v] = TRUE;
165 break;
166 case BAR: case RNEWE:
167 first(left[v]);
168 first(right[v]);
169 break;
170 case CARAT:
171 if(stnum % 2 == 1)
172 first(left[v]);
173 break;
174 case RSCON:
175 i = stnum/2 +1;
176 p = (uchar*)right[v];
177 while(*p)
178 if(*p++ == i){
179 first(left[v]);
180 break;
182 break;
183 case STAR: case QUEST: case PLUS: case RSTR:
184 first(left[v]);
185 break;
186 case RCAT: case DIV:
187 first(left[v]);
188 if(nullstr[left[v]])
189 first(right[v]);
190 break;
191 # ifdef DEBUG
192 default:
193 warning("bad switch first %d",v);
194 # endif
198 void
199 cgoto(void)
201 int i, j, s;
202 int npos, curpos, n;
203 int tryit;
204 uchar tch[NCH];
205 int tst[NCH];
206 uchar *q;
208 /* generate initial state, for each start condition */
209 Bprint(&fout,"int yyvstop[] = {\n0,\n");
210 while(stnum < 2 || stnum/2 < sptr){
211 for(i = 0; i<tptr; i++) tmpstat[i] = 0;
212 count = 0;
213 if(tptr > 0)first(tptr-1);
214 add(state,stnum);
215 # ifdef DEBUG
216 if(debug){
217 if(stnum > 1)
218 print("%s:\n",sname[stnum/2]);
219 pstate(stnum);
221 # endif
222 stnum++;
224 stnum--;
225 /* even stnum = might not be at line begin */
226 /* odd stnum = must be at line begin */
227 /* even states can occur anywhere, odd states only at line begin */
228 for(s = 0; s <= stnum; s++){
229 tryit = FALSE;
230 cpackflg[s] = FALSE;
231 sfall[s] = -1;
232 acompute(s);
233 for(i=0;i<NCH;i++) symbol[i] = 0;
234 npos = *state[s];
235 for(i = 1; i<=npos; i++){
236 curpos = *(state[s]+i);
237 if(name[curpos] < NCH) symbol[name[curpos]] = TRUE;
238 else switch(name[curpos]){
239 case RCCL:
240 tryit = TRUE;
241 q = ptr[curpos];
242 while(*q){
243 for(j=1;j<NCH;j++)
244 if(cindex[j] == *q)
245 symbol[j] = TRUE;
246 q++;
248 break;
249 case RSTR:
250 symbol[right[curpos]] = TRUE;
251 break;
252 # ifdef DEBUG
253 case RNULLS:
254 case FINAL:
255 case S1FINAL:
256 case S2FINAL:
257 break;
258 default:
259 warning("bad switch cgoto %d state %d",curpos,s);
260 break;
261 # endif
264 # ifdef DEBUG
265 if(debug){
266 print("State %d transitions on:\n\t",s);
267 charc = 0;
268 for(i = 1; i<NCH; i++){
269 if(symbol[i]) allprint(i);
270 if(charc > LINESIZE){
271 charc = 0;
272 print("\n\t");
275 print("\n");
277 # endif
278 /* for each char, calculate next state */
279 n = 0;
280 for(i = 1; i<NCH; i++){
281 if(symbol[i]){
282 nextstate(s,i); /* executed for each state, transition pair */
283 xstate = notin(stnum);
284 if(xstate == -2) warning("bad state %d %o",s,i);
285 else if(xstate == -1){
286 if(stnum >= nstates)
287 error("Too many states %s",(nstates == NSTATES ? "\nTry using %n num":""));
288 add(state,++stnum);
289 # ifdef DEBUG
290 if(debug)pstate(stnum);
291 # endif
292 tch[n] = i;
293 tst[n++] = stnum;
294 } else { /* xstate >= 0 ==> state exists */
295 tch[n] = i;
296 tst[n++] = xstate;
300 tch[n] = 0;
301 tst[n] = -1;
302 /* pack transitions into permanent array */
303 if(n > 0) packtrans(s,tch,tst,n,tryit);
304 else gotof[s] = -1;
306 Bprint(&fout,"0};\n");
309 /* Beware -- 70% of total CPU time is spent in this subroutine -
310 if you don't believe me - try it yourself ! */
311 void
312 nextstate(int s, int c)
314 int j, *newpos;
315 uchar *temp, *tz;
316 int *pos, i, *f, num, curpos, number;
317 /* state to goto from state s on char c */
318 num = *state[s];
319 temp = tmpstat;
320 pos = state[s] + 1;
321 for(i = 0; i<num; i++){
322 curpos = *pos++;
323 j = name[curpos];
324 if(j < NCH && j == c
325 || j == RSTR && c == right[curpos]
326 || j == RCCL && member(c, ptr[curpos])){
327 f = foll[curpos];
328 number = *f;
329 newpos = f+1;
330 for(j=0;j<number;j++)
331 temp[*newpos++] = 2;
334 j = 0;
335 tz = temp + tptr;
336 while(temp < tz){
337 if(*temp == 2){
338 j++;
339 *temp++ = 1;
341 else *temp++ = 0;
343 count = j;
346 int
347 notin(int n)
348 { /* see if tmpstat occurs previously */
349 int *j,k;
350 uchar *temp;
351 int i;
353 if(count == 0)
354 return(-2);
355 temp = tmpstat;
356 for(i=n;i>=0;i--){ /* for each state */
357 j = state[i];
358 if(count == *j++){
359 for(k=0;k<count;k++)
360 if(!temp[*j++])break;
361 if(k >= count)
362 return(i);
365 return(-1);
368 void
369 packtrans(int st, uchar *tch, int *tst, int cnt, int tryit)
371 /* pack transitions into nchar, nexts */
372 /* nchar is terminated by '\0', nexts uses cnt, followed by elements */
373 /* gotof[st] = index into nchr, nexts for state st */
375 /* sfall[st] = t implies t is fall back state for st */
376 /* == -1 implies no fall back */
378 int i,j,k;
379 int cmin, cval, tcnt, diff, p, *ast;
380 uchar *ach;
381 int go[NCH], temp[NCH], c;
382 int swork[NCH];
383 uchar cwork[NCH];
384 int upper;
386 rcount += cnt;
387 cmin = -1;
388 cval = NCH;
389 ast = tst;
390 ach = tch;
391 /* try to pack transitions using ccl's */
392 if(tryit){ /* ccl's used */
393 for(i=1;i<NCH;i++){
394 go[i] = temp[i] = -1;
395 symbol[i] = 1;
397 for(i=0;i<cnt;i++){
398 go[tch[i]] = tst[i];
399 symbol[tch[i]] = 0;
401 for(i=0; i<cnt;i++){
402 c = match[tch[i]];
403 if(go[c] != tst[i] || c == tch[i])
404 temp[tch[i]] = tst[i];
406 /* fill in error entries */
407 for(i=1;i<NCH;i++)
408 if(symbol[i]) temp[i] = -2; /* error trans */
409 /* count them */
410 k = 0;
411 for(i=1;i<NCH;i++)
412 if(temp[i] != -1)k++;
413 if(k <cnt){ /* compress by char */
414 # ifdef DEBUG
415 if(debug) print("use compression %d, %d vs %d\n",st,k,cnt);
416 # endif
417 k = 0;
418 for(i=1;i<NCH;i++)
419 if(temp[i] != -1){
420 cwork[k] = i;
421 swork[k++] = (temp[i] == -2 ? -1 : temp[i]);
423 cwork[k] = 0;
424 # ifdef PC
425 ach = cwork;
426 ast = swork;
427 cnt = k;
428 cpackflg[st] = TRUE;
429 # endif
432 for(i=0; i<st; i++){ /* get most similar state */
433 /* reject state with more transitions, state already represented by a third state,
434 and state which is compressed by char if ours is not to be */
435 if(sfall[i] != -1) continue;
436 if(cpackflg[st] == 1) if(!(cpackflg[i] == 1)) continue;
437 p = gotof[i];
438 if(p == -1) /* no transitions */ continue;
439 tcnt = nexts[p];
440 if(tcnt > cnt) continue;
441 diff = 0;
442 j = 0;
443 upper = p + tcnt;
444 while(ach[j] && p < upper){
445 while(ach[j] < nchar[p] && ach[j]){diff++; j++; }
446 if(ach[j] == 0)break;
447 if(ach[j] > nchar[p]){diff=NCH;break;}
448 /* ach[j] == nchar[p] */
449 if(ast[j] != nexts[++p] || ast[j] == -1 || (cpackflg[st] && ach[j] != match[ach[j]]))diff++;
450 j++;
452 while(ach[j]){
453 diff++;
454 j++;
456 if(p < upper)diff = NCH;
457 if(diff < cval && diff < tcnt){
458 cval = diff;
459 cmin = i;
460 if(cval == 0)break;
463 /* cmin = state "most like" state st */
464 # ifdef DEBUG
465 if(debug)print("select st %d for st %d diff %d\n",cmin,st,cval);
466 # endif
467 # ifdef PS
468 if(cmin != -1){ /* if we can use st cmin */
469 gotof[st] = nptr;
470 k = 0;
471 sfall[st] = cmin;
472 p = gotof[cmin]+1;
473 j = 0;
474 while(ach[j]){
475 /* if cmin has a transition on c, then so will st */
476 /* st may be "larger" than cmin, however */
477 while(ach[j] < nchar[p-1] && ach[j]){
478 k++;
479 nchar[nptr] = ach[j];
480 nexts[++nptr] = ast[j];
481 j++;
483 if(nchar[p-1] == 0)break;
484 if(ach[j] > nchar[p-1]){
485 warning("bad transition %d %d",st,cmin);
486 goto nopack;
488 /* ach[j] == nchar[p-1] */
489 if(ast[j] != nexts[p] || ast[j] == -1 || (cpackflg[st] && ach[j] != match[ach[j]])){
490 k++;
491 nchar[nptr] = ach[j];
492 nexts[++nptr] = ast[j];
494 p++;
495 j++;
497 while(ach[j]){
498 nchar[nptr] = ach[j];
499 nexts[++nptr] = ast[j++];
500 k++;
502 nexts[gotof[st]] = cnt = k;
503 nchar[nptr++] = 0;
504 } else {
505 # endif
506 nopack:
507 /* stick it in */
508 gotof[st] = nptr;
509 nexts[nptr] = cnt;
510 for(i=0;i<cnt;i++){
511 nchar[nptr] = ach[i];
512 nexts[++nptr] = ast[i];
514 nchar[nptr++] = 0;
515 # ifdef PS
517 # endif
518 if(cnt < 1){
519 gotof[st] = -1;
520 nptr--;
521 } else
522 if(nptr > ntrans)
523 error("Too many transitions %s",(ntrans==NTRANS?"\nTry using %a num":""));
526 # ifdef DEBUG
527 void
528 pstate(int s)
530 int *p,i,j;
531 print("State %d:\n",s);
532 p = state[s];
533 i = *p++;
534 if(i == 0) return;
535 print("%4d",*p++);
536 for(j = 1; j<i; j++){
537 print(", %4d",*p++);
538 if(j%30 == 0)print("\n");
540 print("\n");
541 return;
543 # endif
545 int
546 member(int d, uchar *t)
548 int c;
549 uchar *s;
551 c = d;
552 s = t;
553 c = cindex[c];
554 while(*s)
555 if(*s++ == c) return(1);
556 return(0);
559 # ifdef DEBUG
560 void
561 stprt(int i)
563 int p, t;
565 print("State %d:",i);
566 /* print actions, if any */
567 t = atable[i];
568 if(t != -1)print(" final");
569 print("\n");
570 if(cpackflg[i] == TRUE)print("backup char in use\n");
571 if(sfall[i] != -1)print("fall back state %d\n",sfall[i]);
572 p = gotof[i];
573 if(p == -1) return;
574 print("(%d transitions)\n",nexts[p]);
575 while(nchar[p]){
576 charc = 0;
577 if(nexts[p+1] >= 0)
578 print("%d\t",nexts[p+1]);
579 else print("err\t");
580 allprint(nchar[p++]);
581 while(nexts[p] == nexts[p+1] && nchar[p]){
582 if(charc > LINESIZE){
583 charc = 0;
584 print("\n\t");
586 allprint(nchar[p++]);
588 print("\n");
590 print("\n");
592 # endif
594 void
595 acompute(int s) /* compute action list = set of poss. actions */
597 int *p, i, j;
598 int cnt, m;
599 int temp[300], k, neg[300], n;
601 k = 0;
602 n = 0;
603 p = state[s];
604 cnt = *p++;
605 if(cnt > 300)
606 error("Too many positions for one state - acompute");
607 for(i=0;i<cnt;i++){
608 if(name[*p] == FINAL)temp[k++] = left[*p];
609 else if(name[*p] == S1FINAL){temp[k++] = left[*p];
610 if (left[*p] >= NACTIONS) error("Too many right contexts");
611 extra[left[*p]] = 1;
612 } else if(name[*p] == S2FINAL)neg[n++] = left[*p];
613 p++;
615 atable[s] = -1;
616 if(k < 1 && n < 1) return;
617 # ifdef DEBUG
618 if(debug) print("final %d actions:",s);
619 # endif
620 /* sort action list */
621 for(i=0; i<k; i++)
622 for(j=i+1;j<k;j++)
623 if(temp[j] < temp[i]){
624 m = temp[j];
625 temp[j] = temp[i];
626 temp[i] = m;
628 /* remove dups */
629 for(i=0;i<k-1;i++)
630 if(temp[i] == temp[i+1]) temp[i] = 0;
631 /* copy to permanent quarters */
632 atable[s] = aptr;
633 # ifdef DEBUG
634 Bprint(&fout,"/* actions for state %d */",s);
635 # endif
636 Bputc(&fout, '\n');
637 for(i=0;i<k;i++)
638 if(temp[i] != 0){
639 Bprint(&fout,"%d,\n",temp[i]);
640 # ifdef DEBUG
641 if(debug)
642 print("%d ",temp[i]);
643 # endif
644 aptr++;
646 for(i=0;i<n;i++){ /* copy fall back actions - all neg */
647 Bprint(&fout,"%d,\n",neg[i]);
648 aptr++;
649 # ifdef DEBUG
650 if(debug)print("%d ",neg[i]);
651 # endif
653 # ifdef DEBUG
654 if(debug)print("\n");
655 # endif
656 Bprint(&fout,"0,\n");
657 aptr++;
658 return;
661 # ifdef DEBUG
662 void
663 pccl(void) {
664 /* print character class sets */
665 int i, j;
667 print("char class intersection\n");
668 for(i=0; i< ccount; i++){
669 charc = 0;
670 print("class %d:\n\t",i);
671 for(j=1;j<NCH;j++)
672 if(cindex[j] == i){
673 allprint(j);
674 if(charc > LINESIZE){
675 print("\n\t");
676 charc = 0;
679 print("\n");
681 charc = 0;
682 print("match:\n");
683 for(i=0;i<NCH;i++){
684 allprint(match[i]);
685 if(charc > LINESIZE){
686 print("\n");
687 charc = 0;
690 print("\n");
691 return;
693 # endif
695 void
696 mkmatch(void)
698 int i;
699 uchar tab[NCH];
701 for(i=0; i<ccount; i++)
702 tab[i] = 0;
703 for(i=1;i<NCH;i++)
704 if(tab[cindex[i]] == 0)
705 tab[cindex[i]] = i;
706 /* tab[i] = principal char for new ccl i */
707 for(i = 1; i<NCH; i++)
708 match[i] = tab[cindex[i]];
709 return;
712 void
713 layout(void)
715 /* format and output final program's tables */
716 int i, j, k;
717 int top, bot, startup, omin;
719 for(i=0; i<outsize;i++)
720 verify[i] = advance[i] = 0;
721 omin = 0;
722 yytop = 0;
723 for(i=0; i<= stnum; i++){ /* for each state */
724 j = gotof[i];
725 if(j == -1){
726 stoff[i] = 0;
727 continue;
729 bot = j;
730 while(nchar[j])j++;
731 top = j - 1;
732 # ifdef DEBUG
733 if (debug) {
734 print("State %d: (layout)\n", i);
735 for(j=bot; j<=top;j++) {
736 print(" %o", nchar[j]);
737 if (j%10==0) print("\n");
739 print("\n");
741 # endif
742 while(verify[omin+NCH]) omin++;
743 startup = omin;
744 # ifdef DEBUG
745 if (debug) print("bot,top %d, %d startup begins %d\n",bot,top,startup);
746 # endif
747 do {
748 startup += 1;
749 if(startup > outsize - NCH)
750 error("output table overflow");
751 for(j = bot; j<= top; j++){
752 k = startup + nchar[j];
753 if(verify[k])break;
755 } while (j <= top);
756 /* have found place */
757 # ifdef DEBUG
758 if (debug) print(" startup going to be %d\n", startup);
759 # endif
760 for(j = bot; j<= top; j++){
761 k = startup + nchar[j];
762 verify[k] = i+1; /* state number + 1*/
763 advance[k] = nexts[j+1]+1; /* state number + 1*/
764 if(yytop < k) yytop = k;
766 stoff[i] = startup;
769 /* stoff[i] = offset into verify, advance for trans for state i */
770 /* put out yywork */
771 Bprint(&fout,"# define YYTYPE %s\n",stnum+1 >= NCH ? "int" : "Uchar");
772 Bprint(&fout,"struct yywork { YYTYPE verify, advance; } yycrank[] = {\n");
773 for(i=0;i<=yytop;i+=4){
774 for(j=0;j<4;j++){
775 k = i+j;
776 if(verify[k])
777 Bprint(&fout,"%d,%d,\t",verify[k],advance[k]);
778 else
779 Bprint(&fout,"0,0,\t");
781 Bputc(&fout, '\n');
783 Bprint(&fout,"0,0};\n");
785 /* put out yysvec */
787 Bprint(&fout,"struct yysvf yysvec[] = {\n");
788 Bprint(&fout,"0,\t0,\t0,\n");
789 for(i=0;i<=stnum;i++){ /* for each state */
790 if(cpackflg[i])stoff[i] = -stoff[i];
791 Bprint(&fout,"yycrank+%d,\t",stoff[i]);
792 if(sfall[i] != -1)
793 Bprint(&fout,"yysvec+%d,\t", sfall[i]+1); /* state + 1 */
794 else Bprint(&fout,"0,\t\t");
795 if(atable[i] != -1)
796 Bprint(&fout,"yyvstop+%d,",atable[i]);
797 else Bprint(&fout,"0,\t");
798 # ifdef DEBUG
799 Bprint(&fout,"\t\t/* state %d */",i);
800 # endif
801 Bputc(&fout, '\n');
803 Bprint(&fout,"0,\t0,\t0};\n");
805 /* put out yymatch */
807 Bprint(&fout,"struct yywork *yytop = yycrank+%d;\n",yytop);
808 Bprint(&fout,"struct yysvf *yybgin = yysvec+1;\n");
809 Bprint(&fout,"Uchar yymatch[] = {\n");
810 for(i=0; i<NCH; i+=8){
811 for(j=0; j<8; j++){
812 int fbch;
813 fbch = match[i+j];
814 if(isprint(fbch) && fbch != '\'' && fbch != '\\')
815 Bprint(&fout,"'%c' ,",fbch);
816 else Bprint(&fout,"0%-3o,",fbch);
818 Bputc(&fout, '\n');
820 Bprint(&fout,"0};\n");
821 /* put out yyextra */
822 Bprint(&fout,"Uchar yyextra[] = {\n");
823 for(i=0;i<casecount;i+=8){
824 for(j=0;j<8;j++)
825 Bprint(&fout, "%d,", i+j<NACTIONS ?
826 extra[i+j] : 0);
827 Bputc(&fout, '\n');
829 Bprint(&fout,"0};\n");
832 # ifdef PP
833 void
834 padd(int **array, int n)
836 int i, *j, k;
838 array[n] = nxtpos;
839 if(count == 0){
840 *nxtpos++ = 0;
841 return;
843 for(i=tptr-1;i>=0;i--){
844 j = array[i];
845 if(j && *j++ == count){
846 for(k=0;k<count;k++)
847 if(!tmpstat[*j++])break;
848 if(k >= count){
849 array[n] = array[i];
850 return;
854 add(array,n);
856 # endif