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