xref: /illumos-gate/usr/src/cmd/sgs/lex/common/sub1.c (revision 8eea8e29)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.
24  * All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 /*	Copyright (c) 1988 AT&T	*/
29 /*	All Rights Reserved	*/
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 #include "ldefs.c"
34 #include <limits.h>
35 
36 /*
37  * return next line of input, throw away trailing '\n'
38  * and also throw away trailing blanks (spaces and tabs)
39  * returns 0 if eof is had immediately
40  */
41 
42 CHR *
43 getl(CHR *p)
44 {
45 	int c;
46 	CHR *s, *t, *u;
47 	int blank = 0;
48 
49 	t = s = p;
50 	while (((c = gch()) != 0) && c != '\n') {
51 		if (t >= &p[BUF_SIZ])
52 			error("definitions too long");
53 		if (c == ' ' || c == '\t') {
54 		    if (!blank) {
55 			blank = 1;
56 			u = t;
57 		    }
58 		} else
59 			blank = 0;
60 
61 		*t++ = c;
62 	}
63 	if (blank)
64 		*u = 0;
65 	else
66 		*t = 0;
67 
68 	if (c == 0 && s == t)
69 		return ((CHR *) 0);
70 	prev = '\n';
71 	pres = '\n';
72 	return (s);
73 }
74 
75 int
76 space(int ch)
77 {
78 	switch (ch) {
79 		case ' ':
80 		case '\t':
81 		case '\n':
82 			return (1);
83 	}
84 	return (0);
85 }
86 
87 int
88 digit(int c)
89 {
90 	return (c >= '0' && c <= '9');
91 }
92 
93 /* VARARGS1 */
94 void
95 error(s, p, d)
96 char *s;
97 int p, d;
98 {
99 	/* if(!eof) */
100 	if (!yyline)
101 		(void) fprintf(errorf, "Command line: ");
102 	else {
103 		(void) fprintf(errorf,
104 			!no_input ? "" : "\"%s\":", sargv[optind]);
105 		(void) fprintf(errorf, "line %d: ", yyline);
106 	}
107 	(void) fprintf(errorf, "Error: ");
108 	(void) fprintf(errorf, s, p, d);
109 	(void) putc('\n', errorf);
110 	if (fatal)
111 		error_tail();
112 }
113 
114 void
115 error_tail(void)
116 {
117 #ifdef DEBUG
118 	if (debug && sect != ENDSECTION) {
119 		sect1dump();
120 		sect2dump();
121 	}
122 #endif
123 
124 	if (report == 1)
125 		statistics();
126 	exit(1);
127 	/* NOTREACHED */
128 }
129 
130 /* VARARGS1 */
131 void
132 warning(s, p, d)
133 char *s;
134 int p, d;
135 {
136 	if (!eof)
137 		if (!yyline)
138 			(void) fprintf(errorf, "Command line: ");
139 		else {
140 			(void) fprintf(errorf,
141 				!no_input?"":"\"%s\":", sargv[optind]);
142 			(void) fprintf(errorf,
143 				"line %d: ", yyline);
144 		}
145 	(void) fprintf(errorf, "Warning: ");
146 	(void) fprintf(errorf, s, p, d);
147 	(void) putc('\n', errorf);
148 	(void) fflush(errorf);
149 	if (fout)
150 		(void) fflush(fout);
151 	(void) fflush(stdout);
152 }
153 
154 int
155 index(int a, CHR *s)
156 {
157 	int k;
158 	for (k = 0; s[k]; k++)
159 		if (s[k] == a)
160 			return (k);
161 	return (-1);
162 }
163 
164 int
165 alpha(int c)
166 {
167 	return ('a' <= c && c <= 'z' ||
168 		'A' <= c && c <= 'Z');
169 }
170 
171 int
172 printable(int c)
173 {
174 	return (c > 040 && c < 0177);
175 }
176 
177 void
178 lgate(void)
179 {
180 	char fname[20];
181 
182 	if (lgatflg)
183 		return;
184 	lgatflg = 1;
185 	if (fout == NULL) {
186 		(void) sprintf(fname, "lex.yy.%c", ratfor ? 'r' : 'c');
187 		fout = fopen(fname, "w");
188 	}
189 	if (fout == NULL)
190 		error("Can't open %s", fname);
191 	if (ratfor)
192 		(void) fprintf(fout, "#\n");
193 	phead1();
194 }
195 
196 /*
197  * scopy(ptr to str, ptr to str) - copy first arg str to second
198  * returns ptr to second arg
199  */
200 void
201 scopy(CHR *s, CHR *t)
202 {
203 	CHR *i;
204 	i = t;
205 	while (*i++ = *s++);
206 }
207 
208 /*
209  * convert string t, return integer value
210  */
211 int
212 siconv(CHR *t)
213 {
214 	int i, sw;
215 	CHR *s;
216 	s = t;
217 	while (space(*s))
218 		s++;
219 	if (!digit(*s) && *s != '-')
220 		error("missing translation value");
221 	sw = 0;
222 	if (*s == '-') {
223 		sw = 1;
224 		s++;
225 	}
226 	if (!digit(*s))
227 		error("incomplete translation format");
228 	i = 0;
229 	while ('0' <= *s && *s <= '9')
230 		i = i * 10 + (*(s++)-'0');
231 	return (sw ? -i : i);
232 }
233 
234 /*
235  * slength(ptr to str) - return integer length of string arg
236  * excludes '\0' terminator
237  */
238 int
239 slength(CHR *s)
240 {
241 	int n;
242 	CHR *t;
243 	t = s;
244 	for (n = 0; *t++; n++);
245 	return (n);
246 }
247 
248 /*
249  * scomp(x,y) - return -1 if x < y,
250  *		0 if x == y,
251  *		return 1 if x > y, all lexicographically
252  */
253 int
254 scomp(CHR *x, CHR *y)
255 {
256 	CHR *a, *d;
257 	a = (CHR *) x;
258 	d = (CHR *) y;
259 	while (*a || *d) {
260 		if (*a > *d)
261 			return (1);
262 		if (*a < *d)
263 			return (-1);
264 		a++;
265 		d++;
266 	}
267 	return (0);
268 }
269 
270 int
271 ctrans(CHR **ss)
272 {
273 	int c, k;
274 	if ((c = **ss) != '\\')
275 		return (c);
276 	switch (c = *++*ss) {
277 	case 'a':
278 		c = '\a';
279 		warning("\\a is ANSI C \"alert\" character");
280 		break;
281 	case 'v': c = '\v'; break;
282 	case 'n': c = '\n'; break;
283 	case 't': c = '\t'; break;
284 	case 'r': c = '\r'; break;
285 	case 'b': c = '\b'; break;
286 	case 'f': c = 014; break;		/* form feed for ascii */
287 	case '\\': c = '\\'; break;
288 	case 'x': {
289 		int dd;
290 		warning("\\x is ANSI C hex escape");
291 		if (digit((dd = *++*ss)) ||
292 			('a' <= dd && dd <= 'f') ||
293 			('A' <= dd && dd <= 'F')) {
294 			c = 0;
295 			while (digit(dd) ||
296 				('A' <= dd && dd <= 'F') ||
297 				('a' <= dd && dd <= 'f')) {
298 				if (digit(dd))
299 					c = c*16 + dd - '0';
300 				else if (dd >= 'a')
301 					c = c*16 + 10 + dd - 'a';
302 				else
303 					c = c*16 + 10 + dd - 'A';
304 				dd = *++*ss;
305 			}
306 		} else
307 			c = 'x';
308 		break;
309 		}
310 	case '0': case '1': case '2': case '3':
311 	case '4': case '5': case '6': case '7':
312 		c -= '0';
313 		while ((k = *(*ss+1)) >= '0' && k <= '7') {
314 			c = c*8 + k - '0';
315 			(*ss)++;
316 		}
317 		break;
318 	}
319 	return (c);
320 }
321 
322 void
323 cclinter(int sw)
324 {
325 	/* sw = 1 ==> ccl */
326 	int i, j, k;
327 	int m;
328 	if (!sw) { /* is NCCL */
329 		for (i = 1; i < ncg; i++)
330 			symbol[i] ^= 1;	/* reverse value */
331 	}
332 	for (i = 1; i < ncg; i++)
333 		if (symbol[i])
334 			break;
335 	if (i >= ncg)
336 		return;
337 	i = cindex[i];
338 	/* see if ccl is already in our table */
339 	j = 0;
340 	if (i) {
341 		for (j = 1; j < ncg; j++) {
342 			if ((symbol[j] && cindex[j] != i) ||
343 				(!symbol[j] && cindex[j] == i))
344 				break;
345 		}
346 	}
347 	if (j >= ncg)
348 		return;		/* already in */
349 	m = 0;
350 	k = 0;
351 	for (i = 1; i < ncg; i++) {
352 		if (symbol[i]) {
353 			if (!cindex[i]) {
354 				cindex[i] = ccount;
355 				symbol[i] = 0;
356 				m = 1;
357 			} else
358 				k = 1;
359 		}
360 	}
361 	/* m == 1 implies last value of ccount has been used */
362 	if (m)
363 		ccount++;
364 	if (k == 0)
365 		return;	/* is now in as ccount wholly */
366 	/* intersection must be computed */
367 	for (i = 1; i < ncg; i++) {
368 		if (symbol[i]) {
369 			m = 0;
370 			j = cindex[i];	/* will be non-zero */
371 			for (k = 1; k < ncg; k++) {
372 				if (cindex[k] == j) {
373 					if (symbol[k])
374 						symbol[k] = 0;
375 					else {
376 						cindex[k] = ccount;
377 						m = 1;
378 					}
379 				}
380 			}
381 			if (m)
382 				ccount++;
383 		}
384 	}
385 }
386 
387 int
388 usescape(int c)
389 {
390 	char d;
391 	switch (c) {
392 	case 'a':
393 		c = '\a';
394 		warning("\\a is ANSI C \"alert\" character"); break;
395 	case 'v': c = '\v'; break;
396 	case 'n': c = '\n'; break;
397 	case 'r': c = '\r'; break;
398 	case 't': c = '\t'; break;
399 	case 'b': c = '\b'; break;
400 	case 'f': c = 014; break;		/* form feed for ascii */
401 	case 'x': {
402 		int dd;
403 		if (digit((dd = gch())) ||
404 			('A' <= dd && dd <= 'F') ||
405 			('a' <= dd && dd <= 'f')) {
406 			c = 0;
407 			while (digit(dd) ||
408 				('A' <= dd && dd <= 'F') ||
409 				('a' <= dd && dd <= 'f')) {
410 				if (digit(dd))
411 					c = c*16 + dd - '0';
412 				else if (dd >= 'a')
413 					c = c*16 + 10 + dd - 'a';
414 				else
415 					c = c*16 + 10 + dd - 'A';
416 				if (!digit(peek) &&
417 					!('A' <= peek && peek <= 'F') &&
418 					!('a' <= peek && peek <= 'f'))
419 					break;
420 				dd = gch();
421 			}
422 
423 		} else
424 			c = 'x';
425 		break;
426 	}
427 	case '0': case '1': case '2': case '3':
428 	case '4': case '5': case '6': case '7':
429 		c -= '0';
430 		while ('0' <= (d = gch()) && d <= '7') {
431 			c = c * 8 + (d-'0');
432 			if (!('0' <= peek && peek <= '7')) break;
433 			}
434 
435 		break;
436 	}
437 
438 	if (handleeuc && !isascii(c)) {
439 		char tmpchar = c & 0x00ff;
440 		mbtowc((wchar_t *)&c, &tmpchar, sizeof (tmpchar));
441 	}
442 	return (c);
443 }
444 
445 int
446 lookup(CHR *s, CHR **t)
447 {
448 	int i;
449 	i = 0;
450 	while (*t) {
451 		if (scomp(s, *t) == 0)
452 			return (i);
453 		i++;
454 		t++;
455 	}
456 	return (-1);
457 }
458 
459 void
460 cpycom(CHR *p)
461 {
462 	static CHR *t;
463 	static int c;
464 	t = p;
465 
466 	if (sargv[optind] == NULL)
467 		(void) fprintf(fout, "\n# line %d\n", yyline);
468 	else
469 		(void) fprintf(fout,
470 			"\n# line %d \"%s\"\n", yyline, sargv[optind]);
471 
472 	(void) putc(*t++, fout);
473 	(void) putc(*t++, fout);
474 	while (*t) {
475 		while (*t == '*') {
476 			(void) putc(*t++, fout);
477 			if (*t == '/')
478 				goto backcall;
479 		}
480 		/*
481 		 * FIX BUG #1058428, not parsing comments correctly
482 		 * that span more than one line
483 		 */
484 		if (*t != NULL)
485 			(void) putc(*t++, fout);
486 	}
487 	(void) putc('\n', fout);
488 	while (c = gch()) {
489 		while (c == '*') {
490 			(void) putc((char)c, fout);
491 			if ((c = gch()) == '/') {
492 				while ((c = gch()) == ' ' || c == '\t');
493 				if (!space(c))
494 					error("unacceptable statement");
495 				prev = '\n';
496 				goto backcall;
497 			}
498 		}
499 		(void) putc((char)c, fout);
500 	}
501 	error("unexpected EOF inside comment");
502 backcall:
503 	(void) putc('/', fout);
504 	(void) putc('\n', fout);
505 }
506 
507 /*
508  * copy C action to the next ; or closing
509  */
510 int
511 cpyact(void)
512 {
513 	int brac, c, mth;
514 	static int sw, savline;
515 
516 	brac = 0;
517 	sw = TRUE;
518 	savline = yyline;
519 
520 	if (sargv[optind] == NULL)
521 		(void) fprintf(fout, "\n# line %d\n", yyline);
522 	else
523 		(void) fprintf(fout,
524 			"\n# line %d \"%s\"\n", yyline, sargv[optind]);
525 
526 	while (!eof) {
527 		c = gch();
528 	swt:
529 		switch (c) {
530 		case '|':
531 			if (brac == 0 && sw == TRUE) {
532 				if (peek == '|')
533 					(void) gch(); /* eat up an extra '|' */
534 				return (0);
535 			}
536 			break;
537 		case ';':
538 			if (brac == 0) {
539 				(void) putwc(c, fout);
540 				(void) putc('\n', fout);
541 				return (1);
542 			}
543 			break;
544 		case '{':
545 			brac++;
546 			savline = yyline;
547 			break;
548 		case '}':
549 			brac--;
550 			if (brac == 0) {
551 				(void) putwc(c, fout);
552 				(void) putc('\n', fout);
553 				return (1);
554 			}
555 			break;
556 		case '/':
557 			(void) putwc(c, fout);
558 			c = gch();
559 			if (c != '*')
560 				goto swt;
561 			(void) putwc(c, fout);
562 			savline = yyline;
563 			while (c = gch()) {
564 				while (c == '*') {
565 					(void) putwc(c, fout);
566 					if ((c = gch()) == '/') {
567 						(void) putc('/', fout);
568 						while ((c = gch()) == ' ' ||
569 							c == '\t' || c == '\n')
570 							(void) putwc(c, fout);
571 						goto swt;
572 					}
573 				}
574 				(void) putc((char)c, fout);
575 			}
576 			yyline = savline;
577 			error("EOF inside comment");
578 			/* NOTREACHED */
579 			break;
580 		case '\'': /* character constant */
581 		case '"': /* character string */
582 			mth = c;
583 			(void) putwc(c, fout);
584 			while (c = gch()) {
585 				if (c == '\\') {
586 					(void) putwc(c, fout);
587 					c = gch();
588 				}
589 				else
590 					if (c == mth)
591 						goto loop;
592 				(void) putwc(c, fout);
593 				if (c == '\n') {
594 					yyline--;
595 					error(
596 "Non-terminated string or character constant");
597 				}
598 			}
599 			error("EOF in string or character constant");
600 			/* NOTREACHED */
601 			break;
602 		case '\0':
603 			yyline = savline;
604 			error("Action does not terminate");
605 			/* NOTREACHED */
606 			break;
607 		default:
608 			break; /* usual character */
609 		}
610 	loop:
611 		if (c != ' ' && c != '\t' && c != '\n')
612 			sw = FALSE;
613 		(void) putwc(c, fout);
614 		if (peek == '\n' && !brac && copy_line) {
615 			(void) putc('\n', fout);
616 			return (1);
617 		}
618 	}
619 	error("Premature EOF");
620 	return (0);
621 }
622 
623 int
624 gch(void)
625 {
626 	int c;
627 	prev = pres;
628 	c = pres = peek;
629 	peek = pushptr > pushc ? *--pushptr : getwc(fin);
630 	while (peek == EOF) {
631 		if (no_input) {
632 			if (!yyline)
633 				error("Cannot read from -- %s",
634 				sargv[optind]);
635 			if (optind < sargc-1) {
636 				yyline = 0;
637 				if (fin != stdin)
638 					(void) fclose(fin);
639 				fin = fopen(sargv[++optind], "r");
640 				if (fin == NULL)
641 					error("Cannot open file -- %s",
642 					sargv[optind]);
643 				peek = getwc(fin);
644 			} else
645 				break;
646 		} else {
647 			if (fin != stdin)
648 				(void) fclose(fin);
649 			if (!yyline)
650 				error("Cannot read from -- standard input");
651 			else
652 				break;
653 		}
654 	}
655 	if (c == EOF) {
656 		eof = TRUE;
657 		return (0);
658 	}
659 	if (c == '\n')
660 		yyline++;
661 	return (c);
662 }
663 
664 int
665 mn2(int a, int d, int c)
666 {
667 	if (tptr >= treesize) {
668 		tptr++;
669 		error("Parse tree too big %s",
670 			(treesize == TREESIZE ? "\nTry using %e num" : ""));
671 	}
672 	if (d >= treesize) {
673 		error("Parse error");
674 	}
675 	name[tptr] = a;
676 	left[tptr] = d;
677 	right[tptr] = c;
678 	parent[tptr] = 0;
679 	nullstr[tptr] = 0;
680 	switch (a) {
681 	case RSTR:
682 		parent[d] = tptr;
683 		break;
684 	case BAR:
685 	case RNEWE:
686 		if (nullstr[d] || nullstr[c])
687 			nullstr[tptr] = TRUE;
688 		parent[d] = parent[c] = tptr;
689 		break;
690 	case RCAT:
691 	case DIV:
692 		if (nullstr[d] && nullstr[c])
693 			nullstr[tptr] = TRUE;
694 		parent[d] = parent[c] = tptr;
695 		break;
696 	/* XCU4: add RXSCON */
697 	case RXSCON:
698 	case RSCON:
699 		parent[d] = tptr;
700 		nullstr[tptr] = nullstr[d];
701 		break;
702 #ifdef DEBUG
703 	default:
704 		warning("bad switch mn2 %d %d", a, d);
705 		break;
706 #endif
707 	}
708 	return (tptr++);
709 }
710 
711 int
712 mn1(int a, int d)
713 {
714 	if (tptr >= treesize) {
715 		tptr++;
716 		error("Parse tree too big %s",
717 		(treesize == TREESIZE ? "\nTry using %e num" : ""));
718 	}
719 	name[tptr] = a;
720 	left[tptr] = d;
721 	parent[tptr] = 0;
722 	nullstr[tptr] = 0;
723 	switch (a) {
724 	case RCCL:
725 	case RNCCL:
726 		if (slength((CHR *)d) == 0)
727 			nullstr[tptr] = TRUE;
728 		break;
729 	case STAR:
730 	case QUEST:
731 		nullstr[tptr] = TRUE;
732 		parent[d] = tptr;
733 		break;
734 	case PLUS:
735 	case CARAT:
736 		nullstr[tptr] = nullstr[d];
737 		parent[d] = tptr;
738 		break;
739 	case S2FINAL:
740 		nullstr[tptr] = TRUE;
741 		break;
742 #ifdef DEBUG
743 	case FINAL:
744 	case S1FINAL:
745 		break;
746 	default:
747 		warning("bad switch mn1 %d %d", a, d);
748 		break;
749 #endif
750 	}
751 	return (tptr++);
752 }
753 
754 int
755 mn0(int a)
756 {
757 	if (tptr >= treesize) {
758 		tptr++;
759 		error("Parse tree too big %s",
760 			(treesize == TREESIZE ? "\nTry using %e num" : ""));
761 	}
762 
763 	name[tptr] = a;
764 	parent[tptr] = 0;
765 	nullstr[tptr] = 0;
766 	if (ISOPERATOR(a)) {
767 		switch (a) {
768 		case DOT: break;
769 		case RNULLS: nullstr[tptr] = TRUE; break;
770 #ifdef DEBUG
771 		default:
772 			warning("bad switch mn0 %d", a);
773 			break;
774 #endif
775 		}
776 	}
777 	return (tptr++);
778 }
779 
780 void
781 munput(int t, CHR *p)
782 {
783 	int i, j;
784 	if (t == 'c') {
785 		*pushptr++ = peek;
786 		peek = *p;
787 	} else if (t == 's') {
788 		*pushptr++ = peek;
789 		peek = p[0];
790 		i = slength(p);
791 		for (j = i - 1; j >= 1; j--)
792 			*pushptr++ = p[j];
793 	}
794 	if (pushptr >= pushc + TOKENSIZE)
795 		error("Too many characters pushed");
796 }
797 
798 int
799 dupl(int n)
800 {
801 	/* duplicate the subtree whose root is n, return ptr to it */
802 	int i;
803 	i = name[n];
804 	if (!ISOPERATOR(i))
805 		return (mn0(i));
806 	switch (i) {
807 	case DOT:
808 	case RNULLS:
809 		return (mn0(i));
810 	case RCCL: case RNCCL: case FINAL: case S1FINAL: case S2FINAL:
811 		return (mn1(i, left[n]));
812 	case STAR: case QUEST: case PLUS: case CARAT:
813 		return (mn1(i, dupl(left[n])));
814 
815 	/* XCU4: add RXSCON */
816 	case RSTR: case RSCON: case RXSCON:
817 		return (mn2(i, dupl(left[n]), right[n]));
818 	case BAR: case RNEWE: case RCAT: case DIV:
819 		return (mn2(i, dupl(left[n]), dupl(right[n])));
820 	}
821 	return (0);
822 }
823 
824 #ifdef DEBUG
825 void
826 allprint(CHR c)
827 {
828 	switch (c) {
829 	case 014:
830 		(void) printf("\\f");
831 		charc++;
832 		break;
833 	case '\n':
834 		(void) printf("\\n");
835 		charc++;
836 		break;
837 	case '\t':
838 		(void) printf("\\t");
839 		charc++;
840 		break;
841 	case '\b':
842 		(void) printf("\\b");
843 		charc++;
844 		break;
845 	case ' ':
846 		(void) printf("\\_");
847 		break;
848 	default:
849 		if (!iswprint(c)) {
850 			printf("\\x%-2x", c); /* up to fashion. */
851 			charc += 3;
852 		} else
853 			(void) putwc(c, stdout);
854 		break;
855 	}
856 	charc++;
857 }
858 
859 void
860 strpt(CHR *s)
861 {
862 	charc = 0;
863 	while (*s) {
864 		allprint(*s++);
865 		if (charc > LINESIZE) {
866 			charc = 0;
867 			(void) printf("\n\t");
868 		}
869 	}
870 }
871 
872 void
873 sect1dump(void)
874 {
875 	int i;
876 	(void) printf("Sect 1:\n");
877 	if (def[0]) {
878 		(void) printf("str	trans\n");
879 		i = -1;
880 		while (def[++i])
881 			(void) printf("%ws\t%ws\n", def[i], subs[i]);
882 	}
883 	if (sname[0]) {
884 		(void) printf("start names\n");
885 		i = -1;
886 		while (sname[++i])
887 			(void) printf("%ws\n", sname[i]);
888 	}
889 	if (chset == TRUE) {
890 		(void) printf("char set changed\n");
891 		for (i = 1; i < NCH; i++) {
892 			if (i != ctable[i]) {
893 				allprint(i);
894 				(void) putchar(' ');
895 				iswprint(ctable[i]) ?
896 					(void) putwc(ctable[i], stdout) :
897 					(void) printf("%d", ctable[i]);
898 				(void) putchar('\n');
899 			}
900 		}
901 	}
902 }
903 
904 void
905 sect2dump(void)
906 {
907 	(void) printf("Sect 2:\n");
908 	treedump();
909 }
910 
911 void
912 treedump(void)
913 {
914 	int t;
915 	CHR *p;
916 	(void) printf("treedump %d nodes:\n", tptr);
917 	for (t = 0; t < tptr; t++) {
918 		(void) printf("%4d ", t);
919 		parent[t] ? (void) printf("p=%4d", parent[t]) :
920 			(void) printf("      ");
921 		(void) printf("  ");
922 		if (!ISOPERATOR(name[t])) {
923 			allprint(name[t]);
924 		} else
925 			switch (name[t]) {
926 			case RSTR:
927 				(void) printf("%d ", left[t]);
928 				allprint(right[t]);
929 				break;
930 			case RCCL:
931 				(void) printf("ccl ");
932 				strpt(left[t]);
933 				break;
934 			case RNCCL:
935 				(void) printf("nccl ");
936 				strpt(left[t]);
937 				break;
938 			case DIV:
939 				(void) printf("/ %d %d", left[t], right[t]);
940 				break;
941 			case BAR:
942 				(void) printf("| %d %d", left[t], right[t]);
943 				break;
944 			case RCAT:
945 				(void) printf("cat %d %d", left[t], right[t]);
946 				break;
947 			case PLUS:
948 				(void) printf("+ %d", left[t]);
949 				break;
950 			case STAR:
951 				(void) printf("* %d", left[t]);
952 				break;
953 			case CARAT:
954 				(void) printf("^ %d", left[t]);
955 				break;
956 			case QUEST:
957 				(void) printf("? %d", left[t]);
958 				break;
959 			case RNULLS:
960 				(void) printf("nullstring");
961 				break;
962 			case FINAL:
963 				(void) printf("final %d", left[t]);
964 				break;
965 			case S1FINAL:
966 				(void) printf("s1final %d", left[t]);
967 				break;
968 			case S2FINAL:
969 				(void) printf("s2final %d", left[t]);
970 				break;
971 			case RNEWE:
972 				(void) printf("new %d %d", left[t], right[t]);
973 				break;
974 
975 			/* XCU4: add RXSCON */
976 			case RXSCON:
977 				p = (CHR *)right[t];
978 				(void) printf("exstart %s", sname[*p++-1]);
979 				while (*p)
980 					(void) printf(", %ws", sname[*p++-1]);
981 				(void) printf(" %d", left[t]);
982 				break;
983 			case RSCON:
984 				p = (CHR *)right[t];
985 				(void) printf("start %s", sname[*p++-1]);
986 				while (*p)
987 					(void) printf(", %ws", sname[*p++-1]);
988 				(void) printf(" %d", left[t]);
989 				break;
990 			case DOT:
991 				printf("dot");
992 				break;
993 			default:
994 				(void) printf(
995 				"unknown %d %d %d", name[t], left[t], right[t]);
996 				break;
997 			}
998 		if (nullstr[t])
999 			(void) printf("\t(null poss.)");
1000 		(void) putchar('\n');
1001 	}
1002 }
1003 #endif
1004