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