1 /* $Id: reader.c,v 1.47 2014/04/09 21:09:27 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 #define L_PAREN '(' 15 #define R_PAREN ')' 16 #define L_BRAC '[' 17 #define R_BRAC ']' 18 19 /* the maximum number of arguments (inherited attributes) to a non-terminal */ 20 /* this is a hard limit, but seems more than adequate */ 21 #define MAXARGS 20 22 23 static void start_rule(bucket *bp, int s_lineno); 24 #if defined(YYBTYACC) 25 static void copy_destructor(void); 26 static char *process_destructor_XX(char *code, char *tag); 27 #endif 28 29 static char *cache; 30 static int cinc, cache_size; 31 32 int ntags; 33 static int tagmax, havetags; 34 static char **tag_table; 35 36 static char saw_eof; 37 char unionized; 38 char *cptr, *line; 39 static int linesize; 40 41 static bucket *goal; 42 static Value_t prec; 43 static int gensym; 44 static char last_was_action; 45 46 static int maxitems; 47 static bucket **pitem; 48 49 static int maxrules; 50 static bucket **plhs; 51 52 static size_t name_pool_size; 53 static char *name_pool; 54 55 char line_format[] = "#line %d \"%s\"\n"; 56 57 param *lex_param; 58 param *parse_param; 59 60 #if defined(YYBTYACC) 61 int destructor = 0; /* =1 if at least one %destructor */ 62 63 static bucket *default_destructor[3] = 64 {0, 0, 0}; 65 66 #define UNTYPED_DEFAULT 0 67 #define TYPED_DEFAULT 1 68 #define TYPE_SPECIFIED 2 69 70 static bucket * 71 lookup_type_destructor(char *tag) 72 { 73 char name[1024] = "\0"; 74 bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED]; 75 76 while ((bp = *bpp) != NULL) 77 { 78 if (bp->tag == tag) 79 return (bp); 80 bpp = &bp->link; 81 } 82 83 *bpp = bp = make_bucket(strcat(strcpy(name, tag), " destructor")); 84 bp->tag = tag; 85 86 return (bp); 87 } 88 #endif /* defined(YYBTYACC) */ 89 90 static void 91 cachec(int c) 92 { 93 assert(cinc >= 0); 94 if (cinc >= cache_size) 95 { 96 cache_size += 256; 97 cache = TREALLOC(char, cache, cache_size); 98 NO_SPACE(cache); 99 } 100 cache[cinc] = (char)c; 101 ++cinc; 102 } 103 104 static void 105 get_line(void) 106 { 107 FILE *f = input_file; 108 int c; 109 int i; 110 111 if (saw_eof || (c = getc(f)) == EOF) 112 { 113 if (line) 114 { 115 FREE(line); 116 line = 0; 117 } 118 cptr = 0; 119 saw_eof = 1; 120 return; 121 } 122 123 if (line == 0 || linesize != (LINESIZE + 1)) 124 { 125 if (line) 126 FREE(line); 127 linesize = LINESIZE + 1; 128 line = TMALLOC(char, linesize); 129 NO_SPACE(line); 130 } 131 132 i = 0; 133 ++lineno; 134 for (;;) 135 { 136 line[i] = (char)c; 137 if (c == '\n') 138 break; 139 if (++i >= linesize) 140 { 141 linesize += LINESIZE; 142 line = TREALLOC(char, line, linesize); 143 NO_SPACE(line); 144 } 145 c = getc(f); 146 if (c == EOF) 147 { 148 line[i] = '\n'; 149 saw_eof = 1; 150 break; 151 } 152 } 153 cptr = line; 154 return; 155 } 156 157 static char * 158 dup_line(void) 159 { 160 char *p, *s, *t; 161 162 if (line == 0) 163 return (0); 164 s = line; 165 while (*s != '\n') 166 ++s; 167 p = TMALLOC(char, s - line + 1); 168 NO_SPACE(p); 169 170 s = line; 171 t = p; 172 while ((*t++ = *s++) != '\n') 173 continue; 174 return (p); 175 } 176 177 static void 178 skip_comment(void) 179 { 180 char *s; 181 182 int st_lineno = lineno; 183 char *st_line = dup_line(); 184 char *st_cptr = st_line + (cptr - line); 185 186 s = cptr + 2; 187 for (;;) 188 { 189 if (*s == '*' && s[1] == '/') 190 { 191 cptr = s + 2; 192 FREE(st_line); 193 return; 194 } 195 if (*s == '\n') 196 { 197 get_line(); 198 if (line == 0) 199 unterminated_comment(st_lineno, st_line, st_cptr); 200 s = cptr; 201 } 202 else 203 ++s; 204 } 205 } 206 207 static int 208 nextc(void) 209 { 210 char *s; 211 212 if (line == 0) 213 { 214 get_line(); 215 if (line == 0) 216 return (EOF); 217 } 218 219 s = cptr; 220 for (;;) 221 { 222 switch (*s) 223 { 224 case '\n': 225 get_line(); 226 if (line == 0) 227 return (EOF); 228 s = cptr; 229 break; 230 231 case ' ': 232 case '\t': 233 case '\f': 234 case '\r': 235 case '\v': 236 case ',': 237 case ';': 238 ++s; 239 break; 240 241 case '\\': 242 cptr = s; 243 return ('%'); 244 245 case '/': 246 if (s[1] == '*') 247 { 248 cptr = s; 249 skip_comment(); 250 s = cptr; 251 break; 252 } 253 else if (s[1] == '/') 254 { 255 get_line(); 256 if (line == 0) 257 return (EOF); 258 s = cptr; 259 break; 260 } 261 /* FALLTHRU */ 262 263 default: 264 cptr = s; 265 return (*s); 266 } 267 } 268 } 269 /* *INDENT-OFF* */ 270 static struct keyword 271 { 272 char name[13]; 273 int token; 274 } 275 keywords[] = { 276 { "binary", NONASSOC }, 277 #if defined(YYBTYACC) 278 { "destructor", DESTRUCTOR }, 279 #endif 280 { "expect", EXPECT }, 281 { "expect-rr", EXPECT_RR }, 282 { "ident", IDENT }, 283 { "left", LEFT }, 284 { "lex-param", LEX_PARAM }, 285 #if defined(YYBTYACC) 286 { "locations", LOCATIONS }, 287 #endif 288 { "nonassoc", NONASSOC }, 289 { "parse-param", PARSE_PARAM }, 290 { "pure-parser", PURE_PARSER }, 291 { "right", RIGHT }, 292 { "start", START }, 293 { "term", TOKEN }, 294 { "token", TOKEN }, 295 { "token-table", TOKEN_TABLE }, 296 { "type", TYPE }, 297 { "union", UNION }, 298 { "yacc", POSIX_YACC }, 299 }; 300 /* *INDENT-ON* */ 301 302 static int 303 compare_keys(const void *a, const void *b) 304 { 305 const struct keyword *p = (const struct keyword *)a; 306 const struct keyword *q = (const struct keyword *)b; 307 return strcmp(p->name, q->name); 308 } 309 310 static int 311 keyword(void) 312 { 313 int c; 314 char *t_cptr = cptr; 315 struct keyword *key; 316 317 c = *++cptr; 318 if (isalpha(c)) 319 { 320 cinc = 0; 321 for (;;) 322 { 323 if (isalpha(c)) 324 { 325 if (isupper(c)) 326 c = tolower(c); 327 cachec(c); 328 } 329 else if (isdigit(c) 330 || c == '-' 331 || c == '.' 332 || c == '$') 333 { 334 cachec(c); 335 } 336 else if (c == '_') 337 { 338 /* treat keywords spelled with '_' as if it were '-' */ 339 cachec('-'); 340 } 341 else 342 { 343 break; 344 } 345 c = *++cptr; 346 } 347 cachec(NUL); 348 349 if ((key = bsearch(cache, keywords, 350 sizeof(keywords) / sizeof(*key), 351 sizeof(*key), compare_keys))) 352 return key->token; 353 } 354 else 355 { 356 ++cptr; 357 if (c == L_CURL) 358 return (TEXT); 359 if (c == '%' || c == '\\') 360 return (MARK); 361 if (c == '<') 362 return (LEFT); 363 if (c == '>') 364 return (RIGHT); 365 if (c == '0') 366 return (TOKEN); 367 if (c == '2') 368 return (NONASSOC); 369 } 370 syntax_error(lineno, line, t_cptr); 371 return (-1); 372 } 373 374 static void 375 copy_ident(void) 376 { 377 int c; 378 FILE *f = output_file; 379 380 c = nextc(); 381 if (c == EOF) 382 unexpected_EOF(); 383 if (c != '"') 384 syntax_error(lineno, line, cptr); 385 ++outline; 386 fprintf(f, "#ident \""); 387 for (;;) 388 { 389 c = *++cptr; 390 if (c == '\n') 391 { 392 fprintf(f, "\"\n"); 393 return; 394 } 395 putc(c, f); 396 if (c == '"') 397 { 398 putc('\n', f); 399 ++cptr; 400 return; 401 } 402 } 403 } 404 405 static char * 406 copy_string(int quote) 407 { 408 struct mstring *temp = msnew(); 409 int c; 410 int s_lineno = lineno; 411 char *s_line = dup_line(); 412 char *s_cptr = s_line + (cptr - line - 1); 413 414 for (;;) 415 { 416 c = *cptr++; 417 mputc(temp, c); 418 if (c == quote) 419 { 420 FREE(s_line); 421 return msdone(temp); 422 } 423 if (c == '\n') 424 unterminated_string(s_lineno, s_line, s_cptr); 425 if (c == '\\') 426 { 427 c = *cptr++; 428 mputc(temp, c); 429 if (c == '\n') 430 { 431 get_line(); 432 if (line == 0) 433 unterminated_string(s_lineno, s_line, s_cptr); 434 } 435 } 436 } 437 } 438 439 static char * 440 copy_comment(void) 441 { 442 struct mstring *temp = msnew(); 443 int c; 444 445 c = *cptr; 446 if (c == '/') 447 { 448 mputc(temp, '*'); 449 while ((c = *++cptr) != '\n') 450 { 451 mputc(temp, c); 452 if (c == '*' && cptr[1] == '/') 453 mputc(temp, ' '); 454 } 455 mputc(temp, '*'); 456 mputc(temp, '/'); 457 } 458 else if (c == '*') 459 { 460 int c_lineno = lineno; 461 char *c_line = dup_line(); 462 char *c_cptr = c_line + (cptr - line - 1); 463 464 mputc(temp, c); 465 ++cptr; 466 for (;;) 467 { 468 c = *cptr++; 469 mputc(temp, c); 470 if (c == '*' && *cptr == '/') 471 { 472 mputc(temp, '/'); 473 ++cptr; 474 FREE(c_line); 475 return msdone(temp); 476 } 477 if (c == '\n') 478 { 479 get_line(); 480 if (line == 0) 481 unterminated_comment(c_lineno, c_line, c_cptr); 482 } 483 } 484 } 485 return msdone(temp); 486 } 487 488 static void 489 copy_text(void) 490 { 491 int c; 492 FILE *f = text_file; 493 int need_newline = 0; 494 int t_lineno = lineno; 495 char *t_line = dup_line(); 496 char *t_cptr = t_line + (cptr - line - 2); 497 498 if (*cptr == '\n') 499 { 500 get_line(); 501 if (line == 0) 502 unterminated_text(t_lineno, t_line, t_cptr); 503 } 504 if (!lflag) 505 fprintf(f, line_format, lineno, input_file_name); 506 507 loop: 508 c = *cptr++; 509 switch (c) 510 { 511 case '\n': 512 putc('\n', f); 513 need_newline = 0; 514 get_line(); 515 if (line) 516 goto loop; 517 unterminated_text(t_lineno, t_line, t_cptr); 518 519 case '\'': 520 case '"': 521 putc(c, f); 522 { 523 char *s = copy_string(c); 524 fputs(s, f); 525 free(s); 526 } 527 need_newline = 1; 528 goto loop; 529 530 case '/': 531 putc(c, f); 532 { 533 char *s = copy_comment(); 534 fputs(s, f); 535 free(s); 536 } 537 need_newline = 1; 538 goto loop; 539 540 case '%': 541 case '\\': 542 if (*cptr == R_CURL) 543 { 544 if (need_newline) 545 putc('\n', f); 546 ++cptr; 547 FREE(t_line); 548 return; 549 } 550 /* FALLTHRU */ 551 552 default: 553 putc(c, f); 554 need_newline = 1; 555 goto loop; 556 } 557 } 558 559 static void 560 puts_both(const char *s) 561 { 562 fputs(s, text_file); 563 if (dflag) 564 fputs(s, union_file); 565 } 566 567 static void 568 putc_both(int c) 569 { 570 putc(c, text_file); 571 if (dflag) 572 putc(c, union_file); 573 } 574 575 static void 576 copy_union(void) 577 { 578 int c; 579 int depth; 580 int u_lineno = lineno; 581 char *u_line = dup_line(); 582 char *u_cptr = u_line + (cptr - line - 6); 583 584 if (unionized) 585 over_unionized(cptr - 6); 586 unionized = 1; 587 588 if (!lflag) 589 fprintf(text_file, line_format, lineno, input_file_name); 590 591 puts_both("#ifdef YYSTYPE\n"); 592 puts_both("#undef YYSTYPE_IS_DECLARED\n"); 593 puts_both("#define YYSTYPE_IS_DECLARED 1\n"); 594 puts_both("#endif\n"); 595 puts_both("#ifndef YYSTYPE_IS_DECLARED\n"); 596 puts_both("#define YYSTYPE_IS_DECLARED 1\n"); 597 puts_both("typedef union"); 598 599 depth = 0; 600 loop: 601 c = *cptr++; 602 putc_both(c); 603 switch (c) 604 { 605 case '\n': 606 get_line(); 607 if (line == 0) 608 unterminated_union(u_lineno, u_line, u_cptr); 609 goto loop; 610 611 case L_CURL: 612 ++depth; 613 goto loop; 614 615 case R_CURL: 616 if (--depth == 0) 617 { 618 puts_both(" YYSTYPE;\n"); 619 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n"); 620 FREE(u_line); 621 return; 622 } 623 goto loop; 624 625 case '\'': 626 case '"': 627 { 628 char *s = copy_string(c); 629 puts_both(s); 630 free(s); 631 } 632 goto loop; 633 634 case '/': 635 { 636 char *s = copy_comment(); 637 puts_both(s); 638 free(s); 639 } 640 goto loop; 641 642 default: 643 goto loop; 644 } 645 } 646 647 /* 648 * Keep a linked list of parameters 649 */ 650 static void 651 copy_param(int k) 652 { 653 char *buf; 654 int c; 655 param *head, *p; 656 int i; 657 int name, type2; 658 659 c = nextc(); 660 if (c == EOF) 661 unexpected_EOF(); 662 if (c != L_CURL) 663 goto out; 664 cptr++; 665 666 c = nextc(); 667 if (c == EOF) 668 unexpected_EOF(); 669 if (c == R_CURL) 670 goto out; 671 672 buf = TMALLOC(char, linesize); 673 NO_SPACE(buf); 674 675 for (i = 0; (c = *cptr++) != R_CURL; i++) 676 { 677 if (c == '\0') 678 missing_brace(); 679 if (c == EOF) 680 unexpected_EOF(); 681 buf[i] = (char)c; 682 } 683 684 if (i == 0) 685 goto out; 686 687 buf[i--] = '\0'; 688 while (i > 0 && isspace(UCH(buf[i]))) 689 buf[i--] = '\0'; 690 691 if (buf[i] == ']') 692 { 693 int level = 1; 694 while (i >= 0 && level > 0 && buf[i] != '[') 695 { 696 if (buf[i] == ']') 697 ++level; 698 else if (buf[i] == '[') 699 --level; 700 i--; 701 } 702 if (i <= 0) 703 unexpected_EOF(); 704 type2 = i--; 705 } 706 else 707 { 708 type2 = i + 1; 709 } 710 711 while (i > 0 && (isalnum(UCH(buf[i])) || 712 UCH(buf[i]) == '_')) 713 i--; 714 715 if (!isspace(UCH(buf[i])) && buf[i] != '*') 716 goto out; 717 718 name = i + 1; 719 720 p = TMALLOC(param, 1); 721 NO_SPACE(p); 722 723 p->type2 = strdup(buf + type2); 724 NO_SPACE(p->type2); 725 726 buf[type2] = '\0'; 727 728 p->name = strdup(buf + name); 729 NO_SPACE(p->name); 730 731 buf[name] = '\0'; 732 p->type = buf; 733 734 if (k == LEX_PARAM) 735 head = lex_param; 736 else 737 head = parse_param; 738 739 if (head != NULL) 740 { 741 while (head->next) 742 head = head->next; 743 head->next = p; 744 } 745 else 746 { 747 if (k == LEX_PARAM) 748 lex_param = p; 749 else 750 parse_param = p; 751 } 752 p->next = NULL; 753 return; 754 755 out: 756 syntax_error(lineno, line, cptr); 757 } 758 759 static int 760 hexval(int c) 761 { 762 if (c >= '0' && c <= '9') 763 return (c - '0'); 764 if (c >= 'A' && c <= 'F') 765 return (c - 'A' + 10); 766 if (c >= 'a' && c <= 'f') 767 return (c - 'a' + 10); 768 return (-1); 769 } 770 771 static bucket * 772 get_literal(void) 773 { 774 int c, quote; 775 int i; 776 int n; 777 char *s; 778 bucket *bp; 779 int s_lineno = lineno; 780 char *s_line = dup_line(); 781 char *s_cptr = s_line + (cptr - line); 782 783 quote = *cptr++; 784 cinc = 0; 785 for (;;) 786 { 787 c = *cptr++; 788 if (c == quote) 789 break; 790 if (c == '\n') 791 unterminated_string(s_lineno, s_line, s_cptr); 792 if (c == '\\') 793 { 794 char *c_cptr = cptr - 1; 795 796 c = *cptr++; 797 switch (c) 798 { 799 case '\n': 800 get_line(); 801 if (line == 0) 802 unterminated_string(s_lineno, s_line, s_cptr); 803 continue; 804 805 case '0': 806 case '1': 807 case '2': 808 case '3': 809 case '4': 810 case '5': 811 case '6': 812 case '7': 813 n = c - '0'; 814 c = *cptr; 815 if (IS_OCTAL(c)) 816 { 817 n = (n << 3) + (c - '0'); 818 c = *++cptr; 819 if (IS_OCTAL(c)) 820 { 821 n = (n << 3) + (c - '0'); 822 ++cptr; 823 } 824 } 825 if (n > MAXCHAR) 826 illegal_character(c_cptr); 827 c = n; 828 break; 829 830 case 'x': 831 c = *cptr++; 832 n = hexval(c); 833 if (n < 0 || n >= 16) 834 illegal_character(c_cptr); 835 for (;;) 836 { 837 c = *cptr; 838 i = hexval(c); 839 if (i < 0 || i >= 16) 840 break; 841 ++cptr; 842 n = (n << 4) + i; 843 if (n > MAXCHAR) 844 illegal_character(c_cptr); 845 } 846 c = n; 847 break; 848 849 case 'a': 850 c = 7; 851 break; 852 case 'b': 853 c = '\b'; 854 break; 855 case 'f': 856 c = '\f'; 857 break; 858 case 'n': 859 c = '\n'; 860 break; 861 case 'r': 862 c = '\r'; 863 break; 864 case 't': 865 c = '\t'; 866 break; 867 case 'v': 868 c = '\v'; 869 break; 870 } 871 } 872 cachec(c); 873 } 874 FREE(s_line); 875 876 n = cinc; 877 s = TMALLOC(char, n); 878 NO_SPACE(s); 879 880 for (i = 0; i < n; ++i) 881 s[i] = cache[i]; 882 883 cinc = 0; 884 if (n == 1) 885 cachec('\''); 886 else 887 cachec('"'); 888 889 for (i = 0; i < n; ++i) 890 { 891 c = UCH(s[i]); 892 if (c == '\\' || c == cache[0]) 893 { 894 cachec('\\'); 895 cachec(c); 896 } 897 else if (isprint(c)) 898 cachec(c); 899 else 900 { 901 cachec('\\'); 902 switch (c) 903 { 904 case 7: 905 cachec('a'); 906 break; 907 case '\b': 908 cachec('b'); 909 break; 910 case '\f': 911 cachec('f'); 912 break; 913 case '\n': 914 cachec('n'); 915 break; 916 case '\r': 917 cachec('r'); 918 break; 919 case '\t': 920 cachec('t'); 921 break; 922 case '\v': 923 cachec('v'); 924 break; 925 default: 926 cachec(((c >> 6) & 7) + '0'); 927 cachec(((c >> 3) & 7) + '0'); 928 cachec((c & 7) + '0'); 929 break; 930 } 931 } 932 } 933 934 if (n == 1) 935 cachec('\''); 936 else 937 cachec('"'); 938 939 cachec(NUL); 940 bp = lookup(cache); 941 bp->class = TERM; 942 if (n == 1 && bp->value == UNDEFINED) 943 bp->value = UCH(*s); 944 FREE(s); 945 946 return (bp); 947 } 948 949 static int 950 is_reserved(char *name) 951 { 952 char *s; 953 954 if (strcmp(name, ".") == 0 || 955 strcmp(name, "$accept") == 0 || 956 strcmp(name, "$end") == 0) 957 return (1); 958 959 if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2]))) 960 { 961 s = name + 3; 962 while (isdigit(UCH(*s))) 963 ++s; 964 if (*s == NUL) 965 return (1); 966 } 967 968 return (0); 969 } 970 971 static bucket * 972 get_name(void) 973 { 974 int c; 975 976 cinc = 0; 977 for (c = *cptr; IS_IDENT(c); c = *++cptr) 978 cachec(c); 979 cachec(NUL); 980 981 if (is_reserved(cache)) 982 used_reserved(cache); 983 984 return (lookup(cache)); 985 } 986 987 static Value_t 988 get_number(void) 989 { 990 int c; 991 Value_t n; 992 993 n = 0; 994 for (c = *cptr; isdigit(c); c = *++cptr) 995 n = (Value_t) (10 * n + (c - '0')); 996 997 return (n); 998 } 999 1000 static char * 1001 cache_tag(char *tag, size_t len) 1002 { 1003 int i; 1004 char *s; 1005 1006 for (i = 0; i < ntags; ++i) 1007 { 1008 if (strncmp(tag, tag_table[i], len) == 0 && 1009 tag_table[i][len] == NUL) 1010 return (tag_table[i]); 1011 } 1012 1013 if (ntags >= tagmax) 1014 { 1015 tagmax += 16; 1016 tag_table = 1017 (tag_table 1018 ? TREALLOC(char *, tag_table, tagmax) 1019 : TMALLOC(char *, tagmax)); 1020 NO_SPACE(tag_table); 1021 } 1022 1023 s = TMALLOC(char, len + 1); 1024 NO_SPACE(s); 1025 1026 strncpy(s, tag, len); 1027 s[len] = 0; 1028 tag_table[ntags++] = s; 1029 return s; 1030 } 1031 1032 static char * 1033 get_tag(void) 1034 { 1035 int c; 1036 int t_lineno = lineno; 1037 char *t_line = dup_line(); 1038 char *t_cptr = t_line + (cptr - line); 1039 1040 ++cptr; 1041 c = nextc(); 1042 if (c == EOF) 1043 unexpected_EOF(); 1044 if (!isalpha(c) && c != '_' && c != '$') 1045 illegal_tag(t_lineno, t_line, t_cptr); 1046 1047 cinc = 0; 1048 do 1049 { 1050 cachec(c); 1051 c = *++cptr; 1052 } 1053 while (IS_IDENT(c)); 1054 cachec(NUL); 1055 1056 c = nextc(); 1057 if (c == EOF) 1058 unexpected_EOF(); 1059 if (c != '>') 1060 illegal_tag(t_lineno, t_line, t_cptr); 1061 ++cptr; 1062 1063 FREE(t_line); 1064 havetags = 1; 1065 return cache_tag(cache, (size_t) cinc); 1066 } 1067 1068 #if defined(YYBTYACC) 1069 static char * 1070 scan_id(void) 1071 { 1072 char *b = cptr; 1073 1074 while (isalnum(*cptr) || *cptr == '_' || *cptr == '$') 1075 cptr++; 1076 return cache_tag(b, (size_t) (cptr - b)); 1077 } 1078 #endif 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 #if defined(YYBTYACC) 1197 static void 1198 declare_argtypes(bucket *bp) 1199 { 1200 char *tags[MAXARGS]; 1201 int args = 0, c; 1202 1203 if (bp->args >= 0) 1204 retyped_warning(bp->name); 1205 cptr++; /* skip open paren */ 1206 for (;;) 1207 { 1208 c = nextc(); 1209 if (c == EOF) 1210 unexpected_EOF(); 1211 if (c != '<') 1212 syntax_error(lineno, line, cptr); 1213 tags[args++] = get_tag(); 1214 c = nextc(); 1215 if (c == R_PAREN) 1216 break; 1217 if (c == EOF) 1218 unexpected_EOF(); 1219 } 1220 cptr++; /* skip close paren */ 1221 bp->args = args; 1222 bp->argnames = TMALLOC(char *, args); 1223 NO_SPACE(bp->argnames); 1224 bp->argtags = CALLOC(sizeof(char *), args + 1); 1225 NO_SPACE(bp->argtags); 1226 while (--args >= 0) 1227 { 1228 bp->argtags[args] = tags[args]; 1229 bp->argnames[args] = NULL; 1230 } 1231 } 1232 #endif 1233 1234 static void 1235 declare_types(void) 1236 { 1237 int c; 1238 bucket *bp; 1239 char *tag = NULL; 1240 1241 c = nextc(); 1242 if (c == EOF) 1243 unexpected_EOF(); 1244 if (c == '<') 1245 tag = get_tag(); 1246 1247 for (;;) 1248 { 1249 c = nextc(); 1250 if (c == EOF) 1251 unexpected_EOF(); 1252 if (isalpha(c) || c == '_' || c == '.' || c == '$') 1253 { 1254 bp = get_name(); 1255 #if defined(YYBTYACC) 1256 if (nextc() == L_PAREN) 1257 declare_argtypes(bp); 1258 else 1259 bp->args = 0; 1260 #endif 1261 } 1262 else if (c == '\'' || c == '"') 1263 { 1264 bp = get_literal(); 1265 #if defined(YYBTYACC) 1266 bp->args = 0; 1267 #endif 1268 } 1269 else 1270 return; 1271 1272 if (tag) 1273 { 1274 if (bp->tag && tag != bp->tag) 1275 retyped_warning(bp->name); 1276 bp->tag = tag; 1277 } 1278 } 1279 } 1280 1281 static void 1282 declare_start(void) 1283 { 1284 int c; 1285 bucket *bp; 1286 1287 c = nextc(); 1288 if (c == EOF) 1289 unexpected_EOF(); 1290 if (!isalpha(c) && c != '_' && c != '.' && c != '$') 1291 syntax_error(lineno, line, cptr); 1292 bp = get_name(); 1293 if (bp->class == TERM) 1294 terminal_start(bp->name); 1295 if (goal && goal != bp) 1296 restarted_warning(); 1297 goal = bp; 1298 } 1299 1300 static void 1301 read_declarations(void) 1302 { 1303 int c, k; 1304 1305 cache_size = 256; 1306 cache = TMALLOC(char, cache_size); 1307 NO_SPACE(cache); 1308 1309 for (;;) 1310 { 1311 c = nextc(); 1312 if (c == EOF) 1313 unexpected_EOF(); 1314 if (c != '%') 1315 syntax_error(lineno, line, cptr); 1316 switch (k = keyword()) 1317 { 1318 case MARK: 1319 return; 1320 1321 case IDENT: 1322 copy_ident(); 1323 break; 1324 1325 case TEXT: 1326 copy_text(); 1327 break; 1328 1329 case UNION: 1330 copy_union(); 1331 break; 1332 1333 case TOKEN: 1334 case LEFT: 1335 case RIGHT: 1336 case NONASSOC: 1337 declare_tokens(k); 1338 break; 1339 1340 case EXPECT: 1341 case EXPECT_RR: 1342 declare_expect(k); 1343 break; 1344 1345 case TYPE: 1346 declare_types(); 1347 break; 1348 1349 case START: 1350 declare_start(); 1351 break; 1352 1353 case PURE_PARSER: 1354 pure_parser = 1; 1355 break; 1356 1357 case PARSE_PARAM: 1358 case LEX_PARAM: 1359 copy_param(k); 1360 break; 1361 1362 case TOKEN_TABLE: 1363 token_table = 1; 1364 break; 1365 1366 #if defined(YYBTYACC) 1367 case LOCATIONS: 1368 locations = 1; 1369 break; 1370 1371 case DESTRUCTOR: 1372 destructor = 1; 1373 copy_destructor(); 1374 break; 1375 #endif 1376 1377 case POSIX_YACC: 1378 /* noop for bison compatibility. byacc is already designed to be posix 1379 * yacc compatible. */ 1380 break; 1381 } 1382 } 1383 } 1384 1385 static void 1386 initialize_grammar(void) 1387 { 1388 nitems = 4; 1389 maxitems = 300; 1390 1391 pitem = TMALLOC(bucket *, maxitems); 1392 NO_SPACE(pitem); 1393 1394 pitem[0] = 0; 1395 pitem[1] = 0; 1396 pitem[2] = 0; 1397 pitem[3] = 0; 1398 1399 nrules = 3; 1400 maxrules = 100; 1401 1402 plhs = TMALLOC(bucket *, maxrules); 1403 NO_SPACE(plhs); 1404 1405 plhs[0] = 0; 1406 plhs[1] = 0; 1407 plhs[2] = 0; 1408 1409 rprec = TMALLOC(Value_t, maxrules); 1410 NO_SPACE(rprec); 1411 1412 rprec[0] = 0; 1413 rprec[1] = 0; 1414 rprec[2] = 0; 1415 1416 rassoc = TMALLOC(Assoc_t, maxrules); 1417 NO_SPACE(rassoc); 1418 1419 rassoc[0] = TOKEN; 1420 rassoc[1] = TOKEN; 1421 rassoc[2] = TOKEN; 1422 } 1423 1424 static void 1425 expand_items(void) 1426 { 1427 maxitems += 300; 1428 pitem = TREALLOC(bucket *, pitem, maxitems); 1429 NO_SPACE(pitem); 1430 } 1431 1432 static void 1433 expand_rules(void) 1434 { 1435 maxrules += 100; 1436 1437 plhs = TREALLOC(bucket *, plhs, maxrules); 1438 NO_SPACE(plhs); 1439 1440 rprec = TREALLOC(Value_t, rprec, maxrules); 1441 NO_SPACE(rprec); 1442 1443 rassoc = TREALLOC(Assoc_t, rassoc, maxrules); 1444 NO_SPACE(rassoc); 1445 } 1446 1447 /* set immediately prior to where copy_args() could be called, and incremented by 1448 the various routines that will rescan the argument list as appropriate */ 1449 static int rescan_lineno; 1450 #if defined(YYBTYACC) 1451 1452 static char * 1453 copy_args(int *alen) 1454 { 1455 struct mstring *s = msnew(); 1456 int depth = 0, len = 1; 1457 char c, quote = 0; 1458 int a_lineno = lineno; 1459 char *a_line = dup_line(); 1460 char *a_cptr = a_line + (cptr - line - 1); 1461 1462 while ((c = *cptr++) != R_PAREN || depth || quote) 1463 { 1464 if (c == ',' && !quote && !depth) 1465 { 1466 len++; 1467 mputc(s, 0); 1468 continue; 1469 } 1470 mputc(s, c); 1471 if (c == '\n') 1472 { 1473 get_line(); 1474 if (!line) 1475 { 1476 if (quote) 1477 unterminated_string(a_lineno, a_line, a_cptr); 1478 else 1479 unterminated_arglist(a_lineno, a_line, a_cptr); 1480 } 1481 } 1482 else if (quote) 1483 { 1484 if (c == quote) 1485 quote = 0; 1486 else if (c == '\\') 1487 { 1488 if (*cptr != '\n') 1489 mputc(s, *cptr++); 1490 } 1491 } 1492 else 1493 { 1494 if (c == L_PAREN) 1495 depth++; 1496 else if (c == R_PAREN) 1497 depth--; 1498 else if (c == '\"' || c == '\'') 1499 quote = c; 1500 } 1501 } 1502 if (alen) 1503 *alen = len; 1504 FREE(a_line); 1505 return msdone(s); 1506 } 1507 1508 static char * 1509 parse_id(char *p, char **save) 1510 { 1511 char *b; 1512 1513 while (isspace(*p)) 1514 if (*p++ == '\n') 1515 rescan_lineno++; 1516 if (!isalpha(*p) && *p != '_') 1517 return NULL; 1518 b = p; 1519 while (isalnum(*p) || *p == '_' || *p == '$') 1520 p++; 1521 if (save) 1522 { 1523 *save = cache_tag(b, (size_t) (p - b)); 1524 } 1525 return p; 1526 } 1527 1528 static char * 1529 parse_int(char *p, int *save) 1530 { 1531 int neg = 0, val = 0; 1532 1533 while (isspace(*p)) 1534 if (*p++ == '\n') 1535 rescan_lineno++; 1536 if (*p == '-') 1537 { 1538 neg = 1; 1539 p++; 1540 } 1541 if (!isdigit(*p)) 1542 return NULL; 1543 while (isdigit(*p)) 1544 val = val * 10 + *p++ - '0'; 1545 if (neg) 1546 val = -val; 1547 if (save) 1548 *save = val; 1549 return p; 1550 } 1551 1552 static void 1553 parse_arginfo(bucket *a, char *args, int argslen) 1554 { 1555 char *p = args, *tmp; 1556 int i, redec = 0; 1557 1558 if (a->args > 0) 1559 { 1560 if (a->args != argslen) 1561 arg_number_disagree_warning(rescan_lineno, a->name); 1562 redec = 1; 1563 } 1564 else 1565 { 1566 if ((a->args = argslen) == 0) 1567 return; 1568 a->argnames = TMALLOC(char *, argslen); 1569 NO_SPACE(a->argnames); 1570 a->argtags = TMALLOC(char *, argslen); 1571 NO_SPACE(a->argtags); 1572 } 1573 if (!args) 1574 return; 1575 for (i = 0; i < argslen; i++) 1576 { 1577 while (isspace(*p)) 1578 if (*p++ == '\n') 1579 rescan_lineno++; 1580 if (*p++ != '$') 1581 bad_formals(); 1582 while (isspace(*p)) 1583 if (*p++ == '\n') 1584 rescan_lineno++; 1585 if (*p == '<') 1586 { 1587 havetags = 1; 1588 if (!(p = parse_id(p + 1, &tmp))) 1589 bad_formals(); 1590 while (isspace(*p)) 1591 if (*p++ == '\n') 1592 rescan_lineno++; 1593 if (*p++ != '>') 1594 bad_formals(); 1595 if (redec) 1596 { 1597 if (a->argtags[i] != tmp) 1598 arg_type_disagree_warning(rescan_lineno, i + 1, a->name); 1599 } 1600 else 1601 a->argtags[i] = tmp; 1602 } 1603 else if (!redec) 1604 a->argtags[i] = NULL; 1605 if (!(p = parse_id(p, &a->argnames[i]))) 1606 bad_formals(); 1607 while (isspace(*p)) 1608 if (*p++ == '\n') 1609 rescan_lineno++; 1610 if (*p++) 1611 bad_formals(); 1612 } 1613 free(args); 1614 } 1615 1616 static char * 1617 compile_arg(char **theptr, char *yyvaltag) 1618 { 1619 char *p = *theptr; 1620 struct mstring *c = msnew(); 1621 int i, j, n; 1622 Value_t *offsets = NULL, maxoffset; 1623 bucket **rhs; 1624 1625 maxoffset = 0; 1626 n = 0; 1627 for (i = nitems - 1; pitem[i]; --i) 1628 { 1629 n++; 1630 if (pitem[i]->class != ARGUMENT) 1631 maxoffset++; 1632 } 1633 if (maxoffset > 0) 1634 { 1635 offsets = TMALLOC(Value_t, maxoffset + 1); 1636 NO_SPACE(offsets); 1637 } 1638 for (j = 0, i++; i < nitems; i++) 1639 if (pitem[i]->class != ARGUMENT) 1640 offsets[++j] = (Value_t) (i - nitems + 1); 1641 rhs = pitem + nitems - 1; 1642 1643 if (yyvaltag) 1644 msprintf(c, "yyval.%s = ", yyvaltag); 1645 else 1646 msprintf(c, "yyval = "); 1647 while (*p) 1648 { 1649 if (*p == '$') 1650 { 1651 char *tag = NULL; 1652 if (*++p == '<') 1653 if (!(p = parse_id(++p, &tag)) || *p++ != '>') 1654 illegal_tag(rescan_lineno, NULL, NULL); 1655 if (isdigit(*p) || *p == '-') 1656 { 1657 int val; 1658 if (!(p = parse_int(p, &val))) 1659 dollar_error(rescan_lineno, NULL, NULL); 1660 if (val <= 0) 1661 i = val - n; 1662 else if (val > maxoffset) 1663 { 1664 dollar_warning(rescan_lineno, val); 1665 i = val - maxoffset; 1666 } 1667 else 1668 { 1669 i = offsets[val]; 1670 if (!tag && !(tag = rhs[i]->tag) && havetags) 1671 untyped_rhs(val, rhs[i]->name); 1672 } 1673 msprintf(c, "yystack.l_mark[%d]", i); 1674 if (tag) 1675 msprintf(c, ".%s", tag); 1676 else if (havetags) 1677 unknown_rhs(val); 1678 } 1679 else if (isalpha(*p) || *p == '_') 1680 { 1681 char *arg; 1682 if (!(p = parse_id(p, &arg))) 1683 dollar_error(rescan_lineno, NULL, NULL); 1684 for (i = plhs[nrules]->args - 1; i >= 0; i--) 1685 if (arg == plhs[nrules]->argnames[i]) 1686 break; 1687 if (i < 0) 1688 unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL); 1689 else if (!tag) 1690 tag = plhs[nrules]->argtags[i]; 1691 msprintf(c, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 1692 - n); 1693 if (tag) 1694 msprintf(c, ".%s", tag); 1695 else if (havetags) 1696 untyped_arg_warning(rescan_lineno, "$", arg); 1697 } 1698 else 1699 dollar_error(rescan_lineno, NULL, NULL); 1700 } 1701 else if (*p == '@') 1702 { 1703 at_error(rescan_lineno, NULL, NULL); 1704 } 1705 else 1706 { 1707 if (*p == '\n') 1708 rescan_lineno++; 1709 mputc(c, *p++); 1710 } 1711 } 1712 *theptr = p; 1713 if (maxoffset > 0) 1714 FREE(offsets); 1715 return msdone(c); 1716 } 1717 1718 #define ARG_CACHE_SIZE 1024 1719 static struct arg_cache 1720 { 1721 struct arg_cache *next; 1722 char *code; 1723 int rule; 1724 } 1725 *arg_cache[ARG_CACHE_SIZE]; 1726 1727 static int 1728 lookup_arg_cache(char *code) 1729 { 1730 struct arg_cache *entry; 1731 1732 entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE]; 1733 while (entry) 1734 { 1735 if (!strnscmp(entry->code, code)) 1736 return entry->rule; 1737 entry = entry->next; 1738 } 1739 return -1; 1740 } 1741 1742 static void 1743 insert_arg_cache(char *code, int rule) 1744 { 1745 struct arg_cache *entry = NEW(struct arg_cache); 1746 int i; 1747 1748 NO_SPACE(entry); 1749 i = strnshash(code) % ARG_CACHE_SIZE; 1750 entry->code = code; 1751 entry->rule = rule; 1752 entry->next = arg_cache[i]; 1753 arg_cache[i] = entry; 1754 } 1755 1756 static void 1757 clean_arg_cache(void) 1758 { 1759 struct arg_cache *e, *t; 1760 int i; 1761 1762 for (i = 0; i < ARG_CACHE_SIZE; i++) 1763 { 1764 for (e = arg_cache[i]; (t = e); e = e->next, FREE(t)) 1765 free(e->code); 1766 arg_cache[i] = NULL; 1767 } 1768 } 1769 #endif 1770 1771 static void 1772 advance_to_start(void) 1773 { 1774 int c; 1775 bucket *bp; 1776 char *s_cptr; 1777 int s_lineno; 1778 #if defined(YYBTYACC) 1779 char *args = NULL; 1780 int argslen = 0; 1781 #endif 1782 1783 for (;;) 1784 { 1785 c = nextc(); 1786 if (c != '%') 1787 break; 1788 s_cptr = cptr; 1789 switch (keyword()) 1790 { 1791 case MARK: 1792 no_grammar(); 1793 1794 case TEXT: 1795 copy_text(); 1796 break; 1797 1798 case START: 1799 declare_start(); 1800 break; 1801 1802 default: 1803 syntax_error(lineno, line, s_cptr); 1804 } 1805 } 1806 1807 c = nextc(); 1808 if (!isalpha(c) && c != '_' && c != '.' && c != '_') 1809 syntax_error(lineno, line, cptr); 1810 bp = get_name(); 1811 if (goal == 0) 1812 { 1813 if (bp->class == TERM) 1814 terminal_start(bp->name); 1815 goal = bp; 1816 } 1817 1818 s_lineno = lineno; 1819 c = nextc(); 1820 if (c == EOF) 1821 unexpected_EOF(); 1822 rescan_lineno = lineno; /* line# for possible inherited args rescan */ 1823 #if defined(YYBTYACC) 1824 if (c == L_PAREN) 1825 { 1826 ++cptr; 1827 args = copy_args(&argslen); 1828 NO_SPACE(args); 1829 c = nextc(); 1830 } 1831 #endif 1832 if (c != ':') 1833 syntax_error(lineno, line, cptr); 1834 start_rule(bp, s_lineno); 1835 #if defined(YYBTYACC) 1836 parse_arginfo(bp, args, argslen); 1837 #endif 1838 ++cptr; 1839 } 1840 1841 static void 1842 start_rule(bucket *bp, int s_lineno) 1843 { 1844 if (bp->class == TERM) 1845 terminal_lhs(s_lineno); 1846 bp->class = NONTERM; 1847 if (!bp->index) 1848 bp->index = nrules; 1849 if (nrules >= maxrules) 1850 expand_rules(); 1851 plhs[nrules] = bp; 1852 rprec[nrules] = UNDEFINED; 1853 rassoc[nrules] = TOKEN; 1854 } 1855 1856 static void 1857 end_rule(void) 1858 { 1859 int i; 1860 1861 if (!last_was_action && plhs[nrules]->tag) 1862 { 1863 if (pitem[nitems - 1]) 1864 { 1865 for (i = nitems - 1; (i > 0) && pitem[i]; --i) 1866 continue; 1867 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag) 1868 default_action_warning(); 1869 } 1870 else 1871 { 1872 default_action_warning(); 1873 } 1874 } 1875 1876 last_was_action = 0; 1877 if (nitems >= maxitems) 1878 expand_items(); 1879 pitem[nitems] = 0; 1880 ++nitems; 1881 ++nrules; 1882 } 1883 1884 static void 1885 insert_empty_rule(void) 1886 { 1887 bucket *bp, **bpp; 1888 1889 assert(cache); 1890 sprintf(cache, "$$%d", ++gensym); 1891 bp = make_bucket(cache); 1892 last_symbol->next = bp; 1893 last_symbol = bp; 1894 bp->tag = plhs[nrules]->tag; 1895 bp->class = ACTION; 1896 #if defined(YYBTYACC) 1897 bp->args = 0; 1898 #endif 1899 1900 nitems = (Value_t) (nitems + 2); 1901 if (nitems > maxitems) 1902 expand_items(); 1903 bpp = pitem + nitems - 1; 1904 *bpp-- = bp; 1905 while ((bpp[0] = bpp[-1]) != 0) 1906 --bpp; 1907 1908 if (++nrules >= maxrules) 1909 expand_rules(); 1910 plhs[nrules] = plhs[nrules - 1]; 1911 plhs[nrules - 1] = bp; 1912 rprec[nrules] = rprec[nrules - 1]; 1913 rprec[nrules - 1] = 0; 1914 rassoc[nrules] = rassoc[nrules - 1]; 1915 rassoc[nrules - 1] = TOKEN; 1916 } 1917 1918 #if defined(YYBTYACC) 1919 static char * 1920 insert_arg_rule(char *arg, char *tag) 1921 { 1922 int line_number = rescan_lineno; 1923 char *code = compile_arg(&arg, tag); 1924 int rule = lookup_arg_cache(code); 1925 FILE *f = action_file; 1926 1927 if (rule < 0) 1928 { 1929 rule = nrules; 1930 insert_arg_cache(code, rule); 1931 fprintf(f, "case %d:\n", rule - 2); 1932 if (!lflag) 1933 fprintf(f, line_format, line_number, input_file_name); 1934 fprintf(f, "%s;\n", code); 1935 fprintf(f, "break;\n"); 1936 insert_empty_rule(); 1937 plhs[rule]->tag = tag; 1938 plhs[rule]->class = ARGUMENT; 1939 } 1940 else 1941 { 1942 if (++nitems > maxitems) 1943 expand_items(); 1944 pitem[nitems - 1] = plhs[rule]; 1945 free(code); 1946 } 1947 return arg + 1; 1948 } 1949 #endif 1950 1951 static void 1952 add_symbol(void) 1953 { 1954 int c; 1955 bucket *bp; 1956 int s_lineno = lineno; 1957 #if defined(YYBTYACC) 1958 char *args = NULL; 1959 int argslen = 0; 1960 #endif 1961 1962 c = *cptr; 1963 if (c == '\'' || c == '"') 1964 bp = get_literal(); 1965 else 1966 bp = get_name(); 1967 1968 c = nextc(); 1969 rescan_lineno = lineno; /* line# for possible inherited args rescan */ 1970 #if defined(YYBTYACC) 1971 if (c == L_PAREN) 1972 { 1973 ++cptr; 1974 args = copy_args(&argslen); 1975 NO_SPACE(args); 1976 c = nextc(); 1977 } 1978 #endif 1979 if (c == ':') 1980 { 1981 end_rule(); 1982 start_rule(bp, s_lineno); 1983 #if defined(YYBTYACC) 1984 parse_arginfo(bp, args, argslen); 1985 #endif 1986 ++cptr; 1987 return; 1988 } 1989 1990 if (last_was_action) 1991 insert_empty_rule(); 1992 last_was_action = 0; 1993 1994 #if defined(YYBTYACC) 1995 if (bp->args < 0) 1996 bp->args = argslen; 1997 if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL) 1998 { 1999 int i; 2000 if (plhs[nrules]->args != bp->args) 2001 wrong_number_args_warning("default ", bp->name); 2002 for (i = bp->args - 1; i >= 0; i--) 2003 if (plhs[nrules]->argtags[i] != bp->argtags[i]) 2004 wrong_type_for_arg_warning(i + 1, bp->name); 2005 } 2006 else if (bp->args != argslen) 2007 wrong_number_args_warning("", bp->name); 2008 if (bp->args > 0 && argslen > 0) 2009 { 2010 char *ap; 2011 int i; 2012 for (ap = args, i = 0; i < argslen; i++) 2013 ap = insert_arg_rule(ap, bp->argtags[i]); 2014 free(args); 2015 } 2016 #endif /* defined(YYBTYACC) */ 2017 2018 if (++nitems > maxitems) 2019 expand_items(); 2020 pitem[nitems - 1] = bp; 2021 } 2022 2023 static char * 2024 after_blanks(char *s) 2025 { 2026 while (*s != '\0' && isspace(UCH(*s))) 2027 ++s; 2028 return s; 2029 } 2030 2031 static void 2032 copy_action(void) 2033 { 2034 int c; 2035 int i, j, n; 2036 int depth; 2037 #if defined(YYBTYACC) 2038 int trialaction = 0; 2039 int haveyyval = 0; 2040 #endif 2041 char *tag; 2042 FILE *f = action_file; 2043 int a_lineno = lineno; 2044 char *a_line = dup_line(); 2045 char *a_cptr = a_line + (cptr - line); 2046 Value_t *offsets = NULL, maxoffset; 2047 bucket **rhs; 2048 2049 if (last_was_action) 2050 insert_empty_rule(); 2051 last_was_action = 1; 2052 2053 fprintf(f, "case %d:\n", nrules - 2); 2054 #if defined(YYBTYACC) 2055 if (backtrack) 2056 { 2057 if (*cptr != L_BRAC) 2058 fprintf(f, " if (!yytrial)\n"); 2059 else 2060 trialaction = 1; 2061 } 2062 #endif 2063 if (!lflag) 2064 fprintf(f, line_format, lineno, input_file_name); 2065 if (*cptr == '=') 2066 ++cptr; 2067 2068 /* avoid putting curly-braces in first column, to ease editing */ 2069 if (*after_blanks(cptr) == L_CURL) 2070 { 2071 putc('\t', f); 2072 cptr = after_blanks(cptr); 2073 } 2074 2075 maxoffset = 0; 2076 n = 0; 2077 for (i = nitems - 1; pitem[i]; --i) 2078 { 2079 ++n; 2080 if (pitem[i]->class != ARGUMENT) 2081 maxoffset++; 2082 } 2083 if (maxoffset > 0) 2084 { 2085 offsets = TMALLOC(Value_t, maxoffset + 1); 2086 NO_SPACE(offsets); 2087 } 2088 for (j = 0, i++; i < nitems; i++) 2089 { 2090 if (pitem[i]->class != ARGUMENT) 2091 { 2092 offsets[++j] = (Value_t) (i - nitems + 1); 2093 } 2094 } 2095 rhs = pitem + nitems - 1; 2096 2097 depth = 0; 2098 loop: 2099 c = *cptr; 2100 if (c == '$') 2101 { 2102 if (cptr[1] == '<') 2103 { 2104 int d_lineno = lineno; 2105 char *d_line = dup_line(); 2106 char *d_cptr = d_line + (cptr - line); 2107 2108 ++cptr; 2109 tag = get_tag(); 2110 c = *cptr; 2111 if (c == '$') 2112 { 2113 fprintf(f, "yyval.%s", tag); 2114 ++cptr; 2115 FREE(d_line); 2116 goto loop; 2117 } 2118 else if (isdigit(c)) 2119 { 2120 i = get_number(); 2121 if (i == 0) 2122 fprintf(f, "yystack.l_mark[%d].%s", -n, tag); 2123 else if (i > maxoffset) 2124 { 2125 dollar_warning(d_lineno, i); 2126 fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag); 2127 } 2128 else if (offsets) 2129 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag); 2130 FREE(d_line); 2131 goto loop; 2132 } 2133 else if (c == '-' && isdigit(UCH(cptr[1]))) 2134 { 2135 ++cptr; 2136 i = -get_number() - n; 2137 fprintf(f, "yystack.l_mark[%d].%s", i, tag); 2138 FREE(d_line); 2139 goto loop; 2140 } 2141 #if defined(YYBTYACC) 2142 else if (isalpha(c) || c == '_') 2143 { 2144 char *arg = scan_id(); 2145 for (i = plhs[nrules]->args - 1; i >= 0; i--) 2146 if (arg == plhs[nrules]->argnames[i]) 2147 break; 2148 if (i < 0) 2149 unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr); 2150 fprintf(f, "yystack.l_mark[%d].%s", i - plhs[nrules]->args + 2151 1 - n, tag); 2152 FREE(d_line); 2153 goto loop; 2154 } 2155 #endif 2156 else 2157 dollar_error(d_lineno, d_line, d_cptr); 2158 } 2159 else if (cptr[1] == '$') 2160 { 2161 if (havetags) 2162 { 2163 tag = plhs[nrules]->tag; 2164 if (tag == 0) 2165 untyped_lhs(); 2166 fprintf(f, "yyval.%s", tag); 2167 } 2168 else 2169 fprintf(f, "yyval"); 2170 cptr += 2; 2171 #if defined(YYBTYACC) 2172 haveyyval = 1; 2173 #endif 2174 goto loop; 2175 } 2176 else if (isdigit(UCH(cptr[1]))) 2177 { 2178 ++cptr; 2179 i = get_number(); 2180 if (havetags) 2181 { 2182 if (i <= 0 || i > maxoffset) 2183 unknown_rhs(i); 2184 tag = rhs[offsets[i]]->tag; 2185 if (tag == 0) 2186 untyped_rhs(i, rhs[offsets[i]]->name); 2187 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag); 2188 } 2189 else 2190 { 2191 if (i == 0) 2192 fprintf(f, "yystack.l_mark[%d]", -n); 2193 else if (i > maxoffset) 2194 { 2195 dollar_warning(lineno, i); 2196 fprintf(f, "yystack.l_mark[%d]", i - maxoffset); 2197 } 2198 else if (offsets) 2199 fprintf(f, "yystack.l_mark[%d]", offsets[i]); 2200 } 2201 goto loop; 2202 } 2203 else if (cptr[1] == '-') 2204 { 2205 cptr += 2; 2206 i = get_number(); 2207 if (havetags) 2208 unknown_rhs(-i); 2209 fprintf(f, "yystack.l_mark[%d]", -i - n); 2210 goto loop; 2211 } 2212 #if defined(YYBTYACC) 2213 else if (isalpha(cptr[1]) || cptr[1] == '_') 2214 { 2215 char *arg; 2216 ++cptr; 2217 arg = scan_id(); 2218 for (i = plhs[nrules]->args - 1; i >= 0; i--) 2219 if (arg == plhs[nrules]->argnames[i]) 2220 break; 2221 if (i < 0) 2222 unknown_arg_warning(lineno, "$", arg, line, cptr); 2223 tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]); 2224 fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n); 2225 if (tag) 2226 fprintf(f, ".%s", tag); 2227 else if (havetags) 2228 untyped_arg_warning(lineno, "$", arg); 2229 goto loop; 2230 } 2231 #endif 2232 } 2233 #if defined(YYBTYACC) 2234 if (c == '@') 2235 { 2236 if (!locations) 2237 { 2238 int l_lineno = lineno; 2239 char *l_line = dup_line(); 2240 char *l_cptr = l_line + (cptr - line); 2241 syntax_error(l_lineno, l_line, l_cptr); 2242 } 2243 if (cptr[1] == '$') 2244 { 2245 fprintf(f, "yyloc"); 2246 cptr += 2; 2247 goto loop; 2248 } 2249 else if (isdigit(UCH(cptr[1]))) 2250 { 2251 ++cptr; 2252 i = get_number(); 2253 if (i == 0) 2254 fprintf(f, "yystack.p_mark[%d]", -n); 2255 else if (i > maxoffset) 2256 { 2257 at_warning(lineno, i); 2258 fprintf(f, "yystack.p_mark[%d]", i - maxoffset); 2259 } 2260 else if (offsets) 2261 fprintf(f, "yystack.p_mark[%d]", offsets[i]); 2262 goto loop; 2263 } 2264 } 2265 #endif 2266 if (isalpha(c) || c == '_' || c == '$') 2267 { 2268 do 2269 { 2270 putc(c, f); 2271 c = *++cptr; 2272 } 2273 while (isalnum(c) || c == '_' || c == '$'); 2274 goto loop; 2275 } 2276 ++cptr; 2277 #if defined(YYBTYACC) 2278 if (backtrack) 2279 { 2280 if (trialaction && c == L_BRAC && depth == 0) 2281 { 2282 ++depth; 2283 putc(L_CURL, f); 2284 goto loop; 2285 } 2286 if (trialaction && c == R_BRAC && depth == 1) 2287 { 2288 --depth; 2289 putc(R_CURL, f); 2290 c = nextc(); 2291 if (c == L_BRAC && !haveyyval) 2292 { 2293 goto loop; 2294 } 2295 if (c == L_CURL && !haveyyval) 2296 { 2297 fprintf(f, " if (!yytrial)\n"); 2298 if (!lflag) 2299 fprintf(f, line_format, lineno, input_file_name); 2300 trialaction = 0; 2301 goto loop; 2302 } 2303 fprintf(f, "\nbreak;\n"); 2304 FREE(a_line); 2305 if (maxoffset > 0) 2306 FREE(offsets); 2307 return; 2308 } 2309 } 2310 #endif 2311 putc(c, f); 2312 switch (c) 2313 { 2314 case '\n': 2315 get_line(); 2316 if (line) 2317 goto loop; 2318 unterminated_action(a_lineno, a_line, a_cptr); 2319 2320 case ';': 2321 if (depth > 0) 2322 goto loop; 2323 fprintf(f, "\nbreak;\n"); 2324 free(a_line); 2325 if (maxoffset > 0) 2326 FREE(offsets); 2327 return; 2328 2329 #if defined(YYBTYACC) 2330 case L_BRAC: 2331 if (backtrack) 2332 ++depth; 2333 goto loop; 2334 2335 case R_BRAC: 2336 if (backtrack) 2337 --depth; 2338 goto loop; 2339 #endif 2340 2341 case L_CURL: 2342 ++depth; 2343 goto loop; 2344 2345 case R_CURL: 2346 if (--depth > 0) 2347 goto loop; 2348 #if defined(YYBTYACC) 2349 if (backtrack) 2350 { 2351 c = nextc(); 2352 if (c == L_BRAC && !haveyyval) 2353 { 2354 trialaction = 1; 2355 goto loop; 2356 } 2357 if (c == L_CURL && !haveyyval) 2358 { 2359 fprintf(f, " if (!yytrial)\n"); 2360 if (!lflag) 2361 fprintf(f, line_format, lineno, input_file_name); 2362 goto loop; 2363 } 2364 } 2365 #endif 2366 fprintf(f, "\nbreak;\n"); 2367 free(a_line); 2368 if (maxoffset > 0) 2369 FREE(offsets); 2370 return; 2371 2372 case '\'': 2373 case '"': 2374 { 2375 char *s = copy_string(c); 2376 fputs(s, f); 2377 free(s); 2378 } 2379 goto loop; 2380 2381 case '/': 2382 { 2383 char *s = copy_comment(); 2384 fputs(s, f); 2385 free(s); 2386 } 2387 goto loop; 2388 2389 default: 2390 goto loop; 2391 } 2392 } 2393 2394 #if defined(YYBTYACC) 2395 static void 2396 copy_destructor(void) 2397 { 2398 int c; 2399 int depth; 2400 char *tag; 2401 bucket *bp; 2402 struct mstring *destructor_text = msnew(); 2403 char *code_text; 2404 int a_lineno; 2405 char *a_line; 2406 char *a_cptr; 2407 2408 if (!lflag) 2409 msprintf(destructor_text, line_format, lineno, input_file_name); 2410 2411 cptr = after_blanks(cptr); 2412 if (*cptr == L_CURL) 2413 /* avoid putting curly-braces in first column, to ease editing */ 2414 mputc(destructor_text, '\t'); 2415 else 2416 syntax_error(lineno, line, cptr); 2417 2418 a_lineno = lineno; 2419 a_line = dup_line(); 2420 a_cptr = a_line + (cptr - line); 2421 2422 depth = 0; 2423 loop: 2424 c = *cptr; 2425 if (c == '$') 2426 { 2427 if (cptr[1] == '<') 2428 { 2429 int d_lineno = lineno; 2430 char *d_line = dup_line(); 2431 char *d_cptr = d_line + (cptr - line); 2432 2433 ++cptr; 2434 tag = get_tag(); 2435 c = *cptr; 2436 if (c == '$') 2437 { 2438 msprintf(destructor_text, "(*val).%s", tag); 2439 ++cptr; 2440 FREE(d_line); 2441 goto loop; 2442 } 2443 else 2444 dollar_error(d_lineno, d_line, d_cptr); 2445 } 2446 else if (cptr[1] == '$') 2447 { 2448 /* process '$$' later; replacement is context dependent */ 2449 msprintf(destructor_text, "$$"); 2450 cptr += 2; 2451 goto loop; 2452 } 2453 } 2454 if (c == '@' && cptr[1] == '$') 2455 { 2456 if (!locations) 2457 { 2458 int l_lineno = lineno; 2459 char *l_line = dup_line(); 2460 char *l_cptr = l_line + (cptr - line); 2461 syntax_error(l_lineno, l_line, l_cptr); 2462 } 2463 msprintf(destructor_text, "(*loc)"); 2464 cptr += 2; 2465 goto loop; 2466 } 2467 if (isalpha(c) || c == '_' || c == '$') 2468 { 2469 do 2470 { 2471 mputc(destructor_text, c); 2472 c = *++cptr; 2473 } 2474 while (isalnum(c) || c == '_' || c == '$'); 2475 goto loop; 2476 } 2477 ++cptr; 2478 mputc(destructor_text, c); 2479 switch (c) 2480 { 2481 case '\n': 2482 get_line(); 2483 if (line) 2484 goto loop; 2485 unterminated_action(a_lineno, a_line, a_cptr); 2486 2487 case L_CURL: 2488 ++depth; 2489 goto loop; 2490 2491 case R_CURL: 2492 if (--depth > 0) 2493 goto loop; 2494 goto process_symbols; 2495 2496 case '\'': 2497 case '"': 2498 { 2499 char *s = copy_string(c); 2500 msprintf(destructor_text, "%s", s); 2501 free(s); 2502 } 2503 goto loop; 2504 2505 case '/': 2506 { 2507 char *s = copy_comment(); 2508 msprintf(destructor_text, "%s", s); 2509 free(s); 2510 } 2511 goto loop; 2512 2513 default: 2514 goto loop; 2515 } 2516 process_symbols: 2517 code_text = msdone(destructor_text); 2518 for (;;) 2519 { 2520 c = nextc(); 2521 if (c == EOF) 2522 unexpected_EOF(); 2523 if (c == '<') 2524 { 2525 if (cptr[1] == '>') 2526 { /* "no semantic type" default destructor */ 2527 cptr += 2; 2528 if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL) 2529 { 2530 static char untyped_default[] = "<>"; 2531 bp = make_bucket("untyped default"); 2532 bp->tag = untyped_default; 2533 default_destructor[UNTYPED_DEFAULT] = bp; 2534 } 2535 if (bp->destructor != NULL) 2536 destructor_redeclared_warning(a_lineno, a_line, a_cptr); 2537 else 2538 /* replace "$$" with "(*val)" in destructor code */ 2539 bp->destructor = process_destructor_XX(code_text, NULL); 2540 } 2541 else if (cptr[1] == '*' && cptr[2] == '>') 2542 { /* "no per-symbol or per-type" default destructor */ 2543 cptr += 3; 2544 if ((bp = default_destructor[TYPED_DEFAULT]) == NULL) 2545 { 2546 static char typed_default[] = "<*>"; 2547 bp = make_bucket("typed default"); 2548 bp->tag = typed_default; 2549 default_destructor[TYPED_DEFAULT] = bp; 2550 } 2551 if (bp->destructor != NULL) 2552 destructor_redeclared_warning(a_lineno, a_line, a_cptr); 2553 else 2554 { 2555 /* postpone re-processing destructor $$s until end of grammar spec */ 2556 bp->destructor = TMALLOC(char, strlen(code_text) + 1); 2557 NO_SPACE(bp->destructor); 2558 strcpy(bp->destructor, code_text); 2559 } 2560 } 2561 else 2562 { /* "semantic type" default destructor */ 2563 tag = get_tag(); 2564 bp = lookup_type_destructor(tag); 2565 if (bp->destructor != NULL) 2566 destructor_redeclared_warning(a_lineno, a_line, a_cptr); 2567 else 2568 /* replace "$$" with "(*val).tag" in destructor code */ 2569 bp->destructor = process_destructor_XX(code_text, tag); 2570 } 2571 } 2572 else if (isalpha(c) || c == '_' || c == '.' || c == '$') 2573 { /* "symbol" destructor */ 2574 bp = get_name(); 2575 if (bp->destructor != NULL) 2576 destructor_redeclared_warning(a_lineno, a_line, a_cptr); 2577 else 2578 { 2579 /* postpone re-processing destructor $$s until end of grammar spec */ 2580 bp->destructor = TMALLOC(char, strlen(code_text) + 1); 2581 NO_SPACE(bp->destructor); 2582 strcpy(bp->destructor, code_text); 2583 } 2584 } 2585 else 2586 break; 2587 } 2588 free(a_line); 2589 free(code_text); 2590 } 2591 2592 static char * 2593 process_destructor_XX(char *code, char *tag) 2594 { 2595 int c; 2596 int quote; 2597 int depth; 2598 struct mstring *new_code = msnew(); 2599 char *codeptr = code; 2600 2601 depth = 0; 2602 loop: /* step thru code */ 2603 c = *codeptr; 2604 if (c == '$' && codeptr[1] == '$') 2605 { 2606 codeptr += 2; 2607 if (tag == NULL) 2608 msprintf(new_code, "(*val)"); 2609 else 2610 msprintf(new_code, "(*val).%s", tag); 2611 goto loop; 2612 } 2613 if (isalpha(c) || c == '_' || c == '$') 2614 { 2615 do 2616 { 2617 mputc(new_code, c); 2618 c = *++codeptr; 2619 } 2620 while (isalnum(c) || c == '_' || c == '$'); 2621 goto loop; 2622 } 2623 ++codeptr; 2624 mputc(new_code, c); 2625 switch (c) 2626 { 2627 case L_CURL: 2628 ++depth; 2629 goto loop; 2630 2631 case R_CURL: 2632 if (--depth > 0) 2633 goto loop; 2634 return msdone(new_code); 2635 2636 case '\'': 2637 case '"': 2638 quote = c; 2639 for (;;) 2640 { 2641 c = *codeptr++; 2642 mputc(new_code, c); 2643 if (c == quote) 2644 goto loop; 2645 if (c == '\\') 2646 { 2647 c = *codeptr++; 2648 mputc(new_code, c); 2649 } 2650 } 2651 2652 case '/': 2653 c = *codeptr; 2654 if (c == '*') 2655 { 2656 mputc(new_code, c); 2657 ++codeptr; 2658 for (;;) 2659 { 2660 c = *codeptr++; 2661 mputc(new_code, c); 2662 if (c == '*' && *codeptr == '/') 2663 { 2664 mputc(new_code, '/'); 2665 ++codeptr; 2666 goto loop; 2667 } 2668 } 2669 } 2670 goto loop; 2671 2672 default: 2673 goto loop; 2674 } 2675 } 2676 #endif /* defined(YYBTYACC) */ 2677 2678 static int 2679 mark_symbol(void) 2680 { 2681 int c; 2682 bucket *bp = NULL; 2683 2684 c = cptr[1]; 2685 if (c == '%' || c == '\\') 2686 { 2687 cptr += 2; 2688 return (1); 2689 } 2690 2691 if (c == '=') 2692 cptr += 2; 2693 else if ((c == 'p' || c == 'P') && 2694 ((c = cptr[2]) == 'r' || c == 'R') && 2695 ((c = cptr[3]) == 'e' || c == 'E') && 2696 ((c = cptr[4]) == 'c' || c == 'C') && 2697 ((c = cptr[5], !IS_IDENT(c)))) 2698 cptr += 5; 2699 else 2700 syntax_error(lineno, line, cptr); 2701 2702 c = nextc(); 2703 if (isalpha(c) || c == '_' || c == '.' || c == '$') 2704 bp = get_name(); 2705 else if (c == '\'' || c == '"') 2706 bp = get_literal(); 2707 else 2708 { 2709 syntax_error(lineno, line, cptr); 2710 } 2711 2712 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules]) 2713 prec_redeclared(); 2714 2715 rprec[nrules] = bp->prec; 2716 rassoc[nrules] = bp->assoc; 2717 return (0); 2718 } 2719 2720 static void 2721 read_grammar(void) 2722 { 2723 int c; 2724 2725 initialize_grammar(); 2726 advance_to_start(); 2727 2728 for (;;) 2729 { 2730 c = nextc(); 2731 if (c == EOF) 2732 break; 2733 if (isalpha(c) 2734 || c == '_' 2735 || c == '.' 2736 || c == '$' 2737 || c == '\'' 2738 || c == '"') 2739 add_symbol(); 2740 #if defined(YYBTYACC) 2741 else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC)) 2742 #else 2743 else if (c == L_CURL || c == '=') 2744 #endif 2745 copy_action(); 2746 else if (c == '|') 2747 { 2748 end_rule(); 2749 start_rule(plhs[nrules - 1], 0); 2750 ++cptr; 2751 } 2752 else if (c == '%') 2753 { 2754 if (mark_symbol()) 2755 break; 2756 } 2757 else 2758 syntax_error(lineno, line, cptr); 2759 } 2760 end_rule(); 2761 #if defined(YYBTYACC) 2762 if (goal->args > 0) 2763 start_requires_args(goal->name); 2764 #endif 2765 } 2766 2767 static void 2768 free_tags(void) 2769 { 2770 int i; 2771 2772 if (tag_table == 0) 2773 return; 2774 2775 for (i = 0; i < ntags; ++i) 2776 { 2777 assert(tag_table[i]); 2778 FREE(tag_table[i]); 2779 } 2780 FREE(tag_table); 2781 } 2782 2783 static void 2784 pack_names(void) 2785 { 2786 bucket *bp; 2787 char *p, *s, *t; 2788 2789 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */ 2790 for (bp = first_symbol; bp; bp = bp->next) 2791 name_pool_size += strlen(bp->name) + 1; 2792 2793 name_pool = TMALLOC(char, name_pool_size); 2794 NO_SPACE(name_pool); 2795 2796 strcpy(name_pool, "$accept"); 2797 strcpy(name_pool + 8, "$end"); 2798 t = name_pool + 13; 2799 for (bp = first_symbol; bp; bp = bp->next) 2800 { 2801 p = t; 2802 s = bp->name; 2803 while ((*t++ = *s++) != 0) 2804 continue; 2805 FREE(bp->name); 2806 bp->name = p; 2807 } 2808 } 2809 2810 static void 2811 check_symbols(void) 2812 { 2813 bucket *bp; 2814 2815 if (goal->class == UNKNOWN) 2816 undefined_goal(goal->name); 2817 2818 for (bp = first_symbol; bp; bp = bp->next) 2819 { 2820 if (bp->class == UNKNOWN) 2821 { 2822 undefined_symbol_warning(bp->name); 2823 bp->class = TERM; 2824 } 2825 } 2826 } 2827 2828 static void 2829 protect_string(char *src, char **des) 2830 { 2831 unsigned len; 2832 char *s; 2833 char *d; 2834 2835 *des = src; 2836 if (src) 2837 { 2838 len = 1; 2839 s = src; 2840 while (*s) 2841 { 2842 if ('\\' == *s || '"' == *s) 2843 len++; 2844 s++; 2845 len++; 2846 } 2847 2848 *des = d = TMALLOC(char, len); 2849 NO_SPACE(d); 2850 2851 s = src; 2852 while (*s) 2853 { 2854 if ('\\' == *s || '"' == *s) 2855 *d++ = '\\'; 2856 *d++ = *s++; 2857 } 2858 *d = '\0'; 2859 } 2860 } 2861 2862 static void 2863 pack_symbols(void) 2864 { 2865 bucket *bp; 2866 bucket **v; 2867 Value_t i, j, k, n; 2868 #if defined(YYBTYACC) 2869 Value_t max_tok_pval; 2870 #endif 2871 2872 nsyms = 2; 2873 ntokens = 1; 2874 for (bp = first_symbol; bp; bp = bp->next) 2875 { 2876 ++nsyms; 2877 if (bp->class == TERM) 2878 ++ntokens; 2879 } 2880 start_symbol = (Value_t) ntokens; 2881 nvars = (Value_t) (nsyms - ntokens); 2882 2883 symbol_name = TMALLOC(char *, nsyms); 2884 NO_SPACE(symbol_name); 2885 2886 symbol_value = TMALLOC(Value_t, nsyms); 2887 NO_SPACE(symbol_value); 2888 2889 symbol_prec = TMALLOC(Value_t, nsyms); 2890 NO_SPACE(symbol_prec); 2891 2892 symbol_assoc = TMALLOC(char, nsyms); 2893 NO_SPACE(symbol_assoc); 2894 2895 #if defined(YYBTYACC) 2896 symbol_pval = TMALLOC(Value_t, nsyms); 2897 NO_SPACE(symbol_pval); 2898 2899 if (destructor) 2900 { 2901 symbol_destructor = CALLOC(sizeof(char *), nsyms); 2902 NO_SPACE(symbol_destructor); 2903 2904 symbol_type_tag = CALLOC(sizeof(char *), nsyms); 2905 NO_SPACE(symbol_type_tag); 2906 } 2907 #endif 2908 2909 v = TMALLOC(bucket *, nsyms); 2910 NO_SPACE(v); 2911 2912 v[0] = 0; 2913 v[start_symbol] = 0; 2914 2915 i = 1; 2916 j = (Value_t) (start_symbol + 1); 2917 for (bp = first_symbol; bp; bp = bp->next) 2918 { 2919 if (bp->class == TERM) 2920 v[i++] = bp; 2921 else 2922 v[j++] = bp; 2923 } 2924 assert(i == ntokens && j == nsyms); 2925 2926 for (i = 1; i < ntokens; ++i) 2927 v[i]->index = i; 2928 2929 goal->index = (Index_t) (start_symbol + 1); 2930 k = (Value_t) (start_symbol + 2); 2931 while (++i < nsyms) 2932 if (v[i] != goal) 2933 { 2934 v[i]->index = k; 2935 ++k; 2936 } 2937 2938 goal->value = 0; 2939 k = 1; 2940 for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i) 2941 { 2942 if (v[i] != goal) 2943 { 2944 v[i]->value = k; 2945 ++k; 2946 } 2947 } 2948 2949 k = 0; 2950 for (i = 1; i < ntokens; ++i) 2951 { 2952 n = v[i]->value; 2953 if (n > 256) 2954 { 2955 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j) 2956 symbol_value[j] = symbol_value[j - 1]; 2957 symbol_value[j] = n; 2958 } 2959 } 2960 2961 assert(v[1] != 0); 2962 2963 if (v[1]->value == UNDEFINED) 2964 v[1]->value = 256; 2965 2966 j = 0; 2967 n = 257; 2968 for (i = 2; i < ntokens; ++i) 2969 { 2970 if (v[i]->value == UNDEFINED) 2971 { 2972 while (j < k && n == symbol_value[j]) 2973 { 2974 while (++j < k && n == symbol_value[j]) 2975 continue; 2976 ++n; 2977 } 2978 v[i]->value = n; 2979 ++n; 2980 } 2981 } 2982 2983 symbol_name[0] = name_pool + 8; 2984 symbol_value[0] = 0; 2985 symbol_prec[0] = 0; 2986 symbol_assoc[0] = TOKEN; 2987 #if defined(YYBTYACC) 2988 symbol_pval[0] = 0; 2989 max_tok_pval = 0; 2990 #endif 2991 for (i = 1; i < ntokens; ++i) 2992 { 2993 symbol_name[i] = v[i]->name; 2994 symbol_value[i] = v[i]->value; 2995 symbol_prec[i] = v[i]->prec; 2996 symbol_assoc[i] = v[i]->assoc; 2997 #if defined(YYBTYACC) 2998 symbol_pval[i] = v[i]->value; 2999 if (symbol_pval[i] > max_tok_pval) 3000 max_tok_pval = symbol_pval[i]; 3001 if (destructor) 3002 { 3003 symbol_destructor[i] = v[i]->destructor; 3004 symbol_type_tag[i] = v[i]->tag; 3005 } 3006 #endif 3007 } 3008 symbol_name[start_symbol] = name_pool; 3009 symbol_value[start_symbol] = -1; 3010 symbol_prec[start_symbol] = 0; 3011 symbol_assoc[start_symbol] = TOKEN; 3012 #if defined(YYBTYACC) 3013 symbol_pval[start_symbol] = (Value_t) (max_tok_pval + 1); 3014 #endif 3015 for (++i; i < nsyms; ++i) 3016 { 3017 k = v[i]->index; 3018 symbol_name[k] = v[i]->name; 3019 symbol_value[k] = v[i]->value; 3020 symbol_prec[k] = v[i]->prec; 3021 symbol_assoc[k] = v[i]->assoc; 3022 #if defined(YYBTYACC) 3023 symbol_pval[k] = (Value_t) ((max_tok_pval + 1) + v[i]->value + 1); 3024 if (destructor) 3025 { 3026 symbol_destructor[k] = v[i]->destructor; 3027 symbol_type_tag[k] = v[i]->tag; 3028 } 3029 #endif 3030 } 3031 3032 if (gflag) 3033 { 3034 symbol_pname = TMALLOC(char *, nsyms); 3035 NO_SPACE(symbol_pname); 3036 3037 for (i = 0; i < nsyms; ++i) 3038 protect_string(symbol_name[i], &(symbol_pname[i])); 3039 } 3040 3041 FREE(v); 3042 } 3043 3044 static void 3045 pack_grammar(void) 3046 { 3047 int i; 3048 Value_t j; 3049 Assoc_t assoc; 3050 Value_t prec2; 3051 3052 ritem = TMALLOC(Value_t, nitems); 3053 NO_SPACE(ritem); 3054 3055 rlhs = TMALLOC(Value_t, nrules); 3056 NO_SPACE(rlhs); 3057 3058 rrhs = TMALLOC(Value_t, nrules + 1); 3059 NO_SPACE(rrhs); 3060 3061 rprec = TREALLOC(Value_t, rprec, nrules); 3062 NO_SPACE(rprec); 3063 3064 rassoc = TREALLOC(Assoc_t, rassoc, nrules); 3065 NO_SPACE(rassoc); 3066 3067 ritem[0] = -1; 3068 ritem[1] = goal->index; 3069 ritem[2] = 0; 3070 ritem[3] = -2; 3071 rlhs[0] = 0; 3072 rlhs[1] = 0; 3073 rlhs[2] = start_symbol; 3074 rrhs[0] = 0; 3075 rrhs[1] = 0; 3076 rrhs[2] = 1; 3077 3078 j = 4; 3079 for (i = 3; i < nrules; ++i) 3080 { 3081 #if defined(YYBTYACC) 3082 if (plhs[i]->args > 0) 3083 { 3084 if (plhs[i]->argnames) 3085 { 3086 FREE(plhs[i]->argnames); 3087 plhs[i]->argnames = NULL; 3088 } 3089 if (plhs[i]->argtags) 3090 { 3091 FREE(plhs[i]->argtags); 3092 plhs[i]->argtags = NULL; 3093 } 3094 } 3095 #endif /* defined(YYBTYACC) */ 3096 rlhs[i] = plhs[i]->index; 3097 rrhs[i] = j; 3098 assoc = TOKEN; 3099 prec2 = 0; 3100 while (pitem[j]) 3101 { 3102 ritem[j] = pitem[j]->index; 3103 if (pitem[j]->class == TERM) 3104 { 3105 prec2 = pitem[j]->prec; 3106 assoc = pitem[j]->assoc; 3107 } 3108 ++j; 3109 } 3110 ritem[j] = (Value_t) - i; 3111 ++j; 3112 if (rprec[i] == UNDEFINED) 3113 { 3114 rprec[i] = prec2; 3115 rassoc[i] = assoc; 3116 } 3117 } 3118 rrhs[i] = j; 3119 3120 FREE(plhs); 3121 FREE(pitem); 3122 #if defined(YYBTYACC) 3123 clean_arg_cache(); 3124 #endif 3125 } 3126 3127 static void 3128 print_grammar(void) 3129 { 3130 int i, k; 3131 size_t j, spacing = 0; 3132 FILE *f = verbose_file; 3133 3134 if (!vflag) 3135 return; 3136 3137 k = 1; 3138 for (i = 2; i < nrules; ++i) 3139 { 3140 if (rlhs[i] != rlhs[i - 1]) 3141 { 3142 if (i != 2) 3143 fprintf(f, "\n"); 3144 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]); 3145 spacing = strlen(symbol_name[rlhs[i]]) + 1; 3146 } 3147 else 3148 { 3149 fprintf(f, "%4d ", i - 2); 3150 j = spacing; 3151 while (j-- != 0) 3152 putc(' ', f); 3153 putc('|', f); 3154 } 3155 3156 while (ritem[k] >= 0) 3157 { 3158 fprintf(f, " %s", symbol_name[ritem[k]]); 3159 ++k; 3160 } 3161 ++k; 3162 putc('\n', f); 3163 } 3164 } 3165 3166 #if defined(YYBTYACC) 3167 static void 3168 finalize_destructors(void) 3169 { 3170 int i; 3171 bucket *bp; 3172 char *tag; 3173 3174 for (i = 2; i < nsyms; ++i) 3175 { 3176 tag = symbol_type_tag[i]; 3177 if (symbol_destructor[i] == NULL) 3178 { 3179 if (tag == NULL) 3180 { /* use <> destructor, if there is one */ 3181 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL) 3182 { 3183 symbol_destructor[i] = TMALLOC(char, 3184 strlen(bp->destructor) + 1); 3185 NO_SPACE(symbol_destructor[i]); 3186 strcpy(symbol_destructor[i], bp->destructor); 3187 } 3188 } 3189 else 3190 { /* use type destructor for this tag, if there is one */ 3191 bp = lookup_type_destructor(tag); 3192 if (bp->destructor != NULL) 3193 { 3194 symbol_destructor[i] = TMALLOC(char, 3195 strlen(bp->destructor) + 1); 3196 NO_SPACE(symbol_destructor[i]); 3197 strcpy(symbol_destructor[i], bp->destructor); 3198 } 3199 else 3200 { /* use <*> destructor, if there is one */ 3201 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL) 3202 /* replace "$$" with "(*val).tag" in destructor code */ 3203 symbol_destructor[i] 3204 = process_destructor_XX(bp->destructor, tag); 3205 } 3206 } 3207 } 3208 else 3209 { /* replace "$$" with "(*val)[.tag]" in destructor code */ 3210 symbol_destructor[i] 3211 = process_destructor_XX(symbol_destructor[i], tag); 3212 } 3213 } 3214 /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */ 3215 DO_FREE(symbol_type_tag); /* no longer needed */ 3216 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL) 3217 { 3218 FREE(bp->name); 3219 /* 'bp->tag' is a static value, don't free */ 3220 FREE(bp->destructor); 3221 FREE(bp); 3222 } 3223 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL) 3224 { 3225 FREE(bp->name); 3226 /* 'bp->tag' is a static value, don't free */ 3227 FREE(bp->destructor); 3228 FREE(bp); 3229 } 3230 if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL) 3231 { 3232 bucket *p; 3233 for (; bp; bp = p) 3234 { 3235 p = bp->link; 3236 FREE(bp->name); 3237 /* 'bp->tag' freed by 'free_tags()' */ 3238 FREE(bp->destructor); 3239 FREE(bp); 3240 } 3241 } 3242 } 3243 #endif /* defined(YYBTYACC) */ 3244 3245 void 3246 reader(void) 3247 { 3248 write_section(code_file, banner); 3249 create_symbol_table(); 3250 read_declarations(); 3251 read_grammar(); 3252 free_symbol_table(); 3253 pack_names(); 3254 check_symbols(); 3255 pack_symbols(); 3256 pack_grammar(); 3257 free_symbols(); 3258 print_grammar(); 3259 #if defined(YYBTYACC) 3260 if (destructor) 3261 finalize_destructors(); 3262 #endif 3263 free_tags(); 3264 } 3265 3266 #ifdef NO_LEAKS 3267 static param * 3268 free_declarations(param * list) 3269 { 3270 while (list != 0) 3271 { 3272 param *next = list->next; 3273 free(list->type); 3274 free(list->name); 3275 free(list->type2); 3276 free(list); 3277 list = next; 3278 } 3279 return list; 3280 } 3281 3282 void 3283 reader_leaks(void) 3284 { 3285 lex_param = free_declarations(lex_param); 3286 parse_param = free_declarations(parse_param); 3287 3288 DO_FREE(line); 3289 DO_FREE(rrhs); 3290 DO_FREE(rlhs); 3291 DO_FREE(rprec); 3292 DO_FREE(ritem); 3293 DO_FREE(rassoc); 3294 DO_FREE(cache); 3295 DO_FREE(name_pool); 3296 DO_FREE(symbol_name); 3297 DO_FREE(symbol_prec); 3298 DO_FREE(symbol_assoc); 3299 DO_FREE(symbol_value); 3300 #if defined(YYBTYACC) 3301 DO_FREE(symbol_pval); 3302 DO_FREE(symbol_destructor); 3303 DO_FREE(symbol_type_tag); 3304 #endif 3305 } 3306 #endif 3307