1 /* $Id: reader.c,v 1.91 2022/01/09 18:04:58 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 accommodate 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 #define begin_case(f,n) fprintf(f, "case %d:\n", (int)(n)) 24 25 #define end_case(f) \ 26 fprintf(f, "\n"); \ 27 fprintf_lineno(f, 1, ""); \ 28 fprintf(f, "break;\n") 29 30 static void start_rule(bucket *bp, int s_lineno); 31 #if defined(YYBTYACC) 32 static void copy_initial_action(void); 33 static void copy_destructor(void); 34 static char *process_destructor_XX(char *code, char *tag); 35 #endif 36 37 #define CACHE_SIZE 256 38 static char *cache; 39 static int cinc, cache_size; 40 41 int ntags; 42 static int tagmax, havetags; 43 static char **tag_table; 44 45 static char saw_eof; 46 char unionized; 47 char *cptr, *line; 48 static int linesize; 49 50 static bucket *goal; 51 static Value_t prec; 52 static int gensym; 53 static char last_was_action; 54 #if defined(YYBTYACC) 55 static int trialaction; 56 #endif 57 58 static int maxitems; 59 static bucket **pitem; 60 61 static int maxrules; 62 static bucket **plhs; 63 64 static size_t name_pool_size; 65 static char *name_pool; 66 67 char line_format[] = "#line %d \"%s\"\n"; 68 69 param *lex_param; 70 param *parse_param; 71 72 static const char *code_keys[] = 73 { 74 "", "requires", "provides", "top", "imports", 75 }; 76 77 struct code_lines code_lines[CODE_MAX]; 78 79 #if defined(YYBTYACC) 80 int destructor = 0; /* =1 if at least one %destructor */ 81 82 static bucket *default_destructor[3] = 83 {0, 0, 0}; 84 85 #define UNTYPED_DEFAULT 0 86 #define TYPED_DEFAULT 1 87 #define TYPE_SPECIFIED 2 88 89 static bucket * 90 lookup_type_destructor(char *tag) 91 { 92 const char fmt[] = "%.*s destructor"; 93 char name[1024] = "\0"; 94 bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED]; 95 96 while ((bp = *bpp) != NULL) 97 { 98 if (bp->tag == tag) 99 return (bp); 100 bpp = &bp->link; 101 } 102 103 sprintf(name, fmt, (int)(sizeof(name) - sizeof(fmt)), tag); 104 *bpp = bp = make_bucket(name); 105 bp->tag = tag; 106 107 return (bp); 108 } 109 #endif /* defined(YYBTYACC) */ 110 111 static void 112 cachec(int c) 113 { 114 assert(cinc >= 0); 115 if (cinc >= cache_size) 116 { 117 cache_size += CACHE_SIZE; 118 cache = TREALLOC(char, cache, cache_size); 119 NO_SPACE(cache); 120 } 121 cache[cinc] = (char)c; 122 ++cinc; 123 } 124 125 typedef enum 126 { 127 ldSPC1, 128 ldSPC2, 129 ldNAME, 130 ldSPC3, 131 ldNUM, 132 ldSPC4, 133 ldFILE, 134 ldOK, 135 ldERR 136 } 137 LINE_DIR; 138 139 /* 140 * Expect this pattern: 141 * /^[[:space:]]*#[[:space:]]* 142 * line[[:space:]]+ 143 * [[:digit:]]+ 144 * ([[:space:]]*|[[:space:]]+"[^"]+")/ 145 */ 146 static int 147 line_directive(void) 148 { 149 #define UNLESS(what) if (what) { ld = ldERR; break; } 150 int n; 151 int line_1st = -1; 152 int name_1st = -1; 153 int name_end = -1; 154 LINE_DIR ld = ldSPC1; 155 for (n = 0; (ld <= ldOK) && (line[n] != '\0'); ++n) 156 { 157 int ch = UCH(line[n]); 158 switch (ld) 159 { 160 case ldSPC1: 161 if (isspace(UCH(ch))) 162 { 163 break; 164 } 165 else 166 UNLESS(ch != '#'); 167 ld = ldSPC2; 168 break; 169 case ldSPC2: 170 if (isspace(UCH(ch))) 171 { 172 break; 173 } 174 /* FALLTHRU */ 175 case ldNAME: 176 UNLESS(strncmp(line + n, "line", 4)); 177 n += 4; 178 if (line[n] == '\0') 179 { 180 ld = ldOK; 181 break; 182 } 183 else 184 UNLESS(!isspace(UCH(line[n]))); 185 ld = ldSPC3; 186 break; 187 case ldSPC3: 188 if (isspace(UCH(ch))) 189 { 190 break; 191 } 192 else 193 UNLESS(!isdigit(UCH(ch))); 194 line_1st = n; 195 ld = ldNUM; /* this is needed, but cppcheck says no... */ 196 /* FALLTHRU */ 197 case ldNUM: 198 if (isdigit(UCH(ch))) 199 { 200 break; 201 } 202 else 203 UNLESS(!isspace(UCH(ch))); 204 ld = ldSPC4; 205 break; 206 case ldSPC4: 207 if (isspace(UCH(ch))) 208 { 209 break; 210 } 211 else 212 UNLESS(ch != '"'); 213 UNLESS(line[n + 1] == '"'); 214 ld = ldFILE; 215 name_1st = n; 216 break; 217 case ldFILE: 218 if (ch != '"') 219 { 220 break; 221 } 222 ld = ldOK; 223 name_end = n; 224 /* FALLTHRU */ 225 case ldERR: 226 case ldOK: 227 break; 228 } 229 } 230 231 if (ld == ldOK) 232 { 233 size_t need = (size_t)(name_end - name_1st); 234 if ((long)need > (long)input_file_name_len) 235 { 236 input_file_name_len = ((need + 1) * 3) / 2; 237 input_file_name = TREALLOC(char, input_file_name, input_file_name_len); 238 NO_SPACE(input_file_name); 239 } 240 if ((long)need > 0) 241 { 242 memcpy(input_file_name, line + name_1st + 1, need - 1); 243 input_file_name[need - 1] = '\0'; 244 } 245 else 246 { 247 input_file_name[0] = '\0'; 248 } 249 } 250 251 if (ld >= ldNUM && ld < ldERR) 252 { 253 if (line_1st >= 0) 254 { 255 lineno = (int)strtol(line + line_1st, NULL, 10) - 1; 256 } 257 else 258 { 259 lineno = 0; 260 } 261 } 262 263 return (ld == ldOK); 264 #undef UNLESS 265 } 266 267 static void 268 get_line(void) 269 { 270 FILE *f = input_file; 271 272 do 273 { 274 int c; 275 int i; 276 277 if (saw_eof || (c = getc(f)) == EOF) 278 { 279 if (line) 280 { 281 FREE(line); 282 line = 0; 283 } 284 cptr = 0; 285 saw_eof = 1; 286 return; 287 } 288 289 if (line == NULL || linesize != (LINESIZE + 1)) 290 { 291 if (line) 292 FREE(line); 293 linesize = LINESIZE + 1; 294 line = TMALLOC(char, linesize); 295 NO_SPACE(line); 296 } 297 298 i = 0; 299 ++lineno; 300 for (;;) 301 { 302 line[i++] = (char)c; 303 if (c == '\n') 304 break; 305 if ((i + 3) >= linesize) 306 { 307 linesize += LINESIZE; 308 line = TREALLOC(char, line, linesize); 309 NO_SPACE(line); 310 } 311 c = getc(f); 312 if (c == EOF) 313 { 314 line[i++] = '\n'; 315 saw_eof = 1; 316 break; 317 } 318 } 319 line[i] = '\0'; 320 } 321 while (line_directive()); 322 cptr = line; 323 return; 324 } 325 326 static char * 327 dup_line(void) 328 { 329 char *p, *s, *t; 330 331 if (line == NULL) 332 return (NULL); 333 s = line; 334 while (*s != '\n') 335 ++s; 336 p = TMALLOC(char, s - line + 1); 337 NO_SPACE(p); 338 339 s = line; 340 t = p; 341 while ((*t++ = *s++) != '\n') 342 continue; 343 return (p); 344 } 345 346 static void 347 skip_comment(void) 348 { 349 char *s; 350 struct ainfo a; 351 a.a_lineno = lineno; 352 a.a_line = dup_line(); 353 a.a_cptr = a.a_line + (cptr - line); 354 355 s = cptr + 2; 356 for (;;) 357 { 358 if (*s == '*' && s[1] == '/') 359 { 360 cptr = s + 2; 361 FREE(a.a_line); 362 return; 363 } 364 if (*s == '\n') 365 { 366 get_line(); 367 if (line == NULL) 368 unterminated_comment(&a); 369 s = cptr; 370 } 371 else 372 ++s; 373 } 374 } 375 376 static int 377 next_inline(void) 378 { 379 char *s; 380 381 if (line == NULL) 382 { 383 get_line(); 384 if (line == NULL) 385 return (EOF); 386 } 387 388 s = cptr; 389 for (;;) 390 { 391 switch (*s) 392 { 393 case '/': 394 if (s[1] == '*') 395 { 396 cptr = s; 397 skip_comment(); 398 s = cptr; 399 break; 400 } 401 else if (s[1] == '/') 402 { 403 get_line(); 404 if (line == NULL) 405 return (EOF); 406 s = cptr; 407 break; 408 } 409 /* FALLTHRU */ 410 411 default: 412 cptr = s; 413 return (*s); 414 } 415 } 416 } 417 418 static int 419 nextc(void) 420 { 421 int ch; 422 int finish = 0; 423 424 do 425 { 426 switch (ch = next_inline()) 427 { 428 case '\n': 429 get_line(); 430 break; 431 case ' ': 432 case '\t': 433 case '\f': 434 case '\r': 435 case '\v': 436 case ',': 437 case ';': 438 ++cptr; 439 break; 440 case '\\': 441 ch = '%'; 442 /* FALLTHRU */ 443 default: 444 finish = 1; 445 break; 446 } 447 } 448 while (!finish); 449 450 return ch; 451 } 452 /* *INDENT-OFF* */ 453 static struct keyword 454 { 455 char name[16]; 456 int token; 457 } 458 keywords[] = { 459 { "binary", NONASSOC }, 460 { "code", XCODE }, 461 { "debug", NONPOSIX_DEBUG }, 462 #if defined(YYBTYACC) 463 { "destructor", DESTRUCTOR }, 464 #endif 465 { "error-verbose",ERROR_VERBOSE }, 466 { "expect", EXPECT }, 467 { "expect-rr", EXPECT_RR }, 468 { "ident", IDENT }, 469 #if defined(YYBTYACC) 470 { "initial-action", INITIAL_ACTION }, 471 #endif 472 { "left", LEFT }, 473 { "lex-param", LEX_PARAM }, 474 #if defined(YYBTYACC) 475 { "locations", LOCATIONS }, 476 #endif 477 { "nonassoc", NONASSOC }, 478 { "parse-param", PARSE_PARAM }, 479 { "pure-parser", PURE_PARSER }, 480 { "right", RIGHT }, 481 { "start", START }, 482 { "term", TOKEN }, 483 { "token", TOKEN }, 484 { "token-table", TOKEN_TABLE }, 485 { "type", TYPE }, 486 { "union", UNION }, 487 { "yacc", POSIX_YACC }, 488 }; 489 /* *INDENT-ON* */ 490 491 static int 492 compare_keys(const void *a, const void *b) 493 { 494 const struct keyword *p = (const struct keyword *)a; 495 const struct keyword *q = (const struct keyword *)b; 496 return strcmp(p->name, q->name); 497 } 498 499 static int 500 keyword(void) 501 { 502 int c; 503 char *t_cptr = cptr; 504 505 c = *++cptr; 506 if (isalpha(UCH(c))) 507 { 508 struct keyword *key; 509 510 cinc = 0; 511 for (;;) 512 { 513 if (isalpha(UCH(c))) 514 { 515 if (isupper(UCH(c))) 516 c = tolower(c); 517 cachec(c); 518 } 519 else if (isdigit(UCH(c)) 520 || c == '-' 521 || c == '.' 522 || c == '$') 523 { 524 cachec(c); 525 } 526 else if (c == '_') 527 { 528 /* treat keywords spelled with '_' as if it were '-' */ 529 cachec('-'); 530 } 531 else 532 { 533 break; 534 } 535 c = *++cptr; 536 } 537 cachec(NUL); 538 539 if ((key = bsearch(cache, keywords, 540 sizeof(keywords) / sizeof(*key), 541 sizeof(*key), compare_keys))) 542 return key->token; 543 } 544 else 545 { 546 ++cptr; 547 if (c == L_CURL) 548 return (TEXT); 549 if (c == '%' || c == '\\') 550 return (MARK); 551 if (c == '<') 552 return (LEFT); 553 if (c == '>') 554 return (RIGHT); 555 if (c == '0') 556 return (TOKEN); 557 if (c == '2') 558 return (NONASSOC); 559 } 560 syntax_error(lineno, line, t_cptr); 561 /*NOTREACHED */ 562 } 563 564 static void 565 copy_ident(void) 566 { 567 int c; 568 FILE *f = output_file; 569 570 c = nextc(); 571 if (c == EOF) 572 unexpected_EOF(); 573 if (c != '"') 574 syntax_error(lineno, line, cptr); 575 ++outline; 576 fprintf(f, "#ident \""); 577 for (;;) 578 { 579 c = *++cptr; 580 if (c == '\n') 581 { 582 fprintf(f, "\"\n"); 583 return; 584 } 585 putc(c, f); 586 if (c == '"') 587 { 588 putc('\n', f); 589 ++cptr; 590 return; 591 } 592 } 593 } 594 595 static char * 596 copy_string(int quote) 597 { 598 struct mstring *temp = msnew(); 599 struct ainfo a; 600 a.a_lineno = lineno; 601 a.a_line = dup_line(); 602 a.a_cptr = a.a_line + (cptr - line - 1); 603 604 for (;;) 605 { 606 int c = *cptr++; 607 608 mputc(temp, c); 609 if (c == quote) 610 { 611 FREE(a.a_line); 612 return msdone(temp); 613 } 614 if (c == '\n') 615 unterminated_string(&a); 616 if (c == '\\') 617 { 618 c = *cptr++; 619 mputc(temp, c); 620 if (c == '\n') 621 { 622 get_line(); 623 if (line == NULL) 624 unterminated_string(&a); 625 } 626 } 627 } 628 } 629 630 static char * 631 copy_comment(void) 632 { 633 struct mstring *temp = msnew(); 634 int c; 635 636 c = *cptr; 637 if (c == '/') 638 { 639 mputc(temp, '*'); 640 while ((c = *++cptr) != '\n') 641 { 642 mputc(temp, c); 643 if (c == '*' && cptr[1] == '/') 644 mputc(temp, ' '); 645 } 646 mputc(temp, '*'); 647 mputc(temp, '/'); 648 } 649 else if (c == '*') 650 { 651 struct ainfo a; 652 a.a_lineno = lineno; 653 a.a_line = dup_line(); 654 a.a_cptr = a.a_line + (cptr - line - 1); 655 656 mputc(temp, c); 657 ++cptr; 658 for (;;) 659 { 660 c = *cptr++; 661 mputc(temp, c); 662 if (c == '*' && *cptr == '/') 663 { 664 mputc(temp, '/'); 665 ++cptr; 666 FREE(a.a_line); 667 return msdone(temp); 668 } 669 if (c == '\n') 670 { 671 get_line(); 672 if (line == NULL) 673 unterminated_comment(&a); 674 } 675 } 676 } 677 return msdone(temp); 678 } 679 680 static int 681 check_key(int pos) 682 { 683 const char *key = code_keys[pos]; 684 while (*cptr && *key) 685 if (*key++ != *cptr++) 686 return 0; 687 if (*key || (!isspace(UCH(*cptr)) && *cptr != L_CURL)) 688 return 0; 689 cptr--; 690 return 1; 691 } 692 693 static void 694 copy_code(void) 695 { 696 int c; 697 int curl; 698 int cline; 699 int on_line = 0; 700 int pos = CODE_HEADER; 701 struct mstring *code_mstr; 702 703 /* read %code <keyword> { */ 704 for (;;) 705 { 706 c = *++cptr; 707 if (c == EOF) 708 unexpected_EOF(); 709 if (isspace(UCH(c))) 710 continue; 711 712 if (c == L_CURL) 713 break; 714 715 if (pos == CODE_HEADER) 716 { 717 switch (UCH(c)) 718 { 719 case 'r': 720 pos = CODE_REQUIRES; 721 break; 722 case 'p': 723 pos = CODE_PROVIDES; 724 break; 725 case 't': 726 pos = CODE_TOP; 727 break; 728 case 'i': 729 pos = CODE_IMPORTS; 730 break; 731 default: 732 break; 733 } 734 735 if (pos == -1 || !check_key(pos)) 736 { 737 syntax_error(lineno, line, cptr); 738 /*NOTREACHED */ 739 } 740 } 741 } 742 743 cptr++; /* skip initial curl */ 744 while (*cptr && isspace(UCH(*cptr))) /* skip space */ 745 cptr++; 746 curl = 1; /* nesting count */ 747 748 /* gather text */ 749 code_lines[pos].name = code_keys[pos]; 750 if ((cline = (int)code_lines[pos].num) != 0) 751 { 752 code_mstr = msrenew(code_lines[pos].lines); 753 } 754 else 755 { 756 code_mstr = msnew(); 757 } 758 cline++; 759 if (!lflag) 760 msprintf(code_mstr, line_format, lineno, input_file_name); 761 for (;;) 762 { 763 c = *cptr++; 764 switch (c) 765 { 766 case '\0': 767 get_line(); 768 if (line == NULL) 769 { 770 unexpected_EOF(); 771 /*NOTREACHED */ 772 } 773 continue; 774 case '\n': 775 cline++; 776 on_line = 0; 777 break; 778 case L_CURL: 779 curl++; 780 break; 781 case R_CURL: 782 if (--curl == 0) 783 { 784 if (on_line > 1) 785 { 786 mputc(code_mstr, '\n'); 787 cline++; 788 } 789 code_lines[pos].lines = msdone(code_mstr); 790 code_lines[pos].num = (size_t)cline; 791 return; 792 } 793 break; 794 default: 795 break; 796 } 797 mputc(code_mstr, c); 798 on_line++; 799 } 800 } 801 802 static void 803 copy_text(void) 804 { 805 int c; 806 FILE *f = text_file; 807 int need_newline = 0; 808 struct ainfo a; 809 a.a_lineno = lineno; 810 a.a_line = dup_line(); 811 a.a_cptr = a.a_line + (cptr - line - 2); 812 813 if (*cptr == '\n') 814 { 815 get_line(); 816 if (line == NULL) 817 unterminated_text(&a); 818 } 819 fprintf_lineno(f, lineno, input_file_name); 820 821 loop: 822 c = *cptr++; 823 switch (c) 824 { 825 case '\n': 826 putc('\n', f); 827 need_newline = 0; 828 get_line(); 829 if (line) 830 goto loop; 831 unterminated_text(&a); 832 833 case '\'': 834 case '"': 835 putc(c, f); 836 { 837 char *s = copy_string(c); 838 fputs(s, f); 839 free(s); 840 } 841 need_newline = 1; 842 goto loop; 843 844 case '/': 845 putc(c, f); 846 { 847 char *s = copy_comment(); 848 fputs(s, f); 849 free(s); 850 } 851 need_newline = 1; 852 goto loop; 853 854 case '%': 855 case '\\': 856 if (*cptr == R_CURL) 857 { 858 if (need_newline) 859 putc('\n', f); 860 ++cptr; 861 FREE(a.a_line); 862 return; 863 } 864 /* FALLTHRU */ 865 866 default: 867 putc(c, f); 868 need_newline = 1; 869 goto loop; 870 } 871 } 872 873 static void 874 puts_both(const char *s) 875 { 876 fputs(s, text_file); 877 if (dflag) 878 fputs(s, union_file); 879 } 880 881 static void 882 putc_both(int c) 883 { 884 putc(c, text_file); 885 if (dflag) 886 putc(c, union_file); 887 } 888 889 static void 890 copy_union(void) 891 { 892 int c; 893 int depth; 894 struct ainfo a; 895 a.a_lineno = lineno; 896 a.a_line = dup_line(); 897 a.a_cptr = a.a_line + (cptr - line - 6); 898 899 if (unionized) 900 over_unionized(cptr - 6); 901 unionized = 1; 902 903 puts_both("#ifdef YYSTYPE\n"); 904 puts_both("#undef YYSTYPE_IS_DECLARED\n"); 905 puts_both("#define YYSTYPE_IS_DECLARED 1\n"); 906 puts_both("#endif\n"); 907 puts_both("#ifndef YYSTYPE_IS_DECLARED\n"); 908 puts_both("#define YYSTYPE_IS_DECLARED 1\n"); 909 910 fprintf_lineno(text_file, lineno, input_file_name); 911 puts_both("typedef union"); 912 913 depth = 0; 914 loop: 915 c = *cptr++; 916 putc_both(c); 917 switch (c) 918 { 919 case '\n': 920 get_line(); 921 if (line == NULL) 922 unterminated_union(&a); 923 goto loop; 924 925 case L_CURL: 926 ++depth; 927 goto loop; 928 929 case R_CURL: 930 if (--depth == 0) 931 { 932 puts_both(" YYSTYPE;\n"); 933 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n"); 934 FREE(a.a_line); 935 return; 936 } 937 goto loop; 938 939 case '\'': 940 case '"': 941 { 942 char *s = copy_string(c); 943 puts_both(s); 944 free(s); 945 } 946 goto loop; 947 948 case '/': 949 { 950 char *s = copy_comment(); 951 puts_both(s); 952 free(s); 953 } 954 goto loop; 955 956 default: 957 goto loop; 958 } 959 } 960 961 static char * 962 after_blanks(char *s) 963 { 964 while (*s != '\0' && isspace(UCH(*s))) 965 ++s; 966 return s; 967 } 968 969 /* 970 * Trim leading/trailing blanks, and collapse multiple embedded blanks to a 971 * single space. Return index to last character in the buffer. 972 */ 973 static int 974 trim_blanks(char *buffer) 975 { 976 if (*buffer != '\0') 977 { 978 char *d = buffer; 979 char *s = after_blanks(d); 980 981 while ((*d++ = *s++) != '\0') 982 { 983 ; 984 } 985 986 --d; 987 while ((--d != buffer) && isspace(UCH(*d))) 988 *d = '\0'; 989 990 for (s = d = buffer; (*d++ = *s++) != '\0';) 991 { 992 if (isspace(UCH(*s))) 993 { 994 *s = ' '; 995 while (isspace(UCH(*s))) 996 { 997 *s++ = ' '; 998 } 999 --s; 1000 } 1001 } 1002 } 1003 1004 return (int)strlen(buffer) - 1; 1005 } 1006 1007 /* 1008 * Scan forward in the current line-buffer looking for a right-curly bracket. 1009 * 1010 * Parameters begin with a left-curly bracket, and continue until there are no 1011 * more interesting characters after the last right-curly bracket on the 1012 * current line. Bison documents parameters as separated like this: 1013 * {type param1} {type2 param2} 1014 * but also accepts commas (although some versions of bison mishandle this) 1015 * {type param1, type2 param2} 1016 */ 1017 static int 1018 more_curly(void) 1019 { 1020 char *save = cptr; 1021 int result = 0; 1022 int finish = 0; 1023 do 1024 { 1025 switch (next_inline()) 1026 { 1027 case 0: 1028 case '\n': 1029 finish = 1; 1030 break; 1031 case R_CURL: 1032 finish = 1; 1033 result = 1; 1034 break; 1035 } 1036 ++cptr; 1037 } 1038 while (!finish); 1039 cptr = save; 1040 return result; 1041 } 1042 1043 static void 1044 save_param(int k, char *buffer, int name, int type2) 1045 { 1046 param *head, *p; 1047 1048 p = TMALLOC(param, 1); 1049 NO_SPACE(p); 1050 1051 p->type2 = strdup(buffer + type2); 1052 NO_SPACE(p->type2); 1053 buffer[type2] = '\0'; 1054 (void)trim_blanks(p->type2); 1055 1056 p->name = strdup(buffer + name); 1057 NO_SPACE(p->name); 1058 buffer[name] = '\0'; 1059 (void)trim_blanks(p->name); 1060 1061 p->type = strdup(buffer); 1062 NO_SPACE(p->type); 1063 (void)trim_blanks(p->type); 1064 1065 if (k == LEX_PARAM) 1066 head = lex_param; 1067 else 1068 head = parse_param; 1069 1070 if (head != NULL) 1071 { 1072 while (head->next) 1073 head = head->next; 1074 head->next = p; 1075 } 1076 else 1077 { 1078 if (k == LEX_PARAM) 1079 lex_param = p; 1080 else 1081 parse_param = p; 1082 } 1083 p->next = NULL; 1084 } 1085 1086 /* 1087 * Keep a linked list of parameters. This may be multi-line, if the trailing 1088 * right-curly bracket is absent. 1089 */ 1090 static void 1091 copy_param(int k) 1092 { 1093 int c; 1094 int name, type2; 1095 int curly = 0; 1096 char *buf = 0; 1097 int i = -1; 1098 size_t buf_size = 0; 1099 int st_lineno = lineno; 1100 char *comma; 1101 1102 do 1103 { 1104 int state = curly; 1105 c = next_inline(); 1106 switch (c) 1107 { 1108 case EOF: 1109 unexpected_EOF(); 1110 break; 1111 case L_CURL: 1112 if (curly == 1) 1113 { 1114 goto oops; 1115 } 1116 curly = 1; 1117 st_lineno = lineno; 1118 break; 1119 case R_CURL: 1120 if (curly != 1) 1121 { 1122 goto oops; 1123 } 1124 curly = 2; 1125 break; 1126 case '\n': 1127 if (curly == 0) 1128 { 1129 goto oops; 1130 } 1131 break; 1132 case '%': 1133 if ((curly == 1) && (cptr == line)) 1134 { 1135 lineno = st_lineno; 1136 missing_brace(); 1137 } 1138 /* FALLTHRU */ 1139 case '"': 1140 case '\'': 1141 goto oops; 1142 default: 1143 if (curly == 0 && !isspace(UCH(c))) 1144 { 1145 goto oops; 1146 } 1147 break; 1148 } 1149 if (buf == 0) 1150 { 1151 buf_size = (size_t)linesize; 1152 buf = TMALLOC(char, buf_size); 1153 NO_SPACE(buf); 1154 } 1155 else if (c == '\n') 1156 { 1157 char *tmp; 1158 1159 get_line(); 1160 if (line == NULL) 1161 unexpected_EOF(); 1162 --cptr; 1163 buf_size += (size_t)linesize; 1164 tmp = TREALLOC(char, buf, buf_size); 1165 NO_SPACE(tmp); 1166 buf = tmp; 1167 } 1168 if (curly) 1169 { 1170 if ((state == 2) && (c == L_CURL)) 1171 { 1172 buf[++i] = ','; 1173 } 1174 else if ((state == 2) && isspace(UCH(c))) 1175 { 1176 ; 1177 } 1178 else if ((c != L_CURL) && (c != R_CURL)) 1179 { 1180 buf[++i] = (char)c; 1181 } 1182 } 1183 cptr++; 1184 } 1185 while (curly < 2 || more_curly()); 1186 1187 if (i == 0) 1188 { 1189 if (curly == 1) 1190 { 1191 lineno = st_lineno; 1192 missing_brace(); 1193 } 1194 goto oops; 1195 } 1196 1197 buf[++i] = '\0'; 1198 (void)trim_blanks(buf); 1199 1200 comma = buf - 1; 1201 do 1202 { 1203 char *parms = (comma + 1); 1204 comma = strchr(parms, ','); 1205 if (comma != 0) 1206 *comma = '\0'; 1207 1208 (void)trim_blanks(parms); 1209 i = (int)strlen(parms) - 1; 1210 if (i < 0) 1211 { 1212 goto oops; 1213 } 1214 1215 if (parms[i] == ']') 1216 { 1217 int level = 1; 1218 while (i >= 0) 1219 { 1220 char ch = parms[i--]; 1221 if (ch == ']') 1222 { 1223 ++level; 1224 } 1225 else if (ch == '[') 1226 { 1227 if (--level <= 1) 1228 { 1229 ++i; 1230 break; 1231 } 1232 } 1233 } 1234 if (i <= 0) 1235 unexpected_EOF(); 1236 type2 = i--; 1237 } 1238 else 1239 { 1240 type2 = i + 1; 1241 } 1242 1243 while (i > 0 && (isalnum(UCH(parms[i])) || UCH(parms[i]) == '_')) 1244 i--; 1245 1246 if (!isspace(UCH(parms[i])) && parms[i] != '*') 1247 goto oops; 1248 1249 name = i + 1; 1250 1251 save_param(k, parms, name, type2); 1252 } 1253 while (comma != 0); 1254 FREE(buf); 1255 return; 1256 1257 oops: 1258 FREE(buf); 1259 syntax_error(lineno, line, cptr); 1260 } 1261 1262 static int 1263 hexval(int c) 1264 { 1265 if (c >= '0' && c <= '9') 1266 return (c - '0'); 1267 if (c >= 'A' && c <= 'F') 1268 return (c - 'A' + 10); 1269 if (c >= 'a' && c <= 'f') 1270 return (c - 'a' + 10); 1271 return (-1); 1272 } 1273 1274 static bucket * 1275 get_literal(void) 1276 { 1277 int c, quote; 1278 int i; 1279 int n; 1280 char *s; 1281 bucket *bp; 1282 struct ainfo a; 1283 a.a_lineno = lineno; 1284 a.a_line = dup_line(); 1285 a.a_cptr = a.a_line + (cptr - line); 1286 1287 quote = *cptr++; 1288 cinc = 0; 1289 for (;;) 1290 { 1291 c = *cptr++; 1292 if (c == quote) 1293 break; 1294 if (c == '\n') 1295 unterminated_string(&a); 1296 if (c == '\\') 1297 { 1298 char *c_cptr = cptr - 1; 1299 1300 c = *cptr++; 1301 switch (c) 1302 { 1303 case '\n': 1304 get_line(); 1305 if (line == NULL) 1306 unterminated_string(&a); 1307 continue; 1308 1309 case '0': 1310 case '1': 1311 case '2': 1312 case '3': 1313 case '4': 1314 case '5': 1315 case '6': 1316 case '7': 1317 n = c - '0'; 1318 c = *cptr; 1319 if (IS_OCTAL(c)) 1320 { 1321 n = (n << 3) + (c - '0'); 1322 c = *++cptr; 1323 if (IS_OCTAL(c)) 1324 { 1325 n = (n << 3) + (c - '0'); 1326 ++cptr; 1327 } 1328 } 1329 if (n > MAXCHAR) 1330 illegal_character(c_cptr); 1331 c = n; 1332 break; 1333 1334 case 'x': 1335 c = *cptr++; 1336 n = hexval(c); 1337 if (n < 0 || n >= 16) 1338 illegal_character(c_cptr); 1339 for (;;) 1340 { 1341 c = *cptr; 1342 i = hexval(c); 1343 if (i < 0 || i >= 16) 1344 break; 1345 ++cptr; 1346 n = (n << 4) + i; 1347 if (n > MAXCHAR) 1348 illegal_character(c_cptr); 1349 } 1350 c = n; 1351 break; 1352 1353 case 'a': 1354 c = 7; 1355 break; 1356 case 'b': 1357 c = '\b'; 1358 break; 1359 case 'f': 1360 c = '\f'; 1361 break; 1362 case 'n': 1363 c = '\n'; 1364 break; 1365 case 'r': 1366 c = '\r'; 1367 break; 1368 case 't': 1369 c = '\t'; 1370 break; 1371 case 'v': 1372 c = '\v'; 1373 break; 1374 } 1375 } 1376 cachec(c); 1377 } 1378 FREE(a.a_line); 1379 1380 n = cinc; 1381 s = TMALLOC(char, n); 1382 NO_SPACE(s); 1383 1384 for (i = 0; i < n; ++i) 1385 s[i] = cache[i]; 1386 1387 cinc = 0; 1388 if (n == 1) 1389 cachec('\''); 1390 else 1391 cachec('"'); 1392 1393 for (i = 0; i < n; ++i) 1394 { 1395 c = UCH(s[i]); 1396 if (c == '\\' || c == cache[0]) 1397 { 1398 cachec('\\'); 1399 cachec(c); 1400 } 1401 else if (isprint(UCH(c))) 1402 cachec(c); 1403 else 1404 { 1405 cachec('\\'); 1406 switch (c) 1407 { 1408 case 7: 1409 cachec('a'); 1410 break; 1411 case '\b': 1412 cachec('b'); 1413 break; 1414 case '\f': 1415 cachec('f'); 1416 break; 1417 case '\n': 1418 cachec('n'); 1419 break; 1420 case '\r': 1421 cachec('r'); 1422 break; 1423 case '\t': 1424 cachec('t'); 1425 break; 1426 case '\v': 1427 cachec('v'); 1428 break; 1429 default: 1430 cachec(((c >> 6) & 7) + '0'); 1431 cachec(((c >> 3) & 7) + '0'); 1432 cachec((c & 7) + '0'); 1433 break; 1434 } 1435 } 1436 } 1437 1438 if (n == 1) 1439 cachec('\''); 1440 else 1441 cachec('"'); 1442 1443 cachec(NUL); 1444 bp = lookup(cache); 1445 bp->class = TERM; 1446 if (n == 1 && bp->value == UNDEFINED) 1447 bp->value = UCH(*s); 1448 FREE(s); 1449 1450 return (bp); 1451 } 1452 1453 static int 1454 is_reserved(char *name) 1455 { 1456 if (strcmp(name, ".") == 0 || 1457 strcmp(name, "$accept") == 0 || 1458 strcmp(name, "$end") == 0) 1459 return (1); 1460 1461 if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2]))) 1462 { 1463 char *s = name + 3; 1464 1465 while (isdigit(UCH(*s))) 1466 ++s; 1467 if (*s == NUL) 1468 return (1); 1469 } 1470 1471 return (0); 1472 } 1473 1474 static bucket * 1475 get_name(void) 1476 { 1477 int c; 1478 1479 cinc = 0; 1480 for (c = *cptr; IS_IDENT(c); c = *++cptr) 1481 cachec(c); 1482 cachec(NUL); 1483 1484 if (is_reserved(cache)) 1485 used_reserved(cache); 1486 1487 return (lookup(cache)); 1488 } 1489 1490 static Value_t 1491 get_number(void) 1492 { 1493 int c; 1494 long n; 1495 char *base = cptr; 1496 1497 n = 0; 1498 for (c = *cptr; isdigit(UCH(c)); c = *++cptr) 1499 { 1500 n = (10 * n + (c - '0')); 1501 if (n > MAXYYINT) 1502 { 1503 syntax_error(lineno, line, base); 1504 /*NOTREACHED */ 1505 } 1506 } 1507 1508 return (Value_t)(n); 1509 } 1510 1511 static char * 1512 cache_tag(char *tag, size_t len) 1513 { 1514 int i; 1515 char *s; 1516 1517 for (i = 0; i < ntags; ++i) 1518 { 1519 if (strncmp(tag, tag_table[i], len) == 0 && 1520 tag_table[i][len] == NUL) 1521 return (tag_table[i]); 1522 } 1523 1524 if (ntags >= tagmax) 1525 { 1526 tagmax += 16; 1527 tag_table = 1528 (tag_table 1529 ? TREALLOC(char *, tag_table, tagmax) 1530 : TMALLOC(char *, tagmax)); 1531 NO_SPACE(tag_table); 1532 } 1533 1534 s = TMALLOC(char, len + 1); 1535 NO_SPACE(s); 1536 1537 strncpy(s, tag, len); 1538 s[len] = 0; 1539 tag_table[ntags++] = s; 1540 return s; 1541 } 1542 1543 static char * 1544 get_tag(void) 1545 { 1546 int c; 1547 int t_lineno = lineno; 1548 char *t_line = dup_line(); 1549 char *t_cptr = t_line + (cptr - line); 1550 1551 ++cptr; 1552 c = nextc(); 1553 if (c == EOF) 1554 unexpected_EOF(); 1555 if (!IS_NAME1(c)) 1556 illegal_tag(t_lineno, t_line, t_cptr); 1557 1558 cinc = 0; 1559 do 1560 { 1561 cachec(c); 1562 c = *++cptr; 1563 } 1564 while (IS_IDENT(c)); 1565 cachec(NUL); 1566 1567 c = nextc(); 1568 if (c == EOF) 1569 unexpected_EOF(); 1570 if (c != '>') 1571 illegal_tag(t_lineno, t_line, t_cptr); 1572 ++cptr; 1573 1574 FREE(t_line); 1575 havetags = 1; 1576 return cache_tag(cache, (size_t)cinc); 1577 } 1578 1579 #if defined(YYBTYACC) 1580 static char * 1581 scan_id(void) 1582 { 1583 char *b = cptr; 1584 1585 while (IS_NAME2(UCH(*cptr))) 1586 cptr++; 1587 return cache_tag(b, (size_t)(cptr - b)); 1588 } 1589 #endif 1590 1591 static void 1592 declare_tokens(int assoc) 1593 { 1594 int c; 1595 bucket *bp; 1596 Value_t value; 1597 char *tag = 0; 1598 1599 if (assoc != TOKEN) 1600 ++prec; 1601 1602 c = nextc(); 1603 if (c == EOF) 1604 unexpected_EOF(); 1605 if (c == '<') 1606 { 1607 tag = get_tag(); 1608 c = nextc(); 1609 if (c == EOF) 1610 unexpected_EOF(); 1611 } 1612 1613 for (;;) 1614 { 1615 if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$') 1616 bp = get_name(); 1617 else if (c == '\'' || c == '"') 1618 bp = get_literal(); 1619 else 1620 return; 1621 1622 if (bp == goal) 1623 tokenized_start(bp->name); 1624 bp->class = TERM; 1625 1626 if (tag) 1627 { 1628 if (bp->tag && tag != bp->tag) 1629 retyped_warning(bp->name); 1630 bp->tag = tag; 1631 } 1632 1633 if (assoc != TOKEN) 1634 { 1635 if (bp->prec && prec != bp->prec) 1636 reprec_warning(bp->name); 1637 bp->assoc = (Assoc_t)assoc; 1638 bp->prec = prec; 1639 } 1640 1641 c = nextc(); 1642 if (c == EOF) 1643 unexpected_EOF(); 1644 1645 if (isdigit(UCH(c))) 1646 { 1647 value = get_number(); 1648 if (bp->value != UNDEFINED && value != bp->value) 1649 revalued_warning(bp->name); 1650 bp->value = value; 1651 c = nextc(); 1652 if (c == EOF) 1653 unexpected_EOF(); 1654 } 1655 } 1656 } 1657 1658 /* 1659 * %expect requires special handling 1660 * as it really isn't part of the yacc 1661 * grammar only a flag for yacc proper. 1662 */ 1663 static void 1664 declare_expect(int assoc) 1665 { 1666 int c; 1667 1668 if (assoc != EXPECT && assoc != EXPECT_RR) 1669 ++prec; 1670 1671 /* 1672 * Stay away from nextc - doesn't 1673 * detect EOL and will read to EOF. 1674 */ 1675 c = *++cptr; 1676 if (c == EOF) 1677 unexpected_EOF(); 1678 1679 for (;;) 1680 { 1681 if (isdigit(UCH(c))) 1682 { 1683 if (assoc == EXPECT) 1684 SRexpect = get_number(); 1685 else 1686 RRexpect = get_number(); 1687 break; 1688 } 1689 /* 1690 * Looking for number before EOL. 1691 * Spaces, tabs, and numbers are ok, 1692 * words, punc., etc. are syntax errors. 1693 */ 1694 else if (c == '\n' || isalpha(UCH(c)) || !isspace(UCH(c))) 1695 { 1696 syntax_error(lineno, line, cptr); 1697 } 1698 else 1699 { 1700 c = *++cptr; 1701 if (c == EOF) 1702 unexpected_EOF(); 1703 } 1704 } 1705 } 1706 1707 #if defined(YYBTYACC) 1708 static void 1709 declare_argtypes(bucket *bp) 1710 { 1711 char *tags[MAXARGS]; 1712 int args = 0; 1713 1714 if (bp->args >= 0) 1715 retyped_warning(bp->name); 1716 cptr++; /* skip open paren */ 1717 for (;;) 1718 { 1719 int c = nextc(); 1720 if (c == EOF) 1721 unexpected_EOF(); 1722 if (c != '<') 1723 syntax_error(lineno, line, cptr); 1724 tags[args++] = get_tag(); 1725 c = nextc(); 1726 if (c == R_PAREN) 1727 break; 1728 if (c == EOF) 1729 unexpected_EOF(); 1730 } 1731 cptr++; /* skip close paren */ 1732 bp->args = args; 1733 bp->argnames = TMALLOC(char *, args); 1734 NO_SPACE(bp->argnames); 1735 bp->argtags = CALLOC(sizeof(char *), args + 1); 1736 NO_SPACE(bp->argtags); 1737 while (--args >= 0) 1738 { 1739 bp->argtags[args] = tags[args]; 1740 bp->argnames[args] = NULL; 1741 } 1742 } 1743 #endif 1744 1745 static void 1746 declare_types(void) 1747 { 1748 int c; 1749 bucket *bp = NULL; 1750 char *tag = NULL; 1751 1752 c = nextc(); 1753 if (c == EOF) 1754 unexpected_EOF(); 1755 if (c == '<') 1756 tag = get_tag(); 1757 1758 for (;;) 1759 { 1760 c = nextc(); 1761 if (c == EOF) 1762 unexpected_EOF(); 1763 if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$') 1764 { 1765 bp = get_name(); 1766 #if defined(YYBTYACC) 1767 if (nextc() == L_PAREN) 1768 declare_argtypes(bp); 1769 else 1770 bp->args = 0; 1771 #endif 1772 } 1773 else if (c == '\'' || c == '"') 1774 { 1775 bp = get_literal(); 1776 #if defined(YYBTYACC) 1777 bp->args = 0; 1778 #endif 1779 } 1780 else 1781 return; 1782 1783 if (tag) 1784 { 1785 if (bp->tag && tag != bp->tag) 1786 retyped_warning(bp->name); 1787 bp->tag = tag; 1788 } 1789 } 1790 } 1791 1792 static void 1793 declare_start(void) 1794 { 1795 int c; 1796 bucket *bp; 1797 1798 c = nextc(); 1799 if (c == EOF) 1800 unexpected_EOF(); 1801 if (!isalpha(UCH(c)) && c != '_' && c != '.' && c != '$') 1802 syntax_error(lineno, line, cptr); 1803 bp = get_name(); 1804 if (bp->class == TERM) 1805 terminal_start(bp->name); 1806 if (goal && goal != bp) 1807 restarted_warning(); 1808 goal = bp; 1809 } 1810 1811 static void 1812 read_declarations(void) 1813 { 1814 cache_size = CACHE_SIZE; 1815 cache = TMALLOC(char, cache_size); 1816 NO_SPACE(cache); 1817 1818 for (;;) 1819 { 1820 int k; 1821 int c = nextc(); 1822 1823 if (c == EOF) 1824 unexpected_EOF(); 1825 if (c != '%') 1826 syntax_error(lineno, line, cptr); 1827 switch (k = keyword()) 1828 { 1829 case MARK: 1830 return; 1831 1832 case IDENT: 1833 copy_ident(); 1834 break; 1835 1836 case XCODE: 1837 copy_code(); 1838 break; 1839 1840 case TEXT: 1841 copy_text(); 1842 break; 1843 1844 case UNION: 1845 copy_union(); 1846 break; 1847 1848 case TOKEN: 1849 case LEFT: 1850 case RIGHT: 1851 case NONASSOC: 1852 declare_tokens(k); 1853 break; 1854 1855 case EXPECT: 1856 case EXPECT_RR: 1857 declare_expect(k); 1858 break; 1859 1860 case TYPE: 1861 declare_types(); 1862 break; 1863 1864 case START: 1865 declare_start(); 1866 break; 1867 1868 case PURE_PARSER: 1869 pure_parser = 1; 1870 break; 1871 1872 case PARSE_PARAM: 1873 case LEX_PARAM: 1874 copy_param(k); 1875 break; 1876 1877 case TOKEN_TABLE: 1878 token_table = 1; 1879 break; 1880 1881 case ERROR_VERBOSE: 1882 error_verbose = 1; 1883 break; 1884 1885 #if defined(YYBTYACC) 1886 case LOCATIONS: 1887 locations = 1; 1888 break; 1889 1890 case DESTRUCTOR: 1891 destructor = 1; 1892 copy_destructor(); 1893 break; 1894 case INITIAL_ACTION: 1895 copy_initial_action(); 1896 break; 1897 #endif 1898 1899 case NONPOSIX_DEBUG: 1900 tflag = 1; 1901 break; 1902 1903 case POSIX_YACC: 1904 /* noop for bison compatibility. byacc is already designed to be posix 1905 * yacc compatible. */ 1906 break; 1907 } 1908 } 1909 } 1910 1911 static void 1912 initialize_grammar(void) 1913 { 1914 nitems = 4; 1915 maxitems = 300; 1916 1917 pitem = TMALLOC(bucket *, maxitems); 1918 NO_SPACE(pitem); 1919 1920 pitem[0] = 0; 1921 pitem[1] = 0; 1922 pitem[2] = 0; 1923 pitem[3] = 0; 1924 1925 nrules = 3; 1926 maxrules = 100; 1927 1928 plhs = TMALLOC(bucket *, maxrules); 1929 NO_SPACE(plhs); 1930 1931 plhs[0] = 0; 1932 plhs[1] = 0; 1933 plhs[2] = 0; 1934 1935 rprec = TMALLOC(Value_t, maxrules); 1936 NO_SPACE(rprec); 1937 1938 rprec[0] = 0; 1939 rprec[1] = 0; 1940 rprec[2] = 0; 1941 1942 rassoc = TMALLOC(Assoc_t, maxrules); 1943 NO_SPACE(rassoc); 1944 1945 rassoc[0] = TOKEN; 1946 rassoc[1] = TOKEN; 1947 rassoc[2] = TOKEN; 1948 } 1949 1950 static void 1951 expand_items(void) 1952 { 1953 maxitems += 300; 1954 pitem = TREALLOC(bucket *, pitem, maxitems); 1955 NO_SPACE(pitem); 1956 } 1957 1958 static void 1959 expand_rules(void) 1960 { 1961 maxrules += 100; 1962 1963 plhs = TREALLOC(bucket *, plhs, maxrules); 1964 NO_SPACE(plhs); 1965 1966 rprec = TREALLOC(Value_t, rprec, maxrules); 1967 NO_SPACE(rprec); 1968 1969 rassoc = TREALLOC(Assoc_t, rassoc, maxrules); 1970 NO_SPACE(rassoc); 1971 } 1972 1973 /* set immediately prior to where copy_args() could be called, and incremented by 1974 the various routines that will rescan the argument list as appropriate */ 1975 static int rescan_lineno; 1976 #if defined(YYBTYACC) 1977 1978 static char * 1979 copy_args(int *alen) 1980 { 1981 struct mstring *s = msnew(); 1982 int depth = 0, len = 1; 1983 char c, quote = 0; 1984 struct ainfo a; 1985 1986 a.a_lineno = lineno; 1987 a.a_line = dup_line(); 1988 a.a_cptr = a.a_line + (cptr - line - 1); 1989 1990 while ((c = *cptr++) != R_PAREN || depth || quote) 1991 { 1992 if (c == ',' && !quote && !depth) 1993 { 1994 len++; 1995 mputc(s, 0); 1996 continue; 1997 } 1998 mputc(s, c); 1999 if (c == '\n') 2000 { 2001 get_line(); 2002 if (!line) 2003 { 2004 if (quote) 2005 unterminated_string(&a); 2006 else 2007 unterminated_arglist(&a); 2008 } 2009 } 2010 else if (quote) 2011 { 2012 if (c == quote) 2013 quote = 0; 2014 else if (c == '\\') 2015 { 2016 if (*cptr != '\n') 2017 mputc(s, *cptr++); 2018 } 2019 } 2020 else 2021 { 2022 if (c == L_PAREN) 2023 depth++; 2024 else if (c == R_PAREN) 2025 depth--; 2026 else if (c == '\"' || c == '\'') 2027 quote = c; 2028 } 2029 } 2030 if (alen) 2031 *alen = len; 2032 FREE(a.a_line); 2033 return msdone(s); 2034 } 2035 2036 static char * 2037 parse_id(char *p, char **save) 2038 { 2039 char *b; 2040 2041 while (isspace(UCH(*p))) 2042 if (*p++ == '\n') 2043 rescan_lineno++; 2044 if (!isalpha(UCH(*p)) && *p != '_') 2045 return NULL; 2046 b = p; 2047 while (IS_NAME2(UCH(*p))) 2048 p++; 2049 if (save) 2050 { 2051 *save = cache_tag(b, (size_t)(p - b)); 2052 } 2053 return p; 2054 } 2055 2056 static char * 2057 parse_int(char *p, int *save) 2058 { 2059 int neg = 0, val = 0; 2060 2061 while (isspace(UCH(*p))) 2062 if (*p++ == '\n') 2063 rescan_lineno++; 2064 if (*p == '-') 2065 { 2066 neg = 1; 2067 p++; 2068 } 2069 if (!isdigit(UCH(*p))) 2070 return NULL; 2071 while (isdigit(UCH(*p))) 2072 val = val * 10 + *p++ - '0'; 2073 if (neg) 2074 val = -val; 2075 if (save) 2076 *save = val; 2077 return p; 2078 } 2079 2080 static void 2081 parse_arginfo(bucket *a, char *args, int argslen) 2082 { 2083 char *p = args, *tmp; 2084 int i, redec = 0; 2085 2086 if (a->args >= 0) 2087 { 2088 if (a->args != argslen) 2089 arg_number_disagree_warning(rescan_lineno, a->name); 2090 redec = 1; 2091 } 2092 else 2093 { 2094 if ((a->args = argslen) == 0) 2095 return; 2096 a->argnames = TMALLOC(char *, argslen); 2097 NO_SPACE(a->argnames); 2098 a->argtags = TMALLOC(char *, argslen); 2099 NO_SPACE(a->argtags); 2100 } 2101 if (!args) 2102 return; 2103 for (i = 0; i < argslen; i++) 2104 { 2105 while (isspace(UCH(*p))) 2106 if (*p++ == '\n') 2107 rescan_lineno++; 2108 if (*p++ != '$') 2109 bad_formals(); 2110 while (isspace(UCH(*p))) 2111 if (*p++ == '\n') 2112 rescan_lineno++; 2113 if (*p == '<') 2114 { 2115 havetags = 1; 2116 if (!(p = parse_id(p + 1, &tmp))) 2117 bad_formals(); 2118 while (isspace(UCH(*p))) 2119 if (*p++ == '\n') 2120 rescan_lineno++; 2121 if (*p++ != '>') 2122 bad_formals(); 2123 if (redec) 2124 { 2125 if (a->argtags[i] != tmp) 2126 arg_type_disagree_warning(rescan_lineno, i + 1, a->name); 2127 } 2128 else 2129 a->argtags[i] = tmp; 2130 } 2131 else if (!redec) 2132 a->argtags[i] = NULL; 2133 if (!(p = parse_id(p, &a->argnames[i]))) 2134 bad_formals(); 2135 while (isspace(UCH(*p))) 2136 if (*p++ == '\n') 2137 rescan_lineno++; 2138 if (*p++) 2139 bad_formals(); 2140 } 2141 free(args); 2142 } 2143 2144 static char * 2145 compile_arg(char **theptr, char *yyvaltag) 2146 { 2147 char *p = *theptr; 2148 struct mstring *c = msnew(); 2149 int i, n; 2150 Value_t *offsets = NULL, maxoffset; 2151 bucket **rhs; 2152 2153 maxoffset = 0; 2154 n = 0; 2155 for (i = nitems - 1; pitem[i]; --i) 2156 { 2157 n++; 2158 if (pitem[i]->class != ARGUMENT) 2159 maxoffset++; 2160 } 2161 if (maxoffset > 0) 2162 { 2163 int j; 2164 2165 offsets = TCMALLOC(Value_t, maxoffset + 1); 2166 NO_SPACE(offsets); 2167 2168 for (j = 0, i++; i < nitems; i++) 2169 if (pitem[i]->class != ARGUMENT) 2170 offsets[++j] = (Value_t)(i - nitems + 1); 2171 } 2172 rhs = pitem + nitems - 1; 2173 2174 if (yyvaltag) 2175 msprintf(c, "yyval.%s = ", yyvaltag); 2176 else 2177 msprintf(c, "yyval = "); 2178 while (*p) 2179 { 2180 if (*p == '$') 2181 { 2182 char *tag = NULL; 2183 if (*++p == '<') 2184 if (!(p = parse_id(++p, &tag)) || *p++ != '>') 2185 illegal_tag(rescan_lineno, NULL, NULL); 2186 if (isdigit(UCH(*p)) || *p == '-') 2187 { 2188 int val; 2189 if (!(p = parse_int(p, &val))) 2190 dollar_error(rescan_lineno, NULL, NULL); 2191 if (val <= 0) 2192 i = val - n; 2193 else if (val > maxoffset) 2194 { 2195 dollar_warning(rescan_lineno, val); 2196 i = val - maxoffset; 2197 } 2198 else if (maxoffset > 0) 2199 { 2200 i = offsets[val]; 2201 if (!tag && !(tag = rhs[i]->tag) && havetags) 2202 untyped_rhs(val, rhs[i]->name); 2203 } 2204 msprintf(c, "yystack.l_mark[%d]", i); 2205 if (tag) 2206 msprintf(c, ".%s", tag); 2207 else if (havetags) 2208 unknown_rhs(val); 2209 } 2210 else if (isalpha(UCH(*p)) || *p == '_') 2211 { 2212 char *arg; 2213 if (!(p = parse_id(p, &arg))) 2214 dollar_error(rescan_lineno, NULL, NULL); 2215 for (i = plhs[nrules]->args - 1; i >= 0; i--) 2216 if (arg == plhs[nrules]->argnames[i]) 2217 break; 2218 if (i < 0) 2219 unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL); 2220 else if (!tag) 2221 tag = plhs[nrules]->argtags[i]; 2222 msprintf(c, "yystack.l_mark[%d]", 2223 i - plhs[nrules]->args + 1 - n); 2224 if (tag) 2225 msprintf(c, ".%s", tag); 2226 else if (havetags) 2227 untyped_arg_warning(rescan_lineno, "$", arg); 2228 } 2229 else 2230 dollar_error(rescan_lineno, NULL, NULL); 2231 } 2232 else if (*p == '@') 2233 { 2234 at_error(rescan_lineno, NULL, NULL); 2235 } 2236 else 2237 { 2238 if (*p == '\n') 2239 rescan_lineno++; 2240 mputc(c, *p++); 2241 } 2242 } 2243 *theptr = p; 2244 if (maxoffset > 0) 2245 FREE(offsets); 2246 return msdone(c); 2247 } 2248 2249 static int 2250 can_elide_arg(char **theptr, char *yyvaltag) 2251 { 2252 char *p = *theptr; 2253 int rv = 0; 2254 int i, n = 0; 2255 Value_t *offsets = NULL, maxoffset = 0; 2256 bucket **rhs; 2257 char *tag = 0; 2258 2259 if (*p++ != '$') 2260 return 0; 2261 if (*p == '<') 2262 { 2263 if (!(p = parse_id(++p, &tag)) || *p++ != '>') 2264 return 0; 2265 } 2266 for (i = nitems - 1; pitem[i]; --i) 2267 { 2268 n++; 2269 if (pitem[i]->class != ARGUMENT) 2270 maxoffset++; 2271 } 2272 if (maxoffset > 0) 2273 { 2274 int j; 2275 2276 offsets = TCMALLOC(Value_t, maxoffset + 1); 2277 NO_SPACE(offsets); 2278 2279 for (j = 0, i++; i < nitems; i++) 2280 if (pitem[i]->class != ARGUMENT) 2281 offsets[++j] = (Value_t)(i - nitems + 1); 2282 } 2283 rhs = pitem + nitems - 1; 2284 2285 if (isdigit(UCH(*p)) || *p == '-') 2286 { 2287 int val; 2288 if (!(p = parse_int(p, &val))) 2289 rv = 0; 2290 else 2291 { 2292 if (val <= 0) 2293 rv = 1 - val + n; 2294 else if (val > maxoffset) 2295 rv = 0; 2296 else 2297 { 2298 i = offsets[val]; 2299 rv = 1 - i; 2300 if (!tag) 2301 tag = rhs[i]->tag; 2302 } 2303 } 2304 } 2305 else if (isalpha(UCH(*p)) || *p == '_') 2306 { 2307 char *arg; 2308 if (!(p = parse_id(p, &arg))) 2309 { 2310 FREE(offsets); 2311 return 0; 2312 } 2313 for (i = plhs[nrules]->args - 1; i >= 0; i--) 2314 if (arg == plhs[nrules]->argnames[i]) 2315 break; 2316 if (i >= 0) 2317 { 2318 if (!tag) 2319 tag = plhs[nrules]->argtags[i]; 2320 rv = plhs[nrules]->args + n - i; 2321 } 2322 } 2323 if (tag && yyvaltag) 2324 { 2325 if (strcmp(tag, yyvaltag)) 2326 rv = 0; 2327 } 2328 else if (tag || yyvaltag) 2329 rv = 0; 2330 if (maxoffset > 0) 2331 FREE(offsets); 2332 if (p == 0 || *p || rv <= 0) 2333 return 0; 2334 *theptr = p + 1; 2335 return rv; 2336 } 2337 2338 #define ARG_CACHE_SIZE 1024 2339 static struct arg_cache 2340 { 2341 struct arg_cache *next; 2342 char *code; 2343 int rule; 2344 } 2345 *arg_cache[ARG_CACHE_SIZE]; 2346 2347 static int 2348 lookup_arg_cache(char *code) 2349 { 2350 struct arg_cache *entry; 2351 2352 entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE]; 2353 while (entry) 2354 { 2355 if (!strnscmp(entry->code, code)) 2356 return entry->rule; 2357 entry = entry->next; 2358 } 2359 return -1; 2360 } 2361 2362 static void 2363 insert_arg_cache(char *code, int rule) 2364 { 2365 struct arg_cache *entry = NEW(struct arg_cache); 2366 int i; 2367 2368 NO_SPACE(entry); 2369 i = strnshash(code) % ARG_CACHE_SIZE; 2370 entry->code = code; 2371 entry->rule = rule; 2372 entry->next = arg_cache[i]; 2373 arg_cache[i] = entry; 2374 } 2375 2376 static void 2377 clean_arg_cache(void) 2378 { 2379 struct arg_cache *e, *t; 2380 int i; 2381 2382 for (i = 0; i < ARG_CACHE_SIZE; i++) 2383 { 2384 for (e = arg_cache[i]; (t = e); e = e->next, FREE(t)) 2385 free(e->code); 2386 arg_cache[i] = NULL; 2387 } 2388 } 2389 #endif /* defined(YYBTYACC) */ 2390 2391 static void 2392 advance_to_start(void) 2393 { 2394 int c; 2395 bucket *bp; 2396 int s_lineno; 2397 #if defined(YYBTYACC) 2398 char *args = NULL; 2399 int argslen = 0; 2400 #endif 2401 2402 for (;;) 2403 { 2404 char *s_cptr; 2405 2406 c = nextc(); 2407 if (c != '%') 2408 break; 2409 s_cptr = cptr; 2410 switch (keyword()) 2411 { 2412 case XCODE: 2413 copy_code(); 2414 break; 2415 2416 case MARK: 2417 no_grammar(); 2418 2419 case TEXT: 2420 copy_text(); 2421 break; 2422 2423 case START: 2424 declare_start(); 2425 break; 2426 2427 default: 2428 syntax_error(lineno, line, s_cptr); 2429 } 2430 } 2431 2432 c = nextc(); 2433 if (!isalpha(UCH(c)) && c != '_' && c != '.' && c != '_') 2434 syntax_error(lineno, line, cptr); 2435 bp = get_name(); 2436 if (goal == 0) 2437 { 2438 if (bp->class == TERM) 2439 terminal_start(bp->name); 2440 goal = bp; 2441 } 2442 2443 s_lineno = lineno; 2444 c = nextc(); 2445 if (c == EOF) 2446 unexpected_EOF(); 2447 rescan_lineno = lineno; /* line# for possible inherited args rescan */ 2448 #if defined(YYBTYACC) 2449 if (c == L_PAREN) 2450 { 2451 ++cptr; 2452 args = copy_args(&argslen); 2453 NO_SPACE(args); 2454 c = nextc(); 2455 } 2456 #endif 2457 if (c != ':') 2458 syntax_error(lineno, line, cptr); 2459 start_rule(bp, s_lineno); 2460 #if defined(YYBTYACC) 2461 parse_arginfo(bp, args, argslen); 2462 #endif 2463 ++cptr; 2464 } 2465 2466 static void 2467 start_rule(bucket *bp, int s_lineno) 2468 { 2469 if (bp->class == TERM) 2470 terminal_lhs(s_lineno); 2471 bp->class = NONTERM; 2472 if (!bp->index) 2473 bp->index = nrules; 2474 if (nrules >= maxrules) 2475 expand_rules(); 2476 plhs[nrules] = bp; 2477 rprec[nrules] = UNDEFINED; 2478 rassoc[nrules] = TOKEN; 2479 } 2480 2481 static void 2482 end_rule(void) 2483 { 2484 if (!last_was_action && plhs[nrules]->tag) 2485 { 2486 if (pitem[nitems - 1]) 2487 { 2488 int i; 2489 2490 for (i = nitems - 1; (i > 0) && pitem[i]; --i) 2491 continue; 2492 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag) 2493 default_action_warning(plhs[nrules]->name); 2494 } 2495 else 2496 default_action_warning(plhs[nrules]->name); 2497 } 2498 2499 last_was_action = 0; 2500 if (nitems >= maxitems) 2501 expand_items(); 2502 pitem[nitems] = 0; 2503 ++nitems; 2504 ++nrules; 2505 } 2506 2507 static void 2508 insert_empty_rule(void) 2509 { 2510 bucket *bp, **bpp; 2511 2512 assert(cache); 2513 assert(cache_size >= CACHE_SIZE); 2514 sprintf(cache, "$$%d", ++gensym); 2515 bp = make_bucket(cache); 2516 last_symbol->next = bp; 2517 last_symbol = bp; 2518 bp->tag = plhs[nrules]->tag; 2519 bp->class = ACTION; 2520 #if defined(YYBTYACC) 2521 bp->args = 0; 2522 #endif 2523 2524 nitems = (Value_t)(nitems + 2); 2525 if (nitems > maxitems) 2526 expand_items(); 2527 bpp = pitem + nitems - 1; 2528 *bpp-- = bp; 2529 while ((bpp[0] = bpp[-1]) != 0) 2530 --bpp; 2531 2532 if (++nrules >= maxrules) 2533 expand_rules(); 2534 plhs[nrules] = plhs[nrules - 1]; 2535 plhs[nrules - 1] = bp; 2536 rprec[nrules] = rprec[nrules - 1]; 2537 rprec[nrules - 1] = 0; 2538 rassoc[nrules] = rassoc[nrules - 1]; 2539 rassoc[nrules - 1] = TOKEN; 2540 } 2541 2542 #if defined(YYBTYACC) 2543 static char * 2544 insert_arg_rule(char *arg, char *tag) 2545 { 2546 int line_number = rescan_lineno; 2547 char *code = compile_arg(&arg, tag); 2548 int rule = lookup_arg_cache(code); 2549 FILE *f = action_file; 2550 2551 if (rule < 0) 2552 { 2553 rule = nrules; 2554 insert_arg_cache(code, rule); 2555 trialaction = 1; /* arg rules always run in trial mode */ 2556 begin_case(f, rule - 2); 2557 fprintf_lineno(f, line_number, input_file_name); 2558 fprintf(f, "%s;", code); 2559 end_case(f); 2560 insert_empty_rule(); 2561 plhs[rule]->tag = cache_tag(tag, strlen(tag)); 2562 plhs[rule]->class = ARGUMENT; 2563 } 2564 else 2565 { 2566 if (++nitems > maxitems) 2567 expand_items(); 2568 pitem[nitems - 1] = plhs[rule]; 2569 free(code); 2570 } 2571 return arg + 1; 2572 } 2573 #endif 2574 2575 static void 2576 add_symbol(void) 2577 { 2578 int c; 2579 bucket *bp; 2580 int s_lineno = lineno; 2581 #if defined(YYBTYACC) 2582 char *args = NULL; 2583 int argslen = 0; 2584 #endif 2585 2586 c = *cptr; 2587 if (c == '\'' || c == '"') 2588 bp = get_literal(); 2589 else 2590 bp = get_name(); 2591 2592 c = nextc(); 2593 rescan_lineno = lineno; /* line# for possible inherited args rescan */ 2594 #if defined(YYBTYACC) 2595 if (c == L_PAREN) 2596 { 2597 ++cptr; 2598 args = copy_args(&argslen); 2599 NO_SPACE(args); 2600 c = nextc(); 2601 } 2602 #endif 2603 if (c == ':') 2604 { 2605 end_rule(); 2606 start_rule(bp, s_lineno); 2607 #if defined(YYBTYACC) 2608 parse_arginfo(bp, args, argslen); 2609 #endif 2610 ++cptr; 2611 return; 2612 } 2613 2614 if (last_was_action) 2615 insert_empty_rule(); 2616 last_was_action = 0; 2617 2618 #if defined(YYBTYACC) 2619 if (bp->args < 0) 2620 bp->args = argslen; 2621 if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL) 2622 { 2623 int i; 2624 if (plhs[nrules]->args != bp->args) 2625 wrong_number_args_warning("default ", bp->name); 2626 for (i = bp->args - 1; i >= 0; i--) 2627 if (plhs[nrules]->argtags[i] != bp->argtags[i]) 2628 wrong_type_for_arg_warning(i + 1, bp->name); 2629 } 2630 else if (bp->args != argslen) 2631 wrong_number_args_warning("", bp->name); 2632 if (args != 0) 2633 { 2634 char *ap = args; 2635 int i = 0; 2636 int elide_cnt = can_elide_arg(&ap, bp->argtags[0]); 2637 2638 if (elide_cnt > argslen) 2639 elide_cnt = 0; 2640 if (elide_cnt) 2641 { 2642 for (i = 1; i < elide_cnt; i++) 2643 if (can_elide_arg(&ap, bp->argtags[i]) != elide_cnt - i) 2644 { 2645 elide_cnt = 0; 2646 break; 2647 } 2648 } 2649 if (elide_cnt) 2650 { 2651 assert(i == elide_cnt); 2652 } 2653 else 2654 { 2655 ap = args; 2656 i = 0; 2657 } 2658 for (; i < argslen; i++) 2659 ap = insert_arg_rule(ap, bp->argtags[i]); 2660 free(args); 2661 } 2662 #endif /* defined(YYBTYACC) */ 2663 2664 if (++nitems > maxitems) 2665 expand_items(); 2666 pitem[nitems - 1] = bp; 2667 } 2668 2669 static void 2670 copy_action(void) 2671 { 2672 int c; 2673 int i, j, n; 2674 int depth; 2675 #if defined(YYBTYACC) 2676 int haveyyval = 0; 2677 #endif 2678 char *tag; 2679 FILE *f = action_file; 2680 struct ainfo a; 2681 Value_t *offsets = NULL, maxoffset; 2682 bucket **rhs; 2683 2684 a.a_lineno = lineno; 2685 a.a_line = dup_line(); 2686 a.a_cptr = a.a_line + (cptr - line); 2687 2688 if (last_was_action) 2689 insert_empty_rule(); 2690 last_was_action = 1; 2691 #if defined(YYBTYACC) 2692 trialaction = (*cptr == L_BRAC); 2693 #endif 2694 2695 begin_case(f, nrules - 2); 2696 #if defined(YYBTYACC) 2697 if (backtrack) 2698 { 2699 if (!trialaction) 2700 fprintf(f, " if (!yytrial)\n"); 2701 } 2702 #endif 2703 fprintf_lineno(f, lineno, input_file_name); 2704 if (*cptr == '=') 2705 ++cptr; 2706 2707 /* avoid putting curly-braces in first column, to ease editing */ 2708 if (*after_blanks(cptr) == L_CURL) 2709 { 2710 putc('\t', f); 2711 cptr = after_blanks(cptr); 2712 } 2713 2714 maxoffset = 0; 2715 n = 0; 2716 for (i = nitems - 1; pitem[i]; --i) 2717 { 2718 ++n; 2719 if (pitem[i]->class != ARGUMENT) 2720 maxoffset++; 2721 } 2722 if (maxoffset > 0) 2723 { 2724 offsets = TMALLOC(Value_t, maxoffset + 1); 2725 NO_SPACE(offsets); 2726 2727 for (j = 0, i++; i < nitems; i++) 2728 { 2729 if (pitem[i]->class != ARGUMENT) 2730 { 2731 offsets[++j] = (Value_t)(i - nitems + 1); 2732 } 2733 } 2734 } 2735 rhs = pitem + nitems - 1; 2736 2737 depth = 0; 2738 loop: 2739 c = *cptr; 2740 if (c == '$') 2741 { 2742 if (cptr[1] == '<') 2743 { 2744 int d_lineno = lineno; 2745 char *d_line = dup_line(); 2746 char *d_cptr = d_line + (cptr - line); 2747 2748 ++cptr; 2749 tag = get_tag(); 2750 c = *cptr; 2751 if (c == '$') 2752 { 2753 fprintf(f, "yyval.%s", tag); 2754 ++cptr; 2755 FREE(d_line); 2756 goto loop; 2757 } 2758 else if (isdigit(UCH(c))) 2759 { 2760 i = get_number(); 2761 if (i == 0) 2762 fprintf(f, "yystack.l_mark[%d].%s", -n, tag); 2763 else if (i > maxoffset) 2764 { 2765 dollar_warning(d_lineno, i); 2766 fprintf(f, "yystack.l_mark[%ld].%s", 2767 (long)(i - maxoffset), tag); 2768 } 2769 else if (offsets) 2770 fprintf(f, "yystack.l_mark[%ld].%s", 2771 (long)offsets[i], tag); 2772 FREE(d_line); 2773 goto loop; 2774 } 2775 else if (c == '-' && isdigit(UCH(cptr[1]))) 2776 { 2777 ++cptr; 2778 i = -get_number() - n; 2779 fprintf(f, "yystack.l_mark[%d].%s", i, tag); 2780 FREE(d_line); 2781 goto loop; 2782 } 2783 #if defined(YYBTYACC) 2784 else if (isalpha(UCH(c)) || c == '_') 2785 { 2786 char *arg = scan_id(); 2787 for (i = plhs[nrules]->args - 1; i >= 0; i--) 2788 if (arg == plhs[nrules]->argnames[i]) 2789 break; 2790 if (i < 0) 2791 unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr); 2792 fprintf(f, "yystack.l_mark[%d].%s", 2793 i - plhs[nrules]->args + 1 - n, tag); 2794 FREE(d_line); 2795 goto loop; 2796 } 2797 #endif 2798 else 2799 dollar_error(d_lineno, d_line, d_cptr); 2800 } 2801 else if (cptr[1] == '$') 2802 { 2803 if (havetags) 2804 { 2805 tag = plhs[nrules]->tag; 2806 if (tag == 0) 2807 untyped_lhs(); 2808 fprintf(f, "yyval.%s", tag); 2809 } 2810 else 2811 fprintf(f, "yyval"); 2812 cptr += 2; 2813 #if defined(YYBTYACC) 2814 haveyyval = 1; 2815 #endif 2816 goto loop; 2817 } 2818 else if (isdigit(UCH(cptr[1]))) 2819 { 2820 ++cptr; 2821 i = get_number(); 2822 if (havetags && offsets) 2823 { 2824 if (i <= 0 || i > maxoffset) 2825 unknown_rhs(i); 2826 tag = rhs[offsets[i]]->tag; 2827 if (tag == 0) 2828 untyped_rhs(i, rhs[offsets[i]]->name); 2829 fprintf(f, "yystack.l_mark[%ld].%s", (long)offsets[i], tag); 2830 } 2831 else 2832 { 2833 if (i == 0) 2834 fprintf(f, "yystack.l_mark[%d]", -n); 2835 else if (i > maxoffset) 2836 { 2837 dollar_warning(lineno, i); 2838 fprintf(f, "yystack.l_mark[%ld]", (long)(i - maxoffset)); 2839 } 2840 else if (offsets) 2841 fprintf(f, "yystack.l_mark[%ld]", (long)offsets[i]); 2842 } 2843 goto loop; 2844 } 2845 else if (cptr[1] == '-') 2846 { 2847 cptr += 2; 2848 i = get_number(); 2849 if (havetags) 2850 unknown_rhs(-i); 2851 fprintf(f, "yystack.l_mark[%d]", -i - n); 2852 goto loop; 2853 } 2854 #if defined(YYBTYACC) 2855 else if (isalpha(UCH(cptr[1])) || cptr[1] == '_') 2856 { 2857 char *arg; 2858 ++cptr; 2859 arg = scan_id(); 2860 for (i = plhs[nrules]->args - 1; i >= 0; i--) 2861 if (arg == plhs[nrules]->argnames[i]) 2862 break; 2863 if (i < 0) 2864 unknown_arg_warning(lineno, "$", arg, line, cptr); 2865 tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]); 2866 fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n); 2867 if (tag) 2868 fprintf(f, ".%s", tag); 2869 else if (havetags) 2870 untyped_arg_warning(lineno, "$", arg); 2871 goto loop; 2872 } 2873 #endif 2874 } 2875 #if defined(YYBTYACC) 2876 if (c == '@') 2877 { 2878 if (!locations) 2879 { 2880 int l_lineno = lineno; 2881 char *l_line = dup_line(); 2882 char *l_cptr = l_line + (cptr - line); 2883 syntax_error(l_lineno, l_line, l_cptr); 2884 } 2885 if (cptr[1] == '$') 2886 { 2887 fprintf(f, "yyloc"); 2888 cptr += 2; 2889 goto loop; 2890 } 2891 else if (isdigit(UCH(cptr[1]))) 2892 { 2893 ++cptr; 2894 i = get_number(); 2895 if (i == 0) 2896 fprintf(f, "yystack.p_mark[%d]", -n); 2897 else if (i > maxoffset) 2898 { 2899 at_warning(lineno, i); 2900 fprintf(f, "yystack.p_mark[%d]", i - maxoffset); 2901 } 2902 else if (offsets) 2903 fprintf(f, "yystack.p_mark[%d]", offsets[i]); 2904 goto loop; 2905 } 2906 else if (cptr[1] == '-') 2907 { 2908 cptr += 2; 2909 i = get_number(); 2910 fprintf(f, "yystack.p_mark[%d]", -i - n); 2911 goto loop; 2912 } 2913 } 2914 #endif 2915 if (IS_NAME1(c)) 2916 { 2917 do 2918 { 2919 putc(c, f); 2920 c = *++cptr; 2921 } 2922 while (IS_NAME2(c)); 2923 goto loop; 2924 } 2925 ++cptr; 2926 #if defined(YYBTYACC) 2927 if (backtrack) 2928 { 2929 if (trialaction && c == L_BRAC && depth == 0) 2930 { 2931 ++depth; 2932 putc(L_CURL, f); 2933 goto loop; 2934 } 2935 if (trialaction && c == R_BRAC && depth == 1) 2936 { 2937 --depth; 2938 putc(R_CURL, f); 2939 c = nextc(); 2940 if (c == L_BRAC && !haveyyval) 2941 { 2942 goto loop; 2943 } 2944 if (c == L_CURL && !haveyyval) 2945 { 2946 fprintf(f, " if (!yytrial)\n"); 2947 fprintf_lineno(f, lineno, input_file_name); 2948 trialaction = 0; 2949 goto loop; 2950 } 2951 end_case(f); 2952 FREE(a.a_line); 2953 if (maxoffset > 0) 2954 FREE(offsets); 2955 return; 2956 } 2957 } 2958 #endif 2959 putc(c, f); 2960 switch (c) 2961 { 2962 case '\n': 2963 get_line(); 2964 if (line) 2965 goto loop; 2966 unterminated_action(&a); 2967 2968 case ';': 2969 if (depth > 0) 2970 goto loop; 2971 end_case(f); 2972 free(a.a_line); 2973 if (maxoffset > 0) 2974 FREE(offsets); 2975 return; 2976 2977 #if defined(YYBTYACC) 2978 case L_BRAC: 2979 if (backtrack) 2980 ++depth; 2981 goto loop; 2982 2983 case R_BRAC: 2984 if (backtrack) 2985 --depth; 2986 goto loop; 2987 #endif 2988 2989 case L_CURL: 2990 ++depth; 2991 goto loop; 2992 2993 case R_CURL: 2994 if (--depth > 0) 2995 goto loop; 2996 #if defined(YYBTYACC) 2997 if (backtrack) 2998 { 2999 c = nextc(); 3000 if (c == L_BRAC && !haveyyval) 3001 { 3002 trialaction = 1; 3003 goto loop; 3004 } 3005 if (c == L_CURL && !haveyyval) 3006 { 3007 fprintf(f, " if (!yytrial)\n"); 3008 fprintf_lineno(f, lineno, input_file_name); 3009 goto loop; 3010 } 3011 } 3012 #endif 3013 end_case(f); 3014 free(a.a_line); 3015 if (maxoffset > 0) 3016 FREE(offsets); 3017 return; 3018 3019 case '\'': 3020 case '"': 3021 { 3022 char *s = copy_string(c); 3023 fputs(s, f); 3024 free(s); 3025 } 3026 goto loop; 3027 3028 case '/': 3029 { 3030 char *s = copy_comment(); 3031 fputs(s, f); 3032 free(s); 3033 } 3034 goto loop; 3035 3036 default: 3037 goto loop; 3038 } 3039 } 3040 3041 #if defined(YYBTYACC) 3042 static char * 3043 get_code(struct ainfo *a, const char *loc) 3044 { 3045 int c; 3046 int depth; 3047 char *tag; 3048 struct mstring *code_mstr = msnew(); 3049 3050 if (!lflag) 3051 msprintf(code_mstr, line_format, lineno, input_file_name); 3052 3053 cptr = after_blanks(cptr); 3054 if (*cptr == L_CURL) 3055 /* avoid putting curly-braces in first column, to ease editing */ 3056 mputc(code_mstr, '\t'); 3057 else 3058 syntax_error(lineno, line, cptr); 3059 3060 a->a_lineno = lineno; 3061 a->a_line = dup_line(); 3062 a->a_cptr = a->a_line + (cptr - line); 3063 3064 depth = 0; 3065 loop: 3066 c = *cptr; 3067 if (c == '$') 3068 { 3069 if (cptr[1] == '<') 3070 { 3071 int d_lineno = lineno; 3072 char *d_line = dup_line(); 3073 char *d_cptr = d_line + (cptr - line); 3074 3075 ++cptr; 3076 tag = get_tag(); 3077 c = *cptr; 3078 if (c == '$') 3079 { 3080 msprintf(code_mstr, "(*val).%s", tag); 3081 ++cptr; 3082 FREE(d_line); 3083 goto loop; 3084 } 3085 else 3086 dollar_error(d_lineno, d_line, d_cptr); 3087 } 3088 else if (cptr[1] == '$') 3089 { 3090 /* process '$$' later; replacement is context dependent */ 3091 msprintf(code_mstr, "$$"); 3092 cptr += 2; 3093 goto loop; 3094 } 3095 } 3096 if (c == '@' && cptr[1] == '$') 3097 { 3098 if (!locations) 3099 { 3100 int l_lineno = lineno; 3101 char *l_line = dup_line(); 3102 char *l_cptr = l_line + (cptr - line); 3103 syntax_error(l_lineno, l_line, l_cptr); 3104 } 3105 msprintf(code_mstr, "%s", loc); 3106 cptr += 2; 3107 goto loop; 3108 } 3109 if (IS_NAME1(c)) 3110 { 3111 do 3112 { 3113 mputc(code_mstr, c); 3114 c = *++cptr; 3115 } 3116 while (IS_NAME2(c)); 3117 goto loop; 3118 } 3119 ++cptr; 3120 mputc(code_mstr, c); 3121 switch (c) 3122 { 3123 case '\n': 3124 get_line(); 3125 if (line) 3126 goto loop; 3127 unterminated_action(a); 3128 3129 case L_CURL: 3130 ++depth; 3131 goto loop; 3132 3133 case R_CURL: 3134 if (--depth > 0) 3135 goto loop; 3136 goto out; 3137 3138 case '\'': 3139 case '"': 3140 { 3141 char *s = copy_string(c); 3142 msprintf(code_mstr, "%s", s); 3143 free(s); 3144 } 3145 goto loop; 3146 3147 case '/': 3148 { 3149 char *s = copy_comment(); 3150 msprintf(code_mstr, "%s", s); 3151 free(s); 3152 } 3153 goto loop; 3154 3155 default: 3156 goto loop; 3157 } 3158 out: 3159 return msdone(code_mstr); 3160 } 3161 3162 static void 3163 copy_initial_action(void) 3164 { 3165 struct ainfo a; 3166 3167 initial_action = get_code(&a, "yyloc"); 3168 free(a.a_line); 3169 } 3170 3171 static void 3172 copy_destructor(void) 3173 { 3174 char *code_text; 3175 struct ainfo a; 3176 bucket *bp; 3177 3178 code_text = get_code(&a, "(*loc)"); 3179 3180 for (;;) 3181 { 3182 int c = nextc(); 3183 if (c == EOF) 3184 unexpected_EOF(); 3185 if (c == '<') 3186 { 3187 if (cptr[1] == '>') 3188 { /* "no semantic type" default destructor */ 3189 cptr += 2; 3190 if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL) 3191 { 3192 static char untyped_default[] = "<>"; 3193 bp = make_bucket("untyped default"); 3194 bp->tag = untyped_default; 3195 default_destructor[UNTYPED_DEFAULT] = bp; 3196 } 3197 if (bp->destructor != NULL) 3198 destructor_redeclared_warning(&a); 3199 else 3200 /* replace "$$" with "(*val)" in destructor code */ 3201 bp->destructor = process_destructor_XX(code_text, NULL); 3202 } 3203 else if (cptr[1] == '*' && cptr[2] == '>') 3204 { /* "no per-symbol or per-type" default destructor */ 3205 cptr += 3; 3206 if ((bp = default_destructor[TYPED_DEFAULT]) == NULL) 3207 { 3208 static char typed_default[] = "<*>"; 3209 bp = make_bucket("typed default"); 3210 bp->tag = typed_default; 3211 default_destructor[TYPED_DEFAULT] = bp; 3212 } 3213 if (bp->destructor != NULL) 3214 destructor_redeclared_warning(&a); 3215 else 3216 { 3217 /* postpone re-processing destructor $$s until end of grammar spec */ 3218 bp->destructor = TMALLOC(char, strlen(code_text) + 1); 3219 NO_SPACE(bp->destructor); 3220 strcpy(bp->destructor, code_text); 3221 } 3222 } 3223 else 3224 { /* "semantic type" default destructor */ 3225 char *tag = get_tag(); 3226 bp = lookup_type_destructor(tag); 3227 if (bp->destructor != NULL) 3228 destructor_redeclared_warning(&a); 3229 else 3230 /* replace "$$" with "(*val).tag" in destructor code */ 3231 bp->destructor = process_destructor_XX(code_text, tag); 3232 } 3233 } 3234 else if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$') 3235 { /* "symbol" destructor */ 3236 bp = get_name(); 3237 if (bp->destructor != NULL) 3238 destructor_redeclared_warning(&a); 3239 else 3240 { 3241 /* postpone re-processing destructor $$s until end of grammar spec */ 3242 bp->destructor = TMALLOC(char, strlen(code_text) + 1); 3243 NO_SPACE(bp->destructor); 3244 strcpy(bp->destructor, code_text); 3245 } 3246 } 3247 else 3248 break; 3249 } 3250 free(a.a_line); 3251 free(code_text); 3252 } 3253 3254 static char * 3255 process_destructor_XX(char *code, char *tag) 3256 { 3257 int c; 3258 int quote; 3259 int depth; 3260 struct mstring *new_code = msnew(); 3261 char *codeptr = code; 3262 3263 depth = 0; 3264 loop: /* step thru code */ 3265 c = *codeptr; 3266 if (c == '$' && codeptr[1] == '$') 3267 { 3268 codeptr += 2; 3269 if (tag == NULL) 3270 msprintf(new_code, "(*val)"); 3271 else 3272 msprintf(new_code, "(*val).%s", tag); 3273 goto loop; 3274 } 3275 if (IS_NAME1(c)) 3276 { 3277 do 3278 { 3279 mputc(new_code, c); 3280 c = *++codeptr; 3281 } 3282 while (IS_NAME2(c)); 3283 goto loop; 3284 } 3285 ++codeptr; 3286 mputc(new_code, c); 3287 switch (c) 3288 { 3289 case L_CURL: 3290 ++depth; 3291 goto loop; 3292 3293 case R_CURL: 3294 if (--depth > 0) 3295 goto loop; 3296 return msdone(new_code); 3297 3298 case '\'': 3299 case '"': 3300 quote = c; 3301 for (;;) 3302 { 3303 c = *codeptr++; 3304 mputc(new_code, c); 3305 if (c == quote) 3306 goto loop; 3307 if (c == '\\') 3308 { 3309 c = *codeptr++; 3310 mputc(new_code, c); 3311 } 3312 } 3313 3314 case '/': 3315 c = *codeptr; 3316 if (c == '*') 3317 { 3318 mputc(new_code, c); 3319 ++codeptr; 3320 for (;;) 3321 { 3322 c = *codeptr++; 3323 mputc(new_code, c); 3324 if (c == '*' && *codeptr == '/') 3325 { 3326 mputc(new_code, '/'); 3327 ++codeptr; 3328 goto loop; 3329 } 3330 } 3331 } 3332 goto loop; 3333 3334 default: 3335 goto loop; 3336 } 3337 } 3338 #endif /* defined(YYBTYACC) */ 3339 3340 static int 3341 mark_symbol(void) 3342 { 3343 int c; 3344 bucket *bp = NULL; 3345 3346 c = cptr[1]; 3347 if (c == '%' || c == '\\') 3348 { 3349 cptr += 2; 3350 return (1); 3351 } 3352 3353 if (c == '=') 3354 cptr += 2; 3355 else if ((c == 'p' || c == 'P') && 3356 ((c = cptr[2]) == 'r' || c == 'R') && 3357 ((c = cptr[3]) == 'e' || c == 'E') && 3358 ((c = cptr[4]) == 'c' || c == 'C') && 3359 ((c = cptr[5], !IS_IDENT(c)))) 3360 cptr += 5; 3361 else if ((c == 'e' || c == 'E') && 3362 ((c = cptr[2]) == 'm' || c == 'M') && 3363 ((c = cptr[3]) == 'p' || c == 'P') && 3364 ((c = cptr[4]) == 't' || c == 'T') && 3365 ((c = cptr[5]) == 'y' || c == 'Y') && 3366 ((c = cptr[6], !IS_IDENT(c)))) 3367 { 3368 cptr += 6; 3369 return (1); 3370 } 3371 else 3372 syntax_error(lineno, line, cptr); 3373 3374 c = nextc(); 3375 if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$') 3376 bp = get_name(); 3377 else if (c == '\'' || c == '"') 3378 bp = get_literal(); 3379 else 3380 { 3381 syntax_error(lineno, line, cptr); 3382 /*NOTREACHED */ 3383 } 3384 3385 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules]) 3386 prec_redeclared(); 3387 3388 rprec[nrules] = bp->prec; 3389 rassoc[nrules] = bp->assoc; 3390 return (0); 3391 } 3392 3393 static void 3394 read_grammar(void) 3395 { 3396 initialize_grammar(); 3397 advance_to_start(); 3398 3399 for (;;) 3400 { 3401 int c = nextc(); 3402 3403 if (c == EOF) 3404 break; 3405 if (isalpha(UCH(c)) 3406 || c == '_' 3407 || c == '.' 3408 || c == '$' 3409 || c == '\'' 3410 || c == '"') 3411 { 3412 add_symbol(); 3413 } 3414 else if (c == L_CURL || c == '=' 3415 #if defined(YYBTYACC) 3416 || (backtrack && c == L_BRAC) 3417 #endif 3418 ) 3419 { 3420 copy_action(); 3421 } 3422 else if (c == '|') 3423 { 3424 end_rule(); 3425 start_rule(plhs[nrules - 1], 0); 3426 ++cptr; 3427 } 3428 else if (c == '%') 3429 { 3430 if (mark_symbol()) 3431 break; 3432 } 3433 else 3434 syntax_error(lineno, line, cptr); 3435 } 3436 end_rule(); 3437 #if defined(YYBTYACC) 3438 if (goal->args > 0) 3439 start_requires_args(goal->name); 3440 #endif 3441 } 3442 3443 static void 3444 free_tags(void) 3445 { 3446 int i; 3447 3448 if (tag_table == 0) 3449 return; 3450 3451 for (i = 0; i < ntags; ++i) 3452 { 3453 assert(tag_table[i]); 3454 FREE(tag_table[i]); 3455 } 3456 FREE(tag_table); 3457 } 3458 3459 static void 3460 pack_names(void) 3461 { 3462 bucket *bp; 3463 char *p; 3464 char *t; 3465 3466 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */ 3467 for (bp = first_symbol; bp; bp = bp->next) 3468 name_pool_size += strlen(bp->name) + 1; 3469 3470 name_pool = TMALLOC(char, name_pool_size); 3471 NO_SPACE(name_pool); 3472 3473 strcpy(name_pool, "$accept"); 3474 strcpy(name_pool + 8, "$end"); 3475 t = name_pool + 13; 3476 for (bp = first_symbol; bp; bp = bp->next) 3477 { 3478 char *s = bp->name; 3479 3480 p = t; 3481 while ((*t++ = *s++) != 0) 3482 continue; 3483 FREE(bp->name); 3484 bp->name = p; 3485 } 3486 } 3487 3488 static void 3489 check_symbols(void) 3490 { 3491 bucket *bp; 3492 3493 if (goal->class == UNKNOWN) 3494 undefined_goal(goal->name); 3495 3496 for (bp = first_symbol; bp; bp = bp->next) 3497 { 3498 if (bp->class == UNKNOWN) 3499 { 3500 undefined_symbol_warning(bp->name); 3501 bp->class = TERM; 3502 } 3503 } 3504 } 3505 3506 static void 3507 protect_string(char *src, char **des) 3508 { 3509 *des = src; 3510 if (src) 3511 { 3512 char *s; 3513 char *d; 3514 3515 unsigned len = 1; 3516 3517 s = src; 3518 while (*s) 3519 { 3520 if ('\\' == *s || '"' == *s) 3521 len++; 3522 s++; 3523 len++; 3524 } 3525 3526 *des = d = TMALLOC(char, len); 3527 NO_SPACE(d); 3528 3529 s = src; 3530 while (*s) 3531 { 3532 if ('\\' == *s || '"' == *s) 3533 *d++ = '\\'; 3534 *d++ = *s++; 3535 } 3536 *d = '\0'; 3537 } 3538 } 3539 3540 static void 3541 pack_symbols(void) 3542 { 3543 bucket *bp; 3544 bucket **v; 3545 Value_t i, j, k, n; 3546 #if defined(YYBTYACC) 3547 Value_t max_tok_pval; 3548 #endif 3549 3550 nsyms = 2; 3551 ntokens = 1; 3552 for (bp = first_symbol; bp; bp = bp->next) 3553 { 3554 ++nsyms; 3555 if (bp->class == TERM) 3556 ++ntokens; 3557 } 3558 start_symbol = (Value_t)ntokens; 3559 nvars = (Value_t)(nsyms - ntokens); 3560 3561 symbol_name = TMALLOC(char *, nsyms); 3562 NO_SPACE(symbol_name); 3563 3564 symbol_value = TMALLOC(Value_t, nsyms); 3565 NO_SPACE(symbol_value); 3566 3567 symbol_prec = TMALLOC(Value_t, nsyms); 3568 NO_SPACE(symbol_prec); 3569 3570 symbol_assoc = TMALLOC(char, nsyms); 3571 NO_SPACE(symbol_assoc); 3572 3573 #if defined(YYBTYACC) 3574 symbol_pval = TMALLOC(Value_t, nsyms); 3575 NO_SPACE(symbol_pval); 3576 3577 if (destructor) 3578 { 3579 symbol_destructor = CALLOC(sizeof(char *), nsyms); 3580 NO_SPACE(symbol_destructor); 3581 3582 symbol_type_tag = CALLOC(sizeof(char *), nsyms); 3583 NO_SPACE(symbol_type_tag); 3584 } 3585 #endif 3586 3587 v = TMALLOC(bucket *, nsyms); 3588 NO_SPACE(v); 3589 3590 v[0] = 0; 3591 v[start_symbol] = 0; 3592 3593 i = 1; 3594 j = (Value_t)(start_symbol + 1); 3595 for (bp = first_symbol; bp; bp = bp->next) 3596 { 3597 if (bp->class == TERM) 3598 v[i++] = bp; 3599 else 3600 v[j++] = bp; 3601 } 3602 assert(i == ntokens && j == nsyms); 3603 3604 for (i = 1; i < ntokens; ++i) 3605 v[i]->index = i; 3606 3607 goal->index = (Index_t)(start_symbol + 1); 3608 k = (Value_t)(start_symbol + 2); 3609 while (++i < nsyms) 3610 if (v[i] != goal) 3611 { 3612 v[i]->index = k; 3613 ++k; 3614 } 3615 3616 goal->value = 0; 3617 k = 1; 3618 for (i = (Value_t)(start_symbol + 1); i < nsyms; ++i) 3619 { 3620 if (v[i] != goal) 3621 { 3622 v[i]->value = k; 3623 ++k; 3624 } 3625 } 3626 3627 k = 0; 3628 for (i = 1; i < ntokens; ++i) 3629 { 3630 n = v[i]->value; 3631 if (n > 256) 3632 { 3633 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j) 3634 symbol_value[j] = symbol_value[j - 1]; 3635 symbol_value[j] = n; 3636 } 3637 } 3638 3639 assert(v[1] != 0); 3640 3641 if (v[1]->value == UNDEFINED) 3642 v[1]->value = 256; 3643 3644 j = 0; 3645 n = 257; 3646 for (i = 2; i < ntokens; ++i) 3647 { 3648 if (v[i]->value == UNDEFINED) 3649 { 3650 while (j < k && n == symbol_value[j]) 3651 { 3652 while (++j < k && n == symbol_value[j]) 3653 continue; 3654 ++n; 3655 } 3656 v[i]->value = n; 3657 ++n; 3658 } 3659 } 3660 3661 symbol_name[0] = name_pool + 8; 3662 symbol_value[0] = 0; 3663 symbol_prec[0] = 0; 3664 symbol_assoc[0] = TOKEN; 3665 #if defined(YYBTYACC) 3666 symbol_pval[0] = 0; 3667 max_tok_pval = 0; 3668 #endif 3669 for (i = 1; i < ntokens; ++i) 3670 { 3671 symbol_name[i] = v[i]->name; 3672 symbol_value[i] = v[i]->value; 3673 symbol_prec[i] = v[i]->prec; 3674 symbol_assoc[i] = v[i]->assoc; 3675 #if defined(YYBTYACC) 3676 symbol_pval[i] = v[i]->value; 3677 if (symbol_pval[i] > max_tok_pval) 3678 max_tok_pval = symbol_pval[i]; 3679 if (destructor) 3680 { 3681 symbol_destructor[i] = v[i]->destructor; 3682 symbol_type_tag[i] = v[i]->tag; 3683 } 3684 #endif 3685 } 3686 symbol_name[start_symbol] = name_pool; 3687 symbol_value[start_symbol] = -1; 3688 symbol_prec[start_symbol] = 0; 3689 symbol_assoc[start_symbol] = TOKEN; 3690 #if defined(YYBTYACC) 3691 symbol_pval[start_symbol] = (Value_t)(max_tok_pval + 1); 3692 #endif 3693 for (++i; i < nsyms; ++i) 3694 { 3695 k = v[i]->index; 3696 symbol_name[k] = v[i]->name; 3697 symbol_value[k] = v[i]->value; 3698 symbol_prec[k] = v[i]->prec; 3699 symbol_assoc[k] = v[i]->assoc; 3700 #if defined(YYBTYACC) 3701 symbol_pval[k] = (Value_t)((max_tok_pval + 1) + v[i]->value + 1); 3702 if (destructor) 3703 { 3704 symbol_destructor[k] = v[i]->destructor; 3705 symbol_type_tag[k] = v[i]->tag; 3706 } 3707 #endif 3708 } 3709 3710 if (gflag) 3711 { 3712 symbol_pname = TMALLOC(char *, nsyms); 3713 NO_SPACE(symbol_pname); 3714 3715 for (i = 0; i < nsyms; ++i) 3716 protect_string(symbol_name[i], &(symbol_pname[i])); 3717 } 3718 3719 FREE(v); 3720 } 3721 3722 static void 3723 pack_grammar(void) 3724 { 3725 int i; 3726 Value_t j; 3727 3728 ritem = TMALLOC(Value_t, nitems); 3729 NO_SPACE(ritem); 3730 3731 rlhs = TMALLOC(Value_t, nrules); 3732 NO_SPACE(rlhs); 3733 3734 rrhs = TMALLOC(Value_t, nrules + 1); 3735 NO_SPACE(rrhs); 3736 3737 rprec = TREALLOC(Value_t, rprec, nrules); 3738 NO_SPACE(rprec); 3739 3740 rassoc = TREALLOC(Assoc_t, rassoc, nrules); 3741 NO_SPACE(rassoc); 3742 3743 ritem[0] = -1; 3744 ritem[1] = goal->index; 3745 ritem[2] = 0; 3746 ritem[3] = -2; 3747 rlhs[0] = 0; 3748 rlhs[1] = 0; 3749 rlhs[2] = start_symbol; 3750 rrhs[0] = 0; 3751 rrhs[1] = 0; 3752 rrhs[2] = 1; 3753 3754 j = 4; 3755 for (i = 3; i < nrules; ++i) 3756 { 3757 Assoc_t assoc; 3758 Value_t prec2; 3759 3760 #if defined(YYBTYACC) 3761 if (plhs[i]->args > 0) 3762 { 3763 if (plhs[i]->argnames) 3764 { 3765 FREE(plhs[i]->argnames); 3766 plhs[i]->argnames = NULL; 3767 } 3768 if (plhs[i]->argtags) 3769 { 3770 FREE(plhs[i]->argtags); 3771 plhs[i]->argtags = NULL; 3772 } 3773 } 3774 #endif /* defined(YYBTYACC) */ 3775 rlhs[i] = plhs[i]->index; 3776 rrhs[i] = j; 3777 assoc = TOKEN; 3778 prec2 = 0; 3779 while (pitem[j]) 3780 { 3781 ritem[j] = pitem[j]->index; 3782 if (pitem[j]->class == TERM) 3783 { 3784 prec2 = pitem[j]->prec; 3785 assoc = pitem[j]->assoc; 3786 } 3787 ++j; 3788 } 3789 ritem[j] = (Value_t)-i; 3790 ++j; 3791 if (rprec[i] == UNDEFINED) 3792 { 3793 rprec[i] = prec2; 3794 rassoc[i] = assoc; 3795 } 3796 } 3797 rrhs[i] = j; 3798 3799 FREE(plhs); 3800 FREE(pitem); 3801 #if defined(YYBTYACC) 3802 clean_arg_cache(); 3803 #endif 3804 } 3805 3806 static void 3807 print_grammar(void) 3808 { 3809 int i, k; 3810 size_t j, spacing = 0; 3811 FILE *f = verbose_file; 3812 3813 if (!vflag) 3814 return; 3815 3816 k = 1; 3817 for (i = 2; i < nrules; ++i) 3818 { 3819 if (rlhs[i] != rlhs[i - 1]) 3820 { 3821 if (i != 2) 3822 fprintf(f, "\n"); 3823 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]); 3824 spacing = strlen(symbol_name[rlhs[i]]) + 1; 3825 } 3826 else 3827 { 3828 fprintf(f, "%4d ", i - 2); 3829 j = spacing; 3830 while (j-- != 0) 3831 putc(' ', f); 3832 putc('|', f); 3833 } 3834 3835 while (ritem[k] >= 0) 3836 { 3837 fprintf(f, " %s", symbol_name[ritem[k]]); 3838 ++k; 3839 } 3840 ++k; 3841 putc('\n', f); 3842 } 3843 } 3844 3845 #if defined(YYBTYACC) 3846 static void 3847 finalize_destructors(void) 3848 { 3849 int i; 3850 bucket *bp; 3851 3852 for (i = 2; i < nsyms; ++i) 3853 { 3854 char *tag = symbol_type_tag[i]; 3855 3856 if (symbol_destructor[i] == NULL) 3857 { 3858 if (tag == NULL) 3859 { /* use <> destructor, if there is one */ 3860 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL) 3861 { 3862 symbol_destructor[i] = TMALLOC(char, 3863 strlen(bp->destructor) + 1); 3864 NO_SPACE(symbol_destructor[i]); 3865 strcpy(symbol_destructor[i], bp->destructor); 3866 } 3867 } 3868 else 3869 { /* use type destructor for this tag, if there is one */ 3870 bp = lookup_type_destructor(tag); 3871 if (bp->destructor != NULL) 3872 { 3873 symbol_destructor[i] = TMALLOC(char, 3874 strlen(bp->destructor) + 1); 3875 NO_SPACE(symbol_destructor[i]); 3876 strcpy(symbol_destructor[i], bp->destructor); 3877 } 3878 else 3879 { /* use <*> destructor, if there is one */ 3880 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL) 3881 /* replace "$$" with "(*val).tag" in destructor code */ 3882 symbol_destructor[i] 3883 = process_destructor_XX(bp->destructor, tag); 3884 } 3885 } 3886 } 3887 else 3888 { /* replace "$$" with "(*val)[.tag]" in destructor code */ 3889 char *destructor_source = symbol_destructor[i]; 3890 symbol_destructor[i] 3891 = process_destructor_XX(destructor_source, tag); 3892 FREE(destructor_source); 3893 } 3894 } 3895 /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */ 3896 DO_FREE(symbol_type_tag); /* no longer needed */ 3897 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL) 3898 { 3899 FREE(bp->name); 3900 /* 'bp->tag' is a static value, don't free */ 3901 FREE(bp->destructor); 3902 FREE(bp); 3903 } 3904 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL) 3905 { 3906 FREE(bp->name); 3907 /* 'bp->tag' is a static value, don't free */ 3908 FREE(bp->destructor); 3909 FREE(bp); 3910 } 3911 if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL) 3912 { 3913 bucket *p; 3914 for (; bp; bp = p) 3915 { 3916 p = bp->link; 3917 FREE(bp->name); 3918 /* 'bp->tag' freed by 'free_tags()' */ 3919 FREE(bp->destructor); 3920 FREE(bp); 3921 } 3922 } 3923 } 3924 #endif /* defined(YYBTYACC) */ 3925 3926 void 3927 reader(void) 3928 { 3929 write_section(code_file, banner); 3930 create_symbol_table(); 3931 read_declarations(); 3932 read_grammar(); 3933 free_symbol_table(); 3934 pack_names(); 3935 check_symbols(); 3936 pack_symbols(); 3937 pack_grammar(); 3938 free_symbols(); 3939 print_grammar(); 3940 #if defined(YYBTYACC) 3941 if (destructor) 3942 finalize_destructors(); 3943 #endif 3944 free_tags(); 3945 } 3946 3947 #ifdef NO_LEAKS 3948 static param * 3949 free_declarations(param *list) 3950 { 3951 while (list != 0) 3952 { 3953 param *next = list->next; 3954 free(list->type); 3955 free(list->name); 3956 free(list->type2); 3957 free(list); 3958 list = next; 3959 } 3960 return list; 3961 } 3962 3963 void 3964 reader_leaks(void) 3965 { 3966 lex_param = free_declarations(lex_param); 3967 parse_param = free_declarations(parse_param); 3968 3969 DO_FREE(line); 3970 DO_FREE(rrhs); 3971 DO_FREE(rlhs); 3972 DO_FREE(rprec); 3973 DO_FREE(ritem); 3974 DO_FREE(rassoc); 3975 DO_FREE(cache); 3976 DO_FREE(name_pool); 3977 DO_FREE(symbol_name); 3978 DO_FREE(symbol_prec); 3979 DO_FREE(symbol_assoc); 3980 DO_FREE(symbol_value); 3981 #if defined(YYBTYACC) 3982 DO_FREE(symbol_pval); 3983 DO_FREE(symbol_destructor); 3984 DO_FREE(symbol_type_tag); 3985 #endif 3986 } 3987 #endif 3988