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