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