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