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