xref: /plan9/sys/src/cmd/lex/sub2.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
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 = (uchar *)left[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 				left[v] = (int)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 }
71 
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
92 
93 void
94 add(int **array, int n)
95 {
96 	int i, *temp;
97 	uchar *ctemp;
98 
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;
110 }
111 
112 void
113 follow(int v)
114 {
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;
125 			}
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]);
139 			}
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
149 	}
150 }
151 
152 void
153 first(int v)	/* calculate set of positions with v as root which can be active initially */
154 {
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;
164 			}
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;
181 				}
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
195 	}
196 }
197 
198 void
199 cgoto(void)
200 {
201 	int i, j, s;
202 	int npos, curpos, n;
203 	int tryit;
204 	uchar tch[NCH];
205 	int tst[NCH];
206 	uchar *q;
207 
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);
220 		}
221 # endif
222 		stnum++;
223 	}
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 = (uchar *)left[curpos];
242 				while(*q){
243 					for(j=1;j<NCH;j++)
244 						if(cindex[j] == *q)
245 							symbol[j] = TRUE;
246 					q++;
247 				}
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
262 			}
263 		}
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");
273 				}
274 			}
275 			print("\n");
276 		}
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;
297 				}
298 			}
299 		}
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;
305 	}
306 	Bprint(&fout,"0};\n");
307 }
308 
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)
313 {
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, (uchar *)left[curpos])){
327 			f = foll[curpos];
328 			number = *f;
329 			newpos = f+1;
330 			for(j=0;j<number;j++)
331 				temp[*newpos++] = 2;
332 		}
333 	}
334 	j = 0;
335 	tz = temp + tptr;
336 	while(temp < tz){
337 		if(*temp == 2){
338 			j++;
339 			*temp++ = 1;
340 		}
341 		else *temp++ = 0;
342 	}
343 	count = j;
344 }
345 
346 int
347 notin(int n)
348 {	/* see if tmpstat occurs previously */
349 	int *j,k;
350 	uchar *temp;
351 	int i;
352 
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);
363 		}
364 	}
365 	return(-1);
366 }
367 
368 void
369 packtrans(int st, uchar *tch, int *tst, int cnt, int tryit)
370 {
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 */
374 
375 	/* sfall[st] =  t implies t is fall back state for st */
376 	/*	        == -1 implies no fall back */
377 
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;
385 
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;
396 		}
397 		for(i=0;i<cnt;i++){
398 			go[tch[i]] = tst[i];
399 			symbol[tch[i]] = 0;
400 		}
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];
405 		}
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]);
422 				}
423 			cwork[k] = 0;
424 # ifdef PC
425 			ach = cwork;
426 			ast = swork;
427 			cnt = k;
428 			cpackflg[st] = TRUE;
429 # endif
430 		}
431 	}
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++;
451 		}
452 		while(ach[j]){
453 			diff++;
454 			j++;
455 		}
456 		if(p < upper)diff = NCH;
457 		if(diff < cval && diff < tcnt){
458 			cval = diff;
459 			cmin = i;
460 			if(cval == 0)break;
461 		}
462 	}
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++;
482 			}
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;
487 			}
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];
493 			}
494 			p++;
495 			j++;
496 		}
497 		while(ach[j]){
498 			nchar[nptr] = ach[j];
499 			nexts[++nptr] = ast[j++];
500 			k++;
501 		}
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];
513 		}
514 		nchar[nptr++] = 0;
515 # ifdef PS
516 	}
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":""));
524 }
525 
526 # ifdef DEBUG
527 void
528 pstate(int s)
529 {
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");
539 	}
540 	print("\n");
541 	return;
542 }
543 # endif
544 
545 int
546 member(int d, uchar *t)
547 {
548 	int c;
549 	uchar *s;
550 
551 	c = d;
552 	s = t;
553 	c = cindex[c];
554 	while(*s)
555 		if(*s++ == c) return(1);
556 	return(0);
557 }
558 
559 # ifdef DEBUG
560 void
561 stprt(int i)
562 {
563 	int p, t;
564 
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");
585 			}
586 			allprint(nchar[p++]);
587 		}
588 		print("\n");
589 	}
590 	print("\n");
591 }
592 # endif
593 
594 void
595 acompute(int s)	/* compute action list = set of poss. actions */
596 {
597 	int *p, i, j;
598 	int cnt, m;
599 	int temp[300], k, neg[300], n;
600 
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++;
614 	}
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;
627 			}
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++;
645 		}
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
652 	}
653 # ifdef DEBUG
654 	if(debug)print("\n");
655 # endif
656 	Bprint(&fout,"0,\n");
657 	aptr++;
658 	return;
659 }
660 
661 # ifdef DEBUG
662 void
663 pccl(void) {
664 	/* print character class sets */
665 	int i, j;
666 
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;
677 				}
678 			}
679 		print("\n");
680 	}
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;
688 		}
689 	}
690 	print("\n");
691 	return;
692 }
693 # endif
694 
695 void
696 mkmatch(void)
697 {
698 	int i;
699 	uchar tab[NCH];
700 
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;
710 }
711 
712 void
713 layout(void)
714 {
715 	/* format and output final program's tables */
716 	int i, j, k;
717 	int  top, bot, startup, omin;
718 
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;
728 			}
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");
738 			}
739 			print("\n");
740 		}
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;
754 			}
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;
765 		}
766 		stoff[i] = startup;
767 	}
768 
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");
780 		}
781 		Bputc(&fout, '\n');
782 	}
783 	Bprint(&fout,"0,0};\n");
784 
785 	/* put out yysvec */
786 
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');
802 	}
803 	Bprint(&fout,"0,\t0,\t0};\n");
804 
805 	/* put out yymatch */
806 
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);
817 		}
818 		Bputc(&fout, '\n');
819 	}
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');
828 	}
829 	Bprint(&fout,"0};\n");
830 }
831 
832 # ifdef PP
833 void
834 padd(int **array, int n)
835 {
836 	int i, *j, k;
837 
838 	array[n] = nxtpos;
839 	if(count == 0){
840 		*nxtpos++ = 0;
841 		return;
842 	}
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;
851 			}
852 		}
853 	}
854 	add(array,n);
855 }
856 # endif
857