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