1 /* $NetBSD: reader.c,v 1.7 2011/09/10 21:29:04 christos Exp $ */ 2 /* Id: reader.c,v 1.33 2011/09/06 22:56:53 tom Exp */ 3 4 #include "defs.h" 5 6 #include <sys/cdefs.h> 7 __RCSID("$NetBSD: reader.c,v 1.7 2011/09/10 21:29:04 christos Exp $"); 8 9 /* The line size must be a positive integer. One hundred was chosen */ 10 /* because few lines in Yacc input grammars exceed 100 characters. */ 11 /* Note that if a line exceeds LINESIZE characters, the line buffer */ 12 /* will be expanded to accomodate it. */ 13 14 #define LINESIZE 100 15 16 #define L_CURL '{' 17 #define R_CURL '}' 18 19 static void start_rule(bucket *bp, int s_lineno); 20 21 static char *cache; 22 static int cinc, cache_size; 23 24 int ntags; 25 static int tagmax; 26 static char **tag_table; 27 28 static char saw_eof; 29 char unionized; 30 char *cptr, *line; 31 static int linesize; 32 33 static bucket *goal; 34 static Value_t prec; 35 static int gensym; 36 static char last_was_action; 37 38 static int maxitems; 39 static bucket **pitem; 40 41 static int maxrules; 42 static bucket **plhs; 43 44 static size_t name_pool_size; 45 static char *name_pool; 46 47 char line_format[] = "#line %d \"%s\"\n"; 48 49 param *lex_param; 50 param *parse_param; 51 52 static void 53 cachec(int c) 54 { 55 assert(cinc >= 0); 56 if (cinc >= cache_size) 57 { 58 cache_size += 256; 59 cache = REALLOC(cache, cache_size); 60 NO_SPACE(cache); 61 } 62 cache[cinc] = (char)c; 63 ++cinc; 64 } 65 66 static void 67 get_line(void) 68 { 69 FILE *f = input_file; 70 int c; 71 int i; 72 73 if (saw_eof || (c = getc(f)) == EOF) 74 { 75 if (line) 76 { 77 FREE(line); 78 line = 0; 79 } 80 cptr = 0; 81 saw_eof = 1; 82 return; 83 } 84 85 if (line == 0 || linesize != (LINESIZE + 1)) 86 { 87 if (line) 88 FREE(line); 89 linesize = LINESIZE + 1; 90 line = MALLOC(linesize); 91 NO_SPACE(line); 92 } 93 94 i = 0; 95 ++lineno; 96 for (;;) 97 { 98 line[i] = (char)c; 99 if (c == '\n') 100 { 101 cptr = line; 102 return; 103 } 104 if (++i >= linesize) 105 { 106 linesize += LINESIZE; 107 line = REALLOC(line, linesize); 108 NO_SPACE(line); 109 } 110 c = getc(f); 111 if (c == EOF) 112 { 113 line[i] = '\n'; 114 saw_eof = 1; 115 cptr = line; 116 return; 117 } 118 } 119 } 120 121 static char * 122 dup_line(void) 123 { 124 char *p, *s, *t; 125 126 if (line == 0) 127 return (0); 128 s = line; 129 while (*s != '\n') 130 ++s; 131 p = MALLOC(s - line + 1); 132 NO_SPACE(p); 133 134 s = line; 135 t = p; 136 while ((*t++ = *s++) != '\n') 137 continue; 138 return (p); 139 } 140 141 static void 142 skip_comment(void) 143 { 144 char *s; 145 146 int st_lineno = lineno; 147 char *st_line = dup_line(); 148 char *st_cptr = st_line + (cptr - line); 149 150 s = cptr + 2; 151 for (;;) 152 { 153 if (*s == '*' && s[1] == '/') 154 { 155 cptr = s + 2; 156 FREE(st_line); 157 return; 158 } 159 if (*s == '\n') 160 { 161 get_line(); 162 if (line == 0) 163 unterminated_comment(st_lineno, st_line, st_cptr); 164 s = cptr; 165 } 166 else 167 ++s; 168 } 169 } 170 171 static int 172 nextc(void) 173 { 174 char *s; 175 176 if (line == 0) 177 { 178 get_line(); 179 if (line == 0) 180 return (EOF); 181 } 182 183 s = cptr; 184 for (;;) 185 { 186 switch (*s) 187 { 188 case '\n': 189 get_line(); 190 if (line == 0) 191 return (EOF); 192 s = cptr; 193 break; 194 195 case ' ': 196 case '\t': 197 case '\f': 198 case '\r': 199 case '\v': 200 case ',': 201 case ';': 202 ++s; 203 break; 204 205 case '\\': 206 cptr = s; 207 return ('%'); 208 209 case '/': 210 if (s[1] == '*') 211 { 212 cptr = s; 213 skip_comment(); 214 s = cptr; 215 break; 216 } 217 else if (s[1] == '/') 218 { 219 get_line(); 220 if (line == 0) 221 return (EOF); 222 s = cptr; 223 break; 224 } 225 /* FALLTHRU */ 226 227 default: 228 cptr = s; 229 return (*s); 230 } 231 } 232 } 233 234 /* 235 * Compare keyword to cached token, treating '_' and '-' the same. Some 236 * grammars rely upon this misfeature. 237 */ 238 static int 239 matchec(const char *name) 240 { 241 const char *p = cache; 242 const char *q = name; 243 int code = 0; /* assume mismatch */ 244 245 while (*p != '\0' && *q != '\0') 246 { 247 char a = *p++; 248 char b = *q++; 249 if (a == '_') 250 a = '-'; 251 if (b == '_') 252 b = '-'; 253 if (a != b) 254 break; 255 if (*p == '\0' && *q == '\0') 256 { 257 code = 1; 258 break; 259 } 260 } 261 return code; 262 } 263 264 static int 265 keyword(void) 266 { 267 int c; 268 char *t_cptr = cptr; 269 270 c = *++cptr; 271 if (isalpha(c)) 272 { 273 cinc = 0; 274 for (;;) 275 { 276 if (isalpha(c)) 277 { 278 if (isupper(c)) 279 c = tolower(c); 280 cachec(c); 281 } 282 else if (isdigit(c) 283 || c == '-' 284 || c == '_' 285 || c == '.' 286 || c == '$') 287 { 288 cachec(c); 289 } 290 else 291 { 292 break; 293 } 294 c = *++cptr; 295 } 296 cachec(NUL); 297 298 if (matchec("token") || matchec("term")) 299 return (TOKEN); 300 if (matchec("type")) 301 return (TYPE); 302 if (matchec("left")) 303 return (LEFT); 304 if (matchec("right")) 305 return (RIGHT); 306 if (matchec("nonassoc") || matchec("binary")) 307 return (NONASSOC); 308 if (matchec("start")) 309 return (START); 310 if (matchec("union")) 311 return (UNION); 312 if (matchec("ident")) 313 return (IDENT); 314 if (matchec("expect")) 315 return (EXPECT); 316 if (matchec("expect-rr")) 317 return (EXPECT_RR); 318 if (matchec("pure-parser")) 319 return (PURE_PARSER); 320 if (matchec("parse-param")) 321 return (PARSE_PARAM); 322 if (matchec("lex-param")) 323 return (LEX_PARAM); 324 if (matchec("yacc")) 325 return (POSIX_YACC); 326 } 327 else 328 { 329 ++cptr; 330 if (c == L_CURL) 331 return (TEXT); 332 if (c == '%' || c == '\\') 333 return (MARK); 334 if (c == '<') 335 return (LEFT); 336 if (c == '>') 337 return (RIGHT); 338 if (c == '0') 339 return (TOKEN); 340 if (c == '2') 341 return (NONASSOC); 342 } 343 syntax_error(lineno, line, t_cptr); 344 /*NOTREACHED */ 345 } 346 347 348 static void 349 copy_ident(void) 350 { 351 int c; 352 FILE *f = output_file; 353 354 c = nextc(); 355 if (c == EOF) 356 unexpected_EOF(); 357 if (c != '"') 358 syntax_error(lineno, line, cptr); 359 ++outline; 360 fprintf(f, "#ident \""); 361 for (;;) 362 { 363 c = *++cptr; 364 if (c == '\n') 365 { 366 fprintf(f, "\"\n"); 367 return; 368 } 369 putc(c, f); 370 if (c == '"') 371 { 372 putc('\n', f); 373 ++cptr; 374 return; 375 } 376 } 377 } 378 379 static void 380 copy_text(void) 381 { 382 int c; 383 int quote; 384 FILE *f = text_file; 385 int need_newline = 0; 386 int t_lineno = lineno; 387 char *t_line = dup_line(); 388 char *t_cptr = t_line + (cptr - line - 2); 389 390 if (*cptr == '\n') 391 { 392 get_line(); 393 if (line == 0) 394 unterminated_text(t_lineno, t_line, t_cptr); 395 } 396 if (!lflag) 397 fprintf(f, line_format, lineno, input_file_name); 398 399 loop: 400 c = *cptr++; 401 switch (c) 402 { 403 case '\n': 404 next_line: 405 putc('\n', f); 406 need_newline = 0; 407 get_line(); 408 if (line) 409 goto loop; 410 unterminated_text(t_lineno, t_line, t_cptr); 411 412 case '\'': 413 case '"': 414 { 415 int s_lineno = lineno; 416 char *s_line = dup_line(); 417 char *s_cptr = s_line + (cptr - line - 1); 418 419 quote = c; 420 putc(c, f); 421 for (;;) 422 { 423 c = *cptr++; 424 putc(c, f); 425 if (c == quote) 426 { 427 need_newline = 1; 428 FREE(s_line); 429 goto loop; 430 } 431 if (c == '\n') 432 unterminated_string(s_lineno, s_line, s_cptr); 433 if (c == '\\') 434 { 435 c = *cptr++; 436 putc(c, f); 437 if (c == '\n') 438 { 439 get_line(); 440 if (line == 0) 441 unterminated_string(s_lineno, s_line, s_cptr); 442 } 443 } 444 } 445 } 446 447 case '/': 448 putc(c, f); 449 need_newline = 1; 450 c = *cptr; 451 if (c == '/') 452 { 453 putc('*', f); 454 while ((c = *++cptr) != '\n') 455 { 456 if (c == '*' && cptr[1] == '/') 457 fprintf(f, "* "); 458 else 459 putc(c, f); 460 } 461 fprintf(f, "*/"); 462 goto next_line; 463 } 464 if (c == '*') 465 { 466 int c_lineno = lineno; 467 char *c_line = dup_line(); 468 char *c_cptr = c_line + (cptr - line - 1); 469 470 putc('*', f); 471 ++cptr; 472 for (;;) 473 { 474 c = *cptr++; 475 putc(c, f); 476 if (c == '*' && *cptr == '/') 477 { 478 putc('/', f); 479 ++cptr; 480 FREE(c_line); 481 goto loop; 482 } 483 if (c == '\n') 484 { 485 get_line(); 486 if (line == 0) 487 unterminated_comment(c_lineno, c_line, c_cptr); 488 } 489 } 490 } 491 need_newline = 1; 492 goto loop; 493 494 case '%': 495 case '\\': 496 if (*cptr == R_CURL) 497 { 498 if (need_newline) 499 putc('\n', f); 500 ++cptr; 501 FREE(t_line); 502 return; 503 } 504 /* FALLTHRU */ 505 506 default: 507 putc(c, f); 508 need_newline = 1; 509 goto loop; 510 } 511 } 512 513 static void 514 puts_both(const char *s) 515 { 516 fputs(s, text_file); 517 if (dflag) 518 fputs(s, union_file); 519 } 520 521 static void 522 putc_both(int c) 523 { 524 putc(c, text_file); 525 if (dflag) 526 putc(c, union_file); 527 } 528 529 static void 530 copy_union(void) 531 { 532 int c; 533 int quote; 534 int depth; 535 int u_lineno = lineno; 536 char *u_line = dup_line(); 537 char *u_cptr = u_line + (cptr - line - 6); 538 539 if (unionized) 540 over_unionized(cptr - 6); 541 unionized = 1; 542 543 if (!lflag) 544 fprintf(text_file, line_format, lineno, input_file_name); 545 546 puts_both("#ifdef YYSTYPE\n"); 547 puts_both("#undef YYSTYPE_IS_DECLARED\n"); 548 puts_both("#define YYSTYPE_IS_DECLARED 1\n"); 549 puts_both("#endif\n"); 550 puts_both("#ifndef YYSTYPE_IS_DECLARED\n"); 551 puts_both("#define YYSTYPE_IS_DECLARED 1\n"); 552 puts_both("typedef union"); 553 554 depth = 0; 555 loop: 556 c = *cptr++; 557 putc_both(c); 558 switch (c) 559 { 560 case '\n': 561 next_line: 562 get_line(); 563 if (line == 0) 564 unterminated_union(u_lineno, u_line, u_cptr); 565 goto loop; 566 567 case L_CURL: 568 ++depth; 569 goto loop; 570 571 case R_CURL: 572 if (--depth == 0) 573 { 574 puts_both(" YYSTYPE;\n"); 575 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n"); 576 FREE(u_line); 577 return; 578 } 579 goto loop; 580 581 case '\'': 582 case '"': 583 { 584 int s_lineno = lineno; 585 char *s_line = dup_line(); 586 char *s_cptr = s_line + (cptr - line - 1); 587 588 quote = c; 589 for (;;) 590 { 591 c = *cptr++; 592 putc_both(c); 593 if (c == quote) 594 { 595 FREE(s_line); 596 goto loop; 597 } 598 if (c == '\n') 599 unterminated_string(s_lineno, s_line, s_cptr); 600 if (c == '\\') 601 { 602 c = *cptr++; 603 putc_both(c); 604 if (c == '\n') 605 { 606 get_line(); 607 if (line == 0) 608 unterminated_string(s_lineno, s_line, s_cptr); 609 } 610 } 611 } 612 } 613 614 case '/': 615 c = *cptr; 616 if (c == '/') 617 { 618 putc_both('*'); 619 while ((c = *++cptr) != '\n') 620 { 621 if (c == '*' && cptr[1] == '/') 622 { 623 puts_both("* "); 624 } 625 else 626 { 627 putc_both(c); 628 } 629 } 630 puts_both("*/\n"); 631 goto next_line; 632 } 633 if (c == '*') 634 { 635 int c_lineno = lineno; 636 char *c_line = dup_line(); 637 char *c_cptr = c_line + (cptr - line - 1); 638 639 putc_both('*'); 640 ++cptr; 641 for (;;) 642 { 643 c = *cptr++; 644 putc_both(c); 645 if (c == '*' && *cptr == '/') 646 { 647 putc_both('/'); 648 ++cptr; 649 FREE(c_line); 650 goto loop; 651 } 652 if (c == '\n') 653 { 654 get_line(); 655 if (line == 0) 656 unterminated_comment(c_lineno, c_line, c_cptr); 657 } 658 } 659 } 660 goto loop; 661 662 default: 663 goto loop; 664 } 665 } 666 667 /* 668 * Keep a linked list of parameters 669 */ 670 static void 671 copy_param(int k) 672 { 673 char *buf; 674 int c; 675 param *head, *p; 676 int i; 677 int name, type2; 678 679 c = nextc(); 680 if (c == EOF) 681 unexpected_EOF(); 682 if (c != '{') 683 goto out; 684 cptr++; 685 686 c = nextc(); 687 if (c == EOF) 688 unexpected_EOF(); 689 if (c == '}') 690 goto out; 691 692 buf = MALLOC(linesize); 693 NO_SPACE(buf); 694 695 for (i = 0; (c = *cptr++) != '}'; i++) 696 { 697 if (c == '\0') 698 missing_brace(); 699 if (c == EOF) 700 unexpected_EOF(); 701 buf[i] = (char)c; 702 } 703 704 if (i == 0) 705 goto out; 706 707 buf[i--] = '\0'; 708 while (i >= 0 && isspace(UCH(buf[i]))) 709 buf[i--] = '\0'; 710 711 if (buf[i] == ']') 712 { 713 int level = 1; 714 while (i >= 0 && level > 0 && buf[i] != '[') 715 { 716 if (buf[i] == ']') 717 ++level; 718 else if (buf[i] == '[') 719 --level; 720 i--; 721 } 722 if (i <= 0) 723 unexpected_EOF(); 724 type2 = i--; 725 } 726 else 727 { 728 type2 = i + 1; 729 } 730 731 while (i >= 0 && (isalnum(UCH(buf[i])) || 732 UCH(buf[i]) == '_')) 733 i--; 734 735 if (!isspace(UCH(buf[i])) && buf[i] != '*') 736 goto out; 737 738 name = i + 1; 739 740 p = MALLOC(sizeof(*p)); 741 NO_SPACE(p); 742 743 p->type2 = strdup(buf + type2); 744 NO_SPACE(p->type2); 745 746 buf[type2] = '\0'; 747 748 p->name = strdup(buf + name); 749 NO_SPACE(p->name); 750 751 buf[name] = '\0'; 752 p->type = buf; 753 754 if (k == LEX_PARAM) 755 head = lex_param; 756 else 757 head = parse_param; 758 759 if (head != NULL) 760 { 761 while (head->next) 762 head = head->next; 763 head->next = p; 764 } 765 else 766 { 767 if (k == LEX_PARAM) 768 lex_param = p; 769 else 770 parse_param = p; 771 } 772 p->next = NULL; 773 return; 774 775 out: 776 syntax_error(lineno, line, cptr); 777 } 778 779 static int 780 hexval(int c) 781 { 782 if (c >= '0' && c <= '9') 783 return (c - '0'); 784 if (c >= 'A' && c <= 'F') 785 return (c - 'A' + 10); 786 if (c >= 'a' && c <= 'f') 787 return (c - 'a' + 10); 788 return (-1); 789 } 790 791 static bucket * 792 get_literal(void) 793 { 794 int c, quote; 795 int i; 796 int n; 797 char *s; 798 bucket *bp; 799 int s_lineno = lineno; 800 char *s_line = dup_line(); 801 char *s_cptr = s_line + (cptr - line); 802 803 quote = *cptr++; 804 cinc = 0; 805 for (;;) 806 { 807 c = *cptr++; 808 if (c == quote) 809 break; 810 if (c == '\n') 811 unterminated_string(s_lineno, s_line, s_cptr); 812 if (c == '\\') 813 { 814 char *c_cptr = cptr - 1; 815 816 c = *cptr++; 817 switch (c) 818 { 819 case '\n': 820 get_line(); 821 if (line == 0) 822 unterminated_string(s_lineno, s_line, s_cptr); 823 continue; 824 825 case '0': 826 case '1': 827 case '2': 828 case '3': 829 case '4': 830 case '5': 831 case '6': 832 case '7': 833 n = c - '0'; 834 c = *cptr; 835 if (IS_OCTAL(c)) 836 { 837 n = (n << 3) + (c - '0'); 838 c = *++cptr; 839 if (IS_OCTAL(c)) 840 { 841 n = (n << 3) + (c - '0'); 842 ++cptr; 843 } 844 } 845 if (n > MAXCHAR) 846 illegal_character(c_cptr); 847 c = n; 848 break; 849 850 case 'x': 851 c = *cptr++; 852 n = hexval(c); 853 if (n < 0 || n >= 16) 854 illegal_character(c_cptr); 855 for (;;) 856 { 857 c = *cptr; 858 i = hexval(c); 859 if (i < 0 || i >= 16) 860 break; 861 ++cptr; 862 n = (n << 4) + i; 863 if (n > MAXCHAR) 864 illegal_character(c_cptr); 865 } 866 c = n; 867 break; 868 869 case 'a': 870 c = 7; 871 break; 872 case 'b': 873 c = '\b'; 874 break; 875 case 'f': 876 c = '\f'; 877 break; 878 case 'n': 879 c = '\n'; 880 break; 881 case 'r': 882 c = '\r'; 883 break; 884 case 't': 885 c = '\t'; 886 break; 887 case 'v': 888 c = '\v'; 889 break; 890 } 891 } 892 cachec(c); 893 } 894 FREE(s_line); 895 896 n = cinc; 897 s = MALLOC(n); 898 NO_SPACE(s); 899 900 for (i = 0; i < n; ++i) 901 s[i] = cache[i]; 902 903 cinc = 0; 904 if (n == 1) 905 cachec('\''); 906 else 907 cachec('"'); 908 909 for (i = 0; i < n; ++i) 910 { 911 c = UCH(s[i]); 912 if (c == '\\' || c == cache[0]) 913 { 914 cachec('\\'); 915 cachec(c); 916 } 917 else if (isprint(c)) 918 cachec(c); 919 else 920 { 921 cachec('\\'); 922 switch (c) 923 { 924 case 7: 925 cachec('a'); 926 break; 927 case '\b': 928 cachec('b'); 929 break; 930 case '\f': 931 cachec('f'); 932 break; 933 case '\n': 934 cachec('n'); 935 break; 936 case '\r': 937 cachec('r'); 938 break; 939 case '\t': 940 cachec('t'); 941 break; 942 case '\v': 943 cachec('v'); 944 break; 945 default: 946 cachec(((c >> 6) & 7) + '0'); 947 cachec(((c >> 3) & 7) + '0'); 948 cachec((c & 7) + '0'); 949 break; 950 } 951 } 952 } 953 954 if (n == 1) 955 cachec('\''); 956 else 957 cachec('"'); 958 959 cachec(NUL); 960 bp = lookup(cache); 961 bp->class = TERM; 962 if (n == 1 && bp->value == UNDEFINED) 963 bp->value = UCH(*s); 964 FREE(s); 965 966 return (bp); 967 } 968 969 static int 970 is_reserved(char *name) 971 { 972 char *s; 973 974 if (strcmp(name, ".") == 0 || 975 strcmp(name, "$accept") == 0 || 976 strcmp(name, "$end") == 0) 977 return (1); 978 979 if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2]))) 980 { 981 s = name + 3; 982 while (isdigit(UCH(*s))) 983 ++s; 984 if (*s == NUL) 985 return (1); 986 } 987 988 return (0); 989 } 990 991 static bucket * 992 get_name(void) 993 { 994 int c; 995 996 cinc = 0; 997 for (c = *cptr; IS_IDENT(c); c = *++cptr) 998 cachec(c); 999 cachec(NUL); 1000 1001 if (is_reserved(cache)) 1002 used_reserved(cache); 1003 1004 return (lookup(cache)); 1005 } 1006 1007 static Value_t 1008 get_number(void) 1009 { 1010 int c; 1011 Value_t n; 1012 1013 n = 0; 1014 for (c = *cptr; isdigit(c); c = *++cptr) 1015 n = (Value_t) (10 * n + (c - '0')); 1016 1017 return (n); 1018 } 1019 1020 static char * 1021 get_tag(void) 1022 { 1023 int c; 1024 int i; 1025 char *s; 1026 int t_lineno = lineno; 1027 char *t_line = dup_line(); 1028 char *t_cptr = t_line + (cptr - line); 1029 1030 ++cptr; 1031 c = nextc(); 1032 if (c == EOF) 1033 unexpected_EOF(); 1034 if (!isalpha(c) && c != '_' && c != '$') 1035 illegal_tag(t_lineno, t_line, t_cptr); 1036 1037 cinc = 0; 1038 do 1039 { 1040 cachec(c); 1041 c = *++cptr; 1042 } 1043 while (IS_IDENT(c)); 1044 cachec(NUL); 1045 1046 c = nextc(); 1047 if (c == EOF) 1048 unexpected_EOF(); 1049 if (c != '>') 1050 illegal_tag(t_lineno, t_line, t_cptr); 1051 ++cptr; 1052 1053 for (i = 0; i < ntags; ++i) 1054 { 1055 if (strcmp(cache, tag_table[i]) == 0) 1056 { 1057 FREE(t_line); 1058 return (tag_table[i]); 1059 } 1060 } 1061 1062 if (ntags >= tagmax) 1063 { 1064 tagmax += 16; 1065 tag_table = (char **) 1066 (tag_table 1067 ? REALLOC(tag_table, (unsigned)tagmax * sizeof(char *)) 1068 : MALLOC((unsigned)tagmax * sizeof(char *))); 1069 NO_SPACE(tag_table); 1070 } 1071 1072 s = MALLOC(cinc); 1073 NO_SPACE(s); 1074 1075 strcpy(s, cache); 1076 tag_table[ntags] = s; 1077 ++ntags; 1078 FREE(t_line); 1079 return (s); 1080 } 1081 1082 static void 1083 declare_tokens(int assoc) 1084 { 1085 int c; 1086 bucket *bp; 1087 Value_t value; 1088 char *tag = 0; 1089 1090 if (assoc != TOKEN) 1091 ++prec; 1092 1093 c = nextc(); 1094 if (c == EOF) 1095 unexpected_EOF(); 1096 if (c == '<') 1097 { 1098 tag = get_tag(); 1099 c = nextc(); 1100 if (c == EOF) 1101 unexpected_EOF(); 1102 } 1103 1104 for (;;) 1105 { 1106 if (isalpha(c) || c == '_' || c == '.' || c == '$') 1107 bp = get_name(); 1108 else if (c == '\'' || c == '"') 1109 bp = get_literal(); 1110 else 1111 return; 1112 1113 if (bp == goal) 1114 tokenized_start(bp->name); 1115 bp->class = TERM; 1116 1117 if (tag) 1118 { 1119 if (bp->tag && tag != bp->tag) 1120 retyped_warning(bp->name); 1121 bp->tag = tag; 1122 } 1123 1124 if (assoc != TOKEN) 1125 { 1126 if (bp->prec && prec != bp->prec) 1127 reprec_warning(bp->name); 1128 bp->assoc = (Assoc_t) assoc; 1129 bp->prec = prec; 1130 } 1131 1132 c = nextc(); 1133 if (c == EOF) 1134 unexpected_EOF(); 1135 1136 if (isdigit(c)) 1137 { 1138 value = get_number(); 1139 if (bp->value != UNDEFINED && value != bp->value) 1140 revalued_warning(bp->name); 1141 bp->value = value; 1142 c = nextc(); 1143 if (c == EOF) 1144 unexpected_EOF(); 1145 } 1146 } 1147 } 1148 1149 /* 1150 * %expect requires special handling 1151 * as it really isn't part of the yacc 1152 * grammar only a flag for yacc proper. 1153 */ 1154 static void 1155 declare_expect(int assoc) 1156 { 1157 int c; 1158 1159 if (assoc != EXPECT && assoc != EXPECT_RR) 1160 ++prec; 1161 1162 /* 1163 * Stay away from nextc - doesn't 1164 * detect EOL and will read to EOF. 1165 */ 1166 c = *++cptr; 1167 if (c == EOF) 1168 unexpected_EOF(); 1169 1170 for (;;) 1171 { 1172 if (isdigit(c)) 1173 { 1174 if (assoc == EXPECT) 1175 SRexpect = get_number(); 1176 else 1177 RRexpect = get_number(); 1178 break; 1179 } 1180 /* 1181 * Looking for number before EOL. 1182 * Spaces, tabs, and numbers are ok, 1183 * words, punc., etc. are syntax errors. 1184 */ 1185 else if (c == '\n' || isalpha(c) || !isspace(c)) 1186 { 1187 syntax_error(lineno, line, cptr); 1188 } 1189 else 1190 { 1191 c = *++cptr; 1192 if (c == EOF) 1193 unexpected_EOF(); 1194 } 1195 } 1196 } 1197 1198 static void 1199 declare_types(void) 1200 { 1201 int c; 1202 bucket *bp; 1203 char *tag; 1204 1205 c = nextc(); 1206 if (c == EOF) 1207 unexpected_EOF(); 1208 if (c != '<') 1209 syntax_error(lineno, line, cptr); 1210 tag = get_tag(); 1211 1212 for (;;) 1213 { 1214 c = nextc(); 1215 if (isalpha(c) || c == '_' || c == '.' || c == '$') 1216 bp = get_name(); 1217 else if (c == '\'' || c == '"') 1218 bp = get_literal(); 1219 else 1220 return; 1221 1222 if (bp->tag && tag != bp->tag) 1223 retyped_warning(bp->name); 1224 bp->tag = tag; 1225 } 1226 } 1227 1228 static void 1229 declare_start(void) 1230 { 1231 int c; 1232 bucket *bp; 1233 1234 c = nextc(); 1235 if (c == EOF) 1236 unexpected_EOF(); 1237 if (!isalpha(c) && c != '_' && c != '.' && c != '$') 1238 syntax_error(lineno, line, cptr); 1239 bp = get_name(); 1240 if (bp->class == TERM) 1241 terminal_start(bp->name); 1242 if (goal && goal != bp) 1243 restarted_warning(); 1244 goal = bp; 1245 } 1246 1247 static void 1248 read_declarations(void) 1249 { 1250 int c, k; 1251 1252 cache_size = 256; 1253 cache = MALLOC(cache_size); 1254 NO_SPACE(cache); 1255 1256 for (;;) 1257 { 1258 c = nextc(); 1259 if (c == EOF) 1260 unexpected_EOF(); 1261 if (c != '%') 1262 syntax_error(lineno, line, cptr); 1263 switch (k = keyword()) 1264 { 1265 case MARK: 1266 return; 1267 1268 case IDENT: 1269 copy_ident(); 1270 break; 1271 1272 case TEXT: 1273 copy_text(); 1274 break; 1275 1276 case UNION: 1277 copy_union(); 1278 break; 1279 1280 case TOKEN: 1281 case LEFT: 1282 case RIGHT: 1283 case NONASSOC: 1284 declare_tokens(k); 1285 break; 1286 1287 case EXPECT: 1288 case EXPECT_RR: 1289 declare_expect(k); 1290 break; 1291 1292 case TYPE: 1293 declare_types(); 1294 break; 1295 1296 case START: 1297 declare_start(); 1298 break; 1299 1300 case PURE_PARSER: 1301 pure_parser = 1; 1302 break; 1303 1304 case PARSE_PARAM: 1305 case LEX_PARAM: 1306 copy_param(k); 1307 break; 1308 1309 case POSIX_YACC: 1310 /* noop for bison compatibility. byacc is already designed to be posix 1311 * yacc compatible. */ 1312 break; 1313 } 1314 } 1315 } 1316 1317 static void 1318 initialize_grammar(void) 1319 { 1320 nitems = 4; 1321 maxitems = 300; 1322 1323 pitem = (bucket **)MALLOC((unsigned)maxitems * sizeof(bucket *)); 1324 NO_SPACE(pitem); 1325 1326 pitem[0] = 0; 1327 pitem[1] = 0; 1328 pitem[2] = 0; 1329 pitem[3] = 0; 1330 1331 nrules = 3; 1332 maxrules = 100; 1333 1334 plhs = (bucket **)MALLOC((unsigned)maxrules * sizeof(bucket *)); 1335 NO_SPACE(plhs); 1336 1337 plhs[0] = 0; 1338 plhs[1] = 0; 1339 plhs[2] = 0; 1340 1341 rprec = (short *)MALLOC((unsigned)maxrules * sizeof(short)); 1342 NO_SPACE(rprec); 1343 1344 rprec[0] = 0; 1345 rprec[1] = 0; 1346 rprec[2] = 0; 1347 1348 rassoc = (char *)MALLOC((unsigned)maxrules * sizeof(char)); 1349 NO_SPACE(rassoc); 1350 1351 rassoc[0] = TOKEN; 1352 rassoc[1] = TOKEN; 1353 rassoc[2] = TOKEN; 1354 } 1355 1356 static void 1357 expand_items(void) 1358 { 1359 maxitems += 300; 1360 pitem = (bucket **)REALLOC(pitem, (unsigned)maxitems * sizeof(bucket *)); 1361 NO_SPACE(pitem); 1362 } 1363 1364 static void 1365 expand_rules(void) 1366 { 1367 maxrules += 100; 1368 1369 plhs = (bucket **)REALLOC(plhs, (unsigned)maxrules * sizeof(bucket *)); 1370 NO_SPACE(plhs); 1371 1372 rprec = (short *)REALLOC(rprec, (unsigned)maxrules * sizeof(short)); 1373 NO_SPACE(rprec); 1374 1375 rassoc = (char *)REALLOC(rassoc, (unsigned)maxrules * sizeof(char)); 1376 NO_SPACE(rassoc); 1377 } 1378 1379 static void 1380 advance_to_start(void) 1381 { 1382 int c; 1383 bucket *bp; 1384 char *s_cptr; 1385 int s_lineno; 1386 1387 for (;;) 1388 { 1389 c = nextc(); 1390 if (c != '%') 1391 break; 1392 s_cptr = cptr; 1393 switch (keyword()) 1394 { 1395 case MARK: 1396 no_grammar(); 1397 1398 case TEXT: 1399 copy_text(); 1400 break; 1401 1402 case START: 1403 declare_start(); 1404 break; 1405 1406 default: 1407 syntax_error(lineno, line, s_cptr); 1408 } 1409 } 1410 1411 c = nextc(); 1412 if (!isalpha(c) && c != '_' && c != '.' && c != '_') 1413 syntax_error(lineno, line, cptr); 1414 bp = get_name(); 1415 if (goal == 0) 1416 { 1417 if (bp->class == TERM) 1418 terminal_start(bp->name); 1419 goal = bp; 1420 } 1421 1422 s_lineno = lineno; 1423 c = nextc(); 1424 if (c == EOF) 1425 unexpected_EOF(); 1426 if (c != ':') 1427 syntax_error(lineno, line, cptr); 1428 start_rule(bp, s_lineno); 1429 ++cptr; 1430 } 1431 1432 static void 1433 start_rule(bucket *bp, int s_lineno) 1434 { 1435 if (bp->class == TERM) 1436 terminal_lhs(s_lineno); 1437 bp->class = NONTERM; 1438 if (nrules >= maxrules) 1439 expand_rules(); 1440 plhs[nrules] = bp; 1441 rprec[nrules] = UNDEFINED; 1442 rassoc[nrules] = TOKEN; 1443 } 1444 1445 static void 1446 end_rule(void) 1447 { 1448 int i; 1449 1450 if (!last_was_action && plhs[nrules]->tag) 1451 { 1452 if (pitem[nitems - 1]) 1453 { 1454 for (i = nitems - 1; (i > 0) && pitem[i]; --i) 1455 continue; 1456 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag) 1457 default_action_warning(); 1458 } 1459 else 1460 { 1461 default_action_warning(); 1462 } 1463 } 1464 1465 last_was_action = 0; 1466 if (nitems >= maxitems) 1467 expand_items(); 1468 pitem[nitems] = 0; 1469 ++nitems; 1470 ++nrules; 1471 } 1472 1473 static void 1474 insert_empty_rule(void) 1475 { 1476 bucket *bp, **bpp; 1477 1478 assert(cache); 1479 sprintf(cache, "$$%d", ++gensym); 1480 bp = make_bucket(cache); 1481 last_symbol->next = bp; 1482 last_symbol = bp; 1483 bp->tag = plhs[nrules]->tag; 1484 bp->class = NONTERM; 1485 1486 if ((nitems += 2) > maxitems) 1487 expand_items(); 1488 bpp = pitem + nitems - 1; 1489 *bpp-- = bp; 1490 while ((bpp[0] = bpp[-1]) != 0) 1491 --bpp; 1492 1493 if (++nrules >= maxrules) 1494 expand_rules(); 1495 plhs[nrules] = plhs[nrules - 1]; 1496 plhs[nrules - 1] = bp; 1497 rprec[nrules] = rprec[nrules - 1]; 1498 rprec[nrules - 1] = 0; 1499 rassoc[nrules] = rassoc[nrules - 1]; 1500 rassoc[nrules - 1] = TOKEN; 1501 } 1502 1503 static void 1504 add_symbol(void) 1505 { 1506 int c; 1507 bucket *bp; 1508 int s_lineno = lineno; 1509 1510 c = *cptr; 1511 if (c == '\'' || c == '"') 1512 bp = get_literal(); 1513 else 1514 bp = get_name(); 1515 1516 c = nextc(); 1517 if (c == ':') 1518 { 1519 end_rule(); 1520 start_rule(bp, s_lineno); 1521 ++cptr; 1522 return; 1523 } 1524 1525 if (last_was_action) 1526 insert_empty_rule(); 1527 last_was_action = 0; 1528 1529 if (++nitems > maxitems) 1530 expand_items(); 1531 pitem[nitems - 1] = bp; 1532 } 1533 1534 static char * 1535 after_blanks(char *s) 1536 { 1537 while (*s != '\0' && isspace(UCH(*s))) 1538 ++s; 1539 return s; 1540 } 1541 1542 static void 1543 copy_action(void) 1544 { 1545 int c; 1546 int i, n; 1547 int depth; 1548 int quote; 1549 char *tag; 1550 FILE *f = action_file; 1551 int a_lineno = lineno; 1552 char *a_line = dup_line(); 1553 char *a_cptr = a_line + (cptr - line); 1554 1555 if (last_was_action) 1556 insert_empty_rule(); 1557 last_was_action = 1; 1558 1559 fprintf(f, "case %d:\n", nrules - 2); 1560 if (!lflag) 1561 fprintf(f, line_format, lineno, input_file_name); 1562 if (*cptr == '=') 1563 ++cptr; 1564 1565 /* avoid putting curly-braces in first column, to ease editing */ 1566 if (*after_blanks(cptr) == L_CURL) 1567 { 1568 putc('\t', f); 1569 cptr = after_blanks(cptr); 1570 } 1571 1572 n = 0; 1573 for (i = nitems - 1; pitem[i]; --i) 1574 ++n; 1575 1576 depth = 0; 1577 loop: 1578 c = *cptr; 1579 if (c == '$') 1580 { 1581 if (cptr[1] == '<') 1582 { 1583 int d_lineno = lineno; 1584 char *d_line = dup_line(); 1585 char *d_cptr = d_line + (cptr - line); 1586 1587 ++cptr; 1588 tag = get_tag(); 1589 c = *cptr; 1590 if (c == '$') 1591 { 1592 fprintf(f, "yyval.%s", tag); 1593 ++cptr; 1594 FREE(d_line); 1595 goto loop; 1596 } 1597 else if (isdigit(c)) 1598 { 1599 i = get_number(); 1600 if (i > n) 1601 dollar_warning(d_lineno, i); 1602 fprintf(f, "yystack.l_mark[%d].%s", i - n, tag); 1603 FREE(d_line); 1604 goto loop; 1605 } 1606 else if (c == '-' && isdigit(UCH(cptr[1]))) 1607 { 1608 ++cptr; 1609 i = -get_number() - n; 1610 fprintf(f, "yystack.l_mark[%d].%s", i, tag); 1611 FREE(d_line); 1612 goto loop; 1613 } 1614 else 1615 dollar_error(d_lineno, d_line, d_cptr); 1616 } 1617 else if (cptr[1] == '$') 1618 { 1619 if (ntags) 1620 { 1621 tag = plhs[nrules]->tag; 1622 if (tag == 0) 1623 untyped_lhs(); 1624 fprintf(f, "yyval.%s", tag); 1625 } 1626 else 1627 fprintf(f, "yyval"); 1628 cptr += 2; 1629 goto loop; 1630 } 1631 else if (isdigit(UCH(cptr[1]))) 1632 { 1633 ++cptr; 1634 i = get_number(); 1635 if (ntags) 1636 { 1637 if (i <= 0 || i > n) 1638 unknown_rhs(i); 1639 tag = pitem[nitems + i - n - 1]->tag; 1640 if (tag == 0) 1641 untyped_rhs(i, pitem[nitems + i - n - 1]->name); 1642 fprintf(f, "yystack.l_mark[%d].%s", i - n, tag); 1643 } 1644 else 1645 { 1646 if (i > n) 1647 dollar_warning(lineno, i); 1648 fprintf(f, "yystack.l_mark[%d]", i - n); 1649 } 1650 goto loop; 1651 } 1652 else if (cptr[1] == '-') 1653 { 1654 cptr += 2; 1655 i = get_number(); 1656 if (ntags) 1657 unknown_rhs(-i); 1658 fprintf(f, "yystack.l_mark[%d]", -i - n); 1659 goto loop; 1660 } 1661 } 1662 if (isalpha(c) || c == '_' || c == '$') 1663 { 1664 do 1665 { 1666 putc(c, f); 1667 c = *++cptr; 1668 } 1669 while (isalnum(c) || c == '_' || c == '$'); 1670 goto loop; 1671 } 1672 putc(c, f); 1673 ++cptr; 1674 switch (c) 1675 { 1676 case '\n': 1677 next_line: 1678 get_line(); 1679 if (line) 1680 goto loop; 1681 unterminated_action(a_lineno, a_line, a_cptr); 1682 1683 case ';': 1684 if (depth > 0) 1685 goto loop; 1686 fprintf(f, "\nbreak;\n"); 1687 free(a_line); 1688 return; 1689 1690 case L_CURL: 1691 ++depth; 1692 goto loop; 1693 1694 case R_CURL: 1695 if (--depth > 0) 1696 goto loop; 1697 fprintf(f, "\nbreak;\n"); 1698 free(a_line); 1699 return; 1700 1701 case '\'': 1702 case '"': 1703 { 1704 int s_lineno = lineno; 1705 char *s_line = dup_line(); 1706 char *s_cptr = s_line + (cptr - line - 1); 1707 1708 quote = c; 1709 for (;;) 1710 { 1711 c = *cptr++; 1712 putc(c, f); 1713 if (c == quote) 1714 { 1715 FREE(s_line); 1716 goto loop; 1717 } 1718 if (c == '\n') 1719 unterminated_string(s_lineno, s_line, s_cptr); 1720 if (c == '\\') 1721 { 1722 c = *cptr++; 1723 putc(c, f); 1724 if (c == '\n') 1725 { 1726 get_line(); 1727 if (line == 0) 1728 unterminated_string(s_lineno, s_line, s_cptr); 1729 } 1730 } 1731 } 1732 } 1733 1734 case '/': 1735 c = *cptr; 1736 if (c == '/') 1737 { 1738 putc('*', f); 1739 while ((c = *++cptr) != '\n') 1740 { 1741 if (c == '*' && cptr[1] == '/') 1742 fprintf(f, "* "); 1743 else 1744 putc(c, f); 1745 } 1746 fprintf(f, "*/\n"); 1747 goto next_line; 1748 } 1749 if (c == '*') 1750 { 1751 int c_lineno = lineno; 1752 char *c_line = dup_line(); 1753 char *c_cptr = c_line + (cptr - line - 1); 1754 1755 putc('*', f); 1756 ++cptr; 1757 for (;;) 1758 { 1759 c = *cptr++; 1760 putc(c, f); 1761 if (c == '*' && *cptr == '/') 1762 { 1763 putc('/', f); 1764 ++cptr; 1765 FREE(c_line); 1766 goto loop; 1767 } 1768 if (c == '\n') 1769 { 1770 get_line(); 1771 if (line == 0) 1772 unterminated_comment(c_lineno, c_line, c_cptr); 1773 } 1774 } 1775 } 1776 goto loop; 1777 1778 default: 1779 goto loop; 1780 } 1781 } 1782 1783 static int 1784 mark_symbol(void) 1785 { 1786 int c; 1787 bucket *bp; 1788 1789 c = cptr[1]; 1790 if (c == '%' || c == '\\') 1791 { 1792 cptr += 2; 1793 return (1); 1794 } 1795 1796 if (c == '=') 1797 cptr += 2; 1798 else if ((c == 'p' || c == 'P') && 1799 ((c = cptr[2]) == 'r' || c == 'R') && 1800 ((c = cptr[3]) == 'e' || c == 'E') && 1801 ((c = cptr[4]) == 'c' || c == 'C') && 1802 ((c = cptr[5], !IS_IDENT(c)))) 1803 cptr += 5; 1804 else 1805 syntax_error(lineno, line, cptr); 1806 1807 c = nextc(); 1808 if (isalpha(c) || c == '_' || c == '.' || c == '$') 1809 bp = get_name(); 1810 else if (c == '\'' || c == '"') 1811 bp = get_literal(); 1812 else 1813 { 1814 syntax_error(lineno, line, cptr); 1815 /*NOTREACHED */ 1816 } 1817 1818 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules]) 1819 prec_redeclared(); 1820 1821 rprec[nrules] = bp->prec; 1822 rassoc[nrules] = bp->assoc; 1823 return (0); 1824 } 1825 1826 static void 1827 read_grammar(void) 1828 { 1829 int c; 1830 1831 initialize_grammar(); 1832 advance_to_start(); 1833 1834 for (;;) 1835 { 1836 c = nextc(); 1837 if (c == EOF) 1838 break; 1839 if (isalpha(c) 1840 || c == '_' 1841 || c == '.' 1842 || c == '$' 1843 || c == '\'' 1844 || c == '"') 1845 add_symbol(); 1846 else if (c == L_CURL || c == '=') 1847 copy_action(); 1848 else if (c == '|') 1849 { 1850 end_rule(); 1851 start_rule(plhs[nrules - 1], 0); 1852 ++cptr; 1853 } 1854 else if (c == '%') 1855 { 1856 if (mark_symbol()) 1857 break; 1858 } 1859 else 1860 syntax_error(lineno, line, cptr); 1861 } 1862 end_rule(); 1863 } 1864 1865 static void 1866 free_tags(void) 1867 { 1868 int i; 1869 1870 if (tag_table == 0) 1871 return; 1872 1873 for (i = 0; i < ntags; ++i) 1874 { 1875 assert(tag_table[i]); 1876 FREE(tag_table[i]); 1877 } 1878 FREE(tag_table); 1879 } 1880 1881 static void 1882 pack_names(void) 1883 { 1884 bucket *bp; 1885 char *p, *s, *t; 1886 1887 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */ 1888 for (bp = first_symbol; bp; bp = bp->next) 1889 name_pool_size += strlen(bp->name) + 1; 1890 1891 name_pool = MALLOC(name_pool_size); 1892 NO_SPACE(name_pool); 1893 1894 strlcpy(name_pool, "$accept", name_pool_size); 1895 strlcpy(name_pool + 8, "$end", name_pool_size - 8); 1896 t = name_pool + 13; 1897 for (bp = first_symbol; bp; bp = bp->next) 1898 { 1899 p = t; 1900 s = bp->name; 1901 while ((*t++ = *s++) != 0) 1902 continue; 1903 FREE(bp->name); 1904 bp->name = p; 1905 } 1906 } 1907 1908 static void 1909 check_symbols(void) 1910 { 1911 bucket *bp; 1912 1913 if (goal->class == UNKNOWN) 1914 undefined_goal(goal->name); 1915 1916 for (bp = first_symbol; bp; bp = bp->next) 1917 { 1918 if (bp->class == UNKNOWN) 1919 { 1920 undefined_symbol_warning(bp->name); 1921 bp->class = TERM; 1922 } 1923 } 1924 } 1925 1926 static void 1927 protect_string(char *src, char **des) 1928 { 1929 unsigned len; 1930 char *s; 1931 char *d; 1932 1933 *des = src; 1934 if (src) 1935 { 1936 len = 1; 1937 s = src; 1938 while (*s) 1939 { 1940 if ('\\' == *s || '"' == *s) 1941 len++; 1942 s++; 1943 len++; 1944 } 1945 1946 *des = d = (char *)MALLOC(len); 1947 NO_SPACE(d); 1948 1949 s = src; 1950 while (*s) 1951 { 1952 if ('\\' == *s || '"' == *s) 1953 *d++ = '\\'; 1954 *d++ = *s++; 1955 } 1956 *d = '\0'; 1957 } 1958 } 1959 1960 static void 1961 pack_symbols(void) 1962 { 1963 bucket *bp; 1964 bucket **v; 1965 Value_t i, j, k, n; 1966 1967 nsyms = 2; 1968 ntokens = 1; 1969 for (bp = first_symbol; bp; bp = bp->next) 1970 { 1971 ++nsyms; 1972 if (bp->class == TERM) 1973 ++ntokens; 1974 } 1975 start_symbol = (Value_t) ntokens; 1976 nvars = nsyms - ntokens; 1977 1978 symbol_name = (char **)MALLOC((unsigned)nsyms * sizeof(char *)); 1979 NO_SPACE(symbol_name); 1980 1981 symbol_value = (short *)MALLOC((unsigned)nsyms * sizeof(short)); 1982 NO_SPACE(symbol_value); 1983 1984 symbol_prec = (short *)MALLOC((unsigned)nsyms * sizeof(short)); 1985 NO_SPACE(symbol_prec); 1986 1987 symbol_assoc = MALLOC(nsyms); 1988 NO_SPACE(symbol_assoc); 1989 1990 v = (bucket **)MALLOC((unsigned)nsyms * sizeof(bucket *)); 1991 NO_SPACE(v); 1992 1993 v[0] = 0; 1994 v[start_symbol] = 0; 1995 1996 i = 1; 1997 j = (Value_t) (start_symbol + 1); 1998 for (bp = first_symbol; bp; bp = bp->next) 1999 { 2000 if (bp->class == TERM) 2001 v[i++] = bp; 2002 else 2003 v[j++] = bp; 2004 } 2005 assert(i == ntokens && j == nsyms); 2006 2007 for (i = 1; i < ntokens; ++i) 2008 v[i]->index = i; 2009 2010 goal->index = (Index_t) (start_symbol + 1); 2011 k = (Value_t) (start_symbol + 2); 2012 while (++i < nsyms) 2013 if (v[i] != goal) 2014 { 2015 v[i]->index = k; 2016 ++k; 2017 } 2018 2019 goal->value = 0; 2020 k = 1; 2021 for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i) 2022 { 2023 if (v[i] != goal) 2024 { 2025 v[i]->value = k; 2026 ++k; 2027 } 2028 } 2029 2030 k = 0; 2031 for (i = 1; i < ntokens; ++i) 2032 { 2033 n = v[i]->value; 2034 if (n > 256) 2035 { 2036 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j) 2037 symbol_value[j] = symbol_value[j - 1]; 2038 symbol_value[j] = n; 2039 } 2040 } 2041 2042 assert(v[1] != 0); 2043 2044 if (v[1]->value == UNDEFINED) 2045 v[1]->value = 256; 2046 2047 j = 0; 2048 n = 257; 2049 for (i = 2; i < ntokens; ++i) 2050 { 2051 if (v[i]->value == UNDEFINED) 2052 { 2053 while (j < k && n == symbol_value[j]) 2054 { 2055 while (++j < k && n == symbol_value[j]) 2056 continue; 2057 ++n; 2058 } 2059 v[i]->value = n; 2060 ++n; 2061 } 2062 } 2063 2064 symbol_name[0] = name_pool + 8; 2065 symbol_value[0] = 0; 2066 symbol_prec[0] = 0; 2067 symbol_assoc[0] = TOKEN; 2068 for (i = 1; i < ntokens; ++i) 2069 { 2070 symbol_name[i] = v[i]->name; 2071 symbol_value[i] = v[i]->value; 2072 symbol_prec[i] = v[i]->prec; 2073 symbol_assoc[i] = v[i]->assoc; 2074 } 2075 symbol_name[start_symbol] = name_pool; 2076 symbol_value[start_symbol] = -1; 2077 symbol_prec[start_symbol] = 0; 2078 symbol_assoc[start_symbol] = TOKEN; 2079 for (++i; i < nsyms; ++i) 2080 { 2081 k = v[i]->index; 2082 symbol_name[k] = v[i]->name; 2083 symbol_value[k] = v[i]->value; 2084 symbol_prec[k] = v[i]->prec; 2085 symbol_assoc[k] = v[i]->assoc; 2086 } 2087 2088 if (gflag) 2089 { 2090 symbol_pname = (char **)MALLOC((unsigned)nsyms * sizeof(char *)); 2091 NO_SPACE(symbol_pname); 2092 2093 for (i = 0; i < nsyms; ++i) 2094 protect_string(symbol_name[i], &(symbol_pname[i])); 2095 } 2096 2097 FREE(v); 2098 } 2099 2100 static void 2101 pack_grammar(void) 2102 { 2103 int i; 2104 Value_t j; 2105 Assoc_t assoc; 2106 Value_t prec2; 2107 2108 ritem = (short *)MALLOC((unsigned)nitems * sizeof(short)); 2109 NO_SPACE(ritem); 2110 2111 rlhs = (short *)MALLOC((unsigned)nrules * sizeof(short)); 2112 NO_SPACE(rlhs); 2113 2114 rrhs = (short *)MALLOC((unsigned)(nrules + 1) * sizeof(short)); 2115 NO_SPACE(rrhs); 2116 2117 rprec = (short *)REALLOC(rprec, (unsigned)nrules * sizeof(short)); 2118 NO_SPACE(rprec); 2119 2120 rassoc = REALLOC(rassoc, nrules); 2121 NO_SPACE(rassoc); 2122 2123 ritem[0] = -1; 2124 ritem[1] = goal->index; 2125 ritem[2] = 0; 2126 ritem[3] = -2; 2127 rlhs[0] = 0; 2128 rlhs[1] = 0; 2129 rlhs[2] = start_symbol; 2130 rrhs[0] = 0; 2131 rrhs[1] = 0; 2132 rrhs[2] = 1; 2133 2134 j = 4; 2135 for (i = 3; i < nrules; ++i) 2136 { 2137 rlhs[i] = plhs[i]->index; 2138 rrhs[i] = j; 2139 assoc = TOKEN; 2140 prec2 = 0; 2141 while (pitem[j]) 2142 { 2143 ritem[j] = pitem[j]->index; 2144 if (pitem[j]->class == TERM) 2145 { 2146 prec2 = pitem[j]->prec; 2147 assoc = pitem[j]->assoc; 2148 } 2149 ++j; 2150 } 2151 ritem[j] = (Value_t) - i; 2152 ++j; 2153 if (rprec[i] == UNDEFINED) 2154 { 2155 rprec[i] = prec2; 2156 rassoc[i] = assoc; 2157 } 2158 } 2159 rrhs[i] = j; 2160 2161 FREE(plhs); 2162 FREE(pitem); 2163 } 2164 2165 static void 2166 print_grammar(void) 2167 { 2168 int i, k; 2169 size_t j, spacing = 0; 2170 FILE *f = verbose_file; 2171 2172 if (!vflag) 2173 return; 2174 2175 k = 1; 2176 for (i = 2; i < nrules; ++i) 2177 { 2178 if (rlhs[i] != rlhs[i - 1]) 2179 { 2180 if (i != 2) 2181 fprintf(f, "\n"); 2182 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]); 2183 spacing = strlen(symbol_name[rlhs[i]]) + 1; 2184 } 2185 else 2186 { 2187 fprintf(f, "%4d ", i - 2); 2188 j = spacing; 2189 while (j-- != 0) 2190 putc(' ', f); 2191 putc('|', f); 2192 } 2193 2194 while (ritem[k] >= 0) 2195 { 2196 fprintf(f, " %s", symbol_name[ritem[k]]); 2197 ++k; 2198 } 2199 ++k; 2200 putc('\n', f); 2201 } 2202 } 2203 2204 void 2205 reader(void) 2206 { 2207 write_section(code_file, banner); 2208 create_symbol_table(); 2209 read_declarations(); 2210 read_grammar(); 2211 free_symbol_table(); 2212 free_tags(); 2213 pack_names(); 2214 check_symbols(); 2215 pack_symbols(); 2216 pack_grammar(); 2217 free_symbols(); 2218 print_grammar(); 2219 } 2220 2221 #ifdef NO_LEAKS 2222 static param * 2223 free_declarations(param * list) 2224 { 2225 while (list != 0) 2226 { 2227 param *next = list->next; 2228 free(list->type); 2229 free(list->name); 2230 free(list->type2); 2231 free(list); 2232 list = next; 2233 } 2234 return list; 2235 } 2236 2237 void 2238 reader_leaks(void) 2239 { 2240 lex_param = free_declarations(lex_param); 2241 parse_param = free_declarations(parse_param); 2242 2243 DO_FREE(line); 2244 DO_FREE(rrhs); 2245 DO_FREE(rlhs); 2246 DO_FREE(rprec); 2247 DO_FREE(ritem); 2248 DO_FREE(rassoc); 2249 DO_FREE(cache); 2250 DO_FREE(name_pool); 2251 DO_FREE(symbol_name); 2252 DO_FREE(symbol_prec); 2253 DO_FREE(symbol_assoc); 2254 DO_FREE(symbol_value); 2255 } 2256 #endif 2257