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 (void) fprintf(errorf, "Warning: "); 144 va_start(ap, s); 145 (void) vfprintf(errorf, s, ap); 146 va_end(ap); 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 != 0) 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