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