1 /* $NetBSD: reader.c,v 1.6 2010/12/25 23:43:30 christos Exp $ */ 2 /* Id: reader.c,v 1.31 2010/11/26 12:30:40 tom Exp */ 3 4 #include "defs.h" 5 6 #include <sys/cdefs.h> 7 __RCSID("$NetBSD: reader.c,v 1.6 2010/12/25 23:43:30 christos Exp $"); 8 9 /* The line size must be a positive integer. One hundred was chosen */ 10 /* because few lines in Yacc input grammars exceed 100 characters. */ 11 /* Note that if a line exceeds LINESIZE characters, the line buffer */ 12 /* will be expanded to accomodate it. */ 13 14 #define LINESIZE 100 15 16 #define L_CURL '{' 17 #define R_CURL '}' 18 19 static void start_rule(bucket *bp, int s_lineno); 20 21 static char *cache; 22 static int cinc, cache_size; 23 24 int ntags; 25 static int tagmax; 26 static char **tag_table; 27 28 static char saw_eof; 29 char unionized; 30 char *cptr, *line; 31 static int linesize; 32 33 static bucket *goal; 34 static Value_t prec; 35 static int gensym; 36 static char last_was_action; 37 38 static int maxitems; 39 static bucket **pitem; 40 41 static int maxrules; 42 static bucket **plhs; 43 44 static size_t name_pool_size; 45 static char *name_pool; 46 47 char line_format[] = "#line %d \"%s\"\n"; 48 49 param *lex_param; 50 param *parse_param; 51 52 static void 53 cachec(int c) 54 { 55 assert(cinc >= 0); 56 if (cinc >= cache_size) 57 { 58 cache_size += 256; 59 cache = REALLOC(cache, cache_size); 60 NO_SPACE(cache); 61 } 62 cache[cinc] = (char)c; 63 ++cinc; 64 } 65 66 static void 67 get_line(void) 68 { 69 FILE *f = input_file; 70 int c; 71 int i; 72 73 if (saw_eof || (c = getc(f)) == EOF) 74 { 75 if (line) 76 { 77 FREE(line); 78 line = 0; 79 } 80 cptr = 0; 81 saw_eof = 1; 82 return; 83 } 84 85 if (line == 0 || linesize != (LINESIZE + 1)) 86 { 87 if (line) 88 FREE(line); 89 linesize = LINESIZE + 1; 90 line = MALLOC(linesize); 91 NO_SPACE(line); 92 } 93 94 i = 0; 95 ++lineno; 96 for (;;) 97 { 98 line[i] = (char)c; 99 if (c == '\n') 100 { 101 cptr = line; 102 return; 103 } 104 if (++i >= linesize) 105 { 106 linesize += LINESIZE; 107 line = REALLOC(line, linesize); 108 NO_SPACE(line); 109 } 110 c = getc(f); 111 if (c == EOF) 112 { 113 line[i] = '\n'; 114 saw_eof = 1; 115 cptr = line; 116 return; 117 } 118 } 119 } 120 121 static char * 122 dup_line(void) 123 { 124 char *p, *s, *t; 125 126 if (line == 0) 127 return (0); 128 s = line; 129 while (*s != '\n') 130 ++s; 131 p = MALLOC(s - line + 1); 132 NO_SPACE(p); 133 134 s = line; 135 t = p; 136 while ((*t++ = *s++) != '\n') 137 continue; 138 return (p); 139 } 140 141 static void 142 skip_comment(void) 143 { 144 char *s; 145 146 int st_lineno = lineno; 147 char *st_line = dup_line(); 148 char *st_cptr = st_line + (cptr - line); 149 150 s = cptr + 2; 151 for (;;) 152 { 153 if (*s == '*' && s[1] == '/') 154 { 155 cptr = s + 2; 156 FREE(st_line); 157 return; 158 } 159 if (*s == '\n') 160 { 161 get_line(); 162 if (line == 0) 163 unterminated_comment(st_lineno, st_line, st_cptr); 164 s = cptr; 165 } 166 else 167 ++s; 168 } 169 } 170 171 static int 172 nextc(void) 173 { 174 char *s; 175 176 if (line == 0) 177 { 178 get_line(); 179 if (line == 0) 180 return (EOF); 181 } 182 183 s = cptr; 184 for (;;) 185 { 186 switch (*s) 187 { 188 case '\n': 189 get_line(); 190 if (line == 0) 191 return (EOF); 192 s = cptr; 193 break; 194 195 case ' ': 196 case '\t': 197 case '\f': 198 case '\r': 199 case '\v': 200 case ',': 201 case ';': 202 ++s; 203 break; 204 205 case '\\': 206 cptr = s; 207 return ('%'); 208 209 case '/': 210 if (s[1] == '*') 211 { 212 cptr = s; 213 skip_comment(); 214 s = cptr; 215 break; 216 } 217 else if (s[1] == '/') 218 { 219 get_line(); 220 if (line == 0) 221 return (EOF); 222 s = cptr; 223 break; 224 } 225 /* FALLTHRU */ 226 227 default: 228 cptr = s; 229 return (*s); 230 } 231 } 232 } 233 234 /* 235 * Compare keyword to cached token, treating '_' and '-' the same. Some 236 * grammars rely upon this misfeature. 237 */ 238 static int 239 matchec(const char *name) 240 { 241 const char *p = cache; 242 const char *q = name; 243 int code = 0; /* assume mismatch */ 244 245 while (*p != '\0' && *q != '\0') 246 { 247 char a = *p++; 248 char b = *q++; 249 if (a == '_') 250 a = '-'; 251 if (b == '_') 252 b = '-'; 253 if (a != b) 254 break; 255 if (*p == '\0' && *q == '\0') 256 { 257 code = 1; 258 break; 259 } 260 } 261 return code; 262 } 263 264 static int 265 keyword(void) 266 { 267 int c; 268 char *t_cptr = cptr; 269 270 c = *++cptr; 271 if (isalpha(c)) 272 { 273 cinc = 0; 274 for (;;) 275 { 276 if (isalpha(c)) 277 { 278 if (isupper(c)) 279 c = tolower(c); 280 cachec(c); 281 } 282 else if (isdigit(c) 283 || c == '-' 284 || c == '_' 285 || c == '.' 286 || c == '$') 287 { 288 cachec(c); 289 } 290 else 291 { 292 break; 293 } 294 c = *++cptr; 295 } 296 cachec(NUL); 297 298 if (matchec("token") || matchec("term")) 299 return (TOKEN); 300 if (matchec("type")) 301 return (TYPE); 302 if (matchec("left")) 303 return (LEFT); 304 if (matchec("right")) 305 return (RIGHT); 306 if (matchec("nonassoc") || matchec("binary")) 307 return (NONASSOC); 308 if (matchec("start")) 309 return (START); 310 if (matchec("union")) 311 return (UNION); 312 if (matchec("ident")) 313 return (IDENT); 314 if (matchec("expect")) 315 return (EXPECT); 316 if (matchec("expect-rr")) 317 return (EXPECT_RR); 318 if (matchec("pure-parser")) 319 return (PURE_PARSER); 320 if (matchec("parse-param")) 321 return (PARSE_PARAM); 322 if (matchec("lex-param")) 323 return (LEX_PARAM); 324 if (matchec("yacc")) 325 return (POSIX_YACC); 326 } 327 else 328 { 329 ++cptr; 330 if (c == L_CURL) 331 return (TEXT); 332 if (c == '%' || c == '\\') 333 return (MARK); 334 if (c == '<') 335 return (LEFT); 336 if (c == '>') 337 return (RIGHT); 338 if (c == '0') 339 return (TOKEN); 340 if (c == '2') 341 return (NONASSOC); 342 } 343 syntax_error(lineno, line, t_cptr); 344 /*NOTREACHED */ 345 } 346 347 348 static void 349 copy_ident(void) 350 { 351 int c; 352 FILE *f = output_file; 353 354 c = nextc(); 355 if (c == EOF) 356 unexpected_EOF(); 357 if (c != '"') 358 syntax_error(lineno, line, cptr); 359 ++outline; 360 fprintf(f, "#ident \""); 361 for (;;) 362 { 363 c = *++cptr; 364 if (c == '\n') 365 { 366 fprintf(f, "\"\n"); 367 return; 368 } 369 putc(c, f); 370 if (c == '"') 371 { 372 putc('\n', f); 373 ++cptr; 374 return; 375 } 376 } 377 } 378 379 static void 380 copy_text(void) 381 { 382 int c; 383 int quote; 384 FILE *f = text_file; 385 int need_newline = 0; 386 int t_lineno = lineno; 387 char *t_line = dup_line(); 388 char *t_cptr = t_line + (cptr - line - 2); 389 390 if (*cptr == '\n') 391 { 392 get_line(); 393 if (line == 0) 394 unterminated_text(t_lineno, t_line, t_cptr); 395 } 396 if (!lflag) 397 fprintf(f, line_format, lineno, input_file_name); 398 399 loop: 400 c = *cptr++; 401 switch (c) 402 { 403 case '\n': 404 next_line: 405 putc('\n', f); 406 need_newline = 0; 407 get_line(); 408 if (line) 409 goto loop; 410 unterminated_text(t_lineno, t_line, t_cptr); 411 412 case '\'': 413 case '"': 414 { 415 int s_lineno = lineno; 416 char *s_line = dup_line(); 417 char *s_cptr = s_line + (cptr - line - 1); 418 419 quote = c; 420 putc(c, f); 421 for (;;) 422 { 423 c = *cptr++; 424 putc(c, f); 425 if (c == quote) 426 { 427 need_newline = 1; 428 FREE(s_line); 429 goto loop; 430 } 431 if (c == '\n') 432 unterminated_string(s_lineno, s_line, s_cptr); 433 if (c == '\\') 434 { 435 c = *cptr++; 436 putc(c, f); 437 if (c == '\n') 438 { 439 get_line(); 440 if (line == 0) 441 unterminated_string(s_lineno, s_line, s_cptr); 442 } 443 } 444 } 445 } 446 447 case '/': 448 putc(c, f); 449 need_newline = 1; 450 c = *cptr; 451 if (c == '/') 452 { 453 putc('*', f); 454 while ((c = *++cptr) != '\n') 455 { 456 if (c == '*' && cptr[1] == '/') 457 fprintf(f, "* "); 458 else 459 putc(c, f); 460 } 461 fprintf(f, "*/"); 462 goto next_line; 463 } 464 if (c == '*') 465 { 466 int c_lineno = lineno; 467 char *c_line = dup_line(); 468 char *c_cptr = c_line + (cptr - line - 1); 469 470 putc('*', f); 471 ++cptr; 472 for (;;) 473 { 474 c = *cptr++; 475 putc(c, f); 476 if (c == '*' && *cptr == '/') 477 { 478 putc('/', f); 479 ++cptr; 480 FREE(c_line); 481 goto loop; 482 } 483 if (c == '\n') 484 { 485 get_line(); 486 if (line == 0) 487 unterminated_comment(c_lineno, c_line, c_cptr); 488 } 489 } 490 } 491 need_newline = 1; 492 goto loop; 493 494 case '%': 495 case '\\': 496 if (*cptr == R_CURL) 497 { 498 if (need_newline) 499 putc('\n', f); 500 ++cptr; 501 FREE(t_line); 502 return; 503 } 504 /* FALLTHRU */ 505 506 default: 507 putc(c, f); 508 need_newline = 1; 509 goto loop; 510 } 511 } 512 513 static void 514 puts_both(const char *s) 515 { 516 fputs(s, text_file); 517 if (dflag) 518 fputs(s, union_file); 519 } 520 521 static void 522 putc_both(int c) 523 { 524 putc(c, text_file); 525 if (dflag) 526 putc(c, union_file); 527 } 528 529 static void 530 copy_union(void) 531 { 532 int c; 533 int quote; 534 int depth; 535 int u_lineno = lineno; 536 char *u_line = dup_line(); 537 char *u_cptr = u_line + (cptr - line - 6); 538 539 if (unionized) 540 over_unionized(cptr - 6); 541 unionized = 1; 542 543 if (!lflag) 544 fprintf(text_file, line_format, lineno, input_file_name); 545 546 puts_both("#ifdef YYSTYPE\n"); 547 puts_both("#undef YYSTYPE_IS_DECLARED\n"); 548 puts_both("#define YYSTYPE_IS_DECLARED 1\n"); 549 puts_both("#endif\n"); 550 puts_both("#ifndef YYSTYPE_IS_DECLARED\n"); 551 puts_both("#define YYSTYPE_IS_DECLARED 1\n"); 552 puts_both("typedef union"); 553 554 depth = 0; 555 loop: 556 c = *cptr++; 557 putc_both(c); 558 switch (c) 559 { 560 case '\n': 561 next_line: 562 get_line(); 563 if (line == 0) 564 unterminated_union(u_lineno, u_line, u_cptr); 565 goto loop; 566 567 case L_CURL: 568 ++depth; 569 goto loop; 570 571 case R_CURL: 572 if (--depth == 0) 573 { 574 puts_both(" YYSTYPE;\n"); 575 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n"); 576 FREE(u_line); 577 return; 578 } 579 goto loop; 580 581 case '\'': 582 case '"': 583 { 584 int s_lineno = lineno; 585 char *s_line = dup_line(); 586 char *s_cptr = s_line + (cptr - line - 1); 587 588 quote = c; 589 for (;;) 590 { 591 c = *cptr++; 592 putc_both(c); 593 if (c == quote) 594 { 595 FREE(s_line); 596 goto loop; 597 } 598 if (c == '\n') 599 unterminated_string(s_lineno, s_line, s_cptr); 600 if (c == '\\') 601 { 602 c = *cptr++; 603 putc_both(c); 604 if (c == '\n') 605 { 606 get_line(); 607 if (line == 0) 608 unterminated_string(s_lineno, s_line, s_cptr); 609 } 610 } 611 } 612 } 613 614 case '/': 615 c = *cptr; 616 if (c == '/') 617 { 618 putc_both('*'); 619 while ((c = *++cptr) != '\n') 620 { 621 if (c == '*' && cptr[1] == '/') 622 { 623 puts_both("* "); 624 } 625 else 626 { 627 putc_both(c); 628 } 629 } 630 puts_both("*/\n"); 631 goto next_line; 632 } 633 if (c == '*') 634 { 635 int c_lineno = lineno; 636 char *c_line = dup_line(); 637 char *c_cptr = c_line + (cptr - line - 1); 638 639 putc_both('*'); 640 ++cptr; 641 for (;;) 642 { 643 c = *cptr++; 644 putc_both(c); 645 if (c == '*' && *cptr == '/') 646 { 647 putc_both('/'); 648 ++cptr; 649 FREE(c_line); 650 goto loop; 651 } 652 if (c == '\n') 653 { 654 get_line(); 655 if (line == 0) 656 unterminated_comment(c_lineno, c_line, c_cptr); 657 } 658 } 659 } 660 goto loop; 661 662 default: 663 goto loop; 664 } 665 } 666 667 /* 668 * Keep a linked list of parameters 669 */ 670 static void 671 copy_param(int k) 672 { 673 char *buf; 674 int c; 675 param *head, *p; 676 int i; 677 int name, type2; 678 679 c = nextc(); 680 if (c == EOF) 681 unexpected_EOF(); 682 if (c != '{') 683 goto out; 684 cptr++; 685 686 c = nextc(); 687 if (c == EOF) 688 unexpected_EOF(); 689 if (c == '}') 690 goto out; 691 692 buf = MALLOC(linesize); 693 NO_SPACE(buf); 694 695 for (i = 0; (c = *cptr++) != '}'; i++) 696 { 697 if (c == 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 = MALLOC(sizeof(*p)); 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 = MALLOC(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 = (char **) 1064 (tag_table 1065 ? REALLOC(tag_table, (unsigned)tagmax * sizeof(char *)) 1066 : MALLOC((unsigned)tagmax * sizeof(char *))); 1067 NO_SPACE(tag_table); 1068 } 1069 1070 s = MALLOC(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 = MALLOC(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 POSIX_YACC: 1308 /* noop for bison compatibility. byacc is already designed to be posix 1309 * yacc compatible. */ 1310 break; 1311 } 1312 } 1313 } 1314 1315 static void 1316 initialize_grammar(void) 1317 { 1318 nitems = 4; 1319 maxitems = 300; 1320 1321 pitem = (bucket **)MALLOC((unsigned)maxitems * sizeof(bucket *)); 1322 NO_SPACE(pitem); 1323 1324 pitem[0] = 0; 1325 pitem[1] = 0; 1326 pitem[2] = 0; 1327 pitem[3] = 0; 1328 1329 nrules = 3; 1330 maxrules = 100; 1331 1332 plhs = (bucket **)MALLOC((unsigned)maxrules * sizeof(bucket *)); 1333 NO_SPACE(plhs); 1334 1335 plhs[0] = 0; 1336 plhs[1] = 0; 1337 plhs[2] = 0; 1338 1339 rprec = (short *)MALLOC((unsigned)maxrules * sizeof(short)); 1340 NO_SPACE(rprec); 1341 1342 rprec[0] = 0; 1343 rprec[1] = 0; 1344 rprec[2] = 0; 1345 1346 rassoc = (char *)MALLOC((unsigned)maxrules * sizeof(char)); 1347 NO_SPACE(rassoc); 1348 1349 rassoc[0] = TOKEN; 1350 rassoc[1] = TOKEN; 1351 rassoc[2] = TOKEN; 1352 } 1353 1354 static void 1355 expand_items(void) 1356 { 1357 maxitems += 300; 1358 pitem = (bucket **)REALLOC(pitem, (unsigned)maxitems * sizeof(bucket *)); 1359 NO_SPACE(pitem); 1360 } 1361 1362 static void 1363 expand_rules(void) 1364 { 1365 maxrules += 100; 1366 1367 plhs = (bucket **)REALLOC(plhs, (unsigned)maxrules * sizeof(bucket *)); 1368 NO_SPACE(plhs); 1369 1370 rprec = (short *)REALLOC(rprec, (unsigned)maxrules * sizeof(short)); 1371 NO_SPACE(rprec); 1372 1373 rassoc = (char *)REALLOC(rassoc, (unsigned)maxrules * sizeof(char)); 1374 NO_SPACE(rassoc); 1375 } 1376 1377 static void 1378 advance_to_start(void) 1379 { 1380 int c; 1381 bucket *bp; 1382 char *s_cptr; 1383 int s_lineno; 1384 1385 for (;;) 1386 { 1387 c = nextc(); 1388 if (c != '%') 1389 break; 1390 s_cptr = cptr; 1391 switch (keyword()) 1392 { 1393 case MARK: 1394 no_grammar(); 1395 1396 case TEXT: 1397 copy_text(); 1398 break; 1399 1400 case START: 1401 declare_start(); 1402 break; 1403 1404 default: 1405 syntax_error(lineno, line, s_cptr); 1406 } 1407 } 1408 1409 c = nextc(); 1410 if (!isalpha(c) && c != '_' && c != '.' && c != '_') 1411 syntax_error(lineno, line, cptr); 1412 bp = get_name(); 1413 if (goal == 0) 1414 { 1415 if (bp->class == TERM) 1416 terminal_start(bp->name); 1417 goal = bp; 1418 } 1419 1420 s_lineno = lineno; 1421 c = nextc(); 1422 if (c == EOF) 1423 unexpected_EOF(); 1424 if (c != ':') 1425 syntax_error(lineno, line, cptr); 1426 start_rule(bp, s_lineno); 1427 ++cptr; 1428 } 1429 1430 static void 1431 start_rule(bucket *bp, int s_lineno) 1432 { 1433 if (bp->class == TERM) 1434 terminal_lhs(s_lineno); 1435 bp->class = NONTERM; 1436 if (nrules >= maxrules) 1437 expand_rules(); 1438 plhs[nrules] = bp; 1439 rprec[nrules] = UNDEFINED; 1440 rassoc[nrules] = TOKEN; 1441 } 1442 1443 static void 1444 end_rule(void) 1445 { 1446 int i; 1447 1448 if (!last_was_action && plhs[nrules]->tag) 1449 { 1450 if (pitem[nitems - 1]) 1451 { 1452 for (i = nitems - 1; (i > 0) && pitem[i]; --i) 1453 continue; 1454 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag) 1455 default_action_warning(); 1456 } 1457 else 1458 { 1459 default_action_warning(); 1460 } 1461 } 1462 1463 last_was_action = 0; 1464 if (nitems >= maxitems) 1465 expand_items(); 1466 pitem[nitems] = 0; 1467 ++nitems; 1468 ++nrules; 1469 } 1470 1471 static void 1472 insert_empty_rule(void) 1473 { 1474 bucket *bp, **bpp; 1475 1476 assert(cache); 1477 sprintf(cache, "$$%d", ++gensym); 1478 bp = make_bucket(cache); 1479 last_symbol->next = bp; 1480 last_symbol = bp; 1481 bp->tag = plhs[nrules]->tag; 1482 bp->class = NONTERM; 1483 1484 if ((nitems += 2) > maxitems) 1485 expand_items(); 1486 bpp = pitem + nitems - 1; 1487 *bpp-- = bp; 1488 while ((bpp[0] = bpp[-1]) != 0) 1489 --bpp; 1490 1491 if (++nrules >= maxrules) 1492 expand_rules(); 1493 plhs[nrules] = plhs[nrules - 1]; 1494 plhs[nrules - 1] = bp; 1495 rprec[nrules] = rprec[nrules - 1]; 1496 rprec[nrules - 1] = 0; 1497 rassoc[nrules] = rassoc[nrules - 1]; 1498 rassoc[nrules - 1] = TOKEN; 1499 } 1500 1501 static void 1502 add_symbol(void) 1503 { 1504 int c; 1505 bucket *bp; 1506 int s_lineno = lineno; 1507 1508 c = *cptr; 1509 if (c == '\'' || c == '"') 1510 bp = get_literal(); 1511 else 1512 bp = get_name(); 1513 1514 c = nextc(); 1515 if (c == ':') 1516 { 1517 end_rule(); 1518 start_rule(bp, s_lineno); 1519 ++cptr; 1520 return; 1521 } 1522 1523 if (last_was_action) 1524 insert_empty_rule(); 1525 last_was_action = 0; 1526 1527 if (++nitems > maxitems) 1528 expand_items(); 1529 pitem[nitems - 1] = bp; 1530 } 1531 1532 static char * 1533 after_blanks(char *s) 1534 { 1535 while (*s != '\0' && isspace(UCH(*s))) 1536 ++s; 1537 return s; 1538 } 1539 1540 static void 1541 copy_action(void) 1542 { 1543 int c; 1544 int i, n; 1545 int depth; 1546 int quote; 1547 char *tag; 1548 FILE *f = action_file; 1549 int a_lineno = lineno; 1550 char *a_line = dup_line(); 1551 char *a_cptr = a_line + (cptr - line); 1552 1553 if (last_was_action) 1554 insert_empty_rule(); 1555 last_was_action = 1; 1556 1557 fprintf(f, "case %d:\n", nrules - 2); 1558 if (!lflag) 1559 fprintf(f, line_format, lineno, input_file_name); 1560 if (*cptr == '=') 1561 ++cptr; 1562 1563 /* avoid putting curly-braces in first column, to ease editing */ 1564 if (*after_blanks(cptr) == L_CURL) 1565 { 1566 putc('\t', f); 1567 cptr = after_blanks(cptr); 1568 } 1569 1570 n = 0; 1571 for (i = nitems - 1; pitem[i]; --i) 1572 ++n; 1573 1574 depth = 0; 1575 loop: 1576 c = *cptr; 1577 if (c == '$') 1578 { 1579 if (cptr[1] == '<') 1580 { 1581 int d_lineno = lineno; 1582 char *d_line = dup_line(); 1583 char *d_cptr = d_line + (cptr - line); 1584 1585 ++cptr; 1586 tag = get_tag(); 1587 c = *cptr; 1588 if (c == '$') 1589 { 1590 fprintf(f, "yyval.%s", tag); 1591 ++cptr; 1592 FREE(d_line); 1593 goto loop; 1594 } 1595 else if (isdigit(c)) 1596 { 1597 i = get_number(); 1598 if (i > n) 1599 dollar_warning(d_lineno, i); 1600 fprintf(f, "yystack.l_mark[%d].%s", i - n, tag); 1601 FREE(d_line); 1602 goto loop; 1603 } 1604 else if (c == '-' && isdigit(UCH(cptr[1]))) 1605 { 1606 ++cptr; 1607 i = -get_number() - n; 1608 fprintf(f, "yystack.l_mark[%d].%s", i, tag); 1609 FREE(d_line); 1610 goto loop; 1611 } 1612 else 1613 dollar_error(d_lineno, d_line, d_cptr); 1614 } 1615 else if (cptr[1] == '$') 1616 { 1617 if (ntags) 1618 { 1619 tag = plhs[nrules]->tag; 1620 if (tag == 0) 1621 untyped_lhs(); 1622 fprintf(f, "yyval.%s", tag); 1623 } 1624 else 1625 fprintf(f, "yyval"); 1626 cptr += 2; 1627 goto loop; 1628 } 1629 else if (isdigit(UCH(cptr[1]))) 1630 { 1631 ++cptr; 1632 i = get_number(); 1633 if (ntags) 1634 { 1635 if (i <= 0 || i > n) 1636 unknown_rhs(i); 1637 tag = pitem[nitems + i - n - 1]->tag; 1638 if (tag == 0) 1639 untyped_rhs(i, pitem[nitems + i - n - 1]->name); 1640 fprintf(f, "yystack.l_mark[%d].%s", i - n, tag); 1641 } 1642 else 1643 { 1644 if (i > n) 1645 dollar_warning(lineno, i); 1646 fprintf(f, "yystack.l_mark[%d]", i - n); 1647 } 1648 goto loop; 1649 } 1650 else if (cptr[1] == '-') 1651 { 1652 cptr += 2; 1653 i = get_number(); 1654 if (ntags) 1655 unknown_rhs(-i); 1656 fprintf(f, "yystack.l_mark[%d]", -i - n); 1657 goto loop; 1658 } 1659 } 1660 if (isalpha(c) || c == '_' || c == '$') 1661 { 1662 do 1663 { 1664 putc(c, f); 1665 c = *++cptr; 1666 } 1667 while (isalnum(c) || c == '_' || c == '$'); 1668 goto loop; 1669 } 1670 putc(c, f); 1671 ++cptr; 1672 switch (c) 1673 { 1674 case '\n': 1675 next_line: 1676 get_line(); 1677 if (line) 1678 goto loop; 1679 unterminated_action(a_lineno, a_line, a_cptr); 1680 1681 case ';': 1682 if (depth > 0) 1683 goto loop; 1684 fprintf(f, "\nbreak;\n"); 1685 free(a_line); 1686 return; 1687 1688 case L_CURL: 1689 ++depth; 1690 goto loop; 1691 1692 case R_CURL: 1693 if (--depth > 0) 1694 goto loop; 1695 fprintf(f, "\nbreak;\n"); 1696 free(a_line); 1697 return; 1698 1699 case '\'': 1700 case '"': 1701 { 1702 int s_lineno = lineno; 1703 char *s_line = dup_line(); 1704 char *s_cptr = s_line + (cptr - line - 1); 1705 1706 quote = c; 1707 for (;;) 1708 { 1709 c = *cptr++; 1710 putc(c, f); 1711 if (c == quote) 1712 { 1713 FREE(s_line); 1714 goto loop; 1715 } 1716 if (c == '\n') 1717 unterminated_string(s_lineno, s_line, s_cptr); 1718 if (c == '\\') 1719 { 1720 c = *cptr++; 1721 putc(c, f); 1722 if (c == '\n') 1723 { 1724 get_line(); 1725 if (line == 0) 1726 unterminated_string(s_lineno, s_line, s_cptr); 1727 } 1728 } 1729 } 1730 } 1731 1732 case '/': 1733 c = *cptr; 1734 if (c == '/') 1735 { 1736 putc('*', f); 1737 while ((c = *++cptr) != '\n') 1738 { 1739 if (c == '*' && cptr[1] == '/') 1740 fprintf(f, "* "); 1741 else 1742 putc(c, f); 1743 } 1744 fprintf(f, "*/\n"); 1745 goto next_line; 1746 } 1747 if (c == '*') 1748 { 1749 int c_lineno = lineno; 1750 char *c_line = dup_line(); 1751 char *c_cptr = c_line + (cptr - line - 1); 1752 1753 putc('*', f); 1754 ++cptr; 1755 for (;;) 1756 { 1757 c = *cptr++; 1758 putc(c, f); 1759 if (c == '*' && *cptr == '/') 1760 { 1761 putc('/', f); 1762 ++cptr; 1763 FREE(c_line); 1764 goto loop; 1765 } 1766 if (c == '\n') 1767 { 1768 get_line(); 1769 if (line == 0) 1770 unterminated_comment(c_lineno, c_line, c_cptr); 1771 } 1772 } 1773 } 1774 goto loop; 1775 1776 default: 1777 goto loop; 1778 } 1779 } 1780 1781 static int 1782 mark_symbol(void) 1783 { 1784 int c; 1785 bucket *bp; 1786 1787 c = cptr[1]; 1788 if (c == '%' || c == '\\') 1789 { 1790 cptr += 2; 1791 return (1); 1792 } 1793 1794 if (c == '=') 1795 cptr += 2; 1796 else if ((c == 'p' || c == 'P') && 1797 ((c = cptr[2]) == 'r' || c == 'R') && 1798 ((c = cptr[3]) == 'e' || c == 'E') && 1799 ((c = cptr[4]) == 'c' || c == 'C') && 1800 ((c = cptr[5], !IS_IDENT(c)))) 1801 cptr += 5; 1802 else 1803 syntax_error(lineno, line, cptr); 1804 1805 c = nextc(); 1806 if (isalpha(c) || c == '_' || c == '.' || c == '$') 1807 bp = get_name(); 1808 else if (c == '\'' || c == '"') 1809 bp = get_literal(); 1810 else 1811 { 1812 syntax_error(lineno, line, cptr); 1813 /*NOTREACHED */ 1814 } 1815 1816 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules]) 1817 prec_redeclared(); 1818 1819 rprec[nrules] = bp->prec; 1820 rassoc[nrules] = bp->assoc; 1821 return (0); 1822 } 1823 1824 static void 1825 read_grammar(void) 1826 { 1827 int c; 1828 1829 initialize_grammar(); 1830 advance_to_start(); 1831 1832 for (;;) 1833 { 1834 c = nextc(); 1835 if (c == EOF) 1836 break; 1837 if (isalpha(c) 1838 || c == '_' 1839 || c == '.' 1840 || c == '$' 1841 || c == '\'' 1842 || c == '"') 1843 add_symbol(); 1844 else if (c == L_CURL || c == '=') 1845 copy_action(); 1846 else if (c == '|') 1847 { 1848 end_rule(); 1849 start_rule(plhs[nrules - 1], 0); 1850 ++cptr; 1851 } 1852 else if (c == '%') 1853 { 1854 if (mark_symbol()) 1855 break; 1856 } 1857 else 1858 syntax_error(lineno, line, cptr); 1859 } 1860 end_rule(); 1861 } 1862 1863 static void 1864 free_tags(void) 1865 { 1866 int i; 1867 1868 if (tag_table == 0) 1869 return; 1870 1871 for (i = 0; i < ntags; ++i) 1872 { 1873 assert(tag_table[i]); 1874 FREE(tag_table[i]); 1875 } 1876 FREE(tag_table); 1877 } 1878 1879 static void 1880 pack_names(void) 1881 { 1882 bucket *bp; 1883 char *p, *s, *t; 1884 1885 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */ 1886 for (bp = first_symbol; bp; bp = bp->next) 1887 name_pool_size += strlen(bp->name) + 1; 1888 1889 name_pool = MALLOC(name_pool_size); 1890 NO_SPACE(name_pool); 1891 1892 strlcpy(name_pool, "$accept", name_pool_size); 1893 strlcpy(name_pool + 8, "$end", name_pool_size - 8); 1894 t = name_pool + 13; 1895 for (bp = first_symbol; bp; bp = bp->next) 1896 { 1897 p = t; 1898 s = bp->name; 1899 while ((*t++ = *s++) != 0) 1900 continue; 1901 FREE(bp->name); 1902 bp->name = p; 1903 } 1904 } 1905 1906 static void 1907 check_symbols(void) 1908 { 1909 bucket *bp; 1910 1911 if (goal->class == UNKNOWN) 1912 undefined_goal(goal->name); 1913 1914 for (bp = first_symbol; bp; bp = bp->next) 1915 { 1916 if (bp->class == UNKNOWN) 1917 { 1918 undefined_symbol_warning(bp->name); 1919 bp->class = TERM; 1920 } 1921 } 1922 } 1923 1924 static void 1925 protect_string(char *src, char **des) 1926 { 1927 unsigned len; 1928 char *s; 1929 char *d; 1930 1931 *des = src; 1932 if (src) 1933 { 1934 len = 1; 1935 s = src; 1936 while (*s) 1937 { 1938 if ('\\' == *s || '"' == *s) 1939 len++; 1940 s++; 1941 len++; 1942 } 1943 1944 *des = d = (char *)MALLOC(len); 1945 NO_SPACE(d); 1946 1947 s = src; 1948 while (*s) 1949 { 1950 if ('\\' == *s || '"' == *s) 1951 *d++ = '\\'; 1952 *d++ = *s++; 1953 } 1954 *d = '\0'; 1955 } 1956 } 1957 1958 static void 1959 pack_symbols(void) 1960 { 1961 bucket *bp; 1962 bucket **v; 1963 Value_t i, j, k, n; 1964 1965 nsyms = 2; 1966 ntokens = 1; 1967 for (bp = first_symbol; bp; bp = bp->next) 1968 { 1969 ++nsyms; 1970 if (bp->class == TERM) 1971 ++ntokens; 1972 } 1973 start_symbol = (Value_t) ntokens; 1974 nvars = nsyms - ntokens; 1975 1976 symbol_name = (char **)MALLOC((unsigned)nsyms * sizeof(char *)); 1977 NO_SPACE(symbol_name); 1978 1979 symbol_value = (short *)MALLOC((unsigned)nsyms * sizeof(short)); 1980 NO_SPACE(symbol_value); 1981 1982 symbol_prec = (short *)MALLOC((unsigned)nsyms * sizeof(short)); 1983 NO_SPACE(symbol_prec); 1984 1985 symbol_assoc = MALLOC(nsyms); 1986 NO_SPACE(symbol_assoc); 1987 1988 v = (bucket **)MALLOC((unsigned)nsyms * sizeof(bucket *)); 1989 NO_SPACE(v); 1990 1991 v[0] = 0; 1992 v[start_symbol] = 0; 1993 1994 i = 1; 1995 j = (Value_t) (start_symbol + 1); 1996 for (bp = first_symbol; bp; bp = bp->next) 1997 { 1998 if (bp->class == TERM) 1999 v[i++] = bp; 2000 else 2001 v[j++] = bp; 2002 } 2003 assert(i == ntokens && j == nsyms); 2004 2005 for (i = 1; i < ntokens; ++i) 2006 v[i]->index = i; 2007 2008 goal->index = (Index_t) (start_symbol + 1); 2009 k = (Value_t) (start_symbol + 2); 2010 while (++i < nsyms) 2011 if (v[i] != goal) 2012 { 2013 v[i]->index = k; 2014 ++k; 2015 } 2016 2017 goal->value = 0; 2018 k = 1; 2019 for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i) 2020 { 2021 if (v[i] != goal) 2022 { 2023 v[i]->value = k; 2024 ++k; 2025 } 2026 } 2027 2028 k = 0; 2029 for (i = 1; i < ntokens; ++i) 2030 { 2031 n = v[i]->value; 2032 if (n > 256) 2033 { 2034 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j) 2035 symbol_value[j] = symbol_value[j - 1]; 2036 symbol_value[j] = n; 2037 } 2038 } 2039 2040 assert(v[1] != 0); 2041 2042 if (v[1]->value == UNDEFINED) 2043 v[1]->value = 256; 2044 2045 j = 0; 2046 n = 257; 2047 for (i = 2; i < ntokens; ++i) 2048 { 2049 if (v[i]->value == UNDEFINED) 2050 { 2051 while (j < k && n == symbol_value[j]) 2052 { 2053 while (++j < k && n == symbol_value[j]) 2054 continue; 2055 ++n; 2056 } 2057 v[i]->value = n; 2058 ++n; 2059 } 2060 } 2061 2062 symbol_name[0] = name_pool + 8; 2063 symbol_value[0] = 0; 2064 symbol_prec[0] = 0; 2065 symbol_assoc[0] = TOKEN; 2066 for (i = 1; i < ntokens; ++i) 2067 { 2068 symbol_name[i] = v[i]->name; 2069 symbol_value[i] = v[i]->value; 2070 symbol_prec[i] = v[i]->prec; 2071 symbol_assoc[i] = v[i]->assoc; 2072 } 2073 symbol_name[start_symbol] = name_pool; 2074 symbol_value[start_symbol] = -1; 2075 symbol_prec[start_symbol] = 0; 2076 symbol_assoc[start_symbol] = TOKEN; 2077 for (++i; i < nsyms; ++i) 2078 { 2079 k = v[i]->index; 2080 symbol_name[k] = v[i]->name; 2081 symbol_value[k] = v[i]->value; 2082 symbol_prec[k] = v[i]->prec; 2083 symbol_assoc[k] = v[i]->assoc; 2084 } 2085 2086 if (gflag) 2087 { 2088 symbol_pname = (char **)MALLOC((unsigned)nsyms * sizeof(char *)); 2089 NO_SPACE(symbol_pname); 2090 2091 for (i = 0; i < nsyms; ++i) 2092 protect_string(symbol_name[i], &(symbol_pname[i])); 2093 } 2094 2095 FREE(v); 2096 } 2097 2098 static void 2099 pack_grammar(void) 2100 { 2101 int i; 2102 Value_t j; 2103 Assoc_t assoc; 2104 Value_t prec2; 2105 2106 ritem = (short *)MALLOC((unsigned)nitems * sizeof(short)); 2107 NO_SPACE(ritem); 2108 2109 rlhs = (short *)MALLOC((unsigned)nrules * sizeof(short)); 2110 NO_SPACE(rlhs); 2111 2112 rrhs = (short *)MALLOC((unsigned)(nrules + 1) * sizeof(short)); 2113 NO_SPACE(rrhs); 2114 2115 rprec = (short *)REALLOC(rprec, (unsigned)nrules * sizeof(short)); 2116 NO_SPACE(rprec); 2117 2118 rassoc = REALLOC(rassoc, nrules); 2119 NO_SPACE(rassoc); 2120 2121 ritem[0] = -1; 2122 ritem[1] = goal->index; 2123 ritem[2] = 0; 2124 ritem[3] = -2; 2125 rlhs[0] = 0; 2126 rlhs[1] = 0; 2127 rlhs[2] = start_symbol; 2128 rrhs[0] = 0; 2129 rrhs[1] = 0; 2130 rrhs[2] = 1; 2131 2132 j = 4; 2133 for (i = 3; i < nrules; ++i) 2134 { 2135 rlhs[i] = plhs[i]->index; 2136 rrhs[i] = j; 2137 assoc = TOKEN; 2138 prec2 = 0; 2139 while (pitem[j]) 2140 { 2141 ritem[j] = pitem[j]->index; 2142 if (pitem[j]->class == TERM) 2143 { 2144 prec2 = pitem[j]->prec; 2145 assoc = pitem[j]->assoc; 2146 } 2147 ++j; 2148 } 2149 ritem[j] = (Value_t) - i; 2150 ++j; 2151 if (rprec[i] == UNDEFINED) 2152 { 2153 rprec[i] = prec2; 2154 rassoc[i] = assoc; 2155 } 2156 } 2157 rrhs[i] = j; 2158 2159 FREE(plhs); 2160 FREE(pitem); 2161 } 2162 2163 static void 2164 print_grammar(void) 2165 { 2166 int i, k; 2167 size_t j, spacing = 0; 2168 FILE *f = verbose_file; 2169 2170 if (!vflag) 2171 return; 2172 2173 k = 1; 2174 for (i = 2; i < nrules; ++i) 2175 { 2176 if (rlhs[i] != rlhs[i - 1]) 2177 { 2178 if (i != 2) 2179 fprintf(f, "\n"); 2180 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]); 2181 spacing = strlen(symbol_name[rlhs[i]]) + 1; 2182 } 2183 else 2184 { 2185 fprintf(f, "%4d ", i - 2); 2186 j = spacing; 2187 while (j-- != 0) 2188 putc(' ', f); 2189 putc('|', f); 2190 } 2191 2192 while (ritem[k] >= 0) 2193 { 2194 fprintf(f, " %s", symbol_name[ritem[k]]); 2195 ++k; 2196 } 2197 ++k; 2198 putc('\n', f); 2199 } 2200 } 2201 2202 void 2203 reader(void) 2204 { 2205 write_section(banner); 2206 create_symbol_table(); 2207 read_declarations(); 2208 read_grammar(); 2209 free_symbol_table(); 2210 free_tags(); 2211 pack_names(); 2212 check_symbols(); 2213 pack_symbols(); 2214 pack_grammar(); 2215 free_symbols(); 2216 print_grammar(); 2217 } 2218 2219 #ifdef NO_LEAKS 2220 static param * 2221 free_declarations(param * list) 2222 { 2223 while (list != 0) 2224 { 2225 param *next = list->next; 2226 free(list->type); 2227 free(list->name); 2228 free(list->type2); 2229 free(list); 2230 list = next; 2231 } 2232 return list; 2233 } 2234 2235 void 2236 reader_leaks(void) 2237 { 2238 lex_param = free_declarations(lex_param); 2239 parse_param = free_declarations(parse_param); 2240 2241 DO_FREE(line); 2242 DO_FREE(rrhs); 2243 DO_FREE(rlhs); 2244 DO_FREE(rprec); 2245 DO_FREE(ritem); 2246 DO_FREE(rassoc); 2247 DO_FREE(cache); 2248 DO_FREE(name_pool); 2249 DO_FREE(symbol_name); 2250 DO_FREE(symbol_prec); 2251 DO_FREE(symbol_assoc); 2252 DO_FREE(symbol_value); 2253 } 2254 #endif 2255