xref: /illumos-gate/usr/src/cmd/sgs/lex/common/sub1.c (revision dd4eeefd)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*	Copyright (c) 1988 AT&T	*/
27 /*	All Rights Reserved	*/
28 
29 #pragma ident	"%Z%%M%	%I%	%E% SMI"
30 
31 #include "ldefs.h"
32 #include <limits.h>
33 
34 /*
35  * return next line of input, throw away trailing '\n'
36  * and also throw away trailing blanks (spaces and tabs)
37  * returns 0 if eof is had immediately
38  */
39 
40 CHR *
41 getl(CHR *p)
42 {
43 	int c;
44 	CHR *s, *t, *u;
45 	int blank = 0;
46 
47 	t = s = p;
48 	while (((c = gch()) != 0) && c != '\n') {
49 		if (t >= &p[BUF_SIZ])
50 			error("definitions too long");
51 		if (c == ' ' || c == '\t') {
52 			if (!blank) {
53 				blank = 1;
54 				u = t;
55 			}
56 		} else
57 			blank = 0;
58 
59 		*t++ = c;
60 	}
61 	if (blank)
62 		*u = 0;
63 	else
64 		*t = 0;
65 
66 	if (c == 0 && s == t)
67 		return ((CHR *) 0);
68 	prev = '\n';
69 	pres = '\n';
70 	return (s);
71 }
72 
73 int
74 space(int ch)
75 {
76 	switch (ch) {
77 		case ' ':
78 		case '\t':
79 		case '\n':
80 			return (1);
81 	}
82 	return (0);
83 }
84 
85 int
86 digit(int c)
87 {
88 	return (c >= '0' && c <= '9');
89 }
90 
91 /* VARARGS1 */
92 void
93 error(s, p, d)
94 char *s;
95 int p, d;
96 {
97 	/* if(!eof) */
98 	if (!yyline)
99 		(void) fprintf(errorf, "Command line: ");
100 	else {
101 		(void) fprintf(errorf,
102 			!no_input ? "" : "\"%s\":", sargv[optind]);
103 		(void) fprintf(errorf, "line %d: ", yyline);
104 	}
105 	(void) fprintf(errorf, "Error: ");
106 	(void) fprintf(errorf, s, p, d);
107 	(void) putc('\n', errorf);
108 	if (fatal)
109 		error_tail();
110 }
111 
112 void
113 error_tail(void)
114 {
115 #ifdef DEBUG
116 	if (debug && sect != ENDSECTION) {
117 		sect1dump();
118 		sect2dump();
119 	}
120 #endif
121 
122 	if (report == 1)
123 		statistics();
124 	exit(1);
125 	/* NOTREACHED */
126 }
127 
128 /* VARARGS1 */
129 void
130 warning(s, p, d)
131 char *s;
132 int p, d;
133 {
134 	if (!eof)
135 		if (!yyline)
136 			(void) fprintf(errorf, "Command line: ");
137 		else {
138 			(void) fprintf(errorf,
139 				!no_input?"":"\"%s\":", sargv[optind]);
140 			(void) fprintf(errorf,
141 				"line %d: ", yyline);
142 		}
143 	(void) fprintf(errorf, "Warning: ");
144 	(void) fprintf(errorf, s, p, d);
145 	(void) putc('\n', errorf);
146 	(void) fflush(errorf);
147 	if (fout)
148 		(void) fflush(fout);
149 	(void) fflush(stdout);
150 }
151 
152 int
153 index(int a, CHR *s)
154 {
155 	int k;
156 	for (k = 0; s[k]; k++)
157 		if (s[k] == a)
158 			return (k);
159 	return (-1);
160 }
161 
162 int
163 alpha(int c)
164 {
165 	return ('a' <= c && c <= 'z' ||
166 	    'A' <= c && c <= 'Z');
167 }
168 
169 int
170 printable(int c)
171 {
172 	return (c > 040 && c < 0177);
173 }
174 
175 void
176 lgate(void)
177 {
178 	char fname[20];
179 
180 	if (lgatflg)
181 		return;
182 	lgatflg = 1;
183 	if (fout == NULL) {
184 		(void) sprintf(fname, "lex.yy.%c", ratfor ? 'r' : 'c');
185 		fout = fopen(fname, "w");
186 	}
187 	if (fout == NULL)
188 		error("Can't open %s", fname);
189 	if (ratfor)
190 		(void) fprintf(fout, "#\n");
191 	phead1();
192 }
193 
194 /*
195  * scopy(ptr to str, ptr to str) - copy first arg str to second
196  * returns ptr to second arg
197  */
198 void
199 scopy(CHR *s, CHR *t)
200 {
201 	CHR *i;
202 	i = t;
203 	while (*i++ = *s++)
204 		/* EMPTY */;
205 }
206 
207 /*
208  * convert string t, return integer value
209  */
210 int
211 siconv(CHR *t)
212 {
213 	int i, sw;
214 	CHR *s;
215 	s = t;
216 	while (space(*s))
217 		s++;
218 	if (!digit(*s) && *s != '-')
219 		error("missing translation value");
220 	sw = 0;
221 	if (*s == '-') {
222 		sw = 1;
223 		s++;
224 	}
225 	if (!digit(*s))
226 		error("incomplete translation format");
227 	i = 0;
228 	while ('0' <= *s && *s <= '9')
229 		i = i * 10 + (*(s++)-'0');
230 	return (sw ? -i : i);
231 }
232 
233 /*
234  * slength(ptr to str) - return integer length of string arg
235  * excludes '\0' terminator
236  */
237 int
238 slength(CHR *s)
239 {
240 	int n;
241 	CHR *t;
242 	t = s;
243 	for (n = 0; *t++; n++)
244 		/* EMPTY */;
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 					/* EMPTY */;
494 				if (!space(c))
495 					error("unacceptable statement");
496 				prev = '\n';
497 				goto backcall;
498 			}
499 		}
500 		(void) putc((char)c, fout);
501 	}
502 	error("unexpected EOF inside comment");
503 backcall:
504 	(void) putc('/', fout);
505 	(void) putc('\n', fout);
506 }
507 
508 /*
509  * copy C action to the next ; or closing
510  */
511 int
512 cpyact(void)
513 {
514 	int brac, c, mth;
515 	static int sw, savline;
516 
517 	brac = 0;
518 	sw = TRUE;
519 	savline = yyline;
520 
521 	if (sargv[optind] == NULL)
522 		(void) fprintf(fout, "\n# line %d\n", yyline);
523 	else
524 		(void) fprintf(fout,
525 		    "\n# line %d \"%s\"\n", yyline, sargv[optind]);
526 
527 	while (!eof) {
528 		c = gch();
529 	swt:
530 		switch (c) {
531 		case '|':
532 			if (brac == 0 && sw == TRUE) {
533 				if (peek == '|')
534 					(void) gch(); /* eat up an extra '|' */
535 				return (0);
536 			}
537 			break;
538 		case ';':
539 			if (brac == 0) {
540 				(void) putwc(c, fout);
541 				(void) putc('\n', fout);
542 				return (1);
543 			}
544 			break;
545 		case '{':
546 			brac++;
547 			savline = yyline;
548 			break;
549 		case '}':
550 			brac--;
551 			if (brac == 0) {
552 				(void) putwc(c, fout);
553 				(void) putc('\n', fout);
554 				return (1);
555 			}
556 			break;
557 		case '/':
558 			(void) putwc(c, fout);
559 			c = gch();
560 			if (c != '*')
561 				goto swt;
562 			(void) putwc(c, fout);
563 			savline = yyline;
564 			while (c = gch()) {
565 				while (c == '*') {
566 					(void) putwc(c, fout);
567 					if ((c = gch()) == '/') {
568 						(void) putc('/', fout);
569 						while ((c = gch()) == ' ' ||
570 						    c == '\t' || c == '\n')
571 							(void) putwc(c, fout);
572 						goto swt;
573 					}
574 				}
575 				(void) putc((char)c, fout);
576 			}
577 			yyline = savline;
578 			error("EOF inside comment");
579 			/* NOTREACHED */
580 			break;
581 		case '\'': /* character constant */
582 		case '"': /* character string */
583 			mth = c;
584 			(void) putwc(c, fout);
585 			while (c = gch()) {
586 				if (c == '\\') {
587 					(void) putwc(c, fout);
588 					c = gch();
589 				}
590 				else
591 					if (c == mth)
592 						goto loop;
593 				(void) putwc(c, fout);
594 				if (c == '\n') {
595 					yyline--;
596 					error(
597 "Non-terminated string or character constant");
598 				}
599 			}
600 			error("EOF in string or character constant");
601 			/* NOTREACHED */
602 			break;
603 		case '\0':
604 			yyline = savline;
605 			error("Action does not terminate");
606 			/* NOTREACHED */
607 			break;
608 		default:
609 			break; /* usual character */
610 		}
611 	loop:
612 		if (c != ' ' && c != '\t' && c != '\n')
613 			sw = FALSE;
614 		(void) putwc(c, fout);
615 		if (peek == '\n' && !brac && copy_line) {
616 			(void) putc('\n', fout);
617 			return (1);
618 		}
619 	}
620 	error("Premature EOF");
621 	return (0);
622 }
623 
624 int
625 gch(void)
626 {
627 	int c;
628 	prev = pres;
629 	c = pres = peek;
630 	peek = pushptr > pushc ? *--pushptr : getwc(fin);
631 	while (peek == EOF) {
632 		if (no_input) {
633 			if (!yyline)
634 				error("Cannot read from -- %s",
635 				    sargv[optind]);
636 			if (optind < sargc-1) {
637 				yyline = 0;
638 				if (fin != stdin)
639 					(void) fclose(fin);
640 				fin = fopen(sargv[++optind], "r");
641 				if (fin == NULL)
642 					error("Cannot open file -- %s",
643 					    sargv[optind]);
644 				peek = getwc(fin);
645 			} else
646 				break;
647 		} else {
648 			if (fin != stdin)
649 				(void) fclose(fin);
650 			if (!yyline)
651 				error("Cannot read from -- standard input");
652 			else
653 				break;
654 		}
655 	}
656 	if (c == EOF) {
657 		eof = TRUE;
658 		return (0);
659 	}
660 	if (c == '\n')
661 		yyline++;
662 	return (c);
663 }
664 
665 int
666 mn2(int a, int d, int c)
667 {
668 	if (tptr >= treesize) {
669 		tptr++;
670 		error("Parse tree too big %s",
671 		    (treesize == TREESIZE ? "\nTry using %e num" : ""));
672 	}
673 	if (d >= treesize) {
674 		error("Parse error");
675 	}
676 	name[tptr] = a;
677 	left[tptr] = d;
678 	right[tptr] = c;
679 	parent[tptr] = 0;
680 	nullstr[tptr] = 0;
681 	switch (a) {
682 	case RSTR:
683 		parent[d] = tptr;
684 		break;
685 	case BAR:
686 	case RNEWE:
687 		if (nullstr[d] || nullstr[c])
688 			nullstr[tptr] = TRUE;
689 		parent[d] = parent[c] = tptr;
690 		break;
691 	case RCAT:
692 	case DIV:
693 		if (nullstr[d] && nullstr[c])
694 			nullstr[tptr] = TRUE;
695 		parent[d] = parent[c] = tptr;
696 		break;
697 	/* XCU4: add RXSCON */
698 	case RXSCON:
699 	case RSCON:
700 		parent[d] = tptr;
701 		nullstr[tptr] = nullstr[d];
702 		break;
703 #ifdef DEBUG
704 	default:
705 		warning("bad switch mn2 %d %d", a, d);
706 		break;
707 #endif
708 	}
709 	return (tptr++);
710 }
711 
712 int
713 mn1(int a, int d)
714 {
715 	if (tptr >= treesize) {
716 		tptr++;
717 		error("Parse tree too big %s",
718 		    (treesize == TREESIZE ? "\nTry using %e num" : ""));
719 	}
720 	name[tptr] = a;
721 	left[tptr] = d;
722 	parent[tptr] = 0;
723 	nullstr[tptr] = 0;
724 	switch (a) {
725 	case RCCL:
726 	case RNCCL:
727 		if (slength((CHR *)d) == 0)
728 			nullstr[tptr] = TRUE;
729 		break;
730 	case STAR:
731 	case QUEST:
732 		nullstr[tptr] = TRUE;
733 		parent[d] = tptr;
734 		break;
735 	case PLUS:
736 	case CARAT:
737 		nullstr[tptr] = nullstr[d];
738 		parent[d] = tptr;
739 		break;
740 	case S2FINAL:
741 		nullstr[tptr] = TRUE;
742 		break;
743 #ifdef DEBUG
744 	case FINAL:
745 	case S1FINAL:
746 		break;
747 	default:
748 		warning("bad switch mn1 %d %d", a, d);
749 		break;
750 #endif
751 	}
752 	return (tptr++);
753 }
754 
755 int
756 mn0(int a)
757 {
758 	if (tptr >= treesize) {
759 		tptr++;
760 		error("Parse tree too big %s",
761 		    (treesize == TREESIZE ? "\nTry using %e num" : ""));
762 	}
763 
764 	name[tptr] = a;
765 	parent[tptr] = 0;
766 	nullstr[tptr] = 0;
767 	if (ISOPERATOR(a)) {
768 		switch (a) {
769 		case DOT: break;
770 		case RNULLS: nullstr[tptr] = TRUE; break;
771 #ifdef DEBUG
772 		default:
773 			warning("bad switch mn0 %d", a);
774 			break;
775 #endif
776 		}
777 	}
778 	return (tptr++);
779 }
780 
781 void
782 munput(int t, CHR *p)
783 {
784 	int i, j;
785 	if (t == 'c') {
786 		*pushptr++ = peek;
787 		peek = *p;
788 	} else if (t == 's') {
789 		*pushptr++ = peek;
790 		peek = p[0];
791 		i = slength(p);
792 		for (j = i - 1; j >= 1; j--)
793 			*pushptr++ = p[j];
794 	}
795 	if (pushptr >= pushc + TOKENSIZE)
796 		error("Too many characters pushed");
797 }
798 
799 int
800 dupl(int n)
801 {
802 	/* duplicate the subtree whose root is n, return ptr to it */
803 	int i;
804 	i = name[n];
805 	if (!ISOPERATOR(i))
806 		return (mn0(i));
807 	switch (i) {
808 	case DOT:
809 	case RNULLS:
810 		return (mn0(i));
811 	case RCCL: case RNCCL: case FINAL: case S1FINAL: case S2FINAL:
812 		return (mn1(i, left[n]));
813 	case STAR: case QUEST: case PLUS: case CARAT:
814 		return (mn1(i, dupl(left[n])));
815 
816 	/* XCU4: add RXSCON */
817 	case RSTR: case RSCON: case RXSCON:
818 		return (mn2(i, dupl(left[n]), right[n]));
819 	case BAR: case RNEWE: case RCAT: case DIV:
820 		return (mn2(i, dupl(left[n]), dupl(right[n])));
821 	}
822 	return (0);
823 }
824 
825 #ifdef DEBUG
826 void
827 allprint(CHR c)
828 {
829 	switch (c) {
830 	case 014:
831 		(void) printf("\\f");
832 		charc++;
833 		break;
834 	case '\n':
835 		(void) printf("\\n");
836 		charc++;
837 		break;
838 	case '\t':
839 		(void) printf("\\t");
840 		charc++;
841 		break;
842 	case '\b':
843 		(void) printf("\\b");
844 		charc++;
845 		break;
846 	case ' ':
847 		(void) printf("\\_");
848 		break;
849 	default:
850 		if (!iswprint(c)) {
851 			printf("\\x%-2x", c); /* up to fashion. */
852 			charc += 3;
853 		} else
854 			(void) putwc(c, stdout);
855 		break;
856 	}
857 	charc++;
858 }
859 
860 void
861 strpt(CHR *s)
862 {
863 	charc = 0;
864 	while (*s) {
865 		allprint(*s++);
866 		if (charc > LINESIZE) {
867 			charc = 0;
868 			(void) printf("\n\t");
869 		}
870 	}
871 }
872 
873 void
874 sect1dump(void)
875 {
876 	int i;
877 	(void) printf("Sect 1:\n");
878 	if (def[0]) {
879 		(void) printf("str	trans\n");
880 		i = -1;
881 		while (def[++i])
882 			(void) printf("%ws\t%ws\n", def[i], subs[i]);
883 	}
884 	if (sname[0]) {
885 		(void) printf("start names\n");
886 		i = -1;
887 		while (sname[++i])
888 			(void) printf("%ws\n", sname[i]);
889 	}
890 	if (chset == TRUE) {
891 		(void) printf("char set changed\n");
892 		for (i = 1; i < NCH; i++) {
893 			if (i != ctable[i]) {
894 				allprint(i);
895 				(void) putchar(' ');
896 				iswprint(ctable[i]) ?
897 				    (void) putwc(ctable[i], stdout) :
898 				    (void) printf("%d", ctable[i]);
899 				(void) putchar('\n');
900 			}
901 		}
902 	}
903 }
904 
905 void
906 sect2dump(void)
907 {
908 	(void) printf("Sect 2:\n");
909 	treedump();
910 }
911 
912 void
913 treedump(void)
914 {
915 	int t;
916 	CHR *p;
917 	(void) printf("treedump %d nodes:\n", tptr);
918 	for (t = 0; t < tptr; t++) {
919 		(void) printf("%4d ", t);
920 		parent[t] ? (void) printf("p=%4d", parent[t]) :
921 		    (void) printf("      ");
922 		(void) printf("  ");
923 		if (!ISOPERATOR(name[t])) {
924 			allprint(name[t]);
925 		} else
926 			switch (name[t]) {
927 			case RSTR:
928 				(void) printf("%d ", left[t]);
929 				allprint(right[t]);
930 				break;
931 			case RCCL:
932 				(void) printf("ccl ");
933 				strpt(left[t]);
934 				break;
935 			case RNCCL:
936 				(void) printf("nccl ");
937 				strpt(left[t]);
938 				break;
939 			case DIV:
940 				(void) printf("/ %d %d", left[t], right[t]);
941 				break;
942 			case BAR:
943 				(void) printf("| %d %d", left[t], right[t]);
944 				break;
945 			case RCAT:
946 				(void) printf("cat %d %d", left[t], right[t]);
947 				break;
948 			case PLUS:
949 				(void) printf("+ %d", left[t]);
950 				break;
951 			case STAR:
952 				(void) printf("* %d", left[t]);
953 				break;
954 			case CARAT:
955 				(void) printf("^ %d", left[t]);
956 				break;
957 			case QUEST:
958 				(void) printf("? %d", left[t]);
959 				break;
960 			case RNULLS:
961 				(void) printf("nullstring");
962 				break;
963 			case FINAL:
964 				(void) printf("final %d", left[t]);
965 				break;
966 			case S1FINAL:
967 				(void) printf("s1final %d", left[t]);
968 				break;
969 			case S2FINAL:
970 				(void) printf("s2final %d", left[t]);
971 				break;
972 			case RNEWE:
973 				(void) printf("new %d %d", left[t], right[t]);
974 				break;
975 
976 			/* XCU4: add RXSCON */
977 			case RXSCON:
978 				p = (CHR *)right[t];
979 				(void) printf("exstart %s", sname[*p++-1]);
980 				while (*p)
981 					(void) printf(", %ws", sname[*p++-1]);
982 				(void) printf(" %d", left[t]);
983 				break;
984 			case RSCON:
985 				p = (CHR *)right[t];
986 				(void) printf("start %s", sname[*p++-1]);
987 				while (*p)
988 					(void) printf(", %ws", sname[*p++-1]);
989 				(void) printf(" %d", left[t]);
990 				break;
991 			case DOT:
992 				printf("dot");
993 				break;
994 			default:
995 				(void) printf(
996 				"unknown %d %d %d", name[t], left[t], right[t]);
997 				break;
998 			}
999 		if (nullstr[t])
1000 			(void) printf("\t(null poss.)");
1001 		(void) putchar('\n');
1002 	}
1003 }
1004 #endif
1005